diff --git a/abci/client/grpc_client.go b/abci/client/grpc_client.go index 2c645fe50..f1be2c120 100644 --- a/abci/client/grpc_client.go +++ b/abci/client/grpc_client.go @@ -181,3 +181,7 @@ func (cli *grpcClient) VerifyVoteExtension(ctx context.Context, params *types.Re func (cli *grpcClient) FinalizeBlock(ctx context.Context, params *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { return cli.client.FinalizeBlock(ctx, types.ToRequestFinalizeBlock(params).GetFinalizeBlock(), grpc.WaitForReady(true)) } + +func (cli *grpcClient) LoadLatest(ctx context.Context, params *types.RequestLoadLatest) (*types.ResponseLoadLatest, error) { + return cli.client.LoadLatest(ctx, types.ToRequestLoadLatest(params).GetLoadLatest(), grpc.WaitForReady(true)) +} diff --git a/abci/client/mocks/client.go b/abci/client/mocks/client.go index 5ef99aa18..44a5eb00f 100644 --- a/abci/client/mocks/client.go +++ b/abci/client/mocks/client.go @@ -263,6 +263,29 @@ func (_m *Client) ListSnapshots(_a0 context.Context, _a1 *types.RequestListSnaps return r0, r1 } +// LoadLatest provides a mock function with given fields: _a0, _a1 +func (_m *Client) LoadLatest(_a0 context.Context, _a1 *types.RequestLoadLatest) (*types.ResponseLoadLatest, error) { + ret := _m.Called(_a0, _a1) + + var r0 *types.ResponseLoadLatest + if rf, ok := ret.Get(0).(func(context.Context, *types.RequestLoadLatest) *types.ResponseLoadLatest); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ResponseLoadLatest) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.RequestLoadLatest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // LoadSnapshotChunk provides a mock function with given fields: _a0, _a1 func (_m *Client) LoadSnapshotChunk(_a0 context.Context, _a1 *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { ret := _m.Called(_a0, _a1) @@ -425,13 +448,13 @@ func (_m *Client) Wait() { _m.Called() } -type mockConstructorTestingTNewClient interface { +type NewClientT 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 { +func NewClient(t NewClientT) *Client { mock := &Client{} mock.Mock.Test(t) diff --git a/abci/client/socket_client.go b/abci/client/socket_client.go index 7dfcf76cc..80f106333 100644 --- a/abci/client/socket_client.go +++ b/abci/client/socket_client.go @@ -361,6 +361,14 @@ func (cli *socketClient) FinalizeBlock(ctx context.Context, req *types.RequestFi return res.GetFinalizeBlock(), nil } +func (cli *socketClient) LoadLatest(ctx context.Context, req *types.RequestLoadLatest) (*types.ResponseLoadLatest, error) { + res, err := cli.doRequest(ctx, types.ToRequestLoadLatest(req)) + if err != nil { + return nil, err + } + return res.GetLoadLatest(), nil +} + //---------------------------------------- func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { diff --git a/abci/types/application.go b/abci/types/application.go index e74b87743..9915d16a1 100644 --- a/abci/types/application.go +++ b/abci/types/application.go @@ -2,9 +2,10 @@ package types import "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. +// +//go:generate ../../scripts/mockery_generate.sh Application type Application interface { // Info/Query Connection Info(context.Context, *RequestInfo) (*ResponseInfo, error) // Return application info @@ -31,6 +32,8 @@ type Application interface { OfferSnapshot(context.Context, *RequestOfferSnapshot) (*ResponseOfferSnapshot, error) // Offer a snapshot to the application LoadSnapshotChunk(context.Context, *RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) // Load a snapshot chunk ApplySnapshotChunk(context.Context, *RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) // Apply a shapshot chunk + // Notify application to load latest application state (e.g. after DBSync finishes) + LoadLatest(context.Context, *RequestLoadLatest) (*ResponseLoadLatest, error) } //------------------------------------------------------- @@ -119,3 +122,7 @@ func (BaseApplication) FinalizeBlock(_ context.Context, req *RequestFinalizeBloc TxResults: txs, }, nil } + +func (BaseApplication) LoadLatest(_ context.Context, _ *RequestLoadLatest) (*ResponseLoadLatest, error) { + return &ResponseLoadLatest{}, nil +} diff --git a/abci/types/messages.go b/abci/types/messages.go index 80ab19525..2ab6ac1df 100644 --- a/abci/types/messages.go +++ b/abci/types/messages.go @@ -123,6 +123,12 @@ func ToRequestFinalizeBlock(req *RequestFinalizeBlock) *Request { } } +func ToRequestLoadLatest(req *RequestLoadLatest) *Request { + return &Request{ + Value: &Request_LoadLatest{req}, + } +} + //---------------------------------------- func ToResponseException(errStr string) *Response { @@ -226,3 +232,9 @@ func ToResponseFinalizeBlock(res *ResponseFinalizeBlock) *Response { Value: &Response_FinalizeBlock{res}, } } + +func ToResponseLoadLatest(res *ResponseLoadLatest) *Response { + return &Response{ + Value: &Response_LoadLatest{res}, + } +} diff --git a/abci/types/mocks/application.go b/abci/types/mocks/application.go index 16cf59d66..c6eb29219 100644 --- a/abci/types/mocks/application.go +++ b/abci/types/mocks/application.go @@ -198,6 +198,29 @@ func (_m *Application) ListSnapshots(_a0 context.Context, _a1 *types.RequestList return r0, r1 } +// LoadLatest provides a mock function with given fields: _a0, _a1 +func (_m *Application) LoadLatest(_a0 context.Context, _a1 *types.RequestLoadLatest) (*types.ResponseLoadLatest, error) { + ret := _m.Called(_a0, _a1) + + var r0 *types.ResponseLoadLatest + if rf, ok := ret.Get(0).(func(context.Context, *types.RequestLoadLatest) *types.ResponseLoadLatest); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ResponseLoadLatest) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.RequestLoadLatest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // LoadSnapshotChunk provides a mock function with given fields: _a0, _a1 func (_m *Application) LoadSnapshotChunk(_a0 context.Context, _a1 *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { ret := _m.Called(_a0, _a1) @@ -336,13 +359,13 @@ func (_m *Application) VerifyVoteExtension(_a0 context.Context, _a1 *types.Reque return r0, r1 } -type mockConstructorTestingTNewApplication interface { +type NewApplicationT 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 { +func NewApplication(t NewApplicationT) *Application { mock := &Application{} mock.Mock.Test(t) diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index 35c5a92d0..da2d42b2e 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -120,7 +120,7 @@ func (x ResponseOfferSnapshot_Result) String() string { } func (ResponseOfferSnapshot_Result) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{33, 0} + return fileDescriptor_252557cfdd89a31a, []int{34, 0} } type ResponseApplySnapshotChunk_Result int32 @@ -157,7 +157,7 @@ func (x ResponseApplySnapshotChunk_Result) String() string { } func (ResponseApplySnapshotChunk_Result) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{35, 0} + return fileDescriptor_252557cfdd89a31a, []int{36, 0} } type ResponseProcessProposal_ProposalStatus int32 @@ -185,7 +185,7 @@ func (x ResponseProcessProposal_ProposalStatus) String() string { } func (ResponseProcessProposal_ProposalStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{37, 0} + return fileDescriptor_252557cfdd89a31a, []int{38, 0} } type ResponseVerifyVoteExtension_VerifyStatus int32 @@ -213,7 +213,7 @@ func (x ResponseVerifyVoteExtension_VerifyStatus) String() string { } func (ResponseVerifyVoteExtension_VerifyStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{39, 0} + return fileDescriptor_252557cfdd89a31a, []int{40, 0} } // TxAction contains App-provided information on what to do with a transaction that is part of a raw proposal @@ -245,7 +245,7 @@ func (x TxRecord_TxAction) String() string { } func (TxRecord_TxAction) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{48, 0} + return fileDescriptor_252557cfdd89a31a, []int{50, 0} } type Request struct { @@ -269,6 +269,7 @@ type Request struct { // *Request_BeginBlock // *Request_DeliverTx // *Request_EndBlock + // *Request_LoadLatest Value isRequest_Value `protobuf_oneof:"value"` } @@ -368,6 +369,9 @@ type Request_DeliverTx struct { type Request_EndBlock struct { EndBlock *RequestEndBlock `protobuf:"bytes,22,opt,name=end_block,json=endBlock,proto3,oneof" json:"end_block,omitempty"` } +type Request_LoadLatest struct { + LoadLatest *RequestLoadLatest `protobuf:"bytes,23,opt,name=load_latest,json=loadLatest,proto3,oneof" json:"load_latest,omitempty"` +} func (*Request_Echo) isRequest_Value() {} func (*Request_Flush) isRequest_Value() {} @@ -388,6 +392,7 @@ func (*Request_FinalizeBlock) isRequest_Value() {} func (*Request_BeginBlock) isRequest_Value() {} func (*Request_DeliverTx) isRequest_Value() {} func (*Request_EndBlock) isRequest_Value() {} +func (*Request_LoadLatest) isRequest_Value() {} func (m *Request) GetValue() isRequest_Value { if m != nil { @@ -529,6 +534,13 @@ func (m *Request) GetEndBlock() *RequestEndBlock { return nil } +func (m *Request) GetLoadLatest() *RequestLoadLatest { + if x, ok := m.GetValue().(*Request_LoadLatest); ok { + return x.LoadLatest + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*Request) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -551,6 +563,7 @@ func (*Request) XXX_OneofWrappers() []interface{} { (*Request_BeginBlock)(nil), (*Request_DeliverTx)(nil), (*Request_EndBlock)(nil), + (*Request_LoadLatest)(nil), } } @@ -1988,6 +2001,42 @@ func (m *RequestEndBlock) GetHeight() int64 { return 0 } +type RequestLoadLatest struct { +} + +func (m *RequestLoadLatest) Reset() { *m = RequestLoadLatest{} } +func (m *RequestLoadLatest) String() string { return proto.CompactTextString(m) } +func (*RequestLoadLatest) ProtoMessage() {} +func (*RequestLoadLatest) Descriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{20} +} +func (m *RequestLoadLatest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestLoadLatest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestLoadLatest.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 *RequestLoadLatest) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestLoadLatest.Merge(m, src) +} +func (m *RequestLoadLatest) XXX_Size() int { + return m.Size() +} +func (m *RequestLoadLatest) XXX_DiscardUnknown() { + xxx_messageInfo_RequestLoadLatest.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestLoadLatest proto.InternalMessageInfo + type Response struct { // Types that are valid to be assigned to Value: // *Response_Exception @@ -2010,6 +2059,7 @@ type Response struct { // *Response_BeginBlock // *Response_DeliverTx // *Response_EndBlock + // *Response_LoadLatest Value isResponse_Value `protobuf_oneof:"value"` } @@ -2017,7 +2067,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{20} + return fileDescriptor_252557cfdd89a31a, []int{21} } func (m *Response) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2112,6 +2162,9 @@ type Response_DeliverTx struct { type Response_EndBlock struct { EndBlock *ResponseEndBlock `protobuf:"bytes,23,opt,name=end_block,json=endBlock,proto3,oneof" json:"end_block,omitempty"` } +type Response_LoadLatest struct { + LoadLatest *ResponseLoadLatest `protobuf:"bytes,24,opt,name=load_latest,json=loadLatest,proto3,oneof" json:"load_latest,omitempty"` +} func (*Response_Exception) isResponse_Value() {} func (*Response_Echo) isResponse_Value() {} @@ -2133,6 +2186,7 @@ func (*Response_FinalizeBlock) isResponse_Value() {} func (*Response_BeginBlock) isResponse_Value() {} func (*Response_DeliverTx) isResponse_Value() {} func (*Response_EndBlock) isResponse_Value() {} +func (*Response_LoadLatest) isResponse_Value() {} func (m *Response) GetValue() isResponse_Value { if m != nil { @@ -2281,6 +2335,13 @@ func (m *Response) GetEndBlock() *ResponseEndBlock { return nil } +func (m *Response) GetLoadLatest() *ResponseLoadLatest { + if x, ok := m.GetValue().(*Response_LoadLatest); ok { + return x.LoadLatest + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*Response) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -2304,6 +2365,7 @@ func (*Response) XXX_OneofWrappers() []interface{} { (*Response_BeginBlock)(nil), (*Response_DeliverTx)(nil), (*Response_EndBlock)(nil), + (*Response_LoadLatest)(nil), } } @@ -2316,7 +2378,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{21} + return fileDescriptor_252557cfdd89a31a, []int{22} } func (m *ResponseException) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2360,7 +2422,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{22} + return fileDescriptor_252557cfdd89a31a, []int{23} } func (m *ResponseEcho) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2403,7 +2465,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{23} + return fileDescriptor_252557cfdd89a31a, []int{24} } func (m *ResponseFlush) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2445,7 +2507,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{24} + return fileDescriptor_252557cfdd89a31a, []int{25} } func (m *ResponseInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2519,7 +2581,7 @@ func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } func (*ResponseInitChain) ProtoMessage() {} func (*ResponseInitChain) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{25} + return fileDescriptor_252557cfdd89a31a, []int{26} } func (m *ResponseInitChain) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2586,7 +2648,7 @@ func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } func (*ResponseQuery) ProtoMessage() {} func (*ResponseQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{26} + return fileDescriptor_252557cfdd89a31a, []int{27} } func (m *ResponseQuery) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2686,7 +2748,7 @@ func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } func (*ResponseBeginBlock) ProtoMessage() {} func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{27} + return fileDescriptor_252557cfdd89a31a, []int{28} } func (m *ResponseBeginBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2736,7 +2798,7 @@ func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } func (*ResponseCheckTx) ProtoMessage() {} func (*ResponseCheckTx) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{28} + return fileDescriptor_252557cfdd89a31a, []int{29} } func (m *ResponseCheckTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2829,7 +2891,7 @@ func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } func (*ResponseDeliverTx) ProtoMessage() {} func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{29} + return fileDescriptor_252557cfdd89a31a, []int{30} } func (m *ResponseDeliverTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2924,7 +2986,7 @@ func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } func (*ResponseEndBlock) ProtoMessage() {} func (*ResponseEndBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{30} + return fileDescriptor_252557cfdd89a31a, []int{31} } func (m *ResponseEndBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2983,7 +3045,7 @@ func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } func (*ResponseCommit) ProtoMessage() {} func (*ResponseCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{31} + return fileDescriptor_252557cfdd89a31a, []int{32} } func (m *ResponseCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3027,7 +3089,7 @@ func (m *ResponseListSnapshots) Reset() { *m = ResponseListSnapshots{} } func (m *ResponseListSnapshots) String() string { return proto.CompactTextString(m) } func (*ResponseListSnapshots) ProtoMessage() {} func (*ResponseListSnapshots) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{32} + return fileDescriptor_252557cfdd89a31a, []int{33} } func (m *ResponseListSnapshots) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3071,7 +3133,7 @@ func (m *ResponseOfferSnapshot) Reset() { *m = ResponseOfferSnapshot{} } func (m *ResponseOfferSnapshot) String() string { return proto.CompactTextString(m) } func (*ResponseOfferSnapshot) ProtoMessage() {} func (*ResponseOfferSnapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{33} + return fileDescriptor_252557cfdd89a31a, []int{34} } func (m *ResponseOfferSnapshot) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3115,7 +3177,7 @@ func (m *ResponseLoadSnapshotChunk) Reset() { *m = ResponseLoadSnapshotC func (m *ResponseLoadSnapshotChunk) String() string { return proto.CompactTextString(m) } func (*ResponseLoadSnapshotChunk) ProtoMessage() {} func (*ResponseLoadSnapshotChunk) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{34} + return fileDescriptor_252557cfdd89a31a, []int{35} } func (m *ResponseLoadSnapshotChunk) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3161,7 +3223,7 @@ func (m *ResponseApplySnapshotChunk) Reset() { *m = ResponseApplySnapsho func (m *ResponseApplySnapshotChunk) String() string { return proto.CompactTextString(m) } func (*ResponseApplySnapshotChunk) ProtoMessage() {} func (*ResponseApplySnapshotChunk) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{35} + return fileDescriptor_252557cfdd89a31a, []int{36} } func (m *ResponseApplySnapshotChunk) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3223,7 +3285,7 @@ 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{36} + return fileDescriptor_252557cfdd89a31a, []int{37} } func (m *ResponsePrepareProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3299,7 +3361,7 @@ 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{37} + return fileDescriptor_252557cfdd89a31a, []int{38} } func (m *ResponseProcessProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3371,7 +3433,7 @@ func (m *ResponseExtendVote) Reset() { *m = ResponseExtendVote{} } func (m *ResponseExtendVote) String() string { return proto.CompactTextString(m) } func (*ResponseExtendVote) ProtoMessage() {} func (*ResponseExtendVote) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{38} + return fileDescriptor_252557cfdd89a31a, []int{39} } func (m *ResponseExtendVote) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3415,7 +3477,7 @@ func (m *ResponseVerifyVoteExtension) Reset() { *m = ResponseVerifyVoteE func (m *ResponseVerifyVoteExtension) String() string { return proto.CompactTextString(m) } func (*ResponseVerifyVoteExtension) ProtoMessage() {} func (*ResponseVerifyVoteExtension) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{39} + return fileDescriptor_252557cfdd89a31a, []int{40} } func (m *ResponseVerifyVoteExtension) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3463,7 +3525,7 @@ func (m *ResponseFinalizeBlock) Reset() { *m = ResponseFinalizeBlock{} } func (m *ResponseFinalizeBlock) String() string { return proto.CompactTextString(m) } func (*ResponseFinalizeBlock) ProtoMessage() {} func (*ResponseFinalizeBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{40} + return fileDescriptor_252557cfdd89a31a, []int{41} } func (m *ResponseFinalizeBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3527,6 +3589,42 @@ func (m *ResponseFinalizeBlock) GetAppHash() []byte { return nil } +type ResponseLoadLatest struct { +} + +func (m *ResponseLoadLatest) Reset() { *m = ResponseLoadLatest{} } +func (m *ResponseLoadLatest) String() string { return proto.CompactTextString(m) } +func (*ResponseLoadLatest) ProtoMessage() {} +func (*ResponseLoadLatest) Descriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{42} +} +func (m *ResponseLoadLatest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseLoadLatest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseLoadLatest.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 *ResponseLoadLatest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseLoadLatest.Merge(m, src) +} +func (m *ResponseLoadLatest) XXX_Size() int { + return m.Size() +} +func (m *ResponseLoadLatest) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseLoadLatest.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseLoadLatest proto.InternalMessageInfo + 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"` @@ -3536,7 +3634,7 @@ 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{41} + return fileDescriptor_252557cfdd89a31a, []int{43} } func (m *CommitInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3588,7 +3686,7 @@ func (m *LastCommitInfo) Reset() { *m = LastCommitInfo{} } func (m *LastCommitInfo) String() string { return proto.CompactTextString(m) } func (*LastCommitInfo) ProtoMessage() {} func (*LastCommitInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{42} + return fileDescriptor_252557cfdd89a31a, []int{44} } func (m *LastCommitInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3646,7 +3744,7 @@ 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{43} + return fileDescriptor_252557cfdd89a31a, []int{45} } func (m *ExtendedCommitInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3701,7 +3799,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{44} + return fileDescriptor_252557cfdd89a31a, []int{46} } func (m *Event) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3755,7 +3853,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{45} + return fileDescriptor_252557cfdd89a31a, []int{47} } func (m *EventAttribute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3823,7 +3921,7 @@ func (m *ExecTxResult) Reset() { *m = ExecTxResult{} } func (m *ExecTxResult) String() string { return proto.CompactTextString(m) } func (*ExecTxResult) ProtoMessage() {} func (*ExecTxResult) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{46} + return fileDescriptor_252557cfdd89a31a, []int{48} } func (m *ExecTxResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3922,7 +4020,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{47} + return fileDescriptor_252557cfdd89a31a, []int{49} } func (m *TxResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3988,7 +4086,7 @@ func (m *TxRecord) Reset() { *m = TxRecord{} } func (m *TxRecord) String() string { return proto.CompactTextString(m) } func (*TxRecord) ProtoMessage() {} func (*TxRecord) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{48} + return fileDescriptor_252557cfdd89a31a, []int{50} } func (m *TxRecord) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4042,7 +4140,7 @@ func (m *BlockParams) Reset() { *m = BlockParams{} } func (m *BlockParams) String() string { return proto.CompactTextString(m) } func (*BlockParams) ProtoMessage() {} func (*BlockParams) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{49} + return fileDescriptor_252557cfdd89a31a, []int{51} } func (m *BlockParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4096,7 +4194,7 @@ func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } func (m *ConsensusParams) String() string { return proto.CompactTextString(m) } func (*ConsensusParams) ProtoMessage() {} func (*ConsensusParams) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{50} + return fileDescriptor_252557cfdd89a31a, []int{52} } func (m *ConsensusParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4164,7 +4262,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{51} + return fileDescriptor_252557cfdd89a31a, []int{53} } func (m *Validator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4217,7 +4315,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{52} + return fileDescriptor_252557cfdd89a31a, []int{54} } func (m *ValidatorUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4270,7 +4368,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{53} + return fileDescriptor_252557cfdd89a31a, []int{55} } func (m *VoteInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4327,7 +4425,7 @@ 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{54} + return fileDescriptor_252557cfdd89a31a, []int{56} } func (m *ExtendedVoteInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4395,7 +4493,7 @@ 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{55} + return fileDescriptor_252557cfdd89a31a, []int{57} } func (m *Misbehavior) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4477,7 +4575,7 @@ 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{56} + return fileDescriptor_252557cfdd89a31a, []int{58} } func (m *Evidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4553,7 +4651,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{57} + return fileDescriptor_252557cfdd89a31a, []int{59} } func (m *Snapshot) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4645,6 +4743,7 @@ func init() { proto.RegisterType((*RequestBeginBlock)(nil), "tendermint.abci.RequestBeginBlock") proto.RegisterType((*RequestDeliverTx)(nil), "tendermint.abci.RequestDeliverTx") proto.RegisterType((*RequestEndBlock)(nil), "tendermint.abci.RequestEndBlock") + proto.RegisterType((*RequestLoadLatest)(nil), "tendermint.abci.RequestLoadLatest") proto.RegisterType((*Response)(nil), "tendermint.abci.Response") proto.RegisterType((*ResponseException)(nil), "tendermint.abci.ResponseException") proto.RegisterType((*ResponseEcho)(nil), "tendermint.abci.ResponseEcho") @@ -4666,6 +4765,7 @@ func init() { proto.RegisterType((*ResponseExtendVote)(nil), "tendermint.abci.ResponseExtendVote") proto.RegisterType((*ResponseVerifyVoteExtension)(nil), "tendermint.abci.ResponseVerifyVoteExtension") proto.RegisterType((*ResponseFinalizeBlock)(nil), "tendermint.abci.ResponseFinalizeBlock") + proto.RegisterType((*ResponseLoadLatest)(nil), "tendermint.abci.ResponseLoadLatest") proto.RegisterType((*CommitInfo)(nil), "tendermint.abci.CommitInfo") proto.RegisterType((*LastCommitInfo)(nil), "tendermint.abci.LastCommitInfo") proto.RegisterType((*ExtendedCommitInfo)(nil), "tendermint.abci.ExtendedCommitInfo") @@ -4688,246 +4788,250 @@ func init() { func init() { proto.RegisterFile("tendermint/abci/types.proto", fileDescriptor_252557cfdd89a31a) } var fileDescriptor_252557cfdd89a31a = []byte{ - // 3821 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0xcd, 0x73, 0x1b, 0x57, - 0x72, 0xc7, 0xe0, 0x1b, 0x8d, 0xaf, 0xe1, 0x23, 0x45, 0x41, 0x90, 0x4d, 0xd2, 0xe3, 0x92, 0x2d, - 0xcb, 0x5e, 0x72, 0x43, 0xc7, 0x5a, 0x29, 0xf2, 0x46, 0x21, 0x41, 0x70, 0x41, 0x89, 0x22, 0xe9, - 0x21, 0x48, 0xc7, 0x49, 0x56, 0xb3, 0x43, 0xe0, 0x11, 0x98, 0x15, 0x80, 0x99, 0x9d, 0x19, 0xd0, - 0xa0, 0x4f, 0xa9, 0x24, 0xbe, 0x6c, 0x2e, 0xbe, 0x25, 0x87, 0xec, 0x2d, 0xa9, 0xca, 0x39, 0x87, - 0x54, 0x4e, 0x39, 0xa5, 0x52, 0x7b, 0xc8, 0x61, 0x0f, 0xa9, 0x54, 0x2e, 0xd9, 0xa4, 0xec, 0xdb, - 0xfe, 0x03, 0xb9, 0x25, 0xa9, 0xf7, 0x31, 0x5f, 0xc0, 0x0c, 0x3e, 0x24, 0xd5, 0x56, 0x6d, 0xc5, - 0xb7, 0x79, 0x3d, 0xdd, 0xfd, 0xbe, 0xfa, 0x75, 0xf7, 0xfb, 0xf5, 0x0c, 0xdc, 0xb6, 0xf1, 0xa0, - 0x8d, 0xcd, 0xbe, 0x36, 0xb0, 0xb7, 0xd4, 0x8b, 0x96, 0xb6, 0x65, 0x5f, 0x1b, 0xd8, 0xda, 0x34, - 0x4c, 0xdd, 0xd6, 0x51, 0xd9, 0x7b, 0xb9, 0x49, 0x5e, 0x56, 0xdf, 0xf4, 0x71, 0xb7, 0xcc, 0x6b, - 0xc3, 0xd6, 0xb7, 0x0c, 0x53, 0xd7, 0x2f, 0x19, 0x7f, 0xf5, 0x8d, 0xc9, 0xd7, 0x2f, 0xf0, 0x35, - 0xd7, 0x16, 0x10, 0xa6, 0xbd, 0x6c, 0x19, 0xaa, 0xa9, 0xf6, 0xad, 0x10, 0x61, 0xf6, 0xda, 0x37, - 0x94, 0xea, 0x7a, 0x47, 0xd7, 0x3b, 0x3d, 0xbc, 0x45, 0x5b, 0x17, 0xc3, 0xcb, 0x2d, 0x5b, 0xeb, - 0x63, 0xcb, 0x56, 0xfb, 0x06, 0x67, 0x58, 0xe9, 0xe8, 0x1d, 0x9d, 0x3e, 0x6e, 0x91, 0x27, 0x46, - 0x95, 0xbe, 0xcc, 0x43, 0x46, 0xc6, 0x3f, 0x19, 0x62, 0xcb, 0x46, 0xdb, 0x90, 0xc4, 0xad, 0xae, - 0x5e, 0x11, 0x36, 0x84, 0xbb, 0xf9, 0xed, 0x37, 0x36, 0xc7, 0x26, 0xb7, 0xc9, 0xf9, 0xea, 0xad, - 0xae, 0xde, 0x88, 0xc9, 0x94, 0x17, 0x7d, 0x04, 0xa9, 0xcb, 0xde, 0xd0, 0xea, 0x56, 0xe2, 0x54, - 0xe8, 0xcd, 0x28, 0xa1, 0x7d, 0xc2, 0xd4, 0x88, 0xc9, 0x8c, 0x9b, 0x74, 0xa5, 0x0d, 0x2e, 0xf5, - 0x4a, 0x62, 0x7a, 0x57, 0x07, 0x83, 0x4b, 0xda, 0x15, 0xe1, 0x45, 0xbb, 0x00, 0xda, 0x40, 0xb3, - 0x95, 0x56, 0x57, 0xd5, 0x06, 0x95, 0x24, 0x95, 0x7c, 0x2b, 0x5a, 0x52, 0xb3, 0x6b, 0x84, 0xb1, - 0x11, 0x93, 0x73, 0x9a, 0xd3, 0x20, 0xc3, 0xfd, 0xc9, 0x10, 0x9b, 0xd7, 0x95, 0xd4, 0xf4, 0xe1, - 0x7e, 0x42, 0x98, 0xc8, 0x70, 0x29, 0x37, 0xfa, 0x18, 0xb2, 0xad, 0x2e, 0x6e, 0xbd, 0x50, 0xec, - 0x51, 0x25, 0x43, 0x25, 0xd7, 0xa3, 0x24, 0x6b, 0x84, 0xaf, 0x39, 0x6a, 0xc4, 0xe4, 0x4c, 0x8b, - 0x3d, 0xa2, 0x07, 0x90, 0x6e, 0xe9, 0xfd, 0xbe, 0x66, 0x57, 0x80, 0xca, 0xae, 0x45, 0xca, 0x52, - 0xae, 0x46, 0x4c, 0xe6, 0xfc, 0xe8, 0x08, 0x4a, 0x3d, 0xcd, 0xb2, 0x15, 0x6b, 0xa0, 0x1a, 0x56, - 0x57, 0xb7, 0xad, 0x4a, 0x9e, 0x6a, 0xb8, 0x13, 0xa5, 0xe1, 0x50, 0xb3, 0xec, 0x53, 0x87, 0xb9, - 0x11, 0x93, 0x8b, 0x3d, 0x3f, 0x81, 0xe8, 0xd3, 0x2f, 0x2f, 0xb1, 0xe9, 0x2a, 0xac, 0x14, 0xa6, - 0xeb, 0x3b, 0x26, 0xdc, 0x8e, 0x3c, 0xd1, 0xa7, 0xfb, 0x09, 0xe8, 0x0f, 0x61, 0xb9, 0xa7, 0xab, - 0x6d, 0x57, 0x9d, 0xd2, 0xea, 0x0e, 0x07, 0x2f, 0x2a, 0x45, 0xaa, 0xf4, 0xbd, 0xc8, 0x41, 0xea, - 0x6a, 0xdb, 0x51, 0x51, 0x23, 0x02, 0x8d, 0x98, 0xbc, 0xd4, 0x1b, 0x27, 0xa2, 0xe7, 0xb0, 0xa2, - 0x1a, 0x46, 0xef, 0x7a, 0x5c, 0x7b, 0x89, 0x6a, 0xbf, 0x17, 0xa5, 0x7d, 0x87, 0xc8, 0x8c, 0xab, - 0x47, 0xea, 0x04, 0x15, 0x35, 0x41, 0x34, 0x4c, 0x6c, 0xa8, 0x26, 0x56, 0x0c, 0x53, 0x37, 0x74, - 0x4b, 0xed, 0x55, 0xca, 0x54, 0xf7, 0xbb, 0x51, 0xba, 0x4f, 0x18, 0xff, 0x09, 0x67, 0x6f, 0xc4, - 0xe4, 0xb2, 0x11, 0x24, 0x31, 0xad, 0x7a, 0x0b, 0x5b, 0x96, 0xa7, 0x55, 0x9c, 0xa5, 0x95, 0xf2, - 0x07, 0xb5, 0x06, 0x48, 0xa8, 0x0e, 0x79, 0x3c, 0x22, 0xe2, 0xca, 0x95, 0x6e, 0xe3, 0xca, 0x12, - 0x55, 0x28, 0x45, 0x9e, 0x50, 0xca, 0x7a, 0xae, 0xdb, 0xb8, 0x11, 0x93, 0x01, 0xbb, 0x2d, 0xa4, - 0xc2, 0x8d, 0x2b, 0x6c, 0x6a, 0x97, 0xd7, 0x54, 0x8d, 0x42, 0xdf, 0x58, 0x9a, 0x3e, 0xa8, 0x20, - 0xaa, 0xf0, 0xfd, 0x28, 0x85, 0xe7, 0x54, 0x88, 0xa8, 0xa8, 0x3b, 0x22, 0x8d, 0x98, 0xbc, 0x7c, - 0x35, 0x49, 0x26, 0x26, 0x76, 0xa9, 0x0d, 0xd4, 0x9e, 0xf6, 0x05, 0x56, 0x2e, 0x7a, 0x7a, 0xeb, - 0x45, 0x65, 0x79, 0xba, 0x89, 0xed, 0x73, 0xee, 0x5d, 0xc2, 0x4c, 0x4c, 0xec, 0xd2, 0x4f, 0x20, - 0x33, 0xbf, 0xc0, 0x1d, 0x6d, 0xc0, 0x95, 0xad, 0x4c, 0x9f, 0xf9, 0x2e, 0x61, 0x75, 0x34, 0xc1, - 0x85, 0xdb, 0x22, 0xce, 0xa3, 0x8d, 0x7b, 0xda, 0x15, 0x36, 0xc9, 0x19, 0xbe, 0x31, 0xdd, 0x79, - 0xec, 0x31, 0x4e, 0x7a, 0x8a, 0x73, 0x6d, 0xa7, 0x81, 0x1e, 0x43, 0x8e, 0xec, 0x00, 0x1b, 0xc8, - 0x2a, 0x55, 0xb1, 0x11, 0xb9, 0x05, 0x83, 0xb6, 0x33, 0x8c, 0x2c, 0xe6, 0xcf, 0xbb, 0x19, 0x48, - 0x5d, 0xa9, 0xbd, 0x21, 0x7e, 0x92, 0xcc, 0xa6, 0xc5, 0xcc, 0x93, 0x64, 0x36, 0x2b, 0xe6, 0x9e, - 0x24, 0xb3, 0x39, 0x11, 0xa4, 0x77, 0x21, 0xef, 0x73, 0xaf, 0xa8, 0x02, 0x99, 0x3e, 0xb6, 0x2c, - 0xb5, 0x83, 0xa9, 0x37, 0xce, 0xc9, 0x4e, 0x53, 0x2a, 0x41, 0xc1, 0xef, 0x52, 0xa5, 0xaf, 0x04, - 0x57, 0x92, 0x78, 0x4b, 0x22, 0x79, 0x85, 0x4d, 0xba, 0xa9, 0x5c, 0x92, 0x37, 0xd1, 0xdb, 0x50, - 0xa4, 0x43, 0x57, 0x9c, 0xf7, 0xc4, 0x65, 0x27, 0xe5, 0x02, 0x25, 0x9e, 0x73, 0xa6, 0x75, 0xc8, - 0x1b, 0xdb, 0x86, 0xcb, 0x92, 0xa0, 0x2c, 0x60, 0x6c, 0x1b, 0x0e, 0xc3, 0x5b, 0x50, 0x20, 0xf3, - 0x74, 0x39, 0x92, 0xb4, 0x93, 0x3c, 0xa1, 0x71, 0x16, 0xe9, 0x5f, 0xe2, 0x20, 0x8e, 0xbb, 0x61, - 0xf4, 0x00, 0x92, 0x24, 0x22, 0xf1, 0xe0, 0x52, 0xdd, 0x64, 0xe1, 0x6a, 0xd3, 0x09, 0x57, 0x9b, - 0x4d, 0x27, 0x5c, 0xed, 0x66, 0x7f, 0xfe, 0xcb, 0xf5, 0xd8, 0x57, 0xff, 0xb9, 0x2e, 0xc8, 0x54, - 0x02, 0xdd, 0x22, 0xce, 0x57, 0xd5, 0x06, 0x8a, 0xd6, 0xa6, 0x43, 0xce, 0x11, 0xcf, 0xaa, 0x6a, - 0x83, 0x83, 0x36, 0x3a, 0x04, 0xb1, 0xa5, 0x0f, 0x2c, 0x3c, 0xb0, 0x86, 0x96, 0xc2, 0x82, 0x25, - 0x0f, 0x29, 0x81, 0xbd, 0x65, 0x71, 0xb2, 0xe6, 0x70, 0x9e, 0x50, 0x46, 0xb9, 0xdc, 0x0a, 0x12, - 0xd0, 0x3e, 0xc0, 0x95, 0xda, 0xd3, 0xda, 0xaa, 0xad, 0x9b, 0x56, 0x25, 0xb9, 0x91, 0x08, 0xdd, - 0xe0, 0x73, 0x87, 0xe5, 0xcc, 0x68, 0xab, 0x36, 0xde, 0x4d, 0x92, 0xe1, 0xca, 0x3e, 0x49, 0xf4, - 0x0e, 0x94, 0x55, 0xc3, 0x50, 0x2c, 0x5b, 0xb5, 0xb1, 0x72, 0x71, 0x6d, 0x63, 0x8b, 0x86, 0x9b, - 0x82, 0x5c, 0x54, 0x0d, 0xe3, 0x94, 0x50, 0x77, 0x09, 0x11, 0xdd, 0x81, 0x12, 0x89, 0x4c, 0x9a, - 0xda, 0x53, 0xba, 0x58, 0xeb, 0x74, 0xed, 0x4a, 0x7a, 0x43, 0xb8, 0x9b, 0x90, 0x8b, 0x9c, 0xda, - 0xa0, 0x44, 0xa9, 0xed, 0xee, 0x38, 0x8d, 0x4a, 0x08, 0x41, 0xb2, 0xad, 0xda, 0x2a, 0x5d, 0xc9, - 0x82, 0x4c, 0x9f, 0x09, 0xcd, 0x50, 0xed, 0x2e, 0x5f, 0x1f, 0xfa, 0x8c, 0x56, 0x21, 0xcd, 0xd5, - 0x26, 0xa8, 0x5a, 0xde, 0x42, 0x2b, 0x90, 0x32, 0x4c, 0xfd, 0x0a, 0xd3, 0xad, 0xcb, 0xca, 0xac, - 0x21, 0xc9, 0x50, 0x0a, 0x46, 0x30, 0x54, 0x82, 0xb8, 0x3d, 0xe2, 0xbd, 0xc4, 0xed, 0x11, 0xfa, - 0x2e, 0x24, 0xc9, 0x42, 0xd2, 0x3e, 0x4a, 0x21, 0x31, 0x9b, 0xcb, 0x35, 0xaf, 0x0d, 0x2c, 0x53, - 0x4e, 0xa9, 0x0c, 0xc5, 0x40, 0x64, 0x93, 0x56, 0x61, 0x25, 0x2c, 0x50, 0x49, 0x5d, 0x97, 0x1e, - 0x08, 0x38, 0xe8, 0x23, 0xc8, 0xba, 0x91, 0x8a, 0x19, 0xce, 0xad, 0x89, 0x6e, 0x1d, 0x66, 0xd9, - 0x65, 0x25, 0x16, 0x43, 0x36, 0xa0, 0xab, 0xf2, 0xbc, 0xa4, 0x20, 0x67, 0x54, 0xc3, 0x68, 0xa8, - 0x56, 0x57, 0xfa, 0x11, 0x54, 0xa2, 0xa2, 0x90, 0x6f, 0xc1, 0x04, 0x6a, 0xf6, 0xce, 0x82, 0xad, - 0x42, 0xfa, 0x52, 0x37, 0xfb, 0xaa, 0x4d, 0x95, 0x15, 0x65, 0xde, 0x22, 0x0b, 0xc9, 0x22, 0x52, - 0x82, 0x92, 0x59, 0x43, 0x52, 0xe0, 0x56, 0x64, 0x24, 0x22, 0x22, 0xda, 0xa0, 0x8d, 0xd9, 0xb2, - 0x16, 0x65, 0xd6, 0xf0, 0x14, 0xb1, 0xc1, 0xb2, 0x06, 0xe9, 0xd6, 0xa2, 0x73, 0xa5, 0xfa, 0x73, - 0x32, 0x6f, 0x49, 0xff, 0x9c, 0x86, 0xd5, 0xf0, 0x78, 0x84, 0x36, 0xa0, 0xd0, 0x57, 0x47, 0x8a, - 0x3d, 0xe2, 0x66, 0x27, 0xd0, 0x8d, 0x87, 0xbe, 0x3a, 0x6a, 0x8e, 0x98, 0xcd, 0x89, 0x90, 0xb0, - 0x47, 0x56, 0x25, 0xbe, 0x91, 0xb8, 0x5b, 0x90, 0xc9, 0x23, 0x3a, 0x83, 0xa5, 0x9e, 0xde, 0x52, - 0x7b, 0x4a, 0x4f, 0xb5, 0x6c, 0x85, 0x27, 0x2a, 0xec, 0x10, 0xbd, 0x3d, 0xb1, 0xd8, 0x2c, 0xb2, - 0xe0, 0x36, 0xdb, 0x4f, 0xe2, 0x70, 0xb8, 0xfd, 0x97, 0xa9, 0x8e, 0x43, 0xd5, 0xd9, 0x6a, 0x74, - 0x06, 0x2b, 0x17, 0xd7, 0x5f, 0xa8, 0x03, 0x5b, 0x1b, 0x60, 0x65, 0xe2, 0x58, 0x4d, 0x5a, 0xcf, - 0x33, 0xcd, 0xba, 0xc0, 0x5d, 0xf5, 0x4a, 0xd3, 0x4d, 0xae, 0x72, 0xd9, 0x95, 0x3f, 0xf7, 0xce, - 0x96, 0xb7, 0x47, 0xa9, 0x80, 0x51, 0x3b, 0xee, 0x25, 0xbd, 0xb0, 0x7b, 0xf9, 0x2e, 0xac, 0x0c, - 0xf0, 0xc8, 0xf6, 0x8d, 0x91, 0x19, 0x4e, 0x86, 0xee, 0x05, 0x22, 0xef, 0xbc, 0xfe, 0x89, 0x0d, - 0xa1, 0xf7, 0x68, 0x88, 0x37, 0x74, 0x0b, 0x9b, 0x8a, 0xda, 0x6e, 0x9b, 0xd8, 0xb2, 0x2a, 0x59, - 0xca, 0x5d, 0x76, 0xe8, 0x3b, 0x8c, 0x1c, 0xb0, 0xc4, 0x5c, 0xc0, 0x12, 0xd1, 0xbb, 0x50, 0x1e, - 0xef, 0x12, 0x28, 0x47, 0xe9, 0x2a, 0xd8, 0xdd, 0x1d, 0x28, 0x79, 0x4e, 0x8e, 0xf2, 0xe5, 0x99, - 0x37, 0x71, 0xa9, 0x94, 0xed, 0x36, 0xe4, 0x88, 0x2b, 0x60, 0x1c, 0x05, 0xca, 0x91, 0x25, 0x04, - 0xfa, 0xf2, 0x6d, 0x28, 0xe2, 0x2b, 0xad, 0x8d, 0x07, 0x2d, 0xcc, 0x18, 0x8a, 0x94, 0xa1, 0xe0, - 0x10, 0x29, 0xd3, 0x3b, 0x50, 0xa6, 0x36, 0xc0, 0xa2, 0x04, 0x65, 0x2b, 0xb1, 0x9e, 0x08, 0x99, - 0x85, 0x33, 0xc2, 0xf7, 0x00, 0x6e, 0xf9, 0xf8, 0x0c, 0xd5, 0xb4, 0x15, 0x0b, 0xdb, 0x8a, 0xad, - 0xdb, 0x3c, 0x83, 0x4a, 0xc8, 0x37, 0x5c, 0x89, 0x13, 0xd5, 0xb4, 0x4f, 0xb1, 0xdd, 0x24, 0x2f, - 0xd1, 0x7d, 0xa8, 0x84, 0x49, 0xd2, 0xae, 0x44, 0xda, 0xd5, 0xca, 0xb8, 0x20, 0xed, 0xf1, 0x2e, - 0x88, 0x3e, 0xeb, 0x64, 0xfc, 0x4b, 0x6c, 0xb1, 0x7a, 0xae, 0xc9, 0x51, 0xce, 0x7b, 0xb0, 0x44, - 0x39, 0x4d, 0x6c, 0x0d, 0x7b, 0x36, 0x5f, 0x2f, 0xc4, 0x36, 0x87, 0xbc, 0x90, 0x19, 0x9d, 0xfa, - 0x82, 0xbf, 0xf7, 0x1f, 0xa4, 0x60, 0xbe, 0xc5, 0x8f, 0x89, 0xe0, 0x1d, 0x93, 0x53, 0x58, 0xe1, - 0x9b, 0xdb, 0x0e, 0x9c, 0x14, 0x76, 0xef, 0xb9, 0x3d, 0xe9, 0x0d, 0xc7, 0x4f, 0x08, 0x72, 0xc4, - 0xe7, 0x38, 0x24, 0x89, 0x57, 0x3b, 0x24, 0x08, 0x92, 0x74, 0xde, 0x49, 0x16, 0x21, 0xc8, 0xf3, - 0x6f, 0xf2, 0xc1, 0x81, 0x99, 0x07, 0x27, 0x3f, 0xe7, 0xc1, 0x29, 0xcc, 0x3c, 0x38, 0xc5, 0x59, - 0x07, 0xa7, 0x34, 0xdf, 0xc1, 0x29, 0x2f, 0x7c, 0x70, 0xc4, 0x97, 0x3d, 0x38, 0x4b, 0x0b, 0x1e, - 0x1c, 0x34, 0xff, 0xc1, 0x59, 0x0e, 0x3f, 0x38, 0x8f, 0x61, 0x69, 0xe2, 0xa6, 0xe1, 0x1a, 0x9d, - 0x10, 0x6a, 0x74, 0x71, 0xbf, 0xd1, 0x49, 0x7f, 0x25, 0x40, 0x35, 0xfa, 0x6a, 0x11, 0xaa, 0xea, - 0x7d, 0x58, 0x72, 0xb7, 0xd7, 0x35, 0x1e, 0x16, 0x2f, 0x45, 0xf7, 0x85, 0x63, 0x3d, 0x51, 0xa9, - 0xcf, 0x1d, 0x28, 0x8d, 0x5d, 0x7c, 0xd8, 0x11, 0x29, 0x5e, 0xf9, 0xfb, 0x97, 0xfe, 0x2e, 0xed, - 0xe6, 0x23, 0x81, 0xdb, 0x49, 0x88, 0x5b, 0xf8, 0x04, 0x96, 0xdb, 0xb8, 0xa5, 0xb5, 0x5f, 0xd6, - 0x2b, 0x2c, 0x71, 0xe9, 0x6f, 0x9d, 0xc2, 0xb7, 0x4e, 0xe1, 0x37, 0xdb, 0x29, 0xfc, 0x59, 0xdc, - 0xf5, 0x0a, 0xde, 0x2d, 0x3c, 0xf4, 0x28, 0xdf, 0x27, 0x56, 0xa7, 0x92, 0xc4, 0x96, 0x1d, 0x93, - 0xca, 0xe4, 0x5d, 0xad, 0x41, 0xdf, 0x73, 0x73, 0xe6, 0xdc, 0xe8, 0x38, 0x38, 0x6e, 0x1f, 0x80, - 0x38, 0x89, 0xc6, 0x79, 0xe7, 0xc9, 0x77, 0xd8, 0x7c, 0xd3, 0xa3, 0x77, 0x65, 0x79, 0x6a, 0x8e, - 0x3a, 0x79, 0xd5, 0xa8, 0xf3, 0xfd, 0x9d, 0x72, 0xcc, 0xa4, 0xba, 0x7b, 0xf7, 0x75, 0x51, 0x84, - 0x89, 0x9b, 0xd4, 0x5b, 0x50, 0xb0, 0xb4, 0x8e, 0x42, 0xe1, 0x13, 0x0d, 0xb3, 0x5b, 0x6d, 0x56, - 0xce, 0x5b, 0x5a, 0xe7, 0x9c, 0x93, 0xa4, 0xf7, 0xa0, 0x3c, 0x86, 0x24, 0x8c, 0x5d, 0x4f, 0x3c, - 0x67, 0xfa, 0x1f, 0x79, 0xc8, 0xca, 0xd8, 0x32, 0x88, 0xfd, 0xa2, 0x5d, 0xc8, 0xe1, 0x51, 0x0b, - 0x1b, 0xb6, 0x03, 0x00, 0x84, 0x83, 0x25, 0x8c, 0xbb, 0xee, 0x70, 0x36, 0x62, 0xb2, 0x27, 0x86, - 0x3e, 0xe4, 0x38, 0x70, 0x34, 0xa4, 0xcb, 0xc5, 0xfd, 0x40, 0xf0, 0x7d, 0x07, 0x08, 0x4e, 0x44, - 0x62, 0x9c, 0x4c, 0x6a, 0x0c, 0x09, 0xfe, 0x90, 0x23, 0xc1, 0xc9, 0x19, 0x9d, 0x05, 0xa0, 0xe0, - 0x5a, 0x00, 0x0a, 0x4e, 0xcd, 0x98, 0x66, 0x04, 0x16, 0x7c, 0xdf, 0xc1, 0x82, 0xd3, 0x33, 0x46, - 0x3c, 0x06, 0x06, 0x7f, 0xdf, 0x07, 0x06, 0x67, 0x23, 0x51, 0x20, 0x26, 0x1a, 0x82, 0x06, 0x3f, - 0x74, 0xd1, 0xe0, 0x7c, 0x24, 0x92, 0xcc, 0x85, 0xc7, 0xe1, 0xe0, 0xe3, 0x09, 0x38, 0x98, 0xc1, - 0xb7, 0xef, 0x44, 0xaa, 0x98, 0x81, 0x07, 0x1f, 0x4f, 0xe0, 0xc1, 0xc5, 0x19, 0x0a, 0x67, 0x00, - 0xc2, 0x7f, 0x14, 0x0e, 0x08, 0x47, 0x43, 0xb6, 0x7c, 0x98, 0xf3, 0x21, 0xc2, 0x4a, 0x04, 0x22, - 0x5c, 0x8e, 0x44, 0x2f, 0x99, 0xfa, 0xb9, 0x21, 0xe1, 0xb3, 0x10, 0x48, 0x98, 0x81, 0xb7, 0x77, - 0x23, 0x95, 0xcf, 0x81, 0x09, 0x9f, 0x85, 0x60, 0xc2, 0x4b, 0x33, 0xd5, 0xce, 0x04, 0x85, 0xf7, - 0x83, 0xa0, 0x30, 0x8a, 0xb8, 0xb3, 0x7b, 0xa7, 0x3d, 0x02, 0x15, 0xbe, 0x88, 0x42, 0x85, 0x19, - 0x72, 0xfb, 0x41, 0xa4, 0xc6, 0x05, 0x60, 0xe1, 0xe3, 0x09, 0x58, 0x78, 0x65, 0x86, 0xa5, 0xcd, - 0xc0, 0x85, 0xf7, 0x83, 0xb8, 0xf0, 0x8d, 0x19, 0x93, 0x8f, 0x04, 0x86, 0x6b, 0x01, 0x60, 0x78, - 0x75, 0x86, 0x2b, 0x89, 0x40, 0x86, 0x7f, 0xcf, 0x8f, 0x0c, 0xdf, 0x8c, 0x04, 0x97, 0xf9, 0x3e, - 0xcc, 0x80, 0x86, 0x33, 0x62, 0x96, 0x81, 0xc2, 0x4f, 0x92, 0x59, 0x10, 0xf3, 0xd2, 0x7b, 0x24, - 0xae, 0x8e, 0x39, 0x6c, 0xb4, 0x02, 0x29, 0x6c, 0x9a, 0xba, 0xc9, 0x41, 0x5e, 0xd6, 0x90, 0xee, - 0x42, 0xc1, 0xef, 0x9c, 0xa7, 0xc0, 0xc8, 0x14, 0x9a, 0xf3, 0x39, 0x64, 0xe9, 0x1f, 0x04, 0x4f, - 0x96, 0x06, 0x47, 0x3f, 0xcc, 0x98, 0xe3, 0x30, 0xa3, 0x0f, 0x5c, 0x8e, 0x07, 0xc1, 0xe5, 0x75, - 0xc8, 0x93, 0xd4, 0x6c, 0x0c, 0x37, 0x56, 0x0d, 0x17, 0x37, 0x76, 0x52, 0x09, 0x9e, 0x0e, 0xb1, - 0x40, 0x96, 0xa4, 0x81, 0xac, 0xec, 0x25, 0x44, 0x2c, 0xfd, 0xfc, 0x0e, 0x2c, 0xfb, 0x78, 0xdd, - 0x94, 0x8f, 0x81, 0xa8, 0xa2, 0xcb, 0xbd, 0xc3, 0x31, 0xbd, 0x7f, 0x12, 0xbc, 0x15, 0xf2, 0x00, - 0xe7, 0x30, 0x6c, 0x58, 0x78, 0x4d, 0xd8, 0x70, 0xfc, 0xa5, 0xb1, 0x61, 0x7f, 0x0a, 0x9b, 0x08, - 0x42, 0x93, 0xff, 0x2d, 0x78, 0x7b, 0xe2, 0x22, 0xbd, 0x2d, 0xbd, 0x8d, 0x39, 0x58, 0x48, 0x9f, - 0xc9, 0x15, 0xa4, 0xa7, 0x77, 0x38, 0x24, 0x48, 0x1e, 0x09, 0x97, 0x1b, 0x41, 0x73, 0x3c, 0x40, - 0xba, 0x38, 0x23, 0xcb, 0xeb, 0x39, 0xce, 0x28, 0x42, 0xe2, 0x05, 0x66, 0xf1, 0xae, 0x20, 0x93, - 0x47, 0xc2, 0x47, 0xcd, 0x8e, 0xe7, 0xe7, 0xac, 0x81, 0x1e, 0x40, 0x8e, 0x56, 0xad, 0x15, 0xdd, - 0xb0, 0x78, 0x88, 0x0b, 0x5c, 0x65, 0x58, 0xe9, 0x7a, 0xf3, 0x84, 0xf0, 0x1c, 0x1b, 0x96, 0x9c, - 0x35, 0xf8, 0x93, 0x2f, 0x47, 0xc9, 0x05, 0x2e, 0x14, 0x6f, 0x40, 0x8e, 0x8c, 0xde, 0x32, 0xd4, - 0x16, 0xa6, 0xa9, 0x7b, 0x4e, 0xf6, 0x08, 0xd2, 0x73, 0x40, 0x93, 0xe7, 0x14, 0x35, 0x20, 0x8d, - 0xaf, 0xf0, 0xc0, 0x66, 0xf7, 0xad, 0xfc, 0xf6, 0x6a, 0x48, 0x3e, 0x86, 0x07, 0xf6, 0x6e, 0x85, - 0x2c, 0xf2, 0xaf, 0x7e, 0xb9, 0x2e, 0x32, 0xee, 0x0f, 0xf4, 0xbe, 0x66, 0xe3, 0xbe, 0x61, 0x5f, - 0xcb, 0x5c, 0x5e, 0xfa, 0x57, 0x81, 0x64, 0x53, 0x81, 0x88, 0x1c, 0xba, 0xb6, 0x8e, 0xc9, 0xc7, - 0x7d, 0xc8, 0xfa, 0xe4, 0x7a, 0xbf, 0x09, 0xd0, 0x51, 0x2d, 0xe5, 0x73, 0x75, 0x60, 0xe3, 0x36, - 0x5f, 0xe0, 0x5c, 0x47, 0xb5, 0x3e, 0xa5, 0x84, 0xe0, 0x54, 0xb3, 0x63, 0x53, 0xf5, 0x81, 0xba, - 0x39, 0x3f, 0xa8, 0x8b, 0xaa, 0x90, 0x35, 0x4c, 0x4d, 0x37, 0x35, 0xfb, 0x9a, 0xae, 0x4f, 0x42, - 0x76, 0xdb, 0x4f, 0x92, 0xd9, 0xa4, 0x98, 0x72, 0x6b, 0x46, 0xcc, 0x3d, 0xe4, 0xc5, 0x82, 0xf4, - 0x65, 0xdc, 0xb3, 0x7b, 0x2f, 0xd9, 0x7c, 0xf9, 0x89, 0x85, 0x19, 0xd2, 0x5a, 0xc8, 0x64, 0x7d, - 0x14, 0x32, 0x6e, 0xd2, 0x1a, 0x5a, 0xb8, 0xcd, 0xab, 0x17, 0x6e, 0xdb, 0xb7, 0x81, 0x99, 0x57, - 0xdb, 0xc0, 0xe9, 0x6b, 0x2a, 0xfd, 0x39, 0xad, 0x37, 0x05, 0x9d, 0x2b, 0x3a, 0xf5, 0xe3, 0x05, - 0x43, 0x7a, 0x1c, 0x1d, 0x43, 0x9a, 0xf7, 0xdc, 0x7a, 0xb8, 0x02, 0x23, 0x5b, 0xe8, 0xf7, 0xe1, - 0xe6, 0x98, 0x4f, 0x71, 0x55, 0xc7, 0x23, 0x32, 0xc1, 0x71, 0xcf, 0x72, 0x23, 0xe8, 0x59, 0x1c, - 0xcd, 0xde, 0x5a, 0x25, 0x5e, 0xd1, 0xd8, 0x3f, 0x82, 0x52, 0x30, 0x81, 0x24, 0xd7, 0x55, 0x13, - 0xdb, 0xaa, 0x36, 0x50, 0x02, 0xa0, 0x48, 0x81, 0x11, 0x79, 0x95, 0xe9, 0x04, 0x6e, 0x84, 0x26, - 0x8d, 0xe8, 0x7b, 0x90, 0xf3, 0xf2, 0x4d, 0x21, 0xe2, 0x66, 0xe4, 0x16, 0x61, 0x3c, 0x5e, 0xe9, - 0x1f, 0x05, 0x4f, 0x65, 0xb0, 0xac, 0x53, 0x87, 0x34, 0xbb, 0x51, 0x52, 0x23, 0x2d, 0x6d, 0x7f, - 0x67, 0xbe, 0x74, 0x73, 0x93, 0x5d, 0x37, 0x65, 0x2e, 0x2c, 0x3d, 0x87, 0x34, 0xa3, 0xa0, 0x3c, - 0x64, 0xce, 0x8e, 0x9e, 0x1e, 0x1d, 0x7f, 0x7a, 0x24, 0xc6, 0x10, 0x40, 0x7a, 0xa7, 0x56, 0xab, - 0x9f, 0x34, 0x45, 0x01, 0xe5, 0x20, 0xb5, 0xb3, 0x7b, 0x2c, 0x37, 0xc5, 0x38, 0x21, 0xcb, 0xf5, - 0x27, 0xf5, 0x5a, 0x53, 0x4c, 0xa0, 0x25, 0x28, 0xb2, 0x67, 0x65, 0xff, 0x58, 0x7e, 0xb6, 0xd3, - 0x14, 0x93, 0x3e, 0xd2, 0x69, 0xfd, 0x68, 0xaf, 0x2e, 0x8b, 0x29, 0xe9, 0xb7, 0xe0, 0x56, 0x64, - 0x82, 0xea, 0xd5, 0x6c, 0x04, 0x5f, 0xcd, 0x46, 0xfa, 0xcb, 0x38, 0x54, 0xa3, 0xb3, 0x4e, 0xf4, - 0x64, 0x6c, 0xe2, 0xdb, 0x0b, 0xa4, 0xac, 0x63, 0xb3, 0x47, 0x77, 0xa0, 0x64, 0xe2, 0x4b, 0x6c, - 0xb7, 0xba, 0x2c, 0x0b, 0x66, 0x51, 0xa9, 0x28, 0x17, 0x39, 0x95, 0x0a, 0x59, 0x8c, 0xed, 0xc7, - 0xb8, 0x65, 0x2b, 0xcc, 0xd3, 0x30, 0x03, 0xcb, 0x11, 0x36, 0x42, 0x3d, 0x65, 0x44, 0xe9, 0x47, - 0x0b, 0xad, 0x65, 0x0e, 0x52, 0x72, 0xbd, 0x29, 0x7f, 0x26, 0x26, 0x10, 0x82, 0x12, 0x7d, 0x54, - 0x4e, 0x8f, 0x76, 0x4e, 0x4e, 0x1b, 0xc7, 0x64, 0x2d, 0x97, 0xa1, 0xec, 0xac, 0xa5, 0x43, 0x4c, - 0x49, 0xff, 0x16, 0x87, 0x9b, 0x11, 0x39, 0x33, 0x7a, 0x00, 0x60, 0x8f, 0x14, 0x13, 0xb7, 0x74, - 0xb3, 0x1d, 0x6d, 0x64, 0xcd, 0x91, 0x4c, 0x39, 0xe4, 0x9c, 0xcd, 0x9f, 0xac, 0x29, 0xa5, 0x3e, - 0xf4, 0x31, 0x57, 0x4a, 0x21, 0x0a, 0x7e, 0xac, 0xde, 0x0c, 0xa9, 0x68, 0xe1, 0x16, 0x51, 0x4c, - 0xd7, 0x96, 0x2a, 0xa6, 0xfc, 0xe8, 0x59, 0x98, 0xff, 0x98, 0xb3, 0x26, 0x1c, 0xe2, 0x39, 0x3e, - 0x8b, 0xf6, 0x1c, 0xa9, 0x79, 0x93, 0x92, 0x70, 0xd7, 0x21, 0xfd, 0x75, 0xc2, 0xbf, 0xb0, 0xc1, - 0x2b, 0xc2, 0x31, 0xa4, 0x2d, 0x5b, 0xb5, 0x87, 0x16, 0x37, 0xb8, 0xef, 0xcd, 0x7b, 0xdf, 0xd8, - 0x74, 0x1e, 0x4e, 0xa9, 0xb8, 0xcc, 0xd5, 0x7c, 0xbb, 0xde, 0xd4, 0xc1, 0x06, 0x17, 0x27, 0xfa, - 0xc8, 0x78, 0x3e, 0x27, 0x2e, 0x3d, 0xf2, 0x92, 0x1c, 0x1f, 0x6a, 0x3e, 0x89, 0x48, 0x0b, 0x61, - 0x88, 0xf4, 0xdf, 0x08, 0x70, 0x7b, 0xca, 0xad, 0x0b, 0x7d, 0x32, 0xb6, 0xcf, 0x0f, 0x17, 0xb9, - 0xb3, 0x6d, 0x32, 0x5a, 0x70, 0xa7, 0xa5, 0x0f, 0xa1, 0xe0, 0xa7, 0xcf, 0x37, 0xc9, 0x5f, 0xc5, - 0x3d, 0x9f, 0x1f, 0x84, 0xce, 0x5f, 0x5b, 0x36, 0x37, 0x66, 0x67, 0xf1, 0x05, 0xed, 0x2c, 0x34, - 0x2f, 0x48, 0xbc, 0x62, 0x5e, 0x30, 0xc5, 0xda, 0x92, 0xaf, 0x66, 0x6d, 0x81, 0x03, 0x97, 0x0a, - 0x5e, 0x18, 0x3e, 0x03, 0xf0, 0x81, 0x99, 0x2b, 0x90, 0x32, 0xf5, 0xe1, 0xa0, 0x4d, 0x2d, 0x20, - 0x25, 0xb3, 0x06, 0xfa, 0x08, 0x52, 0xc4, 0x92, 0x9c, 0x75, 0x9a, 0x74, 0xaa, 0xc4, 0x12, 0x7c, - 0x10, 0x29, 0xe3, 0x96, 0x7e, 0x08, 0xa5, 0x20, 0x82, 0xfa, 0x7a, 0xd5, 0x6b, 0x80, 0x26, 0xbf, - 0x24, 0x88, 0xe8, 0xe2, 0xfb, 0xc1, 0x2e, 0xde, 0x8a, 0xfc, 0x26, 0x21, 0xbc, 0xab, 0x2f, 0x20, - 0x45, 0x0d, 0x8b, 0x64, 0xb7, 0xf4, 0xf3, 0x15, 0x7e, 0x9f, 0x25, 0xcf, 0xe8, 0x87, 0x00, 0xaa, - 0x6d, 0x9b, 0xda, 0xc5, 0xd0, 0xeb, 0x60, 0x3d, 0xdc, 0x30, 0x77, 0x1c, 0xbe, 0xdd, 0x37, 0xb8, - 0x85, 0xae, 0x78, 0xa2, 0x3e, 0x2b, 0xf5, 0x29, 0x94, 0x8e, 0xa0, 0x14, 0x94, 0x75, 0x6e, 0x60, - 0x42, 0xc8, 0x0d, 0x2c, 0xee, 0xbf, 0x81, 0xb9, 0xf7, 0xb7, 0x04, 0xfb, 0x46, 0x87, 0x36, 0xa4, - 0xff, 0x11, 0xa0, 0xe0, 0xb7, 0xeb, 0xd7, 0x9c, 0xeb, 0xcf, 0xb8, 0xd8, 0xdc, 0x9a, 0x48, 0xf5, - 0x33, 0x1d, 0xd5, 0x3a, 0xfb, 0x75, 0x66, 0xfa, 0x5f, 0x0a, 0x90, 0x75, 0x27, 0x1f, 0x81, 0x87, - 0x7b, 0x6b, 0x17, 0xf7, 0x7f, 0x63, 0xc3, 0x30, 0xf8, 0x84, 0x8b, 0xc1, 0x3f, 0x72, 0x53, 0xb1, - 0x28, 0xe4, 0xd9, 0xbf, 0xd2, 0x4e, 0x25, 0x82, 0x67, 0x9e, 0x7f, 0xc1, 0xc7, 0x41, 0x72, 0x10, - 0xf4, 0x3b, 0x90, 0x56, 0x5b, 0x2e, 0xde, 0x5e, 0x0a, 0x41, 0x8f, 0x1c, 0xd6, 0xcd, 0xe6, 0x68, - 0x87, 0x72, 0xca, 0x5c, 0x82, 0x8f, 0x2a, 0xee, 0x8c, 0x4a, 0x7a, 0x4c, 0xf4, 0x32, 0x9e, 0xa0, - 0xc3, 0x2d, 0x01, 0x9c, 0x1d, 0x3d, 0x3b, 0xde, 0x3b, 0xd8, 0x3f, 0xa8, 0xef, 0xf1, 0x64, 0x6c, - 0x6f, 0xaf, 0xbe, 0x27, 0xc6, 0x09, 0x9f, 0x5c, 0x7f, 0x76, 0x7c, 0x5e, 0xdf, 0x13, 0x13, 0x52, - 0x0d, 0xf2, 0x4e, 0xbd, 0x47, 0xed, 0x5b, 0xe8, 0x36, 0xe4, 0xfa, 0x6a, 0xf0, 0x6b, 0xa0, 0x6c, - 0x5f, 0xe5, 0xdf, 0x02, 0xdd, 0x84, 0x0c, 0x79, 0xd9, 0x51, 0x2d, 0xa7, 0x3c, 0xdb, 0x57, 0x47, - 0x3f, 0x50, 0x2d, 0xe9, 0x7f, 0x05, 0x28, 0x8f, 0xb9, 0x27, 0xb4, 0x0d, 0x29, 0x06, 0x6f, 0x45, - 0x7d, 0x1d, 0xee, 0xeb, 0x56, 0x66, 0xac, 0xe8, 0x63, 0xc8, 0x3a, 0x25, 0xb1, 0xb0, 0xfb, 0x11, - 0xf3, 0x83, 0x4e, 0x51, 0x85, 0x8b, 0xba, 0x12, 0xe8, 0x31, 0xe4, 0x5c, 0x47, 0x1b, 0xfd, 0x55, - 0x9f, 0xeb, 0xa2, 0xb9, 0xbc, 0x27, 0x83, 0x1e, 0x7a, 0x68, 0x55, 0x72, 0x12, 0x6a, 0xe7, 0xe2, - 0x8c, 0x81, 0x0b, 0x3b, 0xfc, 0xd2, 0x23, 0xc8, 0xb9, 0x8a, 0x51, 0x05, 0x32, 0x4e, 0x61, 0x52, - 0xe0, 0x1e, 0x98, 0x17, 0x24, 0x57, 0x20, 0x65, 0xe8, 0x9f, 0xf3, 0x2f, 0xb4, 0x12, 0x32, 0x6b, - 0x48, 0x6d, 0x28, 0x8f, 0x05, 0x0e, 0xf4, 0x08, 0x32, 0xc6, 0xf0, 0x42, 0x71, 0xce, 0xfe, 0xd8, - 0xfa, 0x39, 0x78, 0xca, 0xf0, 0xa2, 0xa7, 0xb5, 0x9e, 0xe2, 0x6b, 0xc7, 0xda, 0x8c, 0xe1, 0xc5, - 0x53, 0xe6, 0x22, 0x58, 0x2f, 0x71, 0x7f, 0x2f, 0x57, 0x90, 0x75, 0x3c, 0x1e, 0xfa, 0x5d, 0xff, - 0x52, 0x39, 0x5f, 0x58, 0x46, 0x06, 0x33, 0xae, 0xde, 0xb7, 0x52, 0xf7, 0x60, 0xc9, 0xd2, 0x3a, - 0x03, 0xa7, 0x88, 0xcd, 0x36, 0x9a, 0x55, 0xa5, 0xca, 0xec, 0xc5, 0xa1, 0x03, 0xba, 0x91, 0x54, - 0x44, 0x1c, 0x77, 0xb9, 0xbf, 0xce, 0x01, 0x84, 0xa4, 0x4c, 0x89, 0xb0, 0x94, 0xe9, 0x4f, 0xe3, - 0x90, 0xf7, 0x95, 0xc6, 0xd1, 0x6f, 0xfb, 0xfc, 0x7f, 0x29, 0x24, 0xd6, 0xfb, 0x78, 0xbd, 0x4f, - 0x18, 0x83, 0x13, 0x8b, 0x2f, 0x3e, 0xb1, 0xa8, 0x2f, 0x11, 0x9c, 0x0a, 0x7b, 0x72, 0xe1, 0x0a, - 0xfb, 0x07, 0x80, 0x68, 0x6d, 0x58, 0xb9, 0xd2, 0x6d, 0x6d, 0xd0, 0x51, 0x98, 0x69, 0x30, 0x6f, - 0x2d, 0xd2, 0x37, 0xe7, 0xf4, 0xc5, 0x09, 0xb5, 0x92, 0x3f, 0x8e, 0x43, 0xd6, 0x39, 0x61, 0xff, - 0x4f, 0x97, 0xe0, 0x4f, 0x04, 0xc8, 0xba, 0xd0, 0xc3, 0xa2, 0xdf, 0x78, 0xae, 0x42, 0x9a, 0xdf, - 0xae, 0xd9, 0x47, 0x9e, 0xbc, 0x15, 0xfa, 0x35, 0x45, 0x15, 0xb2, 0x7d, 0x6c, 0xab, 0x34, 0xfa, - 0xb2, 0x54, 0xcd, 0x6d, 0xdf, 0x7b, 0x08, 0x79, 0xdf, 0xf7, 0xb1, 0x24, 0x20, 0x1f, 0xd5, 0x3f, - 0x15, 0x63, 0xd5, 0xcc, 0x4f, 0x7f, 0xb6, 0x91, 0x38, 0xc2, 0x9f, 0x13, 0x27, 0x23, 0xd7, 0x6b, - 0x8d, 0x7a, 0xed, 0xa9, 0x28, 0x54, 0xf3, 0x3f, 0xfd, 0xd9, 0x46, 0x46, 0xc6, 0xb4, 0x64, 0x78, - 0xef, 0x29, 0x94, 0xc7, 0x36, 0x26, 0x18, 0x1a, 0x10, 0x94, 0xf6, 0xce, 0x4e, 0x0e, 0x0f, 0x6a, - 0x3b, 0xcd, 0xba, 0x72, 0x7e, 0xdc, 0xac, 0x8b, 0x02, 0xba, 0x09, 0xcb, 0x87, 0x07, 0x3f, 0x68, - 0x34, 0x95, 0xda, 0xe1, 0x41, 0xfd, 0xa8, 0xa9, 0xec, 0x34, 0x9b, 0x3b, 0xb5, 0xa7, 0x62, 0x7c, - 0xfb, 0x6f, 0xf3, 0x50, 0xde, 0xd9, 0xad, 0x1d, 0xec, 0x18, 0x46, 0x4f, 0x6b, 0xa9, 0x34, 0xd0, - 0xd4, 0x20, 0x49, 0xab, 0x05, 0x53, 0xff, 0xf8, 0xa9, 0x4e, 0xaf, 0x03, 0xa3, 0x7d, 0x48, 0xd1, - 0x42, 0x02, 0x9a, 0xfe, 0x0b, 0x50, 0x75, 0x46, 0x61, 0x98, 0x0c, 0x86, 0x7a, 0x94, 0xa9, 0xff, - 0x04, 0x55, 0xa7, 0xd7, 0x89, 0xd1, 0x21, 0x64, 0x1c, 0x9c, 0x77, 0xd6, 0x8f, 0x3a, 0xd5, 0x99, - 0xc5, 0x5b, 0x32, 0x35, 0x86, 0xc7, 0x4f, 0xff, 0x5d, 0xa8, 0x3a, 0xa3, 0x82, 0x8c, 0x0e, 0x20, - 0xcd, 0x11, 0xb9, 0x19, 0x7f, 0x00, 0x55, 0x67, 0xd5, 0x84, 0x91, 0x0c, 0x39, 0xaf, 0xd2, 0x31, - 0xfb, 0x27, 0xa8, 0xea, 0x1c, 0xc5, 0x71, 0xf4, 0x1c, 0x8a, 0x41, 0xe4, 0x6f, 0xbe, 0xbf, 0x8c, - 0xaa, 0x73, 0x56, 0x9f, 0x89, 0xfe, 0x20, 0x0c, 0x38, 0xdf, 0x5f, 0x47, 0xd5, 0x39, 0x8b, 0xd1, - 0xe8, 0xc7, 0xb0, 0x34, 0x09, 0xd3, 0xcd, 0xff, 0x13, 0x52, 0x75, 0x81, 0xf2, 0x34, 0xea, 0x03, - 0x0a, 0x81, 0xf7, 0x16, 0xf8, 0x27, 0xa9, 0xba, 0x48, 0xb5, 0x1a, 0xb5, 0xa1, 0x3c, 0x0e, 0x99, - 0xcd, 0xfb, 0x8f, 0x52, 0x75, 0xee, 0xca, 0x35, 0xeb, 0x25, 0x88, 0x1f, 0xcd, 0xfb, 0xcf, 0x52, - 0x75, 0xee, 0x42, 0x36, 0x3a, 0x03, 0xf0, 0xe1, 0x1f, 0x73, 0xfc, 0xc3, 0x54, 0x9d, 0xa7, 0xa4, - 0x8d, 0x0c, 0x58, 0x0e, 0x03, 0x46, 0x16, 0xf9, 0xa5, 0xa9, 0xba, 0x50, 0xa5, 0x9b, 0xd8, 0x73, - 0x10, 0xe2, 0x98, 0xef, 0x17, 0xa7, 0xea, 0x9c, 0x25, 0xef, 0xdd, 0xfa, 0xcf, 0xbf, 0x5e, 0x13, - 0x7e, 0xf1, 0xf5, 0x9a, 0xf0, 0x5f, 0x5f, 0xaf, 0x09, 0x5f, 0x7d, 0xb3, 0x16, 0xfb, 0xc5, 0x37, - 0x6b, 0xb1, 0x7f, 0xff, 0x66, 0x2d, 0xf6, 0x07, 0xef, 0x77, 0x34, 0xbb, 0x3b, 0xbc, 0xd8, 0x6c, - 0xe9, 0xfd, 0x2d, 0xff, 0x4f, 0xa1, 0x61, 0x7f, 0xaa, 0x5e, 0xa4, 0x69, 0x40, 0xfd, 0xf0, 0xff, - 0x02, 0x00, 0x00, 0xff, 0xff, 0xd2, 0x5a, 0x12, 0x96, 0xc9, 0x3a, 0x00, 0x00, + // 3877 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0x4b, 0x73, 0x23, 0xd7, + 0x75, 0x46, 0xe3, 0x8d, 0x83, 0x57, 0xf3, 0x92, 0xc3, 0xc1, 0x60, 0x24, 0x92, 0x6a, 0xd5, 0x48, + 0xa3, 0x91, 0x4c, 0x3a, 0x54, 0x34, 0x9e, 0xc9, 0xc8, 0x99, 0x90, 0x20, 0x68, 0x70, 0x86, 0x43, + 0x52, 0x4d, 0x90, 0x8a, 0x92, 0x78, 0xda, 0x4d, 0xe0, 0x12, 0x68, 0x0f, 0x80, 0x6e, 0x77, 0x37, + 0x28, 0x50, 0xab, 0x54, 0x12, 0x6f, 0x9c, 0x8d, 0x76, 0xc9, 0x22, 0xde, 0xc5, 0x7f, 0x20, 0x8b, + 0x54, 0x56, 0x59, 0xa5, 0x52, 0x5e, 0x78, 0xe1, 0x45, 0x2a, 0x95, 0x95, 0x93, 0x92, 0x76, 0xfe, + 0x03, 0xd9, 0xc5, 0xa9, 0xfb, 0xe8, 0x17, 0xd0, 0x8d, 0xc7, 0xcc, 0x94, 0xab, 0x5c, 0xd6, 0xae, + 0xef, 0xed, 0x73, 0xce, 0x7d, 0x9d, 0xd7, 0xfd, 0x4e, 0x37, 0xdc, 0xb6, 0xf1, 0xa0, 0x8d, 0xcd, + 0xbe, 0x36, 0xb0, 0xb7, 0xd4, 0x8b, 0x96, 0xb6, 0x65, 0x5f, 0x1b, 0xd8, 0xda, 0x34, 0x4c, 0xdd, + 0xd6, 0x51, 0xd9, 0x7b, 0xb9, 0x49, 0x5e, 0x56, 0xdf, 0xf4, 0x51, 0xb7, 0xcc, 0x6b, 0xc3, 0xd6, + 0xb7, 0x0c, 0x53, 0xd7, 0x2f, 0x19, 0x7d, 0xf5, 0x8d, 0xc9, 0xd7, 0x2f, 0xf0, 0x35, 0x97, 0x16, + 0x60, 0xa6, 0xa3, 0x6c, 0x19, 0xaa, 0xa9, 0xf6, 0xad, 0x10, 0x66, 0xf6, 0xda, 0x37, 0x95, 0xea, + 0x7a, 0x47, 0xd7, 0x3b, 0x3d, 0xbc, 0x45, 0x5b, 0x17, 0xc3, 0xcb, 0x2d, 0x5b, 0xeb, 0x63, 0xcb, + 0x56, 0xfb, 0x06, 0x27, 0x58, 0xe9, 0xe8, 0x1d, 0x9d, 0x3e, 0x6e, 0x91, 0x27, 0xd6, 0x2b, 0xfd, + 0x22, 0x0f, 0x19, 0x19, 0xff, 0x68, 0x88, 0x2d, 0x1b, 0x6d, 0x43, 0x12, 0xb7, 0xba, 0x7a, 0x45, + 0xd8, 0x10, 0xee, 0xe6, 0xb7, 0xdf, 0xd8, 0x1c, 0x5b, 0xdc, 0x26, 0xa7, 0xab, 0xb7, 0xba, 0x7a, + 0x23, 0x26, 0x53, 0x5a, 0xf4, 0x11, 0xa4, 0x2e, 0x7b, 0x43, 0xab, 0x5b, 0x89, 0x53, 0xa6, 0x37, + 0xa3, 0x98, 0xf6, 0x09, 0x51, 0x23, 0x26, 0x33, 0x6a, 0x32, 0x94, 0x36, 0xb8, 0xd4, 0x2b, 0x89, + 0xe9, 0x43, 0x1d, 0x0c, 0x2e, 0xe9, 0x50, 0x84, 0x16, 0xed, 0x02, 0x68, 0x03, 0xcd, 0x56, 0x5a, + 0x5d, 0x55, 0x1b, 0x54, 0x92, 0x94, 0xf3, 0xad, 0x68, 0x4e, 0xcd, 0xae, 0x11, 0xc2, 0x46, 0x4c, + 0xce, 0x69, 0x4e, 0x83, 0x4c, 0xf7, 0x47, 0x43, 0x6c, 0x5e, 0x57, 0x52, 0xd3, 0xa7, 0xfb, 0x09, + 0x21, 0x22, 0xd3, 0xa5, 0xd4, 0xe8, 0x63, 0xc8, 0xb6, 0xba, 0xb8, 0xf5, 0x42, 0xb1, 0x47, 0x95, + 0x0c, 0xe5, 0x5c, 0x8f, 0xe2, 0xac, 0x11, 0xba, 0xe6, 0xa8, 0x11, 0x93, 0x33, 0x2d, 0xf6, 0x88, + 0x1e, 0x40, 0xba, 0xa5, 0xf7, 0xfb, 0x9a, 0x5d, 0x01, 0xca, 0xbb, 0x16, 0xc9, 0x4b, 0xa9, 0x1a, + 0x31, 0x99, 0xd3, 0xa3, 0x23, 0x28, 0xf5, 0x34, 0xcb, 0x56, 0xac, 0x81, 0x6a, 0x58, 0x5d, 0xdd, + 0xb6, 0x2a, 0x79, 0x2a, 0xe1, 0x4e, 0x94, 0x84, 0x43, 0xcd, 0xb2, 0x4f, 0x1d, 0xe2, 0x46, 0x4c, + 0x2e, 0xf6, 0xfc, 0x1d, 0x44, 0x9e, 0x7e, 0x79, 0x89, 0x4d, 0x57, 0x60, 0xa5, 0x30, 0x5d, 0xde, + 0x31, 0xa1, 0x76, 0xf8, 0x89, 0x3c, 0xdd, 0xdf, 0x81, 0xfe, 0x1c, 0x96, 0x7b, 0xba, 0xda, 0x76, + 0xc5, 0x29, 0xad, 0xee, 0x70, 0xf0, 0xa2, 0x52, 0xa4, 0x42, 0xdf, 0x8b, 0x9c, 0xa4, 0xae, 0xb6, + 0x1d, 0x11, 0x35, 0xc2, 0xd0, 0x88, 0xc9, 0x4b, 0xbd, 0xf1, 0x4e, 0xf4, 0x1c, 0x56, 0x54, 0xc3, + 0xe8, 0x5d, 0x8f, 0x4b, 0x2f, 0x51, 0xe9, 0xf7, 0xa2, 0xa4, 0xef, 0x10, 0x9e, 0x71, 0xf1, 0x48, + 0x9d, 0xe8, 0x45, 0x4d, 0x10, 0x0d, 0x13, 0x1b, 0xaa, 0x89, 0x15, 0xc3, 0xd4, 0x0d, 0xdd, 0x52, + 0x7b, 0x95, 0x32, 0x95, 0xfd, 0x6e, 0x94, 0xec, 0x13, 0x46, 0x7f, 0xc2, 0xc9, 0x1b, 0x31, 0xb9, + 0x6c, 0x04, 0xbb, 0x98, 0x54, 0xbd, 0x85, 0x2d, 0xcb, 0x93, 0x2a, 0xce, 0x92, 0x4a, 0xe9, 0x83, + 0x52, 0x03, 0x5d, 0xa8, 0x0e, 0x79, 0x3c, 0x22, 0xec, 0xca, 0x95, 0x6e, 0xe3, 0xca, 0x12, 0x15, + 0x28, 0x45, 0x5a, 0x28, 0x25, 0x3d, 0xd7, 0x6d, 0xdc, 0x88, 0xc9, 0x80, 0xdd, 0x16, 0x52, 0xe1, + 0xc6, 0x15, 0x36, 0xb5, 0xcb, 0x6b, 0x2a, 0x46, 0xa1, 0x6f, 0x2c, 0x4d, 0x1f, 0x54, 0x10, 0x15, + 0xf8, 0x7e, 0x94, 0xc0, 0x73, 0xca, 0x44, 0x44, 0xd4, 0x1d, 0x96, 0x46, 0x4c, 0x5e, 0xbe, 0x9a, + 0xec, 0x26, 0x2a, 0x76, 0xa9, 0x0d, 0xd4, 0x9e, 0xf6, 0x05, 0x56, 0x2e, 0x7a, 0x7a, 0xeb, 0x45, + 0x65, 0x79, 0xba, 0x8a, 0xed, 0x73, 0xea, 0x5d, 0x42, 0x4c, 0x54, 0xec, 0xd2, 0xdf, 0x41, 0x56, + 0x7e, 0x81, 0x3b, 0xda, 0x80, 0x0b, 0x5b, 0x99, 0xbe, 0xf2, 0x5d, 0x42, 0xea, 0x48, 0x82, 0x0b, + 0xb7, 0x45, 0x9c, 0x47, 0x1b, 0xf7, 0xb4, 0x2b, 0x6c, 0x12, 0x1b, 0xbe, 0x31, 0xdd, 0x79, 0xec, + 0x31, 0x4a, 0x6a, 0xc5, 0xb9, 0xb6, 0xd3, 0x40, 0x8f, 0x21, 0x47, 0x4e, 0x80, 0x4d, 0x64, 0x95, + 0x8a, 0xd8, 0x88, 0x3c, 0x82, 0x41, 0xdb, 0x99, 0x46, 0x16, 0xf3, 0x67, 0xb2, 0x16, 0x6a, 0x2e, + 0x3d, 0xd5, 0xc6, 0x96, 0x5d, 0xb9, 0x39, 0x7d, 0x2d, 0xc4, 0x4c, 0x0e, 0x29, 0x25, 0x59, 0x4b, + 0xcf, 0x6d, 0xed, 0x66, 0x20, 0x75, 0xa5, 0xf6, 0x86, 0xf8, 0x49, 0x32, 0x9b, 0x16, 0x33, 0x4f, + 0x92, 0xd9, 0xac, 0x98, 0x7b, 0x92, 0xcc, 0xe6, 0x44, 0x90, 0xde, 0x85, 0xbc, 0xcf, 0x4b, 0xa3, + 0x0a, 0x64, 0xfa, 0xd8, 0xb2, 0xd4, 0x0e, 0xa6, 0x4e, 0x3d, 0x27, 0x3b, 0x4d, 0xa9, 0x04, 0x05, + 0xbf, 0x67, 0x96, 0xbe, 0x14, 0x5c, 0x4e, 0xe2, 0x74, 0x09, 0xe7, 0x15, 0x36, 0xa9, 0x6e, 0x70, + 0x4e, 0xde, 0x44, 0x6f, 0x43, 0x91, 0xee, 0x80, 0xe2, 0xbc, 0x27, 0x9e, 0x3f, 0x29, 0x17, 0x68, + 0xe7, 0x39, 0x27, 0x5a, 0x87, 0xbc, 0xb1, 0x6d, 0xb8, 0x24, 0x09, 0x4a, 0x02, 0xc6, 0xb6, 0xe1, + 0x10, 0xbc, 0x05, 0x05, 0xb2, 0x56, 0x97, 0x22, 0x49, 0x07, 0xc9, 0x93, 0x3e, 0x4e, 0x22, 0xfd, + 0x22, 0x0e, 0xe2, 0xb8, 0x37, 0x47, 0x0f, 0x20, 0x49, 0x02, 0x1b, 0x8f, 0x51, 0xd5, 0x4d, 0x16, + 0xf5, 0x36, 0x9d, 0xa8, 0xb7, 0xd9, 0x74, 0xa2, 0xde, 0x6e, 0xf6, 0xe7, 0xbf, 0x5a, 0x8f, 0x7d, + 0xf9, 0xdf, 0xeb, 0x82, 0x4c, 0x39, 0xd0, 0x2d, 0xe2, 0xc3, 0x55, 0x6d, 0xa0, 0x68, 0x6d, 0x3a, + 0xe5, 0x1c, 0x71, 0xd0, 0xaa, 0x36, 0x38, 0x68, 0xa3, 0x43, 0x10, 0x5b, 0xfa, 0xc0, 0xc2, 0x03, + 0x6b, 0x68, 0x29, 0x2c, 0xe6, 0xf2, 0xc8, 0x14, 0x50, 0x11, 0x16, 0x6e, 0x6b, 0x0e, 0xe5, 0x09, + 0x25, 0x94, 0xcb, 0xad, 0x60, 0x07, 0xda, 0x07, 0xb8, 0x52, 0x7b, 0x5a, 0x5b, 0xb5, 0x75, 0xd3, + 0xaa, 0x24, 0x37, 0x12, 0xa1, 0x7a, 0x72, 0xee, 0x90, 0x9c, 0x19, 0x6d, 0xd5, 0xc6, 0xbb, 0x49, + 0x32, 0x5d, 0xd9, 0xc7, 0x89, 0xde, 0x81, 0xb2, 0x6a, 0x18, 0x8a, 0x65, 0xab, 0x36, 0x56, 0x2e, + 0xae, 0x6d, 0x6c, 0xd1, 0xa8, 0x55, 0x90, 0x8b, 0xaa, 0x61, 0x9c, 0x92, 0xde, 0x5d, 0xd2, 0x89, + 0xee, 0x40, 0x89, 0x04, 0x38, 0x4d, 0xed, 0x29, 0x5d, 0xac, 0x75, 0xba, 0x76, 0x25, 0xbd, 0x21, + 0xdc, 0x4d, 0xc8, 0x45, 0xde, 0xdb, 0xa0, 0x9d, 0x52, 0xdb, 0x3d, 0x71, 0x1a, 0xdc, 0x10, 0x82, + 0x64, 0x5b, 0xb5, 0x55, 0xba, 0x93, 0x05, 0x99, 0x3e, 0x93, 0x3e, 0x43, 0xb5, 0xbb, 0x7c, 0x7f, + 0xe8, 0x33, 0x5a, 0x85, 0x34, 0x17, 0x9b, 0xa0, 0x62, 0x79, 0x0b, 0xad, 0x40, 0xca, 0x30, 0xf5, + 0x2b, 0x4c, 0x8f, 0x2e, 0x2b, 0xb3, 0x86, 0x24, 0x43, 0x29, 0x18, 0x08, 0x51, 0x09, 0xe2, 0xf6, + 0x88, 0x8f, 0x12, 0xb7, 0x47, 0xe8, 0xdb, 0x90, 0x24, 0x1b, 0x49, 0xc7, 0x28, 0x85, 0x84, 0x7e, + 0xce, 0xd7, 0xbc, 0x36, 0xb0, 0x4c, 0x29, 0xa5, 0x32, 0x14, 0x03, 0x01, 0x52, 0x5a, 0x85, 0x95, + 0xb0, 0x78, 0x27, 0x75, 0xdd, 0xfe, 0x40, 0xdc, 0x42, 0x1f, 0x41, 0xd6, 0x0d, 0x78, 0x4c, 0x71, + 0x6e, 0x4d, 0x0c, 0xeb, 0x10, 0xcb, 0x2e, 0x29, 0xd1, 0x18, 0x72, 0x00, 0x5d, 0x95, 0xa7, 0x37, + 0x05, 0x39, 0xa3, 0x1a, 0x46, 0x43, 0xb5, 0xba, 0xd2, 0x0f, 0xa0, 0x12, 0x15, 0xcc, 0x7c, 0x1b, + 0x26, 0x50, 0xb5, 0x77, 0x36, 0x6c, 0x15, 0xd2, 0x97, 0xba, 0xd9, 0x57, 0x6d, 0x2a, 0xac, 0x28, + 0xf3, 0x16, 0xd9, 0x48, 0x16, 0xd8, 0x12, 0xb4, 0x9b, 0x35, 0x24, 0x05, 0x6e, 0x45, 0x06, 0x34, + 0xc2, 0xa2, 0x0d, 0xda, 0x98, 0x6d, 0x6b, 0x51, 0x66, 0x0d, 0x4f, 0x10, 0x9b, 0x2c, 0x6b, 0x90, + 0x61, 0x2d, 0xba, 0x56, 0x2a, 0x3f, 0x27, 0xf3, 0x96, 0xf4, 0xef, 0x69, 0x58, 0x0d, 0x0f, 0x6b, + 0x68, 0x03, 0x0a, 0x7d, 0x75, 0xa4, 0xd8, 0x23, 0xae, 0x76, 0x02, 0x3d, 0x78, 0xe8, 0xab, 0xa3, + 0xe6, 0x88, 0xe9, 0x9c, 0x08, 0x09, 0x7b, 0x64, 0x55, 0xe2, 0x1b, 0x89, 0xbb, 0x05, 0x99, 0x3c, + 0xa2, 0x33, 0x58, 0xea, 0xe9, 0x2d, 0xb5, 0xa7, 0xf4, 0x54, 0xcb, 0x56, 0x78, 0xbe, 0xc3, 0x8c, + 0xe8, 0xed, 0x89, 0xcd, 0x66, 0x01, 0x0a, 0xb7, 0xd9, 0x79, 0x12, 0x87, 0xc3, 0xf5, 0xbf, 0x4c, + 0x65, 0x1c, 0xaa, 0xce, 0x51, 0xa3, 0x33, 0x58, 0xb9, 0xb8, 0xfe, 0x42, 0x1d, 0xd8, 0xda, 0x00, + 0x2b, 0x13, 0x66, 0x35, 0xa9, 0x3d, 0xcf, 0x34, 0xeb, 0x02, 0x77, 0xd5, 0x2b, 0x4d, 0x37, 0xb9, + 0xc8, 0x65, 0x97, 0xff, 0xdc, 0xb3, 0x2d, 0xef, 0x8c, 0x52, 0x01, 0xa5, 0x76, 0xdc, 0x4b, 0x7a, + 0x61, 0xf7, 0xf2, 0x6d, 0x58, 0x19, 0xe0, 0x91, 0xed, 0x9b, 0x23, 0x53, 0x9c, 0x0c, 0x3d, 0x0b, + 0x44, 0xde, 0x79, 0xe3, 0x13, 0x1d, 0x42, 0xef, 0xd1, 0x4c, 0xc1, 0xd0, 0x2d, 0x6c, 0x2a, 0x6a, + 0xbb, 0x6d, 0x62, 0xcb, 0xaa, 0x64, 0x29, 0x75, 0xd9, 0xe9, 0xdf, 0x61, 0xdd, 0x01, 0x4d, 0xcc, + 0x05, 0x34, 0x11, 0xbd, 0x0b, 0xe5, 0xf1, 0x21, 0x81, 0x52, 0x94, 0xae, 0x82, 0xc3, 0xdd, 0x81, + 0x92, 0xe7, 0xe4, 0x28, 0x5d, 0x9e, 0x79, 0x13, 0xb7, 0x97, 0x92, 0xdd, 0x86, 0x1c, 0x71, 0x05, + 0x8c, 0xa2, 0x40, 0x29, 0xb2, 0xa4, 0x83, 0xbe, 0x7c, 0x1b, 0x8a, 0xf8, 0x4a, 0x6b, 0xe3, 0x41, + 0x0b, 0x33, 0x82, 0x22, 0x25, 0x28, 0x38, 0x9d, 0x94, 0xe8, 0x1d, 0x28, 0x53, 0x1d, 0x60, 0x51, + 0x82, 0x92, 0x95, 0xd8, 0x48, 0xa4, 0x9b, 0x45, 0x45, 0x42, 0xf7, 0x00, 0x6e, 0xf9, 0xe8, 0x0c, + 0xd5, 0xb4, 0x15, 0x0b, 0xdb, 0x8a, 0xad, 0xdb, 0x3c, 0x11, 0x4b, 0xc8, 0x37, 0x5c, 0x8e, 0x13, + 0xd5, 0xb4, 0x4f, 0xb1, 0xdd, 0x24, 0x2f, 0xd1, 0x7d, 0xa8, 0x84, 0x71, 0xd2, 0xa1, 0x44, 0x3a, + 0xd4, 0xca, 0x38, 0x23, 0x1d, 0xf1, 0x2e, 0x88, 0x3e, 0xed, 0x64, 0xf4, 0x4b, 0x6c, 0xb3, 0x7a, + 0xae, 0xca, 0x51, 0xca, 0x7b, 0xb0, 0x44, 0x29, 0x4d, 0x6c, 0x0d, 0x7b, 0x36, 0xdf, 0x2f, 0xc4, + 0x0e, 0x87, 0xbc, 0x90, 0x59, 0x3f, 0xf5, 0x05, 0xff, 0xec, 0x37, 0xa4, 0x60, 0xda, 0xc6, 0xcd, + 0x44, 0xf0, 0xcc, 0xe4, 0x14, 0x56, 0xf8, 0xe1, 0xb6, 0x03, 0x96, 0xc2, 0xae, 0x4f, 0xb7, 0x27, + 0xbd, 0xe1, 0xb8, 0x85, 0x20, 0x87, 0x7d, 0x0e, 0x23, 0x49, 0xbc, 0x9a, 0x91, 0x20, 0x48, 0xd2, + 0x75, 0x27, 0x59, 0x84, 0x20, 0xcf, 0xbf, 0xcb, 0x86, 0x03, 0x33, 0x0d, 0x27, 0x3f, 0xa7, 0xe1, + 0x14, 0x66, 0x1a, 0x4e, 0x71, 0x96, 0xe1, 0x94, 0xe6, 0x33, 0x9c, 0xf2, 0xc2, 0x86, 0x23, 0xbe, + 0xac, 0xe1, 0x2c, 0x2d, 0x68, 0x38, 0x68, 0x7e, 0xc3, 0x59, 0x0e, 0x37, 0x9c, 0xc7, 0xb0, 0x34, + 0x71, 0x61, 0x71, 0x95, 0x4e, 0x08, 0x55, 0xba, 0xb8, 0x5f, 0xe9, 0xa4, 0x7f, 0x10, 0xa0, 0x1a, + 0x7d, 0x43, 0x09, 0x15, 0xf5, 0x3e, 0x2c, 0xb9, 0xc7, 0xeb, 0x2a, 0x0f, 0x8b, 0x97, 0xa2, 0xfb, + 0xc2, 0xd1, 0x9e, 0xa8, 0xd4, 0xe7, 0x0e, 0x94, 0xc6, 0xee, 0x4f, 0xcc, 0x44, 0x8a, 0x57, 0xfe, + 0xf1, 0xa5, 0x7f, 0x4a, 0xbb, 0xf9, 0x48, 0xe0, 0x92, 0x13, 0xe2, 0x16, 0x3e, 0x81, 0xe5, 0x36, + 0x6e, 0x69, 0xed, 0x97, 0xf5, 0x0a, 0x4b, 0x9c, 0xfb, 0x1b, 0xa7, 0xf0, 0x8d, 0x53, 0xf8, 0xdd, + 0x76, 0x0a, 0x7f, 0x13, 0x77, 0xbd, 0x82, 0x77, 0x99, 0x0f, 0x35, 0xe5, 0xfb, 0x44, 0xeb, 0x54, + 0x92, 0xd8, 0x32, 0x33, 0xa9, 0x4c, 0xde, 0xd5, 0x1a, 0xf4, 0x3d, 0x57, 0x67, 0x4e, 0x8d, 0x8e, + 0x83, 0xf3, 0xf6, 0xe1, 0x90, 0x93, 0xa0, 0x9e, 0x67, 0x4f, 0x3e, 0x63, 0xf3, 0x2d, 0x8f, 0xde, + 0x95, 0xe5, 0xa9, 0x39, 0xea, 0xe4, 0x55, 0xa3, 0xce, 0xcf, 0x77, 0x8a, 0x99, 0x49, 0x75, 0xf7, + 0xee, 0xeb, 0x82, 0x11, 0x13, 0x37, 0xa9, 0xb7, 0xa0, 0x60, 0x69, 0x1d, 0x85, 0xa2, 0x30, 0x1a, + 0x66, 0xb7, 0xda, 0xac, 0x9c, 0xb7, 0xb4, 0xce, 0x39, 0xef, 0x92, 0xde, 0x83, 0xf2, 0x18, 0x20, + 0x31, 0x76, 0x3d, 0xf1, 0x9c, 0xe9, 0xb2, 0xbb, 0xef, 0x1e, 0xf0, 0x20, 0xfd, 0xac, 0x00, 0x59, + 0x19, 0x5b, 0x06, 0x51, 0x6a, 0xb4, 0x0b, 0x39, 0x3c, 0x6a, 0x61, 0xc3, 0x76, 0x50, 0x81, 0x70, + 0xf0, 0x82, 0x51, 0xd7, 0x1d, 0xca, 0x46, 0x4c, 0xf6, 0xd8, 0xd0, 0x87, 0x1c, 0x63, 0x8e, 0x86, + 0x8b, 0x39, 0xbb, 0x1f, 0x64, 0xbe, 0xef, 0x80, 0xcc, 0x89, 0x48, 0xfc, 0x94, 0x71, 0x8d, 0xa1, + 0xcc, 0x1f, 0x72, 0x94, 0x39, 0x39, 0x63, 0xb0, 0x00, 0xcc, 0x5c, 0x0b, 0xc0, 0xcc, 0xa9, 0x19, + 0xcb, 0x8c, 0xc0, 0x99, 0xef, 0x3b, 0x38, 0x73, 0x7a, 0xc6, 0x8c, 0xc7, 0x80, 0xe6, 0xef, 0xfa, + 0x80, 0xe6, 0x6c, 0x24, 0xc2, 0xc4, 0x58, 0x43, 0x90, 0xe6, 0x87, 0x2e, 0xd2, 0x9c, 0x8f, 0x44, + 0xa9, 0x39, 0xf3, 0x38, 0xd4, 0x7c, 0x3c, 0x01, 0x35, 0x33, 0x68, 0xf8, 0x9d, 0x48, 0x11, 0x33, + 0xb0, 0xe6, 0xe3, 0x09, 0xac, 0xb9, 0x38, 0x43, 0xe0, 0x0c, 0xb0, 0xf9, 0x2f, 0xc2, 0xc1, 0xe6, + 0x68, 0x38, 0x98, 0x4f, 0x73, 0x3e, 0xb4, 0x59, 0x89, 0x40, 0x9b, 0xcb, 0x91, 0xc8, 0x28, 0x13, + 0x3f, 0x37, 0xdc, 0x7c, 0x16, 0x02, 0x37, 0x33, 0x60, 0xf8, 0x6e, 0xa4, 0xf0, 0x39, 0xf0, 0xe6, + 0xb3, 0x10, 0xbc, 0x79, 0x69, 0xa6, 0xd8, 0x99, 0x80, 0xf3, 0x7e, 0x10, 0x70, 0x46, 0x11, 0x17, + 0x79, 0xcf, 0xda, 0x23, 0x10, 0xe7, 0x8b, 0x28, 0xc4, 0x99, 0xa1, 0xc2, 0x1f, 0x44, 0x4a, 0x5c, + 0x00, 0x72, 0x3e, 0x9e, 0x80, 0x9c, 0x57, 0x66, 0x68, 0xda, 0x0c, 0xcc, 0x79, 0x3f, 0x88, 0x39, + 0xdf, 0x98, 0xb1, 0xf8, 0x48, 0xd0, 0xb9, 0x16, 0x00, 0x9d, 0x57, 0x67, 0xb8, 0x92, 0x08, 0xd4, + 0xf9, 0x4f, 0xfc, 0xa8, 0xf3, 0xcd, 0x48, 0xe0, 0x9a, 0x9f, 0x43, 0x18, 0xec, 0xbc, 0x1f, 0x84, + 0x9d, 0x2b, 0x33, 0x96, 0x33, 0x0f, 0xee, 0x9c, 0x11, 0xb3, 0x0c, 0x71, 0x7e, 0x92, 0xcc, 0x82, + 0x98, 0x97, 0xde, 0x23, 0xc1, 0x63, 0xcc, 0xf1, 0xa3, 0x15, 0x48, 0x61, 0xd3, 0xd4, 0x4d, 0x8e, + 0x20, 0xb3, 0x86, 0x74, 0x17, 0x0a, 0x7e, 0x27, 0x3f, 0x05, 0xa3, 0xa6, 0xb8, 0x9f, 0xcf, 0xb1, + 0x4b, 0xff, 0x22, 0x78, 0xbc, 0x34, 0xf2, 0xfa, 0x31, 0xcc, 0x1c, 0xc7, 0x30, 0x7d, 0xc8, 0x75, + 0x3c, 0x88, 0x5c, 0xaf, 0x43, 0x9e, 0xe4, 0x7d, 0x63, 0xa0, 0xb4, 0x6a, 0xb8, 0xa0, 0xb4, 0x93, + 0xa7, 0xf0, 0x5c, 0x8b, 0x45, 0xc9, 0x24, 0x8d, 0x92, 0x65, 0x2f, 0xdb, 0x62, 0xb9, 0xed, 0xb7, + 0x60, 0xd9, 0x47, 0xeb, 0xe6, 0x93, 0x0c, 0xa1, 0x15, 0x5d, 0xea, 0x1d, 0x0e, 0x18, 0xfe, 0x9b, + 0xe0, 0xed, 0x90, 0x87, 0x66, 0x87, 0x01, 0xcf, 0xc2, 0x6b, 0x02, 0x9e, 0xe3, 0x2f, 0x0d, 0x3c, + 0xfb, 0xf3, 0xe3, 0x44, 0x10, 0xf7, 0xfc, 0x5f, 0xc1, 0x3b, 0x13, 0x17, 0x46, 0x6e, 0xe9, 0x6d, + 0xcc, 0x91, 0x48, 0xfa, 0x4c, 0xee, 0x37, 0x3d, 0xbd, 0xc3, 0xf1, 0x46, 0xf2, 0x48, 0xa8, 0xdc, + 0x48, 0x9c, 0xe3, 0x81, 0xd6, 0x05, 0x31, 0xd9, 0xa5, 0x81, 0x83, 0x98, 0x22, 0x24, 0x5e, 0x60, + 0x16, 0x37, 0x0b, 0x32, 0x79, 0x24, 0x74, 0x54, 0xed, 0x78, 0xf2, 0xcf, 0x1a, 0xe8, 0x01, 0xe4, + 0x68, 0x65, 0x5d, 0xd1, 0x0d, 0x8b, 0x87, 0xca, 0xc0, 0x3d, 0x89, 0x95, 0xd7, 0x37, 0x4f, 0x08, + 0xcd, 0xb1, 0x61, 0xc9, 0x59, 0x83, 0x3f, 0xf9, 0x12, 0xa0, 0x5c, 0xe0, 0xb6, 0xf2, 0x06, 0xe4, + 0xc8, 0xec, 0x2d, 0x43, 0x6d, 0x61, 0x7a, 0x2f, 0xc8, 0xc9, 0x5e, 0x87, 0xf4, 0x1c, 0xd0, 0xa4, + 0xbd, 0xa3, 0x06, 0xa4, 0xf1, 0x15, 0x1e, 0xd8, 0xec, 0x32, 0x97, 0xdf, 0x5e, 0x0d, 0x49, 0xf6, + 0xf0, 0xc0, 0xde, 0xad, 0x90, 0x4d, 0xfe, 0xf5, 0xaf, 0xd6, 0x45, 0x46, 0xfd, 0x81, 0xde, 0xd7, + 0x6c, 0xdc, 0x37, 0xec, 0x6b, 0x99, 0xf3, 0x4b, 0xff, 0x21, 0x90, 0x54, 0x2d, 0x10, 0xd9, 0x43, + 0xf7, 0xd6, 0x51, 0xf9, 0xb8, 0x0f, 0xb6, 0x9f, 0xdc, 0xef, 0x37, 0x01, 0x3a, 0xaa, 0xa5, 0x7c, + 0xae, 0x0e, 0x6c, 0xdc, 0xe6, 0x1b, 0x9c, 0xeb, 0xa8, 0xd6, 0xa7, 0xb4, 0x23, 0xb8, 0xd4, 0xec, + 0xd8, 0x52, 0x7d, 0x88, 0x71, 0xce, 0x8f, 0x18, 0xa3, 0x2a, 0x64, 0x0d, 0x53, 0xd3, 0x4d, 0xcd, + 0xbe, 0xa6, 0xfb, 0x93, 0x90, 0xdd, 0xf6, 0x93, 0x64, 0x36, 0x29, 0xa6, 0xdc, 0x82, 0x14, 0x73, + 0x0f, 0x79, 0xb1, 0x20, 0xfd, 0x38, 0xee, 0xe9, 0xbd, 0x97, 0xc9, 0xbe, 0xfc, 0xc2, 0xc2, 0x14, + 0x69, 0x2d, 0x64, 0xb1, 0xbe, 0x1e, 0x32, 0x6f, 0xd2, 0x1a, 0x5a, 0xb8, 0xcd, 0x4b, 0x23, 0x6e, + 0xdb, 0x77, 0x80, 0x99, 0x57, 0x3b, 0xc0, 0xe9, 0x7b, 0x2a, 0xfd, 0x2d, 0x2d, 0x66, 0x05, 0x9d, + 0x34, 0x3a, 0xf5, 0x83, 0x11, 0x43, 0x6a, 0x8e, 0x8e, 0x22, 0xcd, 0x6b, 0xb7, 0x1e, 0x68, 0xc1, + 0xba, 0x2d, 0xf4, 0xa7, 0x70, 0x73, 0xcc, 0xa7, 0xb8, 0xa2, 0xe3, 0x11, 0x19, 0xe5, 0xb8, 0x67, + 0xb9, 0x11, 0xf4, 0x2c, 0x8e, 0x64, 0x6f, 0xaf, 0x12, 0xaf, 0xa8, 0xec, 0x1f, 0x41, 0x29, 0x98, + 0x88, 0x92, 0xbb, 0xb0, 0x89, 0x6d, 0x55, 0x1b, 0x28, 0x01, 0xc4, 0xa5, 0xc0, 0x3a, 0x79, 0x09, + 0xeb, 0x04, 0x6e, 0x84, 0x26, 0x9f, 0xe8, 0x3b, 0x90, 0xf3, 0xf2, 0x56, 0x21, 0xe2, 0xda, 0xe5, + 0x56, 0x78, 0x3c, 0x5a, 0xe9, 0x5f, 0x05, 0x4f, 0x64, 0xb0, 0x66, 0x54, 0x87, 0x34, 0xbb, 0xae, + 0x52, 0x25, 0x2d, 0x6d, 0x7f, 0x6b, 0xbe, 0xb4, 0x75, 0x93, 0xdd, 0x65, 0x65, 0xce, 0x2c, 0x3d, + 0x87, 0x34, 0xeb, 0x41, 0x79, 0xc8, 0x9c, 0x1d, 0x3d, 0x3d, 0x3a, 0xfe, 0xf4, 0x48, 0x8c, 0x21, + 0x80, 0xf4, 0x4e, 0xad, 0x56, 0x3f, 0x69, 0x8a, 0x02, 0xca, 0x41, 0x6a, 0x67, 0xf7, 0x58, 0x6e, + 0x8a, 0x71, 0xd2, 0x2d, 0xd7, 0x9f, 0xd4, 0x6b, 0x4d, 0x31, 0x81, 0x96, 0xa0, 0xc8, 0x9e, 0x95, + 0xfd, 0x63, 0xf9, 0xd9, 0x4e, 0x53, 0x4c, 0xfa, 0xba, 0x4e, 0xeb, 0x47, 0x7b, 0x75, 0x59, 0x4c, + 0x49, 0x7f, 0x00, 0xb7, 0x22, 0x13, 0x5d, 0xaf, 0x20, 0x24, 0xf8, 0x0a, 0x42, 0xd2, 0xdf, 0xc7, + 0xa1, 0x1a, 0x9d, 0xbd, 0xa2, 0x27, 0x63, 0x0b, 0xdf, 0x5e, 0x20, 0xf5, 0x1d, 0x5b, 0x3d, 0xba, + 0x03, 0x25, 0x13, 0x5f, 0x62, 0xbb, 0xd5, 0x65, 0xd9, 0x34, 0x8b, 0x4a, 0x45, 0xb9, 0xc8, 0x7b, + 0x29, 0x93, 0xc5, 0xc8, 0x7e, 0x88, 0x5b, 0xb6, 0xc2, 0x3c, 0x0d, 0x53, 0xb0, 0x1c, 0x21, 0x23, + 0xbd, 0xa7, 0xac, 0x53, 0xfa, 0xc1, 0x42, 0x7b, 0x99, 0x83, 0x94, 0x5c, 0x6f, 0xca, 0x9f, 0x89, + 0x09, 0x84, 0xa0, 0x44, 0x1f, 0x95, 0xd3, 0xa3, 0x9d, 0x93, 0xd3, 0xc6, 0x31, 0xd9, 0xcb, 0x65, + 0x28, 0x3b, 0x7b, 0xe9, 0x74, 0xa6, 0xa4, 0xff, 0x8c, 0xc3, 0xcd, 0x88, 0xdc, 0x1b, 0x3d, 0x00, + 0xb0, 0x47, 0x8a, 0x89, 0x5b, 0xba, 0xd9, 0x8e, 0x56, 0xb2, 0xe6, 0x48, 0xa6, 0x14, 0x72, 0xce, + 0xe6, 0x4f, 0xd6, 0x94, 0x3a, 0x22, 0xfa, 0x98, 0x0b, 0xa5, 0xf8, 0x07, 0x37, 0xab, 0x37, 0x43, + 0xca, 0x65, 0xb8, 0x45, 0x04, 0xd3, 0xbd, 0xa5, 0x82, 0x29, 0x3d, 0x7a, 0x16, 0xe6, 0x3f, 0xe6, + 0x2c, 0x38, 0x87, 0x78, 0x8e, 0xcf, 0xa2, 0x3d, 0x47, 0x6a, 0xde, 0xa4, 0x24, 0xdc, 0x75, 0x48, + 0xff, 0x98, 0xf0, 0x6f, 0x6c, 0xf0, 0xaa, 0x71, 0x0c, 0x69, 0xcb, 0x56, 0xed, 0xa1, 0xc5, 0x15, + 0xee, 0x3b, 0xf3, 0xde, 0x5b, 0x36, 0x9d, 0x87, 0x53, 0xca, 0x2e, 0x73, 0x31, 0xdf, 0xec, 0x37, + 0x75, 0xb0, 0xc1, 0xcd, 0x89, 0x36, 0x19, 0xcf, 0xe7, 0xc4, 0xa5, 0x47, 0x5e, 0x92, 0xe3, 0x83, + 0xe4, 0x27, 0xe1, 0x6e, 0x21, 0x0c, 0xee, 0xfe, 0x99, 0x00, 0xb7, 0xa7, 0xdc, 0xde, 0xd0, 0x27, + 0x63, 0xe7, 0xfc, 0x70, 0x91, 0xbb, 0xdf, 0x26, 0xeb, 0x0b, 0x9e, 0xb4, 0xf4, 0x21, 0x14, 0xfc, + 0xfd, 0xf3, 0x2d, 0xf2, 0xd7, 0x71, 0xcf, 0xe7, 0x07, 0x71, 0xf9, 0xd7, 0x96, 0xcd, 0x8d, 0xe9, + 0x59, 0x7c, 0x41, 0x3d, 0x0b, 0xcd, 0x0b, 0x12, 0xaf, 0x98, 0x17, 0x4c, 0xd1, 0xb6, 0xe4, 0xab, + 0x69, 0x5b, 0xc0, 0xe0, 0x52, 0xc1, 0x0b, 0xc3, 0x8a, 0xa7, 0x51, 0x3e, 0x58, 0xf1, 0x33, 0x00, + 0x1f, 0x7e, 0xba, 0x02, 0x29, 0x53, 0x1f, 0x0e, 0xda, 0x54, 0x2f, 0x52, 0x32, 0x6b, 0xa0, 0x8f, + 0x20, 0x45, 0xf4, 0xcb, 0xd9, 0xbd, 0x49, 0x57, 0x4b, 0xf4, 0xc3, 0x87, 0xca, 0x32, 0x6a, 0xe9, + 0xfb, 0x50, 0x0a, 0x82, 0xb6, 0xaf, 0x57, 0xbc, 0x06, 0x68, 0xf2, 0xe3, 0x85, 0x88, 0x21, 0xbe, + 0x1b, 0x1c, 0xe2, 0xad, 0xc8, 0xcf, 0x20, 0xc2, 0x87, 0xfa, 0x02, 0x52, 0x54, 0xdd, 0x48, 0xce, + 0x4b, 0xbf, 0x98, 0xe1, 0xb7, 0x5c, 0xf2, 0x8c, 0xbe, 0x0f, 0xa0, 0xda, 0xb6, 0xa9, 0x5d, 0x0c, + 0xbd, 0x01, 0xd6, 0xc3, 0xd5, 0x75, 0xc7, 0xa1, 0xdb, 0x7d, 0x83, 0xeb, 0xed, 0x8a, 0xc7, 0xea, + 0xd3, 0x5d, 0x9f, 0x40, 0xe9, 0x08, 0x4a, 0x41, 0x5e, 0xe7, 0x5e, 0x26, 0x84, 0xdc, 0xcb, 0xe2, + 0xfe, 0x7b, 0x99, 0x7b, 0xab, 0x4b, 0xb0, 0xcf, 0x82, 0x68, 0x43, 0xfa, 0x3f, 0x01, 0x0a, 0x7e, + 0x6d, 0x7f, 0xcd, 0x37, 0x80, 0x19, 0xd7, 0x9d, 0x5b, 0x13, 0x17, 0x80, 0x4c, 0x47, 0xb5, 0xce, + 0x7e, 0x9b, 0xf9, 0xff, 0x8f, 0x05, 0xc8, 0xba, 0x8b, 0x8f, 0x80, 0xe0, 0xbd, 0xbd, 0x8b, 0xfb, + 0x3f, 0xeb, 0x61, 0xb0, 0x7f, 0xc2, 0x85, 0xfd, 0x1f, 0xb9, 0x09, 0x5a, 0x14, 0xae, 0xed, 0xdf, + 0x69, 0xa7, 0xf8, 0xc1, 0xf3, 0xd1, 0xbf, 0xe3, 0xf3, 0x20, 0x99, 0x09, 0xfa, 0x23, 0x48, 0xab, + 0x2d, 0x17, 0xcd, 0x2f, 0x85, 0x60, 0x53, 0x0e, 0xe9, 0x66, 0x73, 0xb4, 0x43, 0x29, 0x65, 0xce, + 0xc1, 0x67, 0x15, 0x77, 0x66, 0x25, 0x3d, 0x26, 0x72, 0x19, 0x4d, 0xd0, 0x0d, 0x97, 0x00, 0xce, + 0x8e, 0x9e, 0x1d, 0xef, 0x1d, 0xec, 0x1f, 0xd4, 0xf7, 0x78, 0x8a, 0xb6, 0xb7, 0x57, 0xdf, 0x13, + 0xe3, 0x84, 0x4e, 0xae, 0x3f, 0x3b, 0x3e, 0xaf, 0xef, 0x89, 0x09, 0xa9, 0x06, 0x79, 0xa7, 0xc4, + 0xa4, 0xf6, 0x2d, 0x74, 0x1b, 0x72, 0x7d, 0x35, 0xf8, 0x01, 0x52, 0xb6, 0xaf, 0xf2, 0xcf, 0x8f, + 0x6e, 0x42, 0x86, 0xbc, 0xec, 0xa8, 0x96, 0x53, 0x11, 0xee, 0xab, 0xa3, 0xef, 0xa9, 0x96, 0xf4, + 0x1b, 0x01, 0xca, 0x63, 0x4e, 0x0b, 0x6d, 0x43, 0x8a, 0x81, 0x67, 0x51, 0xdf, 0xb5, 0xfb, 0x86, + 0x95, 0x19, 0x29, 0xfa, 0x18, 0xb2, 0x4e, 0x15, 0x2e, 0xec, 0xd6, 0xc4, 0xbc, 0xa3, 0x53, 0xc7, + 0xe1, 0xac, 0x2e, 0x07, 0x7a, 0x0c, 0x39, 0xd7, 0xfd, 0x46, 0x7f, 0x48, 0xe8, 0x3a, 0x6e, 0xce, + 0xef, 0xf1, 0xa0, 0x87, 0x1e, 0x86, 0x95, 0x9c, 0x04, 0xf2, 0x39, 0x3b, 0x23, 0xe0, 0xcc, 0x0e, + 0xbd, 0xf4, 0x08, 0x72, 0xae, 0x60, 0x54, 0x81, 0x8c, 0x53, 0x0b, 0x15, 0xb8, 0x5f, 0xe6, 0x35, + 0xd0, 0x15, 0x48, 0x19, 0xfa, 0xe7, 0xfc, 0xa3, 0xb0, 0x84, 0xcc, 0x1a, 0x52, 0x1b, 0xca, 0x63, + 0xe1, 0x04, 0x3d, 0x82, 0x8c, 0x31, 0xbc, 0x50, 0x1c, 0xdb, 0x1f, 0xdb, 0x3f, 0x07, 0x65, 0x19, + 0x5e, 0xf4, 0xb4, 0xd6, 0x53, 0x7c, 0xed, 0x68, 0x9b, 0x31, 0xbc, 0x78, 0xca, 0x5c, 0x04, 0x1b, + 0x25, 0xee, 0x1f, 0xe5, 0x0a, 0xb2, 0x8e, 0xc7, 0x43, 0x7f, 0xec, 0xdf, 0x2a, 0xe7, 0xa3, 0xce, + 0xc8, 0x10, 0xc7, 0xc5, 0xfb, 0x76, 0xea, 0x1e, 0x2c, 0x59, 0x5a, 0x67, 0xe0, 0xd4, 0xcd, 0xd9, + 0x41, 0xb3, 0x42, 0x58, 0x99, 0xbd, 0x38, 0x74, 0xa0, 0x38, 0x92, 0xa0, 0x88, 0xe3, 0x2e, 0xf7, + 0xb7, 0x39, 0x81, 0x90, 0x44, 0x2a, 0x11, 0x96, 0x48, 0xfd, 0x75, 0x1c, 0xf2, 0xbe, 0x6a, 0x3c, + 0xfa, 0x43, 0x9f, 0xff, 0x2f, 0x85, 0x64, 0x00, 0x3e, 0x5a, 0xef, 0xab, 0xc9, 0xe0, 0xc2, 0xe2, + 0x8b, 0x2f, 0x2c, 0xea, 0xe3, 0x07, 0xa7, 0xa8, 0x9f, 0x5c, 0xb8, 0xa8, 0xff, 0x01, 0x20, 0x5a, + 0x8e, 0x56, 0xae, 0x74, 0x5b, 0x1b, 0x74, 0x14, 0xa6, 0x1a, 0xcc, 0x5b, 0x8b, 0xf4, 0xcd, 0x39, + 0x7d, 0x71, 0x42, 0xb5, 0xe4, 0x2f, 0xe3, 0x90, 0x75, 0x2c, 0xec, 0xf7, 0x74, 0x0b, 0xfe, 0x4a, + 0x80, 0xac, 0x0b, 0x48, 0x2c, 0xfa, 0x59, 0xe9, 0x2a, 0xa4, 0xf9, 0x9d, 0x9b, 0x7d, 0x57, 0xca, + 0x5b, 0xa1, 0x1f, 0x70, 0x54, 0x21, 0xdb, 0xc7, 0xb6, 0x4a, 0xa3, 0x2f, 0x4b, 0xe0, 0xdc, 0xf6, + 0xbd, 0x87, 0x90, 0xf7, 0x7d, 0x92, 0x4b, 0x02, 0xf2, 0x51, 0xfd, 0x53, 0x31, 0x56, 0xcd, 0xfc, + 0xe4, 0xa7, 0x1b, 0x89, 0x23, 0xfc, 0x39, 0x71, 0x32, 0x72, 0xbd, 0xd6, 0xa8, 0xd7, 0x9e, 0x8a, + 0x42, 0x35, 0xff, 0x93, 0x9f, 0x6e, 0x64, 0x64, 0x4c, 0x0b, 0x92, 0xf7, 0x9e, 0x42, 0x79, 0xec, + 0x60, 0x82, 0xa1, 0x01, 0x41, 0x69, 0xef, 0xec, 0xe4, 0xf0, 0xa0, 0xb6, 0xd3, 0xac, 0x2b, 0xe7, + 0xc7, 0xcd, 0xba, 0x28, 0xa0, 0x9b, 0xb0, 0x7c, 0x78, 0xf0, 0xbd, 0x46, 0x53, 0xa9, 0x1d, 0x1e, + 0xd4, 0x8f, 0x9a, 0xca, 0x4e, 0xb3, 0xb9, 0x53, 0x7b, 0x2a, 0xc6, 0xb7, 0x7f, 0x93, 0x87, 0xf2, + 0xce, 0x6e, 0xed, 0x60, 0xc7, 0x30, 0x7a, 0x5a, 0x4b, 0xa5, 0x81, 0xa6, 0x06, 0x49, 0x5a, 0x43, + 0x98, 0xfa, 0xaf, 0x52, 0x75, 0x7a, 0x95, 0x19, 0xed, 0x43, 0x8a, 0x96, 0x17, 0xd0, 0xf4, 0x9f, + 0x97, 0xaa, 0x33, 0xca, 0xce, 0x64, 0x32, 0xd4, 0xa3, 0x4c, 0xfd, 0x9b, 0xa9, 0x3a, 0xbd, 0x0a, + 0x8d, 0x0e, 0x21, 0xe3, 0xa0, 0xbf, 0xb3, 0x7e, 0x31, 0xaa, 0xce, 0x2c, 0x0d, 0x93, 0xa5, 0x31, + 0x94, 0x7e, 0xfa, 0x8f, 0x4e, 0xd5, 0x19, 0xf5, 0x69, 0x74, 0x00, 0x69, 0x8e, 0xd3, 0xcd, 0xf8, + 0x77, 0xa9, 0x3a, 0xab, 0xe2, 0x8c, 0x64, 0xc8, 0x79, 0xf5, 0x8f, 0xd9, 0xbf, 0x6f, 0x55, 0xe7, + 0x28, 0xbd, 0xa3, 0xe7, 0x50, 0x0c, 0xe2, 0x81, 0xf3, 0xfd, 0x1f, 0x55, 0x9d, 0xb3, 0xb6, 0x4d, + 0xe4, 0x07, 0xc1, 0xc1, 0xf9, 0xfe, 0x97, 0xaa, 0xce, 0x59, 0xea, 0x46, 0x3f, 0x84, 0xa5, 0x49, + 0xf0, 0x6e, 0xfe, 0xdf, 0xa7, 0xaa, 0x0b, 0x14, 0xbf, 0x51, 0x1f, 0x50, 0x08, 0xe8, 0xb7, 0xc0, + 0xdf, 0x54, 0xd5, 0x45, 0x6a, 0xe1, 0xa8, 0x0d, 0xe5, 0x71, 0x20, 0x6d, 0xde, 0xbf, 0xab, 0xaa, + 0x73, 0xd7, 0xc5, 0xd9, 0x28, 0x41, 0x54, 0x69, 0xde, 0xbf, 0xad, 0xaa, 0x73, 0x97, 0xc9, 0xd1, + 0x19, 0x80, 0x0f, 0x15, 0x99, 0xe3, 0xef, 0xab, 0xea, 0x3c, 0x05, 0x73, 0x64, 0xc0, 0x72, 0x18, + 0x5c, 0xb2, 0xc8, 0xcf, 0x58, 0xd5, 0x85, 0xea, 0xe8, 0x44, 0x9f, 0x83, 0xc0, 0xc7, 0x7c, 0x3f, + 0x67, 0x55, 0xe7, 0x2c, 0xa8, 0x93, 0x8d, 0xf2, 0x2e, 0xfb, 0x68, 0x8e, 0x1f, 0x9c, 0xaa, 0xf3, + 0x54, 0xa3, 0x77, 0xeb, 0x3f, 0xff, 0x6a, 0x4d, 0xf8, 0xe5, 0x57, 0x6b, 0xc2, 0xff, 0x7c, 0xb5, + 0x26, 0x7c, 0xf9, 0xf5, 0x5a, 0xec, 0x97, 0x5f, 0xaf, 0xc5, 0xfe, 0xeb, 0xeb, 0xb5, 0xd8, 0x9f, + 0xbd, 0xdf, 0xd1, 0xec, 0xee, 0xf0, 0x62, 0xb3, 0xa5, 0xf7, 0xb7, 0xfc, 0x7f, 0xc9, 0x86, 0xfd, + 0xba, 0x7b, 0x91, 0xa6, 0x71, 0xfa, 0xc3, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x49, 0xed, 0xf9, + 0xc8, 0xda, 0x3b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -4958,6 +5062,7 @@ type ABCIApplicationClient interface { ExtendVote(ctx context.Context, in *RequestExtendVote, opts ...grpc.CallOption) (*ResponseExtendVote, error) VerifyVoteExtension(ctx context.Context, in *RequestVerifyVoteExtension, opts ...grpc.CallOption) (*ResponseVerifyVoteExtension, error) FinalizeBlock(ctx context.Context, in *RequestFinalizeBlock, opts ...grpc.CallOption) (*ResponseFinalizeBlock, error) + LoadLatest(ctx context.Context, in *RequestLoadLatest, opts ...grpc.CallOption) (*ResponseLoadLatest, error) } type aBCIApplicationClient struct { @@ -5112,6 +5217,15 @@ func (c *aBCIApplicationClient) FinalizeBlock(ctx context.Context, in *RequestFi return out, nil } +func (c *aBCIApplicationClient) LoadLatest(ctx context.Context, in *RequestLoadLatest, opts ...grpc.CallOption) (*ResponseLoadLatest, error) { + out := new(ResponseLoadLatest) + err := c.cc.Invoke(ctx, "/tendermint.abci.ABCIApplication/LoadLatest", 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) @@ -5130,6 +5244,7 @@ type ABCIApplicationServer interface { ExtendVote(context.Context, *RequestExtendVote) (*ResponseExtendVote, error) VerifyVoteExtension(context.Context, *RequestVerifyVoteExtension) (*ResponseVerifyVoteExtension, error) FinalizeBlock(context.Context, *RequestFinalizeBlock) (*ResponseFinalizeBlock, error) + LoadLatest(context.Context, *RequestLoadLatest) (*ResponseLoadLatest, error) } // UnimplementedABCIApplicationServer can be embedded to have forward compatible implementations. @@ -5184,6 +5299,9 @@ func (*UnimplementedABCIApplicationServer) VerifyVoteExtension(ctx context.Conte func (*UnimplementedABCIApplicationServer) FinalizeBlock(ctx context.Context, req *RequestFinalizeBlock) (*ResponseFinalizeBlock, error) { return nil, status.Errorf(codes.Unimplemented, "method FinalizeBlock not implemented") } +func (*UnimplementedABCIApplicationServer) LoadLatest(ctx context.Context, req *RequestLoadLatest) (*ResponseLoadLatest, error) { + return nil, status.Errorf(codes.Unimplemented, "method LoadLatest not implemented") +} func RegisterABCIApplicationServer(s *grpc.Server, srv ABCIApplicationServer) { s.RegisterService(&_ABCIApplication_serviceDesc, srv) @@ -5477,6 +5595,24 @@ func _ABCIApplication_FinalizeBlock_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _ABCIApplication_LoadLatest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestLoadLatest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).LoadLatest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/tendermint.abci.ABCIApplication/LoadLatest", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).LoadLatest(ctx, req.(*RequestLoadLatest)) + } + return interceptor(ctx, in, info, handler) +} + var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ ServiceName: "tendermint.abci.ABCIApplication", HandlerType: (*ABCIApplicationServer)(nil), @@ -5545,6 +5681,10 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ MethodName: "FinalizeBlock", Handler: _ABCIApplication_FinalizeBlock_Handler, }, + { + MethodName: "LoadLatest", + Handler: _ABCIApplication_LoadLatest_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "tendermint/abci/types.proto", @@ -5995,6 +6135,29 @@ func (m *Request_EndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } +func (m *Request_LoadLatest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_LoadLatest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LoadLatest != nil { + { + size, err := m.LoadLatest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xba + } + return len(dAtA) - i, nil +} func (m *RequestEcho) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -6160,12 +6323,12 @@ func (m *RequestInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - n21, err21 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err21 != nil { - return 0, err21 + 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 -= n21 - i = encodeVarintTypes(dAtA, i, uint64(n21)) + i -= n22 + i = encodeVarintTypes(dAtA, i, uint64(n22)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil @@ -6534,12 +6697,12 @@ func (m *RequestPrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) i-- dAtA[i] = 0x3a } - n23, err23 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err23 != nil { - return 0, err23 + 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 -= n23 - i = encodeVarintTypes(dAtA, i, uint64(n23)) + i -= n24 + i = encodeVarintTypes(dAtA, i, uint64(n24)) i-- dAtA[i] = 0x32 if m.Height != 0 { @@ -6698,12 +6861,12 @@ func (m *RequestProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) i-- dAtA[i] = 0x3a } - n25, err25 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err25 != nil { - return 0, err25 + n26, err26 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err26 != nil { + return 0, err26 } - i -= n25 - i = encodeVarintTypes(dAtA, i, uint64(n25)) + i -= n26 + i = encodeVarintTypes(dAtA, i, uint64(n26)) i-- dAtA[i] = 0x32 if m.Height != 0 { @@ -6948,12 +7111,12 @@ func (m *RequestFinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x3a } - n27, err27 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err27 != nil { - return 0, err27 + n28, err28 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err28 != nil { + return 0, err28 } - i -= n27 - i = encodeVarintTypes(dAtA, i, uint64(n27)) + i -= n28 + i = encodeVarintTypes(dAtA, i, uint64(n28)) i-- dAtA[i] = 0x32 if m.Height != 0 { @@ -7136,6 +7299,29 @@ func (m *RequestEndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *RequestLoadLatest) 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 *RequestLoadLatest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestLoadLatest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func (m *Response) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7604,6 +7790,29 @@ func (m *Response_EndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } +func (m *Response_LoadLatest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_LoadLatest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LoadLatest != nil { + { + size, err := m.LoadLatest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xc2 + } + return len(dAtA) - i, nil +} func (m *ResponseException) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -8281,20 +8490,20 @@ func (m *ResponseApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, err } } if len(m.RefetchChunks) > 0 { - dAtA55 := make([]byte, len(m.RefetchChunks)*10) - var j54 int + dAtA57 := make([]byte, len(m.RefetchChunks)*10) + var j56 int for _, num := range m.RefetchChunks { for num >= 1<<7 { - dAtA55[j54] = uint8(uint64(num)&0x7f | 0x80) + dAtA57[j56] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j54++ + j56++ } - dAtA55[j54] = uint8(num) - j54++ + dAtA57[j56] = uint8(num) + j56++ } - i -= j54 - copy(dAtA[i:], dAtA55[:j54]) - i = encodeVarintTypes(dAtA, i, uint64(j54)) + i -= j56 + copy(dAtA[i:], dAtA57[:j56]) + i = encodeVarintTypes(dAtA, i, uint64(j56)) i-- dAtA[i] = 0x12 } @@ -8607,6 +8816,29 @@ func (m *ResponseFinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ResponseLoadLatest) 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 *ResponseLoadLatest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseLoadLatest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func (m *CommitInfo) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -9284,12 +9516,12 @@ func (m *Misbehavior) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x28 } - n67, err67 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err67 != nil { - return 0, err67 + n69, err69 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err69 != nil { + return 0, err69 } - i -= n67 - i = encodeVarintTypes(dAtA, i, uint64(n67)) + i -= n69 + i = encodeVarintTypes(dAtA, i, uint64(n69)) i-- dAtA[i] = 0x22 if m.Height != 0 { @@ -9340,12 +9572,12 @@ func (m *Evidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x28 } - n69, err69 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err69 != nil { - return 0, err69 + n71, err71 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err71 != nil { + return 0, err71 } - i -= n69 - i = encodeVarintTypes(dAtA, i, uint64(n69)) + i -= n71 + i = encodeVarintTypes(dAtA, i, uint64(n71)) i-- dAtA[i] = 0x22 if m.Height != 0 { @@ -9674,6 +9906,18 @@ func (m *Request_EndBlock) Size() (n int) { } return n } +func (m *Request_LoadLatest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LoadLatest != nil { + l = m.LoadLatest.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} func (m *RequestEcho) Size() (n int) { if m == nil { return 0 @@ -10190,6 +10434,15 @@ func (m *RequestEndBlock) Size() (n int) { return n } +func (m *RequestLoadLatest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func (m *Response) Size() (n int) { if m == nil { return 0 @@ -10442,6 +10695,18 @@ func (m *Response_EndBlock) Size() (n int) { } return n } +func (m *Response_LoadLatest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LoadLatest != nil { + l = m.LoadLatest.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} func (m *ResponseException) Size() (n int) { if m == nil { return 0 @@ -10887,6 +11152,15 @@ func (m *ResponseFinalizeBlock) Size() (n int) { return n } +func (m *ResponseLoadLatest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func (m *CommitInfo) Size() (n int) { if m == nil { return 0 @@ -11929,6 +12203,41 @@ func (m *Request) Unmarshal(dAtA []byte) error { } m.Value = &Request_EndBlock{v} iNdEx = postIndex + case 23: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LoadLatest", 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 := &RequestLoadLatest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_LoadLatest{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -15692,6 +16001,56 @@ func (m *RequestEndBlock) Unmarshal(dAtA []byte) error { } return nil } +func (m *RequestLoadLatest) 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: RequestLoadLatest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestLoadLatest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 @@ -16421,6 +16780,41 @@ func (m *Response) Unmarshal(dAtA []byte) error { } m.Value = &Response_EndBlock{v} iNdEx = postIndex + case 24: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LoadLatest", 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 := &ResponseLoadLatest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_LoadLatest{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -19336,6 +19730,56 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { } return nil } +func (m *ResponseLoadLatest) 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: ResponseLoadLatest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseLoadLatest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *CommitInfo) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/cmd/tendermint/commands/snapshot.go b/cmd/tendermint/commands/snapshot.go new file mode 100644 index 000000000..5c95e9a7b --- /dev/null +++ b/cmd/tendermint/commands/snapshot.go @@ -0,0 +1,27 @@ +package commands + +import ( + "strconv" + + "github.com/spf13/cobra" + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/internal/dbsync" +) + +func MakeSnapshotCommand(confGetter func(*cobra.Command) (*config.Config, error)) *cobra.Command { + return &cobra.Command{ + Use: "snapshot [height]", + Short: "Take DBSync snapshot for given height", + RunE: func(cmd *cobra.Command, args []string) error { + conf, err := confGetter(cmd) + if err != nil { + return err + } + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + return dbsync.Snapshot(height, *conf.DBSync, conf.BaseConfig) + }, + } +} diff --git a/config/config.go b/config/config.go index 6808f8e0c..b18e961c1 100644 --- a/config/config.go +++ b/config/config.go @@ -73,6 +73,7 @@ type Config struct { Instrumentation *InstrumentationConfig `mapstructure:"instrumentation"` PrivValidator *PrivValidatorConfig `mapstructure:"priv-validator"` SelfRemediation *SelfRemediationConfig `mapstructure:"self-remediation"` + DBSync *DBSyncConfig `mapstructure:"db-sync"` } // DefaultConfig returns a default configuration for a Tendermint node @@ -88,6 +89,7 @@ func DefaultConfig() *Config { Instrumentation: DefaultInstrumentationConfig(), PrivValidator: DefaultPrivValidatorConfig(), SelfRemediation: DefaultSelfRemediationConfig(), + DBSync: DefaultDBSyncConfig(), } } @@ -111,6 +113,7 @@ func TestConfig() *Config { Instrumentation: TestInstrumentationConfig(), PrivValidator: DefaultPrivValidatorConfig(), SelfRemediation: DefaultSelfRemediationConfig(), + DBSync: DefaultDBSyncConfig(), } } @@ -1066,7 +1069,7 @@ func DefaultConsensusConfig() *ConsensusConfig { PeerQueryMaj23SleepDuration: 2000 * time.Millisecond, DoubleSignCheckHeight: int64(0), // Sei Configurations - GossipTransactionKeyOnly: true, + GossipTransactionKeyOnly: true, } } @@ -1257,6 +1260,45 @@ func (cfg *InstrumentationConfig) ValidateBasic() error { return nil } +type DBSyncConfig struct { + Enable bool `mapstructure:"db-sync-enable"` + SnapshotInterval int `mapstructure:"snapshot-interval"` + SnapshotDirectory string `mapstructure:"snapshot-directory"` + SnapshotWorkerCount int `mapstructure:"snapshot-worker-count"` + TimeoutInSeconds int `mapstructure:"timeout-in-seconds"` + NoFileSleepInSeconds int `mapstructure:"no-file-sleep-in-seconds"` + FileWorkerCount int `mapstructure:"file-worker-count"` + FileWorkerTimeout int `mapstructure:"file-worker-timeout"` + TrustHeight int64 `mapstructure:"trust-height"` + TrustHash string `mapstructure:"trust-hash"` + TrustPeriod time.Duration `mapstructure:"trust-period"` +} + +func DefaultDBSyncConfig() *DBSyncConfig { + return &DBSyncConfig{ + Enable: false, + SnapshotInterval: 0, + SnapshotDirectory: "", + SnapshotWorkerCount: 16, + TimeoutInSeconds: 1200, + NoFileSleepInSeconds: 1, + FileWorkerCount: 32, + FileWorkerTimeout: 30, + TrustHeight: 0, + TrustHash: "", + TrustPeriod: time.Duration(86400) * time.Second, + } +} + +func (cfg *DBSyncConfig) TrustHashBytes() []byte { + // validated in ValidateBasic, so we can safely panic here + bytes, err := hex.DecodeString(cfg.TrustHash) + if err != nil { + panic(err) + } + return bytes +} + //----------------------------------------------------------------------------- // Utils @@ -1283,7 +1325,6 @@ func getDefaultMoniker() string { return moniker } - //----------------------------------------------------------------------------- // SelfRemediationConfig @@ -1312,10 +1353,10 @@ type SelfRemediationConfig struct { // reporting. func DefaultSelfRemediationConfig() *SelfRemediationConfig { return &SelfRemediationConfig{ - P2pNoPeersRestarWindowSeconds: 0, + P2pNoPeersRestarWindowSeconds: 0, StatesyncNoPeersRestartWindowSeconds: 0, - BlocksBehindThreshold: 0, - BlocksBehindCheckIntervalSeconds: 30, + BlocksBehindThreshold: 0, + BlocksBehindCheckIntervalSeconds: 30, // 30 minutes RestartCooldownSeconds: 1800, } @@ -1330,4 +1371,3 @@ func TestSelfRemediationConfig() *SelfRemediationConfig { func (cfg *SelfRemediationConfig) ValidateBasic() error { return nil } - diff --git a/config/toml.go b/config/toml.go index 22a15a823..066126e39 100644 --- a/config/toml.go +++ b/config/toml.go @@ -584,6 +584,18 @@ blocks-behind-check-interval = {{ .SelfRemediation.BlocksBehindCheckIntervalSeco # Cooldown between each restart restart-cooldown-seconds = {{ .SelfRemediation.RestartCooldownSeconds }} +[db-sync] +db-sync-enable = "{{ .DBSync.Enable }}" +snapshot-interval = "{{ .DBSync.SnapshotInterval }}" +snapshot-directory = "{{ .DBSync.SnapshotDirectory }}" +snapshot-worker-count = "{{ .DBSync.SnapshotWorkerCount }}" +timeout-in-seconds = "{{ .DBSync.TimeoutInSeconds }}" +no-file-sleep-in-seconds = "{{ .DBSync.NoFileSleepInSeconds }}" +file-worker-count = "{{ .DBSync.FileWorkerCount }}" +file-worker-timeout = "{{ .DBSync.FileWorkerTimeout }}" +trust-height = "{{ .DBSync.TrustHeight }}" +trust-hash = "{{ .DBSync.TrustHash }}" +trust-period = "{{ .DBSync.TrustPeriod }}" ` /****** these are for test settings ***********/ diff --git a/internal/consensus/reactor_test.go b/internal/consensus/reactor_test.go index 6245eae3f..f54780784 100644 --- a/internal/consensus/reactor_test.go +++ b/internal/consensus/reactor_test.go @@ -232,7 +232,7 @@ func waitForAndValidateBlockWithTx( ) { t.Helper() - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() fn := func(j int) { diff --git a/internal/dbsync/reactor.go b/internal/dbsync/reactor.go new file mode 100644 index 000000000..930992f3b --- /dev/null +++ b/internal/dbsync/reactor.go @@ -0,0 +1,687 @@ +package dbsync + +import ( + "context" + "errors" + "fmt" + "os" + "path/filepath" + "strconv" + "sync" + "time" + + "github.com/gogo/protobuf/proto" + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/internal/eventbus" + "github.com/tendermint/tendermint/internal/p2p" + sm "github.com/tendermint/tendermint/internal/state" + "github.com/tendermint/tendermint/internal/store" + "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/libs/service" + "github.com/tendermint/tendermint/light" + "github.com/tendermint/tendermint/light/provider" + dstypes "github.com/tendermint/tendermint/proto/tendermint/dbsync" + "github.com/tendermint/tendermint/types" +) + +const ( + // MetadataChannel exchanges DB metadata + MetadataChannel = p2p.ChannelID(0x70) + + // FileChannel exchanges file data + FileChannel = p2p.ChannelID(0x71) + + LightBlockChannel = p2p.ChannelID(0x72) + + ParamsChannel = p2p.ChannelID(0x73) + + metadataMsgSize = int(4e6) // ~4MB + + fileMsgSize = int(16e6) // ~16MB + + lightBlockMsgSize = int(1e7) // ~1MB + + paramMsgSize = int(1e5) // ~100kb + + MetadataHeightFilename = "LATEST_HEIGHT" + HeightSubdirectoryPrefix = "snapshot_" + MetadataFilename = "METADATA" +) + +func GetMetadataChannelDescriptor() *p2p.ChannelDescriptor { + return &p2p.ChannelDescriptor{ + ID: MetadataChannel, + MessageType: new(dstypes.Message), + Priority: 6, + SendQueueCapacity: 10, + RecvMessageCapacity: metadataMsgSize, + RecvBufferCapacity: 128, + Name: "metadata", + } +} + +func GetFileChannelDescriptor() *p2p.ChannelDescriptor { + return &p2p.ChannelDescriptor{ + ID: FileChannel, + Priority: 3, + MessageType: new(dstypes.Message), + SendQueueCapacity: 4, + RecvMessageCapacity: fileMsgSize, + RecvBufferCapacity: 128, + Name: "chunk", + } +} + +func GetLightBlockChannelDescriptor() *p2p.ChannelDescriptor { + return &p2p.ChannelDescriptor{ + ID: LightBlockChannel, + MessageType: new(dstypes.Message), + Priority: 5, + SendQueueCapacity: 10, + RecvMessageCapacity: lightBlockMsgSize, + RecvBufferCapacity: 128, + Name: "light-block", + } +} + +func GetParamsChannelDescriptor() *p2p.ChannelDescriptor { + return &p2p.ChannelDescriptor{ + ID: ParamsChannel, + MessageType: new(dstypes.Message), + Priority: 2, + SendQueueCapacity: 10, + RecvMessageCapacity: paramMsgSize, + RecvBufferCapacity: 128, + Name: "params", + } +} + +type Reactor struct { + service.BaseService + logger log.Logger + + // Dispatcher is used to multiplex light block requests and responses over multiple + // peers used by the p2p state provider and in reverse sync. + dispatcher *light.Dispatcher + peers *light.PeerList + stateStore sm.Store + blockStore *store.BlockStore + initialHeight int64 + + chainID string + config config.DBSyncConfig + providers map[types.NodeID]*light.BlockProvider + stateProvider light.StateProvider + + metadataChannel *p2p.Channel + fileChannel *p2p.Channel + lightBlockChannel *p2p.Channel + paramsChannel *p2p.Channel + + peerEvents p2p.PeerEventSubscriber + eventBus *eventbus.EventBus + + syncer *Syncer + + mtx sync.RWMutex + + postSyncHook func(context.Context, sm.State) error +} + +func NewReactor( + logger log.Logger, + config config.DBSyncConfig, + baseConfig config.BaseConfig, + peerEvents p2p.PeerEventSubscriber, + stateStore sm.Store, + blockStore *store.BlockStore, + initialHeight int64, + chainID string, + eventBus *eventbus.EventBus, + postSyncHook func(context.Context, sm.State) error, +) *Reactor { + reactor := &Reactor{ + logger: logger, + peerEvents: peerEvents, + peers: light.NewPeerList(), + stateStore: stateStore, + blockStore: blockStore, + initialHeight: initialHeight, + chainID: chainID, + providers: make(map[types.NodeID]*light.BlockProvider), + eventBus: eventBus, + config: config, + postSyncHook: postSyncHook, + } + syncer := NewSyncer(logger, config, baseConfig, reactor.requestMetadata, reactor.requestFile, reactor.commitState, reactor.postSync, defaultResetDirFn) + reactor.syncer = syncer + + reactor.BaseService = *service.NewBaseService(logger, "DBSync", reactor) + return reactor +} + +func (r *Reactor) SetMetadataChannel(ch *p2p.Channel) { + r.metadataChannel = ch +} + +func (r *Reactor) SetFileChannel(ch *p2p.Channel) { + r.fileChannel = ch +} + +func (r *Reactor) SetLightBlockChannel(ch *p2p.Channel) { + r.lightBlockChannel = ch +} + +func (r *Reactor) SetParamsChannel(ch *p2p.Channel) { + r.paramsChannel = ch +} + +func (r *Reactor) OnStart(ctx context.Context) error { + go r.processPeerUpdates(ctx, r.peerEvents(ctx)) + r.dispatcher = light.NewDispatcher(r.lightBlockChannel, func(height uint64) proto.Message { + return &dstypes.LightBlockRequest{ + Height: height, + } + }) + go r.processMetadataCh(ctx, r.metadataChannel) + go r.processFileCh(ctx, r.fileChannel) + go r.processLightBlockCh(ctx, r.lightBlockChannel) + go r.processParamsCh(ctx, r.paramsChannel) + if r.config.Enable { + to := light.TrustOptions{ + Period: r.config.TrustPeriod, + Height: r.config.TrustHeight, + Hash: r.config.TrustHashBytes(), + } + r.logger.Info("begin waiting for at least 2 peers") + if err := r.waitForEnoughPeers(ctx, 2); err != nil { + return err + } + r.logger.Info("enough peers discovered") + + peers := r.peers.All() + providers := make([]provider.Provider, len(peers)) + for idx, p := range peers { + providers[idx] = light.NewBlockProvider(p, r.chainID, r.dispatcher) + } + + stateProvider, err := light.NewP2PStateProvider(ctx, r.chainID, r.initialHeight, providers, to, r.paramsChannel, r.logger.With("module", "stateprovider"), func(height uint64) proto.Message { + return &dstypes.ParamsRequest{ + Height: height, + } + }) + if err != nil { + return fmt.Errorf("failed to initialize P2P state provider: %w", err) + } + r.stateProvider = stateProvider + } + + go r.syncer.Process(ctx) + return nil +} + +func (r *Reactor) OnStop() { + // tell the dispatcher to stop sending any more requests + r.dispatcher.Close() + // clear up half-populated directories + r.syncer.Stop() +} + +func (r *Reactor) handleMetadataRequest(ctx context.Context, req *dstypes.MetadataRequest, from types.NodeID) (err error) { + responded := false + defer func() { + if err != nil { + r.logger.Debug(fmt.Sprintf("handle metadata request encountered error %s", err)) + } + if !responded { + err = r.metadataChannel.Send(ctx, p2p.Envelope{ + To: from, + Message: &dstypes.MetadataResponse{ + Height: 0, + Hash: []byte{}, + Filenames: []string{}, + }, + }) + } + }() + + if r.config.SnapshotDirectory == "" { + return + } + + metadataHeightFile := filepath.Join(r.config.SnapshotDirectory, MetadataHeightFilename) + heightData, err := os.ReadFile(metadataHeightFile) + if err != nil { + err = fmt.Errorf("cannot read height file %s due to %s", metadataHeightFile, err) + return + } + height, err := strconv.ParseUint(string(heightData), 10, 64) + if err != nil { + err = fmt.Errorf("height data should be an integer but got %s", heightData) + return + } + heightSubdirectory := filepath.Join(r.config.SnapshotDirectory, fmt.Sprintf("%s%d", HeightSubdirectoryPrefix, height)) + metadataFilename := filepath.Join(heightSubdirectory, MetadataFilename) + data, err := os.ReadFile(metadataFilename) + if err != nil { + err = fmt.Errorf("cannot read metadata file %s due to %s", metadataFilename, err) + return + } + msg := dstypes.MetadataResponse{} + err = msg.Unmarshal(data) + if err != nil { + err = fmt.Errorf("cannot unmarshal metadata file %s due to %s", metadataFilename, err) + return + } + err = r.metadataChannel.Send(ctx, p2p.Envelope{ + To: from, + Message: &msg, + }) + responded = true + return +} + +func (r *Reactor) handleMetadataMessage(ctx context.Context, envelope *p2p.Envelope) error { + logger := r.logger.With("peer", envelope.From) + + switch msg := envelope.Message.(type) { + case *dstypes.MetadataRequest: + return r.handleMetadataRequest(ctx, msg, envelope.From) + + case *dstypes.MetadataResponse: + if msg.Height == 0 { + return nil + } + logger.Info("received metadata", "height", msg.Height, "size", len(msg.Filenames)) + r.syncer.SetMetadata(ctx, envelope.From, msg) + + default: + return fmt.Errorf("received unknown message: %T", msg) + } + + return nil +} + +func (r *Reactor) handleFileRequest(ctx context.Context, req *dstypes.FileRequest, from types.NodeID) (err error) { + responded := false + defer func() { + if err != nil { + r.logger.Debug(fmt.Sprintf("handle file request encountered error %s", err)) + } + if !responded { + err = r.fileChannel.Send(ctx, p2p.Envelope{ + To: from, + Message: &dstypes.FileResponse{ + Height: 0, + Filename: "", + Data: []byte{}, + }, + }) + } + }() + + if r.config.SnapshotDirectory == "" { + return + } + + heightSubdirectory := filepath.Join(r.config.SnapshotDirectory, fmt.Sprintf("%s%d", HeightSubdirectoryPrefix, req.Height)) + filename := filepath.Join(heightSubdirectory, req.Filename) + data, err := os.ReadFile(filename) + if err != nil { + err = fmt.Errorf("cannot read file %s due to %s", filename, err) + return + } + err = r.fileChannel.Send(ctx, p2p.Envelope{ + To: from, + Message: &dstypes.FileResponse{ + Height: req.Height, + Filename: req.Filename, + Data: data, + }, + }) + responded = true + return +} + +func (r *Reactor) handleFileMessage(ctx context.Context, envelope *p2p.Envelope) error { + switch msg := envelope.Message.(type) { + case *dstypes.FileRequest: + return r.handleFileRequest(ctx, msg, envelope.From) + + case *dstypes.FileResponse: + if len(msg.Data) == 0 { + return nil + } + r.syncer.PushFile(msg) + + default: + return fmt.Errorf("received unknown message: %T", msg) + } + + return nil +} + +func (r *Reactor) handleLightBlockMessage(ctx context.Context, envelope *p2p.Envelope) error { + switch msg := envelope.Message.(type) { + case *dstypes.LightBlockRequest: + lb, err := r.fetchLightBlock(msg.Height) + if err != nil { + r.logger.Error("failed to retrieve light block", "err", err, "height", msg.Height) + return err + } + if lb == nil { + if err := r.lightBlockChannel.Send(ctx, p2p.Envelope{ + To: envelope.From, + Message: &dstypes.LightBlockResponse{ + LightBlock: nil, + }, + }); err != nil { + return err + } + return nil + } + + lbproto, err := lb.ToProto() + if err != nil { + r.logger.Error("marshaling light block to proto", "err", err) + return nil + } + + // NOTE: If we don't have the light block we will send a nil light block + // back to the requested node, indicating that we don't have it. + if err := r.lightBlockChannel.Send(ctx, p2p.Envelope{ + To: envelope.From, + Message: &dstypes.LightBlockResponse{ + LightBlock: lbproto, + }, + }); err != nil { + return err + } + case *dstypes.LightBlockResponse: + var height int64 + if msg.LightBlock != nil { + height = msg.LightBlock.SignedHeader.Header.Height + } + if err := r.dispatcher.Respond(ctx, msg.LightBlock, envelope.From); err != nil { + if errors.Is(err, context.Canceled) { + return err + } + r.logger.Error("error processing light block response", "err", err, "height", height) + } + + default: + return fmt.Errorf("received unknown message: %T", msg) + } + + return nil +} + +func (r *Reactor) handleParamsMessage(ctx context.Context, envelope *p2p.Envelope) error { + switch msg := envelope.Message.(type) { + case *dstypes.ParamsRequest: + cp, err := r.stateStore.LoadConsensusParams(int64(msg.Height)) + if err != nil { + r.logger.Error("failed to fetch requested consensus params", "err", err, "height", msg.Height) + return nil + } + + cpproto := cp.ToProto() + if err := r.paramsChannel.Send(ctx, p2p.Envelope{ + To: envelope.From, + Message: &dstypes.ParamsResponse{ + Height: msg.Height, + ConsensusParams: cpproto, + }, + }); err != nil { + return err + } + case *dstypes.ParamsResponse: + r.mtx.RLock() + defer r.mtx.RUnlock() + + cp := types.ConsensusParamsFromProto(msg.ConsensusParams) + + if sp, ok := r.stateProvider.(*light.StateProviderP2P); ok { + select { + case sp.ParamsRecvCh() <- cp: + case <-ctx.Done(): + return ctx.Err() + case <-time.After(time.Second): + r.logger.Error("failed to send consensus params, stateprovider not ready for response") + } + } else { + r.logger.Debug("received unexpected params response; using RPC state provider", "peer", envelope.From) + } + + default: + return fmt.Errorf("received unknown message: %T", msg) + } + + return nil +} + +func (r *Reactor) processPeerUpdate(ctx context.Context, peerUpdate p2p.PeerUpdate) { + r.logger.Debug("received peer update", "peer", peerUpdate.NodeID, "status", peerUpdate.Status) + + switch peerUpdate.Status { + case p2p.PeerStatusUp: + if peerUpdate.Channels.Contains(MetadataChannel) && peerUpdate.Channels.Contains(FileChannel) { + r.peers.Append(peerUpdate.NodeID) + } else { + r.logger.Error("could not use peer for dbsync (removing)", "peer", peerUpdate.NodeID) + r.peers.Remove(peerUpdate.NodeID) + } + case p2p.PeerStatusDown: + r.peers.Remove(peerUpdate.NodeID) + } + + r.mtx.Lock() + defer r.mtx.Unlock() + + switch peerUpdate.Status { + case p2p.PeerStatusUp: + newProvider := light.NewBlockProvider(peerUpdate.NodeID, r.chainID, r.dispatcher) + + r.providers[peerUpdate.NodeID] = newProvider + if sp, ok := r.stateProvider.(*light.StateProviderP2P); ok { + // we do this in a separate routine to not block whilst waiting for the light client to finish + // whatever call it's currently executing + go sp.AddProvider(newProvider) + } + + case p2p.PeerStatusDown: + delete(r.providers, peerUpdate.NodeID) + } + r.logger.Debug("processed peer update", "peer", peerUpdate.NodeID, "status", peerUpdate.Status) +} + +func (r *Reactor) processPeerUpdates(ctx context.Context, peerUpdates *p2p.PeerUpdates) { + for { + select { + case <-ctx.Done(): + return + case peerUpdate := <-peerUpdates.Updates(): + r.processPeerUpdate(ctx, peerUpdate) + } + } +} + +func (r *Reactor) processMetadataCh(ctx context.Context, ch *p2p.Channel) { + iter := ch.Receive(ctx) + for iter.Next(ctx) { + envelope := iter.Envelope() + if err := r.handleMetadataMessage(ctx, envelope); err != nil { + r.logger.Error("failed to process message", "ch_id", envelope.ChannelID, "envelope", envelope, "err", err) + if serr := ch.SendError(ctx, p2p.PeerError{ + NodeID: envelope.From, + Err: err, + }); serr != nil { + return + } + } + } +} + +func (r *Reactor) processFileCh(ctx context.Context, ch *p2p.Channel) { + iter := ch.Receive(ctx) + for iter.Next(ctx) { + envelope := iter.Envelope() + if err := r.handleFileMessage(ctx, envelope); err != nil { + r.logger.Error("failed to process message", "ch_id", envelope.ChannelID, "envelope", envelope, "err", err) + if serr := ch.SendError(ctx, p2p.PeerError{ + NodeID: envelope.From, + Err: err, + }); serr != nil { + return + } + } + } +} + +func (r *Reactor) processLightBlockCh(ctx context.Context, ch *p2p.Channel) { + iter := ch.Receive(ctx) + for iter.Next(ctx) { + envelope := iter.Envelope() + if err := r.handleLightBlockMessage(ctx, envelope); err != nil { + r.logger.Error("failed to process message", "ch_id", envelope.ChannelID, "envelope", envelope, "err", err) + if serr := ch.SendError(ctx, p2p.PeerError{ + NodeID: envelope.From, + Err: err, + }); serr != nil { + return + } + } + } +} + +func (r *Reactor) processParamsCh(ctx context.Context, ch *p2p.Channel) { + iter := ch.Receive(ctx) + for iter.Next(ctx) { + envelope := iter.Envelope() + if err := r.handleParamsMessage(ctx, envelope); err != nil { + r.logger.Error("failed to process message", "ch_id", envelope.ChannelID, "envelope", envelope, "err", err) + if serr := ch.SendError(ctx, p2p.PeerError{ + NodeID: envelope.From, + Err: err, + }); serr != nil { + return + } + } + } +} + +func (r *Reactor) requestMetadata(ctx context.Context) error { + return r.metadataChannel.Send(ctx, p2p.Envelope{ + Broadcast: true, + Message: &dstypes.MetadataRequest{}, + }) +} + +func (r *Reactor) requestFile(ctx context.Context, peer types.NodeID, height uint64, filename string) error { + return r.fileChannel.Send(ctx, p2p.Envelope{ + To: peer, + Message: &dstypes.FileRequest{ + Height: height, + Filename: filename, + }, + }) +} + +func (r *Reactor) fetchLightBlock(height uint64) (*types.LightBlock, error) { + h := int64(height) + + blockMeta := r.blockStore.LoadBlockMeta(h) + if blockMeta == nil { + return nil, nil + } + + commit := r.blockStore.LoadBlockCommit(h) + if commit == nil { + return nil, nil + } + + vals, err := r.stateStore.LoadValidators(h) + if err != nil { + return nil, err + } + if vals == nil { + return nil, nil + } + + return &types.LightBlock{ + SignedHeader: &types.SignedHeader{ + Header: &blockMeta.Header, + Commit: commit, + }, + ValidatorSet: vals, + }, nil +} + +func (r *Reactor) waitForEnoughPeers(ctx context.Context, numPeers int) error { + startAt := time.Now() + t := time.NewTicker(100 * time.Millisecond) + defer t.Stop() + logT := time.NewTicker(time.Minute) + defer logT.Stop() + var iter int + for r.peers.Len() < numPeers { + iter++ + select { + case <-ctx.Done(): + return fmt.Errorf("operation canceled while waiting for peers after %.2fs [%d/%d]", + time.Since(startAt).Seconds(), r.peers.Len(), numPeers) + case <-t.C: + continue + case <-logT.C: + r.logger.Info("waiting for sufficient peers to start statesync", + "duration", time.Since(startAt).String(), + "target", numPeers, + "peers", r.peers.Len(), + "iters", iter, + ) + continue + } + } + return nil +} + +func (r *Reactor) commitState(ctx context.Context, height uint64) (sm.State, *types.Commit, error) { + appHash, err := r.stateProvider.AppHash(ctx, height) + if err != nil { + r.logger.Error(fmt.Sprintf("error getting apphash for %d due to %s", height, err)) + return sm.State{}, nil, err + } + r.logger.Info(fmt.Sprintf("got apphash %X for %d", appHash, height)) + state, err := r.stateProvider.State(ctx, height) + if err != nil { + r.logger.Error(fmt.Sprintf("error getting state for %d due to %s", height, err)) + return sm.State{}, nil, err + } + commit, err := r.stateProvider.Commit(ctx, height) + if err != nil { + r.logger.Error(fmt.Sprintf("error committing for %d due to %s", height, err)) + return sm.State{}, nil, err + } + return state, commit, nil +} + +func (r *Reactor) postSync(ctx context.Context, state sm.State, commit *types.Commit) error { + if err := r.stateStore.Bootstrap(state); err != nil { + return err + } + if err := r.blockStore.SaveSeenCommit(state.LastBlockHeight, commit); err != nil { + return err + } + if err := r.eventBus.PublishEventStateSyncStatus(types.EventDataStateSyncStatus{ + Complete: true, + Height: state.LastBlockHeight, + }); err != nil { + return err + } + if err := r.postSyncHook(ctx, state); err != nil { + r.logger.Error(fmt.Sprintf("encountered error in post sync hook: %s", err)) + return nil + } + + return nil +} diff --git a/internal/dbsync/snapshot.go b/internal/dbsync/snapshot.go new file mode 100644 index 000000000..942993fc5 --- /dev/null +++ b/internal/dbsync/snapshot.go @@ -0,0 +1,128 @@ +package dbsync + +import ( + "crypto/md5" + "fmt" + "io" + "io/ioutil" + "os" + "path" + "sync" + + "github.com/tendermint/tendermint/config" + dstypes "github.com/tendermint/tendermint/proto/tendermint/dbsync" +) + +func Snapshot(height uint64, dbsyncConfig config.DBSyncConfig, baseConfig config.BaseConfig) error { + src := path.Join(baseConfig.DBDir(), ApplicationDBSubdirectory) + wasmSrc := path.Join(baseConfig.RootDir, WasmDirectory) + dst := path.Join(dbsyncConfig.SnapshotDirectory, fmt.Sprintf("%s%d", HeightSubdirectoryPrefix, height)) + os.RemoveAll(dst) + err := os.MkdirAll(dst, os.ModePerm) + if err != nil { + return fmt.Errorf("error creating directory %s - %s", dst, err) + } + var fds []os.FileInfo + if fds, err = ioutil.ReadDir(src); err != nil { + return err + } + wasmNames := map[string]struct{}{} + if wasmFds, _ := ioutil.ReadDir(wasmSrc); wasmFds != nil { + fds = append(fds, wasmFds...) + for _, fd := range wasmFds { + wasmNames[fd.Name()] = struct{}{} + } + } + + assignments := make([][]os.FileInfo, dbsyncConfig.SnapshotWorkerCount) + + for i, fd := range fds { + assignments[i%dbsyncConfig.SnapshotWorkerCount] = append(assignments[i%dbsyncConfig.SnapshotWorkerCount], fd) + } + + metadata := dstypes.MetadataResponse{ + Height: height, + Filenames: []string{}, + Md5Checksum: [][]byte{}, + } + metadataMtx := &sync.Mutex{} + + wg := sync.WaitGroup{} + for i := 0; i < dbsyncConfig.SnapshotWorkerCount; i++ { + wg.Add(1) + assignment := assignments[i] + go func() { + for _, fd := range assignment { + var srcfp, dstfp string + if _, ok := wasmNames[fd.Name()]; ok { + srcfp = path.Join(wasmSrc, fd.Name()) + dstfp = path.Join(dst, fd.Name()) + WasmSuffix + } else { + srcfp = path.Join(src, fd.Name()) + dstfp = path.Join(dst, fd.Name()) + } + + var srcfd *os.File + var dstfd *os.File + if srcfd, err = os.Open(srcfp); err != nil { + panic(err) + } + + if dstfd, err = os.Create(dstfp); err != nil { + srcfd.Close() + panic(err) + } + + if _, err = io.Copy(dstfd, srcfd); err != nil { + srcfd.Close() + dstfd.Close() + panic(err) + } + + filename := fd.Name() + if _, ok := wasmNames[fd.Name()]; ok { + filename += WasmSuffix + } + + bz, err := ioutil.ReadFile(path.Join(dst, filename)) + if err != nil { + panic(err) + } + sum := md5.Sum(bz) + + metadataMtx.Lock() + metadata.Filenames = append(metadata.Filenames, filename) + metadata.Md5Checksum = append(metadata.Md5Checksum, sum[:]) + + metadataMtx.Unlock() + srcfd.Close() + dstfd.Close() + } + wg.Done() + }() + } + wg.Wait() + + metadataBz, err := metadata.Marshal() + if err != nil { + return err + } + + metadataFile, err := os.Create(path.Join(dst, MetadataFilename)) + if err != nil { + return err + } + defer metadataFile.Close() + _, err = metadataFile.Write(metadataBz) + if err != nil { + return err + } + + heightFile, err := os.Create(path.Join(dbsyncConfig.SnapshotDirectory, MetadataHeightFilename)) + if err != nil { + return err + } + defer heightFile.Close() + _, err = heightFile.Write([]byte(fmt.Sprintf("%d", height))) + return err +} diff --git a/internal/dbsync/snapshot_test.go b/internal/dbsync/snapshot_test.go new file mode 100644 index 000000000..ae479c980 --- /dev/null +++ b/internal/dbsync/snapshot_test.go @@ -0,0 +1,80 @@ +package dbsync + +import ( + "crypto/md5" + "fmt" + "io/ioutil" + "os" + "path" + "strconv" + "testing" + + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/config" + dstypes "github.com/tendermint/tendermint/proto/tendermint/dbsync" +) + +func TestSnapshot(t *testing.T) { + baseConfig := config.BaseConfig{ + RootDir: t.TempDir(), + DBPath: "data", + } + appDBDir := path.Join(baseConfig.DBDir(), ApplicationDBSubdirectory) + os.MkdirAll(appDBDir, os.ModePerm) + wasmDir := path.Join(baseConfig.RootDir, WasmDirectory) + os.MkdirAll(wasmDir, os.ModePerm) + dbsyncConfig := config.DBSyncConfig{ + SnapshotDirectory: t.TempDir(), + SnapshotWorkerCount: 1, + } + os.MkdirAll(dbsyncConfig.SnapshotDirectory, os.ModePerm) + + dataFilename1, dataFilename2 := "d1", "d2" + wasmFilename := "w" + f1, _ := os.Create(path.Join(appDBDir, dataFilename1)) + defer f1.Close() + f1.WriteString("abc") + f2, _ := os.Create(path.Join(appDBDir, dataFilename2)) + defer f2.Close() + f2.WriteString("def") + w, _ := os.Create(path.Join(wasmDir, wasmFilename)) + defer w.Close() + w.WriteString("ghi") + + height := uint64(1000) + err := Snapshot(height, dbsyncConfig, baseConfig) + require.Nil(t, err) + + // assert snapshot_1000 directory exists + subdir := path.Join(dbsyncConfig.SnapshotDirectory, fmt.Sprintf("snapshot_%d", height)) + _, err = os.Stat(subdir) + require.Nil(t, err) + + // assert 3 files + METADATA exist in snapshot_1000 + fds, err := ioutil.ReadDir(subdir) + require.Nil(t, err) + expected := map[string]string{"d1": "abc", "d2": "def", "w_wasm": "ghi"} + checksum1, checksum2, checksum3 := md5.Sum([]byte("abc")), md5.Sum([]byte("def")), md5.Sum([]byte("ghi")) + expectedMetadata := dstypes.MetadataResponse{ + Height: height, + Filenames: []string{"d1", "d2", "w_wasm"}, + Md5Checksum: [][]byte{checksum1[:], checksum2[:], checksum3[:]}, + } + serialized, _ := expectedMetadata.Marshal() + expected["METADATA"] = string(serialized) + for _, fd := range fds { + require.Contains(t, expected, fd.Name()) + fp := path.Join(subdir, fd.Name()) + data, err := ioutil.ReadFile(fp) + require.Nil(t, err) + require.Equal(t, expected[fd.Name()], string(data)) + delete(expected, fd.Name()) + } + + // assert LATEST_HEIGHT is updated + hbz, err := ioutil.ReadFile(path.Join(dbsyncConfig.SnapshotDirectory, MetadataHeightFilename)) + require.Nil(t, err) + writtenHeight, err := strconv.ParseUint(string(hbz), 10, 64) + require.Nil(t, err) + require.Equal(t, height, writtenHeight) +} diff --git a/internal/dbsync/syncer.go b/internal/dbsync/syncer.go new file mode 100644 index 000000000..8e74f9581 --- /dev/null +++ b/internal/dbsync/syncer.go @@ -0,0 +1,327 @@ +package dbsync + +import ( + "bytes" + "context" + "crypto/md5" + "errors" + "fmt" + "io/fs" + "os" + "path" + "strings" + "sync" + "time" + + "github.com/tendermint/tendermint/config" + sm "github.com/tendermint/tendermint/internal/state" + "github.com/tendermint/tendermint/libs/log" + dstypes "github.com/tendermint/tendermint/proto/tendermint/dbsync" + "github.com/tendermint/tendermint/types" +) + +const ApplicationDBSubdirectory = "application.db" + +// TODO: this is bad as TM shouldn't be aware of wasm. DB sync/restore logic should ideally happen +// on application-level (i.e. Cosmos layer) and communicate to TM via new ABCI methods +const WasmDirectory = "wasm/wasm/state/wasm" +const WasmSuffix = "_wasm" +const LockFile = "LOCK" + +type Syncer struct { + mtx *sync.RWMutex + logger log.Logger + + active bool + heightToSync uint64 + peersToSync []types.NodeID + expectedChecksums map[string][]byte + pendingFiles map[string]struct{} + syncedFiles map[string]struct{} + completionSignals map[string]chan struct{} + metadataSetAt time.Time + timeoutInSeconds time.Duration + fileQueue []*dstypes.FileResponse + applicationDBDirectory string + wasmStateDirectory string + sleepInSeconds time.Duration + fileWorkerCount int + fileWorkerTimeout time.Duration + fileWorkerCancelFn context.CancelFunc + + metadataRequestFn func(context.Context) error + fileRequestFn func(context.Context, types.NodeID, uint64, string) error + commitStateFn func(context.Context, uint64) (sm.State, *types.Commit, error) + postSyncFn func(context.Context, sm.State, *types.Commit) error + resetDirFn func(*Syncer) + + state sm.State + commit *types.Commit +} + +func defaultResetDirFn(s *Syncer) { + os.RemoveAll(s.applicationDBDirectory) + os.MkdirAll(s.applicationDBDirectory, fs.ModeDir) + os.RemoveAll(s.wasmStateDirectory) + os.MkdirAll(s.wasmStateDirectory, fs.ModeDir) +} + +func NewSyncer( + logger log.Logger, + dbsyncConfig config.DBSyncConfig, + baseConfig config.BaseConfig, + metadataRequestFn func(context.Context) error, + fileRequestFn func(context.Context, types.NodeID, uint64, string) error, + commitStateFn func(context.Context, uint64) (sm.State, *types.Commit, error), + postSyncFn func(context.Context, sm.State, *types.Commit) error, + resetDirFn func(*Syncer), +) *Syncer { + return &Syncer{ + logger: logger, + active: dbsyncConfig.Enable, + timeoutInSeconds: time.Duration(dbsyncConfig.TimeoutInSeconds) * time.Second, + fileQueue: []*dstypes.FileResponse{}, + applicationDBDirectory: path.Join(baseConfig.DBDir(), ApplicationDBSubdirectory), + wasmStateDirectory: path.Join(baseConfig.RootDir, WasmDirectory), + sleepInSeconds: time.Duration(dbsyncConfig.NoFileSleepInSeconds) * time.Second, + fileWorkerCount: dbsyncConfig.FileWorkerCount, + fileWorkerTimeout: time.Duration(dbsyncConfig.FileWorkerTimeout) * time.Second, + metadataRequestFn: metadataRequestFn, + fileRequestFn: fileRequestFn, + commitStateFn: commitStateFn, + postSyncFn: postSyncFn, + resetDirFn: resetDirFn, + mtx: &sync.RWMutex{}, + } +} + +func (s *Syncer) SetMetadata(ctx context.Context, sender types.NodeID, metadata *dstypes.MetadataResponse) { + s.mtx.RLock() + + if !s.active { + s.mtx.RUnlock() + return + } + s.mtx.RUnlock() + + if len(metadata.Filenames) != len(metadata.Md5Checksum) { + s.logger.Error("received bad metadata with inconsistent files and checksums count") + return + } + + timedOut, now := s.isCurrentMetadataTimedOut() + s.mtx.Lock() + defer s.mtx.Unlock() + if timedOut { + if s.fileWorkerCancelFn != nil { + s.fileWorkerCancelFn() + } + + state, commit, err := s.commitStateFn(ctx, metadata.Height) + if err != nil { + return + } + s.state = state + s.commit = commit + s.metadataSetAt = now + s.heightToSync = metadata.Height + s.expectedChecksums = map[string][]byte{} + s.syncedFiles = map[string]struct{}{} + s.pendingFiles = map[string]struct{}{} + s.completionSignals = map[string]chan struct{}{} + for i, filename := range metadata.Filenames { + if filename == LockFile { + // ignore lockfile + continue + } + s.expectedChecksums[filename] = metadata.Md5Checksum[i] + } + s.fileQueue = []*dstypes.FileResponse{} + s.peersToSync = []types.NodeID{sender} + s.resetDirFn(s) + + cancellableCtx, cancel := context.WithCancel(ctx) + s.fileWorkerCancelFn = cancel + s.requestFiles(cancellableCtx, s.metadataSetAt) + } else if metadata.Height == s.heightToSync { + s.peersToSync = append(s.peersToSync, sender) + } +} + +func (s *Syncer) Process(ctx context.Context) { + for { + s.mtx.RLock() + if !s.active { + s.logger.Info(fmt.Sprintf("sync for height %d with %d files finished!", s.heightToSync, len(s.expectedChecksums))) + s.mtx.RUnlock() + break + } + s.mtx.RUnlock() + timedOut, _ := s.isCurrentMetadataTimedOut() + if timedOut { + s.logger.Info(fmt.Sprintf("last metadata has timed out; sleeping for %f seconds", s.sleepInSeconds.Seconds())) + s.metadataRequestFn(ctx) + time.Sleep(s.sleepInSeconds) + continue + } + file := s.popFile() + if file == nil { + s.mtx.RLock() + numSynced := len(s.syncedFiles) + numTotal := len(s.expectedChecksums) + s.mtx.RUnlock() + s.logger.Info(fmt.Sprintf("no file to sync; sync'ed %d out of %d so far; sleeping for %f seconds", numSynced, numTotal, s.sleepInSeconds.Seconds())) + time.Sleep(s.sleepInSeconds) + continue + } + if err := s.processFile(ctx, file); err != nil { + s.logger.Error(err.Error()) + } + } +} + +func (s *Syncer) Stop() { + s.mtx.Lock() + defer s.mtx.Unlock() + if s.active { + s.resetDirFn(s) + s.active = false + } +} + +func (s *Syncer) processFile(ctx context.Context, file *dstypes.FileResponse) error { + s.mtx.Lock() + defer s.mtx.Unlock() + defer func() { + delete(s.pendingFiles, file.Filename) + }() + + if file.Height != s.heightToSync { + return fmt.Errorf("current height is %d but received file for height %d", s.heightToSync, file.Height) + } + + if expectedChecksum, ok := s.expectedChecksums[file.Filename]; !ok { + return fmt.Errorf("received unexpected file %s", file.Filename) + } else if _, ok := s.syncedFiles[file.Filename]; ok { + return fmt.Errorf("received duplicate file %s", file.Filename) + } else if _, ok := s.pendingFiles[file.Filename]; !ok { + return fmt.Errorf("received unrequested file %s", file.Filename) + } else { + checkSum := md5.Sum(file.Data) + if !bytes.Equal(checkSum[:], expectedChecksum) { + return errors.New("received unexpected checksum") + } + } + + var dbFile *os.File + var err error + if strings.HasSuffix(file.Filename, WasmSuffix) { + dbFile, err = os.Create(path.Join(s.wasmStateDirectory, strings.TrimSuffix(file.Filename, WasmSuffix))) + } else { + dbFile, err = os.Create(path.Join(s.applicationDBDirectory, file.Filename)) + } + if err != nil { + return err + } + defer dbFile.Close() + _, err = dbFile.Write(file.Data) + if err != nil { + return err + } + + s.syncedFiles[file.Filename] = struct{}{} + if len(s.syncedFiles) == len(s.expectedChecksums) { + // we have finished syncing + if err := s.postSyncFn(ctx, s.state, s.commit); err != nil { + // no graceful way to handle postsync error since we might be in a partially updated state + panic(err) + } + s.active = false + } + s.completionSignals[file.Filename] <- struct{}{} + return nil +} + +func (s *Syncer) isCurrentMetadataTimedOut() (bool, time.Time) { + s.mtx.RLock() + defer s.mtx.RUnlock() + now := time.Now() + if s.metadataSetAt.IsZero() { + return true, now + } + return now.After(s.metadataSetAt.Add(s.timeoutInSeconds)), now +} + +func (s *Syncer) requestFiles(ctx context.Context, metadataSetAt time.Time) { + worker := func() { + for { + s.mtx.Lock() + if metadataSetAt != s.metadataSetAt { + s.mtx.Unlock() + break + } + if len(s.expectedChecksums) == len(s.pendingFiles)+len(s.syncedFiles) { + // even if there are still pending items, there should be enough + // workers to handle them given one worker can have at most one + // pending item at a time + s.mtx.Unlock() + break + } + var picked string + for filename := range s.expectedChecksums { + _, pending := s.pendingFiles[filename] + _, synced := s.syncedFiles[filename] + if pending || synced { + continue + } + picked = filename + break + } + s.pendingFiles[picked] = struct{}{} + completionSignal := make(chan struct{}, 1) + s.completionSignals[picked] = completionSignal + s.fileRequestFn(ctx, s.peersToSync[0], s.heightToSync, picked) + s.mtx.Unlock() + + ticker := time.NewTicker(s.fileWorkerTimeout) + defer ticker.Stop() + + select { + case <-completionSignal: + + case <-ticker.C: + s.mtx.Lock() + delete(s.pendingFiles, picked) + s.mtx.Unlock() + + case <-ctx.Done(): + return + } + + ticker.Stop() + } + } + for i := 0; i < s.fileWorkerCount; i++ { + go worker() + } +} + +func (s *Syncer) popFile() *dstypes.FileResponse { + s.mtx.Lock() + defer s.mtx.Unlock() + + if len(s.fileQueue) == 0 { + return nil + } + + file := s.fileQueue[0] + s.fileQueue = s.fileQueue[1:] + return file +} + +func (s *Syncer) PushFile(file *dstypes.FileResponse) { + s.mtx.Lock() + defer s.mtx.Unlock() + + s.fileQueue = append(s.fileQueue, file) +} diff --git a/internal/dbsync/syncer_test.go b/internal/dbsync/syncer_test.go new file mode 100644 index 000000000..8fcf3df29 --- /dev/null +++ b/internal/dbsync/syncer_test.go @@ -0,0 +1,125 @@ +package dbsync + +import ( + "context" + "crypto/md5" + "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/internal/state" + "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/proto/tendermint/dbsync" + "github.com/tendermint/tendermint/types" +) + +func getTestSyncer(t *testing.T) *Syncer { + baseConfig := config.DefaultBaseConfig() + dbsyncConfig := config.DefaultDBSyncConfig() + dbsyncConfig.TimeoutInSeconds = 99999 + dbsyncConfig.NoFileSleepInSeconds = 5 + dbsyncConfig.FileWorkerTimeout = 10 + syncer := NewSyncer( + log.NewNopLogger(), + *dbsyncConfig, + baseConfig, + func(ctx context.Context) error { return nil }, + func(ctx context.Context, ni types.NodeID, u uint64, s string) error { return nil }, + func(ctx context.Context, u uint64) (state.State, *types.Commit, error) { + return state.State{}, nil, nil + }, + func(ctx context.Context, s state.State, c *types.Commit) error { return nil }, + func(s *Syncer) { + s.applicationDBDirectory = t.TempDir() + s.wasmStateDirectory = t.TempDir() + }, + ) + syncer.active = true + syncer.applicationDBDirectory = t.TempDir() + syncer.wasmStateDirectory = t.TempDir() + return syncer +} + +func TestSetMetadata(t *testing.T) { + syncer := getTestSyncer(t) + // initial + syncer.SetMetadata(context.Background(), types.NodeID("someone"), &dbsync.MetadataResponse{ + Height: 1, + Hash: []byte("hash"), + Filenames: []string{"f1"}, + Md5Checksum: [][]byte{[]byte("sum")}, + }) + syncer.fileWorkerCancelFn() + require.Equal(t, uint64(1), syncer.heightToSync) + require.NotNil(t, syncer.metadataSetAt) + require.Equal(t, 1, len(syncer.expectedChecksums)) + require.Equal(t, 1, len(syncer.peersToSync)) + + // second time + syncer.SetMetadata(context.Background(), types.NodeID("someone else"), &dbsync.MetadataResponse{ + Height: 1, + Hash: []byte("hash"), + Filenames: []string{"f1"}, + Md5Checksum: [][]byte{[]byte("sum")}, + }) + require.Equal(t, uint64(1), syncer.heightToSync) + require.NotNil(t, syncer.metadataSetAt) + require.Equal(t, 1, len(syncer.expectedChecksums)) + require.Equal(t, 2, len(syncer.peersToSync)) +} + +func TestFileProcessHappyPath(t *testing.T) { + // successful process + syncer := getTestSyncer(t) + data := []byte("data") + sum := md5.Sum(data) + syncer.SetMetadata(context.Background(), types.NodeID("someone"), &dbsync.MetadataResponse{ + Height: 1, + Hash: []byte("hash"), + Filenames: []string{"f1"}, + Md5Checksum: [][]byte{sum[:]}, + }) + for { + syncer.mtx.RLock() + _, ok := syncer.pendingFiles["f1"] + syncer.mtx.RUnlock() + if ok { + break + } + } + syncer.PushFile(&dbsync.FileResponse{ + Height: 1, + Filename: "f1", + Data: data, + }) + syncer.Process(context.Background()) +} + +func TestFileProcessTimeoutReprocess(t *testing.T) { + // successful process + syncer := getTestSyncer(t) + data := []byte("data") + sum := md5.Sum(data) + syncer.SetMetadata(context.Background(), types.NodeID("someone"), &dbsync.MetadataResponse{ + Height: 1, + Hash: []byte("hash"), + Filenames: []string{"f1"}, + Md5Checksum: [][]byte{sum[:]}, + }) + for { + syncer.mtx.RLock() + _, ok := syncer.pendingFiles["f1"] + syncer.mtx.RUnlock() + if ok { + break + } + } + time.Sleep(syncer.fileWorkerTimeout + time.Second) // add some padding + syncer.PushFile(&dbsync.FileResponse{ + Height: 1, + Filename: "f1", + Data: data, + }) + syncer.Process(context.Background()) +} diff --git a/internal/mempool/reactor.go b/internal/mempool/reactor.go index f9007b881..cdd8bd4ed 100644 --- a/internal/mempool/reactor.go +++ b/internal/mempool/reactor.go @@ -41,7 +41,8 @@ type Reactor struct { mtx sync.Mutex peerRoutines map[types.NodeID]context.CancelFunc - channel *p2p.Channel + channel *p2p.Channel + readyToStart chan struct{} } // NewReactor returns a reference to a new reactor. @@ -59,12 +60,17 @@ func NewReactor( peerEvents: peerEvents, peerRoutines: make(map[types.NodeID]context.CancelFunc), observePanic: defaultObservePanic, + readyToStart: make(chan struct{}, 1), } r.BaseService = *service.NewBaseService(logger, "Mempool", r) return r } +func (r *Reactor) MarkReadyToStart() { + r.readyToStart <- struct{}{} +} + func (r *Reactor) SetChannel(ch *p2p.Channel) { r.channel = ch } @@ -196,6 +202,7 @@ func (r *Reactor) handleMessage(ctx context.Context, envelope *p2p.Envelope) (er // processMempoolCh implements a blocking event loop where we listen for p2p // Envelope messages from the mempoolCh. func (r *Reactor) processMempoolCh(ctx context.Context, mempoolCh *p2p.Channel) { + <-r.readyToStart iter := mempoolCh.Receive(ctx) for iter.Next(ctx) { envelope := iter.Envelope() diff --git a/internal/mempool/reactor_test.go b/internal/mempool/reactor_test.go index 4d45ee51a..9ab4fbc70 100644 --- a/internal/mempool/reactor_test.go +++ b/internal/mempool/reactor_test.go @@ -81,6 +81,7 @@ func setupReactors(ctx context.Context, t *testing.T, logger log.Logger, numNode mempool, func(ctx context.Context) *p2p.PeerUpdates { return rts.peerUpdates[nodeID] }, ) + rts.reactors[nodeID].MarkReadyToStart() rts.reactors[nodeID].SetChannel(rts.mempoolChannels[nodeID]) rts.nodes = append(rts.nodes, nodeID) diff --git a/internal/proxy/client.go b/internal/proxy/client.go index 735c99656..fa1d8c66e 100644 --- a/internal/proxy/client.go +++ b/internal/proxy/client.go @@ -154,6 +154,11 @@ func (app *proxyClient) FinalizeBlock(ctx context.Context, req *types.RequestFin return app.client.FinalizeBlock(ctx, req) } +func (app *proxyClient) LoadLatest(ctx context.Context, req *types.RequestLoadLatest) (*types.ResponseLoadLatest, error) { + defer addTimeSample(app.metrics.MethodTiming.With("method", "load_latest", "type", "sync"))() + return app.client.LoadLatest(ctx, req) +} + func (app *proxyClient) Commit(ctx context.Context) (*types.ResponseCommit, error) { defer addTimeSample(app.metrics.MethodTiming.With("method", "commit", "type", "sync"))() return app.client.Commit(ctx) diff --git a/internal/statesync/reactor.go b/internal/statesync/reactor.go index f41f13f4e..c26a0eb0e 100644 --- a/internal/statesync/reactor.go +++ b/internal/statesync/reactor.go @@ -11,6 +11,7 @@ import ( "sync" "time" + "github.com/gogo/protobuf/proto" abciclient "github.com/tendermint/tendermint/abci/client" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/config" @@ -63,10 +64,6 @@ const ( // return a light block lightBlockResponseTimeout = 10 * time.Second - // consensusParamsResponseTimeout is the time the p2p state provider waits - // before performing a secondary call - consensusParamsResponseTimeout = 5 * time.Second - // maxLightBlockRequestRetries is the amount of retries acceptable before // the backfill process aborts maxLightBlockRequestRetries = 20 @@ -157,8 +154,8 @@ type Reactor struct { // Dispatcher is used to multiplex light block requests and responses over multiple // peers used by the p2p state provider and in reverse sync. - dispatcher *Dispatcher - peers *peerList + dispatcher *light.Dispatcher + peers *light.PeerList // These will only be set when a state sync is in progress. It is used to feed // received snapshots and chunks into the syncer and manage incoming and outgoing @@ -167,9 +164,9 @@ type Reactor struct { initSyncer func() *syncer requestSnaphot func() error syncer *syncer - providers map[types.NodeID]*BlockProvider + providers map[types.NodeID]*light.BlockProvider initStateProvider func(ctx context.Context, chainID string, initialHeight int64) error - stateProvider StateProvider + stateProvider light.StateProvider eventBus *eventbus.EventBus metrics *Metrics @@ -220,8 +217,8 @@ func NewReactor( tempDir: tempDir, stateStore: stateStore, blockStore: blockStore, - peers: newPeerList(), - providers: make(map[types.NodeID]*BlockProvider), + peers: light.NewPeerList(), + providers: make(map[types.NodeID]*light.BlockProvider), metrics: ssMetrics, eventBus: eventBus, postSyncHook: postSyncHook, @@ -275,7 +272,11 @@ func (r *Reactor) OnStart(ctx context.Context) error { metrics: r.metrics, } } - r.dispatcher = NewDispatcher(r.lightBlockChannel) + r.dispatcher = light.NewDispatcher(r.lightBlockChannel, func(height uint64) proto.Message { + return &ssproto.LightBlockRequest{ + Height: height, + } + }) r.requestSnaphot = func() error { // request snapshots from all currently connected peers return r.snapshotChannel.Send(ctx, p2p.Envelope{ @@ -303,10 +304,14 @@ func (r *Reactor) OnStart(ctx context.Context) error { peers := r.peers.All() providers := make([]provider.Provider, len(peers)) for idx, p := range peers { - providers[idx] = NewBlockProvider(p, chainID, r.dispatcher) + providers[idx] = light.NewBlockProvider(p, chainID, r.dispatcher) } - stateProvider, err := NewP2PStateProvider(ctx, chainID, initialHeight, providers, to, r.paramsChannel, r.logger.With("module", "stateprovider")) + stateProvider, err := light.NewP2PStateProvider(ctx, chainID, initialHeight, providers, to, r.paramsChannel, r.logger.With("module", "stateprovider"), func(height uint64) proto.Message { + return &ssproto.ParamsRequest{ + Height: height, + } + }) if err != nil { return fmt.Errorf("failed to initialize P2P state provider: %w", err) } @@ -314,7 +319,7 @@ func (r *Reactor) OnStart(ctx context.Context) error { return nil } - stateProvider, err := NewRPCStateProvider(ctx, chainID, initialHeight, r.cfg.RPCServers, to, spLogger) + stateProvider, err := light.NewRPCStateProvider(ctx, chainID, initialHeight, r.cfg.RPCServers, to, spLogger) if err != nil { return fmt.Errorf("failed to initialize RPC state provider: %w", err) } @@ -503,7 +508,7 @@ func (r *Reactor) backfill( } if err != nil { queue.retry(height) - if errors.Is(err, errNoConnectedPeers) { + if errors.Is(err, light.ErrNoConnectedPeers) { r.logger.Info("backfill: no connected peers to fetch light blocks from; sleeping...", "sleepTime", sleepTime) time.Sleep(sleepTime) @@ -873,9 +878,9 @@ func (r *Reactor) handleParamsMessage(ctx context.Context, envelope *p2p.Envelop cp := types.ConsensusParamsFromProto(msg.ConsensusParams) - if sp, ok := r.stateProvider.(*stateProviderP2P); ok { + if sp, ok := r.stateProvider.(*light.StateProviderP2P); ok { select { - case sp.paramsRecvCh <- cp: + case sp.ParamsRecvCh() <- cp: case <-ctx.Done(): return ctx.Err() case <-time.After(time.Second): @@ -1010,7 +1015,7 @@ func (r *Reactor) processPeerUpdate(ctx context.Context, peerUpdate p2p.PeerUpda switch peerUpdate.Status { case p2p.PeerStatusUp: - newProvider := NewBlockProvider(peerUpdate.NodeID, r.chainID, r.dispatcher) + newProvider := light.NewBlockProvider(peerUpdate.NodeID, r.chainID, r.dispatcher) r.providers[peerUpdate.NodeID] = newProvider err := r.syncer.AddPeer(ctx, peerUpdate.NodeID) @@ -1018,10 +1023,10 @@ func (r *Reactor) processPeerUpdate(ctx context.Context, peerUpdate p2p.PeerUpda r.logger.Error("error adding peer to syncer", "error", err) return } - if sp, ok := r.stateProvider.(*stateProviderP2P); ok { + if sp, ok := r.stateProvider.(*light.StateProviderP2P); ok { // we do this in a separate routine to not block whilst waiting for the light client to finish // whatever call it's currently executing - go sp.addProvider(newProvider) + go sp.AddProvider(newProvider) } case p2p.PeerStatusDown: diff --git a/internal/statesync/reactor_test.go b/internal/statesync/reactor_test.go index defae7b6a..2e243fe47 100644 --- a/internal/statesync/reactor_test.go +++ b/internal/statesync/reactor_test.go @@ -23,6 +23,7 @@ import ( "github.com/tendermint/tendermint/internal/store" "github.com/tendermint/tendermint/internal/test/factory" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/light" "github.com/tendermint/tendermint/light/provider" ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -505,7 +506,7 @@ func TestReactor_BlockProviders(t *testing.T) { providers := make([]provider.Provider, len(peers)) for idx, peer := range peers { - providers[idx] = NewBlockProvider(peer, factory.DefaultTestChainID, rts.reactor.dispatcher) + providers[idx] = light.NewBlockProvider(peer, factory.DefaultTestChainID, rts.reactor.dispatcher) } wg := sync.WaitGroup{} diff --git a/internal/statesync/syncer.go b/internal/statesync/syncer.go index ac735be90..02d76f8ab 100644 --- a/internal/statesync/syncer.go +++ b/internal/statesync/syncer.go @@ -53,7 +53,7 @@ var ( // snapshot. Snapshots and chunks are fed via AddSnapshot() and AddChunk() as appropriate. type syncer struct { logger log.Logger - stateProvider StateProvider + stateProvider light.StateProvider conn abciclient.Client snapshots *snapshotPool snapshotCh *p2p.Channel diff --git a/internal/statesync/dispatcher.go b/light/dispatcher.go similarity index 86% rename from internal/statesync/dispatcher.go rename to light/dispatcher.go index 9cdb34978..9ade8ae5f 100644 --- a/internal/statesync/dispatcher.go +++ b/light/dispatcher.go @@ -1,4 +1,4 @@ -package statesync +package light import ( "context" @@ -6,18 +6,18 @@ import ( "fmt" "sync" + "github.com/gogo/protobuf/proto" "github.com/tendermint/tendermint/internal/p2p" "github.com/tendermint/tendermint/light/provider" - ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) var ( - errNoConnectedPeers = errors.New("no available peers to dispatch request to") - errUnsolicitedResponse = errors.New("unsolicited light block response") - errPeerAlreadyBusy = errors.New("peer is already processing a request") - errDisconnected = errors.New("dispatcher disconnected") + ErrNoConnectedPeers = errors.New("no available peers to dispatch request to") + ErrUnsolicitedResponse = errors.New("unsolicited light block response") + ErrPeerAlreadyBusy = errors.New("peer is already processing a request") + ErrDisconnected = errors.New("dispatcher disconnected") ) // A Dispatcher multiplexes concurrent requests by multiple peers for light blocks. @@ -31,12 +31,15 @@ type Dispatcher struct { mtx sync.Mutex // all pending calls that have been dispatched and are awaiting an answer calls map[types.NodeID]chan *types.LightBlock + + lightBlockMsgCreator func(uint64) proto.Message } -func NewDispatcher(requestChannel *p2p.Channel) *Dispatcher { +func NewDispatcher(requestChannel *p2p.Channel, lightBlockMsgCreator func(uint64) proto.Message) *Dispatcher { return &Dispatcher{ - requestCh: requestChannel, - calls: make(map[types.NodeID]chan *types.LightBlock), + requestCh: requestChannel, + calls: make(map[types.NodeID]chan *types.LightBlock), + lightBlockMsgCreator: lightBlockMsgCreator, } } @@ -77,7 +80,7 @@ func (d *Dispatcher) dispatch(ctx context.Context, peer types.NodeID, height int defer d.mtx.Unlock() select { case <-ctx.Done(): - return nil, errDisconnected + return nil, ErrDisconnected default: } @@ -86,16 +89,14 @@ func (d *Dispatcher) dispatch(ctx context.Context, peer types.NodeID, height int // check if a request for the same peer has already been made if _, ok := d.calls[peer]; ok { close(ch) - return ch, errPeerAlreadyBusy + return ch, ErrPeerAlreadyBusy } d.calls[peer] = ch // send request if err := d.requestCh.Send(ctx, p2p.Envelope{ - To: peer, - Message: &ssproto.LightBlockRequest{ - Height: uint64(height), - }, + To: peer, + Message: d.lightBlockMsgCreator(uint64(height)), }); err != nil { close(ch) return ch, err @@ -115,7 +116,7 @@ func (d *Dispatcher) Respond(ctx context.Context, lb *tmproto.LightBlock, peer t answerCh, ok := d.calls[peer] if !ok { // this can also happen if the response came in after the timeout - return errUnsolicitedResponse + return ErrUnsolicitedResponse } // If lb is nil we take that to mean that the peer didn't have the requested light @@ -192,7 +193,7 @@ func (p *BlockProvider) LightBlock(ctx context.Context, height int64) (*types.Li } case context.DeadlineExceeded, context.Canceled: return nil, err - case errPeerAlreadyBusy: + case ErrPeerAlreadyBusy: return nil, provider.ErrLightBlockNotFound default: return nil, provider.ErrUnreliableProvider{Reason: err} @@ -231,26 +232,26 @@ func (p *BlockProvider) ID() string { return string(p.peer) } // peerList is a rolling list of peers. This is used to distribute the load of // retrieving blocks over all the peers the reactor is connected to -type peerList struct { +type PeerList struct { mtx sync.Mutex peers []types.NodeID waiting []chan types.NodeID } -func newPeerList() *peerList { - return &peerList{ +func NewPeerList() *PeerList { + return &PeerList{ peers: make([]types.NodeID, 0), waiting: make([]chan types.NodeID, 0), } } -func (l *peerList) Len() int { +func (l *PeerList) Len() int { l.mtx.Lock() defer l.mtx.Unlock() return len(l.peers) } -func (l *peerList) Pop(ctx context.Context) types.NodeID { +func (l *PeerList) Pop(ctx context.Context) types.NodeID { l.mtx.Lock() if len(l.peers) == 0 { // if we don't have any peers in the list we block until a peer is @@ -274,7 +275,7 @@ func (l *peerList) Pop(ctx context.Context) types.NodeID { return peer } -func (l *peerList) Append(peer types.NodeID) { +func (l *PeerList) Append(peer types.NodeID) { l.mtx.Lock() defer l.mtx.Unlock() if len(l.waiting) > 0 { @@ -287,7 +288,7 @@ func (l *peerList) Append(peer types.NodeID) { } } -func (l *peerList) Remove(peer types.NodeID) { +func (l *PeerList) Remove(peer types.NodeID) { l.mtx.Lock() defer l.mtx.Unlock() for i, p := range l.peers { @@ -298,13 +299,13 @@ func (l *peerList) Remove(peer types.NodeID) { } } -func (l *peerList) All() []types.NodeID { +func (l *PeerList) All() []types.NodeID { l.mtx.Lock() defer l.mtx.Unlock() return l.peers } -func (l *peerList) Contains(id types.NodeID) bool { +func (l *PeerList) Contains(id types.NodeID) bool { l.mtx.Lock() defer l.mtx.Unlock() diff --git a/internal/statesync/dispatcher_test.go b/light/dispatcher_test.go similarity index 76% rename from internal/statesync/dispatcher_test.go rename to light/dispatcher_test.go index 8ec074bd1..6fc21fb0d 100644 --- a/internal/statesync/dispatcher_test.go +++ b/light/dispatcher_test.go @@ -1,4 +1,4 @@ -package statesync +package light import ( "context" @@ -9,12 +9,14 @@ import ( "time" "github.com/fortytw2/leaktest" + "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/internal/p2p" "github.com/tendermint/tendermint/internal/test/factory" ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) @@ -42,7 +44,11 @@ func TestDispatcherBasic(t *testing.T) { chans, ch := testChannel(100) - d := NewDispatcher(ch) + d := NewDispatcher(ch, func(height uint64) proto.Message { + return &ssproto.LightBlockRequest{ + Height: height, + } + }) go handleRequests(ctx, t, d, chans.Out) peers := createPeerSet(numPeers) @@ -74,7 +80,11 @@ func TestDispatcherReturnsNoBlock(t *testing.T) { chans, ch := testChannel(100) - d := NewDispatcher(ch) + d := NewDispatcher(ch, func(height uint64) proto.Message { + return &ssproto.LightBlockRequest{ + Height: height, + } + }) peer := factory.NodeID(t, "a") @@ -98,7 +108,11 @@ func TestDispatcherTimeOutWaitingOnLightBlock(t *testing.T) { defer cancel() _, ch := testChannel(100) - d := NewDispatcher(ch) + d := NewDispatcher(ch, func(height uint64) proto.Message { + return &ssproto.LightBlockRequest{ + Height: height, + } + }) peer := factory.NodeID(t, "a") ctx, cancelFunc := context.WithTimeout(ctx, 10*time.Millisecond) @@ -121,7 +135,11 @@ func TestDispatcherProviders(t *testing.T) { chans, ch := testChannel(100) - d := NewDispatcher(ch) + d := NewDispatcher(ch, func(height uint64) proto.Message { + return &ssproto.LightBlockRequest{ + Height: height, + } + }) go handleRequests(ctx, t, d, chans.Out) peers := createPeerSet(5) @@ -145,7 +163,7 @@ func TestPeerListBasic(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - peerList := newPeerList() + peerList := NewPeerList() assert.Zero(t, peerList.Len()) numPeers := 10 peerSet := createPeerSet(numPeers) @@ -186,7 +204,7 @@ func TestPeerListBasic(t *testing.T) { func TestPeerListBlocksWhenEmpty(t *testing.T) { t.Cleanup(leaktest.Check(t)) - peerList := newPeerList() + peerList := NewPeerList() require.Zero(t, peerList.Len()) doneCh := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background()) @@ -204,7 +222,7 @@ func TestPeerListBlocksWhenEmpty(t *testing.T) { func TestEmptyPeerListReturnsWhenContextCanceled(t *testing.T) { t.Cleanup(leaktest.Check(t)) - peerList := newPeerList() + peerList := NewPeerList() require.Zero(t, peerList.Len()) doneCh := make(chan struct{}) @@ -236,7 +254,7 @@ func TestPeerListConcurrent(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - peerList := newPeerList() + peerList := NewPeerList() numPeers := 10 wg := sync.WaitGroup{} @@ -280,7 +298,7 @@ func TestPeerListConcurrent(t *testing.T) { } func TestPeerListRemove(t *testing.T) { - peerList := newPeerList() + peerList := NewPeerList() numPeers := 10 peerSet := createPeerSet(numPeers) @@ -323,3 +341,48 @@ func createPeerSet(num int) []types.NodeID { } return peers } + +const testAppVersion = 9 + +type lightBlockResponse struct { + block *types.LightBlock + peer types.NodeID +} + +func mockLBResp(ctx context.Context, t *testing.T, peer types.NodeID, height int64, time time.Time) lightBlockResponse { + t.Helper() + vals, pv := factory.ValidatorSet(ctx, t, 3, 10) + _, _, lb := mockLB(ctx, t, height, time, factory.MakeBlockID(), vals, pv) + return lightBlockResponse{ + block: lb, + peer: peer, + } +} + +func mockLB(ctx context.Context, t *testing.T, height int64, time time.Time, lastBlockID types.BlockID, + currentVals *types.ValidatorSet, currentPrivVals []types.PrivValidator, +) (*types.ValidatorSet, []types.PrivValidator, *types.LightBlock) { + t.Helper() + header := factory.MakeHeader(t, &types.Header{ + Height: height, + LastBlockID: lastBlockID, + Time: time, + }) + header.Version.App = testAppVersion + + nextVals, nextPrivVals := factory.ValidatorSet(ctx, t, 3, 10) + header.ValidatorsHash = currentVals.Hash() + header.NextValidatorsHash = nextVals.Hash() + header.ConsensusHash = types.DefaultConsensusParams().HashConsensusParams() + lastBlockID = factory.MakeBlockIDWithHash(header.Hash()) + voteSet := types.NewExtendedVoteSet(factory.DefaultTestChainID, height, 0, tmproto.PrecommitType, currentVals) + extCommit, err := factory.MakeExtendedCommit(ctx, lastBlockID, height, 0, voteSet, currentPrivVals, time) + require.NoError(t, err) + return nextVals, nextPrivVals, &types.LightBlock{ + SignedHeader: &types.SignedHeader{ + Header: header, + Commit: extCommit.ToCommit(), + }, + ValidatorSet: currentVals, + } +} diff --git a/internal/statesync/stateprovider.go b/light/stateprovider.go similarity index 89% rename from internal/statesync/stateprovider.go rename to light/stateprovider.go index a796b0b2e..ca2a346c8 100644 --- a/internal/statesync/stateprovider.go +++ b/light/stateprovider.go @@ -1,4 +1,4 @@ -package statesync +package light import ( "bytes" @@ -9,22 +9,25 @@ import ( "sync" "time" + "github.com/gogo/protobuf/proto" dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/internal/p2p" sm "github.com/tendermint/tendermint/internal/state" "github.com/tendermint/tendermint/libs/log" - "github.com/tendermint/tendermint/light" lightprovider "github.com/tendermint/tendermint/light/provider" lighthttp "github.com/tendermint/tendermint/light/provider/http" lightrpc "github.com/tendermint/tendermint/light/rpc" lightdb "github.com/tendermint/tendermint/light/store/db" - ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" rpchttp "github.com/tendermint/tendermint/rpc/client/http" "github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/version" ) +const ( + consensusParamsResponseTimeout = 5 * time.Second +) + //go:generate ../../scripts/mockery_generate.sh StateProvider // StateProvider is a provider of trusted state data for bootstrapping a node. This refers @@ -41,7 +44,7 @@ type StateProvider interface { type stateProviderRPC struct { sync.Mutex // light.Client is not concurrency-safe - lc *light.Client + lc *Client initialHeight int64 providers map[lightprovider.Provider]string logger log.Logger @@ -53,7 +56,7 @@ func NewRPCStateProvider( chainID string, initialHeight int64, servers []string, - trustOptions light.TrustOptions, + trustOptions TrustOptions, logger log.Logger, ) (StateProvider, error) { if len(servers) < 2 { @@ -74,8 +77,8 @@ func NewRPCStateProvider( providerRemotes[provider] = server } - lc, err := light.NewClient(ctx, chainID, trustOptions, providers[0], providers[1:], - lightdb.New(dbm.NewMemDB()), light.Logger(logger)) + lc, err := NewClient(ctx, chainID, trustOptions, providers[0], providers[1:], + lightdb.New(dbm.NewMemDB()), Logger(logger)) if err != nil { return nil, err } @@ -204,12 +207,13 @@ func rpcClient(server string) (*rpchttp.HTTP, error) { return rpchttp.New(server) } -type stateProviderP2P struct { - sync.Mutex // light.Client is not concurrency-safe - lc *light.Client - initialHeight int64 - paramsSendCh *p2p.Channel - paramsRecvCh chan types.ConsensusParams +type StateProviderP2P struct { + sync.Mutex // light.Client is not concurrency-safe + lc *Client + initialHeight int64 + paramsSendCh *p2p.Channel + paramsRecvCh chan types.ConsensusParams + paramsReqCreator func(uint64) proto.Message } // NewP2PStateProvider creates a light client state @@ -219,36 +223,38 @@ func NewP2PStateProvider( chainID string, initialHeight int64, providers []lightprovider.Provider, - trustOptions light.TrustOptions, + trustOptions TrustOptions, paramsSendCh *p2p.Channel, logger log.Logger, + paramsReqCreator func(uint64) proto.Message, ) (StateProvider, error) { if len(providers) < 2 { return nil, fmt.Errorf("at least 2 peers are required, got %d", len(providers)) } - lc, err := light.NewClient(ctx, chainID, trustOptions, providers[0], providers[1:], - lightdb.New(dbm.NewMemDB()), light.Logger(logger)) + lc, err := NewClient(ctx, chainID, trustOptions, providers[0], providers[1:], + lightdb.New(dbm.NewMemDB()), Logger(logger)) if err != nil { return nil, err } - return &stateProviderP2P{ - lc: lc, - initialHeight: initialHeight, - paramsSendCh: paramsSendCh, - paramsRecvCh: make(chan types.ConsensusParams), + return &StateProviderP2P{ + lc: lc, + initialHeight: initialHeight, + paramsSendCh: paramsSendCh, + paramsRecvCh: make(chan types.ConsensusParams), + paramsReqCreator: paramsReqCreator, }, nil } -func (s *stateProviderP2P) verifyLightBlockAtHeight(ctx context.Context, height uint64, ts time.Time) (*types.LightBlock, error) { +func (s *StateProviderP2P) verifyLightBlockAtHeight(ctx context.Context, height uint64, ts time.Time) (*types.LightBlock, error) { ctx, cancel := context.WithTimeout(ctx, 20*time.Second) defer cancel() return s.lc.VerifyLightBlockAtHeight(ctx, int64(height), ts) } // AppHash implements StateProvider. -func (s *stateProviderP2P) AppHash(ctx context.Context, height uint64) ([]byte, error) { +func (s *StateProviderP2P) AppHash(ctx context.Context, height uint64) ([]byte, error) { s.Lock() defer s.Unlock() @@ -269,7 +275,7 @@ func (s *stateProviderP2P) AppHash(ctx context.Context, height uint64) ([]byte, } // Commit implements StateProvider. -func (s *stateProviderP2P) Commit(ctx context.Context, height uint64) (*types.Commit, error) { +func (s *StateProviderP2P) Commit(ctx context.Context, height uint64) (*types.Commit, error) { s.Lock() defer s.Unlock() header, err := s.verifyLightBlockAtHeight(ctx, height, time.Now()) @@ -280,7 +286,7 @@ func (s *stateProviderP2P) Commit(ctx context.Context, height uint64) (*types.Co } // State implements StateProvider. -func (s *stateProviderP2P) State(ctx context.Context, height uint64) (sm.State, error) { +func (s *StateProviderP2P) State(ctx context.Context, height uint64) (sm.State, error) { s.Lock() defer s.Unlock() @@ -345,12 +351,16 @@ func (s *stateProviderP2P) State(ctx context.Context, height uint64) (sm.State, // addProvider dynamically adds a peer as a new witness. A limit of 6 providers is kept as a // heuristic. Too many overburdens the network and too little compromises the second layer of security. -func (s *stateProviderP2P) addProvider(p lightprovider.Provider) { +func (s *StateProviderP2P) AddProvider(p lightprovider.Provider) { if len(s.lc.Witnesses()) < 6 { s.lc.AddProvider(p) } } +func (s *StateProviderP2P) ParamsRecvCh() chan types.ConsensusParams { + return s.paramsRecvCh +} + // consensusParams sends out a request for consensus params blocking // until one is returned. // @@ -358,7 +368,7 @@ func (s *stateProviderP2P) addProvider(p lightprovider.Provider) { // none responds it will retry them all sometime later until it // receives some response. This operation will block until it receives // a response or the context is canceled. -func (s *stateProviderP2P) consensusParams(ctx context.Context, height int64) (types.ConsensusParams, error) { +func (s *StateProviderP2P) consensusParams(ctx context.Context, height int64) (types.ConsensusParams, error) { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -389,10 +399,8 @@ func (s *stateProviderP2P) consensusParams(ctx context.Context, height int64) (t for { iterCount++ if err := s.paramsSendCh.Send(ctx, p2p.Envelope{ - To: peer, - Message: &ssproto.ParamsRequest{ - Height: uint64(height), - }, + To: peer, + Message: s.paramsReqCreator(uint64(height)), }); err != nil { // this only errors if // the context is diff --git a/node/node.go b/node/node.go index 957a86e82..22bea13f1 100644 --- a/node/node.go +++ b/node/node.go @@ -20,6 +20,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/internal/blocksync" "github.com/tendermint/tendermint/internal/consensus" + "github.com/tendermint/tendermint/internal/dbsync" "github.com/tendermint/tendermint/internal/eventbus" "github.com/tendermint/tendermint/internal/eventlog" "github.com/tendermint/tendermint/internal/evidence" @@ -54,15 +55,15 @@ type nodeImpl struct { config *config.Config genesisDoc *types.GenesisDoc // initial validator set privValidator types.PrivValidator // local node's validator key - shouldStateSync bool // set during makeNode + shouldHandshake bool // set during makeNode // network - peerManager *p2p.PeerManager - router *p2p.Router + peerManager *p2p.PeerManager + router *p2p.Router routerRestartCh chan struct{} // Used to signal a restart the node on the application level ServiceRestartCh chan []string - nodeInfo types.NodeInfo - nodeKey types.NodeKey // our node privkey + nodeInfo types.NodeInfo + nodeKey types.NodeKey // our node privkey // services eventSinks []indexer.EventSink @@ -71,7 +72,7 @@ type nodeImpl struct { blockStore *store.BlockStore // store the blockchain to disk evPool *evidence.Pool indexerService *indexer.Service - services []service.Service + services []service.Service rpcListeners []net.Listener // rpc servers shutdownOps closer rpcEnv *rpccore.Environment @@ -283,6 +284,9 @@ func makeNode( mpReactor, mp := createMempoolReactor(logger, cfg, proxyApp, stateStore, nodeMetrics.mempool, peerManager.Subscribe, peerManager) node.router.AddChDescToBeAdded(mempool.GetChannelDescriptor(cfg.Mempool), mpReactor.SetChannel) + if !cfg.DBSync.Enable { + mpReactor.MarkReadyToStart() + } node.rpcEnv.Mempool = mp node.services = append(node.services, mpReactor) @@ -305,10 +309,14 @@ func makeNode( stateSync = false } + if stateSync && cfg.DBSync.Enable { + panic("statesync and dbsync cannot be turned on at the same time") + } + // Determine whether we should do block sync. This must happen after the handshake, since the // app may modify the validator set, specifying ourself as the only validator. blockSync := !onlyValidatorIsUs(state, pubKey) - waitSync := stateSync || blockSync + waitSync := stateSync || blockSync || cfg.DBSync.Enable csState, err := consensus.NewState(logger.With("module", "consensus"), cfg.Consensus, @@ -352,7 +360,7 @@ func makeNode( blockStore, csReactor, peerManager.Subscribe, - blockSync && !stateSync, + blockSync && !stateSync && !cfg.DBSync.Enable, nodeMetrics.consensus, eventBus, restartCh, @@ -382,6 +390,21 @@ func makeNode( node.router.AddChDescToBeAdded(pex.ChannelDescriptor(), pxReactor.SetChannel) } + postSyncHook := func(ctx context.Context, state sm.State) error { + csReactor.SetStateSyncingMetrics(0) + + // TODO: Some form of orchestrator is needed here between the state + // advancing reactors to be able to control which one of the three + // is running + // FIXME Very ugly to have these metrics bleed through here. + csReactor.SetBlockSyncingMetrics(1) + if err := bcReactor.SwitchToBlockSync(ctx, state); err != nil { + logger.Error("failed to switch to block sync", "err", err) + return err + } + + return nil + } // Set up state sync reactor, and schedule a sync if requested. // FIXME The way we do phased startups (e.g. replay -> block sync -> consensus) is very messy, // we should clean this whole thing up. See: @@ -399,32 +422,43 @@ func makeNode( nodeMetrics.statesync, eventBus, // the post-sync operation - func(ctx context.Context, state sm.State) error { - csReactor.SetStateSyncingMetrics(0) - - // TODO: Some form of orchestrator is needed here between the state - // advancing reactors to be able to control which one of the three - // is running - // FIXME Very ugly to have these metrics bleed through here. - csReactor.SetBlockSyncingMetrics(1) - if err := bcReactor.SwitchToBlockSync(ctx, state); err != nil { - logger.Error("failed to switch to block sync", "err", err) - return err - } - - return nil - }, + postSyncHook, stateSync, restartCh, cfg.SelfRemediation, ) - node.shouldStateSync = stateSync + + node.shouldHandshake = !stateSync && !cfg.DBSync.Enable node.services = append(node.services, ssReactor) node.router.AddChDescToBeAdded(statesync.GetSnapshotChannelDescriptor(), ssReactor.SetSnapshotChannel) node.router.AddChDescToBeAdded(statesync.GetChunkChannelDescriptor(), ssReactor.SetChunkChannel) node.router.AddChDescToBeAdded(statesync.GetLightBlockChannelDescriptor(), ssReactor.SetLightBlockChannel) node.router.AddChDescToBeAdded(statesync.GetParamsChannelDescriptor(), ssReactor.SetParamsChannel) + dbsyncReactor := dbsync.NewReactor( + logger.With("module", "dbsync"), + *cfg.DBSync, + cfg.BaseConfig, + peerManager.Subscribe, + stateStore, + blockStore, + genDoc.InitialHeight, + genDoc.ChainID, + eventBus, + func(ctx context.Context, state sm.State) error { + if _, err := client.LoadLatest(ctx, &abci.RequestLoadLatest{}); err != nil { + return err + } + mpReactor.MarkReadyToStart() + return postSyncHook(ctx, state) + }, + ) + node.services = append(node.services, dbsyncReactor) + node.router.AddChDescToBeAdded(dbsync.GetMetadataChannelDescriptor(), dbsyncReactor.SetMetadataChannel) + node.router.AddChDescToBeAdded(dbsync.GetFileChannelDescriptor(), dbsyncReactor.SetFileChannel) + node.router.AddChDescToBeAdded(dbsync.GetLightBlockChannelDescriptor(), dbsyncReactor.SetLightBlockChannel) + node.router.AddChDescToBeAdded(dbsync.GetParamsChannelDescriptor(), dbsyncReactor.SetParamsChannel) + if cfg.Mode == config.ModeValidator { if privValidator != nil { csState.SetPrivValidator(ctx, privValidator) @@ -458,7 +492,7 @@ func (n *nodeImpl) OnStart(ctx context.Context) error { // state sync will cover initialization the chain. Also calling InitChain isn't safe // when there is state sync as InitChain itself doesn't commit application state which // would get mixed up with application state writes by state sync. - if !n.shouldStateSync { + if n.shouldHandshake { // Create the handshaker, which calls RequestInfo, sets the AppVersion on the state, // and replays any blocks as necessary to sync tendermint with the app. if err := consensus.NewHandshaker(n.logger.With("module", "handshaker"), diff --git a/proto/tendermint/abci/types.proto b/proto/tendermint/abci/types.proto index 8d2637a47..f282f65d4 100644 --- a/proto/tendermint/abci/types.proto +++ b/proto/tendermint/abci/types.proto @@ -38,6 +38,7 @@ message Request { RequestBeginBlock begin_block = 20; RequestDeliverTx deliver_tx = 21; RequestEndBlock end_block = 22; + RequestLoadLatest load_latest = 23; } reserved 6, 8, 9; // RequestBeginBlock, RequestDeliverTx, RequestEndBlock } @@ -207,6 +208,8 @@ message RequestEndBlock { int64 height = 1; } +message RequestLoadLatest {} + //---------------------------------------- // Response types @@ -232,6 +235,7 @@ message Response { ResponseBeginBlock begin_block = 21; ResponseDeliverTx deliver_tx = 22; ResponseEndBlock end_block = 23; + ResponseLoadLatest load_latest = 24; } reserved 7, 9, 10; // ResponseBeginBlock, ResponseDeliverTx, ResponseEndBlock } @@ -400,6 +404,8 @@ message ResponseFinalizeBlock { bytes app_hash = 5; } +message ResponseLoadLatest {} + //---------------------------------------- // Misc. @@ -591,4 +597,5 @@ service ABCIApplication { rpc ExtendVote(RequestExtendVote) returns (ResponseExtendVote); rpc VerifyVoteExtension(RequestVerifyVoteExtension) returns (ResponseVerifyVoteExtension); rpc FinalizeBlock(RequestFinalizeBlock) returns (ResponseFinalizeBlock); + rpc LoadLatest(RequestLoadLatest) returns (ResponseLoadLatest); } diff --git a/proto/tendermint/dbsync/message.go b/proto/tendermint/dbsync/message.go new file mode 100644 index 000000000..b50067cca --- /dev/null +++ b/proto/tendermint/dbsync/message.go @@ -0,0 +1,84 @@ +package dbsync + +import ( + "errors" + "fmt" + + "github.com/gogo/protobuf/proto" +) + +// Wrap implements the p2p Wrapper interface and wraps a state sync proto message. +func (m *Message) Wrap(pb proto.Message) error { + switch msg := pb.(type) { + case *MetadataRequest: + m.Sum = &Message_MetadataRequest{MetadataRequest: msg} + + case *MetadataResponse: + m.Sum = &Message_MetadataResponse{MetadataResponse: msg} + + case *FileRequest: + m.Sum = &Message_FileRequest{FileRequest: msg} + + case *FileResponse: + m.Sum = &Message_FileResponse{FileResponse: msg} + + case *LightBlockRequest: + m.Sum = &Message_LightBlockRequest{LightBlockRequest: msg} + + case *LightBlockResponse: + m.Sum = &Message_LightBlockResponse{LightBlockResponse: msg} + + case *ParamsRequest: + m.Sum = &Message_ParamsRequest{ParamsRequest: msg} + + case *ParamsResponse: + m.Sum = &Message_ParamsResponse{ParamsResponse: msg} + + default: + return fmt.Errorf("unknown message: %T", msg) + } + + return nil +} + +// Unwrap implements the p2p Wrapper interface and unwraps a wrapped state sync +// proto message. +func (m *Message) Unwrap() (proto.Message, error) { + switch msg := m.Sum.(type) { + case *Message_MetadataRequest: + return m.GetMetadataRequest(), nil + + case *Message_MetadataResponse: + return m.GetMetadataResponse(), nil + + case *Message_FileRequest: + return m.GetFileRequest(), nil + + case *Message_FileResponse: + return m.GetFileResponse(), nil + + case *Message_LightBlockRequest: + return m.GetLightBlockRequest(), nil + + case *Message_LightBlockResponse: + return m.GetLightBlockResponse(), nil + + case *Message_ParamsRequest: + return m.GetParamsRequest(), nil + + case *Message_ParamsResponse: + return m.GetParamsResponse(), nil + + default: + return nil, fmt.Errorf("unknown message: %T", msg) + } +} + +// Validate validates the message returning an error upon failure. +func (m *Message) Validate() error { + if m == nil { + return errors.New("message cannot be nil") + } + + return nil +} diff --git a/proto/tendermint/dbsync/types.pb.go b/proto/tendermint/dbsync/types.pb.go new file mode 100644 index 000000000..d3e364bde --- /dev/null +++ b/proto/tendermint/dbsync/types.pb.go @@ -0,0 +1,2568 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: tendermint/dbsync/types.proto + +package dbsync + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + types "github.com/tendermint/tendermint/proto/tendermint/types" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type Message struct { + // Types that are valid to be assigned to Sum: + // *Message_MetadataRequest + // *Message_MetadataResponse + // *Message_FileRequest + // *Message_FileResponse + // *Message_LightBlockRequest + // *Message_LightBlockResponse + // *Message_ParamsRequest + // *Message_ParamsResponse + Sum isMessage_Sum `protobuf_oneof:"sum"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_aab44cdc90da47cb, []int{0} +} +func (m *Message) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Message.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 *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(m, src) +} +func (m *Message) XXX_Size() int { + return m.Size() +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +type isMessage_Sum interface { + isMessage_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type Message_MetadataRequest struct { + MetadataRequest *MetadataRequest `protobuf:"bytes,1,opt,name=metadata_request,json=metadataRequest,proto3,oneof" json:"metadata_request,omitempty"` +} +type Message_MetadataResponse struct { + MetadataResponse *MetadataResponse `protobuf:"bytes,2,opt,name=metadata_response,json=metadataResponse,proto3,oneof" json:"metadata_response,omitempty"` +} +type Message_FileRequest struct { + FileRequest *FileRequest `protobuf:"bytes,3,opt,name=file_request,json=fileRequest,proto3,oneof" json:"file_request,omitempty"` +} +type Message_FileResponse struct { + FileResponse *FileResponse `protobuf:"bytes,4,opt,name=file_response,json=fileResponse,proto3,oneof" json:"file_response,omitempty"` +} +type Message_LightBlockRequest struct { + LightBlockRequest *LightBlockRequest `protobuf:"bytes,5,opt,name=light_block_request,json=lightBlockRequest,proto3,oneof" json:"light_block_request,omitempty"` +} +type Message_LightBlockResponse struct { + LightBlockResponse *LightBlockResponse `protobuf:"bytes,6,opt,name=light_block_response,json=lightBlockResponse,proto3,oneof" json:"light_block_response,omitempty"` +} +type Message_ParamsRequest struct { + ParamsRequest *ParamsRequest `protobuf:"bytes,7,opt,name=params_request,json=paramsRequest,proto3,oneof" json:"params_request,omitempty"` +} +type Message_ParamsResponse struct { + ParamsResponse *ParamsResponse `protobuf:"bytes,8,opt,name=params_response,json=paramsResponse,proto3,oneof" json:"params_response,omitempty"` +} + +func (*Message_MetadataRequest) isMessage_Sum() {} +func (*Message_MetadataResponse) isMessage_Sum() {} +func (*Message_FileRequest) isMessage_Sum() {} +func (*Message_FileResponse) isMessage_Sum() {} +func (*Message_LightBlockRequest) isMessage_Sum() {} +func (*Message_LightBlockResponse) isMessage_Sum() {} +func (*Message_ParamsRequest) isMessage_Sum() {} +func (*Message_ParamsResponse) isMessage_Sum() {} + +func (m *Message) GetSum() isMessage_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *Message) GetMetadataRequest() *MetadataRequest { + if x, ok := m.GetSum().(*Message_MetadataRequest); ok { + return x.MetadataRequest + } + return nil +} + +func (m *Message) GetMetadataResponse() *MetadataResponse { + if x, ok := m.GetSum().(*Message_MetadataResponse); ok { + return x.MetadataResponse + } + return nil +} + +func (m *Message) GetFileRequest() *FileRequest { + if x, ok := m.GetSum().(*Message_FileRequest); ok { + return x.FileRequest + } + return nil +} + +func (m *Message) GetFileResponse() *FileResponse { + if x, ok := m.GetSum().(*Message_FileResponse); ok { + return x.FileResponse + } + return nil +} + +func (m *Message) GetLightBlockRequest() *LightBlockRequest { + if x, ok := m.GetSum().(*Message_LightBlockRequest); ok { + return x.LightBlockRequest + } + return nil +} + +func (m *Message) GetLightBlockResponse() *LightBlockResponse { + if x, ok := m.GetSum().(*Message_LightBlockResponse); ok { + return x.LightBlockResponse + } + return nil +} + +func (m *Message) GetParamsRequest() *ParamsRequest { + if x, ok := m.GetSum().(*Message_ParamsRequest); ok { + return x.ParamsRequest + } + return nil +} + +func (m *Message) GetParamsResponse() *ParamsResponse { + if x, ok := m.GetSum().(*Message_ParamsResponse); ok { + return x.ParamsResponse + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Message) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Message_MetadataRequest)(nil), + (*Message_MetadataResponse)(nil), + (*Message_FileRequest)(nil), + (*Message_FileResponse)(nil), + (*Message_LightBlockRequest)(nil), + (*Message_LightBlockResponse)(nil), + (*Message_ParamsRequest)(nil), + (*Message_ParamsResponse)(nil), + } +} + +type MetadataRequest struct { +} + +func (m *MetadataRequest) Reset() { *m = MetadataRequest{} } +func (m *MetadataRequest) String() string { return proto.CompactTextString(m) } +func (*MetadataRequest) ProtoMessage() {} +func (*MetadataRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_aab44cdc90da47cb, []int{1} +} +func (m *MetadataRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MetadataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MetadataRequest.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 *MetadataRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MetadataRequest.Merge(m, src) +} +func (m *MetadataRequest) XXX_Size() int { + return m.Size() +} +func (m *MetadataRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MetadataRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MetadataRequest proto.InternalMessageInfo + +type MetadataResponse struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` + Filenames []string `protobuf:"bytes,3,rep,name=filenames,proto3" json:"filenames,omitempty"` + Md5Checksum [][]byte `protobuf:"bytes,4,rep,name=md5checksum,proto3" json:"md5checksum,omitempty"` +} + +func (m *MetadataResponse) Reset() { *m = MetadataResponse{} } +func (m *MetadataResponse) String() string { return proto.CompactTextString(m) } +func (*MetadataResponse) ProtoMessage() {} +func (*MetadataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_aab44cdc90da47cb, []int{2} +} +func (m *MetadataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MetadataResponse.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 *MetadataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MetadataResponse.Merge(m, src) +} +func (m *MetadataResponse) XXX_Size() int { + return m.Size() +} +func (m *MetadataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MetadataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MetadataResponse proto.InternalMessageInfo + +func (m *MetadataResponse) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *MetadataResponse) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *MetadataResponse) GetFilenames() []string { + if m != nil { + return m.Filenames + } + return nil +} + +func (m *MetadataResponse) GetMd5Checksum() [][]byte { + if m != nil { + return m.Md5Checksum + } + return nil +} + +type FileRequest struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Filename string `protobuf:"bytes,2,opt,name=filename,proto3" json:"filename,omitempty"` +} + +func (m *FileRequest) Reset() { *m = FileRequest{} } +func (m *FileRequest) String() string { return proto.CompactTextString(m) } +func (*FileRequest) ProtoMessage() {} +func (*FileRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_aab44cdc90da47cb, []int{3} +} +func (m *FileRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FileRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FileRequest.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 *FileRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_FileRequest.Merge(m, src) +} +func (m *FileRequest) XXX_Size() int { + return m.Size() +} +func (m *FileRequest) XXX_DiscardUnknown() { + xxx_messageInfo_FileRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_FileRequest proto.InternalMessageInfo + +func (m *FileRequest) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *FileRequest) GetFilename() string { + if m != nil { + return m.Filename + } + return "" +} + +type FileResponse struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Filename string `protobuf:"bytes,2,opt,name=filename,proto3" json:"filename,omitempty"` + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` +} + +func (m *FileResponse) Reset() { *m = FileResponse{} } +func (m *FileResponse) String() string { return proto.CompactTextString(m) } +func (*FileResponse) ProtoMessage() {} +func (*FileResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_aab44cdc90da47cb, []int{4} +} +func (m *FileResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FileResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FileResponse.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 *FileResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_FileResponse.Merge(m, src) +} +func (m *FileResponse) XXX_Size() int { + return m.Size() +} +func (m *FileResponse) XXX_DiscardUnknown() { + xxx_messageInfo_FileResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_FileResponse proto.InternalMessageInfo + +func (m *FileResponse) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *FileResponse) GetFilename() string { + if m != nil { + return m.Filename + } + return "" +} + +func (m *FileResponse) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +type LightBlockRequest struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *LightBlockRequest) Reset() { *m = LightBlockRequest{} } +func (m *LightBlockRequest) String() string { return proto.CompactTextString(m) } +func (*LightBlockRequest) ProtoMessage() {} +func (*LightBlockRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_aab44cdc90da47cb, []int{5} +} +func (m *LightBlockRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LightBlockRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LightBlockRequest.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 *LightBlockRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_LightBlockRequest.Merge(m, src) +} +func (m *LightBlockRequest) XXX_Size() int { + return m.Size() +} +func (m *LightBlockRequest) XXX_DiscardUnknown() { + xxx_messageInfo_LightBlockRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_LightBlockRequest proto.InternalMessageInfo + +func (m *LightBlockRequest) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +type LightBlockResponse struct { + LightBlock *types.LightBlock `protobuf:"bytes,1,opt,name=light_block,json=lightBlock,proto3" json:"light_block,omitempty"` +} + +func (m *LightBlockResponse) Reset() { *m = LightBlockResponse{} } +func (m *LightBlockResponse) String() string { return proto.CompactTextString(m) } +func (*LightBlockResponse) ProtoMessage() {} +func (*LightBlockResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_aab44cdc90da47cb, []int{6} +} +func (m *LightBlockResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LightBlockResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LightBlockResponse.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 *LightBlockResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_LightBlockResponse.Merge(m, src) +} +func (m *LightBlockResponse) XXX_Size() int { + return m.Size() +} +func (m *LightBlockResponse) XXX_DiscardUnknown() { + xxx_messageInfo_LightBlockResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_LightBlockResponse proto.InternalMessageInfo + +func (m *LightBlockResponse) GetLightBlock() *types.LightBlock { + if m != nil { + return m.LightBlock + } + return nil +} + +type ParamsRequest struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *ParamsRequest) Reset() { *m = ParamsRequest{} } +func (m *ParamsRequest) String() string { return proto.CompactTextString(m) } +func (*ParamsRequest) ProtoMessage() {} +func (*ParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_aab44cdc90da47cb, []int{7} +} +func (m *ParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ParamsRequest.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 *ParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ParamsRequest.Merge(m, src) +} +func (m *ParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *ParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ParamsRequest proto.InternalMessageInfo + +func (m *ParamsRequest) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +type ParamsResponse struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + ConsensusParams types.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` +} + +func (m *ParamsResponse) Reset() { *m = ParamsResponse{} } +func (m *ParamsResponse) String() string { return proto.CompactTextString(m) } +func (*ParamsResponse) ProtoMessage() {} +func (*ParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_aab44cdc90da47cb, []int{8} +} +func (m *ParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ParamsResponse.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 *ParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ParamsResponse.Merge(m, src) +} +func (m *ParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *ParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ParamsResponse proto.InternalMessageInfo + +func (m *ParamsResponse) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *ParamsResponse) GetConsensusParams() types.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return types.ConsensusParams{} +} + +func init() { + proto.RegisterType((*Message)(nil), "tendermint.dbsync.Message") + proto.RegisterType((*MetadataRequest)(nil), "tendermint.dbsync.MetadataRequest") + proto.RegisterType((*MetadataResponse)(nil), "tendermint.dbsync.MetadataResponse") + proto.RegisterType((*FileRequest)(nil), "tendermint.dbsync.FileRequest") + proto.RegisterType((*FileResponse)(nil), "tendermint.dbsync.FileResponse") + proto.RegisterType((*LightBlockRequest)(nil), "tendermint.dbsync.LightBlockRequest") + proto.RegisterType((*LightBlockResponse)(nil), "tendermint.dbsync.LightBlockResponse") + proto.RegisterType((*ParamsRequest)(nil), "tendermint.dbsync.ParamsRequest") + proto.RegisterType((*ParamsResponse)(nil), "tendermint.dbsync.ParamsResponse") +} + +func init() { proto.RegisterFile("tendermint/dbsync/types.proto", fileDescriptor_aab44cdc90da47cb) } + +var fileDescriptor_aab44cdc90da47cb = []byte{ + // 577 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xcb, 0x6a, 0xdb, 0x40, + 0x18, 0x85, 0xe5, 0xfa, 0x92, 0xf8, 0xb7, 0x7c, 0x9b, 0x86, 0x62, 0x8c, 0xa3, 0x38, 0x6a, 0x4b, + 0x0d, 0x05, 0x1b, 0x5a, 0x0a, 0xdd, 0x74, 0x51, 0x07, 0x42, 0x0a, 0x09, 0x2d, 0x53, 0x08, 0xb4, + 0x1b, 0x23, 0xcb, 0x63, 0x4b, 0x44, 0x23, 0xa9, 0x1e, 0x69, 0x11, 0x28, 0x7d, 0x84, 0xd2, 0xc7, + 0xca, 0x32, 0xcb, 0xae, 0x4a, 0xb1, 0x5f, 0xa4, 0x68, 0xa4, 0x48, 0x23, 0xc9, 0x4a, 0x21, 0xbb, + 0x99, 0xf3, 0x1f, 0x7f, 0x73, 0x24, 0x1d, 0x0f, 0x1c, 0x7a, 0xc4, 0x5e, 0x90, 0x35, 0x35, 0x6d, + 0x6f, 0xb2, 0x98, 0xb3, 0x6b, 0x5b, 0x9f, 0x78, 0xd7, 0x2e, 0x61, 0x63, 0x77, 0xed, 0x78, 0x0e, + 0xea, 0x26, 0xe3, 0x71, 0x38, 0xee, 0x1f, 0xac, 0x9c, 0x95, 0xc3, 0xa7, 0x93, 0x60, 0x15, 0x1a, + 0xfb, 0x03, 0x81, 0xc3, 0x01, 0x22, 0xa6, 0x7f, 0x98, 0x9b, 0xba, 0xda, 0x5a, 0xa3, 0xd1, 0x58, + 0xfd, 0x59, 0x85, 0xbd, 0x0b, 0xc2, 0x98, 0xb6, 0x22, 0xe8, 0x23, 0x74, 0x28, 0xf1, 0xb4, 0x85, + 0xe6, 0x69, 0xb3, 0x35, 0xf9, 0xe6, 0x13, 0xe6, 0xf5, 0x4a, 0xc3, 0xd2, 0xa8, 0xf1, 0x4a, 0x1d, + 0xe7, 0xc2, 0x8c, 0x2f, 0x22, 0x2b, 0x0e, 0x9d, 0x67, 0x12, 0x6e, 0xd3, 0xb4, 0x84, 0x30, 0x74, + 0x05, 0x20, 0x73, 0x1d, 0x9b, 0x91, 0xde, 0x23, 0x4e, 0x7c, 0x7a, 0x2f, 0x31, 0xb4, 0x9e, 0x49, + 0xb8, 0x43, 0x33, 0x1a, 0x3a, 0x01, 0x79, 0x69, 0x5a, 0x24, 0x0e, 0x58, 0xe6, 0x38, 0x65, 0x07, + 0xee, 0xd4, 0xb4, 0x48, 0x12, 0xae, 0xb1, 0x4c, 0xb6, 0xe8, 0x14, 0x9a, 0x11, 0x24, 0x0a, 0x55, + 0xe1, 0x94, 0xa3, 0x42, 0x4a, 0x1c, 0x48, 0x5e, 0x0a, 0x7b, 0x74, 0x09, 0x8f, 0x2d, 0x73, 0x65, + 0x78, 0xb3, 0xb9, 0xe5, 0xe8, 0x57, 0x71, 0xa6, 0x2a, 0xa7, 0x3d, 0xdb, 0x41, 0x3b, 0x0f, 0xdc, + 0xd3, 0xc0, 0x9c, 0x24, 0xeb, 0x5a, 0x59, 0x11, 0x7d, 0x81, 0x83, 0x34, 0x37, 0x8a, 0x59, 0xe3, + 0xe0, 0xe7, 0xff, 0x01, 0xc7, 0x61, 0x91, 0x95, 0x53, 0xd1, 0x07, 0x68, 0x85, 0x05, 0x88, 0xd3, + 0xee, 0x71, 0xe8, 0x70, 0x07, 0xf4, 0x13, 0x37, 0x26, 0x49, 0x9b, 0xae, 0x28, 0xa0, 0x73, 0x68, + 0xc7, 0xa8, 0x28, 0xe0, 0x3e, 0x67, 0x1d, 0xdf, 0xc3, 0x8a, 0xc3, 0xb5, 0xdc, 0x94, 0x32, 0xad, + 0x42, 0x99, 0xf9, 0x54, 0xed, 0x42, 0x3b, 0xd3, 0x2c, 0xf5, 0x07, 0x74, 0xb2, 0xd5, 0x40, 0x4f, + 0xa0, 0x66, 0x90, 0xe0, 0xe9, 0x78, 0x43, 0x2b, 0x38, 0xda, 0x21, 0x04, 0x15, 0x43, 0x63, 0x06, + 0x6f, 0x99, 0x8c, 0xf9, 0x1a, 0x0d, 0xa0, 0x1e, 0x7c, 0x35, 0x5b, 0xa3, 0x84, 0xf5, 0xca, 0xc3, + 0xf2, 0xa8, 0x8e, 0x13, 0x01, 0x0d, 0xa1, 0x41, 0x17, 0x6f, 0x74, 0x83, 0xe8, 0x57, 0xcc, 0xa7, + 0xbd, 0xca, 0xb0, 0x3c, 0x92, 0xb1, 0x28, 0xa9, 0xef, 0xa1, 0x21, 0x74, 0xa9, 0xf0, 0xe8, 0x3e, + 0xec, 0xdf, 0x51, 0xf9, 0xf1, 0x75, 0x1c, 0xef, 0xd5, 0x4b, 0x90, 0xc5, 0x22, 0x3d, 0x84, 0x11, + 0x3c, 0x5a, 0xf0, 0x0a, 0x78, 0xe3, 0x65, 0xcc, 0xd7, 0xea, 0x4b, 0xe8, 0xe6, 0x2a, 0x55, 0x04, + 0x57, 0x3f, 0x03, 0xca, 0xd7, 0x04, 0xbd, 0x83, 0x86, 0xd0, 0xb5, 0xe8, 0x0f, 0x3f, 0x10, 0xbf, + 0x60, 0x78, 0x9d, 0x08, 0x3f, 0x85, 0xa4, 0x57, 0xea, 0x0b, 0x68, 0xa6, 0x6a, 0x52, 0x78, 0xfa, + 0x77, 0x68, 0xa5, 0x3b, 0x50, 0xf8, 0x12, 0x30, 0x74, 0xf4, 0xc0, 0x60, 0x33, 0x9f, 0xcd, 0xc2, + 0x96, 0x44, 0xb7, 0xc6, 0x71, 0x3e, 0xd6, 0xc9, 0x9d, 0x33, 0x84, 0x4f, 0x2b, 0x37, 0x7f, 0x8e, + 0x24, 0xdc, 0xd6, 0x33, 0x32, 0xbe, 0xd9, 0x28, 0xa5, 0xdb, 0x8d, 0x52, 0xfa, 0xbb, 0x51, 0x4a, + 0xbf, 0xb6, 0x8a, 0x74, 0xbb, 0x55, 0xa4, 0xdf, 0x5b, 0x45, 0xfa, 0xfa, 0x76, 0x65, 0x7a, 0x86, + 0x3f, 0x1f, 0xeb, 0x0e, 0x9d, 0x88, 0x77, 0x65, 0xb2, 0x0c, 0x6f, 0xdc, 0xdc, 0x6d, 0x3d, 0xaf, + 0xf1, 0xc1, 0xeb, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x94, 0x9f, 0x5e, 0x2b, 0xc9, 0x05, 0x00, + 0x00, +} + +func (m *Message) 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 *Message) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Message_MetadataRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_MetadataRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.MetadataRequest != nil { + { + size, err := m.MetadataRequest.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 *Message_MetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_MetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.MetadataResponse != nil { + { + size, err := m.MetadataResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Message_FileRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_FileRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.FileRequest != nil { + { + size, err := m.FileRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Message_FileResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_FileResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.FileResponse != nil { + { + size, err := m.FileResponse.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 *Message_LightBlockRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_LightBlockRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LightBlockRequest != nil { + { + size, err := m.LightBlockRequest.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 *Message_LightBlockResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_LightBlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LightBlockResponse != nil { + { + size, err := m.LightBlockResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Message_ParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_ParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ParamsRequest != nil { + { + size, err := m.ParamsRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Message_ParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_ParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ParamsResponse != nil { + { + size, err := m.ParamsResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *MetadataRequest) 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 *MetadataRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MetadataRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MetadataResponse) 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 *MetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Md5Checksum) > 0 { + for iNdEx := len(m.Md5Checksum) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Md5Checksum[iNdEx]) + copy(dAtA[i:], m.Md5Checksum[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Md5Checksum[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Filenames) > 0 { + for iNdEx := len(m.Filenames) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Filenames[iNdEx]) + copy(dAtA[i:], m.Filenames[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Filenames[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + 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] = 0x12 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *FileRequest) 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 *FileRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FileRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Filename) > 0 { + i -= len(m.Filename) + copy(dAtA[i:], m.Filename) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Filename))) + i-- + dAtA[i] = 0x12 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *FileResponse) 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 *FileResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FileResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x1a + } + if len(m.Filename) > 0 { + i -= len(m.Filename) + copy(dAtA[i:], m.Filename) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Filename))) + i-- + dAtA[i] = 0x12 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *LightBlockRequest) 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 *LightBlockRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LightBlockRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *LightBlockResponse) 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 *LightBlockResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LightBlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.LightBlock != nil { + { + size, err := m.LightBlock.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 *ParamsRequest) 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 *ParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ParamsResponse) 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 *ParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Message) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *Message_MetadataRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MetadataRequest != nil { + l = m.MetadataRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_MetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MetadataResponse != nil { + l = m.MetadataResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_FileRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.FileRequest != nil { + l = m.FileRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_FileResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.FileResponse != nil { + l = m.FileResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_LightBlockRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LightBlockRequest != nil { + l = m.LightBlockRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_LightBlockResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LightBlockResponse != nil { + l = m.LightBlockResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_ParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ParamsRequest != nil { + l = m.ParamsRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_ParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ParamsResponse != nil { + l = m.ParamsResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *MetadataRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Filenames) > 0 { + for _, s := range m.Filenames { + l = len(s) + n += 1 + l + sovTypes(uint64(l)) + } + } + if len(m.Md5Checksum) > 0 { + for _, b := range m.Md5Checksum { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *FileRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = len(m.Filename) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *FileResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = len(m.Filename) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *LightBlockRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *LightBlockResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LightBlock != nil { + l = m.LightBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *ParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Message) 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: Message: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Message: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MetadataRequest", 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 := &MetadataRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_MetadataRequest{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MetadataResponse", 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 := &MetadataResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_MetadataResponse{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FileRequest", 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 := &FileRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_FileRequest{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FileResponse", 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 := &FileResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_FileResponse{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LightBlockRequest", 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 := &LightBlockRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_LightBlockRequest{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LightBlockResponse", 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 := &LightBlockResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_LightBlockResponse{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ParamsRequest", 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 := &ParamsRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_ParamsRequest{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ParamsResponse", 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 := &ParamsResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_ParamsResponse{v} + 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 *MetadataRequest) 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: MetadataRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MetadataRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *MetadataResponse) 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: MetadataResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + 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 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Filenames", 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.Filenames = append(m.Filenames, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Md5Checksum", 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.Md5Checksum = append(m.Md5Checksum, make([]byte, postIndex-iNdEx)) + copy(m.Md5Checksum[len(m.Md5Checksum)-1], 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 *FileRequest) 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: FileRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FileRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Filename", 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.Filename = 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 *FileResponse) 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: FileResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FileResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Filename", 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.Filename = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", 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.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []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 *LightBlockRequest) 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: LightBlockRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LightBlockRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 |= uint64(b&0x7F) << shift + if b < 0x80 { + 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 *LightBlockResponse) 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: LightBlockResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LightBlockResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LightBlock", 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.LightBlock == nil { + m.LightBlock = &types.LightBlock{} + } + if err := m.LightBlock.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 *ParamsRequest) 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: ParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 |= uint64(b&0x7F) << shift + if b < 0x80 { + 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 *ParamsResponse) 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: ParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", 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.ConsensusParams.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 skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/tendermint/dbsync/types.proto b/proto/tendermint/dbsync/types.proto new file mode 100644 index 000000000..bd7471742 --- /dev/null +++ b/proto/tendermint/dbsync/types.proto @@ -0,0 +1,59 @@ +syntax = "proto3"; +package tendermint.dbsync; + +option go_package = "github.com/tendermint/tendermint/proto/tendermint/dbsync"; + +import "gogoproto/gogo.proto"; +import "tendermint/types/types.proto"; +import "tendermint/types/params.proto"; + +message Message { + oneof sum { + MetadataRequest metadata_request = 1; + MetadataResponse metadata_response = 2; + FileRequest file_request = 3; + FileResponse file_response = 4; + LightBlockRequest light_block_request = 5; + LightBlockResponse light_block_response = 6; + ParamsRequest params_request = 7; + ParamsResponse params_response = 8; + } +} + +message MetadataRequest {} + +message MetadataResponse { + uint64 height = 1; + bytes hash = 2; + repeated string filenames = 3; + repeated bytes md5checksum = 4; +} + +message FileRequest { + uint64 height = 1; + string filename = 2; +} + +message FileResponse { + uint64 height = 1; + string filename = 2; + bytes data = 3; +} + +message LightBlockRequest { + uint64 height = 1; +} + +message LightBlockResponse { + tendermint.types.LightBlock light_block = 1; +} + +message ParamsRequest { + uint64 height = 1; +} + +message ParamsResponse { + uint64 height = 1; + tendermint.types.ConsensusParams consensus_params = 2 + [(gogoproto.nullable) = false]; +} \ No newline at end of file