diff --git a/.gitignore b/.gitignore index 1e3cbce3c..7a1c528b8 100644 --- a/.gitignore +++ b/.gitignore @@ -51,7 +51,6 @@ proto/spec/**/*.pb.go *.aux *.bbl *.blg -*.log *.pdf *.gz *.dvi diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index a2ae47a09..f4ca1867f 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -17,6 +17,12 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [abci/counter] \#6684 Delete counter example app - [txResults] \#9175 Remove `gas_used` & `gas_wanted` from being merkelized in the lastresulthash in the header - [abci] \#5783 Make length delimiter encoding consistent (`uint64`) between ABCI and P2P wire-level protocols + - [abci] \#9145 Removes unused Response/Request `SetOption` from ABCI (@samricotta) + - [abci] \#8656 Added cli command for `PrepareProposal`. (@jmalicevic) + - [abci] \#8901 Added cli command for `ProcessProposal`. (@hvanz) + - [abci/params] \#9287 Deduplicate `ConsensusParams` and `BlockParams` so only `types` proto definitions are used (@cmwaters) + - Remove `TimeIotaMs` and use a hard-coded 1 millisecond value to ensure monotonically increasing block times. + - Rename `AppVersion` to `App` so as to not stutter. - P2P Protocol @@ -31,6 +37,8 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi ### IMPROVEMENTS +- [abci] \#5706 Added `AbciVersion` to `RequestInfo` allowing applications to check ABCI version when connecting to Tendermint. (@marbar3778) + ### BUG FIXES - [consensus] \#9229 fix round number of `enterPropose` when handling `RoundStepNewRound` timeout. (@fatcat22) diff --git a/UPGRADING.md b/UPGRADING.md index b701bccbf..241a9fea8 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -17,6 +17,12 @@ NOTE: v0.35 was recalled and v0.36 was skipped values, which was inconsistent with the `uint64` varint length delimiters used in the P2P layer. Both now consistently use `uint64` varint length delimiters. +## Unreleased + +### ABCI Changes + +* Added `AbciVersion` to `RequestInfo`. Applications should check that the ABCI version they expect is being used in order to avoid unimplemented changes errors. + ## v0.34.20 ### Feature: Priority Mempool diff --git a/abci/client/client.go b/abci/client/client.go index c5c7c82b3..cffb62f12 100644 --- a/abci/client/client.go +++ b/abci/client/client.go @@ -14,6 +14,8 @@ const ( echoRetryIntervalSeconds = 1 ) +//go:generate ../../scripts/mockery_generate.sh Client + // 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. @@ -28,34 +30,36 @@ type Client interface { FlushAsync() *ReqRes EchoAsync(msg string) *ReqRes InfoAsync(types.RequestInfo) *ReqRes - SetOptionAsync(types.RequestSetOption) *ReqRes DeliverTxAsync(types.RequestDeliverTx) *ReqRes CheckTxAsync(types.RequestCheckTx) *ReqRes QueryAsync(types.RequestQuery) *ReqRes CommitAsync() *ReqRes InitChainAsync(types.RequestInitChain) *ReqRes + PrepareProposalAsync(types.RequestPrepareProposal) *ReqRes BeginBlockAsync(types.RequestBeginBlock) *ReqRes EndBlockAsync(types.RequestEndBlock) *ReqRes ListSnapshotsAsync(types.RequestListSnapshots) *ReqRes OfferSnapshotAsync(types.RequestOfferSnapshot) *ReqRes LoadSnapshotChunkAsync(types.RequestLoadSnapshotChunk) *ReqRes ApplySnapshotChunkAsync(types.RequestApplySnapshotChunk) *ReqRes + ProcessProposalAsync(types.RequestProcessProposal) *ReqRes FlushSync() error EchoSync(msg string) (*types.ResponseEcho, error) InfoSync(types.RequestInfo) (*types.ResponseInfo, error) - SetOptionSync(types.RequestSetOption) (*types.ResponseSetOption, error) DeliverTxSync(types.RequestDeliverTx) (*types.ResponseDeliverTx, error) CheckTxSync(types.RequestCheckTx) (*types.ResponseCheckTx, error) QuerySync(types.RequestQuery) (*types.ResponseQuery, error) CommitSync() (*types.ResponseCommit, error) InitChainSync(types.RequestInitChain) (*types.ResponseInitChain, error) + PrepareProposalSync(types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) BeginBlockSync(types.RequestBeginBlock) (*types.ResponseBeginBlock, error) EndBlockSync(types.RequestEndBlock) (*types.ResponseEndBlock, error) ListSnapshotsSync(types.RequestListSnapshots) (*types.ResponseListSnapshots, error) OfferSnapshotSync(types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) LoadSnapshotChunkSync(types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) ApplySnapshotChunkSync(types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) + ProcessProposalSync(types.RequestProcessProposal) (*types.ResponseProcessProposal, error) } //---------------------------------------- diff --git a/abci/client/grpc_client.go b/abci/client/grpc_client.go index f271345ab..1258f013f 100644 --- a/abci/client/grpc_client.go +++ b/abci/client/grpc_client.go @@ -192,15 +192,6 @@ func (cli *grpcClient) InfoAsync(params types.RequestInfo) *ReqRes { return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Info{Info: res}}) } -func (cli *grpcClient) SetOptionAsync(params types.RequestSetOption) *ReqRes { - req := types.ToRequestSetOption(params) - res, err := cli.client.SetOption(context.Background(), req.GetSetOption(), grpc.WaitForReady(true)) - if err != nil { - cli.StopForError(err) - } - return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_SetOption{SetOption: res}}) -} - func (cli *grpcClient) DeliverTxAsync(params types.RequestDeliverTx) *ReqRes { req := types.ToRequestDeliverTx(params) res, err := cli.client.DeliverTx(context.Background(), req.GetDeliverTx(), grpc.WaitForReady(true)) @@ -300,6 +291,25 @@ func (cli *grpcClient) ApplySnapshotChunkAsync(params types.RequestApplySnapshot return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_ApplySnapshotChunk{ApplySnapshotChunk: res}}) } +func (cli *grpcClient) PrepareProposalAsync(params types.RequestPrepareProposal) *ReqRes { + req := types.ToRequestPrepareProposal(params) + res, err := cli.client.PrepareProposal(context.Background(), req.GetPrepareProposal(), grpc.WaitForReady(true)) + if err != nil { + cli.StopForError(err) + } + return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_PrepareProposal{PrepareProposal: res}}) +} + +func (cli *grpcClient) ProcessProposalAsync(params types.RequestProcessProposal) *ReqRes { + req := types.ToRequestProcessProposal(params) + res, err := cli.client.ProcessProposal(context.Background(), req.GetProcessProposal(), grpc.WaitForReady(true)) + if err != nil { + cli.StopForError(err) + } + + return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_ProcessProposal{ProcessProposal: res}}) +} + // finishAsyncCall creates a ReqRes for an async call, and immediately populates it // with the response. We don't complete it until it's been ordered via the channel. func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) *ReqRes { @@ -356,11 +366,6 @@ func (cli *grpcClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, err return cli.finishSyncCall(reqres).GetInfo(), cli.Error() } -func (cli *grpcClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { - reqres := cli.SetOptionAsync(req) - return reqres.Response.GetSetOption(), cli.Error() -} - func (cli *grpcClient) DeliverTxSync(params types.RequestDeliverTx) (*types.ResponseDeliverTx, error) { reqres := cli.DeliverTxAsync(params) return cli.finishSyncCall(reqres).GetDeliverTx(), cli.Error() @@ -417,3 +422,14 @@ func (cli *grpcClient) ApplySnapshotChunkSync( reqres := cli.ApplySnapshotChunkAsync(params) return cli.finishSyncCall(reqres).GetApplySnapshotChunk(), cli.Error() } + +func (cli *grpcClient) PrepareProposalSync( + params types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { + reqres := cli.PrepareProposalAsync(params) + return cli.finishSyncCall(reqres).GetPrepareProposal(), cli.Error() +} + +func (cli *grpcClient) ProcessProposalSync(params types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { + reqres := cli.ProcessProposalAsync(params) + return cli.finishSyncCall(reqres).GetProcessProposal(), cli.Error() +} diff --git a/abci/client/local_client.go b/abci/client/local_client.go index 62b0942c1..fd6f361ce 100644 --- a/abci/client/local_client.go +++ b/abci/client/local_client.go @@ -75,17 +75,6 @@ func (app *localClient) InfoAsync(req types.RequestInfo) *ReqRes { ) } -func (app *localClient) SetOptionAsync(req types.RequestSetOption) *ReqRes { - app.mtx.Lock() - defer app.mtx.Unlock() - - res := app.Application.SetOption(req) - return app.callback( - types.ToRequestSetOption(req), - types.ToResponseSetOption(res), - ) -} - func (app *localClient) DeliverTxAsync(params types.RequestDeliverTx) *ReqRes { app.mtx.Lock() defer app.mtx.Unlock() @@ -207,6 +196,28 @@ func (app *localClient) ApplySnapshotChunkAsync(req types.RequestApplySnapshotCh ) } +func (app *localClient) PrepareProposalAsync(req types.RequestPrepareProposal) *ReqRes { + app.mtx.Lock() + defer app.mtx.Unlock() + + res := app.Application.PrepareProposal(req) + return app.callback( + types.ToRequestPrepareProposal(req), + types.ToResponsePrepareProposal(res), + ) +} + +func (app *localClient) ProcessProposalAsync(req types.RequestProcessProposal) *ReqRes { + app.mtx.Lock() + defer app.mtx.Unlock() + + res := app.Application.ProcessProposal(req) + return app.callback( + types.ToRequestProcessProposal(req), + types.ToResponseProcessProposal(res), + ) +} + //------------------------------------------------------- func (app *localClient) FlushSync() error { @@ -225,14 +236,6 @@ func (app *localClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, er return &res, nil } -func (app *localClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { - app.mtx.Lock() - defer app.mtx.Unlock() - - res := app.Application.SetOption(req) - return &res, nil -} - func (app *localClient) DeliverTxSync(req types.RequestDeliverTx) (*types.ResponseDeliverTx, error) { app.mtx.Lock() defer app.mtx.Unlock() @@ -323,6 +326,22 @@ func (app *localClient) ApplySnapshotChunkSync( return &res, nil } +func (app *localClient) PrepareProposalSync(req types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { + app.mtx.Lock() + defer app.mtx.Unlock() + + res := app.Application.PrepareProposal(req) + return &res, nil +} + +func (app *localClient) ProcessProposalSync(req types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { + app.mtx.Lock() + defer app.mtx.Unlock() + + res := app.Application.ProcessProposal(req) + return &res, nil +} + //------------------------------------------------------- func (app *localClient) callback(req *types.Request, res *types.Response) *ReqRes { diff --git a/abci/client/mocks/client.go b/abci/client/mocks/client.go index 6d7f99b0f..7356be39e 100644 --- a/abci/client/mocks/client.go +++ b/abci/client/mocks/client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v1.1.1. DO NOT EDIT. +// Code generated by mockery. DO NOT EDIT. package mocks @@ -575,6 +575,84 @@ func (_m *Client) OnStop() { _m.Called() } +// PrepareProposalAsync provides a mock function with given fields: _a0 +func (_m *Client) PrepareProposalAsync(_a0 types.RequestPrepareProposal) *abcicli.ReqRes { + ret := _m.Called(_a0) + + var r0 *abcicli.ReqRes + if rf, ok := ret.Get(0).(func(types.RequestPrepareProposal) *abcicli.ReqRes); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*abcicli.ReqRes) + } + } + + return r0 +} + +// PrepareProposalSync provides a mock function with given fields: _a0 +func (_m *Client) PrepareProposalSync(_a0 types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { + ret := _m.Called(_a0) + + var r0 *types.ResponsePrepareProposal + if rf, ok := ret.Get(0).(func(types.RequestPrepareProposal) *types.ResponsePrepareProposal); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ResponsePrepareProposal) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(types.RequestPrepareProposal) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ProcessProposalAsync provides a mock function with given fields: _a0 +func (_m *Client) ProcessProposalAsync(_a0 types.RequestProcessProposal) *abcicli.ReqRes { + ret := _m.Called(_a0) + + var r0 *abcicli.ReqRes + if rf, ok := ret.Get(0).(func(types.RequestProcessProposal) *abcicli.ReqRes); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*abcicli.ReqRes) + } + } + + return r0 +} + +// ProcessProposalSync provides a mock function with given fields: _a0 +func (_m *Client) ProcessProposalSync(_a0 types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { + ret := _m.Called(_a0) + + var r0 *types.ResponseProcessProposal + if rf, ok := ret.Get(0).(func(types.RequestProcessProposal) *types.ResponseProcessProposal); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ResponseProcessProposal) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(types.RequestProcessProposal) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // QueryAsync provides a mock function with given fields: _a0 func (_m *Client) QueryAsync(_a0 types.RequestQuery) *abcicli.ReqRes { ret := _m.Called(_a0) @@ -649,45 +727,6 @@ func (_m *Client) SetLogger(_a0 log.Logger) { _m.Called(_a0) } -// SetOptionAsync provides a mock function with given fields: _a0 -func (_m *Client) SetOptionAsync(_a0 types.RequestSetOption) *abcicli.ReqRes { - ret := _m.Called(_a0) - - var r0 *abcicli.ReqRes - if rf, ok := ret.Get(0).(func(types.RequestSetOption) *abcicli.ReqRes); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*abcicli.ReqRes) - } - } - - return r0 -} - -// SetOptionSync provides a mock function with given fields: _a0 -func (_m *Client) SetOptionSync(_a0 types.RequestSetOption) (*types.ResponseSetOption, error) { - ret := _m.Called(_a0) - - var r0 *types.ResponseSetOption - if rf, ok := ret.Get(0).(func(types.RequestSetOption) *types.ResponseSetOption); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseSetOption) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(types.RequestSetOption) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // SetResponseCallback provides a mock function with given fields: _a0 func (_m *Client) SetResponseCallback(_a0 abcicli.Callback) { _m.Called(_a0) @@ -734,3 +773,18 @@ func (_m *Client) String() string { return r0 } + +type mockConstructorTestingTNewClient interface { + mock.TestingT + Cleanup(func()) +} + +// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewClient(t mockConstructorTestingTNewClient) *Client { + mock := &Client{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/abci/client/socket_client.go b/abci/client/socket_client.go index a369f878c..3df6007d2 100644 --- a/abci/client/socket_client.go +++ b/abci/client/socket_client.go @@ -231,10 +231,6 @@ func (cli *socketClient) InfoAsync(req types.RequestInfo) *ReqRes { return cli.queueRequest(types.ToRequestInfo(req)) } -func (cli *socketClient) SetOptionAsync(req types.RequestSetOption) *ReqRes { - return cli.queueRequest(types.ToRequestSetOption(req)) -} - func (cli *socketClient) DeliverTxAsync(req types.RequestDeliverTx) *ReqRes { return cli.queueRequest(types.ToRequestDeliverTx(req)) } @@ -279,6 +275,14 @@ func (cli *socketClient) ApplySnapshotChunkAsync(req types.RequestApplySnapshotC return cli.queueRequest(types.ToRequestApplySnapshotChunk(req)) } +func (cli *socketClient) PrepareProposalAsync(req types.RequestPrepareProposal) *ReqRes { + return cli.queueRequest(types.ToRequestPrepareProposal(req)) +} + +func (cli *socketClient) ProcessProposalAsync(req types.RequestProcessProposal) *ReqRes { + return cli.queueRequest(types.ToRequestProcessProposal(req)) +} + //---------------------------------------- func (cli *socketClient) FlushSync() error { @@ -308,15 +312,6 @@ func (cli *socketClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, e return reqres.Response.GetInfo(), cli.Error() } -func (cli *socketClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { - reqres := cli.queueRequest(types.ToRequestSetOption(req)) - if err := cli.FlushSync(); err != nil { - return nil, err - } - - return reqres.Response.GetSetOption(), cli.Error() -} - func (cli *socketClient) DeliverTxSync(req types.RequestDeliverTx) (*types.ResponseDeliverTx, error) { reqres := cli.queueRequest(types.ToRequestDeliverTx(req)) if err := cli.FlushSync(); err != nil { @@ -417,6 +412,24 @@ func (cli *socketClient) ApplySnapshotChunkSync( return reqres.Response.GetApplySnapshotChunk(), cli.Error() } +func (cli *socketClient) PrepareProposalSync(req types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { + reqres := cli.queueRequest(types.ToRequestPrepareProposal(req)) + if err := cli.FlushSync(); err != nil { + return nil, err + } + + return reqres.Response.GetPrepareProposal(), cli.Error() +} + +func (cli *socketClient) ProcessProposalSync(req types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { + reqres := cli.queueRequest(types.ToRequestProcessProposal(req)) + if err := cli.FlushSync(); err != nil { + return nil, err + } + + return reqres.Response.GetProcessProposal(), cli.Error() +} + //---------------------------------------- func (cli *socketClient) queueRequest(req *types.Request) *ReqRes { @@ -468,8 +481,6 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { _, ok = res.Value.(*types.Response_Flush) case *types.Request_Info: _, ok = res.Value.(*types.Response_Info) - case *types.Request_SetOption: - _, ok = res.Value.(*types.Response_SetOption) case *types.Request_DeliverTx: _, ok = res.Value.(*types.Response_DeliverTx) case *types.Request_CheckTx: @@ -492,6 +503,10 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { _, ok = res.Value.(*types.Response_ListSnapshots) case *types.Request_OfferSnapshot: _, ok = res.Value.(*types.Response_OfferSnapshot) + case *types.Request_PrepareProposal: + _, ok = res.Value.(*types.Response_PrepareProposal) + case *types.Request_ProcessProposal: + _, ok = res.Value.(*types.Response_ProcessProposal) } return ok } diff --git a/abci/cmd/abci-cli/abci-cli.go b/abci/cmd/abci-cli/abci-cli.go index c78f525f8..e8de62d10 100644 --- a/abci/cmd/abci-cli/abci-cli.go +++ b/abci/cmd/abci-cli/abci-cli.go @@ -83,10 +83,11 @@ var RootCmd = &cobra.Command{ // Structure for data passed to print response. type response struct { // generic abci response - Data []byte - Code uint32 - Info string - Log string + Data []byte + Code uint32 + Info string + Log string + Status int32 Query *queryResponse } @@ -138,12 +139,13 @@ func addCommands() { RootCmd.AddCommand(consoleCmd) RootCmd.AddCommand(echoCmd) RootCmd.AddCommand(infoCmd) - RootCmd.AddCommand(setOptionCmd) RootCmd.AddCommand(deliverTxCmd) RootCmd.AddCommand(checkTxCmd) RootCmd.AddCommand(commitCmd) RootCmd.AddCommand(versionCmd) RootCmd.AddCommand(testCmd) + RootCmd.AddCommand(prepareProposalCmd) + RootCmd.AddCommand(processProposalCmd) addQueryFlags() RootCmd.AddCommand(queryCmd) @@ -164,7 +166,6 @@ you'd like to run: where example.file looks something like: - set_option serial on check_tx 0x00 check_tx 0xff deliver_tx 0x00 @@ -186,7 +187,7 @@ This command opens an interactive console for running any of the other commands without opening a new connection each time `, Args: cobra.ExactArgs(0), - ValidArgs: []string{"echo", "info", "set_option", "deliver_tx", "check_tx", "commit", "query"}, + ValidArgs: []string{"echo", "info", "deliver_tx", "check_tx", "prepare_proposal", "process_proposal", "commit", "query"}, RunE: cmdConsole, } @@ -204,13 +205,6 @@ var infoCmd = &cobra.Command{ Args: cobra.ExactArgs(0), RunE: cmdInfo, } -var setOptionCmd = &cobra.Command{ - Use: "set_option", - Short: "set an option on the application", - Long: "set an option on the application", - Args: cobra.ExactArgs(2), - RunE: cmdSetOption, -} var deliverTxCmd = &cobra.Command{ Use: "deliver_tx", @@ -247,6 +241,22 @@ var versionCmd = &cobra.Command{ }, } +var prepareProposalCmd = &cobra.Command{ + Use: "prepare_proposal", + Short: "prepare proposal", + Long: "prepare proposal", + Args: cobra.MinimumNArgs(0), + RunE: cmdPrepareProposal, +} + +var processProposalCmd = &cobra.Command{ + Use: "process_proposal", + Short: "process proposal", + Long: "process proposal", + Args: cobra.MinimumNArgs(0), + RunE: cmdProcessProposal, +} + var queryCmd = &cobra.Command{ Use: "query", Short: "query the application state", @@ -304,7 +314,6 @@ func cmdTest(cmd *cobra.Command, args []string) error { 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) }, @@ -319,6 +328,16 @@ func cmdTest(cmd *cobra.Command, args []string) 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() error { + return servertest.PrepareProposal(client, [][]byte{ + {0x01}, + }, [][]byte{{0x01}}, nil) + }, + func() error { + return servertest.ProcessProposal(client, [][]byte{ + {0x01}, + }, types.ResponseProcessProposal_ACCEPT) + }, }) } @@ -419,8 +438,10 @@ func muxOnCommands(cmd *cobra.Command, pArgs []string) error { return cmdInfo(cmd, actualArgs) case "query": return cmdQuery(cmd, actualArgs) - case "set_option": - return cmdSetOption(cmd, actualArgs) + case "prepare_proposal": + return cmdPrepareProposal(cmd, actualArgs) + case "process_proposal": + return cmdProcessProposal(cmd, actualArgs) default: return cmdUnimplemented(cmd, pArgs) } @@ -444,7 +465,6 @@ func cmdUnimplemented(cmd *cobra.Command, args []string) error { fmt.Printf("%s: %s\n", deliverTxCmd.Use, deliverTxCmd.Short) fmt.Printf("%s: %s\n", queryCmd.Use, queryCmd.Short) fmt.Printf("%s: %s\n", commitCmd.Use, commitCmd.Short) - fmt.Printf("%s: %s\n", setOptionCmd.Use, setOptionCmd.Short) fmt.Println("Use \"[command] --help\" for more information about a command.") return nil @@ -484,25 +504,6 @@ func cmdInfo(cmd *cobra.Command, args []string) error { 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] - _, err := client.SetOptionSync(types.RequestSetOption{Key: key, Value: val}) - if err != nil { - return err - } - printResponse(cmd, args, response{Log: "OK (SetOption doesn't return anything.)"}) // NOTE: Nothing to show... - return nil -} - // Append a new tx to application func cmdDeliverTx(cmd *cobra.Command, args []string) error { if len(args) == 0 { @@ -605,17 +606,75 @@ func cmdQuery(cmd *cobra.Command, args []string) error { return nil } +func cmdPrepareProposal(cmd *cobra.Command, args []string) error { + txsBytesArray := make([][]byte, len(args)) + + for i, arg := range args { + txBytes, err := stringOrHexToBytes(arg) + if err != nil { + return err + } + txsBytesArray[i] = txBytes + } + + res, err := client.PrepareProposalSync(types.RequestPrepareProposal{ + Txs: txsBytesArray, + // kvstore has to have this parameter in order not to reject a tx as the default value is 0 + MaxTxBytes: 65536, + }) + if err != nil { + return err + } + resps := make([]response, 0, len(res.Txs)) + for _, tx := range res.Txs { + resps = append(resps, response{ + Code: code.CodeTypeOK, + Log: "Succeeded. Tx: " + string(tx), + }) + } + + printResponse(cmd, args, resps...) + return nil +} + +func cmdProcessProposal(cmd *cobra.Command, args []string) error { + txsBytesArray := make([][]byte, len(args)) + + for i, arg := range args { + txBytes, err := stringOrHexToBytes(arg) + if err != nil { + return err + } + txsBytesArray[i] = txBytes + } + + res, err := client.ProcessProposalSync(types.RequestProcessProposal{ + Txs: txsBytesArray, + }) + if err != nil { + return err + } + + printResponse(cmd, args, response{ + Status: int32(res.Status), + }) + return nil +} + func cmdKVStore(cmd *cobra.Command, args []string) error { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Create the application - in memory or persisted to disk var app types.Application if flagPersist == "" { - app = kvstore.NewApplication() - } else { - app = kvstore.NewPersistentKVStoreApplication(flagPersist) - app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore")) + var err error + flagPersist, err = os.MkdirTemp("", "persistent_kvstore_tmp") + if err != nil { + return err + } } + app = kvstore.NewPersistentKVStoreApplication(flagPersist) + app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore")) // Start the listener srv, err := server.NewServer(flagAddress, flagAbci, app) @@ -641,44 +700,49 @@ func cmdKVStore(cmd *cobra.Command, args []string) error { //-------------------------------------------------------------------------------- -func printResponse(cmd *cobra.Command, args []string, rsp response) { +func printResponse(cmd *cobra.Command, args []string, rsps ...response) { if flagVerbose { fmt.Println(">", cmd.Use, strings.Join(args, " ")) } - // Always print the status code. - if rsp.Code == types.CodeTypeOK { - fmt.Printf("-> code: OK\n") - } else { - fmt.Printf("-> code: %d\n", rsp.Code) + for _, rsp := range rsps { + // Always print the status 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 - // because the string comes out as gibberish - if cmd.Use != "commit" { - fmt.Printf("-> data: %s\n", rsp.Data) + if len(rsp.Data) != 0 { + // 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) + } + if cmd.Use == "process_proposal" { + fmt.Printf("-> status: %s\n", types.ResponseProcessProposal_ProposalStatus_name[rsp.Status]) } - fmt.Printf("-> data.hex: 0x%X\n", rsp.Data) - } - if rsp.Log != "" { - fmt.Printf("-> log: %s\n", rsp.Log) - } - if rsp.Query != nil { - fmt.Printf("-> height: %d\n", rsp.Query.Height) - if rsp.Query.Key != nil { - fmt.Printf("-> key: %s\n", rsp.Query.Key) - fmt.Printf("-> key.hex: %X\n", rsp.Query.Key) - } - if rsp.Query.Value != nil { - fmt.Printf("-> value: %s\n", rsp.Query.Value) - fmt.Printf("-> value.hex: %X\n", rsp.Query.Value) - } - if rsp.Query.ProofOps != nil { - fmt.Printf("-> proof: %#v\n", rsp.Query.ProofOps) + 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.ProofOps != nil { + fmt.Printf("-> proof: %#v\n", rsp.Query.ProofOps) + } } } } diff --git a/abci/example/code/code.go b/abci/example/code/code.go index 988b2a93e..6d011ed9d 100644 --- a/abci/example/code/code.go +++ b/abci/example/code/code.go @@ -7,4 +7,5 @@ const ( CodeTypeBadNonce uint32 = 2 CodeTypeUnauthorized uint32 = 3 CodeTypeUnknownError uint32 = 4 + CodeTypeExecuted uint32 = 5 ) diff --git a/abci/example/kvstore/kvstore.go b/abci/example/kvstore/kvstore.go index 8b851ca9a..aa05f2fa9 100644 --- a/abci/example/kvstore/kvstore.go +++ b/abci/example/kvstore/kvstore.go @@ -68,6 +68,7 @@ type Application struct { state State RetainBlocks int64 // blocks to retain after commit (via ResponseCommit.RetainHeight) + txToRemove map[string]struct{} } func NewApplication() *Application { @@ -87,6 +88,9 @@ func (app *Application) Info(req types.RequestInfo) (resInfo types.ResponseInfo) // tx is either "key=value" or just arbitrary bytes func (app *Application) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx { + if isReplacedTx(req.Tx) { + app.txToRemove[string(req.Tx)] = struct{}{} + } var key, value []byte parts := bytes.Split(req.Tx, []byte("=")) if len(parts) == 2 { @@ -117,6 +121,11 @@ func (app *Application) DeliverTx(req types.RequestDeliverTx) types.ResponseDeli } func (app *Application) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx { + if req.Type == types.CheckTxType_Recheck { + if _, ok := app.txToRemove[string(req.Tx)]; ok { + return types.ResponseCheckTx{Code: code.CodeTypeExecuted, GasWanted: 1} + } + } return types.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1} } @@ -126,6 +135,8 @@ func (app *Application) Commit() types.ResponseCommit { binary.PutVarint(appHash, app.state.Size) app.state.AppHash = appHash app.state.Height++ + + // empty out the set of transactions to remove via rechecktx saveState(app.state) resp := types.ResponseCommit{Data: appHash} @@ -170,3 +181,18 @@ func (app *Application) Query(reqQuery types.RequestQuery) (resQuery types.Respo return resQuery } + +func (app *Application) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { + app.txToRemove = map[string]struct{}{} + return types.ResponseBeginBlock{} +} + +func (app *Application) ProcessProposal( + req types.RequestProcessProposal) types.ResponseProcessProposal { + for _, tx := range req.Txs { + if len(tx) == 0 { + return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_REJECT} + } + } + return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_ACCEPT} +} diff --git a/abci/example/kvstore/persistent_kvstore.go b/abci/example/kvstore/persistent_kvstore.go index 320918b5b..500d4c5c9 100644 --- a/abci/example/kvstore/persistent_kvstore.go +++ b/abci/example/kvstore/persistent_kvstore.go @@ -45,7 +45,10 @@ func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication state := loadState(db) return &PersistentKVStoreApplication{ - app: &Application{state: state}, + app: &Application{ + state: state, + txToRemove: map[string]struct{}{}, + }, valAddrToPubKeyMap: make(map[string]pc.PublicKey), logger: log.NewNopLogger(), } @@ -62,10 +65,6 @@ func (app *PersistentKVStoreApplication) Info(req types.RequestInfo) types.Respo return res } -func (app *PersistentKVStoreApplication) SetOption(req types.RequestSetOption) types.ResponseSetOption { - return app.app.SetOption(req) -} - // tx is either "val:pubkey!power" or "key=value" or just arbitrary bytes func (app *PersistentKVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx { // if it starts with "val:", update the validator set @@ -76,6 +75,10 @@ func (app *PersistentKVStoreApplication) DeliverTx(req types.RequestDeliverTx) t return app.execValidatorTx(req.Tx) } + if isPrepareTx(req.Tx) { + return app.execPrepareTx(req.Tx) + } + // otherwise, update the key-value store return app.app.DeliverTx(req) } @@ -126,7 +129,7 @@ func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) // Punish validators who committed equivocation. for _, ev := range req.ByzantineValidators { - if ev.Type == types.EvidenceType_DUPLICATE_VOTE { + if ev.Type == types.MisbehaviorType_DUPLICATE_VOTE { addr := string(ev.Validator.Address) if pubKey, ok := app.valAddrToPubKeyMap[addr]; ok { app.updateValidator(types.ValidatorUpdate{ @@ -142,7 +145,7 @@ func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) } } - return types.ResponseBeginBlock{} + return app.app.BeginBlock(req) } // Update the validator set @@ -170,6 +173,21 @@ func (app *PersistentKVStoreApplication) ApplySnapshotChunk( return types.ResponseApplySnapshotChunk{Result: types.ResponseApplySnapshotChunk_ABORT} } +func (app *PersistentKVStoreApplication) PrepareProposal( + req types.RequestPrepareProposal) types.ResponsePrepareProposal { + return types.ResponsePrepareProposal{Txs: app.substPrepareTx(req.Txs, req.MaxTxBytes)} +} + +func (app *PersistentKVStoreApplication) ProcessProposal( + req types.RequestProcessProposal) types.ResponseProcessProposal { + for _, tx := range req.Txs { + if len(tx) == 0 || isPrepareTx(tx) { + return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_REJECT} + } + } + return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_ACCEPT} +} + //--------------------------------------------- // update validators @@ -284,3 +302,42 @@ func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate return types.ResponseDeliverTx{Code: code.CodeTypeOK} } + +// ----------------------------- + +const ( + PreparePrefix = "prepare" + ReplacePrefix = "replace" +) + +func isPrepareTx(tx []byte) bool { return bytes.HasPrefix(tx, []byte(PreparePrefix)) } + +func isReplacedTx(tx []byte) bool { + return bytes.HasPrefix(tx, []byte(ReplacePrefix)) +} + +// execPrepareTx is noop. tx data is considered as placeholder +// and is substitute at the PrepareProposal. +func (app *PersistentKVStoreApplication) execPrepareTx(tx []byte) types.ResponseDeliverTx { + // noop + return types.ResponseDeliverTx{} +} + +// substPrepareTx substitutes all the transactions prefixed with 'prepare' in the +// proposal for transactions with the prefix stripped. +func (app *PersistentKVStoreApplication) substPrepareTx(blockData [][]byte, maxTxBytes int64) [][]byte { + txs := make([][]byte, 0, len(blockData)) + var totalBytes int64 + for _, tx := range blockData { + txMod := tx + if isPrepareTx(tx) { + txMod = bytes.Replace(tx, []byte(PreparePrefix), []byte(ReplacePrefix), 1) + } + totalBytes += int64(len(txMod)) + if totalBytes > maxTxBytes { + break + } + txs = append(txs, txMod) + } + return txs +} diff --git a/abci/server/socket_server.go b/abci/server/socket_server.go index 3f99a3765..5da8bf5ba 100644 --- a/abci/server/socket_server.go +++ b/abci/server/socket_server.go @@ -200,9 +200,6 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types case *types.Request_Info: res := s.app.Info(*r.Info) responses <- types.ToResponseInfo(res) - case *types.Request_SetOption: - res := s.app.SetOption(*r.SetOption) - responses <- types.ToResponseSetOption(res) case *types.Request_DeliverTx: res := s.app.DeliverTx(*r.DeliverTx) responses <- types.ToResponseDeliverTx(res) @@ -230,6 +227,12 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types case *types.Request_OfferSnapshot: res := s.app.OfferSnapshot(*r.OfferSnapshot) responses <- types.ToResponseOfferSnapshot(res) + case *types.Request_PrepareProposal: + res := s.app.PrepareProposal(*r.PrepareProposal) + responses <- types.ToResponsePrepareProposal(res) + case *types.Request_ProcessProposal: + res := s.app.ProcessProposal(*r.ProcessProposal) + responses <- types.ToResponseProcessProposal(res) case *types.Request_LoadSnapshotChunk: res := s.app.LoadSnapshotChunk(*r.LoadSnapshotChunk) responses <- types.ToResponseLoadSnapshotChunk(res) diff --git a/abci/tests/server/client.go b/abci/tests/server/client.go index beaa3da89..76d315216 100644 --- a/abci/tests/server/client.go +++ b/abci/tests/server/client.go @@ -29,17 +29,6 @@ func InitChain(client abcicli.Client) error { return nil } -func SetOption(client abcicli.Client, key, value string) error { - _, err := client.SetOptionSync(types.RequestSetOption{Key: key, Value: value}) - if err != nil { - fmt.Println("Failed test: SetOption") - fmt.Printf("error while setting %v=%v: \nerror: %v\n", key, value, err) - return err - } - fmt.Println("Passed test: SetOption") - return nil -} - func Commit(client abcicli.Client, hashExp []byte) error { res, err := client.CommitSync() data := res.Data @@ -76,6 +65,32 @@ func DeliverTx(client abcicli.Client, txBytes []byte, codeExp uint32, dataExp [] return nil } +func PrepareProposal(client abcicli.Client, txBytes [][]byte, txExpected [][]byte, dataExp []byte) error { + res, _ := client.PrepareProposalSync(types.RequestPrepareProposal{Txs: txBytes}) + for i, tx := range res.Txs { + if !bytes.Equal(tx, txExpected[i]) { + fmt.Println("Failed test: PrepareProposal") + fmt.Printf("PrepareProposal transaction was unexpected. Got %x expected %x.", + tx, txExpected[i]) + return errors.New("PrepareProposal error") + } + } + fmt.Println("Passed test: PrepareProposal") + return nil +} + +func ProcessProposal(client abcicli.Client, txBytes [][]byte, statusExp types.ResponseProcessProposal_ProposalStatus) error { + res, _ := client.ProcessProposalSync(types.RequestProcessProposal{Txs: txBytes}) + if res.Status != statusExp { + fmt.Println("Failed test: ProcessProposal") + fmt.Printf("ProcessProposal response status was unexpected. Got %v expected %v.", + res.Status, statusExp) + return errors.New("ProcessProposal error") + } + fmt.Println("Passed test: ProcessProposal") + return nil +} + func CheckTx(client abcicli.Client, txBytes []byte, codeExp uint32, dataExp []byte) error { res, _ := client.CheckTxSync(types.RequestCheckTx{Tx: txBytes}) code, data, log := res.Code, res.Data, res.Log diff --git a/abci/tests/test_cli/ex1.abci b/abci/tests/test_cli/ex1.abci index e909266ec..e772593cc 100644 --- a/abci/tests/test_cli/ex1.abci +++ b/abci/tests/test_cli/ex1.abci @@ -1,5 +1,7 @@ echo hello info +prepare_proposal "abc" +process_proposal "abc" commit deliver_tx "abc" info @@ -8,3 +10,9 @@ query "abc" deliver_tx "def=xyz" commit query "def" +prepare_proposal "preparedef" +process_proposal "replacedef" +process_proposal "preparedef" +prepare_proposal +process_proposal +commit diff --git a/abci/tests/test_cli/ex1.abci.out b/abci/tests/test_cli/ex1.abci.out index 9e702b5ce..dbc818855 100644 --- a/abci/tests/test_cli/ex1.abci.out +++ b/abci/tests/test_cli/ex1.abci.out @@ -8,6 +8,14 @@ -> data: {"size":0} -> data.hex: 0x7B2273697A65223A307D +> prepare_proposal "abc" +-> code: OK +-> log: Succeeded. Tx: abc + +> process_proposal "abc" +-> code: OK +-> status: ACCEPT + > commit -> code: OK -> data.hex: 0x0000000000000000 @@ -49,3 +57,25 @@ -> value: xyz -> value.hex: 78797A +> prepare_proposal "preparedef" +-> code: OK +-> log: Succeeded. Tx: replacedef + +> process_proposal "replacedef" +-> code: OK +-> status: ACCEPT + +> process_proposal "preparedef" +-> code: OK +-> status: REJECT + +> prepare_proposal + +> process_proposal +-> code: OK +-> status: ACCEPT + +> commit +-> code: OK +-> data.hex: 0x0400000000000000 + diff --git a/abci/tests/test_cli/ex2.abci b/abci/tests/test_cli/ex2.abci index 3b435f22a..965ca842c 100644 --- a/abci/tests/test_cli/ex2.abci +++ b/abci/tests/test_cli/ex2.abci @@ -1,4 +1,3 @@ -set_option serial on check_tx 0x00 check_tx 0xff deliver_tx 0x00 diff --git a/abci/tests/test_cli/ex2.abci.out b/abci/tests/test_cli/ex2.abci.out index 5bceb85d8..a2f03ed6c 100644 --- a/abci/tests/test_cli/ex2.abci.out +++ b/abci/tests/test_cli/ex2.abci.out @@ -1,7 +1,3 @@ -> set_option serial on --> code: OK --> log: OK (SetOption doesn't return anything.) - > check_tx 0x00 -> code: OK @@ -12,18 +8,16 @@ -> code: OK > check_tx 0x00 --> code: 2 --> log: Invalid nonce. Expected >= 1, got 0 +-> code: OK > deliver_tx 0x01 -> code: OK > deliver_tx 0x04 --> code: 2 --> log: Invalid nonce. Expected 2, got 4 +-> code: OK > info -> code: OK --> data: {"hashes":0,"txs":2} --> data.hex: 0x7B22686173686573223A302C22747873223A327D +-> data: {"size":3} +-> data.hex: 0x7B2273697A65223A337D diff --git a/abci/tests/test_cli/test.sh b/abci/tests/test_cli/test.sh index 9c02ce6f5..078d645af 100755 --- a/abci/tests/test_cli/test.sh +++ b/abci/tests/test_cli/test.sh @@ -30,6 +30,8 @@ function testExample() { cat "${INPUT}.out.new" echo "Expected:" cat "${INPUT}.out" + echo "Diff:" + diff "${INPUT}.out" "${INPUT}.out.new" exit 1 fi @@ -37,6 +39,7 @@ function testExample() { } testExample 1 tests/test_cli/ex1.abci abci-cli kvstore +testExample 2 tests/test_cli/ex2.abci abci-cli kvstore echo "" echo "PASS" diff --git a/abci/types/application.go b/abci/types/application.go index 65cc78b8c..0913ea463 100644 --- a/abci/types/application.go +++ b/abci/types/application.go @@ -4,21 +4,24 @@ import ( context "golang.org/x/net/context" ) +//go:generate ../../scripts/mockery_generate.sh Application + // Application is an interface that enables any finite, deterministic state machine // 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(RequestSetOption) ResponseSetOption // Set application option - Query(RequestQuery) ResponseQuery // Query for state + Info(RequestInfo) ResponseInfo // Return application info + Query(RequestQuery) ResponseQuery // Query for state // Mempool Connection CheckTx(RequestCheckTx) ResponseCheckTx // Validate a tx for the mempool // Consensus Connection - InitChain(RequestInitChain) ResponseInitChain // Initialize blockchain w validators/other info from TendermintCore + InitChain(RequestInitChain) ResponseInitChain // Initialize blockchain w validators/other info from TendermintCore + PrepareProposal(RequestPrepareProposal) ResponsePrepareProposal + ProcessProposal(RequestProcessProposal) ResponseProcessProposal BeginBlock(RequestBeginBlock) ResponseBeginBlock // Signals the beginning of a block DeliverTx(RequestDeliverTx) ResponseDeliverTx // Deliver a tx for full processing EndBlock(RequestEndBlock) ResponseEndBlock // Signals the end of a block, returns changes to the validator set @@ -47,10 +50,6 @@ func (BaseApplication) Info(req RequestInfo) ResponseInfo { return ResponseInfo{} } -func (BaseApplication) SetOption(req RequestSetOption) ResponseSetOption { - return ResponseSetOption{} -} - func (BaseApplication) DeliverTx(req RequestDeliverTx) ResponseDeliverTx { return ResponseDeliverTx{Code: CodeTypeOK} } @@ -95,6 +94,24 @@ func (BaseApplication) ApplySnapshotChunk(req RequestApplySnapshotChunk) Respons return ResponseApplySnapshotChunk{} } +func (BaseApplication) PrepareProposal(req RequestPrepareProposal) ResponsePrepareProposal { + txs := make([][]byte, 0, len(req.Txs)) + var totalBytes int64 + for _, tx := range req.Txs { + totalBytes += int64(len(tx)) + if totalBytes > req.MaxTxBytes { + break + } + txs = append(txs, tx) + } + return ResponsePrepareProposal{Txs: txs} +} + +func (BaseApplication) ProcessProposal(req RequestProcessProposal) ResponseProcessProposal { + return ResponseProcessProposal{ + Status: ResponseProcessProposal_ACCEPT} +} + //------------------------------------------------------- // GRPCApplication is a GRPC wrapper for Application @@ -119,11 +136,6 @@ func (app *GRPCApplication) Info(ctx context.Context, req *RequestInfo) (*Respon return &res, nil } -func (app *GRPCApplication) SetOption(ctx context.Context, req *RequestSetOption) (*ResponseSetOption, error) { - res := app.app.SetOption(*req) - return &res, nil -} - func (app *GRPCApplication) DeliverTx(ctx context.Context, req *RequestDeliverTx) (*ResponseDeliverTx, error) { res := app.app.DeliverTx(*req) return &res, nil @@ -182,3 +194,15 @@ func (app *GRPCApplication) ApplySnapshotChunk( res := app.app.ApplySnapshotChunk(*req) return &res, nil } + +func (app *GRPCApplication) PrepareProposal( + ctx context.Context, req *RequestPrepareProposal) (*ResponsePrepareProposal, error) { + res := app.app.PrepareProposal(*req) + return &res, nil +} + +func (app *GRPCApplication) ProcessProposal( + ctx context.Context, req *RequestProcessProposal) (*ResponseProcessProposal, error) { + res := app.app.ProcessProposal(*req) + return &res, nil +} diff --git a/abci/types/messages.go b/abci/types/messages.go index 0686b6b25..3f2060575 100644 --- a/abci/types/messages.go +++ b/abci/types/messages.go @@ -48,12 +48,6 @@ func ToRequestInfo(req RequestInfo) *Request { } } -func ToRequestSetOption(req RequestSetOption) *Request { - return &Request{ - Value: &Request_SetOption{&req}, - } -} - func ToRequestDeliverTx(req RequestDeliverTx) *Request { return &Request{ Value: &Request_DeliverTx{&req}, @@ -120,6 +114,18 @@ func ToRequestApplySnapshotChunk(req RequestApplySnapshotChunk) *Request { } } +func ToRequestPrepareProposal(req RequestPrepareProposal) *Request { + return &Request{ + Value: &Request_PrepareProposal{&req}, + } +} + +func ToRequestProcessProposal(req RequestProcessProposal) *Request { + return &Request{ + Value: &Request_ProcessProposal{&req}, + } +} + //---------------------------------------- func ToResponseException(errStr string) *Response { @@ -146,12 +152,6 @@ func ToResponseInfo(res ResponseInfo) *Response { } } -func ToResponseSetOption(res ResponseSetOption) *Response { - return &Response{ - Value: &Response_SetOption{&res}, - } -} - func ToResponseDeliverTx(res ResponseDeliverTx) *Response { return &Response{ Value: &Response_DeliverTx{&res}, @@ -217,3 +217,15 @@ func ToResponseApplySnapshotChunk(res ResponseApplySnapshotChunk) *Response { Value: &Response_ApplySnapshotChunk{&res}, } } + +func ToResponsePrepareProposal(res ResponsePrepareProposal) *Response { + return &Response{ + Value: &Response_PrepareProposal{&res}, + } +} + +func ToResponseProcessProposal(res ResponseProcessProposal) *Response { + return &Response{ + Value: &Response_ProcessProposal{&res}, + } +} diff --git a/abci/types/mocks/application.go b/abci/types/mocks/application.go new file mode 100644 index 000000000..75f573a84 --- /dev/null +++ b/abci/types/mocks/application.go @@ -0,0 +1,224 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + types "github.com/tendermint/tendermint/abci/types" +) + +// Application is an autogenerated mock type for the Application type +type Application struct { + mock.Mock +} + +// ApplySnapshotChunk provides a mock function with given fields: _a0 +func (_m *Application) ApplySnapshotChunk(_a0 types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk { + ret := _m.Called(_a0) + + var r0 types.ResponseApplySnapshotChunk + if rf, ok := ret.Get(0).(func(types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseApplySnapshotChunk) + } + + return r0 +} + +// BeginBlock provides a mock function with given fields: _a0 +func (_m *Application) BeginBlock(_a0 types.RequestBeginBlock) types.ResponseBeginBlock { + ret := _m.Called(_a0) + + var r0 types.ResponseBeginBlock + if rf, ok := ret.Get(0).(func(types.RequestBeginBlock) types.ResponseBeginBlock); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseBeginBlock) + } + + return r0 +} + +// CheckTx provides a mock function with given fields: _a0 +func (_m *Application) CheckTx(_a0 types.RequestCheckTx) types.ResponseCheckTx { + ret := _m.Called(_a0) + + var r0 types.ResponseCheckTx + if rf, ok := ret.Get(0).(func(types.RequestCheckTx) types.ResponseCheckTx); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseCheckTx) + } + + return r0 +} + +// Commit provides a mock function with given fields: +func (_m *Application) Commit() types.ResponseCommit { + ret := _m.Called() + + var r0 types.ResponseCommit + if rf, ok := ret.Get(0).(func() types.ResponseCommit); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(types.ResponseCommit) + } + + return r0 +} + +// DeliverTx provides a mock function with given fields: _a0 +func (_m *Application) DeliverTx(_a0 types.RequestDeliverTx) types.ResponseDeliverTx { + ret := _m.Called(_a0) + + var r0 types.ResponseDeliverTx + if rf, ok := ret.Get(0).(func(types.RequestDeliverTx) types.ResponseDeliverTx); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseDeliverTx) + } + + return r0 +} + +// EndBlock provides a mock function with given fields: _a0 +func (_m *Application) EndBlock(_a0 types.RequestEndBlock) types.ResponseEndBlock { + ret := _m.Called(_a0) + + var r0 types.ResponseEndBlock + if rf, ok := ret.Get(0).(func(types.RequestEndBlock) types.ResponseEndBlock); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseEndBlock) + } + + return r0 +} + +// Info provides a mock function with given fields: _a0 +func (_m *Application) Info(_a0 types.RequestInfo) types.ResponseInfo { + ret := _m.Called(_a0) + + var r0 types.ResponseInfo + if rf, ok := ret.Get(0).(func(types.RequestInfo) types.ResponseInfo); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseInfo) + } + + return r0 +} + +// InitChain provides a mock function with given fields: _a0 +func (_m *Application) InitChain(_a0 types.RequestInitChain) types.ResponseInitChain { + ret := _m.Called(_a0) + + var r0 types.ResponseInitChain + if rf, ok := ret.Get(0).(func(types.RequestInitChain) types.ResponseInitChain); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseInitChain) + } + + return r0 +} + +// ListSnapshots provides a mock function with given fields: _a0 +func (_m *Application) ListSnapshots(_a0 types.RequestListSnapshots) types.ResponseListSnapshots { + ret := _m.Called(_a0) + + var r0 types.ResponseListSnapshots + if rf, ok := ret.Get(0).(func(types.RequestListSnapshots) types.ResponseListSnapshots); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseListSnapshots) + } + + return r0 +} + +// LoadSnapshotChunk provides a mock function with given fields: _a0 +func (_m *Application) LoadSnapshotChunk(_a0 types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk { + ret := _m.Called(_a0) + + var r0 types.ResponseLoadSnapshotChunk + if rf, ok := ret.Get(0).(func(types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseLoadSnapshotChunk) + } + + return r0 +} + +// OfferSnapshot provides a mock function with given fields: _a0 +func (_m *Application) OfferSnapshot(_a0 types.RequestOfferSnapshot) types.ResponseOfferSnapshot { + ret := _m.Called(_a0) + + var r0 types.ResponseOfferSnapshot + if rf, ok := ret.Get(0).(func(types.RequestOfferSnapshot) types.ResponseOfferSnapshot); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseOfferSnapshot) + } + + return r0 +} + +// PrepareProposal provides a mock function with given fields: _a0 +func (_m *Application) PrepareProposal(_a0 types.RequestPrepareProposal) types.ResponsePrepareProposal { + ret := _m.Called(_a0) + + var r0 types.ResponsePrepareProposal + if rf, ok := ret.Get(0).(func(types.RequestPrepareProposal) types.ResponsePrepareProposal); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponsePrepareProposal) + } + + return r0 +} + +// ProcessProposal provides a mock function with given fields: _a0 +func (_m *Application) ProcessProposal(_a0 types.RequestProcessProposal) types.ResponseProcessProposal { + ret := _m.Called(_a0) + + var r0 types.ResponseProcessProposal + if rf, ok := ret.Get(0).(func(types.RequestProcessProposal) types.ResponseProcessProposal); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseProcessProposal) + } + + return r0 +} + +// Query provides a mock function with given fields: _a0 +func (_m *Application) Query(_a0 types.RequestQuery) types.ResponseQuery { + ret := _m.Called(_a0) + + var r0 types.ResponseQuery + if rf, ok := ret.Get(0).(func(types.RequestQuery) types.ResponseQuery); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(types.ResponseQuery) + } + + return r0 +} + +type mockConstructorTestingTNewApplication interface { + mock.TestingT + Cleanup(func()) +} + +// NewApplication creates a new instance of Application. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewApplication(t mockConstructorTestingTNewApplication) *Application { + mock := &Application{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/abci/types/mocks/base.go b/abci/types/mocks/base.go new file mode 100644 index 000000000..d0a33ebb0 --- /dev/null +++ b/abci/types/mocks/base.go @@ -0,0 +1,187 @@ +package mocks + +import ( + types "github.com/tendermint/tendermint/abci/types" +) + +// BaseMock provides a wrapper around the generated Application mock and a BaseApplication. +// BaseMock first tries to use the mock's implementation of the method. +// If no functionality was provided for the mock by the user, BaseMock dispatches +// to the BaseApplication and uses its functionality. +// BaseMock allows users to provide mocked functionality for only the methods that matter +// for their test while avoiding a panic if the code calls Application methods that are +// not relevant to the test. +type BaseMock struct { + base *types.BaseApplication + *Application +} + +func NewBaseMock() BaseMock { + return BaseMock{ + base: types.NewBaseApplication(), + Application: new(Application), + } +} + +// Info/Query Connection +// Return application info +func (m BaseMock) Info(input types.RequestInfo) types.ResponseInfo { + var ret types.ResponseInfo + defer func() { + if r := recover(); r != nil { + ret = m.base.Info(input) + } + }() + ret = m.Application.Info(input) + return ret +} + +func (m BaseMock) Query(input types.RequestQuery) types.ResponseQuery { + var ret types.ResponseQuery + defer func() { + if r := recover(); r != nil { + ret = m.base.Query(input) + } + }() + ret = m.Application.Query(input) + return ret +} + +// Mempool Connection +// Validate a tx for the mempool +func (m BaseMock) CheckTx(input types.RequestCheckTx) types.ResponseCheckTx { + var ret types.ResponseCheckTx + defer func() { + if r := recover(); r != nil { + ret = m.base.CheckTx(input) + } + }() + ret = m.Application.CheckTx(input) + return ret +} + +// Consensus Connection +// Initialize blockchain w validators/other info from TendermintCore +func (m BaseMock) InitChain(input types.RequestInitChain) types.ResponseInitChain { + var ret types.ResponseInitChain + defer func() { + if r := recover(); r != nil { + ret = m.base.InitChain(input) + } + }() + ret = m.Application.InitChain(input) + return ret +} + +func (m BaseMock) PrepareProposal(input types.RequestPrepareProposal) types.ResponsePrepareProposal { + var ret types.ResponsePrepareProposal + defer func() { + if r := recover(); r != nil { + ret = m.base.PrepareProposal(input) + } + }() + ret = m.Application.PrepareProposal(input) + return ret +} + +func (m BaseMock) ProcessProposal(input types.RequestProcessProposal) types.ResponseProcessProposal { + var ret types.ResponseProcessProposal + defer func() { + if r := recover(); r != nil { + ret = m.base.ProcessProposal(input) + } + }() + ret = m.Application.ProcessProposal(input) + return ret +} + +// Commit the state and return the application Merkle root hash +func (m BaseMock) Commit() types.ResponseCommit { + var ret types.ResponseCommit + defer func() { + if r := recover(); r != nil { + ret = m.base.Commit() + } + }() + ret = m.Application.Commit() + return ret +} + +// State Sync Connection +// List available snapshots +func (m BaseMock) ListSnapshots(input types.RequestListSnapshots) types.ResponseListSnapshots { + var ret types.ResponseListSnapshots + defer func() { + if r := recover(); r != nil { + ret = m.base.ListSnapshots(input) + } + }() + ret = m.Application.ListSnapshots(input) + return ret +} + +func (m BaseMock) OfferSnapshot(input types.RequestOfferSnapshot) types.ResponseOfferSnapshot { + var ret types.ResponseOfferSnapshot + defer func() { + if r := recover(); r != nil { + ret = m.base.OfferSnapshot(input) + } + }() + ret = m.Application.OfferSnapshot(input) + return ret +} + +func (m BaseMock) LoadSnapshotChunk(input types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk { + var ret types.ResponseLoadSnapshotChunk + defer func() { + if r := recover(); r != nil { + ret = m.base.LoadSnapshotChunk(input) + } + }() + ret = m.Application.LoadSnapshotChunk(input) + return ret +} + +func (m BaseMock) ApplySnapshotChunk(input types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk { + var ret types.ResponseApplySnapshotChunk + defer func() { + if r := recover(); r != nil { + ret = m.base.ApplySnapshotChunk(input) + } + }() + ret = m.Application.ApplySnapshotChunk(input) + return ret +} + +func (m BaseMock) BeginBlock(input types.RequestBeginBlock) types.ResponseBeginBlock { + var ret types.ResponseBeginBlock + defer func() { + if r := recover(); r != nil { + ret = m.base.BeginBlock(input) + } + }() + ret = m.Application.BeginBlock(input) + return ret +} + +func (m BaseMock) DeliverTx(input types.RequestDeliverTx) types.ResponseDeliverTx { + var ret types.ResponseDeliverTx + defer func() { + if r := recover(); r != nil { + ret = m.base.DeliverTx(input) + } + }() + ret = m.Application.DeliverTx(input) + return ret +} + +func (m BaseMock) EndBlock(input types.RequestEndBlock) types.ResponseEndBlock { + var ret types.ResponseEndBlock + defer func() { + if r := recover(); r != nil { + ret = m.base.EndBlock(input) + } + }() + ret = m.Application.EndBlock(input) + return ret +} diff --git a/abci/types/result.go b/abci/types/types.go similarity index 90% rename from abci/types/result.go rename to abci/types/types.go index 53acdb906..de3abfe5f 100644 --- a/abci/types/result.go +++ b/abci/types/types.go @@ -41,6 +41,16 @@ func (r ResponseQuery) IsErr() bool { return r.Code != CodeTypeOK } +// IsAccepted returns true if Code is ACCEPT +func (r ResponseProcessProposal) IsAccepted() bool { + return r.Status == ResponseProcessProposal_ACCEPT +} + +// IsStatusUnknown returns true if Code is UNKNOWN +func (r ResponseProcessProposal) IsStatusUnknown() bool { + return r.Status == ResponseProcessProposal_UNKNOWN +} + //--------------------------------------------------------------------------- // override JSON marshaling so we emit defaults (ie. disable omitempty) @@ -52,16 +62,6 @@ var ( jsonpbUnmarshaller = jsonpb.Unmarshaler{} ) -func (r *ResponseSetOption) MarshalJSON() ([]byte, error) { - 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) { s, err := jsonpbMarshaller.MarshalToString(r) return []byte(s), err @@ -126,6 +126,5 @@ var _ jsonRoundTripper = (*ResponseCommit)(nil) var _ jsonRoundTripper = (*ResponseQuery)(nil) var _ jsonRoundTripper = (*ResponseDeliverTx)(nil) var _ jsonRoundTripper = (*ResponseCheckTx)(nil) -var _ jsonRoundTripper = (*ResponseSetOption)(nil) var _ jsonRoundTripper = (*EventAttribute)(nil) diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index 5da9c878f..766f900c7 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -58,31 +58,31 @@ func (CheckTxType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_252557cfdd89a31a, []int{0} } -type EvidenceType int32 +type MisbehaviorType int32 const ( - EvidenceType_UNKNOWN EvidenceType = 0 - EvidenceType_DUPLICATE_VOTE EvidenceType = 1 - EvidenceType_LIGHT_CLIENT_ATTACK EvidenceType = 2 + MisbehaviorType_UNKNOWN MisbehaviorType = 0 + MisbehaviorType_DUPLICATE_VOTE MisbehaviorType = 1 + MisbehaviorType_LIGHT_CLIENT_ATTACK MisbehaviorType = 2 ) -var EvidenceType_name = map[int32]string{ +var MisbehaviorType_name = map[int32]string{ 0: "UNKNOWN", 1: "DUPLICATE_VOTE", 2: "LIGHT_CLIENT_ATTACK", } -var EvidenceType_value = map[string]int32{ +var MisbehaviorType_value = map[string]int32{ "UNKNOWN": 0, "DUPLICATE_VOTE": 1, "LIGHT_CLIENT_ATTACK": 2, } -func (x EvidenceType) String() string { - return proto.EnumName(EvidenceType_name, int32(x)) +func (x MisbehaviorType) String() string { + return proto.EnumName(MisbehaviorType_name, int32(x)) } -func (EvidenceType) EnumDescriptor() ([]byte, []int) { +func (MisbehaviorType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_252557cfdd89a31a, []int{1} } @@ -160,12 +160,39 @@ func (ResponseApplySnapshotChunk_Result) EnumDescriptor() ([]byte, []int) { return fileDescriptor_252557cfdd89a31a, []int{32, 0} } +type ResponseProcessProposal_ProposalStatus int32 + +const ( + ResponseProcessProposal_UNKNOWN ResponseProcessProposal_ProposalStatus = 0 + ResponseProcessProposal_ACCEPT ResponseProcessProposal_ProposalStatus = 1 + ResponseProcessProposal_REJECT ResponseProcessProposal_ProposalStatus = 2 +) + +var ResponseProcessProposal_ProposalStatus_name = map[int32]string{ + 0: "UNKNOWN", + 1: "ACCEPT", + 2: "REJECT", +} + +var ResponseProcessProposal_ProposalStatus_value = map[string]int32{ + "UNKNOWN": 0, + "ACCEPT": 1, + "REJECT": 2, +} + +func (x ResponseProcessProposal_ProposalStatus) String() string { + return proto.EnumName(ResponseProcessProposal_ProposalStatus_name, int32(x)) +} + +func (ResponseProcessProposal_ProposalStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{34, 0} +} + type Request struct { // Types that are valid to be assigned to Value: // *Request_Echo // *Request_Flush // *Request_Info - // *Request_SetOption // *Request_InitChain // *Request_Query // *Request_BeginBlock @@ -177,6 +204,8 @@ type Request struct { // *Request_OfferSnapshot // *Request_LoadSnapshotChunk // *Request_ApplySnapshotChunk + // *Request_PrepareProposal + // *Request_ProcessProposal Value isRequest_Value `protobuf_oneof:"value"` } @@ -228,9 +257,6 @@ type Request_Flush struct { type Request_Info struct { Info *RequestInfo `protobuf:"bytes,3,opt,name=info,proto3,oneof" json:"info,omitempty"` } -type Request_SetOption struct { - SetOption *RequestSetOption `protobuf:"bytes,4,opt,name=set_option,json=setOption,proto3,oneof" json:"set_option,omitempty"` -} type Request_InitChain struct { InitChain *RequestInitChain `protobuf:"bytes,5,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` } @@ -264,11 +290,16 @@ type Request_LoadSnapshotChunk struct { type Request_ApplySnapshotChunk struct { ApplySnapshotChunk *RequestApplySnapshotChunk `protobuf:"bytes,15,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` } +type Request_PrepareProposal struct { + PrepareProposal *RequestPrepareProposal `protobuf:"bytes,16,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` +} +type Request_ProcessProposal struct { + ProcessProposal *RequestProcessProposal `protobuf:"bytes,17,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` +} func (*Request_Echo) isRequest_Value() {} func (*Request_Flush) isRequest_Value() {} func (*Request_Info) isRequest_Value() {} -func (*Request_SetOption) isRequest_Value() {} func (*Request_InitChain) isRequest_Value() {} func (*Request_Query) isRequest_Value() {} func (*Request_BeginBlock) isRequest_Value() {} @@ -280,6 +311,8 @@ func (*Request_ListSnapshots) isRequest_Value() {} func (*Request_OfferSnapshot) isRequest_Value() {} func (*Request_LoadSnapshotChunk) isRequest_Value() {} func (*Request_ApplySnapshotChunk) isRequest_Value() {} +func (*Request_PrepareProposal) isRequest_Value() {} +func (*Request_ProcessProposal) isRequest_Value() {} func (m *Request) GetValue() isRequest_Value { if m != nil { @@ -309,13 +342,6 @@ func (m *Request) GetInfo() *RequestInfo { return nil } -func (m *Request) GetSetOption() *RequestSetOption { - if x, ok := m.GetValue().(*Request_SetOption); ok { - return x.SetOption - } - return nil -} - func (m *Request) GetInitChain() *RequestInitChain { if x, ok := m.GetValue().(*Request_InitChain); ok { return x.InitChain @@ -393,13 +419,26 @@ func (m *Request) GetApplySnapshotChunk() *RequestApplySnapshotChunk { return nil } +func (m *Request) GetPrepareProposal() *RequestPrepareProposal { + if x, ok := m.GetValue().(*Request_PrepareProposal); ok { + return x.PrepareProposal + } + return nil +} + +func (m *Request) GetProcessProposal() *RequestProcessProposal { + if x, ok := m.GetValue().(*Request_ProcessProposal); ok { + return x.ProcessProposal + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*Request) XXX_OneofWrappers() []interface{} { return []interface{}{ (*Request_Echo)(nil), (*Request_Flush)(nil), (*Request_Info)(nil), - (*Request_SetOption)(nil), (*Request_InitChain)(nil), (*Request_Query)(nil), (*Request_BeginBlock)(nil), @@ -411,6 +450,8 @@ func (*Request) XXX_OneofWrappers() []interface{} { (*Request_OfferSnapshot)(nil), (*Request_LoadSnapshotChunk)(nil), (*Request_ApplySnapshotChunk)(nil), + (*Request_PrepareProposal)(nil), + (*Request_ProcessProposal)(nil), } } @@ -498,6 +539,7 @@ type RequestInfo struct { Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` BlockVersion uint64 `protobuf:"varint,2,opt,name=block_version,json=blockVersion,proto3" json:"block_version,omitempty"` P2PVersion uint64 `protobuf:"varint,3,opt,name=p2p_version,json=p2pVersion,proto3" json:"p2p_version,omitempty"` + AbciVersion string `protobuf:"bytes,4,opt,name=abci_version,json=abciVersion,proto3" json:"abci_version,omitempty"` } func (m *RequestInfo) Reset() { *m = RequestInfo{} } @@ -554,73 +596,27 @@ func (m *RequestInfo) GetP2PVersion() uint64 { return 0 } -// nondeterministic -type RequestSetOption struct { - 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 fileDescriptor_252557cfdd89a31a, []int{4} -} -func (m *RequestSetOption) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *RequestSetOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_RequestSetOption.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *RequestSetOption) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestSetOption.Merge(m, src) -} -func (m *RequestSetOption) XXX_Size() int { - return m.Size() -} -func (m *RequestSetOption) XXX_DiscardUnknown() { - xxx_messageInfo_RequestSetOption.DiscardUnknown(m) -} - -var xxx_messageInfo_RequestSetOption proto.InternalMessageInfo - -func (m *RequestSetOption) GetKey() string { +func (m *RequestInfo) GetAbciVersion() string { if m != nil { - return m.Key - } - return "" -} - -func (m *RequestSetOption) GetValue() string { - if m != nil { - return m.Value + return m.AbciVersion } return "" } type RequestInitChain struct { - Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time"` - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - ConsensusParams *ConsensusParams `protobuf:"bytes,3,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` - Validators []ValidatorUpdate `protobuf:"bytes,4,rep,name=validators,proto3" json:"validators"` - AppStateBytes []byte `protobuf:"bytes,5,opt,name=app_state_bytes,json=appStateBytes,proto3" json:"app_state_bytes,omitempty"` - InitialHeight int64 `protobuf:"varint,6,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` + Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ConsensusParams *types1.ConsensusParams `protobuf:"bytes,3,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []ValidatorUpdate `protobuf:"bytes,4,rep,name=validators,proto3" json:"validators"` + AppStateBytes []byte `protobuf:"bytes,5,opt,name=app_state_bytes,json=appStateBytes,proto3" json:"app_state_bytes,omitempty"` + InitialHeight int64 `protobuf:"varint,6,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,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 fileDescriptor_252557cfdd89a31a, []int{5} + return fileDescriptor_252557cfdd89a31a, []int{4} } func (m *RequestInitChain) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -663,7 +659,7 @@ func (m *RequestInitChain) GetChainId() string { return "" } -func (m *RequestInitChain) GetConsensusParams() *ConsensusParams { +func (m *RequestInitChain) GetConsensusParams() *types1.ConsensusParams { if m != nil { return m.ConsensusParams } @@ -702,7 +698,7 @@ func (m *RequestQuery) Reset() { *m = RequestQuery{} } func (m *RequestQuery) String() string { return proto.CompactTextString(m) } func (*RequestQuery) ProtoMessage() {} func (*RequestQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{6} + return fileDescriptor_252557cfdd89a31a, []int{5} } func (m *RequestQuery) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -760,17 +756,17 @@ func (m *RequestQuery) GetProve() bool { } type RequestBeginBlock struct { - Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` - Header types1.Header `protobuf:"bytes,2,opt,name=header,proto3" json:"header"` - LastCommitInfo LastCommitInfo `protobuf:"bytes,3,opt,name=last_commit_info,json=lastCommitInfo,proto3" json:"last_commit_info"` - ByzantineValidators []Evidence `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators,proto3" json:"byzantine_validators"` + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Header types1.Header `protobuf:"bytes,2,opt,name=header,proto3" json:"header"` + LastCommitInfo CommitInfo `protobuf:"bytes,3,opt,name=last_commit_info,json=lastCommitInfo,proto3" json:"last_commit_info"` + ByzantineValidators []Misbehavior `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators,proto3" json:"byzantine_validators"` } func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } func (*RequestBeginBlock) ProtoMessage() {} func (*RequestBeginBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{7} + return fileDescriptor_252557cfdd89a31a, []int{6} } func (m *RequestBeginBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -813,14 +809,14 @@ func (m *RequestBeginBlock) GetHeader() types1.Header { return types1.Header{} } -func (m *RequestBeginBlock) GetLastCommitInfo() LastCommitInfo { +func (m *RequestBeginBlock) GetLastCommitInfo() CommitInfo { if m != nil { return m.LastCommitInfo } - return LastCommitInfo{} + return CommitInfo{} } -func (m *RequestBeginBlock) GetByzantineValidators() []Evidence { +func (m *RequestBeginBlock) GetByzantineValidators() []Misbehavior { if m != nil { return m.ByzantineValidators } @@ -836,7 +832,7 @@ func (m *RequestCheckTx) Reset() { *m = RequestCheckTx{} } func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) } func (*RequestCheckTx) ProtoMessage() {} func (*RequestCheckTx) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{8} + return fileDescriptor_252557cfdd89a31a, []int{7} } func (m *RequestCheckTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -887,7 +883,7 @@ func (m *RequestDeliverTx) Reset() { *m = RequestDeliverTx{} } func (m *RequestDeliverTx) String() string { return proto.CompactTextString(m) } func (*RequestDeliverTx) ProtoMessage() {} func (*RequestDeliverTx) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{9} + return fileDescriptor_252557cfdd89a31a, []int{8} } func (m *RequestDeliverTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -931,7 +927,7 @@ func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) } func (*RequestEndBlock) ProtoMessage() {} func (*RequestEndBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{10} + return fileDescriptor_252557cfdd89a31a, []int{9} } func (m *RequestEndBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -974,7 +970,7 @@ func (m *RequestCommit) Reset() { *m = RequestCommit{} } func (m *RequestCommit) String() string { return proto.CompactTextString(m) } func (*RequestCommit) ProtoMessage() {} func (*RequestCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{11} + return fileDescriptor_252557cfdd89a31a, []int{10} } func (m *RequestCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1011,7 +1007,7 @@ func (m *RequestListSnapshots) Reset() { *m = RequestListSnapshots{} } func (m *RequestListSnapshots) String() string { return proto.CompactTextString(m) } func (*RequestListSnapshots) ProtoMessage() {} func (*RequestListSnapshots) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{12} + return fileDescriptor_252557cfdd89a31a, []int{11} } func (m *RequestListSnapshots) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1050,7 +1046,7 @@ func (m *RequestOfferSnapshot) Reset() { *m = RequestOfferSnapshot{} } func (m *RequestOfferSnapshot) String() string { return proto.CompactTextString(m) } func (*RequestOfferSnapshot) ProtoMessage() {} func (*RequestOfferSnapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{13} + return fileDescriptor_252557cfdd89a31a, []int{12} } func (m *RequestOfferSnapshot) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1104,7 +1100,7 @@ func (m *RequestLoadSnapshotChunk) Reset() { *m = RequestLoadSnapshotChu func (m *RequestLoadSnapshotChunk) String() string { return proto.CompactTextString(m) } func (*RequestLoadSnapshotChunk) ProtoMessage() {} func (*RequestLoadSnapshotChunk) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{14} + return fileDescriptor_252557cfdd89a31a, []int{13} } func (m *RequestLoadSnapshotChunk) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1165,7 +1161,7 @@ func (m *RequestApplySnapshotChunk) Reset() { *m = RequestApplySnapshotC func (m *RequestApplySnapshotChunk) String() string { return proto.CompactTextString(m) } func (*RequestApplySnapshotChunk) ProtoMessage() {} func (*RequestApplySnapshotChunk) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{15} + return fileDescriptor_252557cfdd89a31a, []int{14} } func (m *RequestApplySnapshotChunk) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1215,13 +1211,218 @@ func (m *RequestApplySnapshotChunk) GetSender() string { return "" } +type RequestPrepareProposal struct { + // the modified transactions cannot exceed this size. + MaxTxBytes int64 `protobuf:"varint,1,opt,name=max_tx_bytes,json=maxTxBytes,proto3" json:"max_tx_bytes,omitempty"` + // txs is an array of transactions that will be included in a block, + // sent to the app for possible modifications. + Txs [][]byte `protobuf:"bytes,2,rep,name=txs,proto3" json:"txs,omitempty"` + LocalLastCommit ExtendedCommitInfo `protobuf:"bytes,3,opt,name=local_last_commit,json=localLastCommit,proto3" json:"local_last_commit"` + Misbehavior []Misbehavior `protobuf:"bytes,4,rep,name=misbehavior,proto3" json:"misbehavior"` + Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` + Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"` + NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + // address of the public key of the validator proposing the block. + ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` +} + +func (m *RequestPrepareProposal) Reset() { *m = RequestPrepareProposal{} } +func (m *RequestPrepareProposal) String() string { return proto.CompactTextString(m) } +func (*RequestPrepareProposal) ProtoMessage() {} +func (*RequestPrepareProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{15} +} +func (m *RequestPrepareProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestPrepareProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestPrepareProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestPrepareProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestPrepareProposal.Merge(m, src) +} +func (m *RequestPrepareProposal) XXX_Size() int { + return m.Size() +} +func (m *RequestPrepareProposal) XXX_DiscardUnknown() { + xxx_messageInfo_RequestPrepareProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestPrepareProposal proto.InternalMessageInfo + +func (m *RequestPrepareProposal) GetMaxTxBytes() int64 { + if m != nil { + return m.MaxTxBytes + } + return 0 +} + +func (m *RequestPrepareProposal) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +func (m *RequestPrepareProposal) GetLocalLastCommit() ExtendedCommitInfo { + if m != nil { + return m.LocalLastCommit + } + return ExtendedCommitInfo{} +} + +func (m *RequestPrepareProposal) GetMisbehavior() []Misbehavior { + if m != nil { + return m.Misbehavior + } + return nil +} + +func (m *RequestPrepareProposal) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestPrepareProposal) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestPrepareProposal) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *RequestPrepareProposal) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +type RequestProcessProposal struct { + Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` + ProposedLastCommit CommitInfo `protobuf:"bytes,2,opt,name=proposed_last_commit,json=proposedLastCommit,proto3" json:"proposed_last_commit"` + Misbehavior []Misbehavior `protobuf:"bytes,3,rep,name=misbehavior,proto3" json:"misbehavior"` + // hash is the merkle root hash of the fields of the proposed block. + Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` + Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` + Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"` + NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + // address of the public key of the original proposer of the block. + ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` +} + +func (m *RequestProcessProposal) Reset() { *m = RequestProcessProposal{} } +func (m *RequestProcessProposal) String() string { return proto.CompactTextString(m) } +func (*RequestProcessProposal) ProtoMessage() {} +func (*RequestProcessProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{16} +} +func (m *RequestProcessProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestProcessProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestProcessProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestProcessProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestProcessProposal.Merge(m, src) +} +func (m *RequestProcessProposal) XXX_Size() int { + return m.Size() +} +func (m *RequestProcessProposal) XXX_DiscardUnknown() { + xxx_messageInfo_RequestProcessProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestProcessProposal proto.InternalMessageInfo + +func (m *RequestProcessProposal) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +func (m *RequestProcessProposal) GetProposedLastCommit() CommitInfo { + if m != nil { + return m.ProposedLastCommit + } + return CommitInfo{} +} + +func (m *RequestProcessProposal) GetMisbehavior() []Misbehavior { + if m != nil { + return m.Misbehavior + } + return nil +} + +func (m *RequestProcessProposal) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *RequestProcessProposal) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestProcessProposal) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestProcessProposal) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *RequestProcessProposal) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + type Response struct { // Types that are valid to be assigned to Value: // *Response_Exception // *Response_Echo // *Response_Flush // *Response_Info - // *Response_SetOption // *Response_InitChain // *Response_Query // *Response_BeginBlock @@ -1233,6 +1434,8 @@ type Response struct { // *Response_OfferSnapshot // *Response_LoadSnapshotChunk // *Response_ApplySnapshotChunk + // *Response_PrepareProposal + // *Response_ProcessProposal Value isResponse_Value `protobuf_oneof:"value"` } @@ -1240,7 +1443,7 @@ func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{16} + return fileDescriptor_252557cfdd89a31a, []int{17} } func (m *Response) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1287,9 +1490,6 @@ type Response_Flush struct { type Response_Info struct { Info *ResponseInfo `protobuf:"bytes,4,opt,name=info,proto3,oneof" json:"info,omitempty"` } -type Response_SetOption struct { - SetOption *ResponseSetOption `protobuf:"bytes,5,opt,name=set_option,json=setOption,proto3,oneof" json:"set_option,omitempty"` -} type Response_InitChain struct { InitChain *ResponseInitChain `protobuf:"bytes,6,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` } @@ -1323,12 +1523,17 @@ type Response_LoadSnapshotChunk struct { type Response_ApplySnapshotChunk struct { ApplySnapshotChunk *ResponseApplySnapshotChunk `protobuf:"bytes,16,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` } +type Response_PrepareProposal struct { + PrepareProposal *ResponsePrepareProposal `protobuf:"bytes,17,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` +} +type Response_ProcessProposal struct { + ProcessProposal *ResponseProcessProposal `protobuf:"bytes,18,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` +} 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_InitChain) isResponse_Value() {} func (*Response_Query) isResponse_Value() {} func (*Response_BeginBlock) isResponse_Value() {} @@ -1340,6 +1545,8 @@ func (*Response_ListSnapshots) isResponse_Value() {} func (*Response_OfferSnapshot) isResponse_Value() {} func (*Response_LoadSnapshotChunk) isResponse_Value() {} func (*Response_ApplySnapshotChunk) isResponse_Value() {} +func (*Response_PrepareProposal) isResponse_Value() {} +func (*Response_ProcessProposal) isResponse_Value() {} func (m *Response) GetValue() isResponse_Value { if m != nil { @@ -1376,13 +1583,6 @@ func (m *Response) GetInfo() *ResponseInfo { return nil } -func (m *Response) GetSetOption() *ResponseSetOption { - if x, ok := m.GetValue().(*Response_SetOption); ok { - return x.SetOption - } - return nil -} - func (m *Response) GetInitChain() *ResponseInitChain { if x, ok := m.GetValue().(*Response_InitChain); ok { return x.InitChain @@ -1460,6 +1660,20 @@ func (m *Response) GetApplySnapshotChunk() *ResponseApplySnapshotChunk { return nil } +func (m *Response) GetPrepareProposal() *ResponsePrepareProposal { + if x, ok := m.GetValue().(*Response_PrepareProposal); ok { + return x.PrepareProposal + } + return nil +} + +func (m *Response) GetProcessProposal() *ResponseProcessProposal { + if x, ok := m.GetValue().(*Response_ProcessProposal); ok { + return x.ProcessProposal + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*Response) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -1467,7 +1681,6 @@ func (*Response) XXX_OneofWrappers() []interface{} { (*Response_Echo)(nil), (*Response_Flush)(nil), (*Response_Info)(nil), - (*Response_SetOption)(nil), (*Response_InitChain)(nil), (*Response_Query)(nil), (*Response_BeginBlock)(nil), @@ -1479,6 +1692,8 @@ func (*Response) XXX_OneofWrappers() []interface{} { (*Response_OfferSnapshot)(nil), (*Response_LoadSnapshotChunk)(nil), (*Response_ApplySnapshotChunk)(nil), + (*Response_PrepareProposal)(nil), + (*Response_ProcessProposal)(nil), } } @@ -1491,7 +1706,7 @@ func (m *ResponseException) Reset() { *m = ResponseException{} } func (m *ResponseException) String() string { return proto.CompactTextString(m) } func (*ResponseException) ProtoMessage() {} func (*ResponseException) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{17} + return fileDescriptor_252557cfdd89a31a, []int{18} } func (m *ResponseException) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1535,7 +1750,7 @@ func (m *ResponseEcho) Reset() { *m = ResponseEcho{} } func (m *ResponseEcho) String() string { return proto.CompactTextString(m) } func (*ResponseEcho) ProtoMessage() {} func (*ResponseEcho) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{18} + return fileDescriptor_252557cfdd89a31a, []int{19} } func (m *ResponseEcho) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1578,7 +1793,7 @@ func (m *ResponseFlush) Reset() { *m = ResponseFlush{} } func (m *ResponseFlush) String() string { return proto.CompactTextString(m) } func (*ResponseFlush) ProtoMessage() {} func (*ResponseFlush) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{19} + return fileDescriptor_252557cfdd89a31a, []int{20} } func (m *ResponseFlush) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1619,7 +1834,7 @@ func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } func (m *ResponseInfo) String() string { return proto.CompactTextString(m) } func (*ResponseInfo) ProtoMessage() {} func (*ResponseInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{20} + return fileDescriptor_252557cfdd89a31a, []int{21} } func (m *ResponseInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1683,72 +1898,10 @@ func (m *ResponseInfo) GetLastBlockAppHash() []byte { return nil } -// nondeterministic -type ResponseSetOption struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - // bytes data = 2; - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,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 fileDescriptor_252557cfdd89a31a, []int{21} -} -func (m *ResponseSetOption) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ResponseSetOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ResponseSetOption.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ResponseSetOption) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseSetOption.Merge(m, src) -} -func (m *ResponseSetOption) XXX_Size() int { - return m.Size() -} -func (m *ResponseSetOption) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseSetOption.DiscardUnknown(m) -} - -var xxx_messageInfo_ResponseSetOption proto.InternalMessageInfo - -func (m *ResponseSetOption) GetCode() uint32 { - if m != nil { - return m.Code - } - return 0 -} - -func (m *ResponseSetOption) GetLog() string { - if m != nil { - return m.Log - } - return "" -} - -func (m *ResponseSetOption) GetInfo() string { - if m != nil { - return m.Info - } - return "" -} - type ResponseInitChain struct { - ConsensusParams *ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` - Validators []ValidatorUpdate `protobuf:"bytes,2,rep,name=validators,proto3" json:"validators"` - AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` + ConsensusParams *types1.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []ValidatorUpdate `protobuf:"bytes,2,rep,name=validators,proto3" json:"validators"` + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } @@ -1784,7 +1937,7 @@ func (m *ResponseInitChain) XXX_DiscardUnknown() { var xxx_messageInfo_ResponseInitChain proto.InternalMessageInfo -func (m *ResponseInitChain) GetConsensusParams() *ConsensusParams { +func (m *ResponseInitChain) GetConsensusParams() *types1.ConsensusParams { if m != nil { return m.ConsensusParams } @@ -2185,9 +2338,9 @@ func (m *ResponseDeliverTx) GetCodespace() string { } type ResponseEndBlock struct { - ValidatorUpdates []ValidatorUpdate `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` - ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` - Events []Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"` + ValidatorUpdates []ValidatorUpdate `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` + ConsensusParamUpdates *types1.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` + Events []Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"` } func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } @@ -2230,7 +2383,7 @@ func (m *ResponseEndBlock) GetValidatorUpdates() []ValidatorUpdate { return nil } -func (m *ResponseEndBlock) GetConsensusParamUpdates() *ConsensusParams { +func (m *ResponseEndBlock) GetConsensusParamUpdates() *types1.ConsensusParams { if m != nil { return m.ConsensusParamUpdates } @@ -2489,27 +2642,22 @@ func (m *ResponseApplySnapshotChunk) GetRejectSenders() []string { return nil } -// ConsensusParams contains all consensus-relevant parameters -// that can be adjusted by the abci app -type ConsensusParams struct { - Block *BlockParams `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Evidence *types1.EvidenceParams `protobuf:"bytes,2,opt,name=evidence,proto3" json:"evidence,omitempty"` - Validator *types1.ValidatorParams `protobuf:"bytes,3,opt,name=validator,proto3" json:"validator,omitempty"` - Version *types1.VersionParams `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` +type ResponsePrepareProposal struct { + Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` } -func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } -func (m *ConsensusParams) String() string { return proto.CompactTextString(m) } -func (*ConsensusParams) ProtoMessage() {} -func (*ConsensusParams) Descriptor() ([]byte, []int) { +func (m *ResponsePrepareProposal) Reset() { *m = ResponsePrepareProposal{} } +func (m *ResponsePrepareProposal) String() string { return proto.CompactTextString(m) } +func (*ResponsePrepareProposal) ProtoMessage() {} +func (*ResponsePrepareProposal) Descriptor() ([]byte, []int) { return fileDescriptor_252557cfdd89a31a, []int{33} } -func (m *ConsensusParams) XXX_Unmarshal(b []byte) error { +func (m *ResponsePrepareProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ConsensusParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ResponsePrepareProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ConsensusParams.Marshal(b, m, deterministic) + return xxx_messageInfo_ResponsePrepareProposal.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2519,66 +2667,41 @@ func (m *ConsensusParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, err return b[:n], nil } } -func (m *ConsensusParams) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConsensusParams.Merge(m, src) +func (m *ResponsePrepareProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponsePrepareProposal.Merge(m, src) } -func (m *ConsensusParams) XXX_Size() int { +func (m *ResponsePrepareProposal) XXX_Size() int { return m.Size() } -func (m *ConsensusParams) XXX_DiscardUnknown() { - xxx_messageInfo_ConsensusParams.DiscardUnknown(m) +func (m *ResponsePrepareProposal) XXX_DiscardUnknown() { + xxx_messageInfo_ResponsePrepareProposal.DiscardUnknown(m) } -var xxx_messageInfo_ConsensusParams proto.InternalMessageInfo +var xxx_messageInfo_ResponsePrepareProposal proto.InternalMessageInfo -func (m *ConsensusParams) GetBlock() *BlockParams { +func (m *ResponsePrepareProposal) GetTxs() [][]byte { if m != nil { - return m.Block + return m.Txs } return nil } -func (m *ConsensusParams) GetEvidence() *types1.EvidenceParams { - if m != nil { - return m.Evidence - } - return nil +type ResponseProcessProposal struct { + Status ResponseProcessProposal_ProposalStatus `protobuf:"varint,1,opt,name=status,proto3,enum=tendermint.abci.ResponseProcessProposal_ProposalStatus" json:"status,omitempty"` } -func (m *ConsensusParams) GetValidator() *types1.ValidatorParams { - if m != nil { - return m.Validator - } - return nil -} - -func (m *ConsensusParams) GetVersion() *types1.VersionParams { - if m != nil { - return m.Version - } - return nil -} - -// BlockParams contains limits on the block size. -type BlockParams struct { - // Note: must be greater than 0 - MaxBytes int64 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` - // Note: must be greater or equal to -1 - MaxGas int64 `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` -} - -func (m *BlockParams) Reset() { *m = BlockParams{} } -func (m *BlockParams) String() string { return proto.CompactTextString(m) } -func (*BlockParams) ProtoMessage() {} -func (*BlockParams) Descriptor() ([]byte, []int) { +func (m *ResponseProcessProposal) Reset() { *m = ResponseProcessProposal{} } +func (m *ResponseProcessProposal) String() string { return proto.CompactTextString(m) } +func (*ResponseProcessProposal) ProtoMessage() {} +func (*ResponseProcessProposal) Descriptor() ([]byte, []int) { return fileDescriptor_252557cfdd89a31a, []int{34} } -func (m *BlockParams) XXX_Unmarshal(b []byte) error { +func (m *ResponseProcessProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *BlockParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ResponseProcessProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_BlockParams.Marshal(b, m, deterministic) + return xxx_messageInfo_ResponseProcessProposal.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2588,49 +2711,42 @@ func (m *BlockParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } -func (m *BlockParams) XXX_Merge(src proto.Message) { - xxx_messageInfo_BlockParams.Merge(m, src) +func (m *ResponseProcessProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseProcessProposal.Merge(m, src) } -func (m *BlockParams) XXX_Size() int { +func (m *ResponseProcessProposal) XXX_Size() int { return m.Size() } -func (m *BlockParams) XXX_DiscardUnknown() { - xxx_messageInfo_BlockParams.DiscardUnknown(m) +func (m *ResponseProcessProposal) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseProcessProposal.DiscardUnknown(m) } -var xxx_messageInfo_BlockParams proto.InternalMessageInfo +var xxx_messageInfo_ResponseProcessProposal proto.InternalMessageInfo -func (m *BlockParams) GetMaxBytes() int64 { +func (m *ResponseProcessProposal) GetStatus() ResponseProcessProposal_ProposalStatus { if m != nil { - return m.MaxBytes + return m.Status } - return 0 + return ResponseProcessProposal_UNKNOWN } -func (m *BlockParams) GetMaxGas() int64 { - if m != nil { - return m.MaxGas - } - return 0 -} - -type LastCommitInfo struct { +type CommitInfo struct { Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` Votes []VoteInfo `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes"` } -func (m *LastCommitInfo) Reset() { *m = LastCommitInfo{} } -func (m *LastCommitInfo) String() string { return proto.CompactTextString(m) } -func (*LastCommitInfo) ProtoMessage() {} -func (*LastCommitInfo) Descriptor() ([]byte, []int) { +func (m *CommitInfo) Reset() { *m = CommitInfo{} } +func (m *CommitInfo) String() string { return proto.CompactTextString(m) } +func (*CommitInfo) ProtoMessage() {} +func (*CommitInfo) Descriptor() ([]byte, []int) { return fileDescriptor_252557cfdd89a31a, []int{35} } -func (m *LastCommitInfo) XXX_Unmarshal(b []byte) error { +func (m *CommitInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *LastCommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *CommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_LastCommitInfo.Marshal(b, m, deterministic) + return xxx_messageInfo_CommitInfo.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2640,26 +2756,81 @@ func (m *LastCommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, erro return b[:n], nil } } -func (m *LastCommitInfo) XXX_Merge(src proto.Message) { - xxx_messageInfo_LastCommitInfo.Merge(m, src) +func (m *CommitInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommitInfo.Merge(m, src) } -func (m *LastCommitInfo) XXX_Size() int { +func (m *CommitInfo) XXX_Size() int { return m.Size() } -func (m *LastCommitInfo) XXX_DiscardUnknown() { - xxx_messageInfo_LastCommitInfo.DiscardUnknown(m) +func (m *CommitInfo) XXX_DiscardUnknown() { + xxx_messageInfo_CommitInfo.DiscardUnknown(m) } -var xxx_messageInfo_LastCommitInfo proto.InternalMessageInfo +var xxx_messageInfo_CommitInfo proto.InternalMessageInfo -func (m *LastCommitInfo) GetRound() int32 { +func (m *CommitInfo) GetRound() int32 { if m != nil { return m.Round } return 0 } -func (m *LastCommitInfo) GetVotes() []VoteInfo { +func (m *CommitInfo) GetVotes() []VoteInfo { + if m != nil { + return m.Votes + } + return nil +} + +type ExtendedCommitInfo struct { + // The round at which the block proposer decided in the previous height. + Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` + // List of validators' addresses in the last validator set with their voting + // information, including vote extensions. + Votes []ExtendedVoteInfo `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes"` +} + +func (m *ExtendedCommitInfo) Reset() { *m = ExtendedCommitInfo{} } +func (m *ExtendedCommitInfo) String() string { return proto.CompactTextString(m) } +func (*ExtendedCommitInfo) ProtoMessage() {} +func (*ExtendedCommitInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{36} +} +func (m *ExtendedCommitInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExtendedCommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExtendedCommitInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExtendedCommitInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendedCommitInfo.Merge(m, src) +} +func (m *ExtendedCommitInfo) XXX_Size() int { + return m.Size() +} +func (m *ExtendedCommitInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendedCommitInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtendedCommitInfo proto.InternalMessageInfo + +func (m *ExtendedCommitInfo) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *ExtendedCommitInfo) GetVotes() []ExtendedVoteInfo { if m != nil { return m.Votes } @@ -2678,7 +2849,7 @@ func (m *Event) Reset() { *m = Event{} } func (m *Event) String() string { return proto.CompactTextString(m) } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{36} + return fileDescriptor_252557cfdd89a31a, []int{37} } func (m *Event) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2732,7 +2903,7 @@ func (m *EventAttribute) Reset() { *m = EventAttribute{} } func (m *EventAttribute) String() string { return proto.CompactTextString(m) } func (*EventAttribute) ProtoMessage() {} func (*EventAttribute) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{37} + return fileDescriptor_252557cfdd89a31a, []int{38} } func (m *EventAttribute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2796,7 +2967,7 @@ func (m *TxResult) Reset() { *m = TxResult{} } func (m *TxResult) String() string { return proto.CompactTextString(m) } func (*TxResult) ProtoMessage() {} func (*TxResult) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{38} + return fileDescriptor_252557cfdd89a31a, []int{39} } func (m *TxResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2864,7 +3035,7 @@ func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} func (*Validator) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{39} + return fileDescriptor_252557cfdd89a31a, []int{40} } func (m *Validator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2917,7 +3088,7 @@ func (m *ValidatorUpdate) Reset() { *m = ValidatorUpdate{} } func (m *ValidatorUpdate) String() string { return proto.CompactTextString(m) } func (*ValidatorUpdate) ProtoMessage() {} func (*ValidatorUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{40} + return fileDescriptor_252557cfdd89a31a, []int{41} } func (m *ValidatorUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2970,7 +3141,7 @@ func (m *VoteInfo) Reset() { *m = VoteInfo{} } func (m *VoteInfo) String() string { return proto.CompactTextString(m) } func (*VoteInfo) ProtoMessage() {} func (*VoteInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{41} + return fileDescriptor_252557cfdd89a31a, []int{42} } func (m *VoteInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3013,8 +3184,68 @@ func (m *VoteInfo) GetSignedLastBlock() bool { return false } -type Evidence struct { - Type EvidenceType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.abci.EvidenceType" json:"type,omitempty"` +type ExtendedVoteInfo struct { + Validator Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator"` + SignedLastBlock bool `protobuf:"varint,2,opt,name=signed_last_block,json=signedLastBlock,proto3" json:"signed_last_block,omitempty"` + VoteExtension []byte `protobuf:"bytes,3,opt,name=vote_extension,json=voteExtension,proto3" json:"vote_extension,omitempty"` +} + +func (m *ExtendedVoteInfo) Reset() { *m = ExtendedVoteInfo{} } +func (m *ExtendedVoteInfo) String() string { return proto.CompactTextString(m) } +func (*ExtendedVoteInfo) ProtoMessage() {} +func (*ExtendedVoteInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{43} +} +func (m *ExtendedVoteInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExtendedVoteInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExtendedVoteInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExtendedVoteInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendedVoteInfo.Merge(m, src) +} +func (m *ExtendedVoteInfo) XXX_Size() int { + return m.Size() +} +func (m *ExtendedVoteInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendedVoteInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtendedVoteInfo proto.InternalMessageInfo + +func (m *ExtendedVoteInfo) GetValidator() Validator { + if m != nil { + return m.Validator + } + return Validator{} +} + +func (m *ExtendedVoteInfo) GetSignedLastBlock() bool { + if m != nil { + return m.SignedLastBlock + } + return false +} + +func (m *ExtendedVoteInfo) GetVoteExtension() []byte { + if m != nil { + return m.VoteExtension + } + return nil +} + +type Misbehavior struct { + Type MisbehaviorType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.abci.MisbehaviorType" json:"type,omitempty"` // The offending validator Validator Validator `protobuf:"bytes,2,opt,name=validator,proto3" json:"validator"` // The height when the offense occurred @@ -3027,18 +3258,18 @@ type Evidence struct { TotalVotingPower int64 `protobuf:"varint,5,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,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 fileDescriptor_252557cfdd89a31a, []int{42} +func (m *Misbehavior) Reset() { *m = Misbehavior{} } +func (m *Misbehavior) String() string { return proto.CompactTextString(m) } +func (*Misbehavior) ProtoMessage() {} +func (*Misbehavior) Descriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{44} } -func (m *Evidence) XXX_Unmarshal(b []byte) error { +func (m *Misbehavior) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *Evidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *Misbehavior) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_Evidence.Marshal(b, m, deterministic) + return xxx_messageInfo_Misbehavior.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -3048,47 +3279,47 @@ func (m *Evidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return b[:n], nil } } -func (m *Evidence) XXX_Merge(src proto.Message) { - xxx_messageInfo_Evidence.Merge(m, src) +func (m *Misbehavior) XXX_Merge(src proto.Message) { + xxx_messageInfo_Misbehavior.Merge(m, src) } -func (m *Evidence) XXX_Size() int { +func (m *Misbehavior) XXX_Size() int { return m.Size() } -func (m *Evidence) XXX_DiscardUnknown() { - xxx_messageInfo_Evidence.DiscardUnknown(m) +func (m *Misbehavior) XXX_DiscardUnknown() { + xxx_messageInfo_Misbehavior.DiscardUnknown(m) } -var xxx_messageInfo_Evidence proto.InternalMessageInfo +var xxx_messageInfo_Misbehavior proto.InternalMessageInfo -func (m *Evidence) GetType() EvidenceType { +func (m *Misbehavior) GetType() MisbehaviorType { if m != nil { return m.Type } - return EvidenceType_UNKNOWN + return MisbehaviorType_UNKNOWN } -func (m *Evidence) GetValidator() Validator { +func (m *Misbehavior) GetValidator() Validator { if m != nil { return m.Validator } return Validator{} } -func (m *Evidence) GetHeight() int64 { +func (m *Misbehavior) GetHeight() int64 { if m != nil { return m.Height } return 0 } -func (m *Evidence) GetTime() time.Time { +func (m *Misbehavior) GetTime() time.Time { if m != nil { return m.Time } return time.Time{} } -func (m *Evidence) GetTotalVotingPower() int64 { +func (m *Misbehavior) GetTotalVotingPower() int64 { if m != nil { return m.TotalVotingPower } @@ -3107,7 +3338,7 @@ func (m *Snapshot) Reset() { *m = Snapshot{} } func (m *Snapshot) String() string { return proto.CompactTextString(m) } func (*Snapshot) ProtoMessage() {} func (*Snapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{43} + return fileDescriptor_252557cfdd89a31a, []int{45} } func (m *Snapshot) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3173,14 +3404,14 @@ func (m *Snapshot) GetMetadata() []byte { func init() { proto.RegisterEnum("tendermint.abci.CheckTxType", CheckTxType_name, CheckTxType_value) - proto.RegisterEnum("tendermint.abci.EvidenceType", EvidenceType_name, EvidenceType_value) + proto.RegisterEnum("tendermint.abci.MisbehaviorType", MisbehaviorType_name, MisbehaviorType_value) proto.RegisterEnum("tendermint.abci.ResponseOfferSnapshot_Result", ResponseOfferSnapshot_Result_name, ResponseOfferSnapshot_Result_value) proto.RegisterEnum("tendermint.abci.ResponseApplySnapshotChunk_Result", ResponseApplySnapshotChunk_Result_name, ResponseApplySnapshotChunk_Result_value) + proto.RegisterEnum("tendermint.abci.ResponseProcessProposal_ProposalStatus", ResponseProcessProposal_ProposalStatus_name, ResponseProcessProposal_ProposalStatus_value) proto.RegisterType((*Request)(nil), "tendermint.abci.Request") proto.RegisterType((*RequestEcho)(nil), "tendermint.abci.RequestEcho") proto.RegisterType((*RequestFlush)(nil), "tendermint.abci.RequestFlush") proto.RegisterType((*RequestInfo)(nil), "tendermint.abci.RequestInfo") - proto.RegisterType((*RequestSetOption)(nil), "tendermint.abci.RequestSetOption") proto.RegisterType((*RequestInitChain)(nil), "tendermint.abci.RequestInitChain") proto.RegisterType((*RequestQuery)(nil), "tendermint.abci.RequestQuery") proto.RegisterType((*RequestBeginBlock)(nil), "tendermint.abci.RequestBeginBlock") @@ -3192,12 +3423,13 @@ func init() { proto.RegisterType((*RequestOfferSnapshot)(nil), "tendermint.abci.RequestOfferSnapshot") proto.RegisterType((*RequestLoadSnapshotChunk)(nil), "tendermint.abci.RequestLoadSnapshotChunk") proto.RegisterType((*RequestApplySnapshotChunk)(nil), "tendermint.abci.RequestApplySnapshotChunk") + proto.RegisterType((*RequestPrepareProposal)(nil), "tendermint.abci.RequestPrepareProposal") + proto.RegisterType((*RequestProcessProposal)(nil), "tendermint.abci.RequestProcessProposal") proto.RegisterType((*Response)(nil), "tendermint.abci.Response") proto.RegisterType((*ResponseException)(nil), "tendermint.abci.ResponseException") proto.RegisterType((*ResponseEcho)(nil), "tendermint.abci.ResponseEcho") proto.RegisterType((*ResponseFlush)(nil), "tendermint.abci.ResponseFlush") proto.RegisterType((*ResponseInfo)(nil), "tendermint.abci.ResponseInfo") - proto.RegisterType((*ResponseSetOption)(nil), "tendermint.abci.ResponseSetOption") proto.RegisterType((*ResponseInitChain)(nil), "tendermint.abci.ResponseInitChain") proto.RegisterType((*ResponseQuery)(nil), "tendermint.abci.ResponseQuery") proto.RegisterType((*ResponseBeginBlock)(nil), "tendermint.abci.ResponseBeginBlock") @@ -3209,197 +3441,213 @@ func init() { proto.RegisterType((*ResponseOfferSnapshot)(nil), "tendermint.abci.ResponseOfferSnapshot") proto.RegisterType((*ResponseLoadSnapshotChunk)(nil), "tendermint.abci.ResponseLoadSnapshotChunk") proto.RegisterType((*ResponseApplySnapshotChunk)(nil), "tendermint.abci.ResponseApplySnapshotChunk") - proto.RegisterType((*ConsensusParams)(nil), "tendermint.abci.ConsensusParams") - proto.RegisterType((*BlockParams)(nil), "tendermint.abci.BlockParams") - proto.RegisterType((*LastCommitInfo)(nil), "tendermint.abci.LastCommitInfo") + proto.RegisterType((*ResponsePrepareProposal)(nil), "tendermint.abci.ResponsePrepareProposal") + proto.RegisterType((*ResponseProcessProposal)(nil), "tendermint.abci.ResponseProcessProposal") + proto.RegisterType((*CommitInfo)(nil), "tendermint.abci.CommitInfo") + proto.RegisterType((*ExtendedCommitInfo)(nil), "tendermint.abci.ExtendedCommitInfo") proto.RegisterType((*Event)(nil), "tendermint.abci.Event") proto.RegisterType((*EventAttribute)(nil), "tendermint.abci.EventAttribute") proto.RegisterType((*TxResult)(nil), "tendermint.abci.TxResult") proto.RegisterType((*Validator)(nil), "tendermint.abci.Validator") proto.RegisterType((*ValidatorUpdate)(nil), "tendermint.abci.ValidatorUpdate") proto.RegisterType((*VoteInfo)(nil), "tendermint.abci.VoteInfo") - proto.RegisterType((*Evidence)(nil), "tendermint.abci.Evidence") + proto.RegisterType((*ExtendedVoteInfo)(nil), "tendermint.abci.ExtendedVoteInfo") + proto.RegisterType((*Misbehavior)(nil), "tendermint.abci.Misbehavior") proto.RegisterType((*Snapshot)(nil), "tendermint.abci.Snapshot") } func init() { proto.RegisterFile("tendermint/abci/types.proto", fileDescriptor_252557cfdd89a31a) } var fileDescriptor_252557cfdd89a31a = []byte{ - // 2782 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x4b, 0x77, 0x23, 0xc5, - 0xf5, 0xd7, 0x5b, 0xea, 0x2b, 0xeb, 0xe1, 0x1a, 0x33, 0x08, 0x31, 0xd8, 0x43, 0x73, 0xe0, 0x0f, - 0x03, 0xd8, 0x7f, 0xcc, 0x81, 0x40, 0x20, 0x01, 0x4b, 0x68, 0x90, 0xb1, 0xb1, 0x9c, 0xb6, 0x66, - 0xc8, 0x8b, 0x69, 0x5a, 0xea, 0xb2, 0xd4, 0x8c, 0xd4, 0xdd, 0x74, 0x97, 0x8c, 0xc5, 0x32, 0x8f, - 0x0d, 0xd9, 0x90, 0x5d, 0x36, 0x7c, 0x8f, 0xac, 0xb2, 0xc9, 0x86, 0x73, 0xb2, 0x61, 0x99, 0x45, - 0x0e, 0xc9, 0x99, 0x39, 0xd9, 0xe4, 0x0b, 0x64, 0x95, 0x93, 0x9c, 0x7a, 0xf4, 0x4b, 0x52, 0x4b, - 0x32, 0x64, 0x97, 0x5d, 0xd5, 0xed, 0x7b, 0x6f, 0xab, 0xaa, 0xeb, 0xfe, 0xee, 0xef, 0xde, 0x12, - 0x3c, 0x4e, 0xb0, 0xa9, 0x63, 0x67, 0x6c, 0x98, 0x64, 0x4f, 0xeb, 0xf5, 0x8d, 0x3d, 0x32, 0xb5, - 0xb1, 0xbb, 0x6b, 0x3b, 0x16, 0xb1, 0x50, 0x25, 0x78, 0xb8, 0x4b, 0x1f, 0xd6, 0x9f, 0x08, 0x69, - 0xf7, 0x9d, 0xa9, 0x4d, 0xac, 0x3d, 0xdb, 0xb1, 0xac, 0x73, 0xae, 0x5f, 0xbf, 0x11, 0x7a, 0xcc, - 0xfc, 0x84, 0xbd, 0x45, 0x9e, 0x0a, 0xe3, 0xfb, 0x78, 0xea, 0x3d, 0x7d, 0x62, 0xce, 0xd6, 0xd6, - 0x1c, 0x6d, 0xec, 0x3d, 0xde, 0x19, 0x58, 0xd6, 0x60, 0x84, 0xf7, 0xd8, 0xac, 0x37, 0x39, 0xdf, - 0x23, 0xc6, 0x18, 0xbb, 0x44, 0x1b, 0xdb, 0x42, 0x61, 0x6b, 0x60, 0x0d, 0x2c, 0x36, 0xdc, 0xa3, - 0x23, 0x2e, 0x95, 0x7f, 0x5b, 0x80, 0xbc, 0x82, 0x3f, 0x99, 0x60, 0x97, 0xa0, 0x7d, 0xc8, 0xe0, - 0xfe, 0xd0, 0xaa, 0x25, 0x6f, 0x26, 0x9f, 0x2d, 0xee, 0xdf, 0xd8, 0x9d, 0x59, 0xdc, 0xae, 0xd0, - 0x6b, 0xf5, 0x87, 0x56, 0x3b, 0xa1, 0x30, 0x5d, 0xf4, 0x0a, 0x64, 0xcf, 0x47, 0x13, 0x77, 0x58, - 0x4b, 0x31, 0xa3, 0x27, 0xe2, 0x8c, 0x6e, 0x53, 0xa5, 0x76, 0x42, 0xe1, 0xda, 0xf4, 0x55, 0x86, - 0x79, 0x6e, 0xd5, 0xd2, 0xcb, 0x5f, 0x75, 0x68, 0x9e, 0xb3, 0x57, 0x51, 0x5d, 0xd4, 0x00, 0x70, - 0x31, 0x51, 0x2d, 0x9b, 0x18, 0x96, 0x59, 0xcb, 0x30, 0xcb, 0x27, 0xe3, 0x2c, 0xcf, 0x30, 0xe9, - 0x30, 0xc5, 0x76, 0x42, 0x91, 0x5c, 0x6f, 0x42, 0x7d, 0x18, 0xa6, 0x41, 0xd4, 0xfe, 0x50, 0x33, - 0xcc, 0x5a, 0x76, 0xb9, 0x8f, 0x43, 0xd3, 0x20, 0x4d, 0xaa, 0x48, 0x7d, 0x18, 0xde, 0x84, 0x2e, - 0xf9, 0x93, 0x09, 0x76, 0xa6, 0xb5, 0xdc, 0xf2, 0x25, 0xff, 0x88, 0x2a, 0xd1, 0x25, 0x33, 0x6d, - 0xd4, 0x82, 0x62, 0x0f, 0x0f, 0x0c, 0x53, 0xed, 0x8d, 0xac, 0xfe, 0xfd, 0x5a, 0x9e, 0x19, 0xcb, - 0x71, 0xc6, 0x0d, 0xaa, 0xda, 0xa0, 0x9a, 0xed, 0x84, 0x02, 0x3d, 0x7f, 0x86, 0xde, 0x84, 0x42, - 0x7f, 0x88, 0xfb, 0xf7, 0x55, 0x72, 0x59, 0x2b, 0x30, 0x1f, 0x3b, 0x71, 0x3e, 0x9a, 0x54, 0xaf, - 0x7b, 0xd9, 0x4e, 0x28, 0xf9, 0x3e, 0x1f, 0xd2, 0xf5, 0xeb, 0x78, 0x64, 0x5c, 0x60, 0x87, 0xda, - 0x4b, 0xcb, 0xd7, 0xff, 0x0e, 0xd7, 0x64, 0x1e, 0x24, 0xdd, 0x9b, 0xa0, 0xb7, 0x40, 0xc2, 0xa6, - 0x2e, 0x96, 0x01, 0xcc, 0xc5, 0xcd, 0xd8, 0xb3, 0x62, 0xea, 0xde, 0x22, 0x0a, 0x58, 0x8c, 0xd1, - 0x6b, 0x90, 0xeb, 0x5b, 0xe3, 0xb1, 0x41, 0x6a, 0x45, 0x66, 0xbd, 0x1d, 0xbb, 0x00, 0xa6, 0xd5, - 0x4e, 0x28, 0x42, 0x1f, 0x9d, 0x40, 0x79, 0x64, 0xb8, 0x44, 0x75, 0x4d, 0xcd, 0x76, 0x87, 0x16, - 0x71, 0x6b, 0x1b, 0xcc, 0xc3, 0xd3, 0x71, 0x1e, 0x8e, 0x0d, 0x97, 0x9c, 0x79, 0xca, 0xed, 0x84, - 0x52, 0x1a, 0x85, 0x05, 0xd4, 0x9f, 0x75, 0x7e, 0x8e, 0x1d, 0xdf, 0x61, 0xad, 0xb4, 0xdc, 0x5f, - 0x87, 0x6a, 0x7b, 0xf6, 0xd4, 0x9f, 0x15, 0x16, 0xa0, 0x9f, 0xc1, 0xb5, 0x91, 0xa5, 0xe9, 0xbe, - 0x3b, 0xb5, 0x3f, 0x9c, 0x98, 0xf7, 0x6b, 0x65, 0xe6, 0xf4, 0xb9, 0xd8, 0x1f, 0x69, 0x69, 0xba, - 0xe7, 0xa2, 0x49, 0x0d, 0xda, 0x09, 0x65, 0x73, 0x34, 0x2b, 0x44, 0xf7, 0x60, 0x4b, 0xb3, 0xed, - 0xd1, 0x74, 0xd6, 0x7b, 0x85, 0x79, 0xbf, 0x15, 0xe7, 0xfd, 0x80, 0xda, 0xcc, 0xba, 0x47, 0xda, - 0x9c, 0xb4, 0x91, 0x87, 0xec, 0x85, 0x36, 0x9a, 0x60, 0xf9, 0xff, 0xa0, 0x18, 0x0a, 0x75, 0x54, - 0x83, 0xfc, 0x18, 0xbb, 0xae, 0x36, 0xc0, 0x0c, 0x19, 0x24, 0xc5, 0x9b, 0xca, 0x65, 0xd8, 0x08, - 0x87, 0xb7, 0x3c, 0xf6, 0x0d, 0x69, 0xe0, 0x52, 0xc3, 0x0b, 0xec, 0xb8, 0x34, 0x5a, 0x85, 0xa1, - 0x98, 0xa2, 0xa7, 0xa0, 0xc4, 0x8e, 0x8f, 0xea, 0x3d, 0xa7, 0xe8, 0x91, 0x51, 0x36, 0x98, 0xf0, - 0xae, 0x50, 0xda, 0x81, 0xa2, 0xbd, 0x6f, 0xfb, 0x2a, 0x69, 0xa6, 0x02, 0xf6, 0xbe, 0x2d, 0x14, - 0xe4, 0xef, 0x43, 0x75, 0x36, 0xda, 0x51, 0x15, 0xd2, 0xf7, 0xf1, 0x54, 0xbc, 0x8f, 0x0e, 0xd1, - 0x96, 0x58, 0x16, 0x7b, 0x87, 0xa4, 0x88, 0x35, 0xfe, 0x29, 0xe5, 0x1b, 0xfb, 0x61, 0x8e, 0x5e, - 0x83, 0x0c, 0x45, 0x4d, 0x01, 0x80, 0xf5, 0x5d, 0x0e, 0xa9, 0xbb, 0x1e, 0xa4, 0xee, 0x76, 0x3d, - 0x48, 0x6d, 0x14, 0xbe, 0xfa, 0x66, 0x27, 0xf1, 0xc5, 0x5f, 0x77, 0x92, 0x0a, 0xb3, 0x40, 0x8f, - 0xd1, 0xa8, 0xd4, 0x0c, 0x53, 0x35, 0x74, 0xf1, 0x9e, 0x3c, 0x9b, 0x1f, 0xea, 0xe8, 0x08, 0xaa, - 0x7d, 0xcb, 0x74, 0xb1, 0xe9, 0x4e, 0x5c, 0x95, 0x43, 0xb6, 0x80, 0xbd, 0xf9, 0xa8, 0x69, 0x7a, - 0x8a, 0xa7, 0x4c, 0x4f, 0xa9, 0xf4, 0xa3, 0x02, 0x74, 0x1b, 0xe0, 0x42, 0x1b, 0x19, 0xba, 0x46, - 0x2c, 0xc7, 0xad, 0x65, 0x6e, 0xa6, 0x17, 0xba, 0xb9, 0xeb, 0xa9, 0xdc, 0xb1, 0x75, 0x8d, 0xe0, - 0x46, 0x86, 0xfe, 0x5a, 0x25, 0x64, 0x89, 0x9e, 0x81, 0x8a, 0x66, 0xdb, 0xaa, 0x4b, 0x34, 0x82, - 0xd5, 0xde, 0x94, 0x60, 0x97, 0x81, 0xe1, 0x86, 0x52, 0xd2, 0x6c, 0xfb, 0x8c, 0x4a, 0x1b, 0x54, - 0x88, 0x9e, 0x86, 0x32, 0x05, 0x3e, 0x43, 0x1b, 0xa9, 0x43, 0x6c, 0x0c, 0x86, 0x84, 0x81, 0x5e, - 0x5a, 0x29, 0x09, 0x69, 0x9b, 0x09, 0x65, 0xdd, 0x3f, 0x08, 0x0c, 0xf4, 0x10, 0x82, 0x8c, 0xae, - 0x11, 0x8d, 0x6d, 0xe4, 0x86, 0xc2, 0xc6, 0x54, 0x66, 0x6b, 0x64, 0x28, 0xb6, 0x87, 0x8d, 0xd1, - 0x75, 0xc8, 0x09, 0xb7, 0x69, 0xe6, 0x56, 0xcc, 0xe8, 0x37, 0xb3, 0x1d, 0xeb, 0x02, 0x33, 0x94, - 0x2f, 0x28, 0x7c, 0x22, 0xff, 0x2a, 0x05, 0x9b, 0x73, 0xf0, 0x48, 0xfd, 0x0e, 0x35, 0x77, 0xe8, - 0xbd, 0x8b, 0x8e, 0xd1, 0xab, 0xd4, 0xaf, 0xa6, 0x63, 0x47, 0xa4, 0xa5, 0x5a, 0x78, 0x8b, 0x78, - 0xca, 0x6d, 0xb3, 0xe7, 0x62, 0x6b, 0x84, 0x36, 0xea, 0x40, 0x75, 0xa4, 0xb9, 0x44, 0xe5, 0x70, - 0xa3, 0x86, 0x52, 0xd4, 0x3c, 0xc8, 0x1e, 0x6b, 0x1e, 0x40, 0xd1, 0xc3, 0x2e, 0x1c, 0x95, 0x47, - 0x11, 0x29, 0x52, 0x60, 0xab, 0x37, 0xfd, 0x4c, 0x33, 0x89, 0x61, 0x62, 0x75, 0xee, 0xcb, 0x3d, - 0x36, 0xe7, 0xb4, 0x75, 0x61, 0xe8, 0xd8, 0xec, 0x7b, 0x9f, 0xec, 0x9a, 0x6f, 0xec, 0x7f, 0x52, - 0x57, 0x56, 0xa0, 0x1c, 0x05, 0x78, 0x54, 0x86, 0x14, 0xb9, 0x14, 0x1b, 0x90, 0x22, 0x97, 0xe8, - 0xff, 0x21, 0x43, 0x17, 0xc9, 0x16, 0x5f, 0x5e, 0x90, 0x5d, 0x85, 0x5d, 0x77, 0x6a, 0x63, 0x85, - 0x69, 0xca, 0xb2, 0x1f, 0x0d, 0x3e, 0xe8, 0xcf, 0x7a, 0x95, 0x9f, 0x83, 0xca, 0x0c, 0xaa, 0x87, - 0xbe, 0x5f, 0x32, 0xfc, 0xfd, 0xe4, 0x0a, 0x94, 0x22, 0x10, 0x2e, 0x5f, 0x87, 0xad, 0x45, 0x88, - 0x2c, 0x0f, 0x7d, 0x79, 0x04, 0x59, 0xd1, 0x2b, 0x50, 0xf0, 0x21, 0x99, 0x47, 0xe3, 0xfc, 0x5e, - 0x79, 0xca, 0x8a, 0xaf, 0x4a, 0xc3, 0x90, 0x1e, 0x6b, 0x76, 0x1e, 0x52, 0xec, 0x87, 0xe7, 0x35, - 0xdb, 0x6e, 0x6b, 0xee, 0x50, 0xfe, 0x08, 0x6a, 0x71, 0x70, 0x3b, 0xb3, 0x8c, 0x8c, 0x7f, 0x0c, - 0xaf, 0x43, 0xee, 0xdc, 0x72, 0xc6, 0x1a, 0x61, 0xce, 0x4a, 0x8a, 0x98, 0xd1, 0xe3, 0xc9, 0xa1, - 0x37, 0xcd, 0xc4, 0x7c, 0x22, 0xab, 0xf0, 0x58, 0x2c, 0xe4, 0x52, 0x13, 0xc3, 0xd4, 0x31, 0xdf, - 0xcf, 0x92, 0xc2, 0x27, 0x81, 0x23, 0xfe, 0x63, 0xf9, 0x84, 0xbe, 0xd6, 0x65, 0x6b, 0x65, 0xfe, - 0x25, 0x45, 0xcc, 0xe4, 0xbf, 0x17, 0xa0, 0xa0, 0x60, 0xd7, 0xa6, 0x98, 0x80, 0x1a, 0x20, 0xe1, - 0xcb, 0x3e, 0xe6, 0x64, 0x28, 0x19, 0x4b, 0x26, 0xb8, 0x76, 0xcb, 0xd3, 0xa4, 0x99, 0xdc, 0x37, - 0x43, 0x2f, 0x0b, 0xc2, 0x17, 0xcf, 0xdd, 0x84, 0x79, 0x98, 0xf1, 0xbd, 0xea, 0x31, 0xbe, 0x74, - 0x6c, 0xf2, 0xe6, 0x56, 0x33, 0x94, 0xef, 0x65, 0x41, 0xf9, 0x32, 0x2b, 0x5e, 0x16, 0xe1, 0x7c, - 0xcd, 0x08, 0xe7, 0xcb, 0xae, 0x58, 0x66, 0x0c, 0xe9, 0x6b, 0x46, 0x48, 0x5f, 0x6e, 0x85, 0x93, - 0x18, 0xd6, 0xf7, 0xaa, 0xc7, 0xfa, 0xf2, 0x2b, 0x96, 0x3d, 0x43, 0xfb, 0x6e, 0x47, 0x69, 0x1f, - 0xa7, 0x6c, 0x4f, 0xc5, 0x5a, 0xc7, 0xf2, 0xbe, 0x1f, 0x84, 0x78, 0x9f, 0x14, 0x4b, 0xba, 0xb8, - 0x93, 0x05, 0xc4, 0xaf, 0x19, 0x21, 0x7e, 0xb0, 0x62, 0x0f, 0x62, 0x98, 0xdf, 0xdb, 0x61, 0xe6, - 0x57, 0x8c, 0x25, 0x8f, 0xe2, 0xd0, 0x2c, 0xa2, 0x7e, 0xaf, 0xfb, 0xd4, 0x6f, 0x23, 0x96, 0xbb, - 0x8a, 0x35, 0xcc, 0x72, 0xbf, 0xce, 0x1c, 0xf7, 0xe3, 0x5c, 0xed, 0x99, 0x58, 0x17, 0x2b, 0xc8, - 0x5f, 0x67, 0x8e, 0xfc, 0x95, 0x57, 0x38, 0x5c, 0xc1, 0xfe, 0x7e, 0xbe, 0x98, 0xfd, 0xc5, 0xf3, - 0x33, 0xf1, 0x33, 0xd7, 0xa3, 0x7f, 0x6a, 0x0c, 0xfd, 0xab, 0x32, 0xf7, 0xcf, 0xc7, 0xba, 0xbf, - 0x3a, 0xff, 0x7b, 0x8e, 0xa6, 0xd9, 0x19, 0xe0, 0xa0, 0x50, 0x85, 0x1d, 0xc7, 0x72, 0x04, 0xb5, - 0xe2, 0x13, 0xf9, 0x59, 0x9a, 0xf8, 0x03, 0x90, 0x58, 0xc2, 0x15, 0x59, 0x4a, 0x08, 0x01, 0x83, - 0xfc, 0xfb, 0x64, 0x60, 0xcb, 0x72, 0x65, 0x98, 0x34, 0x48, 0x82, 0x34, 0x84, 0x28, 0x64, 0x2a, - 0x4a, 0x21, 0x77, 0xa0, 0x48, 0xa1, 0x7e, 0x86, 0x1d, 0x6a, 0xb6, 0xc7, 0x0e, 0xd1, 0x2d, 0xd8, - 0x64, 0xb9, 0x9c, 0x13, 0x4d, 0x81, 0xef, 0x19, 0x96, 0xa6, 0x2a, 0xf4, 0x01, 0x3f, 0x9c, 0x1c, - 0xe8, 0x5f, 0x84, 0x6b, 0x21, 0x5d, 0x3f, 0x85, 0x70, 0x4a, 0x54, 0xf5, 0xb5, 0x0f, 0x44, 0x2e, - 0x79, 0x3f, 0xd8, 0xa0, 0x80, 0x79, 0x22, 0xc8, 0xf4, 0x2d, 0x1d, 0x0b, 0x80, 0x67, 0x63, 0xca, - 0x46, 0x47, 0xd6, 0x40, 0xc0, 0x38, 0x1d, 0x52, 0x2d, 0x1f, 0x05, 0x25, 0x0e, 0x72, 0xf2, 0x1f, - 0x93, 0x81, 0xbf, 0x80, 0x8c, 0x2e, 0xe2, 0x8d, 0xc9, 0xff, 0x0e, 0x6f, 0x4c, 0x7d, 0x6b, 0xde, - 0x18, 0x4e, 0xb0, 0xe9, 0x68, 0x82, 0xfd, 0x67, 0x32, 0xf8, 0xc2, 0x3e, 0x0b, 0xfc, 0x76, 0x3b, - 0x12, 0x64, 0xcb, 0x2c, 0xfb, 0x5e, 0x22, 0x5b, 0x0a, 0x6e, 0x9f, 0x63, 0xef, 0x8d, 0x72, 0xfb, - 0x3c, 0xcf, 0x9f, 0x6c, 0x82, 0x5e, 0x03, 0x89, 0x35, 0x5d, 0x54, 0xcb, 0x76, 0x05, 0xe0, 0x3e, - 0x1e, 0x5e, 0x2b, 0xef, 0xad, 0xec, 0x9e, 0x52, 0x9d, 0x8e, 0xed, 0x2a, 0x05, 0x5b, 0x8c, 0x42, - 0x44, 0x40, 0x8a, 0xf0, 0xd1, 0x1b, 0x20, 0xd1, 0x5f, 0xef, 0xda, 0x5a, 0x1f, 0x33, 0xf0, 0x94, - 0x94, 0x40, 0x20, 0xdf, 0x03, 0x34, 0x0f, 0xdf, 0xa8, 0x0d, 0x39, 0x7c, 0x81, 0x4d, 0x42, 0xbf, - 0x1a, 0xdd, 0xee, 0xeb, 0x0b, 0xc8, 0x1e, 0x36, 0x49, 0xa3, 0x46, 0x37, 0xf9, 0x1f, 0xdf, 0xec, - 0x54, 0xb9, 0xf6, 0x0b, 0xd6, 0xd8, 0x20, 0x78, 0x6c, 0x93, 0xa9, 0x22, 0xec, 0xe5, 0xbf, 0xa4, - 0x28, 0xf3, 0x8a, 0x40, 0xfb, 0xc2, 0xbd, 0xf5, 0x02, 0x28, 0x15, 0x62, 0xdd, 0xeb, 0xed, 0xf7, - 0x36, 0xc0, 0x40, 0x73, 0xd5, 0x4f, 0x35, 0x93, 0x60, 0x5d, 0x6c, 0x7a, 0x48, 0x82, 0xea, 0x50, - 0xa0, 0xb3, 0x89, 0x8b, 0x75, 0x51, 0x00, 0xf8, 0xf3, 0xd0, 0x3a, 0xf3, 0xdf, 0x6d, 0x9d, 0xd1, - 0x5d, 0x2e, 0xcc, 0xec, 0x72, 0x88, 0x15, 0x49, 0x61, 0x56, 0x44, 0x7f, 0x9b, 0xed, 0x18, 0x96, - 0x63, 0x90, 0x29, 0xfb, 0x34, 0x69, 0xc5, 0x9f, 0xd3, 0x3a, 0x73, 0x8c, 0xc7, 0xb6, 0x65, 0x8d, - 0x54, 0x0e, 0x5e, 0x45, 0x66, 0xba, 0x21, 0x84, 0x2d, 0x86, 0x61, 0xbf, 0x4e, 0x05, 0xe1, 0x17, - 0xb0, 0xdf, 0xff, 0xb9, 0x0d, 0x96, 0x7f, 0xc3, 0x4a, 0xe2, 0x68, 0xf2, 0x46, 0x67, 0xb0, 0xe9, - 0x87, 0xbf, 0x3a, 0x61, 0xb0, 0xe0, 0x1d, 0xe8, 0x75, 0xf1, 0xa3, 0x7a, 0x11, 0x15, 0xbb, 0xe8, - 0xc7, 0xf0, 0xe8, 0x0c, 0xb4, 0xf9, 0xae, 0x53, 0x6b, 0x22, 0xdc, 0x23, 0x51, 0x84, 0xf3, 0x3c, - 0x07, 0x7b, 0x95, 0xfe, 0x8e, 0x41, 0x77, 0x48, 0xab, 0xac, 0x30, 0x15, 0x59, 0xf8, 0xf5, 0x9f, - 0x82, 0x92, 0x83, 0x09, 0x2d, 0xfc, 0x23, 0x75, 0xec, 0x06, 0x17, 0x8a, 0xea, 0xf8, 0x14, 0x1e, - 0x59, 0x48, 0x49, 0xd0, 0xf7, 0x40, 0x0a, 0xd8, 0x4c, 0x32, 0xa6, 0x24, 0xf4, 0xcb, 0x9c, 0x40, - 0x57, 0xfe, 0x43, 0x32, 0x70, 0x19, 0x2d, 0x9c, 0x5a, 0x90, 0x73, 0xb0, 0x3b, 0x19, 0xf1, 0x52, - 0xa6, 0xbc, 0xff, 0xe2, 0x7a, 0x64, 0x86, 0x4a, 0x27, 0x23, 0xa2, 0x08, 0x63, 0xf9, 0x1e, 0xe4, - 0xb8, 0x04, 0x15, 0x21, 0x7f, 0xe7, 0xe4, 0xe8, 0xa4, 0xf3, 0xc1, 0x49, 0x35, 0x81, 0x00, 0x72, - 0x07, 0xcd, 0x66, 0xeb, 0xb4, 0x5b, 0x4d, 0x22, 0x09, 0xb2, 0x07, 0x8d, 0x8e, 0xd2, 0xad, 0xa6, - 0xa8, 0x58, 0x69, 0xbd, 0xd7, 0x6a, 0x76, 0xab, 0x69, 0xb4, 0x09, 0x25, 0x3e, 0x56, 0x6f, 0x77, - 0x94, 0xf7, 0x0f, 0xba, 0xd5, 0x4c, 0x48, 0x74, 0xd6, 0x3a, 0x79, 0xa7, 0xa5, 0x54, 0xb3, 0xf2, - 0x4b, 0xb4, 0x56, 0x8a, 0xa1, 0x3f, 0x41, 0x55, 0x94, 0x0c, 0x55, 0x45, 0xf2, 0xef, 0x52, 0x50, - 0x8f, 0xe7, 0x34, 0xe8, 0xbd, 0x99, 0x85, 0xef, 0x5f, 0x81, 0x10, 0xcd, 0xac, 0x1e, 0x3d, 0x0d, - 0x65, 0x07, 0x9f, 0x63, 0xd2, 0x1f, 0x72, 0x8e, 0xc5, 0x33, 0x66, 0x49, 0x29, 0x09, 0x29, 0x33, - 0x72, 0xb9, 0xda, 0xc7, 0xb8, 0x4f, 0x54, 0x0e, 0x45, 0xfc, 0xd0, 0x49, 0x54, 0x8d, 0x4a, 0xcf, - 0xb8, 0x50, 0xfe, 0xe8, 0x4a, 0x7b, 0x29, 0x41, 0x56, 0x69, 0x75, 0x95, 0x9f, 0x54, 0xd3, 0x08, - 0x41, 0x99, 0x0d, 0xd5, 0xb3, 0x93, 0x83, 0xd3, 0xb3, 0x76, 0x87, 0xee, 0xe5, 0x35, 0xa8, 0x78, - 0x7b, 0xe9, 0x09, 0xb3, 0xf2, 0xbf, 0x93, 0x50, 0x99, 0x09, 0x10, 0xb4, 0x0f, 0x59, 0xce, 0xd3, - 0xe3, 0xba, 0xf9, 0x2c, 0xbe, 0x45, 0x34, 0x71, 0x55, 0xf4, 0x26, 0x14, 0xb0, 0x68, 0x40, 0x2c, - 0x0a, 0x44, 0xde, 0x38, 0xf1, 0x5a, 0x14, 0xc2, 0xd4, 0xb7, 0x40, 0x6f, 0x81, 0xe4, 0x47, 0xba, - 0x28, 0x0e, 0x9f, 0x9c, 0x37, 0xf7, 0x31, 0x42, 0xd8, 0x07, 0x36, 0xe8, 0xf5, 0x80, 0xec, 0x65, - 0xe6, 0xab, 0x03, 0x61, 0xce, 0x15, 0x84, 0xb1, 0xa7, 0x2f, 0x37, 0xa1, 0x18, 0x5a, 0x0f, 0x7a, - 0x1c, 0xa4, 0xb1, 0x76, 0x29, 0x1a, 0x5b, 0xbc, 0x35, 0x51, 0x18, 0x6b, 0x97, 0xbc, 0xa7, 0xf5, - 0x28, 0xe4, 0xe9, 0xc3, 0x81, 0xc6, 0xd1, 0x26, 0xad, 0xe4, 0xc6, 0xda, 0xe5, 0xbb, 0x9a, 0x2b, - 0x7f, 0x08, 0xe5, 0x68, 0x53, 0x87, 0x9e, 0x44, 0xc7, 0x9a, 0x98, 0x3a, 0xf3, 0x91, 0x55, 0xf8, - 0x04, 0xbd, 0x02, 0xd9, 0x0b, 0x8b, 0x83, 0xd5, 0xe2, 0x90, 0xbd, 0x6b, 0x11, 0x1c, 0x6a, 0x0a, - 0x71, 0x6d, 0xf9, 0x33, 0xc8, 0x32, 0xf0, 0xa1, 0x40, 0xc2, 0xda, 0x33, 0x82, 0xe8, 0xd2, 0x31, - 0xfa, 0x10, 0x40, 0x23, 0xc4, 0x31, 0x7a, 0x93, 0xc0, 0xf1, 0xce, 0x62, 0xf0, 0x3a, 0xf0, 0xf4, - 0x1a, 0x37, 0x04, 0x8a, 0x6d, 0x05, 0xa6, 0x21, 0x24, 0x0b, 0x39, 0x94, 0x4f, 0xa0, 0x1c, 0xb5, - 0x0d, 0x37, 0x4a, 0x37, 0x16, 0x34, 0x4a, 0x7d, 0x32, 0xe5, 0x53, 0xb1, 0x34, 0x6f, 0xc5, 0xb1, - 0x89, 0xfc, 0x79, 0x12, 0x0a, 0xdd, 0x4b, 0x71, 0xac, 0x63, 0xba, 0x40, 0x81, 0x69, 0x2a, 0xdc, - 0xf3, 0xe0, 0x6d, 0xa5, 0xb4, 0xdf, 0xac, 0x7a, 0xdb, 0x0f, 0xdc, 0xcc, 0xba, 0x55, 0xa9, 0xd7, - 0xb5, 0x13, 0x60, 0xf5, 0x06, 0x48, 0xfe, 0xa9, 0xa2, 0x15, 0x83, 0xa6, 0xeb, 0x0e, 0x76, 0x5d, - 0xb1, 0x36, 0x6f, 0xca, 0x9a, 0x8a, 0xd6, 0xa7, 0xa2, 0xab, 0x92, 0x56, 0xf8, 0x44, 0xd6, 0xa1, - 0x32, 0x93, 0xb6, 0xd0, 0x1b, 0x90, 0xb7, 0x27, 0x3d, 0xd5, 0xdb, 0x9e, 0x99, 0xe0, 0xf1, 0xd8, - 0xe3, 0xa4, 0x37, 0x32, 0xfa, 0x47, 0x78, 0xea, 0xfd, 0x18, 0x7b, 0xd2, 0x3b, 0xe2, 0xbb, 0xc8, - 0xdf, 0x92, 0x0a, 0xbf, 0xe5, 0x02, 0x0a, 0xde, 0xa1, 0x40, 0x3f, 0x0c, 0xc7, 0x89, 0xd7, 0x6a, - 0x8e, 0x4d, 0xa5, 0xc2, 0x7d, 0x28, 0x4c, 0x6e, 0xc1, 0xa6, 0x6b, 0x0c, 0x4c, 0xac, 0xab, 0x41, - 0xcd, 0xc2, 0xde, 0x56, 0x50, 0x2a, 0xfc, 0xc1, 0xb1, 0x57, 0xb0, 0xc8, 0xff, 0x4a, 0x42, 0xc1, - 0x0b, 0x58, 0xf4, 0x52, 0xe8, 0xdc, 0x95, 0x17, 0x74, 0x60, 0x3c, 0xc5, 0xa0, 0x2f, 0x18, 0xfd, - 0xad, 0xa9, 0xab, 0xff, 0xd6, 0xb8, 0x06, 0xaf, 0xd7, 0x69, 0xcf, 0x5c, 0xb9, 0xd3, 0xfe, 0x02, - 0x20, 0x62, 0x11, 0x6d, 0xa4, 0x5e, 0x58, 0xc4, 0x30, 0x07, 0x2a, 0xdf, 0x6c, 0xce, 0xa8, 0xaa, - 0xec, 0xc9, 0x5d, 0xf6, 0xe0, 0x94, 0xed, 0xfb, 0x2f, 0x92, 0x50, 0xf0, 0x73, 0xe3, 0x55, 0xdb, - 0x7c, 0xd7, 0x21, 0x27, 0xe0, 0x9f, 0xf7, 0xf9, 0xc4, 0xcc, 0xef, 0x38, 0x67, 0x42, 0x1d, 0xe7, - 0x3a, 0x14, 0xc6, 0x98, 0x68, 0x8c, 0x20, 0xf0, 0xb2, 0xd1, 0x9f, 0xdf, 0x7a, 0x1d, 0x8a, 0xa1, - 0x8e, 0x2b, 0x8d, 0xbc, 0x93, 0xd6, 0x07, 0xd5, 0x44, 0x3d, 0xff, 0xf9, 0x97, 0x37, 0xd3, 0x27, - 0xf8, 0x53, 0x7a, 0x66, 0x95, 0x56, 0xb3, 0xdd, 0x6a, 0x1e, 0x55, 0x93, 0xf5, 0xe2, 0xe7, 0x5f, - 0xde, 0xcc, 0x2b, 0x98, 0x35, 0x6e, 0x6e, 0xb5, 0x61, 0x23, 0xfc, 0x55, 0xa2, 0x19, 0x04, 0x41, - 0xf9, 0x9d, 0x3b, 0xa7, 0xc7, 0x87, 0xcd, 0x83, 0x6e, 0x4b, 0xbd, 0xdb, 0xe9, 0xb6, 0xaa, 0x49, - 0xf4, 0x28, 0x5c, 0x3b, 0x3e, 0x7c, 0xb7, 0xdd, 0x55, 0x9b, 0xc7, 0x87, 0xad, 0x93, 0xae, 0x7a, - 0xd0, 0xed, 0x1e, 0x34, 0x8f, 0xaa, 0xa9, 0xfd, 0x5f, 0x02, 0x54, 0x0e, 0x1a, 0xcd, 0x43, 0x9a, - 0xfd, 0x8c, 0xbe, 0x26, 0x1a, 0x63, 0x19, 0x56, 0xb5, 0x2f, 0xbd, 0xea, 0xad, 0x2f, 0xef, 0x0b, - 0xa2, 0xdb, 0x90, 0x65, 0x05, 0x3d, 0x5a, 0x7e, 0xf7, 0x5b, 0x5f, 0xd1, 0x28, 0xa4, 0x3f, 0x86, - 0x85, 0xc7, 0xd2, 0xcb, 0xe0, 0xfa, 0xf2, 0xbe, 0x21, 0x52, 0x40, 0x0a, 0x2a, 0xf2, 0xd5, 0x97, - 0xc3, 0xf5, 0x35, 0x7a, 0x89, 0xd4, 0x67, 0x50, 0x16, 0xac, 0xbe, 0x2c, 0xad, 0xaf, 0x01, 0x60, - 0xe8, 0x18, 0xf2, 0x5e, 0x25, 0xb7, 0xea, 0xfa, 0xb6, 0xbe, 0xb2, 0xcf, 0x47, 0x3f, 0x01, 0xaf, - 0xb8, 0x97, 0xdf, 0x45, 0xd7, 0x57, 0x34, 0x2d, 0xd1, 0x21, 0xe4, 0x04, 0xd7, 0x5d, 0x71, 0x25, - 0x5b, 0x5f, 0xd5, 0xb7, 0xa3, 0x9b, 0x16, 0xb4, 0x32, 0x56, 0xdf, 0xb0, 0xd7, 0xd7, 0xe8, 0xc7, - 0xa2, 0x3b, 0x00, 0xa1, 0xfa, 0x7a, 0x8d, 0xab, 0xf3, 0xfa, 0x3a, 0x7d, 0x56, 0xd4, 0x81, 0x82, - 0x5f, 0xee, 0xac, 0xbc, 0xc8, 0xae, 0xaf, 0x6e, 0x78, 0xa2, 0x7b, 0x50, 0x8a, 0xf2, 0xfc, 0xf5, - 0xae, 0xa7, 0xeb, 0x6b, 0x76, 0x32, 0xa9, 0xff, 0x28, 0xe9, 0x5f, 0xef, 0xba, 0xba, 0xbe, 0x66, - 0x63, 0x13, 0x7d, 0x0c, 0x9b, 0xf3, 0xa4, 0x7c, 0xfd, 0xdb, 0xeb, 0xfa, 0x15, 0x5a, 0x9d, 0x68, - 0x0c, 0x68, 0x01, 0x99, 0xbf, 0xc2, 0x65, 0x76, 0xfd, 0x2a, 0x9d, 0xcf, 0x46, 0xeb, 0xab, 0x07, - 0xdb, 0xc9, 0xaf, 0x1f, 0x6c, 0x27, 0xff, 0xf6, 0x60, 0x3b, 0xf9, 0xc5, 0xc3, 0xed, 0xc4, 0xd7, - 0x0f, 0xb7, 0x13, 0x7f, 0x7e, 0xb8, 0x9d, 0xf8, 0xe9, 0xf3, 0x03, 0x83, 0x0c, 0x27, 0xbd, 0xdd, - 0xbe, 0x35, 0xde, 0x0b, 0xff, 0xd3, 0x66, 0xd1, 0xbf, 0x7f, 0x7a, 0x39, 0x96, 0xa8, 0x5e, 0xfe, - 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4e, 0x2d, 0x07, 0xd8, 0x1d, 0x24, 0x00, 0x00, + // 3004 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x3b, 0x73, 0x23, 0xc7, + 0xf1, 0xc7, 0xfb, 0xd1, 0x78, 0x2d, 0xe7, 0xa8, 0x13, 0x0e, 0x3a, 0x91, 0xa7, 0xbd, 0x92, 0x74, + 0x77, 0x92, 0x48, 0xfd, 0xa9, 0xff, 0xe9, 0x51, 0xb2, 0x6c, 0x11, 0x38, 0x9c, 0x41, 0x91, 0x22, + 0xe9, 0x25, 0x78, 0x2a, 0xf9, 0x71, 0xab, 0x05, 0x76, 0x48, 0xac, 0x0e, 0xd8, 0x5d, 0xed, 0x0e, + 0x28, 0x50, 0xa1, 0x55, 0xae, 0x72, 0xa9, 0x1c, 0x28, 0x54, 0xa2, 0xc0, 0x81, 0xbf, 0x83, 0x23, + 0x47, 0x0e, 0x14, 0x38, 0x50, 0xe0, 0xc0, 0x81, 0x4b, 0x76, 0x49, 0x99, 0xbf, 0x80, 0x03, 0x07, + 0x76, 0xcd, 0x63, 0x5f, 0x00, 0x96, 0x00, 0x25, 0x97, 0xab, 0x5c, 0xce, 0x66, 0x7a, 0xbb, 0x7b, + 0x66, 0x7a, 0x66, 0xba, 0xfb, 0xd7, 0x3b, 0xf0, 0x04, 0xc1, 0xa6, 0x8e, 0x9d, 0x91, 0x61, 0x92, + 0x4d, 0xad, 0xd7, 0x37, 0x36, 0xc9, 0xb9, 0x8d, 0xdd, 0x0d, 0xdb, 0xb1, 0x88, 0x85, 0x6a, 0xc1, + 0xc7, 0x0d, 0xfa, 0xb1, 0xf1, 0x64, 0x88, 0xbb, 0xef, 0x9c, 0xdb, 0xc4, 0xda, 0xb4, 0x1d, 0xcb, + 0x3a, 0xe1, 0xfc, 0x8d, 0xeb, 0xa1, 0xcf, 0x4c, 0x4f, 0x58, 0x5b, 0xe4, 0xab, 0x10, 0x7e, 0x84, + 0xcf, 0xbd, 0xaf, 0x4f, 0xce, 0xc8, 0xda, 0x9a, 0xa3, 0x8d, 0xbc, 0xcf, 0xeb, 0xa7, 0x96, 0x75, + 0x3a, 0xc4, 0x9b, 0xac, 0xd7, 0x1b, 0x9f, 0x6c, 0x12, 0x63, 0x84, 0x5d, 0xa2, 0x8d, 0x6c, 0xc1, + 0xb0, 0x7a, 0x6a, 0x9d, 0x5a, 0xac, 0xb9, 0x49, 0x5b, 0x9c, 0x2a, 0xff, 0xb3, 0x00, 0x79, 0x05, + 0x7f, 0x30, 0xc6, 0x2e, 0x41, 0x5b, 0x90, 0xc1, 0xfd, 0x81, 0x55, 0x4f, 0xde, 0x48, 0xde, 0x2a, + 0x6d, 0x5d, 0xdf, 0x98, 0x5a, 0xdc, 0x86, 0xe0, 0x6b, 0xf7, 0x07, 0x56, 0x27, 0xa1, 0x30, 0x5e, + 0x74, 0x17, 0xb2, 0x27, 0xc3, 0xb1, 0x3b, 0xa8, 0xa7, 0x98, 0xd0, 0x93, 0x71, 0x42, 0xf7, 0x29, + 0x53, 0x27, 0xa1, 0x70, 0x6e, 0x3a, 0x94, 0x61, 0x9e, 0x58, 0xf5, 0xf4, 0xc5, 0x43, 0xed, 0x98, + 0x27, 0x6c, 0x28, 0xca, 0x8b, 0x9a, 0x00, 0x86, 0x69, 0x10, 0xb5, 0x3f, 0xd0, 0x0c, 0xb3, 0x9e, + 0x65, 0x92, 0x4f, 0xc5, 0x4b, 0x1a, 0xa4, 0x45, 0x19, 0x3b, 0x09, 0xa5, 0x68, 0x78, 0x1d, 0x3a, + 0xdd, 0x0f, 0xc6, 0xd8, 0x39, 0xaf, 0xe7, 0x2e, 0x9e, 0xee, 0x8f, 0x28, 0x13, 0x9d, 0x2e, 0xe3, + 0x46, 0x6d, 0x28, 0xf5, 0xf0, 0xa9, 0x61, 0xaa, 0xbd, 0xa1, 0xd5, 0x7f, 0x54, 0xcf, 0x33, 0x61, + 0x39, 0x4e, 0xb8, 0x49, 0x59, 0x9b, 0x94, 0xb3, 0x93, 0x50, 0xa0, 0xe7, 0xf7, 0xd0, 0xf7, 0xa0, + 0xd0, 0x1f, 0xe0, 0xfe, 0x23, 0x95, 0x4c, 0xea, 0x05, 0xa6, 0x63, 0x3d, 0x4e, 0x47, 0x8b, 0xf2, + 0x75, 0x27, 0x9d, 0x84, 0x92, 0xef, 0xf3, 0x26, 0x5d, 0xbf, 0x8e, 0x87, 0xc6, 0x19, 0x76, 0xa8, + 0x7c, 0xf1, 0xe2, 0xf5, 0xdf, 0xe3, 0x9c, 0x4c, 0x43, 0x51, 0xf7, 0x3a, 0xe8, 0x07, 0x50, 0xc4, + 0xa6, 0x2e, 0x96, 0x01, 0x4c, 0xc5, 0x8d, 0xd8, 0x7d, 0x36, 0x75, 0x6f, 0x11, 0x05, 0x2c, 0xda, + 0xe8, 0x55, 0xc8, 0xf5, 0xad, 0xd1, 0xc8, 0x20, 0xf5, 0x12, 0x93, 0x5e, 0x8b, 0x5d, 0x00, 0xe3, + 0xea, 0x24, 0x14, 0xc1, 0x8f, 0xf6, 0xa1, 0x3a, 0x34, 0x5c, 0xa2, 0xba, 0xa6, 0x66, 0xbb, 0x03, + 0x8b, 0xb8, 0xf5, 0x32, 0xd3, 0xf0, 0x74, 0x9c, 0x86, 0x3d, 0xc3, 0x25, 0x47, 0x1e, 0x73, 0x27, + 0xa1, 0x54, 0x86, 0x61, 0x02, 0xd5, 0x67, 0x9d, 0x9c, 0x60, 0xc7, 0x57, 0x58, 0xaf, 0x5c, 0xac, + 0xef, 0x80, 0x72, 0x7b, 0xf2, 0x54, 0x9f, 0x15, 0x26, 0xa0, 0x9f, 0xc0, 0x95, 0xa1, 0xa5, 0xe9, + 0xbe, 0x3a, 0xb5, 0x3f, 0x18, 0x9b, 0x8f, 0xea, 0x55, 0xa6, 0xf4, 0x76, 0xec, 0x24, 0x2d, 0x4d, + 0xf7, 0x54, 0xb4, 0xa8, 0x40, 0x27, 0xa1, 0xac, 0x0c, 0xa7, 0x89, 0xe8, 0x21, 0xac, 0x6a, 0xb6, + 0x3d, 0x3c, 0x9f, 0xd6, 0x5e, 0x63, 0xda, 0xef, 0xc4, 0x69, 0xdf, 0xa6, 0x32, 0xd3, 0xea, 0x91, + 0x36, 0x43, 0x45, 0x5d, 0x90, 0x6c, 0x07, 0xdb, 0x9a, 0x83, 0x55, 0xdb, 0xb1, 0x6c, 0xcb, 0xd5, + 0x86, 0x75, 0x89, 0xe9, 0x7e, 0x36, 0x4e, 0xf7, 0x21, 0xe7, 0x3f, 0x14, 0xec, 0x9d, 0x84, 0x52, + 0xb3, 0xa3, 0x24, 0xae, 0xd5, 0xea, 0x63, 0xd7, 0x0d, 0xb4, 0xae, 0x2c, 0xd2, 0xca, 0xf8, 0xa3, + 0x5a, 0x23, 0xa4, 0x66, 0x1e, 0xb2, 0x67, 0xda, 0x70, 0x8c, 0xdf, 0xca, 0x14, 0x32, 0x52, 0x56, + 0x7e, 0x16, 0x4a, 0x21, 0xc7, 0x82, 0xea, 0x90, 0x1f, 0x61, 0xd7, 0xd5, 0x4e, 0x31, 0xf3, 0x43, + 0x45, 0xc5, 0xeb, 0xca, 0x55, 0x28, 0x87, 0x9d, 0x89, 0xfc, 0x69, 0xd2, 0x97, 0xa4, 0x7e, 0x82, + 0x4a, 0x9e, 0x61, 0xc7, 0x35, 0x2c, 0xd3, 0x93, 0x14, 0x5d, 0x74, 0x13, 0x2a, 0xec, 0xc4, 0xab, + 0xde, 0x77, 0xea, 0xac, 0x32, 0x4a, 0x99, 0x11, 0x1f, 0x08, 0xa6, 0x75, 0x28, 0xd9, 0x5b, 0xb6, + 0xcf, 0x92, 0x66, 0x2c, 0x60, 0x6f, 0xd9, 0x1e, 0xc3, 0x53, 0x50, 0xa6, 0x2b, 0xf5, 0x39, 0x32, + 0x6c, 0x90, 0x12, 0xa5, 0x09, 0x16, 0xf9, 0x0f, 0x29, 0x90, 0xa6, 0x1d, 0x10, 0x7a, 0x15, 0x32, + 0xd4, 0x17, 0x0b, 0xb7, 0xda, 0xd8, 0xe0, 0x8e, 0x7a, 0xc3, 0x73, 0xd4, 0x1b, 0x5d, 0xcf, 0x51, + 0x37, 0x0b, 0x5f, 0x7c, 0xb5, 0x9e, 0xf8, 0xf4, 0x2f, 0xeb, 0x49, 0x85, 0x49, 0xa0, 0x6b, 0xd4, + 0x5f, 0x68, 0x86, 0xa9, 0x1a, 0x3a, 0x9b, 0x72, 0x91, 0x3a, 0x03, 0xcd, 0x30, 0x77, 0x74, 0xb4, + 0x07, 0x52, 0xdf, 0x32, 0x5d, 0x6c, 0xba, 0x63, 0x57, 0xe5, 0x81, 0x40, 0x38, 0xd3, 0x88, 0x4b, + 0xe0, 0xe1, 0xa5, 0xe5, 0x71, 0x1e, 0x32, 0x46, 0xa5, 0xd6, 0x8f, 0x12, 0xd0, 0x7d, 0x80, 0x33, + 0x6d, 0x68, 0xe8, 0x1a, 0xb1, 0x1c, 0xb7, 0x9e, 0xb9, 0x91, 0x9e, 0xeb, 0x17, 0x1e, 0x78, 0x2c, + 0xc7, 0xb6, 0xae, 0x11, 0xdc, 0xcc, 0xd0, 0xe9, 0x2a, 0x21, 0x49, 0xf4, 0x0c, 0xd4, 0x34, 0xdb, + 0x56, 0x5d, 0xa2, 0x11, 0xac, 0xf6, 0xce, 0x09, 0x76, 0x99, 0x9f, 0x2e, 0x2b, 0x15, 0xcd, 0xb6, + 0x8f, 0x28, 0xb5, 0x49, 0x89, 0xe8, 0x69, 0xa8, 0x52, 0x9f, 0x6c, 0x68, 0x43, 0x75, 0x80, 0x8d, + 0xd3, 0x01, 0x61, 0xfe, 0x38, 0xad, 0x54, 0x04, 0xb5, 0xc3, 0x88, 0xb2, 0xee, 0xef, 0x38, 0xf3, + 0xc7, 0x08, 0x41, 0x46, 0xd7, 0x88, 0xc6, 0x2c, 0x59, 0x56, 0x58, 0x9b, 0xd2, 0x6c, 0x8d, 0x0c, + 0x84, 0x7d, 0x58, 0x1b, 0x5d, 0x85, 0x9c, 0x50, 0x9b, 0x66, 0x6a, 0x45, 0x0f, 0xad, 0x42, 0xd6, + 0x76, 0xac, 0x33, 0xcc, 0xb6, 0xae, 0xa0, 0xf0, 0x8e, 0xfc, 0x71, 0x0a, 0x56, 0x66, 0x3c, 0x37, + 0xd5, 0x3b, 0xd0, 0xdc, 0x81, 0x37, 0x16, 0x6d, 0xa3, 0x97, 0xa9, 0x5e, 0x4d, 0xc7, 0x8e, 0x88, + 0x76, 0xf5, 0x59, 0x53, 0x77, 0xd8, 0x77, 0x61, 0x1a, 0xc1, 0x8d, 0x76, 0x41, 0x1a, 0x6a, 0x2e, + 0x51, 0xb9, 0x27, 0x54, 0x43, 0x91, 0xef, 0x89, 0x19, 0x23, 0x73, 0xbf, 0x49, 0x0f, 0xb4, 0x50, + 0x52, 0xa5, 0xa2, 0x01, 0x15, 0x1d, 0xc3, 0x6a, 0xef, 0xfc, 0x23, 0xcd, 0x24, 0x86, 0x89, 0xd5, + 0x99, 0x5d, 0x9b, 0x0d, 0xa5, 0x6f, 0x1b, 0x6e, 0x0f, 0x0f, 0xb4, 0x33, 0xc3, 0xf2, 0xa6, 0x75, + 0xc5, 0x97, 0xf7, 0x77, 0xd4, 0x95, 0x15, 0xa8, 0x46, 0x43, 0x0f, 0xaa, 0x42, 0x8a, 0x4c, 0xc4, + 0xfa, 0x53, 0x64, 0x82, 0x5e, 0x84, 0x0c, 0x5d, 0x23, 0x5b, 0x7b, 0x75, 0xce, 0x40, 0x42, 0xae, + 0x7b, 0x6e, 0x63, 0x85, 0x71, 0xca, 0xb2, 0x7f, 0x1b, 0xfc, 0x70, 0x34, 0xad, 0x55, 0xbe, 0x0d, + 0xb5, 0xa9, 0x78, 0x13, 0xda, 0xbe, 0x64, 0x78, 0xfb, 0xe4, 0x1a, 0x54, 0x22, 0xc1, 0x45, 0xbe, + 0x0a, 0xab, 0xf3, 0x62, 0x85, 0x3c, 0xf0, 0xe9, 0x11, 0x9f, 0x8f, 0xee, 0x42, 0xc1, 0x0f, 0x16, + 0xfc, 0x36, 0x5e, 0x9b, 0x59, 0x85, 0xc7, 0xac, 0xf8, 0xac, 0xf4, 0x1a, 0xd2, 0x53, 0xcd, 0x8e, + 0x43, 0x8a, 0x4d, 0x3c, 0xaf, 0xd9, 0x76, 0x47, 0x73, 0x07, 0xf2, 0x7b, 0x50, 0x8f, 0x0b, 0x04, + 0x53, 0xcb, 0xc8, 0xf8, 0xa7, 0xf0, 0x2a, 0xe4, 0x4e, 0x2c, 0x67, 0xa4, 0x11, 0xa6, 0xac, 0xa2, + 0x88, 0x1e, 0x3d, 0x9d, 0x3c, 0x28, 0xa4, 0x19, 0x99, 0x77, 0x64, 0x15, 0xae, 0xc5, 0x06, 0x03, + 0x2a, 0x62, 0x98, 0x3a, 0xe6, 0xf6, 0xac, 0x28, 0xbc, 0x13, 0x28, 0xe2, 0x93, 0xe5, 0x1d, 0x3a, + 0xac, 0xcb, 0xd6, 0xca, 0xf4, 0x17, 0x15, 0xd1, 0x93, 0x3f, 0x4b, 0xc3, 0xd5, 0xf9, 0x21, 0x01, + 0xdd, 0x80, 0xf2, 0x48, 0x9b, 0xa8, 0x64, 0x22, 0xee, 0x32, 0xdf, 0x0e, 0x18, 0x69, 0x93, 0xee, + 0x84, 0x5f, 0x64, 0x09, 0xd2, 0x64, 0xe2, 0xd6, 0x53, 0x37, 0xd2, 0xb7, 0xca, 0x0a, 0x6d, 0xa2, + 0x63, 0x58, 0x19, 0x5a, 0x7d, 0x6d, 0xa8, 0x86, 0x4e, 0xbc, 0x38, 0xec, 0x37, 0x67, 0x8c, 0xdd, + 0x9e, 0x30, 0x8a, 0x3e, 0x73, 0xe8, 0x6b, 0x4c, 0xc7, 0x9e, 0x7f, 0xf2, 0xd1, 0x3d, 0x28, 0x8d, + 0x82, 0x83, 0x7c, 0x89, 0xc3, 0x1e, 0x16, 0x0b, 0x6d, 0x49, 0x36, 0xe2, 0x18, 0x3c, 0x17, 0x9d, + 0xbb, 0xb4, 0x8b, 0x7e, 0x11, 0x56, 0x4d, 0x3c, 0x21, 0xa1, 0x8b, 0xc8, 0xcf, 0x49, 0x9e, 0x99, + 0x1e, 0xd1, 0x6f, 0xc1, 0x25, 0xa3, 0x47, 0x06, 0xdd, 0x66, 0x41, 0xd5, 0xb6, 0x5c, 0xec, 0xa8, + 0x9a, 0xae, 0x3b, 0xd8, 0x75, 0x59, 0x32, 0x58, 0x66, 0x91, 0x92, 0xd1, 0xb7, 0x39, 0x59, 0xfe, + 0x65, 0x78, 0x6b, 0x22, 0x41, 0xd4, 0x33, 0x7c, 0x32, 0x30, 0xfc, 0x11, 0xac, 0x0a, 0x79, 0x3d, + 0x62, 0xfb, 0xd4, 0xb2, 0x8e, 0x06, 0x79, 0xe2, 0xf1, 0x66, 0x4f, 0x7f, 0x3b, 0xb3, 0x7b, 0xbe, + 0x34, 0x13, 0xf2, 0xa5, 0xff, 0x65, 0x5b, 0xf1, 0xc7, 0x22, 0x14, 0x14, 0xec, 0xda, 0x34, 0x70, + 0xa2, 0x26, 0x14, 0xf1, 0xa4, 0x8f, 0x6d, 0xe2, 0xe5, 0x1a, 0xf3, 0xc1, 0x00, 0xe7, 0x6e, 0x7b, + 0x9c, 0x34, 0x13, 0xf7, 0xc5, 0xd0, 0x4b, 0x02, 0x6c, 0xc5, 0xe3, 0x26, 0x21, 0x1e, 0x46, 0x5b, + 0x2f, 0x7b, 0x68, 0x2b, 0x1d, 0x9b, 0x7c, 0x73, 0xa9, 0x29, 0xb8, 0xf5, 0x92, 0x80, 0x5b, 0x99, + 0x05, 0x83, 0x45, 0xf0, 0x56, 0x2b, 0x82, 0xb7, 0x72, 0x0b, 0x96, 0x19, 0x03, 0xb8, 0x5e, 0xf6, + 0x00, 0x57, 0x7e, 0xc1, 0x8c, 0xa7, 0x10, 0xd7, 0xfd, 0x28, 0xe2, 0x2a, 0xc4, 0x38, 0x10, 0x4f, + 0x3a, 0x16, 0x72, 0xbd, 0x11, 0x82, 0x5c, 0xc5, 0x58, 0xbc, 0xc3, 0x95, 0xcc, 0xc1, 0x5c, 0xad, + 0x08, 0xe6, 0x82, 0x05, 0x36, 0x88, 0x01, 0x5d, 0x6f, 0x86, 0x41, 0x57, 0x29, 0x16, 0xb7, 0x89, + 0xfd, 0x9e, 0x87, 0xba, 0x5e, 0xf3, 0x51, 0x57, 0x39, 0x16, 0x36, 0x8a, 0x35, 0x4c, 0xc3, 0xae, + 0x83, 0x19, 0xd8, 0xc5, 0x61, 0xd2, 0x33, 0xb1, 0x2a, 0x16, 0xe0, 0xae, 0x83, 0x19, 0xdc, 0x55, + 0x5d, 0xa0, 0x70, 0x01, 0xf0, 0xfa, 0xe9, 0x7c, 0xe0, 0x15, 0x0f, 0x8d, 0xc4, 0x34, 0x97, 0x43, + 0x5e, 0x6a, 0x0c, 0xf2, 0xe2, 0xe8, 0xe8, 0xb9, 0x58, 0xf5, 0x4b, 0x43, 0xaf, 0xe3, 0x39, 0xd0, + 0x8b, 0x83, 0xa4, 0x5b, 0xb1, 0xca, 0x97, 0xc0, 0x5e, 0xc7, 0x73, 0xb0, 0x17, 0x5a, 0xa8, 0xf6, + 0x32, 0xe0, 0x2b, 0x2b, 0xe5, 0xe4, 0xdb, 0x34, 0xf5, 0x9d, 0xf2, 0x53, 0x34, 0x7f, 0xc0, 0x8e, + 0x63, 0x39, 0x02, 0x46, 0xf1, 0x8e, 0x7c, 0x8b, 0x26, 0xe3, 0x81, 0x4f, 0xba, 0x00, 0xa8, 0xb1, + 0x3c, 0x2d, 0xe4, 0x87, 0xe4, 0xdf, 0x26, 0x03, 0x59, 0x96, 0xc3, 0x86, 0x13, 0xf9, 0xa2, 0x48, + 0xe4, 0x43, 0xf0, 0x2d, 0x15, 0x85, 0x6f, 0xeb, 0x50, 0xa2, 0xf9, 0xd7, 0x14, 0x32, 0xd3, 0x6c, + 0x1f, 0x99, 0xdd, 0x81, 0x15, 0x16, 0xf1, 0x38, 0xc8, 0x13, 0x61, 0x25, 0xc3, 0xc2, 0x4a, 0x8d, + 0x7e, 0xe0, 0x17, 0x8a, 0xc7, 0x97, 0x17, 0xe0, 0x4a, 0x88, 0xd7, 0xcf, 0xeb, 0x38, 0x4c, 0x91, + 0x7c, 0xee, 0x6d, 0x91, 0xe0, 0xfd, 0x3e, 0x19, 0x58, 0x28, 0x80, 0x74, 0xf3, 0xd0, 0x57, 0xf2, + 0xdf, 0x84, 0xbe, 0x52, 0xdf, 0x1a, 0x7d, 0x85, 0xf3, 0xd4, 0x74, 0x34, 0x4f, 0xfd, 0x7b, 0x32, + 0xd8, 0x13, 0x1f, 0x4b, 0xf5, 0x2d, 0x1d, 0x8b, 0xcc, 0x91, 0xb5, 0x69, 0x52, 0x31, 0xb4, 0x4e, + 0x45, 0x7e, 0x48, 0x9b, 0x94, 0xcb, 0x0f, 0x1c, 0x45, 0x11, 0x17, 0xfc, 0xa4, 0x93, 0x07, 0x6e, + 0x91, 0x74, 0x4a, 0x90, 0x7e, 0x84, 0x79, 0x5d, 0xad, 0xac, 0xd0, 0x26, 0xe5, 0x63, 0x47, 0x4d, + 0x04, 0x60, 0xde, 0x41, 0xaf, 0x42, 0x91, 0x55, 0x44, 0x55, 0xcb, 0x76, 0x85, 0x5b, 0x8f, 0xe4, + 0x26, 0xbc, 0xf0, 0xb9, 0x71, 0x48, 0x79, 0x0e, 0x6c, 0x57, 0x29, 0xd8, 0xa2, 0x15, 0xca, 0x18, + 0x8a, 0x91, 0x8c, 0xe1, 0x3a, 0x14, 0xe9, 0xec, 0x5d, 0x5b, 0xeb, 0x63, 0xe6, 0xa2, 0x8b, 0x4a, + 0x40, 0x90, 0x1f, 0x02, 0x9a, 0x0d, 0x12, 0xa8, 0x03, 0x39, 0x7c, 0x86, 0x4d, 0xc2, 0x33, 0xa8, + 0xd2, 0xd6, 0xd5, 0xd9, 0xd4, 0x94, 0x7e, 0x6e, 0xd6, 0xa9, 0x91, 0xff, 0xf6, 0xd5, 0xba, 0xc4, + 0xb9, 0x9f, 0xb7, 0x46, 0x06, 0xc1, 0x23, 0x9b, 0x9c, 0x2b, 0x42, 0x5e, 0xfe, 0x73, 0x8a, 0x02, + 0x98, 0x48, 0x00, 0x99, 0x6b, 0x5b, 0xef, 0xc8, 0xa7, 0x42, 0xd8, 0x75, 0x39, 0x7b, 0xaf, 0x01, + 0x9c, 0x6a, 0xae, 0xfa, 0xa1, 0x66, 0x12, 0xac, 0x0b, 0xa3, 0x87, 0x28, 0xa8, 0x01, 0x05, 0xda, + 0x1b, 0xbb, 0x58, 0x17, 0x30, 0xda, 0xef, 0x87, 0xd6, 0x99, 0xff, 0x6e, 0xeb, 0x8c, 0x5a, 0xb9, + 0x30, 0x65, 0xe5, 0x10, 0xb8, 0x28, 0x86, 0xc1, 0x05, 0x9d, 0x9b, 0xed, 0x18, 0x96, 0x63, 0x90, + 0x73, 0xb6, 0x35, 0x69, 0xc5, 0xef, 0xa3, 0x9b, 0x50, 0x19, 0xe1, 0x91, 0x6d, 0x59, 0x43, 0x95, + 0xbb, 0x9b, 0x12, 0x13, 0x2d, 0x0b, 0x62, 0x9b, 0x79, 0x9d, 0x5f, 0xa4, 0x82, 0xfb, 0x17, 0x80, + 0xc8, 0xff, 0x39, 0x03, 0xcb, 0xbf, 0x62, 0x95, 0xa5, 0x68, 0x8a, 0x80, 0x8e, 0x60, 0xc5, 0xbf, + 0xfe, 0xea, 0x98, 0xb9, 0x05, 0xef, 0x40, 0x2f, 0xeb, 0x3f, 0xa4, 0xb3, 0x28, 0xd9, 0x45, 0xef, + 0xc2, 0xe3, 0x53, 0xbe, 0xcd, 0x57, 0x9d, 0x5a, 0xd6, 0xc5, 0x3d, 0x16, 0x75, 0x71, 0x9e, 0xea, + 0xc0, 0x58, 0xe9, 0xef, 0x78, 0xeb, 0x76, 0xa0, 0x1a, 0xcd, 0x78, 0xe6, 0x6e, 0xff, 0x4d, 0xa8, + 0x38, 0x98, 0x68, 0x86, 0xa9, 0x46, 0xca, 0x41, 0x65, 0x4e, 0x14, 0x45, 0xa6, 0x43, 0x78, 0x6c, + 0x6e, 0xe6, 0x83, 0x5e, 0x81, 0x62, 0x90, 0x34, 0x71, 0xab, 0x5e, 0x50, 0x2e, 0x08, 0x78, 0xe5, + 0xdf, 0x25, 0x03, 0x95, 0xd1, 0x02, 0x44, 0x1b, 0x72, 0x0e, 0x76, 0xc7, 0x43, 0x5e, 0x12, 0xa8, + 0x6e, 0xbd, 0xb0, 0x5c, 0xce, 0x44, 0xa9, 0xe3, 0x21, 0x51, 0x84, 0xb0, 0xfc, 0x10, 0x72, 0x9c, + 0x82, 0x4a, 0x90, 0x3f, 0xde, 0xdf, 0xdd, 0x3f, 0x78, 0x67, 0x5f, 0x4a, 0x20, 0x80, 0xdc, 0x76, + 0xab, 0xd5, 0x3e, 0xec, 0x4a, 0x49, 0x54, 0x84, 0xec, 0x76, 0xf3, 0x40, 0xe9, 0x4a, 0x29, 0x4a, + 0x56, 0xda, 0x6f, 0xb5, 0x5b, 0x5d, 0x29, 0x8d, 0x56, 0xa0, 0xc2, 0xdb, 0xea, 0xfd, 0x03, 0xe5, + 0xed, 0xed, 0xae, 0x94, 0x09, 0x91, 0x8e, 0xda, 0xfb, 0xf7, 0xda, 0x8a, 0x94, 0x95, 0xff, 0x0f, + 0xae, 0xc5, 0x66, 0x59, 0x41, 0x75, 0x21, 0x19, 0xaa, 0x2e, 0xc8, 0x9f, 0xa5, 0xa0, 0x11, 0x9f, + 0x3a, 0xa1, 0xb7, 0xa6, 0x16, 0xbe, 0x75, 0x89, 0xbc, 0x6b, 0x6a, 0xf5, 0xe8, 0x69, 0xa8, 0x3a, + 0xf8, 0x04, 0x93, 0xfe, 0x80, 0xa7, 0x72, 0x3c, 0x64, 0x56, 0x94, 0x8a, 0xa0, 0x32, 0x21, 0x97, + 0xb3, 0xbd, 0x8f, 0xfb, 0x44, 0xe5, 0xbe, 0x88, 0x1f, 0xba, 0x22, 0x65, 0xa3, 0xd4, 0x23, 0x4e, + 0x94, 0xdf, 0xbb, 0x94, 0x2d, 0x8b, 0x90, 0x55, 0xda, 0x5d, 0xe5, 0x5d, 0x29, 0x8d, 0x10, 0x54, + 0x59, 0x53, 0x3d, 0xda, 0xdf, 0x3e, 0x3c, 0xea, 0x1c, 0x50, 0x5b, 0x5e, 0x81, 0x9a, 0x67, 0x4b, + 0x8f, 0x98, 0x95, 0x9f, 0x83, 0xc7, 0x63, 0xf2, 0xbe, 0x59, 0x14, 0x2f, 0xff, 0x3a, 0x19, 0xe6, + 0x8e, 0x62, 0xfe, 0x03, 0xc8, 0xb9, 0x44, 0x23, 0x63, 0x57, 0x18, 0xf1, 0x95, 0x65, 0x13, 0xc1, + 0x0d, 0xaf, 0x71, 0xc4, 0xc4, 0x15, 0xa1, 0x46, 0xbe, 0x0b, 0xd5, 0xe8, 0x97, 0x78, 0x1b, 0x04, + 0x87, 0x28, 0x25, 0xbf, 0x0b, 0x10, 0xaa, 0x47, 0xae, 0x42, 0xd6, 0xb1, 0xc6, 0xa6, 0xce, 0x26, + 0x95, 0x55, 0x78, 0x07, 0xdd, 0x85, 0xec, 0x99, 0xc5, 0x7d, 0xc6, 0xfc, 0x8b, 0xf3, 0xc0, 0x22, + 0x38, 0x54, 0x7c, 0xe0, 0xdc, 0xb2, 0x01, 0x68, 0xb6, 0x26, 0x14, 0x33, 0xc4, 0x1b, 0xd1, 0x21, + 0x9e, 0x8a, 0xad, 0x2e, 0xcd, 0x1f, 0xea, 0x23, 0xc8, 0x32, 0x6f, 0x43, 0x3d, 0x07, 0xab, 0x6b, + 0x8a, 0x64, 0x94, 0xb6, 0xd1, 0xcf, 0x00, 0x34, 0x42, 0x1c, 0xa3, 0x37, 0x0e, 0x06, 0x58, 0x9f, + 0xef, 0xad, 0xb6, 0x3d, 0xbe, 0xe6, 0x75, 0xe1, 0xb6, 0x56, 0x03, 0xd1, 0x90, 0xeb, 0x0a, 0x29, + 0x94, 0xf7, 0xa1, 0x1a, 0x95, 0xf5, 0xd2, 0xa7, 0xe4, 0x9c, 0xf4, 0x29, 0x15, 0x4e, 0x9f, 0xfc, + 0xe4, 0x2b, 0xcd, 0x4b, 0xd8, 0xac, 0x23, 0x7f, 0x92, 0x84, 0x42, 0x77, 0x22, 0xce, 0x71, 0x4c, + 0xf9, 0x34, 0x10, 0x4d, 0x85, 0x8b, 0x85, 0xbc, 0x1e, 0x9b, 0xf6, 0xab, 0xbc, 0x6f, 0xfa, 0x37, + 0x35, 0xb3, 0x2c, 0xda, 0xf5, 0xaa, 0xdd, 0xc2, 0x3b, 0xbd, 0x0e, 0x45, 0x3f, 0xd6, 0xd0, 0xac, + 0xde, 0xab, 0xac, 0x24, 0x45, 0x4a, 0xca, 0xbb, 0xac, 0x18, 0x6f, 0x7d, 0x28, 0xca, 0x91, 0x69, + 0x85, 0x77, 0x64, 0x1d, 0x6a, 0x53, 0x81, 0x0a, 0xbd, 0x0e, 0x79, 0x7b, 0xdc, 0x53, 0x3d, 0xf3, + 0x4c, 0xd5, 0x9f, 0xbc, 0x7c, 0x71, 0xdc, 0x1b, 0x1a, 0xfd, 0x5d, 0x7c, 0xee, 0x4d, 0xc6, 0x1e, + 0xf7, 0x76, 0xb9, 0x15, 0xf9, 0x28, 0xa9, 0xf0, 0x28, 0x67, 0x50, 0xf0, 0x0e, 0x05, 0xfa, 0x3e, + 0x14, 0xfd, 0x18, 0xe8, 0xff, 0xa3, 0x89, 0x0d, 0x9e, 0x42, 0x7d, 0x20, 0x42, 0xc1, 0x87, 0x6b, + 0x9c, 0x9a, 0x5e, 0xd5, 0x8d, 0xa3, 0xfc, 0x14, 0xdb, 0x9d, 0x1a, 0xff, 0xb0, 0xe7, 0x81, 0x0a, + 0xf9, 0x37, 0x49, 0x90, 0xa6, 0x4f, 0xe5, 0x7f, 0x72, 0x02, 0xd4, 0x29, 0xd2, 0xd3, 0xaf, 0x62, + 0x3a, 0x09, 0x1f, 0x4d, 0x95, 0x95, 0x0a, 0xa5, 0xb6, 0x3d, 0xa2, 0xfc, 0x71, 0x0a, 0x4a, 0xa1, + 0x9a, 0x1e, 0xfa, 0xff, 0xd0, 0x15, 0xa9, 0xce, 0xc9, 0x2d, 0x42, 0xbc, 0x41, 0xf9, 0x3f, 0xba, + 0xb0, 0xd4, 0xe5, 0x17, 0x16, 0xf7, 0x1b, 0xc7, 0x2b, 0x11, 0x66, 0x2e, 0x5d, 0x22, 0x7c, 0x1e, + 0x10, 0xb1, 0x88, 0x36, 0x54, 0xcf, 0x2c, 0x62, 0x98, 0xa7, 0x2a, 0x3f, 0x1a, 0x3c, 0xe3, 0x93, + 0xd8, 0x97, 0x07, 0xec, 0xc3, 0x21, 0x3b, 0x25, 0x3f, 0x4f, 0x42, 0xc1, 0x0f, 0xdd, 0x97, 0xad, + 0xe6, 0x5f, 0x85, 0x9c, 0x88, 0x4e, 0xbc, 0x9c, 0x2f, 0x7a, 0x73, 0x6b, 0xa1, 0x0d, 0x28, 0x8c, + 0x30, 0xd1, 0x58, 0xfe, 0xc2, 0x81, 0xa8, 0xdf, 0xbf, 0xf3, 0x1a, 0x94, 0x42, 0x3f, 0x56, 0xa8, + 0x9f, 0xd8, 0x6f, 0xbf, 0x23, 0x25, 0x1a, 0xf9, 0x4f, 0x3e, 0xbf, 0x91, 0xde, 0xc7, 0x1f, 0xd2, + 0x1b, 0xa6, 0xb4, 0x5b, 0x9d, 0x76, 0x6b, 0x57, 0x4a, 0x36, 0x4a, 0x9f, 0x7c, 0x7e, 0x23, 0xaf, + 0x60, 0x56, 0xbe, 0xba, 0xb3, 0x0b, 0xb5, 0xa9, 0x8d, 0x89, 0xfa, 0x77, 0x04, 0xd5, 0x7b, 0xc7, + 0x87, 0x7b, 0x3b, 0xad, 0xed, 0x6e, 0x5b, 0x7d, 0x70, 0xd0, 0x6d, 0x4b, 0x49, 0xf4, 0x38, 0x5c, + 0xd9, 0xdb, 0xf9, 0x61, 0xa7, 0xab, 0xb6, 0xf6, 0x76, 0xda, 0xfb, 0x5d, 0x75, 0xbb, 0xdb, 0xdd, + 0x6e, 0xed, 0x4a, 0xa9, 0xad, 0x7f, 0x00, 0xd4, 0xb6, 0x9b, 0xad, 0x1d, 0x1a, 0x9f, 0x8d, 0xbe, + 0xc6, 0x0a, 0x05, 0x2d, 0xc8, 0xb0, 0x52, 0xc0, 0x85, 0x4f, 0x45, 0x1a, 0x17, 0xd7, 0x36, 0xd1, + 0x7d, 0xc8, 0xb2, 0x2a, 0x01, 0xba, 0xf8, 0xed, 0x48, 0x63, 0x41, 0xb1, 0x93, 0x4e, 0x86, 0x5d, + 0xa7, 0x0b, 0x1f, 0x93, 0x34, 0x2e, 0xae, 0x7d, 0x22, 0x05, 0x8a, 0x01, 0xca, 0x58, 0xfc, 0xb8, + 0xa2, 0xb1, 0x84, 0x77, 0x44, 0x7b, 0x90, 0xf7, 0x80, 0xe1, 0xa2, 0xe7, 0x1e, 0x8d, 0x85, 0xc5, + 0x49, 0x6a, 0x2e, 0x0e, 0xe0, 0x2f, 0x7e, 0xbb, 0xd2, 0x58, 0x50, 0x69, 0x45, 0x3b, 0x90, 0x13, + 0x99, 0xf3, 0x82, 0x27, 0x1c, 0x8d, 0x45, 0xc5, 0x46, 0x6a, 0xb4, 0xa0, 0x34, 0xb2, 0xf8, 0x45, + 0x4e, 0x63, 0x89, 0x22, 0x32, 0x3a, 0x06, 0x08, 0xc1, 0xf5, 0x25, 0x9e, 0xda, 0x34, 0x96, 0x29, + 0x0e, 0xa3, 0x03, 0x28, 0xf8, 0xe8, 0x69, 0xe1, 0xc3, 0x97, 0xc6, 0xe2, 0x2a, 0x2d, 0x7a, 0x08, + 0x95, 0x28, 0x6a, 0x58, 0xee, 0x39, 0x4b, 0x63, 0xc9, 0xf2, 0x2b, 0xd5, 0x1f, 0x85, 0x10, 0xcb, + 0x3d, 0x6f, 0x69, 0x2c, 0x59, 0x8d, 0x45, 0xef, 0xc3, 0xca, 0x6c, 0x8a, 0xbf, 0xfc, 0x6b, 0x97, + 0xc6, 0x25, 0xea, 0xb3, 0x68, 0x04, 0x68, 0x0e, 0x34, 0xb8, 0xc4, 0xe3, 0x97, 0xc6, 0x65, 0xca, + 0xb5, 0x48, 0x87, 0xda, 0x74, 0xbe, 0xbd, 0xec, 0x63, 0x98, 0xc6, 0xd2, 0xa5, 0x5b, 0x3e, 0x4a, + 0x34, 0x4f, 0x5f, 0xf6, 0x71, 0x4c, 0x63, 0xe9, 0x4a, 0x6e, 0xb3, 0xfd, 0xc5, 0xd7, 0x6b, 0xc9, + 0x2f, 0xbf, 0x5e, 0x4b, 0xfe, 0xf5, 0xeb, 0xb5, 0xe4, 0xa7, 0xdf, 0xac, 0x25, 0xbe, 0xfc, 0x66, + 0x2d, 0xf1, 0xa7, 0x6f, 0xd6, 0x12, 0x3f, 0x7e, 0xee, 0xd4, 0x20, 0x83, 0x71, 0x6f, 0xa3, 0x6f, + 0x8d, 0x36, 0xc3, 0x2f, 0x04, 0xe7, 0xbd, 0x5a, 0xec, 0xe5, 0x58, 0x8c, 0x7c, 0xe9, 0x5f, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x9e, 0x97, 0xe4, 0x35, 0xd5, 0x28, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -3417,7 +3665,6 @@ 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) - SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, 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) @@ -3429,6 +3676,8 @@ type ABCIApplicationClient interface { OfferSnapshot(ctx context.Context, in *RequestOfferSnapshot, opts ...grpc.CallOption) (*ResponseOfferSnapshot, error) LoadSnapshotChunk(ctx context.Context, in *RequestLoadSnapshotChunk, opts ...grpc.CallOption) (*ResponseLoadSnapshotChunk, error) ApplySnapshotChunk(ctx context.Context, in *RequestApplySnapshotChunk, opts ...grpc.CallOption) (*ResponseApplySnapshotChunk, error) + PrepareProposal(ctx context.Context, in *RequestPrepareProposal, opts ...grpc.CallOption) (*ResponsePrepareProposal, error) + ProcessProposal(ctx context.Context, in *RequestProcessProposal, opts ...grpc.CallOption) (*ResponseProcessProposal, error) } type aBCIApplicationClient struct { @@ -3466,15 +3715,6 @@ func (c *aBCIApplicationClient) Info(ctx context.Context, in *RequestInfo, opts return out, nil } -func (c *aBCIApplicationClient) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) { - out := new(ResponseSetOption) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCIApplication/SetOption", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *aBCIApplicationClient) DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) { out := new(ResponseDeliverTx) err := c.cc.Invoke(ctx, "/tendermint.abci.ABCIApplication/DeliverTx", in, out, opts...) @@ -3574,12 +3814,29 @@ func (c *aBCIApplicationClient) ApplySnapshotChunk(ctx context.Context, in *Requ return out, nil } +func (c *aBCIApplicationClient) PrepareProposal(ctx context.Context, in *RequestPrepareProposal, opts ...grpc.CallOption) (*ResponsePrepareProposal, error) { + out := new(ResponsePrepareProposal) + err := c.cc.Invoke(ctx, "/tendermint.abci.ABCIApplication/PrepareProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) ProcessProposal(ctx context.Context, in *RequestProcessProposal, opts ...grpc.CallOption) (*ResponseProcessProposal, error) { + out := new(ResponseProcessProposal) + err := c.cc.Invoke(ctx, "/tendermint.abci.ABCIApplication/ProcessProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ABCIApplicationServer is the server API for ABCIApplication service. type ABCIApplicationServer 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) DeliverTx(context.Context, *RequestDeliverTx) (*ResponseDeliverTx, error) CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) Query(context.Context, *RequestQuery) (*ResponseQuery, error) @@ -3591,6 +3848,8 @@ type ABCIApplicationServer interface { OfferSnapshot(context.Context, *RequestOfferSnapshot) (*ResponseOfferSnapshot, error) LoadSnapshotChunk(context.Context, *RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) ApplySnapshotChunk(context.Context, *RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) + PrepareProposal(context.Context, *RequestPrepareProposal) (*ResponsePrepareProposal, error) + ProcessProposal(context.Context, *RequestProcessProposal) (*ResponseProcessProposal, error) } // UnimplementedABCIApplicationServer can be embedded to have forward compatible implementations. @@ -3606,9 +3865,6 @@ func (*UnimplementedABCIApplicationServer) Flush(ctx context.Context, req *Reque func (*UnimplementedABCIApplicationServer) Info(ctx context.Context, req *RequestInfo) (*ResponseInfo, error) { return nil, status.Errorf(codes.Unimplemented, "method Info not implemented") } -func (*UnimplementedABCIApplicationServer) SetOption(ctx context.Context, req *RequestSetOption) (*ResponseSetOption, error) { - return nil, status.Errorf(codes.Unimplemented, "method SetOption not implemented") -} func (*UnimplementedABCIApplicationServer) DeliverTx(ctx context.Context, req *RequestDeliverTx) (*ResponseDeliverTx, error) { return nil, status.Errorf(codes.Unimplemented, "method DeliverTx not implemented") } @@ -3642,6 +3898,12 @@ func (*UnimplementedABCIApplicationServer) LoadSnapshotChunk(ctx context.Context func (*UnimplementedABCIApplicationServer) ApplySnapshotChunk(ctx context.Context, req *RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) { return nil, status.Errorf(codes.Unimplemented, "method ApplySnapshotChunk not implemented") } +func (*UnimplementedABCIApplicationServer) PrepareProposal(ctx context.Context, req *RequestPrepareProposal) (*ResponsePrepareProposal, error) { + return nil, status.Errorf(codes.Unimplemented, "method PrepareProposal not implemented") +} +func (*UnimplementedABCIApplicationServer) ProcessProposal(ctx context.Context, req *RequestProcessProposal) (*ResponseProcessProposal, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProcessProposal not implemented") +} func RegisterABCIApplicationServer(s *grpc.Server, srv ABCIApplicationServer) { s.RegisterService(&_ABCIApplication_serviceDesc, srv) @@ -3701,24 +3963,6 @@ func _ABCIApplication_Info_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } -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.(ABCIApplicationServer).SetOption(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCIApplication/SetOption", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).SetOption(ctx, req.(*RequestSetOption)) - } - return interceptor(ctx, in, info, handler) -} - 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 { @@ -3917,6 +4161,42 @@ func _ABCIApplication_ApplySnapshotChunk_Handler(srv interface{}, ctx context.Co return interceptor(ctx, in, info, handler) } +func _ABCIApplication_PrepareProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestPrepareProposal) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).PrepareProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/tendermint.abci.ABCIApplication/PrepareProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).PrepareProposal(ctx, req.(*RequestPrepareProposal)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_ProcessProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestProcessProposal) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).ProcessProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/tendermint.abci.ABCIApplication/ProcessProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).ProcessProposal(ctx, req.(*RequestProcessProposal)) + } + return interceptor(ctx, in, info, handler) +} + var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ ServiceName: "tendermint.abci.ABCIApplication", HandlerType: (*ABCIApplicationServer)(nil), @@ -3933,10 +4213,6 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ MethodName: "Info", Handler: _ABCIApplication_Info_Handler, }, - { - MethodName: "SetOption", - Handler: _ABCIApplication_SetOption_Handler, - }, { MethodName: "DeliverTx", Handler: _ABCIApplication_DeliverTx_Handler, @@ -3981,6 +4257,14 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ MethodName: "ApplySnapshotChunk", Handler: _ABCIApplication_ApplySnapshotChunk_Handler, }, + { + MethodName: "PrepareProposal", + Handler: _ABCIApplication_PrepareProposal_Handler, + }, + { + MethodName: "ProcessProposal", + Handler: _ABCIApplication_ProcessProposal_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "tendermint/abci/types.proto", @@ -4081,27 +4365,6 @@ func (m *Request_Info) MarshalToSizedBuffer(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } -func (m *Request_SetOption) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Request_SetOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - if m.SetOption != nil { - { - size, err := m.SetOption.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - return len(dAtA) - i, nil -} func (m *Request_InitChain) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) @@ -4333,6 +4596,52 @@ func (m *Request_ApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, err } return len(dAtA) - i, nil } +func (m *Request_PrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_PrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PrepareProposal != nil { + { + size, err := m.PrepareProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } + return len(dAtA) - i, nil +} +func (m *Request_ProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ProcessProposal != nil { + { + size, err := m.ProcessProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + return len(dAtA) - i, nil +} func (m *RequestEcho) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -4406,6 +4715,13 @@ func (m *RequestInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.AbciVersion) > 0 { + i -= len(m.AbciVersion) + copy(dAtA[i:], m.AbciVersion) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AbciVersion))) + i-- + dAtA[i] = 0x22 + } if m.P2PVersion != 0 { i = encodeVarintTypes(dAtA, i, uint64(m.P2PVersion)) i-- @@ -4426,43 +4742,6 @@ func (m *RequestInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestSetOption) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *RequestSetOption) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *RequestSetOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Value) > 0 { - i -= len(m.Value) - copy(dAtA[i:], m.Value) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Value))) - i-- - dAtA[i] = 0x12 - } - if len(m.Key) > 0 { - i -= len(m.Key) - copy(dAtA[i:], m.Key) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func (m *RequestInitChain) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -4528,12 +4807,12 @@ func (m *RequestInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - n17, err17 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err17 != nil { - return 0, err17 + n18, err18 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err18 != nil { + return 0, err18 } - i -= n17 - i = encodeVarintTypes(dAtA, i, uint64(n17)) + i -= n18 + i = encodeVarintTypes(dAtA, i, uint64(n18)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil @@ -4916,6 +5195,184 @@ func (m *RequestApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } +func (m *RequestPrepareProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestPrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestPrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x3a + } + n22, err22 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err22 != nil { + return 0, err22 + } + i -= n22 + i = encodeVarintTypes(dAtA, i, uint64(n22)) + i-- + dAtA[i] = 0x32 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x28 + } + if len(m.Misbehavior) > 0 { + for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Misbehavior[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + { + size, err := m.LocalLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if m.MaxTxBytes != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.MaxTxBytes)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *RequestProcessProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x3a + } + n24, err24 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err24 != nil { + return 0, err24 + } + i -= n24 + i = encodeVarintTypes(dAtA, i, uint64(n24)) + i-- + dAtA[i] = 0x32 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x28 + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0x22 + } + if len(m.Misbehavior) > 0 { + for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Misbehavior[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.ProposedLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func (m *Response) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -5032,27 +5489,6 @@ func (m *Response_Info) MarshalToSizedBuffer(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } -func (m *Response_SetOption) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Response_SetOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - if m.SetOption != nil { - { - size, err := m.SetOption.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x2a - } - return len(dAtA) - i, nil -} func (m *Response_InitChain) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) @@ -5286,6 +5722,52 @@ func (m *Response_ApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, er } return len(dAtA) - i, nil } +func (m *Response_PrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_PrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PrepareProposal != nil { + { + size, err := m.PrepareProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + return len(dAtA) - i, nil +} +func (m *Response_ProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ProcessProposal != nil { + { + size, err := m.ProcessProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x92 + } + return len(dAtA) - i, nil +} func (m *ResponseException) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -5423,48 +5905,6 @@ func (m *ResponseInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseSetOption) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ResponseSetOption) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ResponseSetOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Info) > 0 { - i -= len(m.Info) - copy(dAtA[i:], m.Info) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) - i-- - dAtA[i] = 0x22 - } - if len(m.Log) > 0 { - i -= len(m.Log) - copy(dAtA[i:], m.Log) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) - i-- - dAtA[i] = 0x1a - } - if m.Code != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.Code)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - func (m *ResponseInitChain) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -6045,20 +6485,20 @@ func (m *ResponseApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, err } } if len(m.RefetchChunks) > 0 { - dAtA41 := make([]byte, len(m.RefetchChunks)*10) - var j40 int + dAtA47 := make([]byte, len(m.RefetchChunks)*10) + var j46 int for _, num := range m.RefetchChunks { for num >= 1<<7 { - dAtA41[j40] = uint8(uint64(num)&0x7f | 0x80) + dAtA47[j46] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j40++ + j46++ } - dAtA41[j40] = uint8(num) - j40++ + dAtA47[j46] = uint8(num) + j46++ } - i -= j40 - copy(dAtA[i:], dAtA41[:j40]) - i = encodeVarintTypes(dAtA, i, uint64(j40)) + i -= j46 + copy(dAtA[i:], dAtA47[:j46]) + i = encodeVarintTypes(dAtA, i, uint64(j46)) i-- dAtA[i] = 0x12 } @@ -6070,7 +6510,7 @@ func (m *ResponseApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } -func (m *ConsensusParams) Marshal() (dAtA []byte, err error) { +func (m *ResponsePrepareProposal) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6080,68 +6520,29 @@ func (m *ConsensusParams) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ConsensusParams) MarshalTo(dAtA []byte) (int, error) { +func (m *ResponsePrepareProposal) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ConsensusParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ResponsePrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.Version != nil { - { - size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0xa } - i-- - dAtA[i] = 0x22 - } - if m.Validator != nil { - { - size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - if m.Evidence != nil { - { - size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if m.Block != nil { - { - size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa } return len(dAtA) - i, nil } -func (m *BlockParams) Marshal() (dAtA []byte, err error) { +func (m *ResponseProcessProposal) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6151,30 +6552,25 @@ func (m *BlockParams) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *BlockParams) MarshalTo(dAtA []byte) (int, error) { +func (m *ResponseProcessProposal) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *BlockParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ResponseProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.MaxGas != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.MaxGas)) - i-- - dAtA[i] = 0x10 - } - if m.MaxBytes != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.MaxBytes)) + if m.Status != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Status)) i-- dAtA[i] = 0x8 } return len(dAtA) - i, nil } -func (m *LastCommitInfo) Marshal() (dAtA []byte, err error) { +func (m *CommitInfo) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6184,12 +6580,54 @@ func (m *LastCommitInfo) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *LastCommitInfo) MarshalTo(dAtA []byte) (int, error) { +func (m *CommitInfo) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *LastCommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *CommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ExtendedCommitInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExtendedCommitInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExtendedCommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6473,7 +6911,7 @@ func (m *VoteInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *Evidence) Marshal() (dAtA []byte, err error) { +func (m *ExtendedVoteInfo) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6483,12 +6921,62 @@ func (m *Evidence) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *Evidence) MarshalTo(dAtA []byte) (int, error) { +func (m *ExtendedVoteInfo) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *Evidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ExtendedVoteInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.VoteExtension) > 0 { + i -= len(m.VoteExtension) + copy(dAtA[i:], m.VoteExtension) + i = encodeVarintTypes(dAtA, i, uint64(len(m.VoteExtension))) + i-- + dAtA[i] = 0x1a + } + if m.SignedLastBlock { + i-- + if m.SignedLastBlock { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Misbehavior) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Misbehavior) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Misbehavior) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6498,12 +6986,12 @@ func (m *Evidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x28 } - n49, err49 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err49 != nil { - return 0, err49 + n52, err52 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err52 != nil { + return 0, err52 } - i -= n49 - i = encodeVarintTypes(dAtA, i, uint64(n49)) + i -= n52 + i = encodeVarintTypes(dAtA, i, uint64(n52)) i-- dAtA[i] = 0x22 if m.Height != 0 { @@ -6640,18 +7128,6 @@ func (m *Request_Info) Size() (n int) { } return n } -func (m *Request_SetOption) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.SetOption != nil { - l = m.SetOption.Size() - n += 1 + l + sovTypes(uint64(l)) - } - return n -} func (m *Request_InitChain) Size() (n int) { if m == nil { return 0 @@ -6784,6 +7260,30 @@ func (m *Request_ApplySnapshotChunk) Size() (n int) { } return n } +func (m *Request_PrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PrepareProposal != nil { + l = m.PrepareProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProcessProposal != nil { + l = m.ProcessProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} func (m *RequestEcho) Size() (n int) { if m == nil { return 0 @@ -6822,20 +7322,7 @@ func (m *RequestInfo) Size() (n int) { if m.P2PVersion != 0 { n += 1 + sovTypes(uint64(m.P2PVersion)) } - return n -} - -func (m *RequestSetOption) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Key) - if l > 0 { - n += 1 + l + sovTypes(uint64(l)) - } - l = len(m.Value) + l = len(m.AbciVersion) if l > 0 { n += 1 + l + sovTypes(uint64(l)) } @@ -7034,6 +7521,85 @@ func (m *RequestApplySnapshotChunk) Size() (n int) { return n } +func (m *RequestPrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MaxTxBytes != 0 { + n += 1 + sovTypes(uint64(m.MaxTxBytes)) + } + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.LocalLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Misbehavior) > 0 { + for _, e := range m.Misbehavior { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.ProposedLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Misbehavior) > 0 { + for _, e := range m.Misbehavior { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + func (m *Response) Size() (n int) { if m == nil { return 0 @@ -7094,18 +7660,6 @@ func (m *Response_Info) Size() (n int) { } return n } -func (m *Response_SetOption) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.SetOption != nil { - l = m.SetOption.Size() - n += 1 + l + sovTypes(uint64(l)) - } - return n -} func (m *Response_InitChain) Size() (n int) { if m == nil { return 0 @@ -7238,6 +7792,30 @@ func (m *Response_ApplySnapshotChunk) Size() (n int) { } return n } +func (m *Response_PrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PrepareProposal != nil { + l = m.PrepareProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProcessProposal != nil { + l = m.ProcessProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} func (m *ResponseException) Size() (n int) { if m == nil { return 0 @@ -7300,26 +7878,6 @@ func (m *ResponseInfo) Size() (n int) { return n } -func (m *ResponseSetOption) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Code != 0 { - n += 1 + sovTypes(uint64(m.Code)) - } - l = len(m.Log) - if l > 0 { - n += 1 + l + sovTypes(uint64(l)) - } - l = len(m.Info) - if l > 0 { - n += 1 + l + sovTypes(uint64(l)) - } - return n -} - func (m *ResponseInitChain) Size() (n int) { if m == nil { return 0 @@ -7597,47 +8155,52 @@ func (m *ResponseApplySnapshotChunk) Size() (n int) { return n } -func (m *ConsensusParams) Size() (n int) { +func (m *ResponsePrepareProposal) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.Block != nil { - l = m.Block.Size() - n += 1 + l + sovTypes(uint64(l)) - } - if m.Evidence != nil { - l = m.Evidence.Size() - n += 1 + l + sovTypes(uint64(l)) - } - if m.Validator != nil { - l = m.Validator.Size() - n += 1 + l + sovTypes(uint64(l)) - } - if m.Version != nil { - l = m.Version.Size() - n += 1 + l + sovTypes(uint64(l)) + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } } return n } -func (m *BlockParams) Size() (n int) { +func (m *ResponseProcessProposal) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.MaxBytes != 0 { - n += 1 + sovTypes(uint64(m.MaxBytes)) - } - if m.MaxGas != 0 { - n += 1 + sovTypes(uint64(m.MaxGas)) + if m.Status != 0 { + n += 1 + sovTypes(uint64(m.Status)) } return n } -func (m *LastCommitInfo) Size() (n int) { +func (m *CommitInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ExtendedCommitInfo) Size() (n int) { if m == nil { return 0 } @@ -7759,7 +8322,25 @@ func (m *VoteInfo) Size() (n int) { return n } -func (m *Evidence) Size() (n int) { +func (m *ExtendedVoteInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.SignedLastBlock { + n += 2 + } + l = len(m.VoteExtension) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Misbehavior) Size() (n int) { if m == nil { return 0 } @@ -7947,41 +8528,6 @@ func (m *Request) Unmarshal(dAtA []byte) error { } m.Value = &Request_Info{v} iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SetOption", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - v := &RequestSetOption{} - if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - m.Value = &Request_SetOption{v} - iNdEx = postIndex case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) @@ -8367,6 +8913,76 @@ func (m *Request) Unmarshal(dAtA []byte) error { } m.Value = &Request_ApplySnapshotChunk{v} iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PrepareProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestPrepareProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_PrepareProposal{v} + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProcessProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestProcessProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ProcessProposal{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -8619,59 +9235,9 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { break } } - default: - iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *RequestSetOption) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: RequestSetOption: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: RequestSetOption: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field AbciVersion", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -8699,39 +9265,7 @@ func (m *RequestSetOption) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Key = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Value = string(dAtA[iNdEx:postIndex]) + m.AbciVersion = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -8878,7 +9412,7 @@ func (m *RequestInitChain) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ConsensusParams == nil { - m.ConsensusParams = &ConsensusParams{} + m.ConsensusParams = &types1.ConsensusParams{} } if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -9305,7 +9839,7 @@ func (m *RequestBeginBlock) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ByzantineValidators = append(m.ByzantineValidators, Evidence{}) + m.ByzantineValidators = append(m.ByzantineValidators, Misbehavior{}) if err := m.ByzantineValidators[len(m.ByzantineValidators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -10049,6 +10583,597 @@ func (m *RequestApplySnapshotChunk) Unmarshal(dAtA []byte) error { } return nil } +func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestPrepareProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestPrepareProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxTxBytes", wireType) + } + m.MaxTxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxTxBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LocalLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Misbehavior", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Misbehavior = append(m.Misbehavior, Misbehavior{}) + if err := m.Misbehavior[len(m.Misbehavior)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestProcessProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestProcessProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestProcessProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposedLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ProposedLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Misbehavior", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Misbehavior = append(m.Misbehavior, Misbehavior{}) + if err := m.Misbehavior[len(m.Misbehavior)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Response) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -10218,41 +11343,6 @@ func (m *Response) Unmarshal(dAtA []byte) error { } m.Value = &Response_Info{v} iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SetOption", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - v := &ResponseSetOption{} - if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - m.Value = &Response_SetOption{v} - iNdEx = postIndex case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) @@ -10638,6 +11728,76 @@ func (m *Response) Unmarshal(dAtA []byte) error { } m.Value = &Response_ApplySnapshotChunk{v} iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PrepareProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponsePrepareProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_PrepareProposal{v} + iNdEx = postIndex + case 18: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProcessProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseProcessProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ProcessProposal{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -11059,139 +12219,6 @@ func (m *ResponseInfo) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseSetOption) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ResponseSetOption: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseSetOption: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) - } - m.Code = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Code |= uint32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Log = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Info = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -11251,7 +12278,7 @@ func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ConsensusParams == nil { - m.ConsensusParams = &ConsensusParams{} + m.ConsensusParams = &types1.ConsensusParams{} } if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -12455,7 +13482,7 @@ func (m *ResponseEndBlock) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ConsensusParamUpdates == nil { - m.ConsensusParamUpdates = &ConsensusParams{} + m.ConsensusParamUpdates = &types1.ConsensusParams{} } if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -13033,7 +14060,7 @@ func (m *ResponseApplySnapshotChunk) Unmarshal(dAtA []byte) error { } return nil } -func (m *ConsensusParams) Unmarshal(dAtA []byte) error { +func (m *ResponsePrepareProposal) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13056,17 +14083,17 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ConsensusParams: wiretype end group for non-group") + return fmt.Errorf("proto: ResponsePrepareProposal: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ConsensusParams: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ResponsePrepareProposal: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) } - var msglen int + var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -13076,135 +14103,23 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + byteLen |= int(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + if byteLen < 0 { return ErrInvalidLengthTypes } - postIndex := iNdEx + msglen + postIndex := iNdEx + byteLen if postIndex < 0 { return ErrInvalidLengthTypes } if postIndex > l { return io.ErrUnexpectedEOF } - if m.Block == nil { - m.Block = &BlockParams{} - } - if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Evidence == nil { - m.Evidence = &types1.EvidenceParams{} - } - if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Validator == nil { - m.Validator = &types1.ValidatorParams{} - } - if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Version == nil { - m.Version = &types1.VersionParams{} - } - if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -13227,7 +14142,7 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { } return nil } -func (m *BlockParams) Unmarshal(dAtA []byte) error { +func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13250,17 +14165,17 @@ func (m *BlockParams) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: BlockParams: wiretype end group for non-group") + return fmt.Errorf("proto: ResponseProcessProposal: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: BlockParams: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ResponseProcessProposal: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxBytes", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) } - m.MaxBytes = 0 + m.Status = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -13270,26 +14185,7 @@ func (m *BlockParams) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.MaxBytes |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxGas", wireType) - } - m.MaxGas = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.MaxGas |= int64(b&0x7F) << shift + m.Status |= ResponseProcessProposal_ProposalStatus(b&0x7F) << shift if b < 0x80 { break } @@ -13315,7 +14211,7 @@ func (m *BlockParams) Unmarshal(dAtA []byte) error { } return nil } -func (m *LastCommitInfo) Unmarshal(dAtA []byte) error { +func (m *CommitInfo) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13338,10 +14234,10 @@ func (m *LastCommitInfo) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: LastCommitInfo: wiretype end group for non-group") + return fmt.Errorf("proto: CommitInfo: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: LastCommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -13418,6 +14314,109 @@ func (m *LastCommitInfo) Unmarshal(dAtA []byte) error { } return nil } +func (m *ExtendedCommitInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExtendedCommitInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExtendedCommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, ExtendedVoteInfo{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Event) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -14135,7 +15134,7 @@ func (m *VoteInfo) Unmarshal(dAtA []byte) error { } return nil } -func (m *Evidence) Unmarshal(dAtA []byte) error { +func (m *ExtendedVoteInfo) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -14158,10 +15157,147 @@ func (m *Evidence) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: Evidence: wiretype end group for non-group") + return fmt.Errorf("proto: ExtendedVoteInfo: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: Evidence: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExtendedVoteInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedLastBlock", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SignedLastBlock = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteExtension", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VoteExtension = append(m.VoteExtension[:0], dAtA[iNdEx:postIndex]...) + if m.VoteExtension == nil { + m.VoteExtension = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Misbehavior) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Misbehavior: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Misbehavior: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -14178,7 +15314,7 @@ func (m *Evidence) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Type |= EvidenceType(b&0x7F) << shift + m.Type |= MisbehaviorType(b&0x7F) << shift if b < 0x80 { break } diff --git a/blocksync/reactor.go b/blocksync/reactor.go index 1f867ca98..1eccd5efb 100644 --- a/blocksync/reactor.go +++ b/blocksync/reactor.go @@ -359,14 +359,20 @@ FOR_LOOP: didProcessCh <- struct{}{} } - firstParts := first.MakePartSet(types.BlockPartSizeBytes) + firstParts, err := first.MakePartSet(types.BlockPartSizeBytes) + if err != nil { + bcR.Logger.Error("failed to make ", + "height", first.Height, + "err", err.Error()) + break FOR_LOOP + } firstPartSetHeader := firstParts.Header() firstID := types.BlockID{Hash: first.Hash(), PartSetHeader: firstPartSetHeader} // Finally, verify the first block using the second's commit // NOTE: we can probably make this more efficient, but note that calling // first.Hash() doesn't verify the tx contents, so MakePartSet() is // currently necessary. - err := state.Validators.VerifyCommitLight( + err = state.Validators.VerifyCommitLight( chainID, firstID, first.Height, second.LastCommit) if err == nil { diff --git a/blocksync/reactor_test.go b/blocksync/reactor_test.go index 1a3c35657..6559ff298 100644 --- a/blocksync/reactor_test.go +++ b/blocksync/reactor_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" dbm "github.com/tendermint/tm-db" @@ -15,7 +16,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/libs/log" - "github.com/tendermint/tendermint/mempool/mock" + mpmocks "github.com/tendermint/tendermint/mempool/mocks" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/proxy" sm "github.com/tendermint/tendermint/state" @@ -52,6 +53,7 @@ type ReactorPair struct { } func newReactor( + t *testing.T, logger log.Logger, genDoc *types.GenesisDoc, privVals []types.PrivValidator, @@ -80,6 +82,18 @@ func newReactor( panic(fmt.Errorf("error constructing state from genesis file: %w", err)) } + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + // Make the Reactor itself. // NOTE we have to create and commit the blocks first because // pool.height is determined from the store. @@ -89,7 +103,7 @@ func newReactor( DiscardABCIResponses: false, }) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - mock.Mempool{}, sm.EmptyEvidencePool{}) + mp, sm.EmptyEvidencePool{}) if err = stateStore.Save(state); err != nil { panic(err) } @@ -116,9 +130,10 @@ func newReactor( lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()}) } - thisBlock := makeBlock(blockHeight, state, lastCommit) + thisBlock := state.MakeBlock(blockHeight, nil, lastCommit, nil, state.Validators.Proposer.Address) - thisParts := thisBlock.MakePartSet(types.BlockPartSizeBytes) + thisParts, err := thisBlock.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) blockID := types.BlockID{Hash: thisBlock.Hash(), PartSetHeader: thisParts.Header()} state, _, err = blockExec.ApplyBlock(state, blockID, thisBlock) @@ -144,8 +159,8 @@ func TestNoBlockResponse(t *testing.T) { reactorPairs := make([]ReactorPair, 2) - reactorPairs[0] = newReactor(log.TestingLogger(), genDoc, privVals, maxBlockHeight) - reactorPairs[1] = newReactor(log.TestingLogger(), genDoc, privVals, 0) + reactorPairs[0] = newReactor(t, log.TestingLogger(), genDoc, privVals, maxBlockHeight) + reactorPairs[1] = newReactor(t, log.TestingLogger(), genDoc, privVals, 0) p2p.MakeConnectedSwitches(config.P2P, 2, func(i int, s *p2p.Switch) *p2p.Switch { s.AddReactor("BLOCKCHAIN", reactorPairs[i].reactor) @@ -206,7 +221,7 @@ func TestBadBlockStopsPeer(t *testing.T) { // Other chain needs a different validator set otherGenDoc, otherPrivVals := randGenesisDoc(1, false, 30) - otherChain := newReactor(log.TestingLogger(), otherGenDoc, otherPrivVals, maxBlockHeight) + otherChain := newReactor(t, log.TestingLogger(), otherGenDoc, otherPrivVals, maxBlockHeight) defer func() { err := otherChain.reactor.Stop() @@ -217,10 +232,10 @@ func TestBadBlockStopsPeer(t *testing.T) { reactorPairs := make([]ReactorPair, 4) - reactorPairs[0] = newReactor(log.TestingLogger(), genDoc, privVals, maxBlockHeight) - reactorPairs[1] = newReactor(log.TestingLogger(), genDoc, privVals, 0) - reactorPairs[2] = newReactor(log.TestingLogger(), genDoc, privVals, 0) - reactorPairs[3] = newReactor(log.TestingLogger(), genDoc, privVals, 0) + reactorPairs[0] = newReactor(t, log.TestingLogger(), genDoc, privVals, maxBlockHeight) + reactorPairs[1] = newReactor(t, log.TestingLogger(), genDoc, privVals, 0) + reactorPairs[2] = newReactor(t, log.TestingLogger(), genDoc, privVals, 0) + reactorPairs[3] = newReactor(t, log.TestingLogger(), genDoc, privVals, 0) switches := p2p.MakeConnectedSwitches(config.P2P, 4, func(i int, s *p2p.Switch) *p2p.Switch { s.AddReactor("BLOCKCHAIN", reactorPairs[i].reactor) @@ -258,7 +273,7 @@ func TestBadBlockStopsPeer(t *testing.T) { // race, but can't be easily avoided. reactorPairs[3].reactor.store = otherChain.reactor.store - lastReactorPair := newReactor(log.TestingLogger(), genDoc, privVals, 0) + lastReactorPair := newReactor(t, log.TestingLogger(), genDoc, privVals, 0) reactorPairs = append(reactorPairs, lastReactorPair) switches = append(switches, p2p.MakeConnectedSwitches(config.P2P, 1, func(i int, s *p2p.Switch) *p2p.Switch { @@ -282,21 +297,6 @@ func TestBadBlockStopsPeer(t *testing.T) { assert.True(t, lastReactorPair.reactor.Switch.Peers().Size() < len(reactorPairs)-1) } -//---------------------------------------------- -// utility funcs - -func makeTxs(height int64) (txs []types.Tx) { - for i := 0; i < 10; i++ { - txs = append(txs, types.Tx([]byte{byte(height), byte(i)})) - } - return txs -} - -func makeBlock(height int64, state sm.State, lastCommit *types.Commit) *types.Block { - block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, nil, state.Validators.GetProposer().Address) - return block -} - type testApp struct { abci.BaseApplication } diff --git a/cmd/tendermint/commands/reindex_event_test.go b/cmd/tendermint/commands/reindex_event_test.go index 716f4167a..87ff80ddc 100644 --- a/cmd/tendermint/commands/reindex_event_test.go +++ b/cmd/tendermint/commands/reindex_event_test.go @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + dbm "github.com/tendermint/tm-db" + abcitypes "github.com/tendermint/tendermint/abci/types" tmcfg "github.com/tendermint/tendermint/config" prototmstate "github.com/tendermint/tendermint/proto/tendermint/state" @@ -16,7 +18,6 @@ import ( "github.com/tendermint/tendermint/state/mocks" txmocks "github.com/tendermint/tendermint/state/txindex/mocks" "github.com/tendermint/tendermint/types" - dbm "github.com/tendermint/tm-db" ) const ( diff --git a/consensus/byzantine_test.go b/consensus/byzantine_test.go index d953ab34b..8b490d906 100644 --- a/consensus/byzantine_test.go +++ b/consensus/byzantine_test.go @@ -213,9 +213,11 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { } proposerAddr := lazyProposer.privValidatorPubKey.Address() - block, blockParts := lazyProposer.blockExec.CreateProposalBlock( - lazyProposer.Height, lazyProposer.state, commit, proposerAddr, - ) + block, err := lazyProposer.blockExec.CreateProposalBlock( + lazyProposer.Height, lazyProposer.state, commit, proposerAddr, nil) + require.NoError(t, err) + blockParts, err := block.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) // Flush the WAL. Otherwise, we may not recompute the same proposal to sign, // and the privValidator will refuse to sign anything. @@ -463,7 +465,10 @@ func byzantineDecideProposalFunc(t *testing.T, height int64, round int32, cs *St // Avoid sending on internalMsgQueue and running consensus state. // Create a new proposal block from state/txs from the mempool. - block1, blockParts1 := cs.createProposalBlock() + block1, err := cs.createProposalBlock() + require.NoError(t, err) + blockParts1, err := block1.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) polRound, propBlockID := cs.ValidRound, types.BlockID{Hash: block1.Hash(), PartSetHeader: blockParts1.Header()} proposal1 := types.NewProposal(height, round, polRound, propBlockID) p1 := proposal1.ToProto() @@ -477,7 +482,10 @@ func byzantineDecideProposalFunc(t *testing.T, height int64, round int32, cs *St deliverTxsRange(cs, 0, 1) // Create a new proposal block from state/txs from the mempool. - block2, blockParts2 := cs.createProposalBlock() + block2, err := cs.createProposalBlock() + require.NoError(t, err) + blockParts2, err := block2.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) polRound, propBlockID = cs.ValidRound, types.BlockID{Hash: block2.Hash(), PartSetHeader: blockParts2.Header()} proposal2 := types.NewProposal(height, round, polRound, propBlockID) p2 := proposal2.ToProto() diff --git a/consensus/common_test.go b/consensus/common_test.go index c52fa5fbe..435dd833d 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/go-kit/log/term" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "path" @@ -199,13 +200,17 @@ func startTestRound(cs *State, height int64, round int32) { // Create proposal block from cs1 but sign it with vs. func decideProposal( + t *testing.T, cs1 *State, vs *validatorStub, height int64, round int32, ) (proposal *types.Proposal, block *types.Block) { cs1.mtx.Lock() - block, blockParts := cs1.createProposalBlock() + block, err := cs1.createProposalBlock() + require.NoError(t, err) + blockParts, err := block.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) validRound := cs1.ValidRound chainID := cs1.state.ChainID cs1.mtx.Unlock() @@ -458,12 +463,16 @@ func loadPrivValidator(config *cfg.Config) *privval.FilePV { } func randState(nValidators int) (*State, []*validatorStub) { + return randStateWithApp(nValidators, kvstore.NewApplication()) +} + +func randStateWithApp(nValidators int, app abci.Application) (*State, []*validatorStub) { // Get State state, privVals := randGenesisState(nValidators, false, 10) vss := make([]*validatorStub, nValidators) - cs := newState(state, privVals[0], kvstore.NewApplication()) + cs := newState(state, privVals[0], app) for i := 0; i < nValidators; i++ { vss[i] = newValidatorStub(privVals[i], int32(i)) @@ -678,6 +687,33 @@ func ensureVote(voteCh <-chan tmpubsub.Message, height int64, round int32, } } +func ensurePrevoteMatch(t *testing.T, voteCh <-chan tmpubsub.Message, height int64, round int32, hash []byte) { + t.Helper() + ensureVoteMatch(t, voteCh, height, round, hash, tmproto.PrevoteType) +} + +func ensureVoteMatch(t *testing.T, voteCh <-chan tmpubsub.Message, height int64, round int32, hash []byte, voteType tmproto.SignedMsgType) { + t.Helper() + select { + case <-time.After(ensureTimeout): + t.Fatal("Timeout expired while waiting for NewVote event") + case msg := <-voteCh: + voteEvent, ok := msg.Data().(types.EventDataVote) + require.True(t, ok, "expected a EventDataVote, got %T. Wrong subscription channel?", + msg.Data()) + + vote := voteEvent.Vote + assert.Equal(t, height, vote.Height, "expected height %d, but got %d", height, vote.Height) + assert.Equal(t, round, vote.Round, "expected round %d, but got %d", round, vote.Round) + assert.Equal(t, voteType, vote.Type, "expected type %s, but got %s", voteType, vote.Type) + if hash == nil { + require.Nil(t, vote.BlockID.Hash, "Expected prevote to be for nil, got %X", vote.BlockID.Hash) + } else { + require.True(t, bytes.Equal(vote.BlockID.Hash, hash), "Expected prevote to be for %X, got %X", hash, vote.BlockID.Hash) + } + } +} + func ensurePrecommitTimeout(ch <-chan tmpubsub.Message) { select { case <-time.After(ensureTimeout): diff --git a/consensus/mempool_test.go b/consensus/mempool_test.go index 73b150093..50d941e59 100644 --- a/consensus/mempool_test.go +++ b/consensus/mempool_test.go @@ -256,3 +256,22 @@ func (app *CounterApplication) Commit() abci.ResponseCommit { binary.BigEndian.PutUint64(hash, uint64(app.txCount)) return abci.ResponseCommit{Data: hash} } + +func (app *CounterApplication) PrepareProposal( + req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { + txs := make([][]byte, 0, len(req.Txs)) + var totalBytes int64 + for _, tx := range req.Txs { + totalBytes += int64(len(tx)) + if totalBytes > req.MaxTxBytes { + break + } + txs = append(txs, tx) + } + return abci.ResponsePrepareProposal{Txs: txs} +} + +func (app *CounterApplication) ProcessProposal( + req abci.RequestProcessProposal) abci.ResponseProcessProposal { + return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT} +} diff --git a/consensus/metrics.gen.go b/consensus/metrics.gen.go index e627dee57..bb9b068dd 100644 --- a/consensus/metrics.gen.go +++ b/consensus/metrics.gen.go @@ -162,6 +162,30 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "full_prevote_delay", Help: "Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted.", }, append(labels, "proposer_address")).With(labelsAndValues...), + ProposalReceiveCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "proposal_receive_count", + Help: "ProposalReceiveCount is the total number of proposals received by this node since process start. The metric is annotated by the status of the proposal from the application, either 'accepted' or 'rejected'.", + }, append(labels, "status")).With(labelsAndValues...), + ProposalCreateCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "proposal_create_count", + Help: "ProposalCreationCount is the total number of proposals created by this node since process start.", + }, labels).With(labelsAndValues...), + RoundVotingPowerPercent: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "round_voting_power_percent", + Help: "RoundVotingPowerPercent is the percentage of the total voting power received with a round. The value begins at 0 for each round and approaches 1.0 as additional voting power is observed. The metric is labeled by vote type.", + }, labels).With(labelsAndValues...), + LateVotes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "late_votes", + Help: "LateVotes stores the number of votes that were received by this node that correspond to earlier heights and rounds than this node is currently in.", + }, labels).With(labelsAndValues...), } } @@ -191,5 +215,9 @@ func NopMetrics() *Metrics { BlockGossipPartsReceived: discard.NewCounter(), QuorumPrevoteDelay: discard.NewGauge(), FullPrevoteDelay: discard.NewGauge(), + ProposalReceiveCount: discard.NewCounter(), + ProposalCreateCount: discard.NewCounter(), + RoundVotingPowerPercent: discard.NewGauge(), + LateVotes: discard.NewCounter(), } } diff --git a/consensus/metrics.go b/consensus/metrics.go index 2a82d732f..ce6de0a3c 100644 --- a/consensus/metrics.go +++ b/consensus/metrics.go @@ -6,6 +6,7 @@ import ( "github.com/go-kit/kit/metrics" cstypes "github.com/tendermint/tendermint/consensus/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) @@ -92,6 +93,26 @@ type Metrics struct { // of the voting power on the network issued prevotes. //metrics:Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted. FullPrevoteDelay metrics.Gauge `metrics_labels:"proposer_address"` + + // ProposalReceiveCount is the total number of proposals received by this node + // since process start. + // The metric is annotated by the status of the proposal from the application, + // either 'accepted' or 'rejected'. + ProposalReceiveCount metrics.Counter `metrics_labels:"status"` + + // ProposalCreationCount is the total number of proposals created by this node + // since process start. + ProposalCreateCount metrics.Counter + + // RoundVotingPowerPercent is the percentage of the total voting power received + // with a round. The value begins at 0 for each round and approaches 1.0 as + // additional voting power is observed. The metric is labeled by vote type. + RoundVotingPowerPercent metrics.Gauge + + // LateVotes stores the number of votes that were received by this node that + // correspond to earlier heights and rounds than this node is currently + // in. + LateVotes metrics.Counter } // RecordConsMetrics uses for recording the block related metrics during fast-sync. @@ -102,12 +123,31 @@ func (m *Metrics) RecordConsMetrics(block *types.Block) { m.CommittedHeight.Set(float64(block.Height)) } +func (m *Metrics) MarkProposalProcessed(accepted bool) { + status := "accepted" + if !accepted { + status = "rejected" + } + m.ProposalReceiveCount.With("status", status).Add(1) +} + +func (m *Metrics) MarkVoteReceived(vt tmproto.SignedMsgType, power, totalPower int64) { + p := float64(power) / float64(totalPower) + n := strings.ToLower(strings.TrimPrefix(vt.String(), "SIGNED_MSG_TYPE_")) + m.RoundVotingPowerPercent.With("vote_type", n).Add(p) +} + func (m *Metrics) MarkRound(r int32, st time.Time) { m.Rounds.Set(float64(r)) roundTime := time.Since(st).Seconds() m.RoundDurationSeconds.Observe(roundTime) } +func (m *Metrics) MarkLateVote(vt tmproto.SignedMsgType) { + n := strings.ToLower(strings.TrimPrefix(vt.String(), "SIGNED_MSG_TYPE_")) + m.LateVotes.With("vote_type", n).Add(1) +} + func (m *Metrics) MarkStep(s cstypes.RoundStepType) { if !m.stepStart.IsZero() { stepTime := time.Since(m.stepStart).Seconds() diff --git a/consensus/reactor_test.go b/consensus/reactor_test.go index 0e6ea0373..8235b2bf8 100644 --- a/consensus/reactor_test.go +++ b/consensus/reactor_test.go @@ -190,7 +190,8 @@ func TestReactorWithEvidence(t *testing.T) { // mock the evidence pool // everyone includes evidence of another double signing vIdx := (i + 1) % nValidators - ev := types.NewMockDuplicateVoteEvidenceWithValidator(1, defaultTestTime, privVals[vIdx], config.ChainID()) + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(1, defaultTestTime, privVals[vIdx], config.ChainID()) + require.NoError(t, err) evpool := &statemocks.EvidencePool{} evpool.On("CheckEvidence", mock.AnythingOfType("types.EvidenceList")).Return(nil) evpool.On("PendingEvidence", mock.AnythingOfType("int64")).Return([]types.Evidence{ @@ -207,7 +208,7 @@ func TestReactorWithEvidence(t *testing.T) { eventBus := types.NewEventBus() eventBus.SetLogger(log.TestingLogger().With("module", "events")) - err := eventBus.Start() + err = eventBus.Start() require.NoError(t, err) cs.SetEventBus(eventBus) diff --git a/consensus/replay.go b/consensus/replay.go index 213bf39f1..6d0056b6a 100644 --- a/consensus/replay.go +++ b/consensus/replay.go @@ -307,12 +307,12 @@ func (h *Handshaker) ReplayBlocks( } validatorSet := types.NewValidatorSet(validators) nextVals := types.TM2PB.ValidatorUpdates(validatorSet) - csParams := types.TM2PB.ConsensusParams(h.genDoc.ConsensusParams) + pbparams := h.genDoc.ConsensusParams.ToProto() req := abci.RequestInitChain{ Time: h.genDoc.GenesisTime, ChainId: h.genDoc.ChainID, InitialHeight: h.genDoc.InitialHeight, - ConsensusParams: csParams, + ConsensusParams: &pbparams, Validators: nextVals, AppStateBytes: h.genDoc.AppState, } @@ -344,8 +344,8 @@ func (h *Handshaker) ReplayBlocks( } if res.ConsensusParams != nil { - state.ConsensusParams = types.UpdateConsensusParams(state.ConsensusParams, res.ConsensusParams) - state.Version.Consensus.App = state.ConsensusParams.Version.AppVersion + state.ConsensusParams = state.ConsensusParams.Update(res.ConsensusParams) + state.Version.Consensus.App = state.ConsensusParams.Version.App } // We update the last results hash with the empty hash, to conform with RFC-6962. state.LastResultsHash = merkle.HashFromByteSlices(nil) diff --git a/consensus/replay_test.go b/consensus/replay_test.go index 7590123b0..e4ecf785d 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -22,6 +22,7 @@ import ( cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/crypto" cryptoenc "github.com/tendermint/tendermint/crypto/encoding" + "github.com/tendermint/tendermint/internal/test" "github.com/tendermint/tendermint/libs/log" tmrand "github.com/tendermint/tendermint/libs/rand" mempl "github.com/tendermint/tendermint/mempool" @@ -363,9 +364,11 @@ func TestSimulateValidatorsChange(t *testing.T) { require.NoError(t, err) newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx1, nil, mempl.TxInfo{}) - assert.Nil(t, err) - propBlock, _ := css[0].createProposalBlock() // changeProposer(t, cs1, vs2) - propBlockParts := propBlock.MakePartSet(partSize) + assert.NoError(t, err) + propBlock, err := css[0].createProposalBlock() // changeProposer(t, cs1, vs2) + require.NoError(t, err) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} proposal := types.NewProposal(vss[1].Height, round, -1, blockID) @@ -393,9 +396,11 @@ func TestSimulateValidatorsChange(t *testing.T) { require.NoError(t, err) updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25) err = assertMempool(css[0].txNotifier).CheckTx(updateValidatorTx1, nil, mempl.TxInfo{}) - assert.Nil(t, err) - propBlock, _ = css[0].createProposalBlock() // changeProposer(t, cs1, vs2) - propBlockParts = propBlock.MakePartSet(partSize) + assert.NoError(t, err) + propBlock, err = css[0].createProposalBlock() // changeProposer(t, cs1, vs2) + require.NoError(t, err) + propBlockParts, err = propBlock.MakePartSet(partSize) + require.NoError(t, err) blockID = types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} proposal = types.NewProposal(vss[2].Height, round, -1, blockID) @@ -430,9 +435,11 @@ func TestSimulateValidatorsChange(t *testing.T) { require.NoError(t, err) newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx3, nil, mempl.TxInfo{}) - assert.Nil(t, err) - propBlock, _ = css[0].createProposalBlock() // changeProposer(t, cs1, vs2) - propBlockParts = propBlock.MakePartSet(partSize) + assert.NoError(t, err) + propBlock, err = css[0].createProposalBlock() // changeProposer(t, cs1, vs2) + require.NoError(t, err) + propBlockParts, err = propBlock.MakePartSet(partSize) + require.NoError(t, err) blockID = types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} newVss := make([]*validatorStub, nVals+1) copy(newVss, vss[:nVals+1]) @@ -505,9 +512,11 @@ func TestSimulateValidatorsChange(t *testing.T) { incrementHeight(vss...) removeValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, 0) err = assertMempool(css[0].txNotifier).CheckTx(removeValidatorTx3, nil, mempl.TxInfo{}) - assert.Nil(t, err) - propBlock, _ = css[0].createProposalBlock() // changeProposer(t, cs1, vs2) - propBlockParts = propBlock.MakePartSet(partSize) + assert.NoError(t, err) + propBlock, err = css[0].createProposalBlock() // changeProposer(t, cs1, vs2) + require.NoError(t, err) + propBlockParts, err = propBlock.MakePartSet(partSize) + require.NoError(t, err) blockID = types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} newVss = make([]*validatorStub, nVals+3) copy(newVss, vss[:nVals+3]) @@ -666,7 +675,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin config = sim.Config chain = append([]*types.Block{}, sim.Chain...) // copy chain commits = sim.Commits - store = newMockBlockStore(config, genesisState.ConsensusParams) + store = newMockBlockStore(t, config, genesisState.ConsensusParams) } else { // test single node testConfig := ResetConfig(fmt.Sprintf("%s_%v_s", t.Name(), mode)) defer os.RemoveAll(testConfig.RootDir) @@ -691,7 +700,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin require.NoError(t, err) pubKey, err := privVal.GetPubKey() require.NoError(t, err) - stateDB, genesisState, store = stateAndStore(config, pubKey, kvstore.ProtocolVersion) + stateDB, genesisState, store = stateAndStore(t, config, pubKey, kvstore.ProtocolVersion) } stateStore := sm.NewStore(stateDB, sm.StoreOptions{ @@ -702,7 +711,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin state := genesisState.Copy() // run the chain through state.ApplyBlock to build up the tendermint state - state = buildTMStateFromChain(config, stateStore, state, chain, nBlocks, mode) + state = buildTMStateFromChain(t, config, stateStore, state, chain, nBlocks, mode) latestAppHash := state.AppHash // make a new client creator @@ -720,7 +729,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin }) err := stateStore.Save(genesisState) require.NoError(t, err) - buildAppStateFromChain(proxyApp, stateStore, genesisState, chain, nBlocks, mode) + buildAppStateFromChain(t, proxyApp, stateStore, genesisState, chain, nBlocks, mode) } // Prune block store if requested @@ -780,19 +789,19 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin } } -func applyBlock(stateStore sm.Store, st sm.State, blk *types.Block, proxyApp proxy.AppConns) sm.State { +func applyBlock(t *testing.T, stateStore sm.Store, st sm.State, blk *types.Block, proxyApp proxy.AppConns) sm.State { testPartSize := types.BlockPartSizeBytes blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), mempool, evpool) - blkID := types.BlockID{Hash: blk.Hash(), PartSetHeader: blk.MakePartSet(testPartSize).Header()} + bps, err := blk.MakePartSet(testPartSize) + require.NoError(t, err) + blkID := types.BlockID{Hash: blk.Hash(), PartSetHeader: bps.Header()} newState, _, err := blockExec.ApplyBlock(st, blkID, blk) - if err != nil { - panic(err) - } + require.NoError(t, err) return newState } -func buildAppStateFromChain(proxyApp proxy.AppConns, stateStore sm.Store, +func buildAppStateFromChain(t *testing.T, proxyApp proxy.AppConns, stateStore sm.Store, state sm.State, chain []*types.Block, nBlocks int, mode uint) { // start a new app without handshake, play nBlocks blocks if err := proxyApp.Start(); err != nil { @@ -814,18 +823,18 @@ func buildAppStateFromChain(proxyApp proxy.AppConns, stateStore sm.Store, case 0: for i := 0; i < nBlocks; i++ { block := chain[i] - state = applyBlock(stateStore, state, block, proxyApp) + state = applyBlock(t, stateStore, state, block, proxyApp) } case 1, 2, 3: for i := 0; i < nBlocks-1; i++ { block := chain[i] - state = applyBlock(stateStore, state, block, proxyApp) + state = applyBlock(t, stateStore, state, block, proxyApp) } if mode == 2 || mode == 3 { // update the kvstore height and apphash // as if we ran commit but not - state = applyBlock(stateStore, state, chain[nBlocks-1], proxyApp) + state = applyBlock(t, stateStore, state, chain[nBlocks-1], proxyApp) } default: panic(fmt.Sprintf("unknown mode %v", mode)) @@ -834,6 +843,7 @@ func buildAppStateFromChain(proxyApp proxy.AppConns, stateStore sm.Store, } func buildTMStateFromChain( + t *testing.T, config *cfg.Config, stateStore sm.Store, state sm.State, @@ -864,19 +874,19 @@ func buildTMStateFromChain( case 0: // sync right up for _, block := range chain { - state = applyBlock(stateStore, state, block, proxyApp) + state = applyBlock(t, stateStore, state, block, proxyApp) } case 1, 2, 3: // sync up to the penultimate as if we stored the block. // whether we commit or not depends on the appHash for _, block := range chain[:len(chain)-1] { - state = applyBlock(stateStore, state, block, proxyApp) + state = applyBlock(t, stateStore, state, block, proxyApp) } // apply the final block to a state copy so we can // get the right next appHash but keep the state back - applyBlock(stateStore, state, chain[len(chain)-1], proxyApp) + applyBlock(t, stateStore, state, chain[len(chain)-1], proxyApp) default: panic(fmt.Sprintf("unknown mode %v", mode)) } @@ -895,14 +905,16 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) { const appVersion = 0x0 pubKey, err := privVal.GetPubKey() require.NoError(t, err) - stateDB, state, store := stateAndStore(config, pubKey, appVersion) + stateDB, state, store := stateAndStore(t, config, pubKey, appVersion) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) genDoc, _ := sm.MakeGenesisDocFromFile(config.GenesisFile()) state.LastValidators = state.Validators.Copy() // mode = 0 for committing all the blocks - blocks := makeBlocks(3, &state, privVal) + blocks, err := test.MakeBlocks(3, state, []types.PrivValidator{privVal}) + require.NoError(t, err) + store.chain = blocks // 2. Tendermint must panic if app returns wrong hash for the first block @@ -954,52 +966,6 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) { } } -func makeBlocks(n int, state *sm.State, privVal types.PrivValidator) []*types.Block { - blocks := make([]*types.Block, 0) - - var ( - prevBlock *types.Block - prevBlockMeta *types.BlockMeta - ) - - appHeight := byte(0x01) - for i := 0; i < n; i++ { - height := int64(i + 1) - - block, parts := makeBlock(*state, prevBlock, prevBlockMeta, privVal, height) - blocks = append(blocks, block) - - prevBlock = block - prevBlockMeta = types.NewBlockMeta(block, parts) - - // update state - state.AppHash = []byte{appHeight} - appHeight++ - state.LastBlockHeight = height - } - - return blocks -} - -func makeBlock(state sm.State, lastBlock *types.Block, lastBlockMeta *types.BlockMeta, - privVal types.PrivValidator, height int64) (*types.Block, *types.PartSet) { - - lastCommit := types.NewCommit(height-1, 0, types.BlockID{}, nil) - if height > 1 { - vote, _ := types.MakeVote( - lastBlock.Header.Height, - lastBlockMeta.BlockID, - state.Validators, - privVal, - lastBlock.Header.ChainID, - time.Now()) - lastCommit = types.NewCommit(vote.Height, vote.Round, - lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()}) - } - - return state.MakeBlock(height, []types.Tx{}, lastCommit, nil, state.Validators.GetProposer().Address) -} - type badApp struct { abci.BaseApplication numBlocks byte @@ -1151,19 +1117,21 @@ func readPieceFromWAL(msg *TimedWALMessage) interface{} { // fresh state and mock store func stateAndStore( + t *testing.T, config *cfg.Config, pubKey crypto.PubKey, - appVersion uint64) (dbm.DB, sm.State, *mockBlockStore) { + appVersion uint64, +) (dbm.DB, sm.State, *mockBlockStore) { stateDB := dbm.NewMemDB() stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) - state, _ := sm.MakeGenesisStateFromFile(config.GenesisFile()) + state, err := sm.MakeGenesisStateFromFile(config.GenesisFile()) + require.NoError(t, err) state.Version.Consensus.App = appVersion - store := newMockBlockStore(config, state.ConsensusParams) - if err := stateStore.Save(state); err != nil { - panic(err) - } + store := newMockBlockStore(t, config, state.ConsensusParams) + require.NoError(t, stateStore.Save(state)) + return stateDB, state, store } @@ -1172,15 +1140,20 @@ func stateAndStore( type mockBlockStore struct { config *cfg.Config - params tmproto.ConsensusParams + params types.ConsensusParams chain []*types.Block commits []*types.Commit base int64 + t *testing.T } // TODO: NewBlockStore(db.NewMemDB) ... -func newMockBlockStore(config *cfg.Config, params tmproto.ConsensusParams) *mockBlockStore { - return &mockBlockStore{config, params, nil, nil, 0} +func newMockBlockStore(t *testing.T, config *cfg.Config, params types.ConsensusParams) *mockBlockStore { + return &mockBlockStore{ + config: config, + params: params, + t: t, + } } func (bs *mockBlockStore) Height() int64 { return int64(len(bs.chain)) } @@ -1193,8 +1166,10 @@ func (bs *mockBlockStore) LoadBlockByHash(hash []byte) *types.Block { } func (bs *mockBlockStore) LoadBlockMeta(height int64) *types.BlockMeta { block := bs.chain[height-1] + bps, err := block.MakePartSet(types.BlockPartSizeBytes) + require.NoError(bs.t, err) return &types.BlockMeta{ - BlockID: types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(types.BlockPartSizeBytes).Header()}, + BlockID: types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}, Header: block.Header, } } @@ -1233,7 +1208,7 @@ func TestHandshakeUpdatesValidators(t *testing.T) { privVal := privval.LoadFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()) pubKey, err := privVal.GetPubKey() require.NoError(t, err) - stateDB, state, store := stateAndStore(config, pubKey, 0x0) + stateDB, state, store := stateAndStore(t, config, pubKey, 0x0) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) diff --git a/consensus/state.go b/consensus/state.go index 9bd1877d9..949742d12 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1140,8 +1140,18 @@ func (cs *State) defaultDecideProposal(height int64, round int32) { block, blockParts = cs.ValidBlock, cs.ValidBlockParts } else { // Create a new proposal block from state/txs from the mempool. - block, blockParts = cs.createProposalBlock() - if block == nil { + var err error + block, err = cs.createProposalBlock() + if err != nil { + cs.Logger.Error("unable to create proposal block", "error", err) + return + } else if block == nil { + panic("Method createProposalBlock should not provide a nil block without errors") + } + cs.metrics.ProposalCreateCount.Add(1) + blockParts, err = block.MakePartSet(types.BlockPartSizeBytes) + if err != nil { + cs.Logger.Error("unable to create proposal block part set", "error", err) return } } @@ -1196,9 +1206,9 @@ func (cs *State) isProposalComplete() bool { // // NOTE: keep it side-effect free for clarity. // CONTRACT: cs.privValidator is not nil. -func (cs *State) createProposalBlock() (block *types.Block, blockParts *types.PartSet) { +func (cs *State) createProposalBlock() (*types.Block, error) { if cs.privValidator == nil { - panic("entered createProposalBlock with privValidator being nil") + return nil, errors.New("entered createProposalBlock with privValidator being nil") } var commit *types.Commit @@ -1213,20 +1223,22 @@ func (cs *State) createProposalBlock() (block *types.Block, blockParts *types.Pa commit = cs.LastCommit.MakeCommit() default: // This shouldn't happen. - cs.Logger.Error("propose step; cannot propose anything without commit for the previous block") - return + return nil, errors.New("propose step; cannot propose anything without commit for the previous block") } if cs.privValidatorPubKey == nil { // If this node is a validator & proposer in the current round, it will // miss the opportunity to create a block. - cs.Logger.Error("propose step; empty priv validator public key", "err", errPubKeyIsNotSet) - return + return nil, fmt.Errorf("propose step; empty priv validator public key, error: %w", errPubKeyIsNotSet) } proposerAddr := cs.privValidatorPubKey.Address() - return cs.blockExec.CreateProposalBlock(cs.Height, cs.state, commit, proposerAddr) + ret, err := cs.blockExec.CreateProposalBlock(cs.Height, cs.state, commit, proposerAddr, cs.LastCommit.GetVotes()) + if err != nil { + panic(err) + } + return ret, nil } // Enter: `timeoutPropose` after entering Propose. @@ -1276,11 +1288,37 @@ func (cs *State) defaultDoPrevote(height int64, round int32) { return } - // Validate proposal block + // Validate proposal block, from Tendermint's perspective err := cs.blockExec.ValidateBlock(cs.state, cs.ProposalBlock) if err != nil { // ProposalBlock is invalid, prevote nil. - logger.Error("prevote step: ProposalBlock is invalid", "err", err) + logger.Error("prevote step: consensus deems this block invalid; prevoting nil", + "err", err) + cs.signAddVote(tmproto.PrevoteType, nil, types.PartSetHeader{}) + return + } + + /* + Before prevoting on the block received from the proposer for the current round and height, + we request the Application, via `ProcessProposal` ABCI call, to confirm that the block is + valid. If the Application does not accept the block, Tendermint prevotes `nil`. + + WARNING: misuse of block rejection by the Application can seriously compromise Tendermint's + liveness properties. Please see `PrepareProosal`-`ProcessProposal` coherence and determinism + properties in the ABCI++ specification. + */ + isAppValid, err := cs.blockExec.ProcessProposal(cs.ProposalBlock, cs.state) + if err != nil { + panic(fmt.Sprintf( + "state machine returned an error (%v) when calling ProcessProposal", err, + )) + } + cs.metrics.MarkProposalProcessed(isAppValid) + + // Vote nil if the Application rejected the block + if !isAppValid { + logger.Error("prevote step: state machine rejected a proposed block; this should not happen:"+ + "the proposer may be misbehaving; prevoting nil", "err", err) cs.signAddVote(tmproto.PrevoteType, nil, types.PartSetHeader{}) return } @@ -2019,6 +2057,10 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error "cs_height", cs.Height, ) + if vote.Height < cs.Height || (vote.Height == cs.Height && vote.Round < cs.Round) { + cs.metrics.MarkLateVote(vote.Type) + } + // A precommit for the previous height? // These come in while we wait timeoutCommit if vote.Height+1 == cs.Height && vote.Type == tmproto.PrecommitType { @@ -2063,6 +2105,11 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error // Either duplicate, or error upon cs.Votes.AddByIndex() return } + if vote.Round == cs.Round { + vals := cs.state.Validators + _, val := vals.GetByIndex(vote.ValidatorIndex) + cs.metrics.MarkVoteReceived(vote.Type, val.VotingPower, vals.TotalVotingPower()) + } if err := cs.eventBus.PublishEventVote(types.EventDataVote{Vote: vote}); err != nil { return added, err @@ -2224,9 +2271,10 @@ func (cs *State) signVote( func (cs *State) voteTime() time.Time { now := tmtime.Now() minVoteTime := now + // Minimum time increment between blocks + const timeIota = time.Millisecond // TODO: We should remove next line in case we don't vote for v in case cs.ProposalBlock == nil, // even if cs.LockedBlock != nil. See https://github.com/tendermint/tendermint/tree/main/spec/. - timeIota := time.Duration(cs.state.ConsensusParams.Block.TimeIotaMs) * time.Millisecond if cs.LockedBlock != nil { // See the BFT time spec // https://github.com/tendermint/tendermint/blob/main/spec/consensus/bft-time.md diff --git a/consensus/state_test.go b/consensus/state_test.go index 895407ed7..3f795d708 100644 --- a/consensus/state_test.go +++ b/consensus/state_test.go @@ -8,11 +8,15 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/abci/example/kvstore" + abci "github.com/tendermint/tendermint/abci/types" + abcimocks "github.com/tendermint/tendermint/abci/types/mocks" cstypes "github.com/tendermint/tendermint/consensus/types" "github.com/tendermint/tendermint/crypto/tmhash" + tmbytes "github.com/tendermint/tendermint/libs/bytes" "github.com/tendermint/tendermint/libs/log" tmpubsub "github.com/tendermint/tendermint/libs/pubsub" tmrand "github.com/tendermint/tendermint/libs/rand" @@ -191,7 +195,8 @@ func TestStateBadProposal(t *testing.T) { proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) voteCh := subscribe(cs1.eventBus, types.EventQueryVote) - propBlock, _ := cs1.createProposalBlock() // changeProposer(t, cs1, vs2) + propBlock, err := cs1.createProposalBlock() // changeProposer(t, cs1, vs2) + require.NoError(t, err) // make the second validator the proposer by incrementing round round++ @@ -204,7 +209,8 @@ func TestStateBadProposal(t *testing.T) { } stateHash[0] = (stateHash[0] + 1) % 255 propBlock.AppHash = stateHash - propBlockParts := propBlock.MakePartSet(partSize) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} proposal := types.NewProposal(vs2.Height, round, -1, blockID) p := proposal.ToProto() @@ -230,13 +236,19 @@ func TestStateBadProposal(t *testing.T) { validatePrevote(t, cs1, round, vss[0], nil) // add bad prevote from vs2 and wait for it - signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2) + bps, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + + signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), bps.Header(), vs2) ensurePrevote(voteCh, height, round) // wait for precommit ensurePrecommit(voteCh, height, round) validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - signAddVotes(cs1, tmproto.PrecommitType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2) + + bps2, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + signAddVotes(cs1, tmproto.PrecommitType, propBlock.Hash(), bps2.Header(), vs2) } func TestStateOversizedBlock(t *testing.T) { @@ -250,7 +262,8 @@ func TestStateOversizedBlock(t *testing.T) { timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) voteCh := subscribe(cs1.eventBus, types.EventQueryVote) - propBlock, _ := cs1.createProposalBlock() + propBlock, err := cs1.createProposalBlock() + require.NoError(t, err) propBlock.Data.Txs = []types.Tx{tmrand.Bytes(2001)} propBlock.Header.DataHash = propBlock.Data.Hash() @@ -258,7 +271,8 @@ func TestStateOversizedBlock(t *testing.T) { round++ incrementRound(vss[1:]...) - propBlockParts := propBlock.MakePartSet(partSize) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} proposal := types.NewProposal(height, round, -1, blockID) p := proposal.ToProto() @@ -290,11 +304,18 @@ func TestStateOversizedBlock(t *testing.T) { // precommit on it ensurePrevote(voteCh, height, round) validatePrevote(t, cs1, round, vss[0], nil) - signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2) + + bps, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + + signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), bps.Header(), vs2) ensurePrevote(voteCh, height, round) ensurePrecommit(voteCh, height, round) validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - signAddVotes(cs1, tmproto.PrecommitType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2) + + bps2, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + signAddVotes(cs1, tmproto.PrecommitType, propBlock.Hash(), bps2.Header(), vs2) } //---------------------------------------------------------------------------------------------------- @@ -466,9 +487,7 @@ func TestStateLockNoPOL(t *testing.T) { rs := cs1.GetRoundState() - if rs.ProposalBlock != nil { - panic("Expected proposal block to be nil") - } + require.Nil(t, rs.ProposalBlock, "Expected proposal block to be nil") // wait to finish prevote ensurePrevote(voteCh, height, round) @@ -476,7 +495,10 @@ func TestStateLockNoPOL(t *testing.T) { validatePrevote(t, cs1, round, vss[0], rs.LockedBlock.Hash()) // add a conflicting prevote from the other validator - signAddVotes(cs1, tmproto.PrevoteType, hash, rs.LockedBlock.MakePartSet(partSize).Header(), vs2) + bps, err := rs.LockedBlock.MakePartSet(partSize) + require.NoError(t, err) + + signAddVotes(cs1, tmproto.PrevoteType, hash, bps.Header(), vs2) ensurePrevote(voteCh, height, round) // now we're going to enter prevote again, but with invalid args @@ -489,7 +511,9 @@ func TestStateLockNoPOL(t *testing.T) { validatePrecommit(t, cs1, round, 0, vss[0], nil, theBlockHash) // add conflicting precommit from vs2 - signAddVotes(cs1, tmproto.PrecommitType, hash, rs.LockedBlock.MakePartSet(partSize).Header(), vs2) + bps2, err := rs.LockedBlock.MakePartSet(partSize) + require.NoError(t, err) + signAddVotes(cs1, tmproto.PrecommitType, hash, bps2.Header(), vs2) ensurePrecommit(voteCh, height, round) // (note we're entering precommit for a second time this round, but with invalid args @@ -519,7 +543,9 @@ func TestStateLockNoPOL(t *testing.T) { ensurePrevote(voteCh, height, round) // prevote validatePrevote(t, cs1, round, vss[0], rs.LockedBlock.Hash()) - signAddVotes(cs1, tmproto.PrevoteType, hash, rs.ProposalBlock.MakePartSet(partSize).Header(), vs2) + bps0, err := rs.ProposalBlock.MakePartSet(partSize) + require.NoError(t, err) + signAddVotes(cs1, tmproto.PrevoteType, hash, bps0.Header(), vs2) ensurePrevote(voteCh, height, round) ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) @@ -527,11 +553,13 @@ func TestStateLockNoPOL(t *testing.T) { validatePrecommit(t, cs1, round, 0, vss[0], nil, theBlockHash) // precommit nil but be locked on proposal + bps1, err := rs.ProposalBlock.MakePartSet(partSize) + require.NoError(t, err) signAddVotes( cs1, tmproto.PrecommitType, hash, - rs.ProposalBlock.MakePartSet(partSize).Header(), + bps1.Header(), vs2) // NOTE: conflicting precommits at same height ensurePrecommit(voteCh, height, round) @@ -539,7 +567,7 @@ func TestStateLockNoPOL(t *testing.T) { cs2, _ := randState(2) // needed so generated block is different than locked block // before we time out into new round, set next proposal block - prop, propBlock := decideProposal(cs2, vs2, vs2.Height, vs2.Round+1) + prop, propBlock := decideProposal(t, cs2, vs2, vs2.Height, vs2.Round+1) if prop == nil || propBlock == nil { t.Fatal("Failed to create proposal block with vs2") } @@ -555,7 +583,9 @@ func TestStateLockNoPOL(t *testing.T) { // now we're on a new round and not the proposer // so set the proposal block - if err := cs1.SetProposalAndBlock(prop, propBlock, propBlock.MakePartSet(partSize), ""); err != nil { + bps3, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + if err := cs1.SetProposalAndBlock(prop, propBlock, bps3, ""); err != nil { t.Fatal(err) } @@ -565,18 +595,23 @@ func TestStateLockNoPOL(t *testing.T) { validatePrevote(t, cs1, 3, vss[0], cs1.LockedBlock.Hash()) // prevote for proposed block - signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2) + bps4, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + + signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), bps4.Header(), vs2) ensurePrevote(voteCh, height, round) ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) ensurePrecommit(voteCh, height, round) validatePrecommit(t, cs1, round, 0, vss[0], nil, theBlockHash) // precommit nil but locked on proposal + bps5, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) signAddVotes( cs1, tmproto.PrecommitType, propBlock.Hash(), - propBlock.MakePartSet(partSize).Header(), + bps5.Header(), vs2) // NOTE: conflicting precommits at same height ensurePrecommit(voteCh, height, round) } @@ -631,11 +666,13 @@ func TestStateLockPOLRelock(t *testing.T) { // before we timeout to the new round set the new proposal cs2 := newState(cs1.state, vs2, kvstore.NewApplication()) - prop, propBlock := decideProposal(cs2, vs2, vs2.Height, vs2.Round+1) + prop, propBlock := decideProposal(t, cs2, vs2, vs2.Height, vs2.Round+1) if prop == nil || propBlock == nil { t.Fatal("Failed to create proposal block with vs2") } - propBlockParts := propBlock.MakePartSet(partSize) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + propBlockHash := propBlock.Hash() require.NotEqual(t, propBlockHash, theBlockHash) @@ -728,8 +765,9 @@ func TestStateLockPOLUnlock(t *testing.T) { signAddVotes(cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs3) // before we time out into new round, set next proposal block - prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1) - propBlockParts := propBlock.MakePartSet(partSize) + prop, propBlock := decideProposal(t, cs1, vs2, vs2.Height, vs2.Round+1) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) // timeout to new round ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) @@ -816,11 +854,13 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) { // before we timeout to the new round set the new proposal cs2 := newState(cs1.state, vs2, kvstore.NewApplication()) - prop, propBlock := decideProposal(cs2, vs2, vs2.Height, vs2.Round+1) + prop, propBlock := decideProposal(t, cs2, vs2, vs2.Height, vs2.Round+1) if prop == nil || propBlock == nil { t.Fatal("Failed to create proposal block with vs2") } - secondBlockParts := propBlock.MakePartSet(partSize) + secondBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + secondBlockHash := propBlock.Hash() require.NotEqual(t, secondBlockHash, firstBlockHash) @@ -860,11 +900,12 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) { // before we timeout to the new round set the new proposal cs3 := newState(cs1.state, vs3, kvstore.NewApplication()) - prop, propBlock = decideProposal(cs3, vs3, vs3.Height, vs3.Round+1) + prop, propBlock = decideProposal(t, cs3, vs3, vs3.Height, vs3.Round+1) if prop == nil || propBlock == nil { t.Fatal("Failed to create proposal block with vs2") } - thirdPropBlockParts := propBlock.MakePartSet(partSize) + thirdPropBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) thirdPropBlockHash := propBlock.Hash() require.NotEqual(t, secondBlockHash, thirdPropBlockHash) @@ -928,7 +969,10 @@ func TestStateLockPOLSafety1(t *testing.T) { validatePrevote(t, cs1, round, vss[0], propBlock.Hash()) // the others sign a polka but we don't see it - prevotes := signVotes(tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2, vs3, vs4) + bps, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + + prevotes := signVotes(tmproto.PrevoteType, propBlock.Hash(), bps.Header(), vs2, vs3, vs4) t.Logf("old prop hash %v", fmt.Sprintf("%X", propBlock.Hash())) @@ -941,9 +985,10 @@ func TestStateLockPOLSafety1(t *testing.T) { t.Log("### ONTO ROUND 1") - prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1) + prop, propBlock := decideProposal(t, cs1, vs2, vs2.Height, vs2.Round+1) propBlockHash := propBlock.Hash() - propBlockParts := propBlock.MakePartSet(partSize) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) incrementRound(vs2, vs3, vs4) @@ -1037,18 +1082,20 @@ func TestStateLockPOLSafety2(t *testing.T) { // the block for R0: gets polkad but we miss it // (even though we signed it, shhh) - _, propBlock0 := decideProposal(cs1, vss[0], height, round) + _, propBlock0 := decideProposal(t, cs1, vss[0], height, round) propBlockHash0 := propBlock0.Hash() - propBlockParts0 := propBlock0.MakePartSet(partSize) + propBlockParts0, err := propBlock0.MakePartSet(partSize) + require.NoError(t, err) propBlockID0 := types.BlockID{Hash: propBlockHash0, PartSetHeader: propBlockParts0.Header()} // the others sign a polka but we don't see it prevotes := signVotes(tmproto.PrevoteType, propBlockHash0, propBlockParts0.Header(), vs2, vs3, vs4) // the block for round 1 - prop1, propBlock1 := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1) + prop1, propBlock1 := decideProposal(t, cs1, vs2, vs2.Height, vs2.Round+1) propBlockHash1 := propBlock1.Hash() - propBlockParts1 := propBlock1.MakePartSet(partSize) + propBlockParts1, err := propBlock1.MakePartSet(partSize) + require.NoError(t, err) incrementRound(vs2, vs3, vs4) @@ -1146,7 +1193,9 @@ func TestProposeValidBlock(t *testing.T) { validatePrevote(t, cs1, round, vss[0], propBlockHash) // the others sign a polka - signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propBlock.MakePartSet(partSize).Header(), vs2, vs3, vs4) + bps, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, bps.Header(), vs2, vs3, vs4) ensurePrecommit(voteCh, height, round) // we should have precommitted @@ -1230,7 +1279,8 @@ func TestSetValidBlockOnDelayedPrevote(t *testing.T) { rs := cs1.GetRoundState() propBlock := rs.ProposalBlock propBlockHash := propBlock.Hash() - propBlockParts := propBlock.MakePartSet(partSize) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) ensurePrevote(voteCh, height, round) validatePrevote(t, cs1, round, vss[0], propBlockHash) @@ -1296,9 +1346,10 @@ func TestSetValidBlockOnDelayedProposal(t *testing.T) { ensurePrevote(voteCh, height, round) validatePrevote(t, cs1, round, vss[0], nil) - prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1) + prop, propBlock := decideProposal(t, cs1, vs2, vs2.Height, vs2.Round+1) propBlockHash := propBlock.Hash() - propBlockParts := propBlock.MakePartSet(partSize) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) // vs2, vs3 and vs4 send prevote for propBlock signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4) @@ -1321,6 +1372,55 @@ func TestSetValidBlockOnDelayedProposal(t *testing.T) { assert.True(t, rs.ValidRound == round) } +func TestProcessProposalAccept(t *testing.T) { + for _, testCase := range []struct { + name string + accept bool + expectedNilPrevote bool + }{ + { + name: "accepted block is prevoted", + accept: true, + expectedNilPrevote: false, + }, + { + name: "rejected block is not prevoted", + accept: false, + expectedNilPrevote: true, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + m := abcimocks.NewApplication(t) + status := abci.ResponseProcessProposal_REJECT + if testCase.accept { + status = abci.ResponseProcessProposal_ACCEPT + } + m.On("ProcessProposal", mock.Anything).Return(abci.ResponseProcessProposal{Status: status}) + m.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{}).Maybe() + cs1, _ := randStateWithApp(4, m) + height, round := cs1.Height, cs1.Round + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + var prevoteHash tmbytes.HexBytes + if !testCase.expectedNilPrevote { + prevoteHash = rs.ProposalBlock.Hash() + } + ensurePrevoteMatch(t, voteCh, height, round, prevoteHash) + }) + } +} + // 4 vals, 3 Nil Precommits at P0 // What we want: // P0 waits for timeoutPrecommit before starting next round @@ -1456,9 +1556,10 @@ func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) { newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) - _, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round) + _, propBlock := decideProposal(t, cs1, vs2, vs2.Height, vs2.Round) propBlockHash := propBlock.Hash() - propBlockParts := propBlock.MakePartSet(partSize) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) // start round in which PO is not proposer startTestRound(cs1, height, round) @@ -1489,9 +1590,10 @@ func TestCommitFromPreviousRound(t *testing.T) { validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round) + prop, propBlock := decideProposal(t, cs1, vs2, vs2.Height, vs2.Round) propBlockHash := propBlock.Hash() - propBlockParts := propBlock.MakePartSet(partSize) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) // start round in which PO is not proposer startTestRound(cs1, height, round) @@ -1634,8 +1736,9 @@ func TestResetTimeoutPrecommitUponNewHeight(t *testing.T) { ensureNewBlockHeader(newBlockHeader, height, theBlockHash) - prop, propBlock := decideProposal(cs1, vs2, height+1, 0) - propBlockParts := propBlock.MakePartSet(partSize) + prop, propBlock := decideProposal(t, cs1, vs2, height+1, 0) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { t.Fatal(err) @@ -1756,7 +1859,8 @@ func TestStateHalt1(t *testing.T) { ensureNewProposal(proposalCh, height, round) rs := cs1.GetRoundState() propBlock := rs.ProposalBlock - propBlockParts := propBlock.MakePartSet(partSize) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) ensurePrevote(voteCh, height, round) diff --git a/consensus/types/round_state.go b/consensus/types/round_state.go index 9e67b76c0..7bdd1c101 100644 --- a/consensus/types/round_state.go +++ b/consensus/types/round_state.go @@ -80,6 +80,15 @@ type RoundState struct { LockedBlock *types.Block `json:"locked_block"` LockedBlockParts *types.PartSet `json:"locked_block_parts"` + // The variables below starting with "Valid..." derive their name from + // the algorithm presented in this paper: + // [The latest gossip on BFT consensus](https://arxiv.org/abs/1807.04938). + // Therefore, "Valid...": + // * means that the block or round that the variable refers to has + // received 2/3+ non-`nil` prevotes (a.k.a. a *polka*) + // * has nothing to do with whether the Application returned "Accept" in its + // response to `ProcessProposal`, or "Reject" + // Last known round with POL for non-nil valid block. ValidRound int32 `json:"valid_round"` ValidBlock *types.Block `json:"valid_block"` // Last known block of POL mentioned above. @@ -186,8 +195,8 @@ func (rs *RoundState) StringIndented(indent string) string { %s ProposalBlock: %v %v %s LockedRound: %v %s LockedBlock: %v %v -%s ValidRound: %v -%s ValidBlock: %v %v +%s ValidRound: %v +%s ValidBlock: %v %v %s Votes: %v %s LastCommit: %v %s LastValidators:%v diff --git a/docs/app-dev/abci-cli.md b/docs/app-dev/abci-cli.md index 026c39b95..e5486ee87 100644 --- a/docs/app-dev/abci-cli.md +++ b/docs/app-dev/abci-cli.md @@ -37,7 +37,6 @@ Available Commands: help Help about any command info Get some info about the application query Query the application state - set_option Set an options on the application Flags: --abci string socket or grpc (default "socket") @@ -169,6 +168,14 @@ Try running these commands: -> data: {"size":0} -> data.hex: 0x7B2273697A65223A307D +> prepare_proposal "abc" +-> code: OK +-> log: Succeeded. Tx: abc action: UNMODIFIED + +> process_proposal "abc" +-> code: OK +-> status: ACCEPT + > commit -> code: OK -> data.hex: 0x0000000000000000 @@ -189,6 +196,8 @@ Try running these commands: -> code: OK -> log: exists -> height: 2 +-> key: abc +-> key.hex: 616263 -> value: abc -> value.hex: 616263 @@ -203,8 +212,34 @@ Try running these commands: -> code: OK -> log: exists -> height: 3 +-> key: def +-> key.hex: 646566 -> value: xyz -> value.hex: 78797A + +> prepare_proposal "preparedef" +-> code: OK +-> log: Succeeded. Tx: def action: ADDED +-> code: OK +-> log: Succeeded. Tx: preparedef action: REMOVED + +> process_proposal "def" +-> code: OK +-> status: ACCEPT + +> process_proposal "preparedef" +-> code: OK +-> status: REJECT + +> prepare_proposal + +> process_proposal +-> code: OK +-> status: ACCEPT + +> commit +-> code: OK +-> data.hex: 0x0400000000000000 ``` Note that if we do `deliver_tx "abc"` it will store `(abc, abc)`, but if diff --git a/docs/tendermint-core/metrics.md b/docs/tendermint-core/metrics.md index 8fb0353a0..2a906e01b 100644 --- a/docs/tendermint-core/metrics.md +++ b/docs/tendermint-core/metrics.md @@ -43,6 +43,12 @@ The following metrics are available: | consensus_step_duration | Histogram | step | Histogram of durations for each step in the consensus protocol | | consensus_round_duration | Histogram | | Histogram of durations for all the rounds that have occurred since the process started | | consensus_block_gossip_parts_received | Counter | matches_current | Number of block parts received by the node | +| consensus_quorum_prevote_delay | Gauge | | Interval in seconds between the proposal timestamp and the timestamp of the earliest prevote that achieved a quorum | +| consensus_full_prevote_delay | Gauge | | Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted | +| consensus_proposal_receive_count | Counter | status | Total number of proposals received by the node since process start | +| consensus_proposal_create_count | Counter | | Total number of proposals created by the node since process start | +| consensus_round_voting_power_percent | Gauge | vote_type | A value between 0 and 1.0 representing the percentage of the total voting power per vote type received within a round | +| consensus_late_votes | Counter | vote_type | Number of votes received by the node since process start that correspond to earlier heights and rounds than this node is currently in. | | p2p_peers | Gauge | | Number of peers node's connected to | | p2p_peer_receive_bytes_total | counter | peer_id, chID | number of bytes per channel received from a given peer | | p2p_peer_send_bytes_total | counter | peer_id, chID | number of bytes per channel sent to a given peer | @@ -54,6 +60,8 @@ The following metrics are available: | mempool_failed_txs | counter | | number of failed transactions | | mempool_recheck_times | counter | | number of transactions rechecked in the mempool | | state_block_processing_time | histogram | | time between BeginBlock and EndBlock in ms | +| state_consensus_param_updates | Counter | | number of consensus parameter updates returned by the application since process start | +| state_validator_set_updates | Counter | | number of validator set updates returned by the application since process start | ## Useful queries diff --git a/docs/tutorials/go-built-in.md b/docs/tutorials/go-built-in.md index 69e1d230d..d81668377 100644 --- a/docs/tutorials/go-built-in.md +++ b/docs/tutorials/go-built-in.md @@ -109,10 +109,6 @@ func (KVStoreApplication) Info(req abcitypes.RequestInfo) abcitypes.ResponseInfo return abcitypes.ResponseInfo{} } -func (KVStoreApplication) SetOption(req abcitypes.RequestSetOption) abcitypes.ResponseSetOption { - return abcitypes.ResponseSetOption{} -} - func (KVStoreApplication) DeliverTx(req abcitypes.RequestDeliverTx) abcitypes.ResponseDeliverTx { return abcitypes.ResponseDeliverTx{Code: 0} } diff --git a/docs/tutorials/go.md b/docs/tutorials/go.md index 8ff38ab6a..e0ba98589 100644 --- a/docs/tutorials/go.md +++ b/docs/tutorials/go.md @@ -111,11 +111,6 @@ func NewKVStoreApplication() *KVStoreApplication { func (KVStoreApplication) Info(req abcitypes.RequestInfo) abcitypes.ResponseInfo { return abcitypes.ResponseInfo{} } - -func (KVStoreApplication) SetOption(req abcitypes.RequestSetOption) abcitypes.ResponseSetOption { - return abcitypes.ResponseSetOption{} -} - func (KVStoreApplication) DeliverTx(req abcitypes.RequestDeliverTx) abcitypes.ResponseDeliverTx { return abcitypes.ResponseDeliverTx{Code: 0} } diff --git a/evidence/pool.go b/evidence/pool.go index dfeb7a717..4d82de971 100644 --- a/evidence/pool.go +++ b/evidence/pool.go @@ -463,10 +463,13 @@ func (evpool *Pool) processConsensusBuffer(state sm.State) { // Check the height of the conflicting votes and fetch the corresponding time and validator set // to produce the valid evidence - var dve *types.DuplicateVoteEvidence + var ( + dve *types.DuplicateVoteEvidence + err error + ) switch { case voteSet.VoteA.Height == state.LastBlockHeight: - dve = types.NewDuplicateVoteEvidence( + dve, err = types.NewDuplicateVoteEvidence( voteSet.VoteA, voteSet.VoteB, state.LastBlockTime, @@ -474,7 +477,8 @@ func (evpool *Pool) processConsensusBuffer(state sm.State) { ) case voteSet.VoteA.Height < state.LastBlockHeight: - valSet, err := evpool.stateDB.LoadValidators(voteSet.VoteA.Height) + var valSet *types.ValidatorSet + valSet, err = evpool.stateDB.LoadValidators(voteSet.VoteA.Height) if err != nil { evpool.logger.Error("failed to load validator set for conflicting votes", "height", voteSet.VoteA.Height, "err", err, @@ -486,7 +490,7 @@ func (evpool *Pool) processConsensusBuffer(state sm.State) { evpool.logger.Error("failed to load block time for conflicting votes", "height", voteSet.VoteA.Height) continue } - dve = types.NewDuplicateVoteEvidence( + dve, err = types.NewDuplicateVoteEvidence( voteSet.VoteA, voteSet.VoteB, blockMeta.Header.Time, @@ -502,6 +506,10 @@ func (evpool *Pool) processConsensusBuffer(state sm.State) { "state.LastBlockHeight", state.LastBlockHeight) continue } + if err != nil { + evpool.logger.Error("error in generating evidence from votes", "err", err) + continue + } // check if we already have this evidence if evpool.isPending(dve) { diff --git a/evidence/pool_test.go b/evidence/pool_test.go index efa3dea10..8283bb2f9 100644 --- a/evidence/pool_test.go +++ b/evidence/pool_test.go @@ -13,8 +13,8 @@ import ( "github.com/tendermint/tendermint/evidence" "github.com/tendermint/tendermint/evidence/mocks" + "github.com/tendermint/tendermint/internal/test" "github.com/tendermint/tendermint/libs/log" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmversion "github.com/tendermint/tendermint/proto/tendermint/version" sm "github.com/tendermint/tendermint/state" smmocks "github.com/tendermint/tendermint/state/mocks" @@ -61,7 +61,8 @@ func TestEvidencePoolBasic(t *testing.T) { assert.Equal(t, 0, len(evs)) assert.Zero(t, size) - ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime, privVals[0], evidenceChainID) + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime, privVals[0], evidenceChainID) + require.NoError(t, err) // good evidence evAdded := make(chan struct{}) @@ -133,8 +134,9 @@ func TestAddExpiredEvidence(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.evDescription, func(t *testing.T) { - ev := types.NewMockDuplicateVoteEvidenceWithValidator(tc.evHeight, tc.evTime, val, evidenceChainID) - err := pool.AddEvidence(ev) + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(tc.evHeight, tc.evTime, val, evidenceChainID) + require.NoError(t, err) + err = pool.AddEvidence(ev) if tc.expErr { assert.Error(t, err) } else { @@ -147,9 +149,10 @@ func TestAddExpiredEvidence(t *testing.T) { func TestReportConflictingVotes(t *testing.T) { var height int64 = 10 - pool, pv := defaultTestPool(height) + pool, pv := defaultTestPool(t, height) val := types.NewValidator(pv.PrivKey.PubKey(), 10) - ev := types.NewMockDuplicateVoteEvidenceWithValidator(height+1, defaultEvidenceTime, pv, evidenceChainID) + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height+1, defaultEvidenceTime, pv, evidenceChainID) + require.NoError(t, err) pool.ReportConflictingVotes(ev.VoteA, ev.VoteB) @@ -181,16 +184,18 @@ func TestReportConflictingVotes(t *testing.T) { func TestEvidencePoolUpdate(t *testing.T) { height := int64(21) - pool, val := defaultTestPool(height) + pool, val := defaultTestPool(t, height) state := pool.State() // create new block (no need to save it to blockStore) - prunedEv := types.NewMockDuplicateVoteEvidenceWithValidator(1, defaultEvidenceTime.Add(1*time.Minute), + prunedEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(1, defaultEvidenceTime.Add(1*time.Minute), val, evidenceChainID) - err := pool.AddEvidence(prunedEv) require.NoError(t, err) - ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime.Add(21*time.Minute), + err = pool.AddEvidence(prunedEv) + require.NoError(t, err) + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime.Add(21*time.Minute), val, evidenceChainID) + require.NoError(t, err) lastCommit := makeCommit(height, val.PrivKey.PubKey().Address()) block := types.MakeBlock(height+1, []types.Tx{}, lastCommit, []types.Evidence{ev}) // update state (partially) @@ -214,10 +219,11 @@ func TestEvidencePoolUpdate(t *testing.T) { func TestVerifyPendingEvidencePasses(t *testing.T) { var height int64 = 1 - pool, val := defaultTestPool(height) - ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime.Add(1*time.Minute), + pool, val := defaultTestPool(t, height) + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime.Add(1*time.Minute), val, evidenceChainID) - err := pool.AddEvidence(ev) + require.NoError(t, err) + err = pool.AddEvidence(ev) require.NoError(t, err) err = pool.CheckEvidence(types.EvidenceList{ev}) @@ -226,10 +232,11 @@ func TestVerifyPendingEvidencePasses(t *testing.T) { func TestVerifyDuplicatedEvidenceFails(t *testing.T) { var height int64 = 1 - pool, val := defaultTestPool(height) - ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime.Add(1*time.Minute), + pool, val := defaultTestPool(t, height) + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime.Add(1*time.Minute), val, evidenceChainID) - err := pool.CheckEvidence(types.EvidenceList{ev, ev}) + require.NoError(t, err) + err = pool.CheckEvidence(types.EvidenceList{ev, ev}) if assert.Error(t, err) { assert.Equal(t, "duplicate evidence", err.(*types.ErrInvalidEvidence).Reason.Error()) } @@ -306,15 +313,18 @@ func TestRecoverPendingEvidence(t *testing.T) { stateStore := initializeValidatorState(val, height) state, err := stateStore.Load() require.NoError(t, err) - blockStore := initializeBlockStore(dbm.NewMemDB(), state, valAddress) + blockStore, err := initializeBlockStore(dbm.NewMemDB(), state, valAddress) + require.NoError(t, err) // create previous pool and populate it pool, err := evidence.NewPool(evidenceDB, stateStore, blockStore) require.NoError(t, err) pool.SetLogger(log.TestingLogger()) - goodEvidence := types.NewMockDuplicateVoteEvidenceWithValidator(height, + goodEvidence, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime.Add(10*time.Minute), val, evidenceChainID) - expiredEvidence := types.NewMockDuplicateVoteEvidenceWithValidator(int64(1), + require.NoError(t, err) + expiredEvidence, err := types.NewMockDuplicateVoteEvidenceWithValidator(int64(1), defaultEvidenceTime.Add(1*time.Minute), val, evidenceChainID) + require.NoError(t, err) err = pool.AddEvidence(goodEvidence) require.NoError(t, err) err = pool.AddEvidence(expiredEvidence) @@ -325,12 +335,12 @@ func TestRecoverPendingEvidence(t *testing.T) { newStateStore.On("Load").Return(sm.State{ LastBlockTime: defaultEvidenceTime.Add(25 * time.Minute), LastBlockHeight: height + 15, - ConsensusParams: tmproto.ConsensusParams{ - Block: tmproto.BlockParams{ + ConsensusParams: types.ConsensusParams{ + Block: types.BlockParams{ MaxBytes: 22020096, MaxGas: -1, }, - Evidence: tmproto.EvidenceParams{ + Evidence: types.EvidenceParams{ MaxAgeNumBlocks: 20, MaxAgeDuration: 20 * time.Minute, MaxBytes: defaultEvidenceMaxBytes, @@ -360,12 +370,12 @@ func initializeStateFromValidatorSet(valSet *types.ValidatorSet, height int64) s NextValidators: valSet.CopyIncrementProposerPriority(1), LastValidators: valSet, LastHeightValidatorsChanged: 1, - ConsensusParams: tmproto.ConsensusParams{ - Block: tmproto.BlockParams{ + ConsensusParams: types.ConsensusParams{ + Block: types.BlockParams{ MaxBytes: 22020096, MaxGas: -1, }, - Evidence: tmproto.EvidenceParams{ + Evidence: types.EvidenceParams{ MaxAgeNumBlocks: 20, MaxAgeDuration: 20 * time.Minute, MaxBytes: 1000, @@ -400,23 +410,25 @@ func initializeValidatorState(privVal types.PrivValidator, height int64) sm.Stor // initializeBlockStore creates a block storage and populates it w/ a dummy // block at +height+. -func initializeBlockStore(db dbm.DB, state sm.State, valAddr []byte) *store.BlockStore { +func initializeBlockStore(db dbm.DB, state sm.State, valAddr []byte) (*store.BlockStore, error) { blockStore := store.NewBlockStore(db) for i := int64(1); i <= state.LastBlockHeight; i++ { lastCommit := makeCommit(i-1, valAddr) - block, _ := state.MakeBlock(i, []types.Tx{}, lastCommit, nil, - state.Validators.GetProposer().Address) + block := state.MakeBlock(i, test.MakeNTxs(i, 1), lastCommit, nil, state.Validators.Proposer.Address) block.Header.Time = defaultEvidenceTime.Add(time.Duration(i) * time.Minute) block.Header.Version = tmversion.Consensus{Block: version.BlockProtocol, App: 1} const parts = 1 - partSet := block.MakePartSet(parts) + partSet, err := block.MakePartSet(parts) + if err != nil { + return nil, err + } seenCommit := makeCommit(i, valAddr) blockStore.SaveBlock(block, partSet, seenCommit) } - return blockStore + return blockStore, nil } func makeCommit(height int64, valAddr []byte) *types.Commit { @@ -429,13 +441,15 @@ func makeCommit(height int64, valAddr []byte) *types.Commit { return types.NewCommit(height, 0, types.BlockID{}, commitSigs) } -func defaultTestPool(height int64) (*evidence.Pool, types.MockPV) { +func defaultTestPool(t *testing.T, height int64) (*evidence.Pool, types.MockPV) { + t.Helper() val := types.NewMockPV() valAddress := val.PrivKey.PubKey().Address() evidenceDB := dbm.NewMemDB() stateStore := initializeValidatorState(val, height) state, _ := stateStore.Load() - blockStore := initializeBlockStore(dbm.NewMemDB(), state, valAddress) + blockStore, err := initializeBlockStore(dbm.NewMemDB(), state, valAddress) + require.NoError(t, err) pool, err := evidence.NewPool(evidenceDB, stateStore, blockStore) if err != nil { panic("test evidence pool could not be created") diff --git a/evidence/reactor_test.go b/evidence/reactor_test.go index c0a22be26..4f8e73261 100644 --- a/evidence/reactor_test.go +++ b/evidence/reactor_test.go @@ -152,9 +152,10 @@ func TestReactorsGossipNoCommittedEvidence(t *testing.T) { // the first reactor receives three more evidence evList = make([]types.Evidence, 3) for i := 0; i < 3; i++ { - ev := types.NewMockDuplicateVoteEvidenceWithValidator(height-3+int64(i), + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height-3+int64(i), time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC), val, state.ChainID) - err := pools[0].AddEvidence(ev) + require.NoError(t, err) + err = pools[0].AddEvidence(ev) require.NoError(t, err) evList[i] = ev } @@ -327,9 +328,10 @@ func _waitForEvidence( func sendEvidence(t *testing.T, evpool *evidence.Pool, val types.PrivValidator, n int) types.EvidenceList { evList := make([]types.Evidence, n) for i := 0; i < n; i++ { - ev := types.NewMockDuplicateVoteEvidenceWithValidator(int64(i+1), + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(int64(i+1), time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC), val, evidenceChainID) - err := evpool.AddEvidence(ev) + require.NoError(t, err) + err = evpool.AddEvidence(ev) require.NoError(t, err) evList[i] = ev } @@ -377,12 +379,13 @@ func TestEvidenceVectors(t *testing.T) { valSet := types.NewValidatorSet([]*types.Validator{val}) - dupl := types.NewDuplicateVoteEvidence( + dupl, err := types.NewDuplicateVoteEvidence( exampleVote(1), exampleVote(2), defaultEvidenceTime, valSet, ) + require.NoError(t, err) testCases := []struct { testName string diff --git a/evidence/verify_test.go b/evidence/verify_test.go index 7825f9d43..f8021f436 100644 --- a/evidence/verify_test.go +++ b/evidence/verify_test.go @@ -412,11 +412,14 @@ func TestVerifyDuplicateVoteEvidence(t *testing.T) { } // create good evidence and correct validator power - goodEv := types.NewMockDuplicateVoteEvidenceWithValidator(10, defaultEvidenceTime, val, chainID) + goodEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(10, defaultEvidenceTime, val, chainID) + require.NoError(t, err) goodEv.ValidatorPower = 1 goodEv.TotalVotingPower = 1 - badEv := types.NewMockDuplicateVoteEvidenceWithValidator(10, defaultEvidenceTime, val, chainID) - badTimeEv := types.NewMockDuplicateVoteEvidenceWithValidator(10, defaultEvidenceTime.Add(1*time.Minute), val, chainID) + badEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(10, defaultEvidenceTime, val, chainID) + require.NoError(t, err) + badTimeEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(10, defaultEvidenceTime.Add(1*time.Minute), val, chainID) + require.NoError(t, err) badTimeEv.ValidatorPower = 1 badTimeEv.TotalVotingPower = 1 state := sm.State{ diff --git a/internal/test/block.go b/internal/test/block.go new file mode 100644 index 000000000..70e4d607e --- /dev/null +++ b/internal/test/block.go @@ -0,0 +1,123 @@ +package test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/tmhash" + sm "github.com/tendermint/tendermint/state" + "github.com/tendermint/tendermint/types" + "github.com/tendermint/tendermint/version" +) + +const ( + DefaultTestChainID = "test-chain" +) + +var ( + DefaultTestTime = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) +) + +func RandomAddress() []byte { + return crypto.CRandBytes(crypto.AddressSize) +} + +func RandomHash() []byte { + return crypto.CRandBytes(tmhash.Size) +} + +func MakeBlockID() types.BlockID { + return MakeBlockIDWithHash(RandomHash()) +} + +func MakeBlockIDWithHash(hash []byte) types.BlockID { + return types.BlockID{ + Hash: hash, + PartSetHeader: types.PartSetHeader{ + Total: 100, + Hash: RandomHash(), + }, + } +} + +// MakeHeader fills the rest of the contents of the header such that it passes +// validate basic +func MakeHeader(t *testing.T, h *types.Header) *types.Header { + t.Helper() + if h.Version.Block == 0 { + h.Version.Block = version.BlockProtocol + } + if h.Height == 0 { + h.Height = 1 + } + if h.LastBlockID.IsZero() { + h.LastBlockID = MakeBlockID() + } + if h.ChainID == "" { + h.ChainID = DefaultTestChainID + } + if len(h.LastCommitHash) == 0 { + h.LastCommitHash = RandomHash() + } + if len(h.DataHash) == 0 { + h.DataHash = RandomHash() + } + if len(h.ValidatorsHash) == 0 { + h.ValidatorsHash = RandomHash() + } + if len(h.NextValidatorsHash) == 0 { + h.NextValidatorsHash = RandomHash() + } + if len(h.ConsensusHash) == 0 { + h.ConsensusHash = RandomHash() + } + if len(h.AppHash) == 0 { + h.AppHash = RandomHash() + } + if len(h.LastResultsHash) == 0 { + h.LastResultsHash = RandomHash() + } + if len(h.EvidenceHash) == 0 { + h.EvidenceHash = RandomHash() + } + if len(h.ProposerAddress) == 0 { + h.ProposerAddress = RandomAddress() + } + + require.NoError(t, h.ValidateBasic()) + + return h +} + +func MakeBlock(state sm.State) *types.Block { + return state.MakeBlock(state.LastBlockHeight+1, MakeNTxs(state.LastBlockHeight+1, 10), new(types.Commit), nil, state.NextValidators.Proposer.Address) +} + +func MakeBlocks(n int, state sm.State, privVals []types.PrivValidator) ([]*types.Block, error) { + blockID := MakeBlockID() + blocks := make([]*types.Block, n) + + for i := 0; i < n; i++ { + height := state.LastBlockHeight + 1 + int64(i) + lastCommit, err := MakeCommit(blockID, height-1, 0, state.LastValidators, privVals, state.ChainID, state.LastBlockTime) + if err != nil { + return nil, err + } + block := state.MakeBlock(height, MakeNTxs(height, 10), lastCommit, nil, state.LastValidators.Proposer.Address) + blocks[i] = block + state.LastBlockID = blockID + state.LastBlockHeight = height + state.LastBlockTime = state.LastBlockTime.Add(1 * time.Second) + state.LastValidators = state.Validators.Copy() + state.Validators = state.NextValidators.Copy() + state.NextValidators = state.NextValidators.CopyIncrementProposerPriority(1) + state.AppHash = RandomHash() + + blockID = MakeBlockIDWithHash(block.Hash()) + } + + return blocks, nil +} diff --git a/internal/test/commit.go b/internal/test/commit.go new file mode 100644 index 000000000..fd3a8ac5a --- /dev/null +++ b/internal/test/commit.go @@ -0,0 +1,90 @@ +package test + +import ( + "fmt" + "time" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + sm "github.com/tendermint/tendermint/state" + "github.com/tendermint/tendermint/types" +) + +func MakeCommitFromVoteSet(blockID types.BlockID, voteSet *types.VoteSet, validators []types.PrivValidator, now time.Time) (*types.Commit, error) { + // all sign + for i := 0; i < len(validators); i++ { + pubKey, err := validators[i].GetPubKey() + if err != nil { + return nil, err + } + vote := &types.Vote{ + ValidatorAddress: pubKey.Address(), + ValidatorIndex: int32(i), + Height: voteSet.GetHeight(), + Round: voteSet.GetRound(), + Type: tmproto.PrecommitType, + BlockID: blockID, + Timestamp: now, + } + + v := vote.ToProto() + + if err := validators[i].SignVote(voteSet.ChainID(), v); err != nil { + return nil, err + } + vote.Signature = v.Signature + if _, err := voteSet.AddVote(vote); err != nil { + return nil, err + } + } + + return voteSet.MakeCommit(), nil +} + +func MakeVoteSet(lastState sm.State, round int32) *types.VoteSet { + return types.NewVoteSet(lastState.ChainID, lastState.LastBlockHeight+1, round, tmproto.PrecommitType, lastState.NextValidators) +} + +func MakeCommit(blockID types.BlockID, height int64, round int32, valSet *types.ValidatorSet, privVals []types.PrivValidator, chainID string, now time.Time) (*types.Commit, error) { + sigs := make([]types.CommitSig, len(valSet.Validators)) + for i := 0; i < len(valSet.Validators); i++ { + sigs[i] = types.NewCommitSigAbsent() + } + + for _, privVal := range privVals { + pk, err := privVal.GetPubKey() + if err != nil { + return nil, err + } + addr := pk.Address() + + idx, _ := valSet.GetByAddress(addr) + if idx < 0 { + return nil, fmt.Errorf("validator with address %s not in validator set", addr) + } + + vote := &types.Vote{ + ValidatorAddress: addr, + ValidatorIndex: idx, + Height: height, + Round: round, + Type: tmproto.PrecommitType, + BlockID: blockID, + Timestamp: now, + } + + v := vote.ToProto() + + if err := privVal.SignVote(chainID, v); err != nil { + return nil, err + } + + sigs[idx] = types.CommitSig{ + BlockIDFlag: types.BlockIDFlagCommit, + ValidatorAddress: addr, + Timestamp: now, + Signature: v.Signature, + } + } + + return types.NewCommit(height, round, blockID, sigs), nil +} diff --git a/internal/test/doc.go b/internal/test/doc.go new file mode 100644 index 000000000..86438e290 --- /dev/null +++ b/internal/test/doc.go @@ -0,0 +1,6 @@ +/* +Package factory provides generation code for common structs in Tendermint. +It is used primarily for the testing of internal components such as statesync, +consensus, blocksync etc.. +*/ +package test diff --git a/internal/test/factory_test.go b/internal/test/factory_test.go new file mode 100644 index 000000000..6231cc7cc --- /dev/null +++ b/internal/test/factory_test.go @@ -0,0 +1,15 @@ +package test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/types" +) + +func TestMakeHeader(t *testing.T) { + header := MakeHeader(t, &types.Header{}) + require.NotNil(t, header) + + require.NoError(t, header.ValidateBasic()) +} diff --git a/internal/test/genesis.go b/internal/test/genesis.go new file mode 100644 index 000000000..732adf5a3 --- /dev/null +++ b/internal/test/genesis.go @@ -0,0 +1,33 @@ +package test + +import ( + "time" + + cfg "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/types" +) + +func GenesisDoc( + config *cfg.Config, + time time.Time, + validators []*types.Validator, + consensusParams *types.ConsensusParams, +) *types.GenesisDoc { + + genesisValidators := make([]types.GenesisValidator, len(validators)) + + for i := range validators { + genesisValidators[i] = types.GenesisValidator{ + Power: validators[i].VotingPower, + PubKey: validators[i].PubKey, + } + } + + return &types.GenesisDoc{ + GenesisTime: time, + InitialHeight: 1, + ChainID: config.ChainID(), + Validators: genesisValidators, + ConsensusParams: consensusParams, + } +} diff --git a/internal/test/tx.go b/internal/test/tx.go new file mode 100644 index 000000000..c61d0cfe0 --- /dev/null +++ b/internal/test/tx.go @@ -0,0 +1,11 @@ +package test + +import "github.com/tendermint/tendermint/types" + +func MakeNTxs(height, n int64) []types.Tx { + txs := make([]types.Tx, n) + for i := range txs { + txs[i] = types.Tx([]byte{byte(height), byte(i / 256), byte(i % 256)}) + } + return txs +} diff --git a/internal/test/validator.go b/internal/test/validator.go new file mode 100644 index 000000000..d0fdf8007 --- /dev/null +++ b/internal/test/validator.go @@ -0,0 +1,41 @@ +package test + +import ( + "context" + "sort" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/types" +) + +func Validator(ctx context.Context, votingPower int64) (*types.Validator, types.PrivValidator, error) { + privVal := types.NewMockPV() + pubKey, err := privVal.GetPubKey() + if err != nil { + return nil, nil, err + } + + val := types.NewValidator(pubKey, votingPower) + return val, privVal, nil +} + +func ValidatorSet(ctx context.Context, t *testing.T, numValidators int, votingPower int64) (*types.ValidatorSet, []types.PrivValidator) { + var ( + valz = make([]*types.Validator, numValidators) + privValidators = make([]types.PrivValidator, numValidators) + ) + t.Helper() + + for i := 0; i < numValidators; i++ { + val, privValidator, err := Validator(ctx, votingPower) + require.NoError(t, err) + valz[i] = val + privValidators[i] = privValidator + } + + sort.Sort(types.PrivValidatorsByAddress(privValidators)) + + return types.NewValidatorSet(valz), privValidators +} diff --git a/internal/test/vote.go b/internal/test/vote.go new file mode 100644 index 000000000..180cb943d --- /dev/null +++ b/internal/test/vote.go @@ -0,0 +1,42 @@ +package test + +import ( + "time" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/tendermint/tendermint/types" +) + +func MakeVote( + val types.PrivValidator, + chainID string, + valIndex int32, + height int64, + round int32, + step int, + blockID types.BlockID, + time time.Time, +) (*types.Vote, error) { + pubKey, err := val.GetPubKey() + if err != nil { + return nil, err + } + + v := &types.Vote{ + ValidatorAddress: pubKey.Address(), + ValidatorIndex: valIndex, + Height: height, + Round: round, + Type: tmproto.SignedMsgType(step), + BlockID: blockID, + Timestamp: time, + } + + vpb := v.ToProto() + if err := val.SignVote(chainID, vpb); err != nil { + return nil, err + } + + v.Signature = vpb.Signature + return v, nil +} diff --git a/light/rpc/client.go b/light/rpc/client.go index 6fc1adbca..bc83eb336 100644 --- a/light/rpc/client.go +++ b/light/rpc/client.go @@ -233,7 +233,7 @@ func (c *Client) ConsensusParams(ctx context.Context, height *int64) (*ctypes.Re } // Validate res. - if err := types.ValidateConsensusParams(res.ConsensusParams); err != nil { + if err := res.ConsensusParams.ValidateBasic(); err != nil { return nil, err } if res.BlockHeight <= 0 { @@ -247,7 +247,7 @@ func (c *Client) ConsensusParams(ctx context.Context, height *int64) (*ctypes.Re } // Verify hash. - if cH, tH := types.HashConsensusParams(res.ConsensusParams), l.ConsensusHash; !bytes.Equal(cH, tH) { + if cH, tH := res.ConsensusParams.Hash(), l.ConsensusHash; !bytes.Equal(cH, tH) { return nil, fmt.Errorf("params hash %X does not match trusted hash %X", cH, tH) } diff --git a/mempool/mempool.go b/mempool/mempool.go index 08717fd95..bf6eb2e72 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -23,6 +23,8 @@ const ( MaxActiveIDs = math.MaxUint16 ) +//go:generate ../scripts/mockery_generate.sh Mempool + // Mempool defines the mempool interface. // // Updates to the mempool need to be synchronized with committing a block so diff --git a/mempool/mock/mempool.go b/mempool/mock/mempool.go deleted file mode 100644 index 3f293381f..000000000 --- a/mempool/mock/mempool.go +++ /dev/null @@ -1,43 +0,0 @@ -package mock - -import ( - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/libs/clist" - "github.com/tendermint/tendermint/mempool" - "github.com/tendermint/tendermint/types" -) - -// Mempool is an empty implementation of a Mempool, useful for testing. -type Mempool struct{} - -var _ mempool.Mempool = Mempool{} - -func (Mempool) Lock() {} -func (Mempool) Unlock() {} -func (Mempool) Size() int { return 0 } -func (Mempool) CheckTx(_ types.Tx, _ func(*abci.Response), _ mempool.TxInfo) error { - return nil -} -func (Mempool) RemoveTxByKey(txKey types.TxKey) error { return nil } -func (Mempool) ReapMaxBytesMaxGas(_, _ int64) types.Txs { return types.Txs{} } -func (Mempool) ReapMaxTxs(n int) types.Txs { return types.Txs{} } -func (Mempool) Update( - _ int64, - _ types.Txs, - _ []*abci.ResponseDeliverTx, - _ mempool.PreCheckFunc, - _ mempool.PostCheckFunc, -) error { - return nil -} -func (Mempool) Flush() {} -func (Mempool) FlushAppConn() error { return nil } -func (Mempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } -func (Mempool) EnableTxsAvailable() {} -func (Mempool) SizeBytes() int64 { return 0 } - -func (Mempool) TxsFront() *clist.CElement { return nil } -func (Mempool) TxsWaitChan() <-chan struct{} { return nil } - -func (Mempool) InitWAL() error { return nil } -func (Mempool) CloseWAL() {} diff --git a/mempool/mocks/mempool.go b/mempool/mocks/mempool.go new file mode 100644 index 000000000..fa16a2633 --- /dev/null +++ b/mempool/mocks/mempool.go @@ -0,0 +1,184 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + abcitypes "github.com/tendermint/tendermint/abci/types" + mempool "github.com/tendermint/tendermint/mempool" + + mock "github.com/stretchr/testify/mock" + + types "github.com/tendermint/tendermint/types" +) + +// Mempool is an autogenerated mock type for the Mempool type +type Mempool struct { + mock.Mock +} + +// CheckTx provides a mock function with given fields: tx, callback, txInfo +func (_m *Mempool) CheckTx(tx types.Tx, callback func(*abcitypes.Response), txInfo mempool.TxInfo) error { + ret := _m.Called(tx, callback, txInfo) + + var r0 error + if rf, ok := ret.Get(0).(func(types.Tx, func(*abcitypes.Response), mempool.TxInfo) error); ok { + r0 = rf(tx, callback, txInfo) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// EnableTxsAvailable provides a mock function with given fields: +func (_m *Mempool) EnableTxsAvailable() { + _m.Called() +} + +// Flush provides a mock function with given fields: +func (_m *Mempool) Flush() { + _m.Called() +} + +// FlushAppConn provides a mock function with given fields: +func (_m *Mempool) FlushAppConn() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Lock provides a mock function with given fields: +func (_m *Mempool) Lock() { + _m.Called() +} + +// ReapMaxBytesMaxGas provides a mock function with given fields: maxBytes, maxGas +func (_m *Mempool) ReapMaxBytesMaxGas(maxBytes int64, maxGas int64) types.Txs { + ret := _m.Called(maxBytes, maxGas) + + var r0 types.Txs + if rf, ok := ret.Get(0).(func(int64, int64) types.Txs); ok { + r0 = rf(maxBytes, maxGas) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.Txs) + } + } + + return r0 +} + +// ReapMaxTxs provides a mock function with given fields: max +func (_m *Mempool) ReapMaxTxs(max int) types.Txs { + ret := _m.Called(max) + + var r0 types.Txs + if rf, ok := ret.Get(0).(func(int) types.Txs); ok { + r0 = rf(max) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.Txs) + } + } + + return r0 +} + +// RemoveTxByKey provides a mock function with given fields: txKey +func (_m *Mempool) RemoveTxByKey(txKey types.TxKey) error { + ret := _m.Called(txKey) + + var r0 error + if rf, ok := ret.Get(0).(func(types.TxKey) error); ok { + r0 = rf(txKey) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Size provides a mock function with given fields: +func (_m *Mempool) Size() int { + ret := _m.Called() + + var r0 int + if rf, ok := ret.Get(0).(func() int); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int) + } + + return r0 +} + +// SizeBytes provides a mock function with given fields: +func (_m *Mempool) SizeBytes() int64 { + ret := _m.Called() + + var r0 int64 + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + return r0 +} + +// TxsAvailable provides a mock function with given fields: +func (_m *Mempool) TxsAvailable() <-chan struct{} { + ret := _m.Called() + + var r0 <-chan struct{} + if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(<-chan struct{}) + } + } + + return r0 +} + +// Unlock provides a mock function with given fields: +func (_m *Mempool) Unlock() { + _m.Called() +} + +// Update provides a mock function with given fields: blockHeight, blockTxs, deliverTxResponses, newPreFn, newPostFn +func (_m *Mempool) Update(blockHeight int64, blockTxs types.Txs, deliverTxResponses []*abcitypes.ResponseDeliverTx, newPreFn mempool.PreCheckFunc, newPostFn mempool.PostCheckFunc) error { + ret := _m.Called(blockHeight, blockTxs, deliverTxResponses, newPreFn, newPostFn) + + var r0 error + if rf, ok := ret.Get(0).(func(int64, types.Txs, []*abcitypes.ResponseDeliverTx, mempool.PreCheckFunc, mempool.PostCheckFunc) error); ok { + r0 = rf(blockHeight, blockTxs, deliverTxResponses, newPreFn, newPostFn) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTNewMempool interface { + mock.TestingT + Cleanup(func()) +} + +// NewMempool creates a new instance of Mempool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewMempool(t mockConstructorTestingTNewMempool) *Mempool { + mock := &Mempool{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index fab3fc910..8b444ac53 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -9,6 +9,7 @@ import ( "time" "github.com/creachadair/taskgroup" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/libs/clist" diff --git a/mempool/v1/mempool_bench_test.go b/mempool/v1/mempool_bench_test.go index bad8ec8ab..a26501275 100644 --- a/mempool/v1/mempool_bench_test.go +++ b/mempool/v1/mempool_bench_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/mempool" ) diff --git a/node/node_test.go b/node/node_test.go index 57b101d82..8c348cf05 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -279,7 +279,8 @@ func TestCreateProposalBlock(t *testing.T) { // than can fit in a block var currentBytes int64 for currentBytes <= maxEvidenceBytes { - ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), privVals[0], "test-chain") + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), privVals[0], "test-chain") + require.NoError(t, err) currentBytes += int64(len(ev.Bytes())) evidencePool.ReportConflictingVotes(ev.VoteA, ev.VoteB) } @@ -307,14 +308,17 @@ func TestCreateProposalBlock(t *testing.T) { ) commit := types.NewCommit(height-1, 0, types.BlockID{}, nil) - block, _ := blockExec.CreateProposalBlock( + block, err := blockExec.CreateProposalBlock( height, state, commit, proposerAddr, + nil, ) + require.NoError(t, err) // check that the part set does not exceed the maximum block size - partSet := block.MakePartSet(partSize) + partSet, err := block.MakePartSet(partSize) + require.NoError(t, err) assert.Less(t, partSet.ByteSize(), int64(maxBytes)) partSetFromHeader := types.NewPartSetFromHeader(partSet.Header()) @@ -387,18 +391,21 @@ func TestMaxProposalBlockSize(t *testing.T) { ) commit := types.NewCommit(height-1, 0, types.BlockID{}, nil) - block, _ := blockExec.CreateProposalBlock( + block, err := blockExec.CreateProposalBlock( height, state, commit, proposerAddr, + nil, ) + require.NoError(t, err) pb, err := block.ToProto() require.NoError(t, err) assert.Less(t, int64(pb.Size()), maxBytes) // check that the part set does not exceed the maximum block size - partSet := block.MakePartSet(partSize) + partSet, err := block.MakePartSet(partSize) + require.NoError(t, err) assert.EqualValues(t, partSet.ByteSize(), int64(pb.Size())) } diff --git a/proto/tendermint/abci/types.proto b/proto/tendermint/abci/types.proto index 340800f46..cd68f444f 100644 --- a/proto/tendermint/abci/types.proto +++ b/proto/tendermint/abci/types.proto @@ -24,7 +24,6 @@ message Request { RequestEcho echo = 1; RequestFlush flush = 2; RequestInfo info = 3; - RequestSetOption set_option = 4; RequestInitChain init_chain = 5; RequestQuery query = 6; RequestBeginBlock begin_block = 7; @@ -36,7 +35,10 @@ message Request { RequestOfferSnapshot offer_snapshot = 13; RequestLoadSnapshotChunk load_snapshot_chunk = 14; RequestApplySnapshotChunk apply_snapshot_chunk = 15; + RequestPrepareProposal prepare_proposal = 16; + RequestProcessProposal process_proposal = 17; } + reserved 4; } message RequestEcho { @@ -49,22 +51,17 @@ message RequestInfo { string version = 1; uint64 block_version = 2; uint64 p2p_version = 3; -} - -// nondeterministic -message RequestSetOption { - string key = 1; - string value = 2; + string abci_version = 4; } message RequestInitChain { google.protobuf.Timestamp time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; - string chain_id = 2; - ConsensusParams consensus_params = 3; - repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; - bytes app_state_bytes = 5; - int64 initial_height = 6; + string chain_id = 2; + tendermint.types.ConsensusParams consensus_params = 3; + repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; + bytes app_state_bytes = 5; + int64 initial_height = 6; } message RequestQuery { @@ -77,8 +74,8 @@ message RequestQuery { message RequestBeginBlock { bytes hash = 1; tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; - LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; - repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; + CommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; + repeated Misbehavior byzantine_validators = 4 [(gogoproto.nullable) = false]; } enum CheckTxType { @@ -124,6 +121,34 @@ message RequestApplySnapshotChunk { string sender = 3; } +message RequestPrepareProposal { + // the modified transactions cannot exceed this size. + int64 max_tx_bytes = 1; + // txs is an array of transactions that will be included in a block, + // sent to the app for possible modifications. + repeated bytes txs = 2; + ExtendedCommitInfo local_last_commit = 3 [(gogoproto.nullable) = false]; + repeated Misbehavior misbehavior = 4 [(gogoproto.nullable) = false]; + int64 height = 5; + google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes next_validators_hash = 7; + // address of the public key of the validator proposing the block. + bytes proposer_address = 8; +} + +message RequestProcessProposal { + repeated bytes txs = 1; + CommitInfo proposed_last_commit = 2 [(gogoproto.nullable) = false]; + repeated Misbehavior misbehavior = 3 [(gogoproto.nullable) = false]; + // hash is the merkle root hash of the fields of the proposed block. + bytes hash = 4; + int64 height = 5; + google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes next_validators_hash = 7; + // address of the public key of the original proposer of the block. + bytes proposer_address = 8; +} + //---------------------------------------- // Response types @@ -133,7 +158,6 @@ message Response { ResponseEcho echo = 2; ResponseFlush flush = 3; ResponseInfo info = 4; - ResponseSetOption set_option = 5; ResponseInitChain init_chain = 6; ResponseQuery query = 7; ResponseBeginBlock begin_block = 8; @@ -145,7 +169,10 @@ message Response { ResponseOfferSnapshot offer_snapshot = 14; ResponseLoadSnapshotChunk load_snapshot_chunk = 15; ResponseApplySnapshotChunk apply_snapshot_chunk = 16; + ResponsePrepareProposal prepare_proposal = 17; + ResponseProcessProposal process_proposal = 18; } + reserved 5; } // nondeterministic @@ -169,18 +196,10 @@ message ResponseInfo { bytes last_block_app_hash = 5; } -// nondeterministic -message ResponseSetOption { - uint32 code = 1; - // bytes data = 2; - string log = 3; - string info = 4; -} - message ResponseInitChain { - ConsensusParams consensus_params = 1; - repeated ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; - bytes app_hash = 3; + tendermint.types.ConsensusParams consensus_params = 1; + repeated ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; + bytes app_hash = 3; } message ResponseQuery { @@ -234,9 +253,9 @@ message ResponseDeliverTx { } message ResponseEndBlock { - repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; - ConsensusParams consensus_param_updates = 2; - repeated Event events = 3 + repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; + tendermint.types.ConsensusParams consensus_param_updates = 2; + repeated Event events = 3 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; } @@ -282,31 +301,36 @@ message ResponseApplySnapshotChunk { } } +message ResponsePrepareProposal { + repeated bytes txs = 1; +} + +message ResponseProcessProposal { + ProposalStatus status = 1; + + enum ProposalStatus { + UNKNOWN = 0; + ACCEPT = 1; + REJECT = 2; + } +} + //---------------------------------------- // Misc. -// ConsensusParams contains all consensus-relevant parameters -// that can be adjusted by the abci app -message ConsensusParams { - BlockParams block = 1; - tendermint.types.EvidenceParams evidence = 2; - tendermint.types.ValidatorParams validator = 3; - tendermint.types.VersionParams version = 4; -} - -// BlockParams contains limits on the block size. -message BlockParams { - // Note: must be greater than 0 - int64 max_bytes = 1; - // Note: must be greater or equal to -1 - int64 max_gas = 2; -} - -message LastCommitInfo { +message CommitInfo { int32 round = 1; repeated VoteInfo votes = 2 [(gogoproto.nullable) = false]; } +message ExtendedCommitInfo { + // The round at which the block proposer decided in the previous height. + int32 round = 1; + // List of validators' addresses in the last validator set with their voting + // information, including vote extensions. + repeated ExtendedVoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + // Event allows application developers to attach additional information to // ResponseBeginBlock, ResponseEndBlock, ResponseCheckTx and ResponseDeliverTx. // Later, transactions may be queried using these events. @@ -357,14 +381,20 @@ message VoteInfo { bool signed_last_block = 2; } -enum EvidenceType { +message ExtendedVoteInfo { + Validator validator = 1 [(gogoproto.nullable) = false]; + bool signed_last_block = 2; + bytes vote_extension = 3; // Reserved for future use +} + +enum MisbehaviorType { UNKNOWN = 0; DUPLICATE_VOTE = 1; LIGHT_CLIENT_ATTACK = 2; } -message Evidence { - EvidenceType type = 1; +message Misbehavior { + MisbehaviorType type = 1; // The offending validator Validator validator = 2 [(gogoproto.nullable) = false]; // The height when the offense occurred @@ -396,7 +426,6 @@ 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); @@ -410,4 +439,6 @@ service ABCIApplication { returns (ResponseLoadSnapshotChunk); rpc ApplySnapshotChunk(RequestApplySnapshotChunk) returns (ResponseApplySnapshotChunk); + rpc PrepareProposal(RequestPrepareProposal) returns (ResponsePrepareProposal); + rpc ProcessProposal(RequestProcessProposal) returns (ResponseProcessProposal); } diff --git a/proto/tendermint/types/params.pb.go b/proto/tendermint/types/params.pb.go index d3deb576a..4a576f57d 100644 --- a/proto/tendermint/types/params.pb.go +++ b/proto/tendermint/types/params.pb.go @@ -30,10 +30,10 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // ConsensusParams contains consensus critical parameters that determine the // validity of blocks. type ConsensusParams struct { - Block BlockParams `protobuf:"bytes,1,opt,name=block,proto3" json:"block"` - Evidence EvidenceParams `protobuf:"bytes,2,opt,name=evidence,proto3" json:"evidence"` - Validator ValidatorParams `protobuf:"bytes,3,opt,name=validator,proto3" json:"validator"` - Version VersionParams `protobuf:"bytes,4,opt,name=version,proto3" json:"version"` + Block *BlockParams `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Evidence *EvidenceParams `protobuf:"bytes,2,opt,name=evidence,proto3" json:"evidence,omitempty"` + Validator *ValidatorParams `protobuf:"bytes,3,opt,name=validator,proto3" json:"validator,omitempty"` + Version *VersionParams `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` } func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } @@ -69,32 +69,32 @@ func (m *ConsensusParams) XXX_DiscardUnknown() { var xxx_messageInfo_ConsensusParams proto.InternalMessageInfo -func (m *ConsensusParams) GetBlock() BlockParams { +func (m *ConsensusParams) GetBlock() *BlockParams { if m != nil { return m.Block } - return BlockParams{} + return nil } -func (m *ConsensusParams) GetEvidence() EvidenceParams { +func (m *ConsensusParams) GetEvidence() *EvidenceParams { if m != nil { return m.Evidence } - return EvidenceParams{} + return nil } -func (m *ConsensusParams) GetValidator() ValidatorParams { +func (m *ConsensusParams) GetValidator() *ValidatorParams { if m != nil { return m.Validator } - return ValidatorParams{} + return nil } -func (m *ConsensusParams) GetVersion() VersionParams { +func (m *ConsensusParams) GetVersion() *VersionParams { if m != nil { return m.Version } - return VersionParams{} + return nil } // BlockParams contains limits on the block size. @@ -105,11 +105,6 @@ type BlockParams struct { // Max gas per block. // Note: must be greater or equal to -1 MaxGas int64 `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` - // Minimum time increment between consecutive blocks (in milliseconds) If the - // block header timestamp is ahead of the system clock, decrease this value. - // - // Not exposed to the application. - TimeIotaMs int64 `protobuf:"varint,3,opt,name=time_iota_ms,json=timeIotaMs,proto3" json:"time_iota_ms,omitempty"` } func (m *BlockParams) Reset() { *m = BlockParams{} } @@ -159,13 +154,6 @@ func (m *BlockParams) GetMaxGas() int64 { return 0 } -func (m *BlockParams) GetTimeIotaMs() int64 { - if m != nil { - return m.TimeIotaMs - } - return 0 -} - // EvidenceParams determine how we handle evidence of malfeasance. type EvidenceParams struct { // Max age of evidence, in blocks. @@ -287,7 +275,7 @@ func (m *ValidatorParams) GetPubKeyTypes() []string { // VersionParams contains the ABCI application version. type VersionParams struct { - AppVersion uint64 `protobuf:"varint,1,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` + App uint64 `protobuf:"varint,1,opt,name=app,proto3" json:"app,omitempty"` } func (m *VersionParams) Reset() { *m = VersionParams{} } @@ -323,9 +311,9 @@ func (m *VersionParams) XXX_DiscardUnknown() { var xxx_messageInfo_VersionParams proto.InternalMessageInfo -func (m *VersionParams) GetAppVersion() uint64 { +func (m *VersionParams) GetApp() uint64 { if m != nil { - return m.AppVersion + return m.App } return 0 } @@ -397,41 +385,40 @@ func init() { func init() { proto.RegisterFile("tendermint/types/params.proto", fileDescriptor_e12598271a686f57) } var fileDescriptor_e12598271a686f57 = []byte{ - // 537 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0x31, 0x6f, 0xd3, 0x40, - 0x18, 0xcd, 0xd5, 0xa5, 0x4d, 0xbe, 0x34, 0x4d, 0x75, 0x42, 0x22, 0x14, 0xd5, 0x0e, 0x1e, 0x50, - 0x25, 0x24, 0x5b, 0x82, 0x01, 0xd1, 0xa5, 0xc2, 0x50, 0x15, 0x84, 0x82, 0x90, 0x05, 0x0c, 0x5d, - 0xac, 0x73, 0x72, 0xb8, 0x56, 0x73, 0x3e, 0xcb, 0x77, 0x8e, 0x92, 0x7f, 0xc1, 0xd8, 0xb1, 0x23, - 0xfc, 0x03, 0x7e, 0x42, 0xc7, 0x8e, 0x4c, 0x80, 0x92, 0x85, 0x9f, 0x81, 0x7c, 0xce, 0xe1, 0x38, - 0x65, 0xf3, 0x7d, 0xdf, 0x7b, 0xef, 0xfc, 0xde, 0xd3, 0xc1, 0x81, 0xa4, 0xc9, 0x88, 0x66, 0x2c, - 0x4e, 0xa4, 0x2b, 0x67, 0x29, 0x15, 0x6e, 0x4a, 0x32, 0xc2, 0x84, 0x93, 0x66, 0x5c, 0x72, 0xbc, - 0x57, 0xad, 0x1d, 0xb5, 0xde, 0xbf, 0x1b, 0xf1, 0x88, 0xab, 0xa5, 0x5b, 0x7c, 0x95, 0xb8, 0x7d, - 0x33, 0xe2, 0x3c, 0x1a, 0x53, 0x57, 0x9d, 0xc2, 0xfc, 0xb3, 0x3b, 0xca, 0x33, 0x22, 0x63, 0x9e, - 0x94, 0x7b, 0xfb, 0x72, 0x03, 0xba, 0x2f, 0x79, 0x22, 0x68, 0x22, 0x72, 0xf1, 0x5e, 0xdd, 0x80, - 0x9f, 0xc3, 0x9d, 0x70, 0xcc, 0x87, 0x17, 0x3d, 0xd4, 0x47, 0x87, 0xed, 0x27, 0x07, 0xce, 0xfa, - 0x5d, 0x8e, 0x57, 0xac, 0x4b, 0xb4, 0xb7, 0x79, 0xfd, 0xd3, 0x6a, 0xf8, 0x25, 0x03, 0x7b, 0xd0, - 0xa4, 0x93, 0x78, 0x44, 0x93, 0x21, 0xed, 0x6d, 0x28, 0x76, 0xff, 0x36, 0xfb, 0x64, 0x89, 0xa8, - 0x09, 0xfc, 0xe3, 0xe1, 0x13, 0x68, 0x4d, 0xc8, 0x38, 0x1e, 0x11, 0xc9, 0xb3, 0x9e, 0xa1, 0x44, - 0x1e, 0xde, 0x16, 0xf9, 0xa4, 0x21, 0x35, 0x95, 0x8a, 0x89, 0x8f, 0x61, 0x7b, 0x42, 0x33, 0x11, - 0xf3, 0xa4, 0xb7, 0xa9, 0x44, 0xac, 0xff, 0x88, 0x94, 0x80, 0x9a, 0x84, 0x66, 0xd9, 0x14, 0xda, - 0x2b, 0x3e, 0xf1, 0x03, 0x68, 0x31, 0x32, 0x0d, 0xc2, 0x99, 0xa4, 0x42, 0x25, 0x63, 0xf8, 0x4d, - 0x46, 0xa6, 0x5e, 0x71, 0xc6, 0xf7, 0x60, 0xbb, 0x58, 0x46, 0x44, 0x28, 0xdb, 0x86, 0xbf, 0xc5, - 0xc8, 0xf4, 0x94, 0x08, 0xdc, 0x87, 0x1d, 0x19, 0x33, 0x1a, 0xc4, 0x5c, 0x92, 0x80, 0x09, 0xe5, - 0xc7, 0xf0, 0xa1, 0x98, 0xbd, 0xe1, 0x92, 0x0c, 0x84, 0xfd, 0x0d, 0xc1, 0x6e, 0x3d, 0x11, 0xfc, - 0x18, 0x70, 0xa1, 0x46, 0x22, 0x1a, 0x24, 0x39, 0x0b, 0x54, 0xb4, 0xfa, 0xce, 0x2e, 0x23, 0xd3, - 0x17, 0x11, 0x7d, 0x97, 0x33, 0xf5, 0x73, 0x02, 0x0f, 0x60, 0x4f, 0x83, 0x75, 0xb7, 0xcb, 0xe8, - 0xef, 0x3b, 0x65, 0xf9, 0x8e, 0x2e, 0xdf, 0x79, 0xb5, 0x04, 0x78, 0xcd, 0xc2, 0xea, 0xe5, 0x2f, - 0x0b, 0xf9, 0xbb, 0xa5, 0x9e, 0xde, 0xd4, 0x6d, 0x1a, 0x75, 0x9b, 0xf6, 0x31, 0x74, 0xd7, 0x72, - 0xc7, 0x36, 0x74, 0xd2, 0x3c, 0x0c, 0x2e, 0xe8, 0x2c, 0x50, 0x99, 0xf6, 0x50, 0xdf, 0x38, 0x6c, - 0xf9, 0xed, 0x34, 0x0f, 0xdf, 0xd2, 0xd9, 0x87, 0x62, 0x74, 0xd4, 0xfc, 0x7e, 0x65, 0xa1, 0x3f, - 0x57, 0x16, 0xb2, 0x8f, 0xa0, 0x53, 0xcb, 0x1c, 0x5b, 0xd0, 0x26, 0x69, 0x1a, 0xe8, 0xa6, 0x0a, - 0x8f, 0x9b, 0x3e, 0x90, 0x34, 0x5d, 0xc2, 0x56, 0xb8, 0x67, 0xb0, 0xf3, 0x9a, 0x88, 0x73, 0x3a, - 0x5a, 0x52, 0x1f, 0x41, 0x57, 0x25, 0x13, 0xac, 0xd7, 0xd2, 0x51, 0xe3, 0x81, 0xee, 0xc6, 0x86, - 0x4e, 0x85, 0xab, 0x1a, 0x6a, 0x6b, 0xd4, 0x29, 0x11, 0xde, 0xc7, 0xaf, 0x73, 0x13, 0x5d, 0xcf, - 0x4d, 0x74, 0x33, 0x37, 0xd1, 0xef, 0xb9, 0x89, 0xbe, 0x2c, 0xcc, 0xc6, 0xcd, 0xc2, 0x6c, 0xfc, - 0x58, 0x98, 0x8d, 0xb3, 0x67, 0x51, 0x2c, 0xcf, 0xf3, 0xd0, 0x19, 0x72, 0xe6, 0xae, 0x3e, 0xcb, - 0xea, 0xb3, 0x7c, 0x77, 0xeb, 0x4f, 0x36, 0xdc, 0x52, 0xf3, 0xa7, 0x7f, 0x03, 0x00, 0x00, 0xff, - 0xff, 0xfe, 0xe0, 0x3d, 0x9c, 0xcd, 0x03, 0x00, 0x00, + // 513 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x93, 0x4f, 0x6f, 0xd3, 0x30, + 0x18, 0xc6, 0xeb, 0xa5, 0x6c, 0xed, 0x5b, 0xba, 0x56, 0x16, 0x12, 0x61, 0x68, 0x49, 0xc9, 0x01, + 0x4d, 0x9a, 0x94, 0x48, 0xec, 0x80, 0x40, 0x48, 0x13, 0x05, 0x34, 0xfe, 0x68, 0x08, 0x45, 0xc0, + 0x61, 0x97, 0xc8, 0x69, 0x4c, 0x16, 0xad, 0x8e, 0xa3, 0x38, 0xa9, 0xda, 0x1b, 0x1f, 0x81, 0x23, + 0xc7, 0x1d, 0xe1, 0x1b, 0xf0, 0x11, 0x76, 0xdc, 0x91, 0x13, 0xa0, 0xf6, 0xc2, 0xc7, 0x40, 0x71, + 0x62, 0xd2, 0x76, 0xbb, 0x39, 0x7e, 0x7e, 0x8f, 0x9d, 0xe7, 0xb1, 0x5e, 0xd8, 0xcd, 0x68, 0x1c, + 0xd0, 0x94, 0x45, 0x71, 0xe6, 0x64, 0xb3, 0x84, 0x0a, 0x27, 0x21, 0x29, 0x61, 0xc2, 0x4e, 0x52, + 0x9e, 0x71, 0xdc, 0xaf, 0x65, 0x5b, 0xca, 0x3b, 0xb7, 0x42, 0x1e, 0x72, 0x29, 0x3a, 0xc5, 0xaa, + 0xe4, 0x76, 0x8c, 0x90, 0xf3, 0x70, 0x4c, 0x1d, 0xf9, 0xe5, 0xe7, 0x9f, 0x9c, 0x20, 0x4f, 0x49, + 0x16, 0xf1, 0xb8, 0xd4, 0xad, 0xcf, 0x1b, 0xd0, 0x7b, 0xc6, 0x63, 0x41, 0x63, 0x91, 0x8b, 0x77, + 0xf2, 0x06, 0x7c, 0x00, 0x37, 0xfc, 0x31, 0x1f, 0x9d, 0xe9, 0x68, 0x80, 0xf6, 0x3a, 0x0f, 0x76, + 0xed, 0xf5, 0xbb, 0xec, 0x61, 0x21, 0x97, 0xb4, 0x5b, 0xb2, 0xf8, 0x09, 0xb4, 0xe8, 0x24, 0x0a, + 0x68, 0x3c, 0xa2, 0xfa, 0x86, 0xf4, 0x0d, 0xae, 0xfa, 0x5e, 0x54, 0x44, 0x65, 0xfd, 0xef, 0xc0, + 0x87, 0xd0, 0x9e, 0x90, 0x71, 0x14, 0x90, 0x8c, 0xa7, 0xba, 0x26, 0xed, 0xf7, 0xae, 0xda, 0x3f, + 0x2a, 0xa4, 0xf2, 0xd7, 0x1e, 0xfc, 0x08, 0xb6, 0x26, 0x34, 0x15, 0x11, 0x8f, 0xf5, 0xa6, 0xb4, + 0x9b, 0xd7, 0xd8, 0x4b, 0xa0, 0x32, 0x2b, 0xde, 0x7a, 0x05, 0x9d, 0xa5, 0x3c, 0xf8, 0x2e, 0xb4, + 0x19, 0x99, 0x7a, 0xfe, 0x2c, 0xa3, 0x42, 0x36, 0xa0, 0xb9, 0x2d, 0x46, 0xa6, 0xc3, 0xe2, 0x1b, + 0xdf, 0x86, 0xad, 0x42, 0x0c, 0x89, 0x90, 0x21, 0x35, 0x77, 0x93, 0x91, 0xe9, 0x11, 0x11, 0xaf, + 0x9b, 0x2d, 0xad, 0xdf, 0xb4, 0xbe, 0x23, 0xd8, 0x5e, 0xcd, 0x88, 0xf7, 0x01, 0x17, 0x0e, 0x12, + 0x52, 0x2f, 0xce, 0x99, 0x27, 0xcb, 0x52, 0xe7, 0xf6, 0x18, 0x99, 0x3e, 0x0d, 0xe9, 0xdb, 0x9c, + 0xc9, 0x1f, 0x10, 0xf8, 0x18, 0xfa, 0x0a, 0x56, 0xef, 0x54, 0x95, 0x79, 0xc7, 0x2e, 0x1f, 0xd2, + 0x56, 0x0f, 0x69, 0x3f, 0xaf, 0x80, 0x61, 0xeb, 0xe2, 0x97, 0xd9, 0xf8, 0xfa, 0xdb, 0x44, 0xee, + 0x76, 0x79, 0x9e, 0x52, 0x56, 0xa3, 0x68, 0xab, 0x51, 0xac, 0x43, 0xe8, 0xad, 0xf5, 0x89, 0x2d, + 0xe8, 0x26, 0xb9, 0xef, 0x9d, 0xd1, 0x99, 0x27, 0x1b, 0xd3, 0xd1, 0x40, 0xdb, 0x6b, 0xbb, 0x9d, + 0x24, 0xf7, 0xdf, 0xd0, 0xd9, 0xfb, 0x62, 0xeb, 0x71, 0xeb, 0xc7, 0xb9, 0x89, 0xfe, 0x9e, 0x9b, + 0xc8, 0xda, 0x87, 0xee, 0x4a, 0xa3, 0xb8, 0x0f, 0x1a, 0x49, 0x12, 0x99, 0xad, 0xe9, 0x16, 0xcb, + 0x25, 0xf8, 0x04, 0x6e, 0xbe, 0x24, 0xe2, 0x94, 0x06, 0x15, 0x7b, 0x1f, 0x7a, 0xb2, 0x0a, 0x6f, + 0xbd, 0xeb, 0xae, 0xdc, 0x3e, 0x56, 0x85, 0x5b, 0xd0, 0xad, 0xb9, 0xba, 0xf6, 0x8e, 0xa2, 0x8e, + 0x88, 0x18, 0x7e, 0xf8, 0x36, 0x37, 0xd0, 0xc5, 0xdc, 0x40, 0x97, 0x73, 0x03, 0xfd, 0x99, 0x1b, + 0xe8, 0xcb, 0xc2, 0x68, 0x5c, 0x2e, 0x8c, 0xc6, 0xcf, 0x85, 0xd1, 0x38, 0x79, 0x18, 0x46, 0xd9, + 0x69, 0xee, 0xdb, 0x23, 0xce, 0x9c, 0xe5, 0x99, 0xaa, 0x97, 0xe5, 0xd0, 0xac, 0xcf, 0x9b, 0xbf, + 0x29, 0xf7, 0x0f, 0xfe, 0x05, 0x00, 0x00, 0xff, 0xff, 0x48, 0xd2, 0x61, 0x14, 0x8a, 0x03, 0x00, + 0x00, } func (this *ConsensusParams) Equal(that interface{}) bool { @@ -453,16 +440,16 @@ func (this *ConsensusParams) Equal(that interface{}) bool { } else if this == nil { return false } - if !this.Block.Equal(&that1.Block) { + if !this.Block.Equal(that1.Block) { return false } - if !this.Evidence.Equal(&that1.Evidence) { + if !this.Evidence.Equal(that1.Evidence) { return false } - if !this.Validator.Equal(&that1.Validator) { + if !this.Validator.Equal(that1.Validator) { return false } - if !this.Version.Equal(&that1.Version) { + if !this.Version.Equal(that1.Version) { return false } return true @@ -492,9 +479,6 @@ func (this *BlockParams) Equal(that interface{}) bool { if this.MaxGas != that1.MaxGas { return false } - if this.TimeIotaMs != that1.TimeIotaMs { - return false - } return true } func (this *EvidenceParams) Equal(that interface{}) bool { @@ -575,7 +559,7 @@ func (this *VersionParams) Equal(that interface{}) bool { } else if this == nil { return false } - if this.AppVersion != that1.AppVersion { + if this.App != that1.App { return false } return true @@ -627,46 +611,54 @@ func (m *ConsensusParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - { - size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.Version != nil { + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintParams(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 } - i-- - dAtA[i] = 0x22 - { - size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.Validator != nil { + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintParams(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a } - i-- - dAtA[i] = 0x1a - { - size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.Evidence != nil { + { + size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintParams(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 } - i-- - dAtA[i] = 0x12 - { - size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.Block != nil { + { + size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintParams(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa } - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -690,11 +682,6 @@ func (m *BlockParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.TimeIotaMs != 0 { - i = encodeVarintParams(dAtA, i, uint64(m.TimeIotaMs)) - i-- - dAtA[i] = 0x18 - } if m.MaxGas != 0 { i = encodeVarintParams(dAtA, i, uint64(m.MaxGas)) i-- @@ -801,8 +788,8 @@ func (m *VersionParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.AppVersion != 0 { - i = encodeVarintParams(dAtA, i, uint64(m.AppVersion)) + if m.App != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.App)) i-- dAtA[i] = 0x8 } @@ -867,7 +854,7 @@ func NewPopulatedValidatorParams(r randyParams, easy bool) *ValidatorParams { func NewPopulatedVersionParams(r randyParams, easy bool) *VersionParams { this := &VersionParams{} - this.AppVersion = uint64(uint64(r.Uint32())) + this.App = uint64(uint64(r.Uint32())) if !easy && r.Intn(10) != 0 { } return this @@ -951,14 +938,22 @@ func (m *ConsensusParams) Size() (n int) { } var l int _ = l - l = m.Block.Size() - n += 1 + l + sovParams(uint64(l)) - l = m.Evidence.Size() - n += 1 + l + sovParams(uint64(l)) - l = m.Validator.Size() - n += 1 + l + sovParams(uint64(l)) - l = m.Version.Size() - n += 1 + l + sovParams(uint64(l)) + if m.Block != nil { + l = m.Block.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Evidence != nil { + l = m.Evidence.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Validator != nil { + l = m.Validator.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Version != nil { + l = m.Version.Size() + n += 1 + l + sovParams(uint64(l)) + } return n } @@ -974,9 +969,6 @@ func (m *BlockParams) Size() (n int) { if m.MaxGas != 0 { n += 1 + sovParams(uint64(m.MaxGas)) } - if m.TimeIotaMs != 0 { - n += 1 + sovParams(uint64(m.TimeIotaMs)) - } return n } @@ -1018,8 +1010,8 @@ func (m *VersionParams) Size() (n int) { } var l int _ = l - if m.AppVersion != 0 { - n += 1 + sovParams(uint64(m.AppVersion)) + if m.App != 0 { + n += 1 + sovParams(uint64(m.App)) } return n } @@ -1103,6 +1095,9 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + if m.Block == nil { + m.Block = &BlockParams{} + } if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1136,6 +1131,9 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + if m.Evidence == nil { + m.Evidence = &EvidenceParams{} + } if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1169,6 +1167,9 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + if m.Validator == nil { + m.Validator = &ValidatorParams{} + } if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1202,6 +1203,9 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + if m.Version == nil { + m.Version = &VersionParams{} + } if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1294,25 +1298,6 @@ func (m *BlockParams) Unmarshal(dAtA []byte) error { break } } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TimeIotaMs", wireType) - } - m.TimeIotaMs = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowParams - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.TimeIotaMs |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) @@ -1568,9 +1553,9 @@ func (m *VersionParams) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AppVersion", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field App", wireType) } - m.AppVersion = 0 + m.App = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowParams @@ -1580,7 +1565,7 @@ func (m *VersionParams) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.AppVersion |= uint64(b&0x7F) << shift + m.App |= uint64(b&0x7F) << shift if b < 0x80 { break } diff --git a/proto/tendermint/types/params.proto b/proto/tendermint/types/params.proto index 0de7d846f..195aa8d17 100644 --- a/proto/tendermint/types/params.proto +++ b/proto/tendermint/types/params.proto @@ -11,10 +11,10 @@ option (gogoproto.equal_all) = true; // ConsensusParams contains consensus critical parameters that determine the // validity of blocks. message ConsensusParams { - BlockParams block = 1 [(gogoproto.nullable) = false]; - EvidenceParams evidence = 2 [(gogoproto.nullable) = false]; - ValidatorParams validator = 3 [(gogoproto.nullable) = false]; - VersionParams version = 4 [(gogoproto.nullable) = false]; + BlockParams block = 1; + EvidenceParams evidence = 2; + ValidatorParams validator = 3; + VersionParams version = 4; } // BlockParams contains limits on the block size. @@ -25,11 +25,8 @@ message BlockParams { // Max gas per block. // Note: must be greater or equal to -1 int64 max_gas = 2; - // Minimum time increment between consecutive blocks (in milliseconds) If the - // block header timestamp is ahead of the system clock, decrease this value. - // - // Not exposed to the application. - int64 time_iota_ms = 3; + + reserved 3; // was TimeIotaMs see https://github.com/tendermint/tendermint/pull/5792 } // EvidenceParams determine how we handle evidence of malfeasance. @@ -68,7 +65,7 @@ message VersionParams { option (gogoproto.populate) = true; option (gogoproto.equal) = true; - uint64 app_version = 1; + uint64 app = 1; } // HashedParams is a subset of ConsensusParams. diff --git a/proxy/app_conn.go b/proxy/app_conn.go index e69daba9d..f3ac18f18 100644 --- a/proxy/app_conn.go +++ b/proxy/app_conn.go @@ -18,7 +18,8 @@ type AppConnConsensus interface { Error() error InitChainSync(types.RequestInitChain) (*types.ResponseInitChain, error) - + PrepareProposalSync(types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) + ProcessProposalSync(types.RequestProcessProposal) (*types.ResponseProcessProposal, error) BeginBlockSync(types.RequestBeginBlock) (*types.ResponseBeginBlock, error) DeliverTxAsync(types.RequestDeliverTx) *abcicli.ReqRes EndBlockSync(types.RequestEndBlock) (*types.ResponseEndBlock, error) @@ -42,8 +43,6 @@ type AppConnQuery interface { EchoSync(string) (*types.ResponseEcho, error) InfoSync(types.RequestInfo) (*types.ResponseInfo, error) QuerySync(types.RequestQuery) (*types.ResponseQuery, error) - - // SetOptionSync(key string, value string) (res types.Result) } type AppConnSnapshot interface { @@ -63,6 +62,8 @@ type appConnConsensus struct { appConn abcicli.Client } +var _ AppConnConsensus = (*appConnConsensus)(nil) + func NewAppConnConsensus(appConn abcicli.Client, metrics *Metrics) AppConnConsensus { return &appConnConsensus{ metrics: metrics, @@ -83,6 +84,17 @@ func (app *appConnConsensus) InitChainSync(req types.RequestInitChain) (*types.R return app.appConn.InitChainSync(req) } +func (app *appConnConsensus) PrepareProposalSync( + req types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { + defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "prepare_proposal", "type", "sync"))() + return app.appConn.PrepareProposalSync(req) +} + +func (app *appConnConsensus) ProcessProposalSync(req types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { + defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "process_proposal", "type", "sync"))() + return app.appConn.ProcessProposalSync(req) +} + func (app *appConnConsensus) BeginBlockSync(req types.RequestBeginBlock) (*types.ResponseBeginBlock, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "begin_block", "type", "sync"))() return app.appConn.BeginBlockSync(req) diff --git a/proxy/mocks/app_conn_consensus.go b/proxy/mocks/app_conn_consensus.go index d70cd7cc1..eccf74fc3 100644 --- a/proxy/mocks/app_conn_consensus.go +++ b/proxy/mocks/app_conn_consensus.go @@ -136,6 +136,52 @@ func (_m *AppConnConsensus) InitChainSync(_a0 types.RequestInitChain) (*types.Re return r0, r1 } +// PrepareProposalSync provides a mock function with given fields: _a0 +func (_m *AppConnConsensus) PrepareProposalSync(_a0 types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { + ret := _m.Called(_a0) + + var r0 *types.ResponsePrepareProposal + if rf, ok := ret.Get(0).(func(types.RequestPrepareProposal) *types.ResponsePrepareProposal); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ResponsePrepareProposal) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(types.RequestPrepareProposal) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ProcessProposalSync provides a mock function with given fields: _a0 +func (_m *AppConnConsensus) ProcessProposalSync(_a0 types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { + ret := _m.Called(_a0) + + var r0 *types.ResponseProcessProposal + if rf, ok := ret.Get(0).(func(types.RequestProcessProposal) *types.ResponseProcessProposal); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ResponseProcessProposal) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(types.RequestProcessProposal) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // SetResponseCallback provides a mock function with given fields: _a0 func (_m *AppConnConsensus) SetResponseCallback(_a0 abcicli.Callback) { _m.Called(_a0) diff --git a/proxy/version.go b/proxy/version.go index be890e12e..110757028 100644 --- a/proxy/version.go +++ b/proxy/version.go @@ -12,4 +12,5 @@ var RequestInfo = abci.RequestInfo{ Version: version.TMCoreSemVer, BlockVersion: version.BlockProtocol, P2PVersion: version.P2PProtocol, + AbciVersion: version.ABCIVersion, } diff --git a/rpc/client/evidence_test.go b/rpc/client/evidence_test.go index 527b8a9b5..a813d3912 100644 --- a/rpc/client/evidence_test.go +++ b/rpc/client/evidence_test.go @@ -45,7 +45,9 @@ func newEvidence(t *testing.T, val *privval.FilePV, validator := types.NewValidator(val.Key.PubKey, 10) valSet := types.NewValidatorSet([]*types.Validator{validator}) - return types.NewDuplicateVoteEvidence(vote, vote2, defaultTestTime, valSet) + ev, err := types.NewDuplicateVoteEvidence(vote, vote2, defaultTestTime, valSet) + require.NoError(t, err) + return ev } func makeEvidences( diff --git a/rpc/client/helpers.go b/rpc/client/helpers.go index 0878df6a8..8014d875a 100644 --- a/rpc/client/helpers.go +++ b/rpc/client/helpers.go @@ -70,7 +70,7 @@ func WaitForOneEvent(c EventsClient, evtTyp string, timeout time.Duration) (type // make sure to unregister after the test is over defer func() { if deferErr := c.UnsubscribeAll(ctx, subscriber); deferErr != nil { - panic(err) + panic(deferErr) } }() diff --git a/rpc/core/tx.go b/rpc/core/tx.go index 8e800a549..aa14cab13 100644 --- a/rpc/core/tx.go +++ b/rpc/core/tx.go @@ -32,19 +32,16 @@ func Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error return nil, fmt.Errorf("tx (%X) not found", hash) } - height := r.Height - index := r.Index - var proof types.TxProof if prove { - block := env.BlockStore.LoadBlock(height) - proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines + block := env.BlockStore.LoadBlock(r.Height) + proof = block.Data.Txs.Proof(int(r.Index)) } return &ctypes.ResultTx{ Hash: hash, - Height: height, - Index: index, + Height: r.Height, + Index: r.Index, TxResult: r.Result, Tx: r.Tx, Proof: proof, @@ -118,7 +115,7 @@ func TxSearch( var proof types.TxProof if prove { block := env.BlockStore.LoadBlock(r.Height) - proof = block.Data.Txs.Proof(int(r.Index)) // XXX: overflow on 32-bit machines + proof = block.Data.Txs.Proof(int(r.Index)) } apiResults = append(apiResults, &ctypes.ResultTx{ diff --git a/rpc/core/types/responses.go b/rpc/core/types/responses.go index 68f3e2b96..747f626a7 100644 --- a/rpc/core/types/responses.go +++ b/rpc/core/types/responses.go @@ -52,7 +52,7 @@ type ResultBlockResults struct { BeginBlockEvents []abci.Event `json:"begin_block_events"` EndBlockEvents []abci.Event `json:"end_block_events"` ValidatorUpdates []abci.ValidatorUpdate `json:"validator_updates"` - ConsensusParamUpdates *abci.ConsensusParams `json:"consensus_param_updates"` + ConsensusParamUpdates *tmproto.ConsensusParams `json:"consensus_param_updates"` } // NewResultCommit is a helper to initialize the ResultCommit with @@ -144,8 +144,8 @@ type ResultValidators struct { // ConsensusParams for given height type ResultConsensusParams struct { - BlockHeight int64 `json:"block_height"` - ConsensusParams tmproto.ConsensusParams `json:"consensus_params"` + BlockHeight int64 `json:"block_height"` + ConsensusParams types.ConsensusParams `json:"consensus_params"` } // Info about the consensus state. diff --git a/state/execution.go b/state/execution.go index 2cc3db6e7..77b39a61a 100644 --- a/state/execution.go +++ b/state/execution.go @@ -9,9 +9,8 @@ import ( cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/libs/fail" "github.com/tendermint/tendermint/libs/log" - mempl "github.com/tendermint/tendermint/mempool" + "github.com/tendermint/tendermint/mempool" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/types" ) @@ -34,7 +33,7 @@ type BlockExecutor struct { // manage the mempool lock during commit // and update both with block results after commit. - mempool mempl.Mempool + mempool mempool.Mempool evpool EvidencePool logger log.Logger @@ -56,7 +55,7 @@ func NewBlockExecutor( stateStore Store, logger log.Logger, proxyApp proxy.AppConnConsensus, - mempool mempl.Mempool, + mempool mempool.Mempool, evpool EvidencePool, options ...BlockExecutorOption, ) *BlockExecutor { @@ -91,11 +90,15 @@ func (blockExec *BlockExecutor) SetEventBus(eventBus types.BlockEventPublisher) // and txs from the mempool. The max bytes must be big enough to fit the commit. // Up to 1/10th of the block space is allcoated for maximum sized evidence. // The rest is given to txs, up to the max gas. +// +// Contract: application will not return more bytes than are sent over the wire. func (blockExec *BlockExecutor) CreateProposalBlock( height int64, - state State, commit *types.Commit, + state State, + commit *types.Commit, proposerAddr []byte, -) (*types.Block, *types.PartSet) { + votes []*types.Vote, +) (*types.Block, error) { maxBytes := state.ConsensusParams.Block.MaxBytes maxGas := state.ConsensusParams.Block.MaxGas @@ -106,8 +109,63 @@ func (blockExec *BlockExecutor) CreateProposalBlock( maxDataBytes := types.MaxDataBytes(maxBytes, evSize, state.Validators.Size()) txs := blockExec.mempool.ReapMaxBytesMaxGas(maxDataBytes, maxGas) + block := state.MakeBlock(height, txs, commit, evidence, proposerAddr) - return state.MakeBlock(height, txs, commit, evidence, proposerAddr) + localLastCommit := buildLastCommitInfo(block, blockExec.store, state.InitialHeight) + rpp, err := blockExec.proxyApp.PrepareProposalSync( + abci.RequestPrepareProposal{ + MaxTxBytes: maxDataBytes, + Txs: block.Txs.ToSliceOfBytes(), + LocalLastCommit: extendedCommitInfo(localLastCommit, votes), + Misbehavior: block.Evidence.Evidence.ToABCI(), + Height: block.Height, + Time: block.Time, + NextValidatorsHash: block.NextValidatorsHash, + ProposerAddress: block.ProposerAddress, + }, + ) + if err != nil { + // The App MUST ensure that only valid (and hence 'processable') transactions + // enter the mempool. Hence, at this point, we can't have any non-processable + // transaction causing an error. + // + // Also, the App can simply skip any transaction that could cause any kind of trouble. + // Either way, we cannot recover in a meaningful way, unless we skip proposing + // this block, repair what caused the error and try again. Hence, we return an + // error for now (the production code calling this function is expected to panic). + return nil, err + } + + txl := types.ToTxs(rpp.Txs) + if err := txl.Validate(maxDataBytes); err != nil { + return nil, err + } + + return state.MakeBlock(height, txl, commit, evidence, proposerAddr), nil +} + +func (blockExec *BlockExecutor) ProcessProposal( + block *types.Block, + state State, +) (bool, error) { + resp, err := blockExec.proxyApp.ProcessProposalSync(abci.RequestProcessProposal{ + Hash: block.Header.Hash(), + Height: block.Header.Height, + Time: block.Header.Time, + Txs: block.Data.Txs.ToSliceOfBytes(), + ProposedLastCommit: buildLastCommitInfo(block, blockExec.store, state.InitialHeight), + Misbehavior: block.Evidence.Evidence.ToABCI(), + ProposerAddress: block.ProposerAddress, + NextValidatorsHash: block.NextValidatorsHash, + }) + if err != nil { + return false, ErrInvalidBlock(err) + } + if resp.IsStatusUnknown() { + panic(fmt.Sprintf("ProcessProposal responded with status %s", resp.Status.String())) + } + + return resp.IsAccepted(), nil } // ValidateBlock validates the given block against the given state. @@ -168,6 +226,10 @@ func (blockExec *BlockExecutor) ApplyBlock( } if len(validatorUpdates) > 0 { blockExec.logger.Debug("updates to validators", "updates", types.ValidatorListString(validatorUpdates)) + blockExec.metrics.ValidatorSetUpdates.Add(1) + } + if abciResponses.EndBlock.ConsensusParamUpdates != nil { + blockExec.metrics.ConsensusParamUpdates.Add(1) } // Update the state with the block and responses. @@ -290,12 +352,7 @@ func execBlockOnProxyApp( } proxyAppConn.SetResponseCallback(proxyCb) - commitInfo := getBeginBlockValidatorInfo(block, store, initialHeight) - - byzVals := make([]abci.Evidence, 0) - for _, evidence := range block.Evidence.Evidence { - byzVals = append(byzVals, evidence.ABCI()...) - } + commitInfo := buildLastCommitInfo(block, store, initialHeight) // Begin block var err error @@ -308,7 +365,7 @@ func execBlockOnProxyApp( Hash: block.Hash(), Header: *pbh, LastCommitInfo: commitInfo, - ByzantineValidators: byzVals, + ByzantineValidators: block.Evidence.Evidence.ToABCI(), }) if err != nil { logger.Error("error in proxyAppConn.BeginBlock", "err", err) @@ -334,48 +391,67 @@ func execBlockOnProxyApp( return abciResponses, nil } -func getBeginBlockValidatorInfo(block *types.Block, store Store, - initialHeight int64) abci.LastCommitInfo { - voteInfos := make([]abci.VoteInfo, block.LastCommit.Size()) - // Initial block -> LastCommitInfo.Votes are empty. - // Remember that the first LastCommit is intentionally empty, so it makes - // sense for LastCommitInfo.Votes to also be empty. - if block.Height > initialHeight { - lastValSet, err := store.LoadValidators(block.Height - 1) - if err != nil { - panic(err) - } +func buildLastCommitInfo(block *types.Block, store Store, initialHeight int64) abci.CommitInfo { + if block.Height == initialHeight { + // there is no last commit for the initial height. + // return an empty value. + return abci.CommitInfo{} + } - // Sanity check that commit size matches validator set size - only applies - // after first block. - var ( - commitSize = block.LastCommit.Size() - valSetLen = len(lastValSet.Validators) - ) - if commitSize != valSetLen { - panic(fmt.Sprintf( - "commit size (%d) doesn't match valset length (%d) at height %d\n\n%v\n\n%v", - commitSize, valSetLen, block.Height, block.LastCommit.Signatures, lastValSet.Validators, - )) - } + lastValSet, err := store.LoadValidators(block.Height - 1) + if err != nil { + panic(fmt.Errorf("failed to load validator set at height %d: %w", block.Height-1, err)) + } - for i, val := range lastValSet.Validators { - commitSig := block.LastCommit.Signatures[i] - voteInfos[i] = abci.VoteInfo{ - Validator: types.TM2PB.Validator(val), - SignedLastBlock: !commitSig.Absent(), - } + var ( + commitSize = block.LastCommit.Size() + valSetLen = len(lastValSet.Validators) + ) + + // ensure that the size of the validator set in the last commit matches + // the size of the validator set in the state store. + if commitSize != valSetLen { + panic(fmt.Sprintf( + "commit size (%d) doesn't match validator set length (%d) at height %d\n\n%v\n\n%v", + commitSize, valSetLen, block.Height, block.LastCommit.Signatures, lastValSet.Validators, + )) + } + + votes := make([]abci.VoteInfo, block.LastCommit.Size()) + for i, val := range lastValSet.Validators { + commitSig := block.LastCommit.Signatures[i] + votes[i] = abci.VoteInfo{ + Validator: types.TM2PB.Validator(val), + SignedLastBlock: commitSig.BlockIDFlag != types.BlockIDFlagAbsent, } } - return abci.LastCommitInfo{ + return abci.CommitInfo{ Round: block.LastCommit.Round, - Votes: voteInfos, + Votes: votes, + } +} + +func extendedCommitInfo(c abci.CommitInfo, votes []*types.Vote) abci.ExtendedCommitInfo { + vs := make([]abci.ExtendedVoteInfo, len(c.Votes)) + for i := range vs { + vs[i] = abci.ExtendedVoteInfo{ + Validator: c.Votes[i].Validator, + SignedLastBlock: c.Votes[i].SignedLastBlock, + /* + TODO: Include vote extensions information when implementing vote extensions. + VoteExtension: []byte{}, + */ + } + } + return abci.ExtendedCommitInfo{ + Round: c.Round, + Votes: vs, } } func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, - params tmproto.ValidatorParams) error { + params types.ValidatorParams) error { for _, valUpdate := range abciUpdates { if valUpdate.GetPower() < 0 { return fmt.Errorf("voting power can't be negative %v", valUpdate) @@ -431,13 +507,13 @@ func updateState( lastHeightParamsChanged := state.LastHeightConsensusParamsChanged if abciResponses.EndBlock.ConsensusParamUpdates != nil { // NOTE: must not mutate s.ConsensusParams - nextParams = types.UpdateConsensusParams(state.ConsensusParams, abciResponses.EndBlock.ConsensusParamUpdates) - err := types.ValidateConsensusParams(nextParams) + nextParams = state.ConsensusParams.Update(abciResponses.EndBlock.ConsensusParamUpdates) + err := nextParams.ValidateBasic() if err != nil { return state, fmt.Errorf("error updating consensus params: %v", err) } - state.Version.Consensus.App = nextParams.Version.AppVersion + state.Version.Consensus.App = nextParams.Version.App // Change results from this height but only applies to the next height. lastHeightParamsChanged = header.Height + 1 diff --git a/state/execution_test.go b/state/execution_test.go index 4db67eda3..b98c35852 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -2,6 +2,7 @@ package state_test import ( "context" + "errors" "testing" "time" @@ -9,16 +10,19 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + abciclientmocks "github.com/tendermint/tendermint/abci/client/mocks" abci "github.com/tendermint/tendermint/abci/types" + abcimocks "github.com/tendermint/tendermint/abci/types/mocks" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/crypto/tmhash" + "github.com/tendermint/tendermint/internal/test" "github.com/tendermint/tendermint/libs/log" - mmock "github.com/tendermint/tendermint/mempool/mock" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + mpmocks "github.com/tendermint/tendermint/mempool/mocks" tmversion "github.com/tendermint/tendermint/proto/tendermint/version" "github.com/tendermint/tendermint/proxy" + pmocks "github.com/tendermint/tendermint/proxy/mocks" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/state/mocks" "github.com/tendermint/tendermint/types" @@ -29,7 +33,6 @@ import ( var ( chainID = "execution_chain" testPartSize uint32 = 65536 - nTxsPerBlock = 10 ) func TestApplyBlock(t *testing.T) { @@ -44,12 +47,24 @@ func TestApplyBlock(t *testing.T) { stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) - + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, sm.EmptyEvidencePool{}) + mp, sm.EmptyEvidencePool{}) - block := makeBlock(state, 1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(state, 1, new(types.Commit)) + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} state, retainHeight, err := blockExec.ApplyBlock(state, blockID, block) require.Nil(t, err) @@ -104,7 +119,7 @@ func TestBeginBlockValidators(t *testing.T) { lastCommit := types.NewCommit(1, 0, prevBlockID, tc.lastCommitSigs) // block for height 2 - block, _ := state.MakeBlock(2, makeTxs(2), lastCommit, nil, state.Validators.GetProposer().Address) + block := makeBlock(state, 2, lastCommit) _, err = sm.ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), stateStore, 1) require.Nil(t, err, tc.desc) @@ -159,7 +174,8 @@ func TestBeginBlockByzantineValidators(t *testing.T) { } // we don't need to worry about validating the evidence as long as they pass validate basic - dve := types.NewMockDuplicateVoteEvidenceWithValidator(3, defaultEvidenceTime, privVal, state.ChainID) + dve, err := types.NewMockDuplicateVoteEvidenceWithValidator(3, defaultEvidenceTime, privVal, state.ChainID) + require.NoError(t, err) dve.ValidatorPower = 1000 lcae := &types.LightClientAttackEvidence{ ConflictingBlock: &types.LightBlock{ @@ -182,16 +198,16 @@ func TestBeginBlockByzantineValidators(t *testing.T) { ev := []types.Evidence{dve, lcae} - abciEv := []abci.Evidence{ + abciMb := []abci.Misbehavior{ { - Type: abci.EvidenceType_DUPLICATE_VOTE, + Type: abci.MisbehaviorType_DUPLICATE_VOTE, Height: 3, Time: defaultEvidenceTime, Validator: types.TM2PB.Validator(state.Validators.Validators[0]), TotalVotingPower: 10, }, { - Type: abci.EvidenceType_LIGHT_CLIENT_ATTACK, + Type: abci.MisbehaviorType_LIGHT_CLIENT_ATTACK, Height: 8, Time: defaultEvidenceTime, Validator: types.TM2PB.Validator(state.Validators.Validators[0]), @@ -203,21 +219,117 @@ func TestBeginBlockByzantineValidators(t *testing.T) { evpool.On("PendingEvidence", mock.AnythingOfType("int64")).Return(ev, int64(100)) evpool.On("Update", mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return() evpool.On("CheckEvidence", mock.AnythingOfType("types.EvidenceList")).Return(nil) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, evpool) + mp, evpool) - block := makeBlock(state, 1) + block := makeBlock(state, 1, new(types.Commit)) block.Evidence = types.EvidenceData{Evidence: ev} block.Header.EvidenceHash = block.Evidence.Hash() - blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + + blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} state, retainHeight, err := blockExec.ApplyBlock(state, blockID, block) require.Nil(t, err) assert.EqualValues(t, retainHeight, 1) // TODO check state and mempool - assert.Equal(t, abciEv, app.ByzantineValidators) + assert.Equal(t, abciMb, app.Misbehavior) +} + +func TestProcessProposal(t *testing.T) { + const height = 2 + txs := test.MakeNTxs(height, 10) + + logger := log.NewNopLogger() + app := abcimocks.NewBaseMock() + app.On("ProcessProposal", mock.Anything).Return(abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}) + + cc := proxy.NewLocalClientCreator(app) + proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) + err := proxyApp.Start() + require.NoError(t, err) + defer proxyApp.Stop() //nolint:errcheck // ignore for tests + + state, stateDB, privVals := makeState(1, height) + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + + eventBus := types.NewEventBus() + err = eventBus.Start() + require.NoError(t, err) + + blockExec := sm.NewBlockExecutor( + stateStore, + logger, + proxyApp.Consensus(), + new(mpmocks.Mempool), + sm.EmptyEvidencePool{}, + ) + + block0 := makeBlock(state, height-1, new(types.Commit)) + lastCommitSig := []types.CommitSig{} + partSet, err := block0.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) + blockID := types.BlockID{Hash: block0.Hash(), PartSetHeader: partSet.Header()} + voteInfos := []abci.VoteInfo{} + for _, privVal := range privVals { + pk, err := privVal.GetPubKey() + require.NoError(t, err) + idx, _ := state.Validators.GetByAddress(pk.Address()) + vote, err := test.MakeVote(privVal, block0.Header.ChainID, idx, height-1, 0, 2, blockID, time.Now()) + require.NoError(t, err) + addr := pk.Address() + voteInfos = append(voteInfos, + abci.VoteInfo{ + SignedLastBlock: true, + Validator: abci.Validator{ + Address: addr, + Power: 1000, + }, + }) + lastCommitSig = append(lastCommitSig, vote.CommitSig()) + } + + block1 := makeBlock(state, height, &types.Commit{ + Height: height - 1, + Signatures: lastCommitSig, + }) + block1.Txs = txs + + expectedRpp := abci.RequestProcessProposal{ + Txs: block1.Txs.ToSliceOfBytes(), + Hash: block1.Hash(), + Height: block1.Header.Height, + Time: block1.Header.Time, + Misbehavior: block1.Evidence.Evidence.ToABCI(), + ProposedLastCommit: abci.CommitInfo{ + Round: 0, + Votes: voteInfos, + }, + NextValidatorsHash: block1.NextValidatorsHash, + ProposerAddress: block1.ProposerAddress, + } + + acceptBlock, err := blockExec.ProcessProposal(block1, state) + require.NoError(t, err) + require.True(t, acceptBlock) + app.AssertExpectations(t) + app.AssertCalled(t, "ProcessProposal", expectedRpp) } func TestValidateValidatorUpdates(t *testing.T) { @@ -228,13 +340,13 @@ func TestValidateValidatorUpdates(t *testing.T) { pk2, err := cryptoenc.PubKeyToProto(pubkey2) assert.NoError(t, err) - defaultValidatorParams := tmproto.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}} + defaultValidatorParams := types.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}} testCases := []struct { name string abciUpdates []abci.ValidatorUpdate - validatorParams tmproto.ValidatorParams + validatorParams types.ValidatorParams shouldErr bool }{ @@ -363,12 +475,24 @@ func TestEndBlockValidatorUpdates(t *testing.T) { stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{}) blockExec := sm.NewBlockExecutor( stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, + mp, sm.EmptyEvidencePool{}, ) @@ -386,8 +510,10 @@ func TestEndBlockValidatorUpdates(t *testing.T) { ) require.NoError(t, err) - block := makeBlock(state, 1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(state, 1, new(types.Commit)) + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} pubkey := ed25519.GenPrivKey().PubKey() pk, err := cryptoenc.PubKeyToProto(pubkey) @@ -440,12 +566,14 @@ func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, + new(mpmocks.Mempool), sm.EmptyEvidencePool{}, ) - block := makeBlock(state, 1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(state, 1, new(types.Commit)) + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} vp, err := cryptoenc.PubKeyToProto(state.Validators.Validators[0].PubKey) require.NoError(t, err) @@ -459,6 +587,244 @@ func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { assert.NotEmpty(t, state.NextValidators.Validators) } +func TestEmptyPrepareProposal(t *testing.T) { + const height = 2 + + app := abcimocks.NewBaseMock() + cc := proxy.NewLocalClientCreator(app) + proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) + err := proxyApp.Start() + require.NoError(t, err) + defer proxyApp.Stop() //nolint:errcheck // ignore for tests + + state, stateDB, privVals := makeState(1, height) + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{}) + + blockExec := sm.NewBlockExecutor( + stateStore, + log.TestingLogger(), + proxyApp.Consensus(), + mp, + sm.EmptyEvidencePool{}, + ) + pa, _ := state.Validators.GetByIndex(0) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + require.NoError(t, err) + _, err = blockExec.CreateProposalBlock(height, state, commit, pa, nil) + require.NoError(t, err) +} + +// TestPrepareProposalTxsAllIncluded tests that any transactions included in +// the prepare proposal response are included in the block. +func TestPrepareProposalTxsAllIncluded(t *testing.T) { + const height = 2 + + state, stateDB, privVals := makeState(1, height) + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + + evpool := &mocks.EvidencePool{} + evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0)) + + txs := test.MakeNTxs(height, 10) + mp := &mpmocks.Mempool{} + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs[2:])) + + app := abcimocks.NewBaseMock() + app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{ + Txs: types.Txs(txs).ToSliceOfBytes(), + }) + cc := proxy.NewLocalClientCreator(app) + proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) + err := proxyApp.Start() + require.NoError(t, err) + defer proxyApp.Stop() //nolint:errcheck // ignore for tests + + blockExec := sm.NewBlockExecutor( + stateStore, + log.TestingLogger(), + proxyApp.Consensus(), + mp, + evpool, + ) + pa, _ := state.Validators.GetByIndex(0) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + require.NoError(t, err) + block, err := blockExec.CreateProposalBlock(height, state, commit, pa, nil) + require.NoError(t, err) + + for i, tx := range block.Data.Txs { + require.Equal(t, txs[i], tx) + } + + mp.AssertExpectations(t) +} + +// TestPrepareProposalReorderTxs tests that CreateBlock produces a block with transactions +// in the order matching the order they are returned from PrepareProposal. +func TestPrepareProposalReorderTxs(t *testing.T) { + const height = 2 + + state, stateDB, privVals := makeState(1, height) + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + + evpool := &mocks.EvidencePool{} + evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0)) + + txs := test.MakeNTxs(height, 10) + mp := &mpmocks.Mempool{} + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs)) + + txs = txs[2:] + txs = append(txs[len(txs)/2:], txs[:len(txs)/2]...) + + app := abcimocks.NewBaseMock() + app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{ + Txs: types.Txs(txs).ToSliceOfBytes(), + }) + + cc := proxy.NewLocalClientCreator(app) + proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) + err := proxyApp.Start() + require.NoError(t, err) + defer proxyApp.Stop() //nolint:errcheck // ignore for tests + + blockExec := sm.NewBlockExecutor( + stateStore, + log.TestingLogger(), + proxyApp.Consensus(), + mp, + evpool, + ) + pa, _ := state.Validators.GetByIndex(0) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + require.NoError(t, err) + block, err := blockExec.CreateProposalBlock(height, state, commit, pa, nil) + require.NoError(t, err) + for i, tx := range block.Data.Txs { + require.Equal(t, txs[i], tx) + } + + mp.AssertExpectations(t) + +} + +// TestPrepareProposalErrorOnTooManyTxs tests that the block creation logic returns +// an error if the ResponsePrepareProposal returned from the application is invalid. +func TestPrepareProposalErrorOnTooManyTxs(t *testing.T) { + const height = 2 + + state, stateDB, privVals := makeState(1, height) + // limit max block size + state.ConsensusParams.Block.MaxBytes = 60 * 1024 + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + + evpool := &mocks.EvidencePool{} + evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0)) + + const nValidators = 1 + var bytesPerTx int64 = 3 + maxDataBytes := types.MaxDataBytes(state.ConsensusParams.Block.MaxBytes, 0, nValidators) + txs := test.MakeNTxs(height, maxDataBytes/bytesPerTx+2) // +2 so that tx don't fit + mp := &mpmocks.Mempool{} + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs)) + + app := abcimocks.NewBaseMock() + app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{ + Txs: types.Txs(txs).ToSliceOfBytes(), + }) + + cc := proxy.NewLocalClientCreator(app) + proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) + err := proxyApp.Start() + require.NoError(t, err) + defer proxyApp.Stop() //nolint:errcheck // ignore for tests + + blockExec := sm.NewBlockExecutor( + stateStore, + log.NewNopLogger(), + proxyApp.Consensus(), + mp, + evpool, + ) + pa, _ := state.Validators.GetByIndex(0) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + require.NoError(t, err) + + block, err := blockExec.CreateProposalBlock(height, state, commit, pa, nil) + require.Nil(t, block) + require.ErrorContains(t, err, "transaction data size exceeds maximum") + + mp.AssertExpectations(t) +} + +// TestPrepareProposalErrorOnPrepareProposalError tests when the client returns an error +// upon calling PrepareProposal on it. +func TestPrepareProposalErrorOnPrepareProposalError(t *testing.T) { + const height = 2 + + state, stateDB, privVals := makeState(1, height) + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + + evpool := &mocks.EvidencePool{} + evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0)) + + txs := test.MakeNTxs(height, 10) + mp := &mpmocks.Mempool{} + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs)) + + cm := &abciclientmocks.Client{} + cm.On("SetLogger", mock.Anything).Return() + cm.On("Start").Return(nil) + cm.On("Quit").Return(nil) + cm.On("PrepareProposalSync", mock.Anything).Return(nil, errors.New("an injected error")).Once() + cm.On("Stop").Return(nil) + cc := &pmocks.ClientCreator{} + cc.On("NewABCIClient").Return(cm, nil) + proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) + err := proxyApp.Start() + require.NoError(t, err) + defer proxyApp.Stop() //nolint:errcheck // ignore for tests + + blockExec := sm.NewBlockExecutor( + stateStore, + log.NewNopLogger(), + proxyApp.Consensus(), + mp, + evpool, + ) + pa, _ := state.Validators.GetByIndex(0) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + require.NoError(t, err) + + block, err := blockExec.CreateProposalBlock(height, state, commit, pa, nil) + require.Nil(t, block) + require.ErrorContains(t, err, "an injected error") + + mp.AssertExpectations(t) +} + func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.BlockID { var ( h = make([]byte, tmhash.Size) diff --git a/state/export_test.go b/state/export_test.go index f6ca0e9cd..7ab180916 100644 --- a/state/export_test.go +++ b/state/export_test.go @@ -5,7 +5,6 @@ import ( abci "github.com/tendermint/tendermint/abci/types" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) @@ -36,7 +35,7 @@ func UpdateState( // ValidateValidatorUpdates is an alias for validateValidatorUpdates exported // from execution.go, exclusively and explicitly for testing. -func ValidateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, params tmproto.ValidatorParams) error { +func ValidateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, params types.ValidatorParams) error { return validateValidatorUpdates(abciUpdates, params) } diff --git a/state/helpers_test.go b/state/helpers_test.go index 12f57733e..66c115ede 100644 --- a/state/helpers_test.go +++ b/state/helpers_test.go @@ -3,6 +3,7 @@ package state_test import ( "bytes" "fmt" + "testing" "time" dbm "github.com/tendermint/tm-db" @@ -10,7 +11,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" - tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/internal/test" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/proxy" @@ -21,7 +22,7 @@ import ( type paramsChangeTestCase struct { height int64 - params tmproto.ConsensusParams + params types.ConsensusParams } func newTestApp() proxy.AppConns { @@ -54,19 +55,34 @@ func makeAndCommitGoodBlock( func makeAndApplyGoodBlock(state sm.State, height int64, lastCommit *types.Commit, proposerAddr []byte, blockExec *sm.BlockExecutor, evidence []types.Evidence) (sm.State, types.BlockID, error) { - block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, evidence, proposerAddr) + block := state.MakeBlock(height, test.MakeNTxs(height, 10), lastCommit, evidence, proposerAddr) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) + if err != nil { + return state, types.BlockID{}, err + } + if err := blockExec.ValidateBlock(state, block); err != nil { return state, types.BlockID{}, err } blockID := types.BlockID{Hash: block.Hash(), - PartSetHeader: types.PartSetHeader{Total: 3, Hash: tmrand.Bytes(32)}} - state, _, err := blockExec.ApplyBlock(state, blockID, block) + PartSetHeader: partSet.Header()} + state, _, err = blockExec.ApplyBlock(state, blockID, block) if err != nil { return state, types.BlockID{}, err } return state, blockID, nil } +func makeBlock(state sm.State, height int64, c *types.Commit) *types.Block { + return state.MakeBlock( + height, + test.MakeNTxs(state.LastBlockHeight, 10), + c, + nil, + state.Validators.GetProposer().Address, + ) +} + func makeValidCommit( height int64, blockID types.BlockID, @@ -85,14 +101,6 @@ func makeValidCommit( return types.NewCommit(height, 0, blockID, sigs), nil } -// make some bogus txs -func makeTxs(height int64) (txs []types.Tx) { - for i := 0; i < nTxsPerBlock; i++ { - txs = append(txs, types.Tx([]byte{byte(height), byte(i)})) - } - return txs -} - func makeState(nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValidator) { vals := make([]types.GenesisValidator, nVals) privVals := make(map[string]types.PrivValidator, nVals) @@ -133,17 +141,6 @@ func makeState(nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValida return s, stateDB, privVals } -func makeBlock(state sm.State, height int64) *types.Block { - block, _ := state.MakeBlock( - height, - makeTxs(state.LastBlockHeight), - new(types.Commit), - nil, - state.Validators.GetProposer().Address, - ) - return block -} - func genValSet(size int) *types.ValidatorSet { vals := make([]*types.Validator, size) for i := 0; i < size; i++ { @@ -153,11 +150,12 @@ func genValSet(size int) *types.ValidatorSet { } func makeHeaderPartsResponsesValPubKeyChange( + t *testing.T, state sm.State, pubkey crypto.PubKey, ) (types.Header, types.BlockID, *tmstate.ABCIResponses) { - block := makeBlock(state, state.LastBlockHeight+1) + block := makeBlock(state, state.LastBlockHeight+1, new(types.Commit)) abciResponses := &tmstate.ABCIResponses{ BeginBlock: &abci.ResponseBeginBlock{}, EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil}, @@ -177,11 +175,12 @@ func makeHeaderPartsResponsesValPubKeyChange( } func makeHeaderPartsResponsesValPowerChange( + t *testing.T, state sm.State, power int64, ) (types.Header, types.BlockID, *tmstate.ABCIResponses) { - block := makeBlock(state, state.LastBlockHeight+1) + block := makeBlock(state, state.LastBlockHeight+1, new(types.Commit)) abciResponses := &tmstate.ABCIResponses{ BeginBlock: &abci.ResponseBeginBlock{}, EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil}, @@ -201,14 +200,15 @@ func makeHeaderPartsResponsesValPowerChange( } func makeHeaderPartsResponsesParams( + t *testing.T, state sm.State, params tmproto.ConsensusParams, ) (types.Header, types.BlockID, *tmstate.ABCIResponses) { - block := makeBlock(state, state.LastBlockHeight+1) + block := makeBlock(state, state.LastBlockHeight+1, new(types.Commit)) abciResponses := &tmstate.ABCIResponses{ BeginBlock: &abci.ResponseBeginBlock{}, - EndBlock: &abci.ResponseEndBlock{ConsensusParamUpdates: types.TM2PB.ConsensusParams(¶ms)}, + EndBlock: &abci.ResponseEndBlock{ConsensusParamUpdates: ¶ms}, } return block.Header, types.BlockID{Hash: block.Hash(), PartSetHeader: types.PartSetHeader{}}, abciResponses } @@ -235,9 +235,9 @@ func randomGenesisDoc() *types.GenesisDoc { type testApp struct { abci.BaseApplication - CommitVotes []abci.VoteInfo - ByzantineValidators []abci.Evidence - ValidatorUpdates []abci.ValidatorUpdate + CommitVotes []abci.VoteInfo + Misbehavior []abci.Misbehavior + ValidatorUpdates []abci.ValidatorUpdate } var _ abci.Application = (*testApp)(nil) @@ -248,16 +248,16 @@ func (app *testApp) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) { func (app *testApp) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock { app.CommitVotes = req.LastCommitInfo.Votes - app.ByzantineValidators = req.ByzantineValidators + app.Misbehavior = req.ByzantineValidators return abci.ResponseBeginBlock{} } func (app *testApp) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock { return abci.ResponseEndBlock{ ValidatorUpdates: app.ValidatorUpdates, - ConsensusParamUpdates: &abci.ConsensusParams{ + ConsensusParamUpdates: &tmproto.ConsensusParams{ Version: &tmproto.VersionParams{ - AppVersion: 1}}} + App: 1}}} } func (app *testApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { @@ -275,3 +275,12 @@ func (app *testApp) Commit() abci.ResponseCommit { func (app *testApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { return } + +func (app *testApp) ProcessProposal(req abci.RequestProcessProposal) abci.ResponseProcessProposal { + for _, tx := range req.Txs { + if len(tx) == 0 { + return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT} + } + } + return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT} +} diff --git a/state/metrics.gen.go b/state/metrics.gen.go index 288f1d7cf..1ce2c4de1 100644 --- a/state/metrics.gen.go +++ b/state/metrics.gen.go @@ -22,11 +22,25 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Buckets: stdprometheus.LinearBuckets(1, 10, 10), }, labels).With(labelsAndValues...), + ConsensusParamUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "consensus_param_updates", + Help: "ConsensusParamUpdates is the total number of times the application has udated the consensus params since process start.", + }, labels).With(labelsAndValues...), + ValidatorSetUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "validator_set_updates", + Help: "ValidatorSetUpdates is the total number of times the application has udated the validator set since process start.", + }, labels).With(labelsAndValues...), } } func NopMetrics() *Metrics { return &Metrics{ - BlockProcessingTime: discard.NewHistogram(), + BlockProcessingTime: discard.NewHistogram(), + ConsensusParamUpdates: discard.NewCounter(), + ValidatorSetUpdates: discard.NewCounter(), } } diff --git a/state/metrics.go b/state/metrics.go index 72712144f..6c238df76 100644 --- a/state/metrics.go +++ b/state/metrics.go @@ -16,4 +16,12 @@ const ( type Metrics struct { // Time between BeginBlock and EndBlock in ms. BlockProcessingTime metrics.Histogram `metrics_buckettype:"lin" metrics_bucketsizes:"1, 10, 10"` + + // ConsensusParamUpdates is the total number of times the application has + // udated the consensus params since process start. + ConsensusParamUpdates metrics.Counter + + // ValidatorSetUpdates is the total number of times the application has + // udated the validator set since process start. + ValidatorSetUpdates metrics.Counter } diff --git a/state/mocks/store.go b/state/mocks/store.go index 8cbe49080..47b5579a7 100644 --- a/state/mocks/store.go +++ b/state/mocks/store.go @@ -8,9 +8,7 @@ import ( tendermintstate "github.com/tendermint/tendermint/proto/tendermint/state" - tenderminttypes "github.com/tendermint/tendermint/types" - - types "github.com/tendermint/tendermint/proto/tendermint/types" + types "github.com/tendermint/tendermint/types" ) // Store is an autogenerated mock type for the Store type @@ -112,18 +110,18 @@ func (_m *Store) LoadConsensusParams(_a0 int64) (types.ConsensusParams, error) { } // LoadFromDBOrGenesisDoc provides a mock function with given fields: _a0 -func (_m *Store) LoadFromDBOrGenesisDoc(_a0 *tenderminttypes.GenesisDoc) (state.State, error) { +func (_m *Store) LoadFromDBOrGenesisDoc(_a0 *types.GenesisDoc) (state.State, error) { ret := _m.Called(_a0) var r0 state.State - if rf, ok := ret.Get(0).(func(*tenderminttypes.GenesisDoc) state.State); ok { + if rf, ok := ret.Get(0).(func(*types.GenesisDoc) state.State); ok { r0 = rf(_a0) } else { r0 = ret.Get(0).(state.State) } var r1 error - if rf, ok := ret.Get(1).(func(*tenderminttypes.GenesisDoc) error); ok { + if rf, ok := ret.Get(1).(func(*types.GenesisDoc) error); ok { r1 = rf(_a0) } else { r1 = ret.Error(1) @@ -177,15 +175,15 @@ func (_m *Store) LoadLastABCIResponse(_a0 int64) (*tendermintstate.ABCIResponses } // LoadValidators provides a mock function with given fields: _a0 -func (_m *Store) LoadValidators(_a0 int64) (*tenderminttypes.ValidatorSet, error) { +func (_m *Store) LoadValidators(_a0 int64) (*types.ValidatorSet, error) { ret := _m.Called(_a0) - var r0 *tenderminttypes.ValidatorSet - if rf, ok := ret.Get(0).(func(int64) *tenderminttypes.ValidatorSet); ok { + var r0 *types.ValidatorSet + if rf, ok := ret.Get(0).(func(int64) *types.ValidatorSet); ok { r0 = rf(_a0) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*tenderminttypes.ValidatorSet) + r0 = ret.Get(0).(*types.ValidatorSet) } } diff --git a/state/rollback.go b/state/rollback.go index 388a597b1..c4686015b 100644 --- a/state/rollback.go +++ b/state/rollback.go @@ -77,7 +77,7 @@ func Rollback(bs BlockStore, ss Store) (int64, []byte, error) { Version: tmstate.Version{ Consensus: tmversion.Consensus{ Block: version.BlockProtocol, - App: previousParams.Version.AppVersion, + App: previousParams.Version.App, }, Software: version.TMCoreSemVer, }, diff --git a/state/rollback_test.go b/state/rollback_test.go index 4cd203810..1c31cf588 100644 --- a/state/rollback_test.go +++ b/state/rollback_test.go @@ -29,7 +29,7 @@ func TestRollback(t *testing.T) { // perform the rollback over a version bump newParams := types.DefaultConsensusParams() - newParams.Version.AppVersion = 11 + newParams.Version.App = 11 newParams.Block.MaxBytes = 1000 nextState := initialState.Copy() nextState.LastBlockHeight = nextHeight @@ -122,7 +122,7 @@ func setupStateStore(t *testing.T, height int64) state.Store { valSet, _ := types.RandValidatorSet(5, 10) params := types.DefaultConsensusParams() - params.Version.AppVersion = 10 + params.Version.App = 10 initialState := state.State{ Version: tmstate.Version{ diff --git a/state/state.go b/state/state.go index be4c7d23c..b1c4c2926 100644 --- a/state/state.go +++ b/state/state.go @@ -10,7 +10,6 @@ import ( "github.com/gogo/protobuf/proto" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmversion "github.com/tendermint/tendermint/proto/tendermint/version" "github.com/tendermint/tendermint/types" tmtime "github.com/tendermint/tendermint/types/time" @@ -70,7 +69,7 @@ type State struct { // Consensus parameters used for validating blocks. // Changes returned by EndBlock and updated after Commit. - ConsensusParams tmproto.ConsensusParams + ConsensusParams types.ConsensusParams LastHeightConsensusParamsChanged int64 // Merkle root of the results from executing prev block @@ -167,7 +166,7 @@ func (state *State) ToProto() (*tmstate.State, error) { } sm.LastHeightValidatorsChanged = state.LastHeightValidatorsChanged - sm.ConsensusParams = state.ConsensusParams + sm.ConsensusParams = state.ConsensusParams.ToProto() sm.LastHeightConsensusParamsChanged = state.LastHeightConsensusParamsChanged sm.LastResultsHash = state.LastResultsHash sm.AppHash = state.AppHash @@ -218,7 +217,7 @@ func FromProto(pb *tmstate.State) (*State, error) { //nolint:golint } state.LastHeightValidatorsChanged = pb.LastHeightValidatorsChanged - state.ConsensusParams = pb.ConsensusParams + state.ConsensusParams = types.ConsensusParamsFromProto(pb.ConsensusParams) state.LastHeightConsensusParamsChanged = pb.LastHeightConsensusParamsChanged state.LastResultsHash = pb.LastResultsHash state.AppHash = pb.AppHash @@ -235,20 +234,20 @@ func FromProto(pb *tmstate.State) (*State, error) { //nolint:golint func (state State) MakeBlock( height int64, txs []types.Tx, - commit *types.Commit, + lastCommit *types.Commit, evidence []types.Evidence, proposerAddress []byte, -) (*types.Block, *types.PartSet) { +) *types.Block { // Build base block with block data. - block := types.MakeBlock(height, txs, commit, evidence) + block := types.MakeBlock(height, txs, lastCommit, evidence) // Set time. var timestamp time.Time if height == state.InitialHeight { timestamp = state.LastBlockTime // genesis time } else { - timestamp = MedianTime(commit, state.LastValidators) + timestamp = MedianTime(lastCommit, state.LastValidators) } // Fill rest of header with state data. @@ -256,11 +255,11 @@ func (state State) MakeBlock( state.Version.Consensus, state.ChainID, timestamp, state.LastBlockID, state.Validators.Hash(), state.NextValidators.Hash(), - types.HashConsensusParams(state.ConsensusParams), state.AppHash, state.LastResultsHash, + state.ConsensusParams.Hash(), state.AppHash, state.LastResultsHash, proposerAddress, ) - return block, block.MakePartSet(types.BlockPartSizeBytes) + return block } // MedianTime computes a median time for a given Commit (based on Timestamp field of votes messages) and the diff --git a/state/state_test.go b/state/state_test.go index 2a6f7fa58..f2de2a1b0 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -19,7 +19,6 @@ import ( cryptoenc "github.com/tendermint/tendermint/crypto/encoding" tmrand "github.com/tendermint/tendermint/libs/rand" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" ) @@ -107,7 +106,7 @@ func TestABCIResponsesSaveLoad1(t *testing.T) { state.LastBlockHeight++ // Build mock responses. - block := makeBlock(state, 2) + block := makeBlock(state, 2, new(types.Commit)) abciResponses := new(tmstate.ABCIResponses) dtxs := make([]*abci.ResponseDeliverTx, 2) @@ -281,12 +280,12 @@ func TestOneValidatorChangesSaveLoad(t *testing.T) { changeIndex++ power++ } - header, blockID, responses := makeHeaderPartsResponsesValPowerChange(state, power) + header, blockID, responses := makeHeaderPartsResponsesValPowerChange(t, state, power) validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates) require.NoError(t, err) state, err = sm.UpdateState(state, blockID, &header, responses, validatorUpdates) require.NoError(t, err) - err := stateStore.Save(state) + err = stateStore.Save(state) require.NoError(t, err) } @@ -455,8 +454,10 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { // NewValidatorSet calls IncrementProposerPriority but uses on a copy of val1 assert.EqualValues(t, 0, val1.ProposerPriority) - block := makeBlock(state, state.LastBlockHeight+1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(state, state.LastBlockHeight+1, new(types.Commit)) + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} abciResponses := &tmstate.ABCIResponses{ BeginBlock: &abci.ResponseBeginBlock{}, EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil}, @@ -569,8 +570,10 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { // we only have one validator: assert.Equal(t, val1PubKey.Address(), state.Validators.Proposer.Address) - block := makeBlock(state, state.LastBlockHeight+1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(state, state.LastBlockHeight+1, new(types.Commit)) + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} // no updates: abciResponses := &tmstate.ABCIResponses{ BeginBlock: &abci.ResponseBeginBlock{}, @@ -756,8 +759,10 @@ func TestLargeGenesisValidator(t *testing.T) { validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates) require.NoError(t, err) - block := makeBlock(oldState, oldState.LastBlockHeight+1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} updatedState, err := sm.UpdateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates) require.NoError(t, err) @@ -785,8 +790,12 @@ func TestLargeGenesisValidator(t *testing.T) { BeginBlock: &abci.ResponseBeginBlock{}, EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{firstAddedVal}}, } - block := makeBlock(oldState, oldState.LastBlockHeight+1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) + + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} updatedState, err := sm.UpdateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates) require.NoError(t, err) @@ -800,8 +809,12 @@ func TestLargeGenesisValidator(t *testing.T) { validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates) require.NoError(t, err) - block := makeBlock(lastState, lastState.LastBlockHeight+1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(lastState, lastState.LastBlockHeight+1, new(types.Commit)) + + bps, err = block.MakePartSet(testPartSize) + require.NoError(t, err) + + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} updatedStateInner, err := sm.UpdateState(lastState, blockID, &block.Header, abciResponses, validatorUpdates) require.NoError(t, err) @@ -833,8 +846,11 @@ func TestLargeGenesisValidator(t *testing.T) { BeginBlock: &abci.ResponseBeginBlock{}, EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{addedVal}}, } - block := makeBlock(oldState, oldState.LastBlockHeight+1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} state, err = sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates) require.NoError(t, err) } @@ -848,8 +864,14 @@ func TestLargeGenesisValidator(t *testing.T) { BeginBlock: &abci.ResponseBeginBlock{}, EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal}}, } - block = makeBlock(oldState, oldState.LastBlockHeight+1) - blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + + block = makeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) + require.NoError(t, err) + + bps, err = block.MakePartSet(testPartSize) + require.NoError(t, err) + + blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates) require.NoError(t, err) updatedState, err = sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates) @@ -869,8 +891,12 @@ func TestLargeGenesisValidator(t *testing.T) { } validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates) require.NoError(t, err) - block = makeBlock(curState, curState.LastBlockHeight+1) - blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block = makeBlock(curState, curState.LastBlockHeight+1, new(types.Commit)) + + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + + blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} curState, err = sm.UpdateState(curState, blockID, &block.Header, abciResponses, validatorUpdates) require.NoError(t, err) if !bytes.Equal(curState.Validators.Proposer.Address, curState.NextValidators.Proposer.Address) { @@ -894,8 +920,12 @@ func TestLargeGenesisValidator(t *testing.T) { validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates) require.NoError(t, err) - block := makeBlock(updatedState, updatedState.LastBlockHeight+1) - blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} + block := makeBlock(updatedState, updatedState.LastBlockHeight+1, new(types.Commit)) + + bps, err := block.MakePartSet(testPartSize) + require.NoError(t, err) + + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} updatedState, err = sm.UpdateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates) require.NoError(t, err) @@ -954,7 +984,7 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) { pubkey := ed25519.GenPrivKey().PubKey() // Swap the first validator with a new one (validator set size stays the same). - header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(state, pubkey) + header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(t, state, pubkey) // Save state etc. var validatorUpdates []*types.Validator @@ -993,7 +1023,7 @@ func TestStateMakeBlock(t *testing.T) { proposerAddress := state.Validators.GetProposer().Address stateVersion := state.Version.Consensus - block := makeBlock(state, 2) + block := makeBlock(state, 2, new(types.Commit)) // test we set some fields assert.Equal(t, stateVersion, block.Version) @@ -1016,12 +1046,12 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) { // Each valset is just one validator. // create list of them. - params := make([]tmproto.ConsensusParams, N+1) + params := make([]types.ConsensusParams, N+1) params[0] = state.ConsensusParams for i := 1; i < N+1; i++ { params[i] = *types.DefaultConsensusParams() params[i].Block.MaxBytes += int64(i) - params[i].Block.TimeIotaMs = 10 + } // Build the params history by running updateState @@ -1037,13 +1067,13 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) { changeIndex++ cp = params[changeIndex] } - header, blockID, responses := makeHeaderPartsResponsesParams(state, cp) + header, blockID, responses := makeHeaderPartsResponsesParams(t, state, cp.ToProto()) validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates) require.NoError(t, err) state, err = sm.UpdateState(state, blockID, &header, responses, validatorUpdates) - require.Nil(t, err) - err := stateStore.Save(state) + require.NoError(t, err) + err = stateStore.Save(state) require.NoError(t, err) } diff --git a/state/store.go b/state/store.go index c42a2f65c..44111ceee 100644 --- a/state/store.go +++ b/state/store.go @@ -63,7 +63,7 @@ type Store interface { // LoadLastABCIResponse loads the last abciResponse for a given height LoadLastABCIResponse(int64) (*tmstate.ABCIResponses, error) // LoadConsensusParams loads the consensus params for a given height - LoadConsensusParams(int64) (tmproto.ConsensusParams, error) + LoadConsensusParams(int64) (types.ConsensusParams, error) // Save overwrites the previous state with the updated one Save(State) error // SaveABCIResponses saves ABCIResponses for a given height @@ -312,10 +312,11 @@ func (store dbStore) PruneStates(from int64, to int64) error { } if p.ConsensusParams.Equal(&tmproto.ConsensusParams{}) { - p.ConsensusParams, err = store.LoadConsensusParams(h) + params, err := store.LoadConsensusParams(h) if err != nil { return err } + p.ConsensusParams = params.ToProto() p.LastHeightChanged = h bz, err := p.Marshal() @@ -585,15 +586,17 @@ func (store dbStore) saveValidatorsInfo(height, lastHeightChanged int64, valSet // ConsensusParamsInfo represents the latest consensus params, or the last height it changed // LoadConsensusParams loads the ConsensusParams for a given height. -func (store dbStore) LoadConsensusParams(height int64) (tmproto.ConsensusParams, error) { - empty := tmproto.ConsensusParams{} - +func (store dbStore) LoadConsensusParams(height int64) (types.ConsensusParams, error) { + var ( + empty = types.ConsensusParams{} + emptypb = tmproto.ConsensusParams{} + ) paramsInfo, err := store.loadConsensusParamsInfo(height) if err != nil { return empty, fmt.Errorf("could not find consensus params for height #%d: %w", height, err) } - if paramsInfo.ConsensusParams.Equal(&empty) { + if paramsInfo.ConsensusParams.Equal(&emptypb) { paramsInfo2, err := store.loadConsensusParamsInfo(paramsInfo.LastHeightChanged) if err != nil { return empty, fmt.Errorf( @@ -607,7 +610,7 @@ func (store dbStore) LoadConsensusParams(height int64) (tmproto.ConsensusParams, paramsInfo = paramsInfo2 } - return paramsInfo.ConsensusParams, nil + return types.ConsensusParamsFromProto(paramsInfo.ConsensusParams), nil } func (store dbStore) loadConsensusParamsInfo(height int64) (*tmstate.ConsensusParamsInfo, error) { @@ -634,13 +637,13 @@ func (store dbStore) loadConsensusParamsInfo(height int64) (*tmstate.ConsensusPa // It should be called from s.Save(), right before the state itself is persisted. // If the consensus params did not change after processing the latest block, // only the last height for which they changed is persisted. -func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, params tmproto.ConsensusParams) error { +func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, params types.ConsensusParams) error { paramsInfo := &tmstate.ConsensusParamsInfo{ LastHeightChanged: changeHeight, } if changeHeight == nextHeight { - paramsInfo.ConsensusParams = params + paramsInfo.ConsensusParams = params.ToProto() } bz, err := paramsInfo.Marshal() if err != nil { diff --git a/state/store_test.go b/state/store_test.go index b91eeb578..8b3a6c4bd 100644 --- a/state/store_test.go +++ b/state/store_test.go @@ -16,7 +16,6 @@ import ( "github.com/tendermint/tendermint/crypto/ed25519" tmrand "github.com/tendermint/tendermint/libs/rand" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" ) @@ -139,8 +138,8 @@ func TestPruneStates(t *testing.T) { LastBlockHeight: h - 1, Validators: validatorSet, NextValidators: validatorSet, - ConsensusParams: tmproto.ConsensusParams{ - Block: tmproto.BlockParams{MaxBytes: 10e6}, + ConsensusParams: types.ConsensusParams{ + Block: types.BlockParams{MaxBytes: 10e6}, }, LastHeightValidatorsChanged: valsChanged, LastHeightConsensusParamsChanged: paramsChanged, @@ -188,9 +187,10 @@ func TestPruneStates(t *testing.T) { params, err := stateStore.LoadConsensusParams(h) if expectParams[h] { require.NoError(t, err, "params height %v", h) - require.False(t, params.Equal(&tmproto.ConsensusParams{})) + require.NotEmpty(t, params) } else { require.Error(t, err, "params height %v", h) + require.Empty(t, params) } abci, err := stateStore.LoadABCIResponses(h) diff --git a/state/validation.go b/state/validation.go index 0ebe37bf9..9057b6c48 100644 --- a/state/validation.go +++ b/state/validation.go @@ -57,10 +57,9 @@ func validateBlock(state State, block *types.Block) error { block.AppHash, ) } - hashCP := types.HashConsensusParams(state.ConsensusParams) - if !bytes.Equal(block.ConsensusHash, hashCP) { + if !bytes.Equal(block.ConsensusHash, state.ConsensusParams.Hash()) { return fmt.Errorf("wrong Block.Header.ConsensusHash. Expected %X, got %v", - hashCP, + state.ConsensusParams.Hash(), block.ConsensusHash, ) } diff --git a/state/validation_test.go b/state/validation_test.go index ddca0d98c..2d1f78c1f 100644 --- a/state/validation_test.go +++ b/state/validation_test.go @@ -11,8 +11,9 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/tmhash" + "github.com/tendermint/tendermint/internal/test" "github.com/tendermint/tendermint/libs/log" - memmock "github.com/tendermint/tendermint/mempool/mock" + mpmocks "github.com/tendermint/tendermint/mempool/mocks" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/state/mocks" @@ -31,11 +32,23 @@ func TestValidateBlockHeader(t *testing.T) { stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + blockExec := sm.NewBlockExecutor( stateStore, log.TestingLogger(), proxyApp.Consensus(), - memmock.Mempool{}, + mp, sm.EmptyEvidencePool{}, ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) @@ -75,12 +88,11 @@ func TestValidateBlockHeader(t *testing.T) { // Build up state for multiple heights for height := int64(1); height < validationTestsStopHeight; height++ { - proposerAddr := state.Validators.GetProposer().Address /* Invalid blocks don't pass */ for _, tc := range testCases { - block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, nil, proposerAddr) + block := makeBlock(state, height, lastCommit) tc.malleateBlock(block) err := blockExec.ValidateBlock(state, block) require.Error(t, err, tc.name) @@ -90,7 +102,8 @@ func TestValidateBlockHeader(t *testing.T) { A good block passes */ var err error - state, _, lastCommit, err = makeAndCommitGoodBlock(state, height, lastCommit, proposerAddr, blockExec, privVals, nil) + state, _, lastCommit, err = makeAndCommitGoodBlock( + state, height, lastCommit, state.Validators.GetProposer().Address, blockExec, privVals, nil) require.NoError(t, err, "height %d", height) } } @@ -104,11 +117,23 @@ func TestValidateBlockCommit(t *testing.T) { stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + blockExec := sm.NewBlockExecutor( stateStore, log.TestingLogger(), proxyApp.Consensus(), - memmock.Mempool{}, + mp, sm.EmptyEvidencePool{}, ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) @@ -122,12 +147,15 @@ func TestValidateBlockCommit(t *testing.T) { #2589: ensure state.LastValidators.VerifyCommit fails here */ // should be height-1 instead of height - wrongHeightVote, err := types.MakeVote( - height, - state.LastBlockID, - state.Validators, + idx, _ := state.Validators.GetByAddress(proposerAddr) + wrongHeightVote, err := test.MakeVote( privVals[proposerAddr.String()], chainID, + idx, + height, + 0, + 2, + state.LastBlockID, time.Now(), ) require.NoError(t, err, "height %d", height) @@ -137,7 +165,7 @@ func TestValidateBlockCommit(t *testing.T) { state.LastBlockID, []types.CommitSig{wrongHeightVote.CommitSig()}, ) - block, _ := state.MakeBlock(height, makeTxs(height), wrongHeightCommit, nil, proposerAddr) + block := makeBlock(state, height, wrongHeightCommit) err = blockExec.ValidateBlock(state, block) _, isErrInvalidCommitHeight := err.(types.ErrInvalidCommitHeight) require.True(t, isErrInvalidCommitHeight, "expected ErrInvalidCommitHeight at height %d but got: %v", height, err) @@ -145,7 +173,7 @@ func TestValidateBlockCommit(t *testing.T) { /* #2589: test len(block.LastCommit.Signatures) == state.LastValidators.Size() */ - block, _ = state.MakeBlock(height, makeTxs(height), wrongSigsCommit, nil, proposerAddr) + block = makeBlock(state, height, wrongSigsCommit) err = blockExec.ValidateBlock(state, block) _, isErrInvalidCommitSignatures := err.(types.ErrInvalidCommitSignatures) require.True(t, isErrInvalidCommitSignatures, @@ -226,14 +254,25 @@ func TestValidateBlockEvidence(t *testing.T) { evpool.On("CheckEvidence", mock.AnythingOfType("types.EvidenceList")).Return(nil) evpool.On("Update", mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return() evpool.On("ABCIEvidence", mock.AnythingOfType("int64"), mock.AnythingOfType("[]types.Evidence")).Return( - []abci.Evidence{}) + []abci.Misbehavior{}) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) state.ConsensusParams.Evidence.MaxBytes = 1000 blockExec := sm.NewBlockExecutor( stateStore, log.TestingLogger(), proxyApp.Consensus(), - memmock.Mempool{}, + mp, evpool, ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) @@ -249,12 +288,14 @@ func TestValidateBlockEvidence(t *testing.T) { var currentBytes int64 // more bytes than the maximum allowed for evidence for currentBytes <= maxBytesEvidence { - newEv := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), + newEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), privVals[proposerAddr.String()], chainID) + require.NoError(t, err) evidence = append(evidence, newEv) currentBytes += int64(len(newEv.Bytes())) } - block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, evidence, proposerAddr) + block := state.MakeBlock(height, test.MakeNTxs(height, 10), lastCommit, evidence, proposerAddr) + err := blockExec.ValidateBlock(state, block) if assert.Error(t, err) { _, ok := err.(*types.ErrEvidenceOverflow) @@ -269,8 +310,9 @@ func TestValidateBlockEvidence(t *testing.T) { var currentBytes int64 // precisely the amount of allowed evidence for { - newEv := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime, + newEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime, privVals[proposerAddr.String()], chainID) + require.NoError(t, err) currentBytes += int64(len(newEv.Bytes())) if currentBytes >= maxBytesEvidence { break diff --git a/store/store_test.go b/store/store_test.go index c9ea3e925..10d9b0af3 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -3,6 +3,7 @@ package store import ( "bytes" "fmt" + stdlog "log" "os" "runtime/debug" "strings" @@ -16,6 +17,7 @@ import ( cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/internal/test" "github.com/tendermint/tendermint/libs/log" tmrand "github.com/tendermint/tendermint/libs/rand" tmstore "github.com/tendermint/tendermint/proto/tendermint/store" @@ -42,18 +44,6 @@ func makeTestCommit(height int64, timestamp time.Time) *types.Commit { types.BlockID{Hash: []byte(""), PartSetHeader: types.PartSetHeader{Hash: []byte(""), Total: 2}}, commitSigs) } -func makeTxs(height int64) (txs []types.Tx) { - for i := 0; i < 10; i++ { - txs = append(txs, types.Tx([]byte{byte(height), byte(i)})) - } - return txs -} - -func makeBlock(height int64, state sm.State, lastCommit *types.Commit) *types.Block { - block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, nil, state.Validators.GetProposer().Address) - return block -} - func makeStateAndBlockStore(logger log.Logger) (sm.State, *BlockStore, cleanupFunc) { config := cfg.ResetTestRoot("blockchain_reactor_test") // blockDB := dbm.NewDebugDB("blockDB", dbm.NewMemDB()) @@ -146,9 +136,14 @@ var ( func TestMain(m *testing.M) { var cleanup cleanupFunc + var err error state, _, cleanup = makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) - block = makeBlock(1, state, new(types.Commit)) - partSet = block.MakePartSet(2) + block = state.MakeBlock(state.LastBlockHeight+1, test.MakeNTxs(state.LastBlockHeight+1, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) + + partSet, err = block.MakePartSet(2) + if err != nil { + stdlog.Fatal(err) + } part1 = partSet.GetPart(0) part2 = partSet.GetPart(1) seenCommit1 = makeTestCommit(10, tmtime.Now()) @@ -174,8 +169,9 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { } // save a block - block := makeBlock(bs.Height()+1, state, new(types.Commit)) - validPartSet := block.MakePartSet(2) + block := state.MakeBlock(bs.Height()+1, nil, new(types.Commit), nil, state.Validators.GetProposer().Address) + validPartSet, err := block.MakePartSet(2) + require.NoError(t, err) seenCommit := makeTestCommit(10, tmtime.Now()) bs.SaveBlock(block, partSet, seenCommit) require.EqualValues(t, 1, bs.Base(), "expecting the new height to be changed") @@ -183,7 +179,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { incompletePartSet := types.NewPartSetFromHeader(types.PartSetHeader{Total: 2}) uncontiguousPartSet := types.NewPartSetFromHeader(types.PartSetHeader{Total: 0}) - _, err := uncontiguousPartSet.AddPart(part2) + _, err = uncontiguousPartSet.AddPart(part2) require.Error(t, err) header1 := types.Header{ @@ -379,8 +375,9 @@ func TestLoadBaseMeta(t *testing.T) { bs := NewBlockStore(dbm.NewMemDB()) for h := int64(1); h <= 10; h++ { - block := makeBlock(h, state, new(types.Commit)) - partSet := block.MakePartSet(2) + block := state.MakeBlock(h, test.MakeNTxs(h, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) + partSet, err := block.MakePartSet(2) + require.NoError(t, err) seenCommit := makeTestCommit(h, tmtime.Now()) bs.SaveBlock(block, partSet, seenCommit) } @@ -449,8 +446,9 @@ func TestPruneBlocks(t *testing.T) { // make more than 1000 blocks, to test batch deletions for h := int64(1); h <= 1500; h++ { - block := makeBlock(h, state, new(types.Commit)) - partSet := block.MakePartSet(2) + block := state.MakeBlock(h, test.MakeNTxs(h, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) + partSet, err := block.MakePartSet(2) + require.NoError(t, err) seenCommit := makeTestCommit(h, tmtime.Now()) bs.SaveBlock(block, partSet, seenCommit) } @@ -558,9 +556,10 @@ func TestBlockFetchAtHeight(t *testing.T) { state, bs, cleanup := makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) defer cleanup() require.Equal(t, bs.Height(), int64(0), "initially the height should be zero") - block := makeBlock(bs.Height()+1, state, new(types.Commit)) + block := state.MakeBlock(bs.Height()+1, nil, new(types.Commit), nil, state.Validators.GetProposer().Address) - partSet := block.MakePartSet(2) + partSet, err := block.MakePartSet(2) + require.NoError(t, err) seenCommit := makeTestCommit(10, tmtime.Now()) bs.SaveBlock(block, partSet, seenCommit) require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed") diff --git a/test/e2e/app/app.go b/test/e2e/app/app.go index c812b0f15..f1c19d63b 100644 --- a/test/e2e/app/app.go +++ b/test/e2e/app/app.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "strconv" + "time" "github.com/tendermint/tendermint/abci/example/code" abci "github.com/tendermint/tendermint/abci/types" @@ -70,6 +71,13 @@ type Config struct { // // height <-> pubkey <-> voting power ValidatorUpdates map[string]map[string]uint8 `toml:"validator_update"` + + // Add artificial delays to each of the main ABCI calls to mimic computation time + // of the application + PrepareProposalDelay time.Duration `toml:"prepare_proposal_delay"` + ProcessProposalDelay time.Duration `toml:"process_proposal_delay"` + CheckTxDelay time.Duration `toml:"check_tx_delay"` + // TODO: add vote extension and finalize block delays once completed (@cmwaters) } func DefaultConfig(dir string) *Config { @@ -136,6 +144,11 @@ func (app *Application) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { Log: err.Error(), } } + + if app.cfg.CheckTxDelay != 0 { + time.Sleep(app.cfg.CheckTxDelay) + } + return abci.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1} } @@ -257,6 +270,42 @@ func (app *Application) ApplySnapshotChunk(req abci.RequestApplySnapshotChunk) a return abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT} } +func (app *Application) PrepareProposal( + req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { + txs := make([][]byte, 0, len(req.Txs)) + var totalBytes int64 + for _, tx := range req.Txs { + totalBytes += int64(len(tx)) + if totalBytes > req.MaxTxBytes { + break + } + txs = append(txs, tx) + } + + if app.cfg.PrepareProposalDelay != 0 { + time.Sleep(app.cfg.PrepareProposalDelay) + } + + return abci.ResponsePrepareProposal{Txs: txs} +} + +// ProcessProposal implements part of the Application interface. +// It accepts any proposal that does not contain a malformed transaction. +func (app *Application) ProcessProposal(req abci.RequestProcessProposal) abci.ResponseProcessProposal { + for _, tx := range req.Txs { + _, _, err := parseTx(tx) + if err != nil { + return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT} + } + } + + if app.cfg.ProcessProposalDelay != 0 { + time.Sleep(app.cfg.ProcessProposalDelay) + } + + return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT} +} + func (app *Application) Rollback() error { return app.state.Rollback() } diff --git a/test/e2e/generator/generate.go b/test/e2e/generator/generate.go index 684acb426..a7946d5be 100644 --- a/test/e2e/generator/generate.go +++ b/test/e2e/generator/generate.go @@ -5,6 +5,7 @@ import ( "math/rand" "sort" "strings" + "time" e2e "github.com/tendermint/tendermint/test/e2e/pkg" ) @@ -34,6 +35,7 @@ var ( nodePersistIntervals = uniformChoice{0, 1, 5} nodeSnapshotIntervals = uniformChoice{0, 3} nodeRetainBlocks = uniformChoice{0, 1, 5} + abciDelays = uniformChoice{"none", "small", "large"} nodePerturbations = probSetChoice{ "disconnect": 0.1, "pause": 0.1, @@ -67,6 +69,17 @@ func generateTestnet(r *rand.Rand, opt map[string]interface{}) (e2e.Manifest, er Nodes: map[string]*e2e.ManifestNode{}, } + switch abciDelays.Choose(r).(string) { + case "none": + case "small": + manifest.PrepareProposalDelay = 100 * time.Millisecond + manifest.ProcessProposalDelay = 100 * time.Millisecond + case "large": + manifest.PrepareProposalDelay = 200 * time.Millisecond + manifest.ProcessProposalDelay = 200 * time.Millisecond + manifest.CheckTxDelay = 20 * time.Millisecond + } + var numSeeds, numValidators, numFulls, numLightClients int switch opt["topology"].(string) { case "single": diff --git a/test/e2e/networks/ci.toml b/test/e2e/networks/ci.toml index e210db379..916deb757 100644 --- a/test/e2e/networks/ci.toml +++ b/test/e2e/networks/ci.toml @@ -3,7 +3,11 @@ ipv6 = true initial_height = 1000 +evidence = 5 initial_state = { initial01 = "a", initial02 = "b", initial03 = "c" } +prepare_proposal_delay = "100ms" +process_proposal_delay = "100ms" +check_tx_delay = "0ms" [validators] validator01 = 100 @@ -27,11 +31,7 @@ validator05 = 50 [node.seed01] mode = "seed" -seeds = ["seed02"] - -[node.seed02] -mode = "seed" -seeds = ["seed01"] +perturb = ["restart"] [node.validator01] seeds = ["seed01"] @@ -39,7 +39,7 @@ snapshot_interval = 5 perturb = ["disconnect"] [node.validator02] -seeds = ["seed02"] +seeds = ["seed01"] database = "boltdb" abci_protocol = "tcp" privval_protocol = "tcp" @@ -53,7 +53,7 @@ database = "badgerdb" #abci_protocol = "grpc" privval_protocol = "unix" persist_interval = 3 -retain_blocks = 3 +retain_blocks = 10 perturb = ["kill"] [node.validator04] @@ -65,7 +65,7 @@ perturb = ["pause"] [node.validator05] block_sync = "v0" start_at = 1005 # Becomes part of the validator set at 1010 -seeds = ["seed02"] +persistent_peers = ["validator01", "full01"] database = "cleveldb" mempool_version = "v1" # FIXME: should be grpc, disabled due to https://github.com/tendermint/tendermint/issues/5439 @@ -78,7 +78,7 @@ start_at = 1010 mode = "full" block_sync = "v0" persistent_peers = ["validator01", "validator02", "validator03", "validator04", "validator05"] -retain_blocks = 1 +retain_blocks = 10 perturb = ["restart"] [node.full02] diff --git a/test/e2e/pkg/manifest.go b/test/e2e/pkg/manifest.go index 6099ab492..a2016c54b 100644 --- a/test/e2e/pkg/manifest.go +++ b/test/e2e/pkg/manifest.go @@ -3,6 +3,7 @@ package e2e import ( "fmt" "os" + "time" "github.com/BurntSushi/toml" ) @@ -51,11 +52,22 @@ type Manifest struct { // Options are ed25519 & secp256k1 KeyType string `toml:"key_type"` + // Evidence indicates the amount of evidence that will be injected into the + // testnet via the RPC endpoint of a random node. Default is 0 + Evidence int `toml:"evidence"` + // ABCIProtocol specifies the protocol used to communicate with the ABCI // application: "unix", "tcp", "grpc", or "builtin". Defaults to builtin. // builtin will build a complete Tendermint node into the application and // launch it instead of launching a separate Tendermint process. ABCIProtocol string `toml:"abci_protocol"` + + // Add artificial delays to each of the main ABCI calls to mimic computation time + // of the application + PrepareProposalDelay time.Duration `toml:"prepare_proposal_delay"` + ProcessProposalDelay time.Duration `toml:"process_proposal_delay"` + CheckTxDelay time.Duration `toml:"check_tx_delay"` + // TODO: add vote extension and finalize block delay (@cmwaters) } // ManifestNode represents a node in a testnet manifest. diff --git a/test/e2e/pkg/testnet.go b/test/e2e/pkg/testnet.go index 3d213f381..47f1b0b26 100644 --- a/test/e2e/pkg/testnet.go +++ b/test/e2e/pkg/testnet.go @@ -11,6 +11,7 @@ import ( "sort" "strconv" "strings" + "time" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" @@ -45,21 +46,28 @@ const ( PerturbationKill Perturbation = "kill" PerturbationPause Perturbation = "pause" PerturbationRestart Perturbation = "restart" + + EvidenceAgeHeight int64 = 7 + EvidenceAgeTime time.Duration = 500 * time.Millisecond ) // Testnet represents a single testnet. type Testnet struct { - Name string - File string - Dir string - IP *net.IPNet - InitialHeight int64 - InitialState map[string]string - Validators map[*Node]int64 - ValidatorUpdates map[int64]map[*Node]int64 - Nodes []*Node - KeyType string - ABCIProtocol string + Name string + File string + Dir string + IP *net.IPNet + InitialHeight int64 + InitialState map[string]string + Validators map[*Node]int64 + ValidatorUpdates map[int64]map[*Node]int64 + Nodes []*Node + KeyType string + Evidence int + ABCIProtocol string + PrepareProposalDelay time.Duration + ProcessProposalDelay time.Duration + CheckTxDelay time.Duration } // Node represents a Tendermint node in a testnet. @@ -113,16 +121,20 @@ func LoadTestnet(file string) (*Testnet, error) { proxyPortGen := newPortGenerator(proxyPortFirst) testnet := &Testnet{ - Name: filepath.Base(dir), - File: file, - Dir: dir, - IP: ipGen.Network(), - InitialHeight: 1, - InitialState: manifest.InitialState, - Validators: map[*Node]int64{}, - ValidatorUpdates: map[int64]map[*Node]int64{}, - Nodes: []*Node{}, - ABCIProtocol: manifest.ABCIProtocol, + Name: filepath.Base(dir), + File: file, + Dir: dir, + IP: ipGen.Network(), + InitialHeight: 1, + InitialState: manifest.InitialState, + Validators: map[*Node]int64{}, + ValidatorUpdates: map[int64]map[*Node]int64{}, + Nodes: []*Node{}, + Evidence: manifest.Evidence, + ABCIProtocol: manifest.ABCIProtocol, + PrepareProposalDelay: manifest.PrepareProposalDelay, + ProcessProposalDelay: manifest.ProcessProposalDelay, + CheckTxDelay: manifest.CheckTxDelay, } if len(manifest.KeyType) != 0 { testnet.KeyType = manifest.KeyType @@ -333,6 +345,10 @@ func (n Node) Validate(testnet Testnet) error { if n.StateSync && n.StartAt == 0 { return errors.New("state synced nodes cannot start at the initial height") } + if n.RetainBlocks != 0 && n.RetainBlocks < uint64(EvidenceAgeHeight) { + return fmt.Errorf("retain_blocks must be greater or equal to max evidence age (%d)", + EvidenceAgeHeight) + } if n.PersistInterval == 0 && n.RetainBlocks > 0 { return errors.New("persist_interval=0 requires retain_blocks=0") } diff --git a/test/e2e/runner/evidence.go b/test/e2e/runner/evidence.go new file mode 100644 index 000000000..0cd56016f --- /dev/null +++ b/test/e2e/runner/evidence.go @@ -0,0 +1,320 @@ +package main + +import ( + "bytes" + "context" + "errors" + "fmt" + "io/ioutil" + "math/rand" + "path/filepath" + "time" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/tmhash" + "github.com/tendermint/tendermint/internal/test" + tmjson "github.com/tendermint/tendermint/libs/json" + "github.com/tendermint/tendermint/privval" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmversion "github.com/tendermint/tendermint/proto/tendermint/version" + e2e "github.com/tendermint/tendermint/test/e2e/pkg" + "github.com/tendermint/tendermint/types" + "github.com/tendermint/tendermint/version" +) + +// 1 in 4 evidence is light client evidence, the rest is duplicate vote evidence +const lightClientEvidenceRatio = 4 + +// InjectEvidence takes a running testnet and generates an amount of valid +// evidence and broadcasts it to a random node through the rpc endpoint `/broadcast_evidence`. +// Evidence is random and can be a mixture of LightClientAttackEvidence and +// DuplicateVoteEvidence. +func InjectEvidence(ctx context.Context, r *rand.Rand, testnet *e2e.Testnet, amount int) error { + // select a random node + var targetNode *e2e.Node + + for _, idx := range r.Perm(len(testnet.Nodes)) { + targetNode = testnet.Nodes[idx] + + if targetNode.Mode == e2e.ModeSeed || targetNode.Mode == e2e.ModeLight { + targetNode = nil + continue + } + + break + } + + if targetNode == nil { + return errors.New("could not find node to inject evidence into") + } + + logger.Info(fmt.Sprintf("Injecting evidence through %v (amount: %d)...", targetNode.Name, amount)) + + client, err := targetNode.Client() + if err != nil { + return err + } + + // request the latest block and validator set from the node + blockRes, err := client.Block(ctx, nil) + if err != nil { + return err + } + evidenceHeight := blockRes.Block.Height + waitHeight := blockRes.Block.Height + 3 + + nValidators := 100 + valRes, err := client.Validators(ctx, &evidenceHeight, nil, &nValidators) + if err != nil { + return err + } + + valSet, err := types.ValidatorSetFromExistingValidators(valRes.Validators) + if err != nil { + return err + } + + // get the private keys of all the validators in the network + privVals, err := getPrivateValidatorKeys(testnet) + if err != nil { + return err + } + + // wait for the node to reach the height above the forged height so that + // it is able to validate the evidence + _, err = waitForNode(targetNode, waitHeight, time.Minute) + if err != nil { + return err + } + + var ev types.Evidence + for i := 1; i <= amount; i++ { + if i%lightClientEvidenceRatio == 0 { + ev, err = generateLightClientAttackEvidence( + ctx, privVals, evidenceHeight, valSet, testnet.Name, blockRes.Block.Time, + ) + } else { + ev, err = generateDuplicateVoteEvidence( + ctx, privVals, evidenceHeight, valSet, testnet.Name, blockRes.Block.Time, + ) + } + if err != nil { + return err + } + + _, err := client.BroadcastEvidence(ctx, ev) + if err != nil { + return err + } + } + + // wait for the node to reach the height above the forged height so that + // it is able to validate the evidence + _, err = waitForNode(targetNode, blockRes.Block.Height+2, 30*time.Second) + if err != nil { + return err + } + + logger.Info(fmt.Sprintf("Finished sending evidence (height %d)", blockRes.Block.Height+2)) + + return nil +} + +func getPrivateValidatorKeys(testnet *e2e.Testnet) ([]types.MockPV, error) { + privVals := []types.MockPV{} + + for _, node := range testnet.Nodes { + if node.Mode == e2e.ModeValidator { + privKeyPath := filepath.Join(testnet.Dir, node.Name, PrivvalKeyFile) + privKey, err := readPrivKey(privKeyPath) + if err != nil { + return nil, err + } + // Create mock private validators from the validators private key. MockPV is + // stateless which means we can double vote and do other funky stuff + privVals = append(privVals, types.NewMockPVWithParams(privKey, false, false)) + } + } + + return privVals, nil +} + +// creates evidence of a lunatic attack. The height provided is the common height. +// The forged height happens 2 blocks later. +func generateLightClientAttackEvidence( + ctx context.Context, + privVals []types.MockPV, + height int64, + vals *types.ValidatorSet, + chainID string, + evTime time.Time, +) (*types.LightClientAttackEvidence, error) { + // forge a random header + forgedHeight := height + 2 + forgedTime := evTime.Add(1 * time.Second) + header := makeHeaderRandom(chainID, forgedHeight) + header.Time = forgedTime + + // add a new bogus validator and remove an existing one to + // vary the validator set slightly + pv, conflictingVals, err := mutateValidatorSet(ctx, privVals, vals) + if err != nil { + return nil, err + } + + header.ValidatorsHash = conflictingVals.Hash() + + // create a commit for the forged header + blockID := makeBlockID(header.Hash(), 1000, []byte("partshash")) + voteSet := types.NewVoteSet(chainID, forgedHeight, 0, tmproto.SignedMsgType(2), conflictingVals) + commit, err := test.MakeCommitFromVoteSet(blockID, voteSet, pv, forgedTime) + if err != nil { + return nil, err + } + + ev := &types.LightClientAttackEvidence{ + ConflictingBlock: &types.LightBlock{ + SignedHeader: &types.SignedHeader{ + Header: header, + Commit: commit, + }, + ValidatorSet: conflictingVals, + }, + CommonHeight: height, + TotalVotingPower: vals.TotalVotingPower(), + Timestamp: evTime, + } + ev.ByzantineValidators = ev.GetByzantineValidators(vals, &types.SignedHeader{ + Header: makeHeaderRandom(chainID, forgedHeight), + }) + return ev, nil +} + +// generateDuplicateVoteEvidence picks a random validator from the val set and +// returns duplicate vote evidence against the validator +func generateDuplicateVoteEvidence( + ctx context.Context, + privVals []types.MockPV, + height int64, + vals *types.ValidatorSet, + chainID string, + time time.Time, +) (*types.DuplicateVoteEvidence, error) { + privVal, valIdx, err := getRandomValidatorIndex(privVals, vals) + if err != nil { + return nil, err + } + voteA, err := test.MakeVote(privVal, chainID, valIdx, height, 0, 2, makeRandomBlockID(), time) + if err != nil { + return nil, err + } + voteB, err := test.MakeVote(privVal, chainID, valIdx, height, 0, 2, makeRandomBlockID(), time) + if err != nil { + return nil, err + } + ev, err := types.NewDuplicateVoteEvidence(voteA, voteB, time, vals) + if err != nil { + return nil, fmt.Errorf("could not generate evidence: %w", err) + } + + return ev, nil +} + +// getRandomValidatorIndex picks a random validator from a slice of mock PrivVals that's +// also part of the validator set, returning the PrivVal and its index in the validator set +func getRandomValidatorIndex(privVals []types.MockPV, vals *types.ValidatorSet) (types.MockPV, int32, error) { + for _, idx := range rand.Perm(len(privVals)) { + pv := privVals[idx] + valIdx, _ := vals.GetByAddress(pv.PrivKey.PubKey().Address()) + if valIdx >= 0 { + return pv, valIdx, nil + } + } + return types.MockPV{}, -1, errors.New("no private validator found in validator set") +} + +func readPrivKey(keyFilePath string) (crypto.PrivKey, error) { + keyJSONBytes, err := ioutil.ReadFile(keyFilePath) + if err != nil { + return nil, err + } + pvKey := privval.FilePVKey{} + err = tmjson.Unmarshal(keyJSONBytes, &pvKey) + if err != nil { + return nil, fmt.Errorf("error reading PrivValidator key from %v: %w", keyFilePath, err) + } + + return pvKey.PrivKey, nil +} + +func makeHeaderRandom(chainID string, height int64) *types.Header { + return &types.Header{ + Version: tmversion.Consensus{Block: version.BlockProtocol, App: 1}, + ChainID: chainID, + Height: height, + Time: time.Now(), + LastBlockID: makeBlockID([]byte("headerhash"), 1000, []byte("partshash")), + LastCommitHash: crypto.CRandBytes(tmhash.Size), + DataHash: crypto.CRandBytes(tmhash.Size), + ValidatorsHash: crypto.CRandBytes(tmhash.Size), + NextValidatorsHash: crypto.CRandBytes(tmhash.Size), + ConsensusHash: crypto.CRandBytes(tmhash.Size), + AppHash: crypto.CRandBytes(tmhash.Size), + LastResultsHash: crypto.CRandBytes(tmhash.Size), + EvidenceHash: crypto.CRandBytes(tmhash.Size), + ProposerAddress: crypto.CRandBytes(crypto.AddressSize), + } +} + +func makeRandomBlockID() types.BlockID { + return makeBlockID(crypto.CRandBytes(tmhash.Size), 100, crypto.CRandBytes(tmhash.Size)) +} + +func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.BlockID { + var ( + h = make([]byte, tmhash.Size) + psH = make([]byte, tmhash.Size) + ) + copy(h, hash) + copy(psH, partSetHash) + return types.BlockID{ + Hash: h, + PartSetHeader: types.PartSetHeader{ + Total: partSetSize, + Hash: psH, + }, + } +} + +func mutateValidatorSet(ctx context.Context, privVals []types.MockPV, vals *types.ValidatorSet, +) ([]types.PrivValidator, *types.ValidatorSet, error) { + newVal, newPrivVal, err := test.Validator(ctx, 10) + if err != nil { + return nil, nil, err + } + + var newVals *types.ValidatorSet + if vals.Size() > 2 { + newVals = types.NewValidatorSet(append(vals.Copy().Validators[:vals.Size()-1], newVal)) + } else { + newVals = types.NewValidatorSet(append(vals.Copy().Validators, newVal)) + } + + // we need to sort the priv validators with the same index as the validator set + pv := make([]types.PrivValidator, newVals.Size()) + for idx, val := range newVals.Validators { + found := false + for _, p := range append(privVals, newPrivVal.(types.MockPV)) { + if bytes.Equal(p.PrivKey.PubKey().Address(), val.Address) { + pv[idx] = p + found = true + break + } + } + if !found { + return nil, nil, fmt.Errorf("missing priv validator for %v", val.Address) + } + } + + return pv, newVals, nil +} diff --git a/test/e2e/runner/main.go b/test/e2e/runner/main.go index 80048ee98..798bf12e4 100644 --- a/test/e2e/runner/main.go +++ b/test/e2e/runner/main.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "math/rand" "os" "strconv" @@ -12,9 +13,9 @@ import ( e2e "github.com/tendermint/tendermint/test/e2e/pkg" ) -var ( - logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) -) +const randomSeed = 2308084734268 + +var logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) func main() { NewCLI().Run() @@ -56,6 +57,8 @@ func NewCLI() *CLI { return err } + r := rand.New(rand.NewSource(randomSeed)) // nolint: gosec + chLoadResult := make(chan error) ctx, loadCancel := context.WithCancel(context.Background()) defer loadCancel() @@ -84,6 +87,15 @@ func NewCLI() *CLI { } } + if cli.testnet.Evidence > 0 { + if err := InjectEvidence(ctx, r, cli.testnet, cli.testnet.Evidence); err != nil { + return err + } + if err := Wait(cli.testnet, 5); err != nil { // ensure chain progress + return err + } + } + loadCancel() if err := <-chLoadResult; err != nil { return err @@ -175,6 +187,29 @@ func NewCLI() *CLI { }, }) + cli.root.AddCommand(&cobra.Command{ + Use: "evidence [amount]", + Args: cobra.MaximumNArgs(1), + Short: "Generates and broadcasts evidence to a random node", + RunE: func(cmd *cobra.Command, args []string) (err error) { + amount := 1 + + if len(args) == 1 { + amount, err = strconv.Atoi(args[0]) + if err != nil { + return err + } + } + + return InjectEvidence( + cmd.Context(), + rand.New(rand.NewSource(randomSeed)), // nolint: gosec + cli.testnet, + amount, + ) + }, + }) + cli.root.AddCommand(&cobra.Command{ Use: "test", Short: "Runs test cases against a running testnet", diff --git a/test/e2e/runner/setup.go b/test/e2e/runner/setup.go index 311b1dda2..db180b382 100644 --- a/test/e2e/runner/setup.go +++ b/test/e2e/runner/setup.go @@ -200,7 +200,7 @@ func MakeGenesis(testnet *e2e.Testnet) (types.GenesisDoc, error) { InitialHeight: testnet.InitialHeight, } // set the app version to 1 - genesis.ConsensusParams.Version.AppVersion = 1 + genesis.ConsensusParams.Version.App = 1 for validator, power := range testnet.Validators { genesis.Validators = append(genesis.Validators, types.GenesisValidator{ Name: validator.Name, @@ -324,16 +324,19 @@ func MakeConfig(node *e2e.Node) (*config.Config, error) { // MakeAppConfig generates an ABCI application config for a node. func MakeAppConfig(node *e2e.Node) ([]byte, error) { cfg := map[string]interface{}{ - "chain_id": node.Testnet.Name, - "dir": "data/app", - "listen": AppAddressUNIX, - "mode": node.Mode, - "proxy_port": node.ProxyPort, - "protocol": "socket", - "persist_interval": node.PersistInterval, - "snapshot_interval": node.SnapshotInterval, - "retain_blocks": node.RetainBlocks, - "key_type": node.PrivvalKey.Type(), + "chain_id": node.Testnet.Name, + "dir": "data/app", + "listen": AppAddressUNIX, + "mode": node.Mode, + "proxy_port": node.ProxyPort, + "protocol": "socket", + "persist_interval": node.PersistInterval, + "snapshot_interval": node.SnapshotInterval, + "retain_blocks": node.RetainBlocks, + "key_type": node.PrivvalKey.Type(), + "prepare_proposal_delay": node.Testnet.PrepareProposalDelay, + "process_proposal_delay": node.Testnet.ProcessProposalDelay, + "check_tx_delay": node.Testnet.CheckTxDelay, } switch node.ABCIProtocol { case e2e.ProtocolUNIX: diff --git a/test/e2e/tests/evidence_test.go b/test/e2e/tests/evidence_test.go new file mode 100644 index 000000000..f7f2ede79 --- /dev/null +++ b/test/e2e/tests/evidence_test.go @@ -0,0 +1,22 @@ +package e2e_test + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +// assert that all nodes that have blocks at the height of a misbehavior has evidence +// for that misbehavior +func TestEvidence_Misbehavior(t *testing.T) { + blocks := fetchBlockChain(t) + testnet := loadTestnet(t) + seenEvidence := 0 + for _, block := range blocks { + if len(block.Evidence.Evidence) != 0 { + seenEvidence += len(block.Evidence.Evidence) + } + } + require.Equal(t, testnet.Evidence, seenEvidence, + "difference between the amount of evidence produced and committed") +} diff --git a/test/fuzz/mempool/v0/fuzz_test.go b/test/fuzz/mempool/v0/fuzz_test.go index 210de40d1..d371ee3ff 100644 --- a/test/fuzz/mempool/v0/fuzz_test.go +++ b/test/fuzz/mempool/v0/fuzz_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" + mempoolv0 "github.com/tendermint/tendermint/test/fuzz/mempool/v0" ) diff --git a/test/fuzz/mempool/v1/fuzz_test.go b/test/fuzz/mempool/v1/fuzz_test.go index 26b2c3609..000f6df3c 100644 --- a/test/fuzz/mempool/v1/fuzz_test.go +++ b/test/fuzz/mempool/v1/fuzz_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" + mempoolv1 "github.com/tendermint/tendermint/test/fuzz/mempool/v1" ) diff --git a/types/block.go b/types/block.go index 2d8b5167a..e31ebb862 100644 --- a/types/block.go +++ b/types/block.go @@ -137,22 +137,22 @@ func (b *Block) Hash() tmbytes.HexBytes { // MakePartSet returns a PartSet containing parts of a serialized block. // This is the form in which the block is gossipped to peers. // CONTRACT: partSize is greater than zero. -func (b *Block) MakePartSet(partSize uint32) *PartSet { +func (b *Block) MakePartSet(partSize uint32) (*PartSet, error) { if b == nil { - return nil + return nil, errors.New("nil block") } b.mtx.Lock() defer b.mtx.Unlock() pbb, err := b.ToProto() if err != nil { - panic(err) + return nil, err } bz, err := proto.Marshal(pbb) if err != nil { - panic(err) + return nil, err } - return NewPartSetFromData(bz, partSize) + return NewPartSetFromData(bz, partSize), nil } // HashesTo is a convenience function that checks if a block hashes to the given argument. @@ -509,7 +509,8 @@ func (h *Header) StringIndented(indent string) string { indent, h.LastResultsHash, indent, h.EvidenceHash, indent, h.ProposerAddress, - indent, h.Hash()) + indent, h.Hash(), + ) } // ToProto converts Header to protobuf diff --git a/types/block_test.go b/types/block_test.go index 2355cb0f1..10a81d5d7 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -41,7 +41,8 @@ func TestBlockAddEvidence(t *testing.T) { commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) require.NoError(t, err) - ev := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + require.NoError(t, err) evList := []Evidence{ev} block := MakeBlock(h, txs, commit, evList) @@ -61,7 +62,8 @@ func TestBlockValidateBasic(t *testing.T) { commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) require.NoError(t, err) - ev := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + require.NoError(t, err) evList := []Evidence{ev} testCases := []struct { @@ -110,15 +112,20 @@ func TestBlockHash(t *testing.T) { } func TestBlockMakePartSet(t *testing.T) { - assert.Nil(t, (*Block)(nil).MakePartSet(2)) + bps, err := (*Block)(nil).MakePartSet(2) + assert.Error(t, err) + assert.Nil(t, bps) - partSet := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).MakePartSet(1024) + partSet, err := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).MakePartSet(1024) + require.NoError(t, err) assert.NotNil(t, partSet) assert.EqualValues(t, 1, partSet.Total()) } func TestBlockMakePartSetWithEvidence(t *testing.T) { - assert.Nil(t, (*Block)(nil).MakePartSet(2)) + bps, err := (*Block)(nil).MakePartSet(2) + assert.Error(t, err) + assert.Nil(t, bps) lastID := makeBlockIDRandom() h := int64(3) @@ -127,10 +134,13 @@ func TestBlockMakePartSetWithEvidence(t *testing.T) { commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) require.NoError(t, err) - ev := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + require.NoError(t, err) evList := []Evidence{ev} - partSet := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(512) + partSet, err := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(512) + require.NoError(t, err) + assert.NotNil(t, partSet) assert.EqualValues(t, 4, partSet.Total()) } @@ -144,7 +154,8 @@ func TestBlockHashesTo(t *testing.T) { commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) require.NoError(t, err) - ev := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + require.NoError(t, err) evList := []Evidence{ev} block := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList) @@ -635,7 +646,8 @@ func TestBlockProtoBuf(t *testing.T) { b2 := MakeBlock(h, []Tx{Tx([]byte{1})}, c1, []Evidence{}) b2.ProposerAddress = tmrand.Bytes(crypto.AddressSize) evidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) - evi := NewMockDuplicateVoteEvidence(h, evidenceTime, "block-test-chain") + evi, err := NewMockDuplicateVoteEvidence(h, evidenceTime, "block-test-chain") + require.NoError(t, err) b2.Evidence = EvidenceData{Evidence: EvidenceList{evi}} b2.EvidenceHash = b2.Evidence.Hash() @@ -699,7 +711,8 @@ func TestDataProtoBuf(t *testing.T) { // TestEvidenceDataProtoBuf ensures parity in converting to and from proto. func TestEvidenceDataProtoBuf(t *testing.T) { const chainID = "mychain" - ev := NewMockDuplicateVoteEvidence(math.MaxInt64, time.Now(), chainID) + ev, err := NewMockDuplicateVoteEvidence(math.MaxInt64, time.Now(), chainID) + require.NoError(t, err) data := &EvidenceData{Evidence: EvidenceList{ev}} _ = data.ByteSize() testCases := []struct { diff --git a/types/event_bus_test.go b/types/event_bus_test.go index a0a2e2e5f..30bd6b178 100644 --- a/types/event_bus_test.go +++ b/types/event_bus_test.go @@ -285,7 +285,8 @@ func TestEventBusPublishEventNewEvidence(t *testing.T) { } }) - ev := NewMockDuplicateVoteEvidence(1, time.Now(), "test-chain-id") + ev, err := NewMockDuplicateVoteEvidence(1, time.Now(), "test-chain-id") + require.NoError(t, err) query := "tm.event='NewEvidence'" evSub, err := eventBus.Subscribe(context.Background(), "test", tmquery.MustParse(query)) diff --git a/types/evidence.go b/types/evidence.go index 35acaaed1..df158de33 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -20,13 +20,13 @@ import ( // Evidence represents any provable malicious activity by a validator. // Verification logic for each evidence is part of the evidence module. type Evidence interface { - ABCI() []abci.Evidence // forms individual evidence to be sent to the application - Bytes() []byte // bytes which comprise the evidence - Hash() []byte // hash of the evidence - Height() int64 // height of the infraction - String() string // string format of the evidence - Time() time.Time // time of the infraction - ValidateBasic() error // basic consistency check + ABCI() []abci.Misbehavior // forms individual evidence to be sent to the application + Bytes() []byte // bytes which comprise the evidence + Hash() []byte // hash of the evidence + Height() int64 // height of the infraction + String() string // string format of the evidence + Time() time.Time // time of the infraction + ValidateBasic() error // basic consistency check } //-------------------------------------------------------------------------------------- @@ -45,15 +45,20 @@ type DuplicateVoteEvidence struct { var _ Evidence = &DuplicateVoteEvidence{} // NewDuplicateVoteEvidence creates DuplicateVoteEvidence with right ordering given -// two conflicting votes. If one of the votes is nil, evidence returned is nil as well -func NewDuplicateVoteEvidence(vote1, vote2 *Vote, blockTime time.Time, valSet *ValidatorSet) *DuplicateVoteEvidence { +// two conflicting votes. If either of the votes is nil, the val set is nil or the voter is +// not in the val set, an error is returned +func NewDuplicateVoteEvidence(vote1, vote2 *Vote, blockTime time.Time, valSet *ValidatorSet, +) (*DuplicateVoteEvidence, error) { var voteA, voteB *Vote - if vote1 == nil || vote2 == nil || valSet == nil { - return nil + if vote1 == nil || vote2 == nil { + return nil, errors.New("missing vote") + } + if valSet == nil { + return nil, errors.New("missing validator set") } idx, val := valSet.GetByAddress(vote1.ValidatorAddress) if idx == -1 { - return nil + return nil, fmt.Errorf("validator %s not in validator set", vote1.ValidatorAddress.String()) } if strings.Compare(vote1.BlockID.Key(), vote2.BlockID.Key()) == -1 { @@ -69,13 +74,13 @@ func NewDuplicateVoteEvidence(vote1, vote2 *Vote, blockTime time.Time, valSet *V TotalVotingPower: valSet.TotalVotingPower(), ValidatorPower: val.VotingPower, Timestamp: blockTime, - } + }, nil } // ABCI returns the application relevant representation of the evidence -func (dve *DuplicateVoteEvidence) ABCI() []abci.Evidence { - return []abci.Evidence{{ - Type: abci.EvidenceType_DUPLICATE_VOTE, +func (dve *DuplicateVoteEvidence) ABCI() []abci.Misbehavior { + return []abci.Misbehavior{{ + Type: abci.MisbehaviorType_DUPLICATE_VOTE, Validator: abci.Validator{ Address: dve.VoteA.ValidatorAddress, Power: dve.ValidatorPower, @@ -199,12 +204,12 @@ type LightClientAttackEvidence struct { var _ Evidence = &LightClientAttackEvidence{} -// ABCI forms an array of abci evidence for each byzantine validator -func (l *LightClientAttackEvidence) ABCI() []abci.Evidence { - abciEv := make([]abci.Evidence, len(l.ByzantineValidators)) +// ABCI forms an array of abci.Misbehavior for each byzantine validator +func (l *LightClientAttackEvidence) ABCI() []abci.Misbehavior { + abciEv := make([]abci.Misbehavior, len(l.ByzantineValidators)) for idx, val := range l.ByzantineValidators { - abciEv[idx] = abci.Evidence{ - Type: abci.EvidenceType_LIGHT_CLIENT_ATTACK, + abciEv[idx] = abci.Misbehavior{ + Type: abci.MisbehaviorType_LIGHT_CLIENT_ATTACK, Validator: TM2PB.Validator(val), Height: l.Height(), Time: l.Timestamp, @@ -459,6 +464,16 @@ func (evl EvidenceList) Has(evidence Evidence) bool { return false } +// ToABCI converts the evidence list to a slice of the ABCI protobuf messages +// for use when communicating the evidence to an application. +func (evl EvidenceList) ToABCI() []abci.Misbehavior { + var el []abci.Misbehavior + for _, e := range evl { + el = append(el, e.ABCI()...) + } + return el +} + //------------------------------------------ PROTO -------------------------------------- // EvidenceToProto is a generalized function for encoding evidence that conforms to the @@ -554,23 +569,32 @@ func (err *ErrEvidenceOverflow) Error() string { // unstable - use only for testing // assumes the round to be 0 and the validator index to be 0 -func NewMockDuplicateVoteEvidence(height int64, time time.Time, chainID string) *DuplicateVoteEvidence { +func NewMockDuplicateVoteEvidence(height int64, time time.Time, chainID string) (*DuplicateVoteEvidence, error) { val := NewMockPV() return NewMockDuplicateVoteEvidenceWithValidator(height, time, val, chainID) } // assumes voting power to be 10 and validator to be the only one in the set func NewMockDuplicateVoteEvidenceWithValidator(height int64, time time.Time, - pv PrivValidator, chainID string) *DuplicateVoteEvidence { - pubKey, _ := pv.GetPubKey() + pv PrivValidator, chainID string) (*DuplicateVoteEvidence, error) { + pubKey, err := pv.GetPubKey() + if err != nil { + return nil, err + } val := NewValidator(pubKey, 10) voteA := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) vA := voteA.ToProto() - _ = pv.SignVote(chainID, vA) + err = pv.SignVote(chainID, vA) + if err != nil { + return nil, err + } voteA.Signature = vA.Signature voteB := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) vB := voteB.ToProto() - _ = pv.SignVote(chainID, vB) + err = pv.SignVote(chainID, vB) + if err != nil { + return nil, err + } voteB.Signature = vB.Signature return NewDuplicateVoteEvidence(voteA, voteB, time, NewValidatorSet([]*Validator{val})) } diff --git a/types/evidence_test.go b/types/evidence_test.go index 946373aad..feb0b0195 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -43,7 +43,8 @@ func randomDuplicateVoteEvidence(t *testing.T) *DuplicateVoteEvidence { func TestDuplicateVoteEvidence(t *testing.T) { const height = int64(13) - ev := NewMockDuplicateVoteEvidence(height, time.Now(), "mock-chain-id") + ev, err := NewMockDuplicateVoteEvidence(height, time.Now(), "mock-chain-id") + require.NoError(t, err) assert.Equal(t, ev.Hash(), tmhash.Sum(ev.Bytes())) assert.NotNil(t, ev.String()) assert.Equal(t, ev.Height(), height) @@ -82,7 +83,8 @@ func TestDuplicateVoteEvidenceValidation(t *testing.T) { vote1 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID, defaultVoteTime) vote2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID2, defaultVoteTime) valSet := NewValidatorSet([]*Validator{val.ExtractIntoValidator(10)}) - ev := NewDuplicateVoteEvidence(vote1, vote2, defaultVoteTime, valSet) + ev, err := NewDuplicateVoteEvidence(vote1, vote2, defaultVoteTime, valSet) + require.NoError(t, err) tc.malleateEvidence(ev) assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result") }) @@ -224,7 +226,8 @@ func TestLightClientAttackEvidenceValidation(t *testing.T) { } func TestMockEvidenceValidateBasic(t *testing.T) { - goodEvidence := NewMockDuplicateVoteEvidence(int64(1), time.Now(), "mock-chain-id") + goodEvidence, err := NewMockDuplicateVoteEvidence(int64(1), time.Now(), "mock-chain-id") + require.NoError(t, err) assert.Nil(t, goodEvidence.ValidateBasic()) } @@ -245,9 +248,8 @@ func makeVote( vpb := v.ToProto() err = val.SignVote(chainID, vpb) - if err != nil { - panic(err) - } + require.NoError(t, err) + v.Signature = vpb.Signature return v } diff --git a/types/genesis.go b/types/genesis.go index 974bb8112..b75bce13e 100644 --- a/types/genesis.go +++ b/types/genesis.go @@ -12,7 +12,6 @@ import ( tmbytes "github.com/tendermint/tendermint/libs/bytes" tmjson "github.com/tendermint/tendermint/libs/json" tmos "github.com/tendermint/tendermint/libs/os" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtime "github.com/tendermint/tendermint/types/time" ) @@ -37,13 +36,13 @@ type GenesisValidator struct { // GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set. type GenesisDoc struct { - GenesisTime time.Time `json:"genesis_time"` - ChainID string `json:"chain_id"` - InitialHeight int64 `json:"initial_height"` - ConsensusParams *tmproto.ConsensusParams `json:"consensus_params,omitempty"` - Validators []GenesisValidator `json:"validators,omitempty"` - AppHash tmbytes.HexBytes `json:"app_hash"` - AppState json.RawMessage `json:"app_state,omitempty"` + GenesisTime time.Time `json:"genesis_time"` + ChainID string `json:"chain_id"` + InitialHeight int64 `json:"initial_height"` + ConsensusParams *ConsensusParams `json:"consensus_params,omitempty"` + Validators []GenesisValidator `json:"validators,omitempty"` + AppHash tmbytes.HexBytes `json:"app_hash"` + AppState json.RawMessage `json:"app_state,omitempty"` } // SaveAs is a utility method for saving GenensisDoc as a JSON file. @@ -83,7 +82,7 @@ func (genDoc *GenesisDoc) ValidateAndComplete() error { if genDoc.ConsensusParams == nil { genDoc.ConsensusParams = DefaultConsensusParams() - } else if err := ValidateConsensusParams(*genDoc.ConsensusParams); err != nil { + } else if err := genDoc.ConsensusParams.ValidateBasic(); err != nil { return err } diff --git a/types/params.go b/types/params.go index 16c85aa55..246037d85 100644 --- a/types/params.go +++ b/types/params.go @@ -5,7 +5,8 @@ import ( "fmt" "time" - abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/tmhash" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -19,11 +20,52 @@ const ( // MaxBlockPartsCount is the maximum number of block parts. MaxBlockPartsCount = (MaxBlockSizeBytes / BlockPartSizeBytes) + 1 + + ABCIPubKeyTypeEd25519 = ed25519.KeyType + ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType ) +var ABCIPubKeyTypesToNames = map[string]string{ + ABCIPubKeyTypeEd25519: ed25519.PubKeyName, + ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName, +} + +// ConsensusParams contains consensus critical parameters that determine the +// validity of blocks. +type ConsensusParams struct { + Block BlockParams `json:"block"` + Evidence EvidenceParams `json:"evidence"` + Validator ValidatorParams `json:"validator"` + Version VersionParams `json:"version"` +} + +// BlockParams define limits on the block size and gas plus minimum time +// between blocks. +type BlockParams struct { + MaxBytes int64 `json:"max_bytes"` + MaxGas int64 `json:"max_gas"` +} + +// EvidenceParams determine how we handle evidence of malfeasance. +type EvidenceParams struct { + MaxAgeNumBlocks int64 `json:"max_age_num_blocks"` // only accept new evidence more recent than this + MaxAgeDuration time.Duration `json:"max_age_duration"` + MaxBytes int64 `json:"max_bytes"` +} + +// ValidatorParams restrict the public key types validators can use. +// NOTE: uses ABCI pubkey naming, not Amino names. +type ValidatorParams struct { + PubKeyTypes []string `json:"pub_key_types"` +} + +type VersionParams struct { + App uint64 `json:"app"` +} + // DefaultConsensusParams returns a default ConsensusParams. -func DefaultConsensusParams() *tmproto.ConsensusParams { - return &tmproto.ConsensusParams{ +func DefaultConsensusParams() *ConsensusParams { + return &ConsensusParams{ Block: DefaultBlockParams(), Evidence: DefaultEvidenceParams(), Validator: DefaultValidatorParams(), @@ -32,17 +74,16 @@ func DefaultConsensusParams() *tmproto.ConsensusParams { } // DefaultBlockParams returns a default BlockParams. -func DefaultBlockParams() tmproto.BlockParams { - return tmproto.BlockParams{ - MaxBytes: 22020096, // 21MB - MaxGas: -1, - TimeIotaMs: 1000, // 1s +func DefaultBlockParams() BlockParams { + return BlockParams{ + MaxBytes: 22020096, // 21MB + MaxGas: -1, } } // DefaultEvidenceParams returns a default EvidenceParams. -func DefaultEvidenceParams() tmproto.EvidenceParams { - return tmproto.EvidenceParams{ +func DefaultEvidenceParams() EvidenceParams { + return EvidenceParams{ MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s MaxAgeDuration: 48 * time.Hour, MaxBytes: 1048576, // 1MB @@ -51,19 +92,19 @@ func DefaultEvidenceParams() tmproto.EvidenceParams { // DefaultValidatorParams returns a default ValidatorParams, which allows // only ed25519 pubkeys. -func DefaultValidatorParams() tmproto.ValidatorParams { - return tmproto.ValidatorParams{ +func DefaultValidatorParams() ValidatorParams { + return ValidatorParams{ PubKeyTypes: []string{ABCIPubKeyTypeEd25519}, } } -func DefaultVersionParams() tmproto.VersionParams { - return tmproto.VersionParams{ - AppVersion: 0, +func DefaultVersionParams() VersionParams { + return VersionParams{ + App: 0, } } -func IsValidPubkeyType(params tmproto.ValidatorParams, pubkeyType string) bool { +func IsValidPubkeyType(params ValidatorParams, pubkeyType string) bool { for i := 0; i < len(params.PubKeyTypes); i++ { if params.PubKeyTypes[i] == pubkeyType { return true @@ -74,7 +115,7 @@ func IsValidPubkeyType(params tmproto.ValidatorParams, pubkeyType string) bool { // Validate validates the ConsensusParams to ensure all values are within their // allowed limits, and returns an error if they are not. -func ValidateConsensusParams(params tmproto.ConsensusParams) error { +func (params ConsensusParams) ValidateBasic() error { if params.Block.MaxBytes <= 0 { return fmt.Errorf("block.MaxBytes must be greater than 0. Got %d", params.Block.MaxBytes) @@ -89,11 +130,6 @@ func ValidateConsensusParams(params tmproto.ConsensusParams) error { params.Block.MaxGas) } - if params.Block.TimeIotaMs <= 0 { - return fmt.Errorf("block.TimeIotaMs must be greater than 0. Got %v", - params.Block.TimeIotaMs) - } - if params.Evidence.MaxAgeNumBlocks <= 0 { return fmt.Errorf("evidence.MaxAgeNumBlocks must be greater than 0. Got %d", params.Evidence.MaxAgeNumBlocks) @@ -134,7 +170,7 @@ func ValidateConsensusParams(params tmproto.ConsensusParams) error { // Only the Block.MaxBytes and Block.MaxGas are included in the hash. // This allows the ConsensusParams to evolve more without breaking the block // protocol. No need for a Merkle tree here, just a small struct to hash. -func HashConsensusParams(params tmproto.ConsensusParams) []byte { +func (params ConsensusParams) Hash() []byte { hasher := tmhash.New() hp := tmproto.HashedParams{ @@ -156,7 +192,7 @@ func HashConsensusParams(params tmproto.ConsensusParams) []byte { // Update returns a copy of the params with updates from the non-zero fields of p2. // NOTE: note: must not modify the original -func UpdateConsensusParams(params tmproto.ConsensusParams, params2 *abci.ConsensusParams) tmproto.ConsensusParams { +func (params ConsensusParams) Update(params2 *tmproto.ConsensusParams) ConsensusParams { res := params // explicit copy if params2 == nil { @@ -179,7 +215,47 @@ func UpdateConsensusParams(params tmproto.ConsensusParams, params2 *abci.Consens res.Validator.PubKeyTypes = append([]string{}, params2.Validator.PubKeyTypes...) } if params2.Version != nil { - res.Version.AppVersion = params2.Version.AppVersion + res.Version.App = params2.Version.App } return res } + +func (params *ConsensusParams) ToProto() tmproto.ConsensusParams { + return tmproto.ConsensusParams{ + Block: &tmproto.BlockParams{ + MaxBytes: params.Block.MaxBytes, + MaxGas: params.Block.MaxGas, + }, + Evidence: &tmproto.EvidenceParams{ + MaxAgeNumBlocks: params.Evidence.MaxAgeNumBlocks, + MaxAgeDuration: params.Evidence.MaxAgeDuration, + MaxBytes: params.Evidence.MaxBytes, + }, + Validator: &tmproto.ValidatorParams{ + PubKeyTypes: params.Validator.PubKeyTypes, + }, + Version: &tmproto.VersionParams{ + App: params.Version.App, + }, + } +} + +func ConsensusParamsFromProto(pbParams tmproto.ConsensusParams) ConsensusParams { + return ConsensusParams{ + Block: BlockParams{ + MaxBytes: pbParams.Block.MaxBytes, + MaxGas: pbParams.Block.MaxGas, + }, + Evidence: EvidenceParams{ + MaxAgeNumBlocks: pbParams.Evidence.MaxAgeNumBlocks, + MaxAgeDuration: pbParams.Evidence.MaxAgeDuration, + MaxBytes: pbParams.Evidence.MaxBytes, + }, + Validator: ValidatorParams{ + PubKeyTypes: pbParams.Validator.PubKeyTypes, + }, + Version: VersionParams{ + App: pbParams.Version.App, + }, + } +} diff --git a/types/params_test.go b/types/params_test.go index f3a71ca50..c3ef682b4 100644 --- a/types/params_test.go +++ b/types/params_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/assert" - abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -19,77 +18,73 @@ var ( func TestConsensusParamsValidation(t *testing.T) { testCases := []struct { - params tmproto.ConsensusParams + params ConsensusParams valid bool }{ // test block params - 0: {makeParams(1, 0, 10, 2, 0, valEd25519), true}, - 1: {makeParams(0, 0, 10, 2, 0, valEd25519), false}, - 2: {makeParams(47*1024*1024, 0, 10, 2, 0, valEd25519), true}, - 3: {makeParams(10, 0, 10, 2, 0, valEd25519), true}, - 4: {makeParams(100*1024*1024, 0, 10, 2, 0, valEd25519), true}, - 5: {makeParams(101*1024*1024, 0, 10, 2, 0, valEd25519), false}, - 6: {makeParams(1024*1024*1024, 0, 10, 2, 0, valEd25519), false}, - 7: {makeParams(1024*1024*1024, 0, 10, -1, 0, valEd25519), false}, - 8: {makeParams(1, 0, -10, 2, 0, valEd25519), false}, + 0: {makeParams(1, 0, 2, 0, valEd25519), true}, + 1: {makeParams(0, 0, 2, 0, valEd25519), false}, + 2: {makeParams(47*1024*1024, 0, 2, 0, valEd25519), true}, + 3: {makeParams(10, 0, 2, 0, valEd25519), true}, + 4: {makeParams(100*1024*1024, 0, 2, 0, valEd25519), true}, + 5: {makeParams(101*1024*1024, 0, 2, 0, valEd25519), false}, + 6: {makeParams(1024*1024*1024, 0, 2, 0, valEd25519), false}, // test evidence params - 9: {makeParams(1, 0, 10, 0, 0, valEd25519), false}, - 10: {makeParams(1, 0, 10, 2, 2, valEd25519), false}, - 11: {makeParams(1000, 0, 10, 2, 1, valEd25519), true}, - 12: {makeParams(1, 0, 10, -1, 0, valEd25519), false}, + 7: {makeParams(1, 0, 0, 0, valEd25519), false}, + 8: {makeParams(1, 0, 2, 2, valEd25519), false}, + 9: {makeParams(1000, 0, 2, 1, valEd25519), true}, + 10: {makeParams(1, 0, -1, 0, valEd25519), false}, // test no pubkey type provided - 13: {makeParams(1, 0, 10, 2, 0, []string{}), false}, + 11: {makeParams(1, 0, 2, 0, []string{}), false}, // test invalid pubkey type provided - 14: {makeParams(1, 0, 10, 2, 0, []string{"potatoes make good pubkeys"}), false}, + 12: {makeParams(1, 0, 2, 0, []string{"potatoes make good pubkeys"}), false}, } for i, tc := range testCases { if tc.valid { - assert.NoErrorf(t, ValidateConsensusParams(tc.params), "expected no error for valid params (#%d)", i) + assert.NoErrorf(t, tc.params.ValidateBasic(), "expected no error for valid params (#%d)", i) } else { - assert.Errorf(t, ValidateConsensusParams(tc.params), "expected error for non valid params (#%d)", i) + assert.Errorf(t, tc.params.ValidateBasic(), "expected error for non valid params (#%d)", i) } } } func makeParams( blockBytes, blockGas int64, - blockTimeIotaMs int64, evidenceAge int64, maxEvidenceBytes int64, pubkeyTypes []string, -) tmproto.ConsensusParams { - return tmproto.ConsensusParams{ - Block: tmproto.BlockParams{ - MaxBytes: blockBytes, - MaxGas: blockGas, - TimeIotaMs: blockTimeIotaMs, +) ConsensusParams { + return ConsensusParams{ + Block: BlockParams{ + MaxBytes: blockBytes, + MaxGas: blockGas, }, - Evidence: tmproto.EvidenceParams{ + Evidence: EvidenceParams{ MaxAgeNumBlocks: evidenceAge, MaxAgeDuration: time.Duration(evidenceAge), MaxBytes: maxEvidenceBytes, }, - Validator: tmproto.ValidatorParams{ + Validator: ValidatorParams{ PubKeyTypes: pubkeyTypes, }, } } func TestConsensusParamsHash(t *testing.T) { - params := []tmproto.ConsensusParams{ - makeParams(4, 2, 10, 3, 1, valEd25519), - makeParams(1, 4, 10, 3, 1, valEd25519), - makeParams(1, 2, 10, 4, 1, valEd25519), - makeParams(2, 5, 10, 7, 1, valEd25519), - makeParams(1, 7, 10, 6, 1, valEd25519), - makeParams(9, 5, 10, 4, 1, valEd25519), - makeParams(7, 8, 10, 9, 1, valEd25519), - makeParams(4, 6, 10, 5, 1, valEd25519), + params := []ConsensusParams{ + makeParams(4, 2, 3, 1, valEd25519), + makeParams(1, 4, 3, 1, valEd25519), + makeParams(1, 2, 4, 1, valEd25519), + makeParams(2, 5, 7, 1, valEd25519), + makeParams(1, 7, 6, 1, valEd25519), + makeParams(9, 5, 4, 1, valEd25519), + makeParams(7, 8, 9, 1, valEd25519), + makeParams(4, 6, 5, 1, valEd25519), } hashes := make([][]byte, len(params)) for i := range params { - hashes[i] = HashConsensusParams(params[i]) + hashes[i] = params[i].Hash() } // make sure there are no duplicates... @@ -104,21 +99,21 @@ func TestConsensusParamsHash(t *testing.T) { func TestConsensusParamsUpdate(t *testing.T) { testCases := []struct { - params tmproto.ConsensusParams - updates *abci.ConsensusParams - updatedParams tmproto.ConsensusParams + params ConsensusParams + updates *tmproto.ConsensusParams + updatedParams ConsensusParams }{ // empty updates { - makeParams(1, 2, 10, 3, 0, valEd25519), - &abci.ConsensusParams{}, - makeParams(1, 2, 10, 3, 0, valEd25519), + makeParams(1, 2, 3, 0, valEd25519), + &tmproto.ConsensusParams{}, + makeParams(1, 2, 3, 0, valEd25519), }, // fine updates { - makeParams(1, 2, 10, 3, 0, valEd25519), - &abci.ConsensusParams{ - Block: &abci.BlockParams{ + makeParams(1, 2, 3, 0, valEd25519), + &tmproto.ConsensusParams{ + Block: &tmproto.BlockParams{ MaxBytes: 100, MaxGas: 200, }, @@ -131,21 +126,44 @@ func TestConsensusParamsUpdate(t *testing.T) { PubKeyTypes: valSecp256k1, }, }, - makeParams(100, 200, 10, 300, 50, valSecp256k1), + makeParams(100, 200, 300, 50, valSecp256k1), }, } + for _, tc := range testCases { - assert.Equal(t, tc.updatedParams, UpdateConsensusParams(tc.params, tc.updates)) + assert.Equal(t, tc.updatedParams, tc.params.Update(tc.updates)) } } func TestConsensusParamsUpdate_AppVersion(t *testing.T) { - params := makeParams(1, 2, 10, 3, 0, valEd25519) + params := makeParams(1, 2, 3, 0, valEd25519) - assert.EqualValues(t, 0, params.Version.AppVersion) + assert.EqualValues(t, 0, params.Version.App) - updated := UpdateConsensusParams(params, - &abci.ConsensusParams{Version: &tmproto.VersionParams{AppVersion: 1}}) + updated := params.Update( + &tmproto.ConsensusParams{Version: &tmproto.VersionParams{App: 1}}) - assert.EqualValues(t, 1, updated.Version.AppVersion) + assert.EqualValues(t, 1, updated.Version.App) +} + +func TestProto(t *testing.T) { + params := []ConsensusParams{ + makeParams(4, 2, 3, 1, valEd25519), + makeParams(1, 4, 3, 1, valEd25519), + makeParams(1, 2, 4, 1, valEd25519), + makeParams(2, 5, 7, 1, valEd25519), + makeParams(1, 7, 6, 1, valEd25519), + makeParams(9, 5, 4, 1, valEd25519), + makeParams(7, 8, 9, 1, valEd25519), + makeParams(4, 6, 5, 1, valEd25519), + } + + for i := range params { + pbParams := params[i].ToProto() + + oriParams := ConsensusParamsFromProto(pbParams) + + assert.Equal(t, params[i], oriParams) + + } } diff --git a/types/protobuf.go b/types/protobuf.go index 1ee094a9f..70b48da18 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -3,27 +3,10 @@ package types import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" cryptoenc "github.com/tendermint/tendermint/crypto/encoding" - "github.com/tendermint/tendermint/crypto/secp256k1" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) -//------------------------------------------------------- -// Use strings to distinguish types in ABCI messages - -const ( - ABCIPubKeyTypeEd25519 = ed25519.KeyType - ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType -) - -// TODO: Make non-global by allowing for registration of more pubkey types - -var ABCIPubKeyTypesToNames = map[string]string{ - ABCIPubKeyTypeEd25519: ed25519.PubKeyName, - ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName, -} - //------------------------------------------------------- // TM2PB is used for converting Tendermint ABCI to protobuf ABCI. @@ -97,17 +80,6 @@ func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate { return validators } -func (tm2pb) ConsensusParams(params *tmproto.ConsensusParams) *abci.ConsensusParams { - return &abci.ConsensusParams{ - Block: &abci.BlockParams{ - MaxBytes: params.Block.MaxBytes, - MaxGas: params.Block.MaxGas, - }, - Evidence: ¶ms.Evidence, - Validator: ¶ms.Validator, - } -} - // XXX: panics on nil or unknown pubkey type func (tm2pb) NewValidatorUpdate(pubkey crypto.PubKey, power int64) abci.ValidatorUpdate { pubkeyABCI, err := cryptoenc.PubKeyToProto(pubkey) diff --git a/types/protobuf_test.go b/types/protobuf_test.go index c617751e4..bfe7084bd 100644 --- a/types/protobuf_test.go +++ b/types/protobuf_test.go @@ -52,14 +52,6 @@ func TestABCIValidators(t *testing.T) { assert.Equal(t, tmValExpected, tmVals[0]) } -func TestABCIConsensusParams(t *testing.T) { - cp := DefaultConsensusParams() - abciCP := TM2PB.ConsensusParams(cp) - cp2 := UpdateConsensusParams(*cp, abciCP) - - assert.Equal(t, *cp, cp2) -} - type pubKeyEddie struct{} func (pubKeyEddie) Address() Address { return []byte{} } diff --git a/types/tx.go b/types/tx.go index b6a0ecd3a..8ed067ff7 100644 --- a/types/tx.go +++ b/types/tx.go @@ -45,13 +45,8 @@ type Txs []Tx // Hash returns the Merkle root hash of the transaction hashes. // i.e. the leaves of the tree are the hashes of the txs. func (txs Txs) Hash() []byte { - // These allocations will be removed once Txs is switched to [][]byte, - // ref #2603. This is because golang does not allow type casting slices without unsafe - txBzs := make([][]byte, len(txs)) - for i := 0; i < len(txs); i++ { - txBzs[i] = txs[i].Hash() - } - return merkle.HashFromByteSlices(txBzs) + hl := txs.hashList() + return merkle.HashFromByteSlices(hl) } // Index returns the index of this transaction in the list, or -1 if not found @@ -74,16 +69,9 @@ func (txs Txs) IndexByHash(hash []byte) int { return -1 } -// Proof returns a simple merkle proof for this node. -// Panics if i < 0 or i >= len(txs) -// TODO: optimize this! func (txs Txs) Proof(i int) TxProof { - l := len(txs) - bzs := make([][]byte, l) - for i := 0; i < l; i++ { - bzs[i] = txs[i].Hash() - } - root, proofs := merkle.ProofsFromByteSlices(bzs) + hl := txs.hashList() + root, proofs := merkle.ProofsFromByteSlices(hl) return TxProof{ RootHash: root, @@ -92,6 +80,50 @@ func (txs Txs) Proof(i int) TxProof { } } +func (txs Txs) hashList() [][]byte { + hl := make([][]byte, len(txs)) + for i := 0; i < len(txs); i++ { + hl[i] = txs[i].Hash() + } + return hl +} + +// Txs is a slice of transactions. Sorting a Txs value orders the transactions +// lexicographically. +func (txs Txs) Len() int { return len(txs) } +func (txs Txs) Swap(i, j int) { txs[i], txs[j] = txs[j], txs[i] } +func (txs Txs) Less(i, j int) bool { + return bytes.Compare(txs[i], txs[j]) == -1 +} + +func ToTxs(txl [][]byte) Txs { + txs := make([]Tx, 0, len(txl)) + for _, tx := range txl { + txs = append(txs, tx) + } + return txs +} + +func (txs Txs) Validate(maxSizeBytes int64) error { + var size int64 + for _, tx := range txs { + size += int64(len(tx)) + if size > maxSizeBytes { + return fmt.Errorf("transaction data size exceeds maximum %d", maxSizeBytes) + } + } + return nil +} + +// ToSliceOfBytes converts a Txs to slice of byte slices. +func (txs Txs) ToSliceOfBytes() [][]byte { + txBzs := make([][]byte, len(txs)) + for i := 0; i < len(txs); i++ { + txBzs[i] = txs[i] + } + return txBzs +} + // TxProof represents a Merkle proof of the presence of a transaction in the Merkle tree. type TxProof struct { RootHash tmbytes.HexBytes `json:"root_hash"` diff --git a/types/tx_test.go b/types/tx_test.go index 0ee308ced..bb53e0ea5 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "math/rand" "testing" "github.com/stretchr/testify/assert" @@ -20,11 +21,6 @@ func makeTxs(cnt, size int) Txs { return txs } -func randInt(low, high int) int { - off := tmrand.Int() % (high - low) - return low + off -} - func TestTxIndex(t *testing.T) { for i := 0; i < 20; i++ { txs := makeTxs(15, 60) @@ -149,3 +145,7 @@ func assertBadProof(t *testing.T, root []byte, bad []byte, good TxProof) { } } } + +func randInt(low, high int) int { + return rand.Intn(high-low) + low +} diff --git a/types/vote.go b/types/vote.go index 7b841c28a..02b3cad3d 100644 --- a/types/vote.go +++ b/types/vote.go @@ -220,6 +220,22 @@ func (vote *Vote) ToProto() *tmproto.Vote { } } +func VotesToProto(votes []*Vote) []*tmproto.Vote { + if votes == nil { + return nil + } + + res := make([]*tmproto.Vote, 0, len(votes)) + for _, vote := range votes { + v := vote.ToProto() + // protobuf crashes when serializing "repeated" fields with nil elements + if v != nil { + res = append(res, v) + } + } + return res +} + // FromProto converts a proto generetad type to a handwritten type // return type, nil if everything converts safely, otherwise nil, error func VoteFromProto(pv *tmproto.Vote) (*Vote, error) { diff --git a/types/vote_set.go b/types/vote_set.go index abdc18e61..829b54b53 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -226,6 +226,13 @@ func (voteSet *VoteSet) getVote(valIndex int32, blockKey string) (vote *Vote, ok return nil, false } +func (voteSet *VoteSet) GetVotes() []*Vote { + if voteSet == nil { + return nil + } + return voteSet.votes +} + // Assumes signature is valid. // If conflicting vote exists, returns it. func (voteSet *VoteSet) addVerifiedVote( @@ -627,6 +634,7 @@ func (voteSet *VoteSet) MakeCommit() *Commit { if commitSig.ForBlock() && !v.BlockID.Equals(*voteSet.maj23) { commitSig = NewCommitSigAbsent() } + commitSigs[i] = commitSig } diff --git a/version/version.go b/version/version.go index f7f0ddd17..d14f5cc31 100644 --- a/version/version.go +++ b/version/version.go @@ -9,7 +9,7 @@ const ( // when not using git describe. It is formatted with semantic versioning. TMVersionDefault = "0.34.20" // ABCISemVer is the semantic version of the ABCI library - ABCISemVer = "0.17.0" + ABCISemVer = "0.18.0" ABCIVersion = ABCISemVer )