diff --git a/abci/example/kvstore/kvstore.go b/abci/example/kvstore/kvstore.go index d2b2d99fe..6b98d54bb 100644 --- a/abci/example/kvstore/kvstore.go +++ b/abci/example/kvstore/kvstore.go @@ -284,7 +284,7 @@ func (app *Application) PrepareProposal(req types.RequestPrepareProposal) types. app.mu.Lock() defer app.mu.Unlock() - return types.ResponsePrepareProposal{BlockData: app.substPrepareTx(req.BlockData)} + return types.ResponsePrepareProposal{TxRecords: app.substPrepareTx(req.Txs)} } func (*Application) ProcessProposal(req types.RequestProcessProposal) types.ResponseProcessProposal { @@ -420,7 +420,7 @@ func (app *Application) updateValidator(v types.ValidatorUpdate) *types.ExecTxRe const PreparePrefix = "prepare" func isPrepareTx(tx []byte) bool { - return strings.HasPrefix(string(tx), PreparePrefix) + return bytes.HasPrefix(tx, []byte(PreparePrefix)) } // execPrepareTx is noop. tx data is considered as placeholder @@ -430,16 +430,30 @@ func (app *Application) execPrepareTx(tx []byte) *types.ExecTxResult { return &types.ExecTxResult{} } -// substPrepareTx subst all the preparetx in the blockdata -// to null string(could be any arbitrary string). -func (app *Application) substPrepareTx(blockData [][]byte) [][]byte { - // TODO: this mechanism will change with the current spec of PrepareProposal - // We now have a special type for marking a tx as changed +// substPrepareTx substitutes all the transactions prefixed with 'prepare' in the +// proposal for transactions with the prefix strips. +// It marks all of the original transactions as 'REMOVED' so that +// Tendermint will remove them from its mempool. +func (app *Application) substPrepareTx(blockData [][]byte) []*types.TxRecord { + trs := make([]*types.TxRecord, len(blockData)) + var removed []*types.TxRecord for i, tx := range blockData { if isPrepareTx(tx) { - blockData[i] = make([]byte, len(tx)) + removed = append(removed, &types.TxRecord{ + Tx: tx, + Action: types.TxRecord_REMOVED, + }) + trs[i] = &types.TxRecord{ + Tx: bytes.TrimPrefix(tx, []byte(PreparePrefix)), + Action: types.TxRecord_ADDED, + } + continue + } + trs[i] = &types.TxRecord{ + Tx: tx, + Action: types.TxRecord_UNMODIFIED, } } - return blockData + return append(trs, removed...) } diff --git a/abci/types/result.go b/abci/types/types.go similarity index 83% rename from abci/types/result.go rename to abci/types/types.go index a7198b633..4240301b5 100644 --- a/abci/types/result.go +++ b/abci/types/types.go @@ -167,3 +167,31 @@ func RespondVerifyVoteExtension(ok bool) ResponseVerifyVoteExtension { Result: result, } } + +// deterministicExecTxResult constructs a copy of response that omits +// non-deterministic fields. The input response is not modified. +func deterministicExecTxResult(response *ExecTxResult) *ExecTxResult { + return &ExecTxResult{ + Code: response.Code, + Data: response.Data, + GasWanted: response.GasWanted, + GasUsed: response.GasUsed, + } +} + +// MarshalTxResults encodes the the TxResults as a list of byte +// slices. It strips off the non-deterministic pieces of the TxResults +// so that the resulting data can be used for hash comparisons and used +// in Merkle proofs. +func MarshalTxResults(r []*ExecTxResult) ([][]byte, error) { + s := make([][]byte, len(r)) + for i, e := range r { + d := deterministicExecTxResult(e) + b, err := d.Marshal() + if err != nil { + return nil, err + } + s[i] = b + } + return s, nil +} diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index 06a25a86d..b42c1e0bf 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -191,6 +191,38 @@ func (ResponseVerifyVoteExtension_Result) EnumDescriptor() ([]byte, []int) { return fileDescriptor_252557cfdd89a31a, []int{37, 0} } +// TxAction contains App-provided information on what to do with a transaction that is part of a raw proposal +type TxRecord_TxAction int32 + +const ( + TxRecord_UNKNOWN TxRecord_TxAction = 0 + TxRecord_UNMODIFIED TxRecord_TxAction = 1 + TxRecord_ADDED TxRecord_TxAction = 2 + TxRecord_REMOVED TxRecord_TxAction = 3 +) + +var TxRecord_TxAction_name = map[int32]string{ + 0: "UNKNOWN", + 1: "UNMODIFIED", + 2: "ADDED", + 3: "REMOVED", +} + +var TxRecord_TxAction_value = map[string]int32{ + "UNKNOWN": 0, + "UNMODIFIED": 1, + "ADDED": 2, + "REMOVED": 3, +} + +func (x TxRecord_TxAction) String() string { + return proto.EnumName(TxRecord_TxAction_name, int32(x)) +} + +func (TxRecord_TxAction) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{47, 0} +} + type Request struct { // Types that are valid to be assigned to Value: // *Request_Echo @@ -1347,15 +1379,15 @@ func (m *RequestVerifyVoteExtension) GetVote() *types1.Vote { } type RequestPrepareProposal struct { - // block_data is an array of transactions that will be included in a block, + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Header types1.Header `protobuf:"bytes,2,opt,name=header,proto3" json:"header"` + // txs is an array of transactions that will be included in a block, // sent to the app for possible modifications. - // applications can not exceed the size of the data passed to it. - BlockData [][]byte `protobuf:"bytes,1,rep,name=block_data,json=blockData,proto3" json:"block_data,omitempty"` - // If an application decides to populate block_data with extra information, they can not exceed this value. - BlockDataSize int64 `protobuf:"varint,2,opt,name=block_data_size,json=blockDataSize,proto3" json:"block_data_size,omitempty"` - // votes includes all votes from the previous block. This contains vote extension data that can be used in proposal - // preparation. The votes here will then form the last commit that gets sent in the proposed block. - Votes []*types1.Vote `protobuf:"bytes,3,rep,name=votes,proto3" json:"votes,omitempty"` + Txs [][]byte `protobuf:"bytes,3,rep,name=txs,proto3" json:"txs,omitempty"` + LocalLastCommit ExtendedCommitInfo `protobuf:"bytes,4,opt,name=local_last_commit,json=localLastCommit,proto3" json:"local_last_commit"` + ByzantineValidators []Evidence `protobuf:"bytes,5,rep,name=byzantine_validators,json=byzantineValidators,proto3" json:"byzantine_validators"` + // the modified transactions cannot exceed this size. + MaxTxBytes int64 `protobuf:"varint,6,opt,name=max_tx_bytes,json=maxTxBytes,proto3" json:"max_tx_bytes,omitempty"` } func (m *RequestPrepareProposal) Reset() { *m = RequestPrepareProposal{} } @@ -1391,27 +1423,48 @@ func (m *RequestPrepareProposal) XXX_DiscardUnknown() { var xxx_messageInfo_RequestPrepareProposal proto.InternalMessageInfo -func (m *RequestPrepareProposal) GetBlockData() [][]byte { +func (m *RequestPrepareProposal) GetHash() []byte { if m != nil { - return m.BlockData + return m.Hash } return nil } -func (m *RequestPrepareProposal) GetBlockDataSize() int64 { +func (m *RequestPrepareProposal) GetHeader() types1.Header { if m != nil { - return m.BlockDataSize + return m.Header } - return 0 + return types1.Header{} } -func (m *RequestPrepareProposal) GetVotes() []*types1.Vote { +func (m *RequestPrepareProposal) GetTxs() [][]byte { if m != nil { - return m.Votes + return m.Txs + } + return nil +} + +func (m *RequestPrepareProposal) GetLocalLastCommit() ExtendedCommitInfo { + if m != nil { + return m.LocalLastCommit + } + return ExtendedCommitInfo{} +} + +func (m *RequestPrepareProposal) GetByzantineValidators() []Evidence { + if m != nil { + return m.ByzantineValidators } return nil } +func (m *RequestPrepareProposal) GetMaxTxBytes() int64 { + if m != nil { + return m.MaxTxBytes + } + return 0 +} + type RequestProcessProposal struct { Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` Header types1.Header `protobuf:"bytes,2,opt,name=header,proto3" json:"header"` @@ -2920,7 +2973,12 @@ func (m *ResponseVerifyVoteExtension) GetResult() ResponseVerifyVoteExtension_Re } type ResponsePrepareProposal struct { - BlockData [][]byte `protobuf:"bytes,1,rep,name=block_data,json=blockData,proto3" json:"block_data,omitempty"` + ModifiedTx bool `protobuf:"varint,1,opt,name=modified_tx,json=modifiedTx,proto3" json:"modified_tx,omitempty"` + TxRecords []*TxRecord `protobuf:"bytes,2,rep,name=tx_records,json=txRecords,proto3" json:"tx_records,omitempty"` + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` + TxResults []*ExecTxResult `protobuf:"bytes,4,rep,name=tx_results,json=txResults,proto3" json:"tx_results,omitempty"` + ValidatorUpdates []*ValidatorUpdate `protobuf:"bytes,5,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates,omitempty"` + ConsensusParamUpdates *types1.ConsensusParams `protobuf:"bytes,6,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` } func (m *ResponsePrepareProposal) Reset() { *m = ResponsePrepareProposal{} } @@ -2956,9 +3014,44 @@ func (m *ResponsePrepareProposal) XXX_DiscardUnknown() { var xxx_messageInfo_ResponsePrepareProposal proto.InternalMessageInfo -func (m *ResponsePrepareProposal) GetBlockData() [][]byte { +func (m *ResponsePrepareProposal) GetModifiedTx() bool { + if m != nil { + return m.ModifiedTx + } + return false +} + +func (m *ResponsePrepareProposal) GetTxRecords() []*TxRecord { + if m != nil { + return m.TxRecords + } + return nil +} + +func (m *ResponsePrepareProposal) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +func (m *ResponsePrepareProposal) GetTxResults() []*ExecTxResult { + if m != nil { + return m.TxResults + } + return nil +} + +func (m *ResponsePrepareProposal) GetValidatorUpdates() []*ValidatorUpdate { if m != nil { - return m.BlockData + return m.ValidatorUpdates + } + return nil +} + +func (m *ResponsePrepareProposal) GetConsensusParamUpdates() *types1.ConsensusParams { + if m != nil { + return m.ConsensusParamUpdates } return nil } @@ -3175,6 +3268,58 @@ func (m *CommitInfo) GetVotes() []VoteInfo { return nil } +type ExtendedCommitInfo struct { + Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` + Votes []ExtendedVoteInfo `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes"` +} + +func (m *ExtendedCommitInfo) Reset() { *m = ExtendedCommitInfo{} } +func (m *ExtendedCommitInfo) String() string { return proto.CompactTextString(m) } +func (*ExtendedCommitInfo) ProtoMessage() {} +func (*ExtendedCommitInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{42} +} +func (m *ExtendedCommitInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExtendedCommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExtendedCommitInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExtendedCommitInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendedCommitInfo.Merge(m, src) +} +func (m *ExtendedCommitInfo) XXX_Size() int { + return m.Size() +} +func (m *ExtendedCommitInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendedCommitInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtendedCommitInfo proto.InternalMessageInfo + +func (m *ExtendedCommitInfo) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *ExtendedCommitInfo) GetVotes() []ExtendedVoteInfo { + if m != nil { + return m.Votes + } + return nil +} + // Event allows application developers to attach additional information to // ResponseBeginBlock, ResponseEndBlock, ResponseCheckTx and ResponseDeliverTx. // Later, transactions may be queried using these events. @@ -3187,7 +3332,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{42} + return fileDescriptor_252557cfdd89a31a, []int{43} } func (m *Event) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3241,7 +3386,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{43} + return fileDescriptor_252557cfdd89a31a, []int{44} } func (m *EventAttribute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3309,7 +3454,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{44} + return fileDescriptor_252557cfdd89a31a, []int{45} } func (m *ExecTxResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3408,7 +3553,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{45} + return fileDescriptor_252557cfdd89a31a, []int{46} } func (m *TxResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3465,6 +3610,58 @@ func (m *TxResult) GetResult() ExecTxResult { return ExecTxResult{} } +type TxRecord struct { + Action TxRecord_TxAction `protobuf:"varint,1,opt,name=action,proto3,enum=tendermint.abci.TxRecord_TxAction" json:"action,omitempty"` + Tx []byte `protobuf:"bytes,2,opt,name=tx,proto3" json:"tx,omitempty"` +} + +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{47} +} +func (m *TxRecord) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TxRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TxRecord.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 *TxRecord) XXX_Merge(src proto.Message) { + xxx_messageInfo_TxRecord.Merge(m, src) +} +func (m *TxRecord) XXX_Size() int { + return m.Size() +} +func (m *TxRecord) XXX_DiscardUnknown() { + xxx_messageInfo_TxRecord.DiscardUnknown(m) +} + +var xxx_messageInfo_TxRecord proto.InternalMessageInfo + +func (m *TxRecord) GetAction() TxRecord_TxAction { + if m != nil { + return m.Action + } + return TxRecord_UNKNOWN +} + +func (m *TxRecord) GetTx() []byte { + if m != nil { + return m.Tx + } + return nil +} + // Validator type Validator struct { Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` @@ -3476,7 +3673,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{46} + return fileDescriptor_252557cfdd89a31a, []int{48} } func (m *Validator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3529,7 +3726,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{47} + return fileDescriptor_252557cfdd89a31a, []int{49} } func (m *ValidatorUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3582,7 +3779,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{48} + return fileDescriptor_252557cfdd89a31a, []int{50} } func (m *VoteInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3625,6 +3822,66 @@ func (m *VoteInfo) GetSignedLastBlock() bool { return false } +type ExtendedVoteInfo struct { + Validator Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator"` + SignedLastBlock bool `protobuf:"varint,2,opt,name=signed_last_block,json=signedLastBlock,proto3" json:"signed_last_block,omitempty"` + VoteExtension []byte `protobuf:"bytes,3,opt,name=vote_extension,json=voteExtension,proto3" json:"vote_extension,omitempty"` +} + +func (m *ExtendedVoteInfo) Reset() { *m = ExtendedVoteInfo{} } +func (m *ExtendedVoteInfo) String() string { return proto.CompactTextString(m) } +func (*ExtendedVoteInfo) ProtoMessage() {} +func (*ExtendedVoteInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_252557cfdd89a31a, []int{51} +} +func (m *ExtendedVoteInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExtendedVoteInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExtendedVoteInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExtendedVoteInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendedVoteInfo.Merge(m, src) +} +func (m *ExtendedVoteInfo) XXX_Size() int { + return m.Size() +} +func (m *ExtendedVoteInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendedVoteInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtendedVoteInfo proto.InternalMessageInfo + +func (m *ExtendedVoteInfo) GetValidator() Validator { + if m != nil { + return m.Validator + } + return Validator{} +} + +func (m *ExtendedVoteInfo) GetSignedLastBlock() bool { + if m != nil { + return m.SignedLastBlock + } + return false +} + +func (m *ExtendedVoteInfo) GetVoteExtension() []byte { + if m != nil { + return m.VoteExtension + } + return nil +} + type Evidence struct { Type EvidenceType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.abci.EvidenceType" json:"type,omitempty"` // The offending validator @@ -3643,7 +3900,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{49} + return fileDescriptor_252557cfdd89a31a, []int{52} } func (m *Evidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3719,7 +3976,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{50} + return fileDescriptor_252557cfdd89a31a, []int{53} } func (m *Snapshot) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3789,6 +4046,7 @@ func init() { proto.RegisterEnum("tendermint.abci.ResponseOfferSnapshot_Result", ResponseOfferSnapshot_Result_name, ResponseOfferSnapshot_Result_value) proto.RegisterEnum("tendermint.abci.ResponseApplySnapshotChunk_Result", ResponseApplySnapshotChunk_Result_name, ResponseApplySnapshotChunk_Result_value) proto.RegisterEnum("tendermint.abci.ResponseVerifyVoteExtension_Result", ResponseVerifyVoteExtension_Result_name, ResponseVerifyVoteExtension_Result_value) + proto.RegisterEnum("tendermint.abci.TxRecord_TxAction", TxRecord_TxAction_name, TxRecord_TxAction_value) proto.RegisterType((*Request)(nil), "tendermint.abci.Request") proto.RegisterType((*RequestEcho)(nil), "tendermint.abci.RequestEcho") proto.RegisterType((*RequestFlush)(nil), "tendermint.abci.RequestFlush") @@ -3831,13 +4089,16 @@ func init() { proto.RegisterType((*ResponseProcessProposal)(nil), "tendermint.abci.ResponseProcessProposal") proto.RegisterType((*ResponseFinalizeBlock)(nil), "tendermint.abci.ResponseFinalizeBlock") proto.RegisterType((*CommitInfo)(nil), "tendermint.abci.CommitInfo") + proto.RegisterType((*ExtendedCommitInfo)(nil), "tendermint.abci.ExtendedCommitInfo") proto.RegisterType((*Event)(nil), "tendermint.abci.Event") proto.RegisterType((*EventAttribute)(nil), "tendermint.abci.EventAttribute") proto.RegisterType((*ExecTxResult)(nil), "tendermint.abci.ExecTxResult") proto.RegisterType((*TxResult)(nil), "tendermint.abci.TxResult") + proto.RegisterType((*TxRecord)(nil), "tendermint.abci.TxRecord") proto.RegisterType((*Validator)(nil), "tendermint.abci.Validator") proto.RegisterType((*ValidatorUpdate)(nil), "tendermint.abci.ValidatorUpdate") proto.RegisterType((*VoteInfo)(nil), "tendermint.abci.VoteInfo") + proto.RegisterType((*ExtendedVoteInfo)(nil), "tendermint.abci.ExtendedVoteInfo") proto.RegisterType((*Evidence)(nil), "tendermint.abci.Evidence") proto.RegisterType((*Snapshot)(nil), "tendermint.abci.Snapshot") } @@ -3845,209 +4106,220 @@ func init() { func init() { proto.RegisterFile("tendermint/abci/types.proto", fileDescriptor_252557cfdd89a31a) } var fileDescriptor_252557cfdd89a31a = []byte{ - // 3225 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0xcd, 0x73, 0xdb, 0xd6, - 0x11, 0xe7, 0xb7, 0xc8, 0xe5, 0xa7, 0x9e, 0x14, 0x85, 0x66, 0x6c, 0xc9, 0x81, 0x27, 0x89, 0xe3, - 0x38, 0x52, 0x23, 0x4f, 0x52, 0x67, 0x92, 0xb6, 0x23, 0xd2, 0x54, 0x28, 0x4b, 0x91, 0x14, 0x88, - 0x72, 0x26, 0x6d, 0x6a, 0x04, 0x24, 0x9e, 0x48, 0xc4, 0x24, 0x80, 0x00, 0x20, 0x23, 0xf9, 0xd4, - 0xe9, 0x4c, 0x2e, 0x99, 0x76, 0x9a, 0x63, 0x67, 0x3a, 0x99, 0x5e, 0x7a, 0xe8, 0x1f, 0xd0, 0x43, - 0x4f, 0x3d, 0xf5, 0x90, 0x43, 0x0f, 0xb9, 0xb5, 0xd3, 0x43, 0xda, 0x49, 0x6e, 0xfd, 0x07, 0x7a, - 0xea, 0xc7, 0xbc, 0x0f, 0x7c, 0x91, 0x04, 0x3f, 0x62, 0xbb, 0x97, 0xde, 0xf0, 0x16, 0xbb, 0x8b, - 0xf7, 0x16, 0xef, 0xed, 0xee, 0x6f, 0xf7, 0xc1, 0x33, 0x36, 0xd6, 0x14, 0x6c, 0xf6, 0x55, 0xcd, - 0xde, 0x92, 0x5b, 0x6d, 0x75, 0xcb, 0xbe, 0x30, 0xb0, 0xb5, 0x69, 0x98, 0xba, 0xad, 0xa3, 0xa2, - 0xf7, 0x72, 0x93, 0xbc, 0xac, 0x5c, 0xf1, 0x71, 0xb7, 0xcd, 0x0b, 0xc3, 0xd6, 0xb7, 0x0c, 0x53, - 0xd7, 0xcf, 0x18, 0x7f, 0xe5, 0xb2, 0xef, 0x35, 0xd5, 0xe3, 0xd7, 0x16, 0x78, 0xcb, 0x85, 0x1f, - 0xe0, 0x0b, 0xe7, 0xed, 0x95, 0x31, 0x59, 0x43, 0x36, 0xe5, 0xbe, 0xf3, 0x7a, 0xa3, 0xa3, 0xeb, - 0x9d, 0x1e, 0xde, 0xa2, 0xa3, 0xd6, 0xe0, 0x6c, 0xcb, 0x56, 0xfb, 0xd8, 0xb2, 0xe5, 0xbe, 0xc1, - 0x19, 0x56, 0x3b, 0x7a, 0x47, 0xa7, 0x8f, 0x5b, 0xe4, 0x89, 0x51, 0x85, 0xff, 0x00, 0x2c, 0x89, - 0xf8, 0xa3, 0x01, 0xb6, 0x6c, 0xb4, 0x0d, 0x09, 0xdc, 0xee, 0xea, 0xe5, 0xe8, 0xd5, 0xe8, 0xf5, - 0xec, 0xf6, 0xe5, 0xcd, 0x91, 0xc5, 0x6d, 0x72, 0xbe, 0x7a, 0xbb, 0xab, 0x37, 0x22, 0x22, 0xe5, - 0x45, 0xaf, 0x42, 0xf2, 0xac, 0x37, 0xb0, 0xba, 0xe5, 0x18, 0x15, 0xba, 0x12, 0x26, 0xb4, 0x4b, - 0x98, 0x1a, 0x11, 0x91, 0x71, 0x93, 0x4f, 0xa9, 0xda, 0x99, 0x5e, 0x8e, 0x4f, 0xff, 0xd4, 0x9e, - 0x76, 0x46, 0x3f, 0x45, 0x78, 0x51, 0x15, 0x40, 0xd5, 0x54, 0x5b, 0x6a, 0x77, 0x65, 0x55, 0x2b, - 0x27, 0xa8, 0xe4, 0xb3, 0xe1, 0x92, 0xaa, 0x5d, 0x23, 0x8c, 0x8d, 0x88, 0x98, 0x51, 0x9d, 0x01, - 0x99, 0xee, 0x47, 0x03, 0x6c, 0x5e, 0x94, 0x93, 0xd3, 0xa7, 0xfb, 0x0e, 0x61, 0x22, 0xd3, 0xa5, - 0xdc, 0x68, 0x0f, 0xb2, 0x2d, 0xdc, 0x51, 0x35, 0xa9, 0xd5, 0xd3, 0xdb, 0x0f, 0xca, 0x29, 0x2a, - 0x2c, 0x84, 0x09, 0x57, 0x09, 0x6b, 0x95, 0x70, 0x56, 0x63, 0xe5, 0x68, 0x23, 0x22, 0x42, 0xcb, - 0xa5, 0xa0, 0x37, 0x21, 0xdd, 0xee, 0xe2, 0xf6, 0x03, 0xc9, 0x3e, 0x2f, 0x2f, 0x51, 0x3d, 0x1b, - 0x61, 0x7a, 0x6a, 0x84, 0xaf, 0x79, 0xde, 0x88, 0x88, 0x4b, 0x6d, 0xf6, 0x88, 0x76, 0x01, 0x14, - 0xdc, 0x53, 0x87, 0xd8, 0x24, 0xf2, 0xe9, 0xe9, 0x36, 0xb8, 0xc3, 0x38, 0x9b, 0xe7, 0x7c, 0x1a, - 0x19, 0xc5, 0x21, 0xa0, 0x1a, 0x64, 0xb0, 0xa6, 0xf0, 0xe5, 0x64, 0xa8, 0x9a, 0xab, 0xa1, 0xff, - 0x5b, 0x53, 0xfc, 0x8b, 0x49, 0x63, 0x3e, 0x46, 0xb7, 0x21, 0xd5, 0xd6, 0xfb, 0x7d, 0xd5, 0x2e, - 0x03, 0xd5, 0xb0, 0x1e, 0xba, 0x10, 0xca, 0xd5, 0x88, 0x88, 0x9c, 0x1f, 0x1d, 0x42, 0xa1, 0xa7, - 0x5a, 0xb6, 0x64, 0x69, 0xb2, 0x61, 0x75, 0x75, 0xdb, 0x2a, 0x67, 0xa9, 0x86, 0xe7, 0xc2, 0x34, - 0x1c, 0xa8, 0x96, 0x7d, 0xe2, 0x30, 0x37, 0x22, 0x62, 0xbe, 0xe7, 0x27, 0x10, 0x7d, 0xfa, 0xd9, - 0x19, 0x36, 0x5d, 0x85, 0xe5, 0xdc, 0x74, 0x7d, 0x47, 0x84, 0xdb, 0x91, 0x27, 0xfa, 0x74, 0x3f, - 0x01, 0xfd, 0x08, 0x56, 0x7a, 0xba, 0xac, 0xb8, 0xea, 0xa4, 0x76, 0x77, 0xa0, 0x3d, 0x28, 0xe7, - 0xa9, 0xd2, 0x17, 0x43, 0x27, 0xa9, 0xcb, 0x8a, 0xa3, 0xa2, 0x46, 0x04, 0x1a, 0x11, 0x71, 0xb9, - 0x37, 0x4a, 0x44, 0xf7, 0x61, 0x55, 0x36, 0x8c, 0xde, 0xc5, 0xa8, 0xf6, 0x02, 0xd5, 0x7e, 0x23, - 0x4c, 0xfb, 0x0e, 0x91, 0x19, 0x55, 0x8f, 0xe4, 0x31, 0x2a, 0x6a, 0x42, 0xc9, 0x30, 0xb1, 0x21, - 0x9b, 0x58, 0x32, 0x4c, 0xdd, 0xd0, 0x2d, 0xb9, 0x57, 0x2e, 0x52, 0xdd, 0x2f, 0x84, 0xe9, 0x3e, - 0x66, 0xfc, 0xc7, 0x9c, 0xbd, 0x11, 0x11, 0x8b, 0x46, 0x90, 0xc4, 0xb4, 0xea, 0x6d, 0x6c, 0x59, - 0x9e, 0xd6, 0xd2, 0x2c, 0xad, 0x94, 0x3f, 0xa8, 0x35, 0x40, 0x42, 0x75, 0xc8, 0xe2, 0x73, 0x22, - 0x2e, 0x0d, 0x75, 0x1b, 0x97, 0x97, 0xa7, 0x1f, 0xac, 0x3a, 0x65, 0xbd, 0xa7, 0xdb, 0x98, 0x1c, - 0x2a, 0xec, 0x8e, 0x90, 0x0c, 0x4f, 0x0d, 0xb1, 0xa9, 0x9e, 0x5d, 0x50, 0x35, 0x12, 0x7d, 0x63, - 0xa9, 0xba, 0x56, 0x46, 0x54, 0xe1, 0x4b, 0x61, 0x0a, 0xef, 0x51, 0x21, 0xa2, 0xa2, 0xee, 0x88, - 0x34, 0x22, 0xe2, 0xca, 0x70, 0x9c, 0x4c, 0xb6, 0xd8, 0x99, 0xaa, 0xc9, 0x3d, 0xf5, 0x21, 0xe6, - 0xc7, 0x66, 0x65, 0xfa, 0x16, 0xdb, 0xe5, 0xdc, 0xf4, 0xac, 0x90, 0x2d, 0x76, 0xe6, 0x27, 0x54, - 0x97, 0x20, 0x39, 0x94, 0x7b, 0x03, 0x2c, 0xbc, 0x00, 0x59, 0x9f, 0x63, 0x45, 0x65, 0x58, 0xea, - 0x63, 0xcb, 0x92, 0x3b, 0x98, 0xfa, 0xe1, 0x8c, 0xe8, 0x0c, 0x85, 0x02, 0xe4, 0xfc, 0xce, 0x54, - 0xf8, 0x2c, 0xea, 0x4a, 0x12, 0x3f, 0x49, 0x24, 0x87, 0xd8, 0xa4, 0xcb, 0xe6, 0x92, 0x7c, 0x88, - 0xae, 0x41, 0x9e, 0x4e, 0x59, 0x72, 0xde, 0x13, 0x67, 0x9d, 0x10, 0x73, 0x94, 0x78, 0x8f, 0x33, - 0x6d, 0x40, 0xd6, 0xd8, 0x36, 0x5c, 0x96, 0x38, 0x65, 0x01, 0x63, 0xdb, 0x70, 0x18, 0x9e, 0x85, - 0x1c, 0x59, 0x9f, 0xcb, 0x91, 0xa0, 0x1f, 0xc9, 0x12, 0x1a, 0x67, 0x11, 0xfe, 0x14, 0x83, 0xd2, - 0xa8, 0x03, 0x46, 0xb7, 0x21, 0x41, 0x62, 0x11, 0x0f, 0x2b, 0x95, 0x4d, 0x16, 0xa8, 0x36, 0x9d, - 0x40, 0xb5, 0xd9, 0x74, 0x02, 0x55, 0x35, 0xfd, 0xc5, 0x57, 0x1b, 0x91, 0xcf, 0xfe, 0xb6, 0x11, - 0x15, 0xa9, 0x04, 0xba, 0x44, 0x7c, 0xa5, 0xac, 0x6a, 0x92, 0xaa, 0xd0, 0x29, 0x67, 0x88, 0x23, - 0x94, 0x55, 0x6d, 0x4f, 0x41, 0x07, 0x50, 0x6a, 0xeb, 0x9a, 0x85, 0x35, 0x6b, 0x60, 0x49, 0x2c, - 0x10, 0xf2, 0x60, 0x12, 0x70, 0x87, 0x2c, 0xbc, 0xd6, 0x1c, 0xce, 0x63, 0xca, 0x28, 0x16, 0xdb, - 0x41, 0x02, 0x71, 0xab, 0x43, 0xb9, 0xa7, 0x2a, 0xb2, 0xad, 0x9b, 0x56, 0x39, 0x71, 0x35, 0x3e, - 0xd1, 0x1f, 0xde, 0x73, 0x58, 0x4e, 0x0d, 0x45, 0xb6, 0x71, 0x35, 0x41, 0xa6, 0x2b, 0xfa, 0x24, - 0xd1, 0xf3, 0x50, 0x94, 0x0d, 0x43, 0xb2, 0x6c, 0xd9, 0xc6, 0x52, 0xeb, 0xc2, 0xc6, 0x16, 0x0d, - 0x34, 0x39, 0x31, 0x2f, 0x1b, 0xc6, 0x09, 0xa1, 0x56, 0x09, 0x11, 0x3d, 0x07, 0x05, 0x12, 0x93, - 0x54, 0xb9, 0x27, 0x75, 0xb1, 0xda, 0xe9, 0xda, 0x34, 0xa4, 0xc4, 0xc5, 0x3c, 0xa7, 0x36, 0x28, - 0x51, 0x50, 0xdc, 0x3f, 0x4e, 0xe3, 0x11, 0x42, 0x90, 0x50, 0x64, 0x5b, 0xa6, 0x96, 0xcc, 0x89, - 0xf4, 0x99, 0xd0, 0x0c, 0xd9, 0xee, 0x72, 0xfb, 0xd0, 0x67, 0xb4, 0x06, 0x29, 0xae, 0x36, 0x4e, - 0xd5, 0xf2, 0x11, 0x5a, 0x85, 0xa4, 0x61, 0xea, 0x43, 0x4c, 0x7f, 0x5d, 0x5a, 0x64, 0x03, 0xe1, - 0x27, 0x31, 0x58, 0x1e, 0x8b, 0x5c, 0x44, 0x6f, 0x57, 0xb6, 0xba, 0xce, 0xb7, 0xc8, 0x33, 0x7a, - 0x8d, 0xe8, 0x95, 0x15, 0x6c, 0xf2, 0x68, 0x5f, 0x1e, 0x37, 0x75, 0x83, 0xbe, 0xe7, 0xa6, 0xe1, - 0xdc, 0x68, 0x1f, 0x4a, 0x3d, 0xd9, 0xb2, 0x25, 0xe6, 0xfd, 0x25, 0x5f, 0xe4, 0x7f, 0x66, 0xcc, - 0xc8, 0x2c, 0x56, 0x90, 0x0d, 0xcd, 0x95, 0x14, 0x88, 0xa8, 0x47, 0x45, 0x22, 0xac, 0xb6, 0x2e, - 0x1e, 0xca, 0x9a, 0xad, 0x6a, 0x58, 0x1a, 0xfb, 0x6b, 0x97, 0xc6, 0x14, 0xd6, 0x87, 0xaa, 0x82, - 0xb5, 0xb6, 0xf3, 0xbb, 0x56, 0x5c, 0x61, 0xf7, 0x77, 0x5a, 0x82, 0x08, 0x85, 0x60, 0xcc, 0x45, - 0x05, 0x88, 0xd9, 0xe7, 0x7c, 0xf1, 0x31, 0xfb, 0x1c, 0x7d, 0x07, 0x12, 0x64, 0x81, 0x74, 0xe1, - 0x85, 0x09, 0x09, 0x0b, 0x97, 0x6b, 0x5e, 0x18, 0x58, 0xa4, 0x9c, 0x82, 0xe0, 0x1e, 0x05, 0x37, - 0x0e, 0x8f, 0x6a, 0x15, 0x5e, 0x84, 0xe2, 0x48, 0x90, 0xf5, 0xfd, 0xbb, 0xa8, 0xff, 0xdf, 0x09, - 0x45, 0xc8, 0x07, 0xa2, 0xa9, 0xb0, 0x06, 0xab, 0x93, 0x82, 0xa3, 0xd0, 0x75, 0xe9, 0x81, 0x20, - 0x87, 0x5e, 0x85, 0xb4, 0x1b, 0x1d, 0xd9, 0x51, 0x1c, 0xb7, 0x95, 0xc3, 0x2c, 0xba, 0xac, 0xe4, - 0x0c, 0x92, 0x2d, 0x4d, 0xf7, 0x42, 0x8c, 0x4e, 0x7c, 0x49, 0x36, 0x8c, 0x86, 0x6c, 0x75, 0x85, - 0x0f, 0xa0, 0x1c, 0x16, 0xf9, 0x46, 0x96, 0x91, 0x70, 0xb7, 0xe0, 0x1a, 0xa4, 0xce, 0x74, 0xb3, - 0x2f, 0xdb, 0x54, 0x59, 0x5e, 0xe4, 0x23, 0xb2, 0x35, 0x59, 0x14, 0x8c, 0x53, 0x32, 0x1b, 0x08, - 0x12, 0x5c, 0x0a, 0x8d, 0x7e, 0x44, 0x44, 0xd5, 0x14, 0xcc, 0xec, 0x99, 0x17, 0xd9, 0xc0, 0x53, - 0xc4, 0x26, 0xcb, 0x06, 0xe4, 0xb3, 0x16, 0x5d, 0x2b, 0xd5, 0x9f, 0x11, 0xf9, 0x48, 0xf8, 0x81, - 0xbb, 0xf5, 0xbd, 0xd8, 0x82, 0x6e, 0x40, 0x82, 0x46, 0x23, 0x66, 0xa5, 0xb5, 0xf1, 0x4d, 0x4e, - 0xb8, 0x44, 0xca, 0x23, 0x34, 0xa0, 0x12, 0x1e, 0x4b, 0x16, 0xd2, 0xf4, 0xf3, 0x28, 0xac, 0x4d, - 0x0e, 0xc7, 0xe8, 0x0a, 0x00, 0xf3, 0xdf, 0xfc, 0xf4, 0xc7, 0xaf, 0xe7, 0xc4, 0x0c, 0xa5, 0xdc, - 0x21, 0x2e, 0xe0, 0x79, 0x28, 0x7a, 0xaf, 0x25, 0x4b, 0x7d, 0xc8, 0xb6, 0x69, 0x5c, 0xcc, 0xbb, - 0x3c, 0x27, 0xea, 0x43, 0x8c, 0x6e, 0x42, 0x92, 0x7c, 0x89, 0x38, 0xca, 0xf8, 0x94, 0xe9, 0x30, - 0x26, 0xe1, 0xd7, 0x31, 0xdf, 0x7c, 0x82, 0x51, 0xfb, 0x71, 0xfa, 0x86, 0x12, 0xc4, 0xed, 0x73, - 0x36, 0xa5, 0x9c, 0x48, 0x1e, 0xd1, 0x09, 0xac, 0xb2, 0x0c, 0x03, 0x2b, 0x92, 0xcf, 0x6d, 0xf0, - 0x8c, 0x7f, 0x0e, 0x8f, 0x81, 0x1c, 0xf1, 0x03, 0xd7, 0x73, 0x84, 0x7a, 0x8d, 0xe4, 0x23, 0x78, - 0x8d, 0x5f, 0xc5, 0xdc, 0xa3, 0x16, 0x08, 0xf6, 0x4f, 0xd8, 0x3e, 0xef, 0xc0, 0x8a, 0x82, 0xdb, - 0xaa, 0xf2, 0x6d, 0xcd, 0xb3, 0xcc, 0xa5, 0x9f, 0xb0, 0x75, 0xfe, 0x9c, 0x85, 0xb4, 0x88, 0x2d, - 0x83, 0x84, 0x5a, 0x54, 0x85, 0x0c, 0x3e, 0x6f, 0x63, 0xc3, 0x76, 0xb2, 0x93, 0xc9, 0x59, 0x1e, - 0xe3, 0xae, 0x3b, 0x9c, 0x04, 0xb3, 0xb8, 0x62, 0xe8, 0x16, 0x87, 0xa7, 0xe1, 0x48, 0x93, 0x8b, - 0xfb, 0xf1, 0xe9, 0x6b, 0x0e, 0x3e, 0x8d, 0x87, 0x42, 0x14, 0x26, 0x35, 0x02, 0x50, 0x6f, 0x71, - 0x80, 0x9a, 0x98, 0xf1, 0xb1, 0x00, 0x42, 0xad, 0x05, 0x10, 0x6a, 0x72, 0xc6, 0x32, 0x43, 0x20, - 0xea, 0x6b, 0x0e, 0x44, 0x4d, 0xcd, 0x98, 0xf1, 0x08, 0x46, 0xbd, 0x1b, 0xc4, 0xa8, 0x0c, 0x5b, - 0x5e, 0x0b, 0x95, 0x9e, 0x0a, 0x52, 0xbf, 0xe7, 0x03, 0xa9, 0xe9, 0x50, 0x74, 0xc8, 0x14, 0x4d, - 0x40, 0xa9, 0x6f, 0x05, 0x50, 0x6a, 0x66, 0x86, 0x1d, 0xa6, 0xc0, 0xd4, 0x3b, 0x7e, 0x98, 0x0a, - 0xa1, 0x68, 0x97, 0xff, 0xf7, 0x30, 0x9c, 0xfa, 0xba, 0x8b, 0x53, 0xb3, 0xa1, 0x80, 0x9b, 0xaf, - 0x65, 0x14, 0xa8, 0x1e, 0x8d, 0x01, 0x55, 0x06, 0x2c, 0x9f, 0x0f, 0x55, 0x31, 0x03, 0xa9, 0x1e, - 0x8d, 0x21, 0xd5, 0xfc, 0x0c, 0x85, 0x33, 0xa0, 0xea, 0xfb, 0x93, 0xa1, 0x6a, 0x38, 0x98, 0xe4, - 0xd3, 0x9c, 0x0f, 0xab, 0x4a, 0x21, 0x58, 0xb5, 0x18, 0x8a, 0xab, 0x98, 0xfa, 0xb9, 0xc1, 0xea, - 0xe9, 0x04, 0xb0, 0xca, 0x60, 0xe5, 0xf5, 0x50, 0xe5, 0x73, 0xa0, 0xd5, 0xd3, 0x09, 0x68, 0x75, - 0x79, 0xa6, 0xda, 0x99, 0x70, 0x75, 0x37, 0x08, 0x57, 0xd1, 0x8c, 0x33, 0x16, 0x8a, 0x57, 0x5b, - 0x61, 0x78, 0x95, 0x61, 0xca, 0x9b, 0xa1, 0x1a, 0x17, 0x00, 0xac, 0x47, 0x63, 0x80, 0x75, 0x75, - 0xc6, 0x4e, 0x9b, 0x17, 0xb1, 0xbe, 0x48, 0x92, 0xa6, 0x11, 0x57, 0x4d, 0xf2, 0x2e, 0x6c, 0x9a, - 0xba, 0xc9, 0xb1, 0x27, 0x1b, 0x08, 0xd7, 0x09, 0x82, 0xf1, 0xdc, 0xf2, 0x14, 0x74, 0x4b, 0xf3, - 0x5b, 0x9f, 0x2b, 0x16, 0x7e, 0x1f, 0xf5, 0x64, 0x69, 0xe2, 0xef, 0x47, 0x3f, 0x19, 0x8e, 0x7e, - 0x7c, 0x98, 0x37, 0x16, 0xc4, 0xbc, 0x1b, 0x90, 0x25, 0x79, 0xeb, 0x08, 0x9c, 0x95, 0x0d, 0x17, - 0xce, 0xde, 0x80, 0x65, 0x1a, 0x3e, 0x59, 0xea, 0xc4, 0x93, 0xd5, 0x04, 0xcd, 0x9b, 0x8a, 0xe4, - 0x05, 0xb3, 0x02, 0xcb, 0x5a, 0x5f, 0x86, 0x15, 0x1f, 0xaf, 0x9b, 0x0f, 0x33, 0x6c, 0x57, 0x72, - 0xb9, 0x77, 0x78, 0x62, 0xfc, 0xc7, 0xa8, 0x67, 0x21, 0x0f, 0x07, 0x4f, 0x82, 0xac, 0xd1, 0xc7, - 0x04, 0x59, 0x63, 0xdf, 0x1a, 0xb2, 0xfa, 0xf3, 0xfb, 0x78, 0x30, 0xbf, 0xff, 0x67, 0xd4, 0xfb, - 0x27, 0x2e, 0x00, 0x6d, 0xeb, 0x0a, 0xe6, 0x19, 0x37, 0x7d, 0x26, 0x09, 0x4a, 0x4f, 0xef, 0xf0, - 0xbc, 0x9a, 0x3c, 0x12, 0x2e, 0x37, 0x76, 0x66, 0x78, 0x68, 0x74, 0x93, 0xf5, 0x24, 0xb5, 0x30, - 0x4f, 0xd6, 0x4b, 0x10, 0x7f, 0x80, 0x59, 0xa4, 0xcb, 0x89, 0xe4, 0x91, 0xf0, 0xd1, 0x4d, 0x46, - 0xe3, 0x57, 0x4e, 0x64, 0x03, 0x74, 0x1b, 0x32, 0xb4, 0x8c, 0x2e, 0xe9, 0x86, 0xc5, 0x03, 0x52, - 0x20, 0xd1, 0x61, 0xd5, 0xf2, 0xcd, 0x63, 0xc2, 0x73, 0x64, 0x58, 0x62, 0xda, 0xe0, 0x4f, 0x3e, - 0x1c, 0x92, 0x09, 0x40, 0xe1, 0xcb, 0x90, 0x21, 0xb3, 0xb7, 0x0c, 0xb9, 0x8d, 0x69, 0x64, 0xc9, - 0x88, 0x1e, 0x41, 0xb8, 0x0f, 0x68, 0x3c, 0x4e, 0xa2, 0x06, 0xa4, 0xf0, 0x10, 0x6b, 0xb6, 0x45, - 0x53, 0xf0, 0x91, 0x04, 0x9a, 0xe7, 0x45, 0x58, 0xb3, 0xab, 0x65, 0x62, 0xe4, 0x7f, 0x7c, 0xb5, - 0x51, 0x62, 0xdc, 0x37, 0xf5, 0xbe, 0x6a, 0xe3, 0xbe, 0x61, 0x5f, 0x88, 0x5c, 0x5e, 0xf8, 0x6b, - 0x8c, 0x00, 0xbf, 0x40, 0xfc, 0x9c, 0x68, 0x5b, 0x67, 0xcb, 0xc7, 0x7c, 0x80, 0x7f, 0x3e, 0x7b, - 0x5f, 0x01, 0xe8, 0xc8, 0x96, 0xf4, 0xb1, 0xac, 0xd9, 0x58, 0xe1, 0x46, 0xcf, 0x74, 0x64, 0xeb, - 0x5d, 0x4a, 0x20, 0x7f, 0x9d, 0xbc, 0x1e, 0x58, 0x58, 0xe1, 0xa5, 0x87, 0xa5, 0x8e, 0x6c, 0x9d, - 0x5a, 0x58, 0xf1, 0xad, 0x72, 0xe9, 0xd1, 0x56, 0x19, 0xb4, 0x71, 0x7a, 0xc4, 0xc6, 0x3e, 0x48, - 0x96, 0xf1, 0x43, 0x32, 0x54, 0x81, 0xb4, 0x61, 0xaa, 0xba, 0xa9, 0xda, 0x17, 0xf4, 0xc7, 0xc4, - 0x45, 0x77, 0x8c, 0xae, 0x41, 0xbe, 0x8f, 0xfb, 0x86, 0xae, 0xf7, 0x24, 0xe6, 0x6c, 0xb2, 0x54, - 0x34, 0xc7, 0x89, 0x75, 0xea, 0x73, 0x3e, 0x89, 0x79, 0xa7, 0xcf, 0x83, 0xde, 0x8f, 0xd7, 0xbc, - 0xeb, 0x13, 0xcc, 0xeb, 0xa3, 0x90, 0x45, 0x8c, 0xd8, 0xd7, 0x1d, 0xff, 0xaf, 0x0c, 0x2c, 0xfc, - 0x8c, 0x16, 0xe3, 0x82, 0xb9, 0x11, 0x3a, 0x81, 0x65, 0xf7, 0xf0, 0x4b, 0x03, 0xea, 0x14, 0x9c, - 0xed, 0x3c, 0xaf, 0xf7, 0x28, 0x0d, 0x83, 0x64, 0x0b, 0xbd, 0x07, 0x4f, 0x8f, 0x78, 0x36, 0x57, - 0x75, 0x6c, 0x5e, 0x07, 0xf7, 0x54, 0xd0, 0xc1, 0x39, 0xaa, 0x3d, 0x63, 0xc5, 0x1f, 0xf1, 0xcc, - 0xed, 0x41, 0x21, 0x98, 0xe6, 0x4d, 0xfc, 0xfd, 0xd7, 0x20, 0x6f, 0x62, 0x5b, 0x56, 0x35, 0x29, - 0x50, 0x41, 0xcb, 0x31, 0x22, 0xaf, 0xcb, 0x1d, 0xc3, 0x53, 0x13, 0xd3, 0x3d, 0xf4, 0x5d, 0xc8, - 0x78, 0x99, 0x62, 0x34, 0x04, 0x3c, 0xb9, 0x45, 0x16, 0x8f, 0x57, 0xf8, 0x43, 0xd4, 0x53, 0x19, - 0x2c, 0xdb, 0xd4, 0x21, 0x65, 0x62, 0x6b, 0xd0, 0x63, 0x85, 0x94, 0xc2, 0xf6, 0xcb, 0xf3, 0x25, - 0x8a, 0x84, 0x3a, 0xe8, 0xd9, 0x22, 0x17, 0x16, 0xee, 0x43, 0x8a, 0x51, 0x50, 0x16, 0x96, 0x4e, - 0x0f, 0xf7, 0x0f, 0x8f, 0xde, 0x3d, 0x2c, 0x45, 0x10, 0x40, 0x6a, 0xa7, 0x56, 0xab, 0x1f, 0x37, - 0x4b, 0x51, 0x94, 0x81, 0xe4, 0x4e, 0xf5, 0x48, 0x6c, 0x96, 0x62, 0x84, 0x2c, 0xd6, 0xef, 0xd6, - 0x6b, 0xcd, 0x52, 0x1c, 0x2d, 0x43, 0x9e, 0x3d, 0x4b, 0xbb, 0x47, 0xe2, 0xdb, 0x3b, 0xcd, 0x52, - 0xc2, 0x47, 0x3a, 0xa9, 0x1f, 0xde, 0xa9, 0x8b, 0xa5, 0xa4, 0xf0, 0x0a, 0x5c, 0x0a, 0x4d, 0x2d, - 0xbd, 0x9a, 0x4c, 0xd4, 0x57, 0x93, 0x11, 0x7e, 0x19, 0x83, 0x4a, 0x78, 0xbe, 0x88, 0xee, 0x8e, - 0x2c, 0x7c, 0x7b, 0x81, 0x64, 0x73, 0x64, 0xf5, 0xe8, 0x39, 0x28, 0x98, 0xf8, 0x0c, 0xdb, 0xed, - 0x2e, 0xcb, 0x5f, 0x59, 0xc0, 0xcc, 0x8b, 0x79, 0x4e, 0xa5, 0x42, 0x16, 0x63, 0xfb, 0x10, 0xb7, - 0x6d, 0x89, 0xf9, 0x22, 0xb6, 0xe9, 0x32, 0x84, 0x8d, 0x50, 0x4f, 0x18, 0x51, 0xf8, 0x60, 0x21, - 0x5b, 0x66, 0x20, 0x29, 0xd6, 0x9b, 0xe2, 0x7b, 0xa5, 0x38, 0x42, 0x50, 0xa0, 0x8f, 0xd2, 0xc9, - 0xe1, 0xce, 0xf1, 0x49, 0xe3, 0x88, 0xd8, 0x72, 0x05, 0x8a, 0x8e, 0x2d, 0x1d, 0x62, 0x52, 0x78, - 0xdf, 0x8b, 0x3f, 0xbe, 0xba, 0xd4, 0x2e, 0x14, 0x46, 0xd2, 0xc5, 0xe8, 0x38, 0x9e, 0xf1, 0x0a, - 0x39, 0x6e, 0x2a, 0x28, 0xe6, 0x87, 0xfe, 0xa1, 0xf0, 0x9b, 0x28, 0x3c, 0x33, 0x25, 0xa1, 0x44, - 0xfb, 0x23, 0x96, 0xbf, 0xb5, 0x48, 0x3a, 0x3a, 0xba, 0xf1, 0x6e, 0xcf, 0x65, 0xac, 0x93, 0x83, - 0x9d, 0x93, 0x46, 0x70, 0xe3, 0x09, 0xb7, 0xe1, 0xe9, 0x90, 0x8c, 0x7f, 0x46, 0x41, 0x4c, 0xf8, - 0x5d, 0xcc, 0x2f, 0x1a, 0x4c, 0xe1, 0xd7, 0x20, 0x25, 0xb7, 0x49, 0xd2, 0x4a, 0x17, 0x97, 0x16, - 0xf9, 0x68, 0x4a, 0x9d, 0x13, 0xbd, 0x09, 0x60, 0x9f, 0x4b, 0x6c, 0x3d, 0x8e, 0x1f, 0x1a, 0xaf, - 0x08, 0xd4, 0xcf, 0x71, 0xbb, 0x79, 0xce, 0x57, 0x9f, 0xb1, 0xf9, 0x93, 0x85, 0xde, 0x9e, 0xe4, - 0x71, 0xe7, 0x6c, 0x31, 0x2c, 0xe6, 0x6b, 0x93, 0x8f, 0xe6, 0x6b, 0x85, 0x5f, 0xc4, 0x3d, 0x27, - 0x14, 0x2c, 0x68, 0x3d, 0xb6, 0xcc, 0x67, 0xc4, 0x96, 0xb1, 0x05, 0x6d, 0x39, 0x31, 0x7a, 0xc5, - 0x9f, 0x5c, 0xf4, 0x4a, 0x3c, 0x62, 0xf4, 0xf2, 0x6f, 0xaa, 0x64, 0x70, 0x53, 0x8d, 0x05, 0x9a, - 0xd4, 0x84, 0x40, 0xf3, 0x1e, 0x80, 0xaf, 0xf3, 0xb1, 0x0a, 0x49, 0x53, 0x1f, 0x68, 0x0a, 0xdd, - 0xb9, 0x49, 0x91, 0x0d, 0xd0, 0xab, 0x4e, 0x55, 0x37, 0x16, 0x12, 0x6f, 0xc8, 0xf1, 0xf4, 0x95, - 0xff, 0x78, 0x79, 0xf7, 0x21, 0x24, 0xe9, 0x3f, 0x23, 0x51, 0x90, 0x76, 0x36, 0x38, 0xac, 0x22, - 0xcf, 0xe8, 0xc7, 0x00, 0xb2, 0x6d, 0x9b, 0x6a, 0x6b, 0xe0, 0x29, 0xde, 0x98, 0xfc, 0xcf, 0x77, - 0x1c, 0xbe, 0xea, 0x65, 0xfe, 0xf3, 0x57, 0x3d, 0x51, 0xdf, 0x06, 0xf0, 0x29, 0x14, 0x0e, 0xa1, - 0x10, 0x94, 0x75, 0x80, 0x00, 0x9b, 0x43, 0x10, 0x08, 0x30, 0x5c, 0xc7, 0x81, 0x80, 0x0b, 0x23, - 0xe2, 0xac, 0x83, 0x45, 0x07, 0xc2, 0xbf, 0xa3, 0x90, 0xf3, 0x6f, 0x99, 0xff, 0xb7, 0x5c, 0x5a, - 0xf8, 0x24, 0x0a, 0x69, 0x77, 0xf1, 0x21, 0x1d, 0x24, 0xcf, 0x76, 0x31, 0x7f, 0xbf, 0x84, 0xb5, - 0xa4, 0xe2, 0x6e, 0xa3, 0xeb, 0x0d, 0xd7, 0xf9, 0x87, 0x95, 0x3e, 0xfd, 0x96, 0x76, 0x8a, 0xd5, - 0xdc, 0xd9, 0xbf, 0x01, 0x19, 0xf7, 0xd4, 0x11, 0x6c, 0x2e, 0x2b, 0x8a, 0x89, 0x2d, 0x8b, 0xc7, - 0x7d, 0x67, 0x48, 0xfb, 0x90, 0xfa, 0xc7, 0xbc, 0x19, 0x13, 0x17, 0xd9, 0x40, 0x50, 0xa0, 0x38, - 0x72, 0x64, 0xd1, 0x1b, 0xb0, 0x64, 0x0c, 0x5a, 0x92, 0xb3, 0x35, 0x46, 0x6e, 0x0a, 0x39, 0xa8, - 0x6f, 0xd0, 0xea, 0xa9, 0xed, 0x7d, 0x7c, 0xe1, 0x4c, 0xc6, 0x18, 0xb4, 0xf6, 0xd9, 0x0e, 0x62, - 0x5f, 0x89, 0xf9, 0xbf, 0xf2, 0xd3, 0x28, 0xa4, 0x9d, 0x13, 0x81, 0xbe, 0x0f, 0x19, 0xd7, 0x1d, - 0xb8, 0xfd, 0xe9, 0x50, 0x3f, 0xc2, 0xf5, 0x7b, 0x22, 0xe8, 0x06, 0x2c, 0x5b, 0x6a, 0x47, 0x73, - 0x2a, 0xf1, 0xac, 0xcc, 0x12, 0xa3, 0x5b, 0xb3, 0xc8, 0x5e, 0x1c, 0x38, 0xb5, 0x81, 0xbb, 0x89, - 0x74, 0xbc, 0x94, 0xb8, 0x9b, 0x48, 0x27, 0x4a, 0x49, 0xe1, 0x5f, 0x51, 0x48, 0x3b, 0x35, 0x74, - 0xf4, 0x8a, 0xef, 0x00, 0x16, 0x26, 0xd9, 0x9b, 0x33, 0x7a, 0xbd, 0xc5, 0xe0, 0xbc, 0x63, 0x8b, - 0xcf, 0x3b, 0xac, 0x41, 0xec, 0xb4, 0xea, 0x13, 0x0b, 0xb7, 0xea, 0x6f, 0x02, 0xb2, 0x75, 0x5b, - 0xee, 0x49, 0x43, 0xdd, 0x56, 0xb5, 0x8e, 0xc4, 0x2c, 0xcf, 0xce, 0x4a, 0x89, 0xbe, 0xb9, 0x47, - 0x5f, 0x1c, 0xbb, 0x3f, 0xc1, 0xcd, 0x70, 0x17, 0x6d, 0x15, 0xae, 0x41, 0x8a, 0x27, 0x71, 0xac, - 0x57, 0xc8, 0x47, 0x6e, 0xd7, 0x25, 0xe1, 0xeb, 0xba, 0x54, 0x20, 0xdd, 0xc7, 0xb6, 0x4c, 0x0f, - 0x3e, 0x73, 0xc0, 0xee, 0xf8, 0xc6, 0xeb, 0x90, 0xf5, 0x75, 0x6d, 0x89, 0x2f, 0x38, 0xac, 0xbf, - 0x5b, 0x8a, 0x54, 0x96, 0x3e, 0xfd, 0xfc, 0x6a, 0xfc, 0x10, 0x7f, 0x4c, 0x36, 0xb0, 0x58, 0xaf, - 0x35, 0xea, 0xb5, 0xfd, 0x52, 0xb4, 0x92, 0xfd, 0xf4, 0xf3, 0xab, 0x4b, 0x22, 0xa6, 0x25, 0xee, - 0x1b, 0x0d, 0xc8, 0xf9, 0xff, 0x4a, 0x30, 0xb5, 0x41, 0x50, 0xb8, 0x73, 0x7a, 0x7c, 0xb0, 0x57, - 0xdb, 0x69, 0xd6, 0xa5, 0x7b, 0x47, 0xcd, 0x7a, 0x29, 0x8a, 0x9e, 0x86, 0x95, 0x83, 0xbd, 0xb7, - 0x1a, 0x4d, 0xa9, 0x76, 0xb0, 0x57, 0x3f, 0x6c, 0x4a, 0x3b, 0xcd, 0xe6, 0x4e, 0x6d, 0xbf, 0x14, - 0xdb, 0xfe, 0x6d, 0x16, 0x8a, 0x3b, 0xd5, 0xda, 0x1e, 0xc9, 0x61, 0xd5, 0xb6, 0x4c, 0x4b, 0x69, - 0x35, 0x48, 0xd0, 0x62, 0xd9, 0xd4, 0x1b, 0x78, 0x95, 0xe9, 0x0d, 0x10, 0xb4, 0x0b, 0x49, 0x5a, - 0x47, 0x43, 0xd3, 0xaf, 0xe4, 0x55, 0x66, 0x74, 0x44, 0xc8, 0x64, 0xe8, 0x51, 0x99, 0x7a, 0x47, - 0xaf, 0x32, 0xbd, 0x41, 0x82, 0x0e, 0x60, 0xc9, 0x29, 0x73, 0xcc, 0xba, 0xed, 0x56, 0x99, 0xd9, - 0x69, 0x20, 0x4b, 0x63, 0xe5, 0xa8, 0xe9, 0xd7, 0xf7, 0x2a, 0x33, 0x5a, 0x27, 0x68, 0x0f, 0x52, - 0x1c, 0x09, 0xce, 0xb8, 0xb9, 0x56, 0x99, 0xd5, 0x31, 0x40, 0x22, 0x64, 0xbc, 0x42, 0xdf, 0xec, - 0x4b, 0x89, 0x95, 0x39, 0xba, 0x42, 0xe8, 0x3e, 0xe4, 0x83, 0xe8, 0x72, 0xbe, 0xdb, 0x71, 0x95, - 0x39, 0x7b, 0x13, 0x44, 0x7f, 0x10, 0x6a, 0xce, 0x77, 0x5b, 0xae, 0x32, 0x67, 0xab, 0x02, 0x7d, - 0x08, 0xcb, 0xe3, 0x50, 0x70, 0xfe, 0xcb, 0x73, 0x95, 0x05, 0x9a, 0x17, 0xa8, 0x0f, 0x68, 0x02, - 0x84, 0x5c, 0xe0, 0x2e, 0x5d, 0x65, 0x91, 0x5e, 0x06, 0x52, 0xa0, 0x38, 0x0a, 0x49, 0xe6, 0xbd, - 0x5b, 0x57, 0x99, 0xbb, 0xaf, 0xc1, 0xbe, 0x12, 0x44, 0x2f, 0xf3, 0xde, 0xb5, 0xab, 0xcc, 0xdd, - 0xe6, 0x40, 0xa7, 0x00, 0x3e, 0x8c, 0x39, 0xc7, 0xdd, 0xbb, 0xca, 0x3c, 0x0d, 0x0f, 0x64, 0xc0, - 0xca, 0x24, 0x6c, 0xb9, 0xc8, 0x55, 0xbc, 0xca, 0x42, 0x7d, 0x10, 0xb2, 0x9f, 0x83, 0xa8, 0x65, - 0xbe, 0xab, 0x79, 0x95, 0x39, 0x1b, 0x22, 0xd5, 0xfa, 0x17, 0x5f, 0xaf, 0x47, 0xbf, 0xfc, 0x7a, - 0x3d, 0xfa, 0xf7, 0xaf, 0xd7, 0xa3, 0x9f, 0x7d, 0xb3, 0x1e, 0xf9, 0xf2, 0x9b, 0xf5, 0xc8, 0x5f, - 0xbe, 0x59, 0x8f, 0xfc, 0xf0, 0xa5, 0x8e, 0x6a, 0x77, 0x07, 0xad, 0xcd, 0xb6, 0xde, 0xdf, 0xf2, - 0xdf, 0xd2, 0x9e, 0x74, 0x73, 0xbc, 0x95, 0xa2, 0xd1, 0xf4, 0xd6, 0x7f, 0x03, 0x00, 0x00, 0xff, - 0xff, 0x8d, 0xc9, 0xd7, 0xa0, 0x59, 0x2e, 0x00, 0x00, + // 3395 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5b, 0x4b, 0x73, 0xdb, 0xd6, + 0xf5, 0xe7, 0xfb, 0x71, 0x28, 0x3e, 0x74, 0xa5, 0x38, 0x34, 0x63, 0x4b, 0x0e, 0x3c, 0x49, 0x1c, + 0x27, 0x91, 0xff, 0xb1, 0x27, 0xf9, 0x3b, 0x4d, 0xd2, 0x8c, 0x44, 0x51, 0xa1, 0x6c, 0x59, 0x52, + 0x20, 0xca, 0x99, 0xb4, 0xa9, 0x11, 0x10, 0xb8, 0x22, 0x11, 0x93, 0x00, 0x02, 0x80, 0x0a, 0x95, + 0x55, 0xa7, 0x33, 0xd9, 0x64, 0x3a, 0xd3, 0xec, 0xda, 0x99, 0x4e, 0xa6, 0x9b, 0x76, 0xa6, 0x1f, + 0xa0, 0x8b, 0xae, 0xba, 0x69, 0x17, 0x59, 0x74, 0x91, 0x5d, 0x3b, 0x5d, 0xa4, 0x9d, 0x64, 0xd7, + 0x2f, 0x90, 0x55, 0x1f, 0x73, 0x1f, 0x00, 0x01, 0x90, 0xe0, 0x23, 0xb6, 0xb3, 0xe9, 0x0e, 0xf7, + 0xf0, 0x9c, 0x83, 0x7b, 0x0f, 0xee, 0x3d, 0xe7, 0xfc, 0xce, 0xb9, 0x84, 0x27, 0x1c, 0xac, 0xab, + 0xd8, 0xea, 0x6b, 0xba, 0x73, 0x4d, 0x6e, 0x2b, 0xda, 0x35, 0xe7, 0xcc, 0xc4, 0xf6, 0x86, 0x69, + 0x19, 0x8e, 0x81, 0xca, 0xa3, 0x1f, 0x37, 0xc8, 0x8f, 0xb5, 0x8b, 0x3e, 0x6e, 0xc5, 0x3a, 0x33, + 0x1d, 0xe3, 0x9a, 0x69, 0x19, 0xc6, 0x09, 0xe3, 0xaf, 0x5d, 0xf0, 0xfd, 0x4c, 0xf5, 0xf8, 0xb5, + 0x05, 0x7e, 0xe5, 0xc2, 0xf7, 0xf1, 0x99, 0xfb, 0xeb, 0xc5, 0x31, 0x59, 0x53, 0xb6, 0xe4, 0xbe, + 0xfb, 0xf3, 0x7a, 0xc7, 0x30, 0x3a, 0x3d, 0x7c, 0x8d, 0x8e, 0xda, 0x83, 0x93, 0x6b, 0x8e, 0xd6, + 0xc7, 0xb6, 0x23, 0xf7, 0x4d, 0xce, 0xb0, 0xda, 0x31, 0x3a, 0x06, 0x7d, 0xbc, 0x46, 0x9e, 0x18, + 0x55, 0xf8, 0x0f, 0x40, 0x56, 0xc4, 0x1f, 0x0c, 0xb0, 0xed, 0xa0, 0xeb, 0x90, 0xc2, 0x4a, 0xd7, + 0xa8, 0xc6, 0x2f, 0xc5, 0xaf, 0x14, 0xae, 0x5f, 0xd8, 0x08, 0x2d, 0x6e, 0x83, 0xf3, 0x35, 0x94, + 0xae, 0xd1, 0x8c, 0x89, 0x94, 0x17, 0xbd, 0x04, 0xe9, 0x93, 0xde, 0xc0, 0xee, 0x56, 0x13, 0x54, + 0xe8, 0x62, 0x94, 0xd0, 0x0e, 0x61, 0x6a, 0xc6, 0x44, 0xc6, 0x4d, 0x5e, 0xa5, 0xe9, 0x27, 0x46, + 0x35, 0x39, 0xfd, 0x55, 0xbb, 0xfa, 0x09, 0x7d, 0x15, 0xe1, 0x45, 0x5b, 0x00, 0x9a, 0xae, 0x39, + 0x92, 0xd2, 0x95, 0x35, 0xbd, 0x9a, 0xa2, 0x92, 0x4f, 0x46, 0x4b, 0x6a, 0x4e, 0x9d, 0x30, 0x36, + 0x63, 0x62, 0x5e, 0x73, 0x07, 0x64, 0xba, 0x1f, 0x0c, 0xb0, 0x75, 0x56, 0x4d, 0x4f, 0x9f, 0xee, + 0x5b, 0x84, 0x89, 0x4c, 0x97, 0x72, 0xa3, 0x5d, 0x28, 0xb4, 0x71, 0x47, 0xd3, 0xa5, 0x76, 0xcf, + 0x50, 0xee, 0x57, 0x33, 0x54, 0x58, 0x88, 0x12, 0xde, 0x22, 0xac, 0x5b, 0x84, 0x73, 0x2b, 0x51, + 0x8d, 0x37, 0x63, 0x22, 0xb4, 0x3d, 0x0a, 0x7a, 0x0d, 0x72, 0x4a, 0x17, 0x2b, 0xf7, 0x25, 0x67, + 0x58, 0xcd, 0x52, 0x3d, 0xeb, 0x51, 0x7a, 0xea, 0x84, 0xaf, 0x35, 0x6c, 0xc6, 0xc4, 0xac, 0xc2, + 0x1e, 0xd1, 0x0e, 0x80, 0x8a, 0x7b, 0xda, 0x29, 0xb6, 0x88, 0x7c, 0x6e, 0xba, 0x0d, 0xb6, 0x19, + 0x67, 0x6b, 0xc8, 0xa7, 0x91, 0x57, 0x5d, 0x02, 0xaa, 0x43, 0x1e, 0xeb, 0x2a, 0x5f, 0x4e, 0x9e, + 0xaa, 0xb9, 0x14, 0xf9, 0xbd, 0x75, 0xd5, 0xbf, 0x98, 0x1c, 0xe6, 0x63, 0x74, 0x13, 0x32, 0x8a, + 0xd1, 0xef, 0x6b, 0x4e, 0x15, 0xa8, 0x86, 0xb5, 0xc8, 0x85, 0x50, 0xae, 0x66, 0x4c, 0xe4, 0xfc, + 0x68, 0x1f, 0x4a, 0x3d, 0xcd, 0x76, 0x24, 0x5b, 0x97, 0x4d, 0xbb, 0x6b, 0x38, 0x76, 0xb5, 0x40, + 0x35, 0x3c, 0x15, 0xa5, 0x61, 0x4f, 0xb3, 0x9d, 0x23, 0x97, 0xb9, 0x19, 0x13, 0x8b, 0x3d, 0x3f, + 0x81, 0xe8, 0x33, 0x4e, 0x4e, 0xb0, 0xe5, 0x29, 0xac, 0x2e, 0x4d, 0xd7, 0x77, 0x40, 0xb8, 0x5d, + 0x79, 0xa2, 0xcf, 0xf0, 0x13, 0xd0, 0x0f, 0x61, 0xa5, 0x67, 0xc8, 0xaa, 0xa7, 0x4e, 0x52, 0xba, + 0x03, 0xfd, 0x7e, 0xb5, 0x48, 0x95, 0x3e, 0x1b, 0x39, 0x49, 0x43, 0x56, 0x5d, 0x15, 0x75, 0x22, + 0xd0, 0x8c, 0x89, 0xcb, 0xbd, 0x30, 0x11, 0xdd, 0x83, 0x55, 0xd9, 0x34, 0x7b, 0x67, 0x61, 0xed, + 0x25, 0xaa, 0xfd, 0x6a, 0x94, 0xf6, 0x4d, 0x22, 0x13, 0x56, 0x8f, 0xe4, 0x31, 0x2a, 0x6a, 0x41, + 0xc5, 0xb4, 0xb0, 0x29, 0x5b, 0x58, 0x32, 0x2d, 0xc3, 0x34, 0x6c, 0xb9, 0x57, 0x2d, 0x53, 0xdd, + 0xcf, 0x44, 0xe9, 0x3e, 0x64, 0xfc, 0x87, 0x9c, 0xbd, 0x19, 0x13, 0xcb, 0x66, 0x90, 0xc4, 0xb4, + 0x1a, 0x0a, 0xb6, 0xed, 0x91, 0xd6, 0xca, 0x2c, 0xad, 0x94, 0x3f, 0xa8, 0x35, 0x40, 0x42, 0x0d, + 0x28, 0xe0, 0x21, 0x11, 0x97, 0x4e, 0x0d, 0x07, 0x57, 0x97, 0xa7, 0x1f, 0xac, 0x06, 0x65, 0xbd, + 0x6b, 0x38, 0x98, 0x1c, 0x2a, 0xec, 0x8d, 0x90, 0x0c, 0x8f, 0x9d, 0x62, 0x4b, 0x3b, 0x39, 0xa3, + 0x6a, 0x24, 0xfa, 0x8b, 0xad, 0x19, 0x7a, 0x15, 0x51, 0x85, 0xcf, 0x45, 0x29, 0xbc, 0x4b, 0x85, + 0x88, 0x8a, 0x86, 0x2b, 0xd2, 0x8c, 0x89, 0x2b, 0xa7, 0xe3, 0x64, 0xb2, 0xc5, 0x4e, 0x34, 0x5d, + 0xee, 0x69, 0x1f, 0x61, 0x7e, 0x6c, 0x56, 0xa6, 0x6f, 0xb1, 0x1d, 0xce, 0x4d, 0xcf, 0x0a, 0xd9, + 0x62, 0x27, 0x7e, 0xc2, 0x56, 0x16, 0xd2, 0xa7, 0x72, 0x6f, 0x80, 0x85, 0x67, 0xa0, 0xe0, 0x73, + 0xac, 0xa8, 0x0a, 0xd9, 0x3e, 0xb6, 0x6d, 0xb9, 0x83, 0xa9, 0x1f, 0xce, 0x8b, 0xee, 0x50, 0x28, + 0xc1, 0x92, 0xdf, 0x99, 0x0a, 0x9f, 0xc6, 0x3d, 0x49, 0xe2, 0x27, 0x89, 0xe4, 0x29, 0xb6, 0xe8, + 0xb2, 0xb9, 0x24, 0x1f, 0xa2, 0xcb, 0x50, 0xa4, 0x53, 0x96, 0xdc, 0xdf, 0x89, 0xb3, 0x4e, 0x89, + 0x4b, 0x94, 0x78, 0x97, 0x33, 0xad, 0x43, 0xc1, 0xbc, 0x6e, 0x7a, 0x2c, 0x49, 0xca, 0x02, 0xe6, + 0x75, 0xd3, 0x65, 0x78, 0x12, 0x96, 0xc8, 0xfa, 0x3c, 0x8e, 0x14, 0x7d, 0x49, 0x81, 0xd0, 0x38, + 0x8b, 0xf0, 0xe7, 0x04, 0x54, 0xc2, 0x0e, 0x18, 0xdd, 0x84, 0x14, 0x89, 0x45, 0x3c, 0xac, 0xd4, + 0x36, 0x58, 0xa0, 0xda, 0x70, 0x03, 0xd5, 0x46, 0xcb, 0x0d, 0x54, 0x5b, 0xb9, 0xcf, 0xbf, 0x5c, + 0x8f, 0x7d, 0xfa, 0xf7, 0xf5, 0xb8, 0x48, 0x25, 0xd0, 0x79, 0xe2, 0x2b, 0x65, 0x4d, 0x97, 0x34, + 0x95, 0x4e, 0x39, 0x4f, 0x1c, 0xa1, 0xac, 0xe9, 0xbb, 0x2a, 0xda, 0x83, 0x8a, 0x62, 0xe8, 0x36, + 0xd6, 0xed, 0x81, 0x2d, 0xb1, 0x40, 0xc8, 0x83, 0x49, 0xc0, 0x1d, 0xb2, 0xf0, 0x5a, 0x77, 0x39, + 0x0f, 0x29, 0xa3, 0x58, 0x56, 0x82, 0x04, 0xe2, 0x56, 0x4f, 0xe5, 0x9e, 0xa6, 0xca, 0x8e, 0x61, + 0xd9, 0xd5, 0xd4, 0xa5, 0xe4, 0x44, 0x7f, 0x78, 0xd7, 0x65, 0x39, 0x36, 0x55, 0xd9, 0xc1, 0x5b, + 0x29, 0x32, 0x5d, 0xd1, 0x27, 0x89, 0x9e, 0x86, 0xb2, 0x6c, 0x9a, 0x92, 0xed, 0xc8, 0x0e, 0x96, + 0xda, 0x67, 0x0e, 0xb6, 0x69, 0xa0, 0x59, 0x12, 0x8b, 0xb2, 0x69, 0x1e, 0x11, 0xea, 0x16, 0x21, + 0xa2, 0xa7, 0xa0, 0x44, 0x62, 0x92, 0x26, 0xf7, 0xa4, 0x2e, 0xd6, 0x3a, 0x5d, 0x87, 0x86, 0x94, + 0xa4, 0x58, 0xe4, 0xd4, 0x26, 0x25, 0x0a, 0xaa, 0xf7, 0xc5, 0x69, 0x3c, 0x42, 0x08, 0x52, 0xaa, + 0xec, 0xc8, 0xd4, 0x92, 0x4b, 0x22, 0x7d, 0x26, 0x34, 0x53, 0x76, 0xba, 0xdc, 0x3e, 0xf4, 0x19, + 0x9d, 0x83, 0x0c, 0x57, 0x9b, 0xa4, 0x6a, 0xf9, 0x08, 0xad, 0x42, 0xda, 0xb4, 0x8c, 0x53, 0x4c, + 0x3f, 0x5d, 0x4e, 0x64, 0x03, 0xe1, 0xc7, 0x09, 0x58, 0x1e, 0x8b, 0x5c, 0x44, 0x6f, 0x57, 0xb6, + 0xbb, 0xee, 0xbb, 0xc8, 0x33, 0x7a, 0x99, 0xe8, 0x95, 0x55, 0x6c, 0xf1, 0x68, 0x5f, 0x1d, 0x37, + 0x75, 0x93, 0xfe, 0xce, 0x4d, 0xc3, 0xb9, 0xd1, 0x6d, 0xa8, 0xf4, 0x64, 0xdb, 0x91, 0x98, 0xf7, + 0x97, 0x7c, 0x91, 0xff, 0x89, 0x31, 0x23, 0xb3, 0x58, 0x41, 0x36, 0x34, 0x57, 0x52, 0x22, 0xa2, + 0x23, 0x2a, 0x12, 0x61, 0xb5, 0x7d, 0xf6, 0x91, 0xac, 0x3b, 0x9a, 0x8e, 0xa5, 0xb1, 0xaf, 0x76, + 0x7e, 0x4c, 0x61, 0xe3, 0x54, 0x53, 0xb1, 0xae, 0xb8, 0x9f, 0x6b, 0xc5, 0x13, 0xf6, 0x3e, 0xa7, + 0x2d, 0x88, 0x50, 0x0a, 0xc6, 0x5c, 0x54, 0x82, 0x84, 0x33, 0xe4, 0x8b, 0x4f, 0x38, 0x43, 0xf4, + 0x7f, 0x90, 0x22, 0x0b, 0xa4, 0x0b, 0x2f, 0x4d, 0x48, 0x58, 0xb8, 0x5c, 0xeb, 0xcc, 0xc4, 0x22, + 0xe5, 0x14, 0x04, 0xef, 0x28, 0x78, 0x71, 0x38, 0xac, 0x55, 0x78, 0x16, 0xca, 0xa1, 0x20, 0xeb, + 0xfb, 0x76, 0x71, 0xff, 0xb7, 0x13, 0xca, 0x50, 0x0c, 0x44, 0x53, 0xe1, 0x1c, 0xac, 0x4e, 0x0a, + 0x8e, 0x42, 0xd7, 0xa3, 0x07, 0x82, 0x1c, 0x7a, 0x09, 0x72, 0x5e, 0x74, 0x64, 0x47, 0x71, 0xdc, + 0x56, 0x2e, 0xb3, 0xe8, 0xb1, 0x92, 0x33, 0x48, 0xb6, 0x34, 0xdd, 0x0b, 0x09, 0x3a, 0xf1, 0xac, + 0x6c, 0x9a, 0x4d, 0xd9, 0xee, 0x0a, 0xef, 0x41, 0x35, 0x2a, 0xf2, 0x85, 0x96, 0x91, 0xf2, 0xb6, + 0xe0, 0x39, 0xc8, 0x9c, 0x18, 0x56, 0x5f, 0x76, 0xa8, 0xb2, 0xa2, 0xc8, 0x47, 0x64, 0x6b, 0xb2, + 0x28, 0x98, 0xa4, 0x64, 0x36, 0x10, 0x24, 0x38, 0x1f, 0x19, 0xfd, 0x88, 0x88, 0xa6, 0xab, 0x98, + 0xd9, 0xb3, 0x28, 0xb2, 0xc1, 0x48, 0x11, 0x9b, 0x2c, 0x1b, 0x90, 0xd7, 0xda, 0x74, 0xad, 0x54, + 0x7f, 0x5e, 0xe4, 0x23, 0xe1, 0x0d, 0x6f, 0xeb, 0x8f, 0x62, 0x0b, 0xba, 0x0a, 0x29, 0x1a, 0x8d, + 0x98, 0x95, 0xce, 0x8d, 0x6f, 0x72, 0xc2, 0x25, 0x52, 0x1e, 0xa1, 0x09, 0xb5, 0xe8, 0x58, 0xb2, + 0x90, 0xa6, 0x3f, 0x26, 0xe0, 0xdc, 0xe4, 0x70, 0xfc, 0x50, 0xcf, 0x62, 0x05, 0x92, 0xce, 0x90, + 0xf8, 0xca, 0xe4, 0x95, 0x25, 0x91, 0x3c, 0xa2, 0x63, 0x58, 0xee, 0x19, 0x8a, 0xdc, 0x93, 0x7c, + 0x67, 0x94, 0xa7, 0xd7, 0x97, 0xc7, 0x4f, 0x13, 0x35, 0x13, 0x56, 0xc7, 0x8e, 0x69, 0x99, 0xea, + 0xd8, 0xf3, 0xce, 0x6a, 0xe4, 0x39, 0x4d, 0x7f, 0xfb, 0x73, 0x8a, 0x2e, 0xc1, 0x52, 0x5f, 0x1e, + 0x4a, 0xce, 0x90, 0x3b, 0x57, 0xe6, 0x35, 0xa1, 0x2f, 0x0f, 0x5b, 0x43, 0xea, 0x59, 0x85, 0x5f, + 0xf9, 0xad, 0x18, 0xcc, 0x35, 0x1e, 0xad, 0x15, 0x8f, 0x60, 0x95, 0xe5, 0x45, 0x58, 0x9d, 0x60, + 0xc8, 0x39, 0xfc, 0x1c, 0x72, 0xc5, 0x1f, 0xad, 0x0d, 0x85, 0x5f, 0x26, 0x3c, 0x07, 0x11, 0x48, + 0x51, 0x1e, 0xb1, 0x7d, 0xde, 0x82, 0x15, 0x15, 0x2b, 0x9a, 0xfa, 0x6d, 0xcd, 0xb3, 0xcc, 0xa5, + 0x1f, 0xb1, 0x75, 0xfe, 0x52, 0x80, 0x9c, 0x88, 0x6d, 0x93, 0x24, 0x08, 0x68, 0x0b, 0xf2, 0x78, + 0xa8, 0x60, 0xd3, 0x71, 0x73, 0xaa, 0xc9, 0xb9, 0x29, 0xe3, 0x6e, 0xb8, 0x9c, 0x04, 0x69, 0x79, + 0x62, 0xe8, 0x06, 0x07, 0xd5, 0xd1, 0xf8, 0x98, 0x8b, 0xfb, 0x51, 0xf5, 0xcb, 0x2e, 0xaa, 0x4e, + 0x46, 0x02, 0x2b, 0x26, 0x15, 0x82, 0xd5, 0x37, 0x38, 0xac, 0x4e, 0xcd, 0x78, 0x59, 0x00, 0x57, + 0xd7, 0x03, 0xb8, 0x3a, 0x3d, 0x63, 0x99, 0x11, 0xc0, 0xfa, 0x65, 0x17, 0x58, 0x67, 0x66, 0xcc, + 0x38, 0x84, 0xac, 0x6f, 0x05, 0x91, 0x75, 0x36, 0xc2, 0xed, 0xb8, 0xd2, 0x53, 0xa1, 0xf5, 0xeb, + 0x3e, 0x68, 0x9d, 0x8b, 0xc4, 0xb4, 0x4c, 0xd1, 0x04, 0x6c, 0xfd, 0x66, 0x00, 0x5b, 0xe7, 0x67, + 0xd8, 0x61, 0x0a, 0xb8, 0xde, 0xf6, 0x83, 0x6b, 0x88, 0xc4, 0xe8, 0xfc, 0xbb, 0x47, 0xa1, 0xeb, + 0x57, 0x3c, 0x74, 0x5d, 0x88, 0x2c, 0x13, 0xf0, 0xb5, 0x84, 0xe1, 0xf5, 0xc1, 0x18, 0xbc, 0x66, + 0x70, 0xf8, 0xe9, 0x48, 0x15, 0x33, 0xf0, 0xf5, 0xc1, 0x18, 0xbe, 0x2e, 0xce, 0x50, 0x38, 0x03, + 0x60, 0xbf, 0x3b, 0x19, 0x60, 0x47, 0x43, 0x60, 0x3e, 0xcd, 0xf9, 0x10, 0xb6, 0x14, 0x81, 0xb0, + 0xcb, 0x91, 0x68, 0x90, 0xa9, 0x9f, 0x1b, 0x62, 0x1f, 0x4f, 0x80, 0xd8, 0x0c, 0x0c, 0x5f, 0x89, + 0x54, 0x3e, 0x07, 0xc6, 0x3e, 0x9e, 0x80, 0xb1, 0x97, 0x67, 0xaa, 0x9d, 0x09, 0xb2, 0x77, 0x82, + 0x20, 0x1b, 0xcd, 0x38, 0x63, 0x91, 0x28, 0xbb, 0x1d, 0x85, 0xb2, 0x19, 0x12, 0x7e, 0x3e, 0x52, + 0xe3, 0x02, 0x30, 0xfb, 0x60, 0x0c, 0x66, 0xaf, 0xce, 0xd8, 0x69, 0xf3, 0xe2, 0xec, 0x67, 0x49, + 0xaa, 0x17, 0x72, 0xd5, 0x24, 0x5b, 0xc4, 0x96, 0x65, 0x58, 0x1c, 0x31, 0xb3, 0x81, 0x70, 0x85, + 0xe0, 0xae, 0x91, 0x5b, 0x9e, 0x82, 0xc9, 0x69, 0x56, 0xee, 0x73, 0xc5, 0xc2, 0xef, 0xe3, 0x23, + 0x59, 0x0a, 0x57, 0xfc, 0x98, 0x2d, 0xcf, 0x31, 0x9b, 0x0f, 0xa9, 0x27, 0x82, 0x48, 0x7d, 0x1d, + 0x0a, 0x24, 0xdb, 0x0e, 0x81, 0x70, 0xd9, 0xf4, 0x40, 0xf8, 0x55, 0x58, 0xa6, 0xe1, 0x93, 0xe1, + 0x79, 0x9e, 0x62, 0xa7, 0x68, 0x1a, 0x54, 0x26, 0x3f, 0x30, 0x2b, 0xb0, 0x5c, 0xfb, 0x05, 0x58, + 0xf1, 0xf1, 0x7a, 0x59, 0x3c, 0x43, 0xa4, 0x15, 0x8f, 0x7b, 0x93, 0xa7, 0xf3, 0x7f, 0x8a, 0x8f, + 0x2c, 0x34, 0x42, 0xef, 0x93, 0x80, 0x76, 0xfc, 0x21, 0x01, 0xed, 0xc4, 0xb7, 0x06, 0xda, 0x7e, + 0x54, 0x92, 0x0c, 0xa2, 0x92, 0x6f, 0xe2, 0xa3, 0x6f, 0xe2, 0xc1, 0x66, 0xc5, 0x50, 0x31, 0xc7, + 0x09, 0xf4, 0x99, 0x24, 0x28, 0x3d, 0xa3, 0xc3, 0xd1, 0x00, 0x79, 0x24, 0x5c, 0x5e, 0xec, 0xcc, + 0xf3, 0xd0, 0xe8, 0x41, 0x8c, 0x34, 0xb5, 0x30, 0x87, 0x18, 0x15, 0x48, 0xde, 0xc7, 0x2c, 0xd2, + 0x2d, 0x89, 0xe4, 0x91, 0xf0, 0xd1, 0x4d, 0x46, 0xe3, 0xd7, 0x92, 0xc8, 0x06, 0xe8, 0x26, 0xe4, + 0x69, 0xf1, 0x5f, 0x32, 0x4c, 0x9b, 0x07, 0xa4, 0x40, 0xa2, 0xc3, 0x6a, 0xfc, 0x1b, 0x87, 0x84, + 0xe7, 0xc0, 0xb4, 0xc5, 0x9c, 0xc9, 0x9f, 0x7c, 0xe8, 0x29, 0x1f, 0x00, 0xf0, 0x17, 0x20, 0x4f, + 0x66, 0x6f, 0x9b, 0xb2, 0x82, 0x69, 0x64, 0xc9, 0x8b, 0x23, 0x82, 0x70, 0x0f, 0xd0, 0x78, 0x9c, + 0x44, 0x4d, 0xc8, 0xe0, 0x53, 0xac, 0x3b, 0xe4, 0xb3, 0x25, 0xc3, 0x28, 0x84, 0xe7, 0x45, 0x58, + 0x77, 0xb6, 0xaa, 0xc4, 0xc8, 0xff, 0xfc, 0x72, 0xbd, 0xc2, 0xb8, 0x9f, 0x37, 0xfa, 0x9a, 0x83, + 0xfb, 0xa6, 0x73, 0x26, 0x72, 0x79, 0xe1, 0x6f, 0x09, 0x02, 0x57, 0x03, 0xf1, 0x73, 0xa2, 0x6d, + 0xdd, 0x2d, 0x9f, 0xf0, 0x95, 0x29, 0xe6, 0xb3, 0xf7, 0x45, 0x80, 0x8e, 0x6c, 0x4b, 0x1f, 0xca, + 0xba, 0x83, 0x55, 0x6e, 0xf4, 0x7c, 0x47, 0xb6, 0xdf, 0xa6, 0x04, 0xf2, 0xd5, 0xc9, 0xcf, 0x03, + 0x1b, 0xab, 0x3c, 0xf5, 0xcf, 0x76, 0x64, 0xfb, 0xd8, 0xc6, 0xaa, 0x6f, 0x95, 0xd9, 0x07, 0x5b, + 0x65, 0xd0, 0xc6, 0xb9, 0x90, 0x8d, 0x7d, 0x40, 0x32, 0xef, 0x07, 0x92, 0xa8, 0x06, 0x39, 0xd3, + 0xd2, 0x0c, 0x4b, 0x73, 0xce, 0xe8, 0x87, 0x49, 0x8a, 0xde, 0x18, 0x5d, 0x86, 0x62, 0x1f, 0xf7, + 0x4d, 0xc3, 0xe8, 0x49, 0xcc, 0xd9, 0x14, 0xa8, 0xe8, 0x12, 0x27, 0x36, 0xa8, 0xcf, 0xf9, 0x38, + 0x31, 0x3a, 0x7d, 0xa3, 0x82, 0xc1, 0xc3, 0x35, 0xef, 0xda, 0x04, 0xf3, 0xfa, 0x28, 0x64, 0x11, + 0x21, 0xfb, 0x7a, 0xe3, 0xef, 0xca, 0xc0, 0xc2, 0x4f, 0x69, 0x09, 0x31, 0x98, 0x1b, 0xa1, 0x23, + 0x58, 0xf6, 0x0e, 0xbf, 0x34, 0xa0, 0x4e, 0xc1, 0xdd, 0xce, 0xf3, 0x7a, 0x8f, 0xca, 0x69, 0x90, + 0x6c, 0xa3, 0x77, 0xe0, 0xf1, 0x90, 0x67, 0xf3, 0x54, 0x27, 0xe6, 0x75, 0x70, 0x8f, 0x05, 0x1d, + 0x9c, 0xab, 0x7a, 0x64, 0xac, 0xe4, 0x03, 0x9e, 0xb9, 0x5d, 0x28, 0x05, 0xd3, 0xbc, 0x89, 0x9f, + 0xff, 0x32, 0x14, 0x2d, 0xec, 0xc8, 0x9a, 0x2e, 0x05, 0xea, 0x7e, 0x4b, 0x8c, 0xc8, 0xab, 0x89, + 0x87, 0xf0, 0xd8, 0xc4, 0x74, 0x0f, 0xfd, 0x3f, 0xe4, 0x47, 0x99, 0x62, 0x3c, 0x02, 0x3c, 0x79, + 0xa5, 0xa1, 0x11, 0xaf, 0xf0, 0x87, 0xf8, 0x48, 0x65, 0xb0, 0xd8, 0xd4, 0x80, 0x8c, 0x85, 0xed, + 0x41, 0x8f, 0x95, 0x7f, 0x4a, 0xd7, 0x5f, 0x98, 0x2f, 0x51, 0x24, 0xd4, 0x41, 0xcf, 0x11, 0xb9, + 0xb0, 0x70, 0x0f, 0x32, 0x8c, 0x82, 0x0a, 0x90, 0x3d, 0xde, 0xbf, 0xbd, 0x7f, 0xf0, 0xf6, 0x7e, + 0x25, 0x86, 0x00, 0x32, 0x9b, 0xf5, 0x7a, 0xe3, 0xb0, 0x55, 0x89, 0xa3, 0x3c, 0xa4, 0x37, 0xb7, + 0x0e, 0xc4, 0x56, 0x25, 0x41, 0xc8, 0x62, 0xe3, 0x56, 0xa3, 0xde, 0xaa, 0x24, 0xd1, 0x32, 0x14, + 0xd9, 0xb3, 0xb4, 0x73, 0x20, 0xde, 0xd9, 0x6c, 0x55, 0x52, 0x3e, 0xd2, 0x51, 0x63, 0x7f, 0xbb, + 0x21, 0x56, 0xd2, 0xc2, 0x8b, 0x70, 0x3e, 0x32, 0xb5, 0x1c, 0x55, 0x92, 0xe2, 0xbe, 0x4a, 0x92, + 0xf0, 0x8b, 0x04, 0xd4, 0xa2, 0xf3, 0x45, 0x74, 0x2b, 0xb4, 0xf0, 0xeb, 0x0b, 0x24, 0x9b, 0xa1, + 0xd5, 0xa3, 0xa7, 0xa0, 0x64, 0xe1, 0x13, 0xec, 0x28, 0x5d, 0x96, 0xbf, 0xb2, 0x80, 0x59, 0x14, + 0x8b, 0x9c, 0x4a, 0x85, 0x6c, 0xc6, 0xf6, 0x3e, 0x56, 0x1c, 0x89, 0xf9, 0x22, 0xb6, 0xe9, 0xf2, + 0x84, 0x8d, 0x50, 0x8f, 0x18, 0x51, 0x78, 0x6f, 0x21, 0x5b, 0xe6, 0x21, 0x2d, 0x36, 0x5a, 0xe2, + 0x3b, 0x95, 0x24, 0x42, 0x50, 0xa2, 0x8f, 0xd2, 0xd1, 0xfe, 0xe6, 0xe1, 0x51, 0xf3, 0x80, 0xd8, + 0x72, 0x05, 0xca, 0xae, 0x2d, 0x5d, 0x62, 0x5a, 0x78, 0x77, 0x14, 0x7f, 0x7c, 0xd5, 0xb4, 0x1d, + 0x28, 0x85, 0xd2, 0xc5, 0xf8, 0x38, 0x9e, 0x19, 0x55, 0xc3, 0xbc, 0x54, 0x50, 0x2c, 0x9e, 0xfa, + 0x87, 0xc2, 0xaf, 0xe3, 0xf0, 0xc4, 0x94, 0x84, 0x12, 0xdd, 0x0e, 0x59, 0xfe, 0xc6, 0x22, 0xe9, + 0x68, 0x78, 0xe3, 0xdd, 0x9c, 0xcb, 0x58, 0x47, 0x7b, 0x9b, 0x47, 0xcd, 0xe0, 0xc6, 0x13, 0xbe, + 0x49, 0xc0, 0xe3, 0x11, 0x29, 0x3f, 0xc9, 0xee, 0xfa, 0x86, 0xaa, 0x9d, 0x68, 0x58, 0x95, 0x78, + 0x1d, 0x38, 0x27, 0x82, 0x4b, 0x6a, 0x0d, 0xd1, 0x4d, 0x00, 0x67, 0x28, 0x59, 0x58, 0x31, 0x2c, + 0xd5, 0x4d, 0x8f, 0xc6, 0x8f, 0x62, 0x6b, 0x28, 0x52, 0x0e, 0x31, 0xef, 0xf0, 0xa7, 0x69, 0x09, + 0x11, 0x7a, 0x8d, 0x2b, 0x25, 0xcb, 0x71, 0xcb, 0xe4, 0x17, 0x27, 0x14, 0xf6, 0xb0, 0x42, 0x14, + 0x53, 0x33, 0x50, 0xc5, 0x94, 0x1f, 0xdd, 0x99, 0xe4, 0x7a, 0xd3, 0xf3, 0xb9, 0xde, 0xc5, 0x9c, + 0x6e, 0xe6, 0xc1, 0x9c, 0xae, 0xf0, 0xbb, 0x80, 0xe5, 0x83, 0x10, 0xe8, 0x1c, 0x64, 0x64, 0x85, + 0x24, 0xfd, 0xdc, 0xe8, 0x7c, 0x34, 0xa5, 0xba, 0x1d, 0x32, 0x5b, 0xf2, 0x61, 0x98, 0x2d, 0xf5, + 0x28, 0xcc, 0x96, 0x7e, 0x40, 0xb3, 0xfd, 0x2c, 0x39, 0x72, 0xe2, 0xc1, 0x82, 0xe0, 0x43, 0xcb, + 0x1c, 0x43, 0xb6, 0x4c, 0x2c, 0x68, 0xcb, 0x89, 0xd1, 0x3f, 0xf9, 0xe8, 0xa2, 0x7f, 0xea, 0x01, + 0xa3, 0xbf, 0x7f, 0x53, 0xa5, 0x83, 0x9b, 0x6a, 0x2c, 0x50, 0x67, 0x26, 0x04, 0xea, 0x77, 0x00, + 0x7c, 0xfd, 0xae, 0x55, 0x48, 0x5b, 0xc6, 0x40, 0x57, 0xe9, 0xce, 0x4d, 0x8b, 0x6c, 0x80, 0x5e, + 0x82, 0x34, 0x71, 0x8f, 0xd1, 0x4e, 0x82, 0xb8, 0x37, 0x5f, 0xf9, 0x94, 0x71, 0x0b, 0x1a, 0xa0, + 0xf1, 0x0a, 0x7e, 0xc4, 0x2b, 0x5e, 0x0f, 0xbe, 0xe2, 0xc9, 0xc8, 0x5e, 0xc0, 0xe4, 0x57, 0x7d, + 0x04, 0x69, 0xba, 0x3d, 0x48, 0xc2, 0x42, 0x5b, 0x67, 0x1c, 0x01, 0x93, 0x67, 0xf4, 0x23, 0x00, + 0xd9, 0x71, 0x2c, 0xad, 0x3d, 0x18, 0xbd, 0x60, 0x7d, 0xf2, 0xf6, 0xda, 0x74, 0xf9, 0xb6, 0x2e, + 0xf0, 0x7d, 0xb6, 0x3a, 0x12, 0xf5, 0xed, 0x35, 0x9f, 0x42, 0x61, 0x1f, 0x4a, 0x41, 0x59, 0x17, + 0xb3, 0xb1, 0x39, 0x04, 0x31, 0x1b, 0x83, 0xe0, 0x1c, 0xb3, 0x79, 0x88, 0x2f, 0xc9, 0x5a, 0xa4, + 0x74, 0x20, 0xfc, 0x3b, 0x0e, 0x4b, 0xfe, 0xdd, 0xf9, 0xbf, 0x06, 0x7b, 0x84, 0x8f, 0xe3, 0x90, + 0xf3, 0x16, 0x1f, 0xd1, 0xa2, 0x1c, 0xd9, 0x2e, 0xe1, 0x6f, 0xc8, 0xb1, 0x9e, 0x67, 0xd2, 0xeb, + 0xa4, 0xbe, 0xea, 0xc5, 0xe9, 0xa8, 0x2a, 0xb5, 0xdf, 0xd2, 0x6e, 0x5f, 0x81, 0xc7, 0xe5, 0x9f, + 0xf3, 0x79, 0x90, 0xa0, 0x87, 0xbe, 0x47, 0x9c, 0xba, 0x57, 0x9b, 0x2f, 0x4d, 0x28, 0xd6, 0xba, + 0xac, 0x1b, 0xad, 0xe1, 0x26, 0xe5, 0x14, 0xb9, 0x04, 0x9f, 0x55, 0xc2, 0xeb, 0xc4, 0xbe, 0x41, + 0xf4, 0x32, 0x9e, 0x60, 0xc8, 0x2f, 0x01, 0x1c, 0xef, 0xdf, 0x39, 0xd8, 0xde, 0xdd, 0xd9, 0x6d, + 0x6c, 0xf3, 0x1c, 0x69, 0x7b, 0xbb, 0xb1, 0x5d, 0x49, 0x10, 0x3e, 0xb1, 0x71, 0xe7, 0xe0, 0x6e, + 0x63, 0xbb, 0x92, 0x14, 0x5e, 0x85, 0xbc, 0xe7, 0x7a, 0x50, 0x15, 0xb2, 0xb2, 0xaa, 0x5a, 0xd8, + 0xb6, 0x79, 0xf2, 0xe8, 0x0e, 0x69, 0x0b, 0xde, 0xf8, 0x90, 0xf7, 0x21, 0x93, 0x22, 0x1b, 0x08, + 0x2a, 0x94, 0x43, 0x7e, 0x0b, 0xbd, 0x0a, 0x59, 0x73, 0xd0, 0x96, 0xdc, 0x4d, 0x1b, 0xba, 0x24, + 0xe7, 0x96, 0x0e, 0x06, 0xed, 0x9e, 0xa6, 0xdc, 0xc6, 0x67, 0xae, 0x99, 0xcc, 0x41, 0xfb, 0x36, + 0xdb, 0xdb, 0xec, 0x2d, 0x09, 0xff, 0x5b, 0x7e, 0x12, 0x87, 0x9c, 0x7b, 0x56, 0xd1, 0xf7, 0x21, + 0xef, 0xf9, 0x44, 0xef, 0x6a, 0x46, 0xa4, 0x33, 0xe5, 0xfa, 0x47, 0x22, 0xe8, 0x2a, 0x2c, 0xdb, + 0x5a, 0x47, 0x77, 0xdb, 0x39, 0xac, 0x56, 0x97, 0xa0, 0x87, 0xa6, 0xcc, 0x7e, 0xd8, 0x73, 0x0b, + 0x4c, 0xb7, 0x52, 0xb9, 0x64, 0x25, 0x75, 0x2b, 0x95, 0x4b, 0x55, 0xd2, 0xc2, 0x6f, 0xe2, 0x50, + 0x09, 0x3b, 0x8e, 0xef, 0x72, 0x32, 0x24, 0x5d, 0x0e, 0xe5, 0xa3, 0x6c, 0x6f, 0x86, 0xd2, 0xcd, + 0x7f, 0xc5, 0x21, 0xe7, 0x36, 0x8c, 0xd0, 0x8b, 0x3e, 0x17, 0x56, 0x9a, 0xb4, 0x63, 0x39, 0xe3, + 0xa8, 0xfd, 0x1f, 0x5c, 0x52, 0x62, 0xf1, 0x25, 0x45, 0xdd, 0xe1, 0x70, 0x6f, 0xd3, 0xa4, 0x16, + 0xbe, 0x4d, 0xf3, 0x3c, 0x20, 0xc7, 0x70, 0xe4, 0x9e, 0x74, 0x6a, 0x38, 0x9a, 0xde, 0x91, 0xd8, + 0x0e, 0x61, 0xde, 0xa6, 0x42, 0x7f, 0xb9, 0x4b, 0x7f, 0x38, 0xf4, 0x36, 0x8b, 0x07, 0xe7, 0x16, + 0xed, 0xe6, 0x9f, 0x83, 0x0c, 0x47, 0x2c, 0xac, 0x9d, 0xcf, 0x47, 0x5e, 0x8b, 0x31, 0xe5, 0x6b, + 0x31, 0xd6, 0x20, 0xd7, 0xc7, 0x8e, 0x4c, 0x5d, 0x27, 0x8b, 0x96, 0xde, 0xf8, 0xea, 0x2b, 0x50, + 0xf0, 0x5d, 0xac, 0x20, 0xde, 0x74, 0xbf, 0xf1, 0x76, 0x25, 0x56, 0xcb, 0x7e, 0xf2, 0xd9, 0xa5, + 0xe4, 0x3e, 0xfe, 0x90, 0x1c, 0x34, 0xb1, 0x51, 0x6f, 0x36, 0xea, 0xb7, 0x2b, 0xf1, 0x5a, 0xe1, + 0x93, 0xcf, 0x2e, 0x65, 0x45, 0x4c, 0xfb, 0x39, 0x57, 0x9b, 0xb0, 0xe4, 0xff, 0x2a, 0xc1, 0x43, + 0x8d, 0xa0, 0xb4, 0x7d, 0x7c, 0xb8, 0xb7, 0x5b, 0xdf, 0x6c, 0x35, 0xa4, 0xbb, 0x07, 0xad, 0x46, + 0x25, 0x8e, 0x1e, 0x87, 0x95, 0xbd, 0xdd, 0x37, 0x9b, 0x2d, 0xa9, 0xbe, 0xb7, 0xdb, 0xd8, 0x6f, + 0x49, 0x9b, 0xad, 0xd6, 0x66, 0xfd, 0x76, 0x25, 0x71, 0xfd, 0xb7, 0x05, 0x28, 0x6f, 0x6e, 0xd5, + 0x77, 0x09, 0x60, 0xd3, 0x14, 0x99, 0xba, 0x88, 0x3a, 0xa4, 0x68, 0x65, 0x78, 0xea, 0x25, 0xd9, + 0xda, 0xf4, 0x6e, 0x1f, 0xda, 0x81, 0x34, 0x2d, 0x1a, 0xa3, 0xe9, 0xb7, 0x66, 0x6b, 0x33, 0xda, + 0x7f, 0x64, 0x32, 0xf4, 0x14, 0x4d, 0xbd, 0x46, 0x5b, 0x9b, 0xde, 0x0d, 0x44, 0x7b, 0x90, 0x75, + 0x6b, 0x7a, 0xb3, 0x2e, 0xa4, 0xd6, 0x66, 0xb6, 0xd5, 0xc8, 0xd2, 0x58, 0xed, 0x75, 0xfa, 0x0d, + 0xdb, 0xda, 0x8c, 0x3e, 0x21, 0xda, 0x85, 0x0c, 0x2f, 0x7b, 0xcc, 0xb8, 0x5c, 0x5a, 0x9b, 0xd5, + 0x1e, 0x43, 0x22, 0xe4, 0x47, 0x55, 0xed, 0xd9, 0xf7, 0x86, 0x6b, 0x73, 0xb4, 0x40, 0xd1, 0x3d, + 0x28, 0x06, 0x4b, 0x29, 0xf3, 0x5d, 0x60, 0xad, 0xcd, 0xd9, 0x88, 0x23, 0xfa, 0x83, 0x75, 0x95, + 0xf9, 0x2e, 0xb4, 0xd6, 0xe6, 0xec, 0xcb, 0xa1, 0xf7, 0x61, 0x79, 0xbc, 0xee, 0x31, 0xff, 0xfd, + 0xd6, 0xda, 0x02, 0x9d, 0x3a, 0xd4, 0x07, 0x34, 0xa1, 0x5e, 0xb2, 0xc0, 0x75, 0xd7, 0xda, 0x22, + 0x8d, 0x3b, 0xa4, 0x42, 0x39, 0x0c, 0xbf, 0xe7, 0xbd, 0xfe, 0x5a, 0x9b, 0xbb, 0x89, 0xc7, 0xde, + 0x12, 0x84, 0x9a, 0xf3, 0x5e, 0x87, 0xad, 0xcd, 0xdd, 0xd3, 0x43, 0xc7, 0x00, 0xbe, 0x82, 0xca, + 0x1c, 0xd7, 0x63, 0x6b, 0xf3, 0x74, 0xf7, 0x90, 0x09, 0x2b, 0x93, 0x0a, 0x29, 0x8b, 0xdc, 0x96, + 0xad, 0x2d, 0xd4, 0xf4, 0x23, 0xfb, 0x39, 0x08, 0x31, 0xe7, 0xbb, 0x3d, 0x5b, 0x9b, 0xb3, 0xfb, + 0xb7, 0xd5, 0xf8, 0xfc, 0xab, 0xb5, 0xf8, 0x17, 0x5f, 0xad, 0xc5, 0xff, 0xf1, 0xd5, 0x5a, 0xfc, + 0xd3, 0xaf, 0xd7, 0x62, 0x5f, 0x7c, 0xbd, 0x16, 0xfb, 0xeb, 0xd7, 0x6b, 0xb1, 0x1f, 0x3c, 0xd7, + 0xd1, 0x9c, 0xee, 0xa0, 0xbd, 0xa1, 0x18, 0xfd, 0x6b, 0xfe, 0x3f, 0x52, 0x4c, 0xfa, 0x73, 0x47, + 0x3b, 0x43, 0xa3, 0xe9, 0x8d, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xf9, 0x85, 0x76, 0xba, 0xfc, + 0x31, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -5752,10 +6024,15 @@ func (m *RequestPrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l - if len(m.Votes) > 0 { - for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + if m.MaxTxBytes != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.MaxTxBytes)) + i-- + dAtA[i] = 0x30 + } + if len(m.ByzantineValidators) > 0 { + for iNdEx := len(m.ByzantineValidators) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.ByzantineValidators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -5763,22 +6040,44 @@ func (m *RequestPrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) i = encodeVarintTypes(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x1a + dAtA[i] = 0x2a } } - if m.BlockDataSize != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.BlockDataSize)) - i-- - dAtA[i] = 0x10 + { + size, err := m.LocalLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) } - if len(m.BlockData) > 0 { - for iNdEx := len(m.BlockData) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.BlockData[iNdEx]) - copy(dAtA[i:], m.BlockData[iNdEx]) - i = encodeVarintTypes(dAtA, i, uint64(len(m.BlockData[iNdEx]))) + i-- + dAtA[i] = 0x22 + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) i-- - dAtA[i] = 0xa + dAtA[i] = 0x1a + } + } + { + size, err := m.Header.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + 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] = 0xa } return len(dAtA) - i, nil } @@ -7108,20 +7407,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 } @@ -7216,16 +7515,78 @@ func (m *ResponsePrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l - if len(m.BlockData) > 0 { - for iNdEx := len(m.BlockData) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.BlockData[iNdEx]) - copy(dAtA[i:], m.BlockData[iNdEx]) - i = encodeVarintTypes(dAtA, i, uint64(len(m.BlockData[iNdEx]))) + if m.ConsensusParamUpdates != nil { + { + size, err := m.ConsensusParamUpdates.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + if len(m.ValidatorUpdates) > 0 { + for iNdEx := len(m.ValidatorUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ValidatorUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } i-- - dAtA[i] = 0xa + dAtA[i] = 0x2a } } - return len(dAtA) - i, nil + if len(m.TxResults) > 0 { + for iNdEx := len(m.TxResults) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TxResults[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x1a + } + if len(m.TxRecords) > 0 { + for iNdEx := len(m.TxRecords) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TxRecords[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.ModifiedTx { + i-- + if m.ModifiedTx { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil } func (m *ResponseProcessProposal) Marshal() (dAtA []byte, err error) { @@ -7439,6 +7800,48 @@ func (m *CommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ExtendedCommitInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExtendedCommitInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExtendedCommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *Event) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7660,6 +8063,41 @@ func (m *TxResult) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *TxRecord) 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 *TxRecord) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TxRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Tx) > 0 { + i -= len(m.Tx) + copy(dAtA[i:], m.Tx) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx))) + i-- + dAtA[i] = 0x12 + } + if m.Action != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Action)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *Validator) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7776,6 +8214,56 @@ func (m *VoteInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ExtendedVoteInfo) 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 *ExtendedVoteInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExtendedVoteInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.VoteExtension) > 0 { + i -= len(m.VoteExtension) + copy(dAtA[i:], m.VoteExtension) + i = encodeVarintTypes(dAtA, i, uint64(len(m.VoteExtension))) + i-- + dAtA[i] = 0x1a + } + if m.SignedLastBlock { + i-- + if m.SignedLastBlock { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *Evidence) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7801,12 +8289,12 @@ func (m *Evidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x28 } - n62, err62 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err62 != nil { - return 0, err62 + n66, err66 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err66 != nil { + return 0, err66 } - i -= n62 - i = encodeVarintTypes(dAtA, i, uint64(n62)) + i -= n66 + i = encodeVarintTypes(dAtA, i, uint64(n66)) i-- dAtA[i] = 0x22 if m.Height != 0 { @@ -8404,21 +8892,29 @@ func (m *RequestPrepareProposal) Size() (n int) { } var l int _ = l - if len(m.BlockData) > 0 { - for _, b := range m.BlockData { + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Header.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Txs) > 0 { + for _, b := range m.Txs { l = len(b) n += 1 + l + sovTypes(uint64(l)) } } - if m.BlockDataSize != 0 { - n += 1 + sovTypes(uint64(m.BlockDataSize)) - } - if len(m.Votes) > 0 { - for _, e := range m.Votes { + l = m.LocalLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.ByzantineValidators) > 0 { + for _, e := range m.ByzantineValidators { l = e.Size() n += 1 + l + sovTypes(uint64(l)) } } + if m.MaxTxBytes != 0 { + n += 1 + sovTypes(uint64(m.MaxTxBytes)) + } return n } @@ -9102,12 +9598,35 @@ func (m *ResponsePrepareProposal) Size() (n int) { } var l int _ = l - if len(m.BlockData) > 0 { - for _, b := range m.BlockData { - l = len(b) + if m.ModifiedTx { + n += 2 + } + if len(m.TxRecords) > 0 { + for _, e := range m.TxRecords { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.TxResults) > 0 { + for _, e := range m.TxResults { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if len(m.ValidatorUpdates) > 0 { + for _, e := range m.ValidatorUpdates { + l = e.Size() n += 1 + l + sovTypes(uint64(l)) } } + if m.ConsensusParamUpdates != nil { + l = m.ConsensusParamUpdates.Size() + n += 1 + l + sovTypes(uint64(l)) + } return n } @@ -9199,6 +9718,24 @@ func (m *CommitInfo) Size() (n int) { return n } +func (m *ExtendedCommitInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + func (m *Event) Size() (n int) { if m == nil { return 0 @@ -9299,6 +9836,22 @@ func (m *TxResult) Size() (n int) { return n } +func (m *TxRecord) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Action != 0 { + n += 1 + sovTypes(uint64(m.Action)) + } + l = len(m.Tx) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + func (m *Validator) Size() (n int) { if m == nil { return 0 @@ -9343,6 +9896,24 @@ func (m *VoteInfo) Size() (n int) { return n } +func (m *ExtendedVoteInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.SignedLastBlock { + n += 2 + } + l = len(m.VoteExtension) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + func (m *Evidence) Size() (n int) { if m == nil { return 0 @@ -11894,7 +12465,7 @@ func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field BlockData", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -11921,14 +12492,16 @@ func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.BlockData = append(m.BlockData, make([]byte, postIndex-iNdEx)) - copy(m.BlockData[len(m.BlockData)-1], dAtA[iNdEx:postIndex]) + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } iNdEx = postIndex case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field BlockDataSize", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType) } - m.BlockDataSize = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -11938,18 +12511,64 @@ func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.BlockDataSize |= int64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + if msglen < 0 { + return ErrInvalidLengthTypes } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { return ErrIntOverflowTypes } if iNdEx >= l { @@ -11972,11 +12591,63 @@ func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Votes = append(m.Votes, &types1.Vote{}) - if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.LocalLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ByzantineValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ByzantineValidators = append(m.ByzantineValidators, Evidence{}) + if err := m.ByzantineValidators[len(m.ByzantineValidators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxTxBytes", wireType) + } + m.MaxTxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxTxBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -15606,10 +16277,10 @@ func (m *ResponsePrepareProposal) Unmarshal(dAtA []byte) error { } switch fieldNum { case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field BlockData", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ModifiedTx", wireType) } - var byteLen int + var v int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -15619,79 +16290,17 @@ func (m *ResponsePrepareProposal) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + v |= 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.BlockData = append(m.BlockData, make([]byte, postIndex-iNdEx)) - copy(m.BlockData[len(m.BlockData)-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 *ResponseProcessProposal) 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: ResponseProcessProposal: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseProcessProposal: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Accept", wireType) + m.ModifiedTx = bool(v != 0) + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxRecords", wireType) } - var v int + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -15701,13 +16310,27 @@ func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - m.Accept = bool(v != 0) - case 2: + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TxRecords = append(m.TxRecords, &TxRecord{}) + if err := m.TxRecords[len(m.TxRecords)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) } @@ -15741,7 +16364,7 @@ func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { m.AppHash = []byte{} } iNdEx = postIndex - case 3: + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field TxResults", wireType) } @@ -15775,7 +16398,7 @@ func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 4: + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ValidatorUpdates", wireType) } @@ -15809,7 +16432,7 @@ func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 5: + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParamUpdates", wireType) } @@ -15866,7 +16489,7 @@ func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { +func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -15889,17 +16512,37 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseFinalizeBlock: wiretype end group for non-group") + return fmt.Errorf("proto: ResponseProcessProposal: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseFinalizeBlock: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ResponseProcessProposal: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Accept", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Accept = bool(v != 0) + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) } - var msglen int + var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -15909,27 +16552,27 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + byteLen |= int(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + if byteLen < 0 { return ErrInvalidLengthTypes } - postIndex := iNdEx + msglen + postIndex := iNdEx + byteLen if postIndex < 0 { return ErrInvalidLengthTypes } if postIndex > l { return io.ErrUnexpectedEOF } - m.Events = append(m.Events, Event{}) - if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} } iNdEx = postIndex - case 2: + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field TxResults", wireType) } @@ -15963,7 +16606,7 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 3: + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ValidatorUpdates", wireType) } @@ -15992,12 +16635,12 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ValidatorUpdates = append(m.ValidatorUpdates, ValidatorUpdate{}) + m.ValidatorUpdates = append(m.ValidatorUpdates, &ValidatorUpdate{}) if err := m.ValidatorUpdates[len(m.ValidatorUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 4: + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParamUpdates", wireType) } @@ -16033,9 +16676,197 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + 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 *ResponseFinalizeBlock) 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: ResponseFinalizeBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseFinalizeBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxResults", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TxResults = append(m.TxResults, &ExecTxResult{}) + if err := m.TxResults[len(m.TxResults)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorUpdates = append(m.ValidatorUpdates, ValidatorUpdate{}) + if err := m.ValidatorUpdates[len(m.ValidatorUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParamUpdates", 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.ConsensusParamUpdates == nil { + m.ConsensusParamUpdates = &types1.ConsensusParams{} + } + if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -16071,7 +16902,95 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field RetainHeight", wireType) } - m.RetainHeight = 0 + m.RetainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RetainHeight |= int64(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 *CommitInfo) 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: CommitInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -16081,11 +17000,26 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.RetainHeight |= int64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, VoteInfo{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -16107,7 +17041,7 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { } return nil } -func (m *CommitInfo) Unmarshal(dAtA []byte) error { +func (m *ExtendedCommitInfo) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -16130,10 +17064,10 @@ func (m *CommitInfo) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CommitInfo: wiretype end group for non-group") + return fmt.Errorf("proto: ExtendedCommitInfo: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExtendedCommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -16184,7 +17118,7 @@ func (m *CommitInfo) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Votes = append(m.Votes, VoteInfo{}) + m.Votes = append(m.Votes, ExtendedVoteInfo{}) if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -16886,6 +17820,109 @@ func (m *TxResult) Unmarshal(dAtA []byte) error { } return nil } +func (m *TxRecord) 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: TxRecord: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TxRecord: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Action", wireType) + } + m.Action = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Action |= TxRecord_TxAction(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tx", 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.Tx = append(m.Tx[:0], dAtA[iNdEx:postIndex]...) + if m.Tx == nil { + m.Tx = []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 *Validator) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -17194,6 +18231,143 @@ func (m *VoteInfo) Unmarshal(dAtA []byte) error { } return nil } +func (m *ExtendedVoteInfo) 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: ExtendedVoteInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExtendedVoteInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedLastBlock", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SignedLastBlock = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteExtension", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VoteExtension = append(m.VoteExtension[:0], dAtA[iNdEx:postIndex]...) + if m.VoteExtension == nil { + m.VoteExtension = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Evidence) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/abci/types/types_test.go b/abci/types/types_test.go new file mode 100644 index 000000000..f79a24454 --- /dev/null +++ b/abci/types/types_test.go @@ -0,0 +1,74 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/merkle" +) + +func TestHashAndProveResults(t *testing.T) { + trs := []*abci.ExecTxResult{ + // Note, these tests rely on the first two entries being in this order. + {Code: 0, Data: nil}, + {Code: 0, Data: []byte{}}, + + {Code: 0, Data: []byte("one")}, + {Code: 14, Data: nil}, + {Code: 14, Data: []byte("foo")}, + {Code: 14, Data: []byte("bar")}, + } + + // Nil and []byte{} should produce the same bytes + bz0, err := trs[0].Marshal() + require.NoError(t, err) + bz1, err := trs[1].Marshal() + require.NoError(t, err) + require.Equal(t, bz0, bz1) + + // Make sure that we can get a root hash from results and verify proofs. + rs, err := abci.MarshalTxResults(trs) + require.NoError(t, err) + root := merkle.HashFromByteSlices(rs) + assert.NotEmpty(t, root) + + _, proofs := merkle.ProofsFromByteSlices(rs) + for i, tr := range trs { + bz, err := tr.Marshal() + require.NoError(t, err) + + valid := proofs[i].Verify(root, bz) + assert.NoError(t, valid, "%d", i) + } +} + +func TestHashDeterministicFieldsOnly(t *testing.T) { + tr1 := abci.ExecTxResult{ + Code: 1, + Data: []byte("transaction"), + Log: "nondeterministic data: abc", + Info: "nondeterministic data: abc", + GasWanted: 1000, + GasUsed: 1000, + Events: []abci.Event{}, + Codespace: "nondeterministic.data.abc", + } + tr2 := abci.ExecTxResult{ + Code: 1, + Data: []byte("transaction"), + Log: "nondeterministic data: def", + Info: "nondeterministic data: def", + GasWanted: 1000, + GasUsed: 1000, + Events: []abci.Event{}, + Codespace: "nondeterministic.data.def", + } + r1, err := abci.MarshalTxResults([]*abci.ExecTxResult{&tr1}) + require.NoError(t, err) + r2, err := abci.MarshalTxResults([]*abci.ExecTxResult{&tr2}) + require.NoError(t, err) + require.Equal(t, merkle.HashFromByteSlices(r1), merkle.HashFromByteSlices(r2)) +} diff --git a/internal/blocksync/reactor_test.go b/internal/blocksync/reactor_test.go index 8d3399d52..14264e040 100644 --- a/internal/blocksync/reactor_test.go +++ b/internal/blocksync/reactor_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/fortytw2/leaktest" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" dbm "github.com/tendermint/tm-db" @@ -15,7 +16,7 @@ import ( "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/internal/consensus" "github.com/tendermint/tendermint/internal/eventbus" - "github.com/tendermint/tendermint/internal/mempool/mock" + mpmocks "github.com/tendermint/tendermint/internal/mempool/mocks" "github.com/tendermint/tendermint/internal/p2p" "github.com/tendermint/tendermint/internal/p2p/p2ptest" "github.com/tendermint/tendermint/internal/proxy" @@ -121,6 +122,17 @@ func (rts *reactorTestSuite) addNode( state, err := sm.MakeGenesisState(genDoc) require.NoError(t, err) require.NoError(t, stateStore.Save(state)) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) eventbus := eventbus.NewDefault(logger) require.NoError(t, eventbus.Start(ctx)) @@ -129,7 +141,7 @@ func (rts *reactorTestSuite) addNode( stateStore, log.TestingLogger(), rts.app[nodeID], - mock.Mempool{}, + mp, sm.EmptyEvidencePool{}, blockStore, eventbus, @@ -159,8 +171,7 @@ func (rts *reactorTestSuite) addNode( ) } - thisBlock, err := sf.MakeBlock(state, blockHeight, lastCommit) - require.NoError(t, err) + thisBlock := sf.MakeBlock(state, blockHeight, lastCommit) thisParts, err := thisBlock.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) blockID := types.BlockID{Hash: thisBlock.Hash(), PartSetHeader: thisParts.Header()} diff --git a/internal/consensus/byzantine_test.go b/internal/consensus/byzantine_test.go index 0573bd19d..221baf3e1 100644 --- a/internal/consensus/byzantine_test.go +++ b/internal/consensus/byzantine_test.go @@ -176,7 +176,6 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { require.NotNil(t, lazyNodeState.privValidator) var commit *types.Commit - var votes []*types.Vote switch { case lazyNodeState.Height == lazyNodeState.state.InitialHeight: // We're creating a proposal for the first block. @@ -185,7 +184,6 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { case lazyNodeState.LastCommit.HasTwoThirdsMajority(): // Make the commit from LastCommit commit = lazyNodeState.LastCommit.MakeCommit() - votes = lazyNodeState.LastCommit.GetVotes() default: // This shouldn't happen. lazyNodeState.logger.Error("enterPropose: Cannot propose anything: No commit for the previous block") return @@ -202,9 +200,10 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { } proposerAddr := lazyNodeState.privValidatorPubKey.Address() - block, blockParts, err := lazyNodeState.blockExec.CreateProposalBlock( - ctx, lazyNodeState.Height, lazyNodeState.state, commit, proposerAddr, votes, - ) + block, err := lazyNodeState.blockExec.CreateProposalBlock( + ctx, lazyNodeState.Height, lazyNodeState.state, commit, proposerAddr, nil) + require.NoError(t, err) + blockParts, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) // Flush the WAL. Otherwise, we may not recompute the same proposal to sign, diff --git a/internal/consensus/common_test.go b/internal/consensus/common_test.go index c9c207b55..b0f22e54f 100644 --- a/internal/consensus/common_test.go +++ b/internal/consensus/common_test.go @@ -242,7 +242,9 @@ func decideProposal( t.Helper() cs1.mtx.Lock() - block, blockParts, err := cs1.createProposalBlock(ctx) + block, err := cs1.createProposalBlock(ctx) + require.NoError(t, err) + blockParts, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) validRound := cs1.ValidRound chainID := cs1.state.ChainID diff --git a/internal/consensus/mempool_test.go b/internal/consensus/mempool_test.go index 41e981003..e527e8598 100644 --- a/internal/consensus/mempool_test.go +++ b/internal/consensus/mempool_test.go @@ -310,7 +310,7 @@ func (app *CounterApplication) Commit() abci.ResponseCommit { func (app *CounterApplication) PrepareProposal( req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { - return abci.ResponsePrepareProposal{BlockData: req.BlockData} + return abci.ResponsePrepareProposal{} } func (app *CounterApplication) ProcessProposal( diff --git a/internal/consensus/pbts_test.go b/internal/consensus/pbts_test.go index f99ec7e39..1cb6892c4 100644 --- a/internal/consensus/pbts_test.go +++ b/internal/consensus/pbts_test.go @@ -203,7 +203,7 @@ func (p *pbtsTestHarness) nextHeight(ctx context.Context, t *testing.T, proposer ensureNewRound(t, p.roundCh, p.currentHeight, p.currentRound) - b, _, err := p.observedState.createProposalBlock(ctx) + b, err := p.observedState.createProposalBlock(ctx) require.NoError(t, err) b.Height = p.currentHeight b.Header.Height = p.currentHeight diff --git a/internal/consensus/replay_test.go b/internal/consensus/replay_test.go index 2f6a531da..c735e9977 100644 --- a/internal/consensus/replay_test.go +++ b/internal/consensus/replay_test.go @@ -380,7 +380,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) err = assertMempool(t, css[0].txNotifier).CheckTx(ctx, newValidatorTx1, nil, mempool.TxInfo{}) assert.NoError(t, err) - propBlock, _, err := css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) + propBlock, err := css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) require.NoError(t, err) propBlockParts, err := propBlock.MakePartSet(partSize) require.NoError(t, err) @@ -414,7 +414,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25) err = assertMempool(t, css[0].txNotifier).CheckTx(ctx, updateValidatorTx1, nil, mempool.TxInfo{}) assert.NoError(t, err) - propBlock, _, err = css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) + propBlock, err = css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) require.NoError(t, err) propBlockParts, err = propBlock.MakePartSet(partSize) require.NoError(t, err) @@ -455,7 +455,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) err = assertMempool(t, css[0].txNotifier).CheckTx(ctx, newValidatorTx3, nil, mempool.TxInfo{}) assert.NoError(t, err) - propBlock, _, err = css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) + propBlock, err = css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) require.NoError(t, err) propBlockParts, err = propBlock.MakePartSet(partSize) require.NoError(t, err) @@ -543,7 +543,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { removeValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, 0) err = assertMempool(t, css[0].txNotifier).CheckTx(ctx, removeValidatorTx3, nil, mempool.TxInfo{}) assert.NoError(t, err) - propBlock, _, err = css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) + propBlock, err = css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) require.NoError(t, err) propBlockParts, err = propBlock.MakePartSet(partSize) require.NoError(t, err) diff --git a/internal/consensus/state.go b/internal/consensus/state.go index bbb28f1d4..92b5b84d6 100644 --- a/internal/consensus/state.go +++ b/internal/consensus/state.go @@ -1300,8 +1300,16 @@ func (cs *State) defaultDecideProposal(ctx context.Context, height int64, round } else { // Create a new proposal block from state/txs from the mempool. var err error - block, blockParts, err = cs.createProposalBlock(ctx) - if block == nil || err != nil { + block, err = cs.createProposalBlock(ctx) + if err != nil { + cs.logger.Error("unable to create proposal block", "error", err) + return + } else if block == nil { + return + } + blockParts, err = block.MakePartSet(types.BlockPartSizeBytes) + if err != nil { + cs.logger.Error("unable to create proposal block part set", "error", err) return } } @@ -1360,13 +1368,12 @@ func (cs *State) isProposalComplete() bool { // // NOTE: keep it side-effect free for clarity. // CONTRACT: cs.privValidator is not nil. -func (cs *State) createProposalBlock(ctx context.Context) (block *types.Block, blockParts *types.PartSet, err error) { +func (cs *State) createProposalBlock(ctx context.Context) (*types.Block, error) { if cs.privValidator == nil { - return nil, nil, errors.New("entered createProposalBlock with privValidator being nil") + return nil, errors.New("entered createProposalBlock with privValidator being nil") } var commit *types.Commit - var votes []*types.Vote switch { case cs.Height == cs.state.InitialHeight: // We're creating a proposal for the first block. @@ -1376,23 +1383,22 @@ func (cs *State) createProposalBlock(ctx context.Context) (block *types.Block, b case cs.LastCommit.HasTwoThirdsMajority(): // Make the commit from LastCommit commit = cs.LastCommit.MakeCommit() - votes = cs.LastCommit.GetVotes() default: // This shouldn't happen. cs.logger.Error("propose step; cannot propose anything without commit for the previous block") - return + return nil, nil } if cs.privValidatorPubKey == nil { // If this node is a validator & proposer in the current round, it will // miss the opportunity to create a block. cs.logger.Error("propose step; empty priv validator public key", "err", errPubKeyIsNotSet) - return + return nil, nil } proposerAddr := cs.privValidatorPubKey.Address() - return cs.blockExec.CreateProposalBlock(ctx, cs.Height, cs.state, commit, proposerAddr, votes) + return cs.blockExec.CreateProposalBlock(ctx, cs.Height, cs.state, commit, proposerAddr, cs.LastCommit.GetVotes()) } // Enter: `timeoutPropose` after entering Propose. diff --git a/internal/consensus/state_test.go b/internal/consensus/state_test.go index 9e67adf31..f008e75d3 100644 --- a/internal/consensus/state_test.go +++ b/internal/consensus/state_test.go @@ -220,7 +220,7 @@ func TestStateBadProposal(t *testing.T) { proposalCh := subscribe(ctx, t, cs1.eventBus, types.EventQueryCompleteProposal) voteCh := subscribe(ctx, t, cs1.eventBus, types.EventQueryVote) - propBlock, _, err := cs1.createProposalBlock(ctx) // changeProposer(t, cs1, vs2) + propBlock, err := cs1.createProposalBlock(ctx) // changeProposer(t, cs1, vs2) require.NoError(t, err) // make the second validator the proposer by incrementing round @@ -282,7 +282,7 @@ func TestStateOversizedBlock(t *testing.T) { timeoutProposeCh := subscribe(ctx, t, cs1.eventBus, types.EventQueryTimeoutPropose) voteCh := subscribe(ctx, t, cs1.eventBus, types.EventQueryVote) - propBlock, _, err := cs1.createProposalBlock(ctx) + propBlock, err := cs1.createProposalBlock(ctx) require.NoError(t, err) propBlock.Data.Txs = []types.Tx{tmrand.Bytes(2001)} propBlock.Header.DataHash = propBlock.Data.Hash() @@ -2632,7 +2632,7 @@ func TestStateTimestamp_ProposalNotMatch(t *testing.T) { addr := pv1.Address() voteCh := subscribeToVoter(ctx, t, cs1, addr) - propBlock, _, err := cs1.createProposalBlock(ctx) + propBlock, err := cs1.createProposalBlock(ctx) require.NoError(t, err) round++ incrementRound(vss[1:]...) @@ -2680,7 +2680,7 @@ func TestStateTimestamp_ProposalMatch(t *testing.T) { addr := pv1.Address() voteCh := subscribeToVoter(ctx, t, cs1, addr) - propBlock, _, err := cs1.createProposalBlock(ctx) + propBlock, err := cs1.createProposalBlock(ctx) require.NoError(t, err) round++ incrementRound(vss[1:]...) diff --git a/internal/evidence/pool_test.go b/internal/evidence/pool_test.go index b3f5df9f1..dcf44a5df 100644 --- a/internal/evidence/pool_test.go +++ b/internal/evidence/pool_test.go @@ -569,10 +569,7 @@ func initializeBlockStore(db dbm.DB, state sm.State, valAddr []byte) (*store.Blo for i := int64(1); i <= state.LastBlockHeight; i++ { lastCommit := makeCommit(i-1, valAddr) - block, err := sf.MakeBlock(state, i, lastCommit) - if err != nil { - return nil, err - } + block := sf.MakeBlock(state, i, lastCommit) block.Header.Time = defaultEvidenceTime.Add(time.Duration(i) * time.Minute) block.Header.Version = version.Consensus{Block: version.BlockProtocol, App: 1} diff --git a/internal/mempool/mock/mempool.go b/internal/mempool/mock/mempool.go deleted file mode 100644 index 1a0cd75ae..000000000 --- a/internal/mempool/mock/mempool.go +++ /dev/null @@ -1,46 +0,0 @@ -package mock - -import ( - "context" - - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/internal/libs/clist" - "github.com/tendermint/tendermint/internal/mempool" - "github.com/tendermint/tendermint/types" -) - -// Mempool is an empty implementation of a Mempool, useful for testing. -type Mempool struct{} - -var _ Mempool = Mempool{} - -func (Mempool) Lock() {} -func (Mempool) Unlock() {} -func (Mempool) Size() int { return 0 } -func (Mempool) CheckTx(context.Context, types.Tx, func(*abci.ResponseCheckTx), mempool.TxInfo) error { - return nil -} -func (Mempool) RemoveTxByKey(txKey types.TxKey) error { return nil } -func (Mempool) ReapMaxBytesMaxGas(_, _ int64) types.Txs { return types.Txs{} } -func (Mempool) ReapMaxTxs(n int) types.Txs { return types.Txs{} } -func (Mempool) Update( - _ context.Context, - _ int64, - _ types.Txs, - _ []*abci.ExecTxResult, - _ mempool.PreCheckFunc, - _ mempool.PostCheckFunc, -) error { - return nil -} -func (Mempool) Flush() {} -func (Mempool) FlushAppConn(ctx context.Context) error { return nil } -func (Mempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } -func (Mempool) EnableTxsAvailable() {} -func (Mempool) SizeBytes() int64 { return 0 } - -func (Mempool) TxsFront() *clist.CElement { return nil } -func (Mempool) TxsWaitChan() <-chan struct{} { return nil } - -func (Mempool) InitWAL() error { return nil } -func (Mempool) CloseWAL() {} diff --git a/internal/mempool/mocks/mempool.go b/internal/mempool/mocks/mempool.go new file mode 100644 index 000000000..d4cdfabd7 --- /dev/null +++ b/internal/mempool/mocks/mempool.go @@ -0,0 +1,172 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + context "context" + + abcitypes "github.com/tendermint/tendermint/abci/types" + + mempool "github.com/tendermint/tendermint/internal/mempool" + + mock "github.com/stretchr/testify/mock" + + types "github.com/tendermint/tendermint/types" +) + +// Mempool is an autogenerated mock type for the Mempool type +type Mempool struct { + mock.Mock +} + +// CheckTx provides a mock function with given fields: ctx, tx, callback, txInfo +func (_m *Mempool) CheckTx(ctx context.Context, tx types.Tx, callback func(*abcitypes.ResponseCheckTx), txInfo mempool.TxInfo) error { + ret := _m.Called(ctx, tx, callback, txInfo) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.Tx, func(*abcitypes.ResponseCheckTx), mempool.TxInfo) error); ok { + r0 = rf(ctx, tx, callback, txInfo) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// EnableTxsAvailable provides a mock function with given fields: +func (_m *Mempool) EnableTxsAvailable() { + _m.Called() +} + +// Flush provides a mock function with given fields: +func (_m *Mempool) Flush() { + _m.Called() +} + +// FlushAppConn provides a mock function with given fields: _a0 +func (_m *Mempool) FlushAppConn(_a0 context.Context) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Lock provides a mock function with given fields: +func (_m *Mempool) Lock() { + _m.Called() +} + +// ReapMaxBytesMaxGas provides a mock function with given fields: maxBytes, maxGas +func (_m *Mempool) ReapMaxBytesMaxGas(maxBytes int64, maxGas int64) types.Txs { + ret := _m.Called(maxBytes, maxGas) + + var r0 types.Txs + if rf, ok := ret.Get(0).(func(int64, int64) types.Txs); ok { + r0 = rf(maxBytes, maxGas) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.Txs) + } + } + + return r0 +} + +// ReapMaxTxs provides a mock function with given fields: max +func (_m *Mempool) ReapMaxTxs(max int) types.Txs { + ret := _m.Called(max) + + var r0 types.Txs + if rf, ok := ret.Get(0).(func(int) types.Txs); ok { + r0 = rf(max) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.Txs) + } + } + + return r0 +} + +// RemoveTxByKey provides a mock function with given fields: txKey +func (_m *Mempool) RemoveTxByKey(txKey types.TxKey) error { + ret := _m.Called(txKey) + + var r0 error + if rf, ok := ret.Get(0).(func(types.TxKey) error); ok { + r0 = rf(txKey) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Size provides a mock function with given fields: +func (_m *Mempool) Size() int { + ret := _m.Called() + + var r0 int + if rf, ok := ret.Get(0).(func() int); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int) + } + + return r0 +} + +// SizeBytes provides a mock function with given fields: +func (_m *Mempool) SizeBytes() int64 { + ret := _m.Called() + + var r0 int64 + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + return r0 +} + +// TxsAvailable provides a mock function with given fields: +func (_m *Mempool) TxsAvailable() <-chan struct{} { + ret := _m.Called() + + var r0 <-chan struct{} + if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(<-chan struct{}) + } + } + + return r0 +} + +// Unlock provides a mock function with given fields: +func (_m *Mempool) Unlock() { + _m.Called() +} + +// Update provides a mock function with given fields: ctx, blockHeight, blockTxs, txResults, newPreFn, newPostFn +func (_m *Mempool) Update(ctx context.Context, blockHeight int64, blockTxs types.Txs, txResults []*abcitypes.ExecTxResult, newPreFn mempool.PreCheckFunc, newPostFn mempool.PostCheckFunc) error { + ret := _m.Called(ctx, blockHeight, blockTxs, txResults, newPreFn, newPostFn) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64, types.Txs, []*abcitypes.ExecTxResult, mempool.PreCheckFunc, mempool.PostCheckFunc) error); ok { + r0 = rf(ctx, blockHeight, blockTxs, txResults, newPreFn, newPostFn) + } else { + r0 = ret.Error(0) + } + + return r0 +} diff --git a/internal/mempool/types.go b/internal/mempool/types.go index c2124d538..a51d286e2 100644 --- a/internal/mempool/types.go +++ b/internal/mempool/types.go @@ -23,6 +23,8 @@ const ( MaxActiveIDs = math.MaxUint16 ) +//go:generate ../../scripts/mockery_generate.sh Mempool + // Mempool defines the mempool interface. // // Updates to the mempool need to be synchronized with committing a block so diff --git a/internal/rpc/core/tx.go b/internal/rpc/core/tx.go index 126875d0d..73fa6d2c8 100644 --- a/internal/rpc/core/tx.go +++ b/internal/rpc/core/tx.go @@ -36,19 +36,16 @@ func (env *Environment) Tx(ctx context.Context, hash bytes.HexBytes, prove bool) return nil, fmt.Errorf("tx (%X) not found, err: %w", hash, err) } - height := r.Height - index := r.Index - var proof types.TxProof if prove { - block := env.BlockStore.LoadBlock(height) - proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines + block := env.BlockStore.LoadBlock(r.Height) + proof = block.Data.Txs.Proof(int(r.Index)) } return &coretypes.ResultTx{ Hash: hash, - Height: height, - Index: index, + Height: r.Height, + Index: r.Index, TxResult: r.Result, Tx: r.Tx, Proof: proof, @@ -127,7 +124,7 @@ func (env *Environment) TxSearch( var proof types.TxProof if prove { block := env.BlockStore.LoadBlock(r.Height) - proof = block.Data.Txs.Proof(int(r.Index)) // XXX: overflow on 32-bit machines + proof = block.Data.Txs.Proof(int(r.Index)) } apiResults = append(apiResults, &coretypes.ResultTx{ diff --git a/internal/state/execution.go b/internal/state/execution.go index 158d0d137..3423b00f6 100644 --- a/internal/state/execution.go +++ b/internal/state/execution.go @@ -8,6 +8,7 @@ import ( abciclient "github.com/tendermint/tendermint/abci/client" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/encoding" + "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/internal/eventbus" "github.com/tendermint/tendermint/internal/mempool" "github.com/tendermint/tendermint/libs/log" @@ -99,10 +100,11 @@ func (blockExec *BlockExecutor) Store() Store { func (blockExec *BlockExecutor) CreateProposalBlock( ctx context.Context, height int64, - state State, commit *types.Commit, + state State, + commit *types.Commit, proposerAddr []byte, votes []*types.Vote, -) (*types.Block, *types.PartSet, error) { +) (*types.Block, error) { maxBytes := state.ConsensusParams.Block.MaxBytes maxGas := state.ConsensusParams.Block.MaxGas @@ -113,13 +115,18 @@ func (blockExec *BlockExecutor) CreateProposalBlock( maxDataBytes := types.MaxDataBytes(maxBytes, evSize, state.Validators.Size()) txs := blockExec.mempool.ReapMaxBytesMaxGas(maxDataBytes, maxGas) + block := state.MakeBlock(height, txs, commit, evidence, proposerAddr) - preparedProposal, err := blockExec.appClient.PrepareProposal( + localLastCommit := buildLastCommitInfo(block, blockExec.store, state.InitialHeight) + rpp, err := blockExec.appClient.PrepareProposal( ctx, abci.RequestPrepareProposal{ - BlockData: txs.ToSliceOfBytes(), - BlockDataSize: maxDataBytes, - Votes: types.VotesToProto(votes), + Hash: block.Hash(), + Header: *block.Header.ToProto(), + Txs: block.Txs.ToSliceOfBytes(), + LocalLastCommit: extendedCommitInfo(localLastCommit, votes), + ByzantineValidators: block.Evidence.ToABCI(), + MaxTxBytes: maxDataBytes, }, ) if err != nil { @@ -133,19 +140,28 @@ func (blockExec *BlockExecutor) CreateProposalBlock( // purpose for now. panic(err) } - newTxs := preparedProposal.GetBlockData() - var txSize int - for _, tx := range newTxs { - txSize += len(tx) - if maxDataBytes < int64(txSize) { - panic("block data exceeds max amount of allowed bytes") - } + if !rpp.ModifiedTx { + return block, nil } + txrSet := types.NewTxRecordSet(rpp.TxRecords) - modifiedTxs := types.ToTxs(preparedProposal.GetBlockData()) + if err := txrSet.Validate(maxDataBytes, block.Txs); err != nil { + return nil, err + } - return state.MakeBlock(height, modifiedTxs, commit, evidence, proposerAddr) + for _, rtx := range txrSet.RemovedTxs() { + if err := blockExec.mempool.RemoveTxByKey(rtx.Key()); err != nil { + blockExec.logger.Debug("error removing transaction from the mempool", "error", err, "tx hash", rtx.Hash()) + } + } + for _, atx := range txrSet.AddedTxs() { + if err := blockExec.mempool.CheckTx(ctx, atx, nil, mempool.TxInfo{}); err != nil { + blockExec.logger.Error("error adding tx to the mempool", "error", err, "tx hash", atx.Hash()) + } + } + itxs := txrSet.IncludedTxs() + return state.MakeBlock(height, itxs, commit, evidence, proposerAddr), nil } func (blockExec *BlockExecutor) ProcessProposal( @@ -249,7 +265,12 @@ func (blockExec *BlockExecutor) ApplyBlock( } // Update the state with the block and responses. - state, err = state.Update(blockID, &block.Header, ABCIResponsesResultsHash(abciResponses), finalizeBlockResponse.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(finalizeBlockResponse.TxResults) + if err != nil { + return state, fmt.Errorf("marshaling TxResults: %w", err) + } + h := merkle.HashFromByteSlices(rs) + state, err = state.Update(blockID, &block.Header, h, finalizeBlockResponse.ConsensusParamUpdates, validatorUpdates) if err != nil { return state, fmt.Errorf("commit failed for application: %w", err) } @@ -410,6 +431,24 @@ func buildLastCommitInfo(block *types.Block, store Store, initialHeight int64) a } } +func extendedCommitInfo(c abci.CommitInfo, votes []*types.Vote) abci.ExtendedCommitInfo { + vs := make([]abci.ExtendedVoteInfo, len(c.Votes)) + for i := range vs { + vs[i] = abci.ExtendedVoteInfo{ + Validator: c.Votes[i].Validator, + SignedLastBlock: c.Votes[i].SignedLastBlock, + /* + TODO: Include vote extensions information when implementing vote extensions. + VoteExtension: []byte{}, + */ + } + } + return abci.ExtendedCommitInfo{ + Round: c.Round, + Votes: vs, + } +} + func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, params types.ValidatorParams) error { for _, valUpdate := range abciUpdates { diff --git a/internal/state/execution_test.go b/internal/state/execution_test.go index 451a9e2bb..e62735a4a 100644 --- a/internal/state/execution_test.go +++ b/internal/state/execution_test.go @@ -18,7 +18,7 @@ import ( "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/internal/eventbus" - mmock "github.com/tendermint/tendermint/internal/mempool/mock" + mpmocks "github.com/tendermint/tendermint/internal/mempool/mocks" "github.com/tendermint/tendermint/internal/proxy" "github.com/tendermint/tendermint/internal/pubsub" sm "github.com/tendermint/tendermint/internal/state" @@ -53,10 +53,20 @@ func TestApplyBlock(t *testing.T) { state, stateDB, _ := makeState(t, 1, 1) stateStore := sm.NewStore(stateDB) blockStore := store.NewBlockStore(dbm.NewMemDB()) - blockExec := sm.NewBlockExecutor(stateStore, logger, proxyApp, mmock.Mempool{}, sm.EmptyEvidencePool{}, blockStore, eventBus) - - block, err := sf.MakeBlock(state, 1, new(types.Commit)) - require.NoError(t, err) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + blockExec := sm.NewBlockExecutor(stateStore, logger, proxyApp, mp, sm.EmptyEvidencePool{}, blockStore, eventBus) + + block := sf.MakeBlock(state, 1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} @@ -103,11 +113,22 @@ func TestFinalizeBlockDecidedLastCommit(t *testing.T) { evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, 0) evpool.On("Update", ctx, mock.Anything, mock.Anything).Return() evpool.On("CheckEvidence", ctx, mock.Anything).Return(nil) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) eventBus := eventbus.NewDefault(logger) require.NoError(t, eventBus.Start(ctx)) - blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), appClient, mmock.Mempool{}, evpool, blockStore, eventBus) + blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), appClient, mp, evpool, blockStore, eventBus) state, _, lastCommit := makeAndCommitGoodBlock(ctx, t, state, 1, new(types.Commit), state.NextValidators.Validators[0].Address, blockExec, privVals, nil) for idx, isAbsent := range tc.absentCommitSigs { @@ -117,8 +138,7 @@ func TestFinalizeBlockDecidedLastCommit(t *testing.T) { } // block for height 2 - block, err := sf.MakeBlock(state, 2, lastCommit) - require.NoError(t, err) + block := sf.MakeBlock(state, 2, lastCommit) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} @@ -215,6 +235,17 @@ func TestFinalizeBlockByzantineValidators(t *testing.T) { evpool.On("PendingEvidence", mock.AnythingOfType("int64")).Return(ev, int64(100)) evpool.On("Update", ctx, mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return() evpool.On("CheckEvidence", ctx, mock.AnythingOfType("types.EvidenceList")).Return(nil) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) eventBus := eventbus.NewDefault(logger) require.NoError(t, eventBus.Start(ctx)) @@ -222,10 +253,9 @@ func TestFinalizeBlockByzantineValidators(t *testing.T) { blockStore := store.NewBlockStore(dbm.NewMemDB()) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp, - mmock.Mempool{}, evpool, blockStore, eventBus) + mp, evpool, blockStore, eventBus) - block, err := sf.MakeBlock(state, 1, new(types.Commit)) - require.NoError(t, err) + block := sf.MakeBlock(state, 1, new(types.Commit)) block.Evidence = ev block.Header.EvidenceHash = block.Evidence.Hash() bps, err := block.MakePartSet(testPartSize) @@ -264,14 +294,13 @@ func TestProcessProposal(t *testing.T) { stateStore, logger, proxyApp, - mmock.Mempool{}, + new(mpmocks.Mempool), sm.EmptyEvidencePool{}, blockStore, eventBus, ) - block0, err := sf.MakeBlock(state, height-1, new(types.Commit)) - require.NoError(t, err) + block0 := sf.MakeBlock(state, height-1, new(types.Commit)) lastCommitSig := []types.CommitSig{} partSet, err := block0.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) @@ -295,8 +324,7 @@ func TestProcessProposal(t *testing.T) { } lastCommit := types.NewCommit(height-1, 0, types.BlockID{}, lastCommitSig) - block1, err := sf.MakeBlock(state, height, lastCommit) - require.NoError(t, err) + block1 := sf.MakeBlock(state, height, lastCommit) block1.Txs = txs expectedRpp := abci.RequestProcessProposal{ @@ -463,6 +491,18 @@ func TestFinalizeBlockValidatorUpdates(t *testing.T) { state, stateDB, _ := makeState(t, 1, 1) stateStore := sm.NewStore(stateDB) blockStore := store.NewBlockStore(dbm.NewMemDB()) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{}) eventBus := eventbus.NewDefault(logger) require.NoError(t, eventBus.Start(ctx)) @@ -471,7 +511,7 @@ func TestFinalizeBlockValidatorUpdates(t *testing.T) { stateStore, logger, proxyApp, - mmock.Mempool{}, + mp, sm.EmptyEvidencePool{}, blockStore, eventBus, @@ -483,8 +523,7 @@ func TestFinalizeBlockValidatorUpdates(t *testing.T) { }) require.NoError(t, err) - block, err := sf.MakeBlock(state, 1, new(types.Commit)) - require.NoError(t, err) + block := sf.MakeBlock(state, 1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} @@ -542,14 +581,13 @@ func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { stateStore, log.TestingLogger(), proxyApp, - mmock.Mempool{}, + new(mpmocks.Mempool), sm.EmptyEvidencePool{}, blockStore, eventBus, ) - block, err := sf.MakeBlock(state, 1, new(types.Commit)) - require.NoError(t, err) + block := sf.MakeBlock(state, 1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} @@ -566,6 +604,292 @@ func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { assert.NotEmpty(t, state.NextValidators.Validators) } +func TestEmptyPrepareProposal(t *testing.T) { + const height = 2 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + logger := log.TestingLogger() + + eventBus := eventbus.NewDefault(logger) + require.NoError(t, eventBus.Start(ctx)) + + app := abcimocks.NewBaseMock() + cc := abciclient.NewLocalClient(logger, app) + proxyApp := proxy.New(cc, logger, proxy.NopMetrics()) + err := proxyApp.Start(ctx) + require.NoError(t, err) + + state, stateDB, privVals := makeState(t, 1, height) + stateStore := sm.NewStore(stateDB) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{}) + + blockExec := sm.NewBlockExecutor( + stateStore, + logger, + proxyApp, + mp, + sm.EmptyEvidencePool{}, + nil, + eventBus, + ) + pa, _ := state.Validators.GetByIndex(0) + commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals) + _, err = blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil) + require.NoError(t, err) +} + +// TestPrepareProposalRemoveTxs tests that any transactions marked as REMOVED +// are not included in the block produced by CreateProposalBlock. The test also +// ensures that any transactions removed are also removed from the mempool. +func TestPrepareProposalRemoveTxs(t *testing.T) { + const height = 2 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + logger := log.TestingLogger() + eventBus := eventbus.NewDefault(logger) + require.NoError(t, eventBus.Start(ctx)) + + state, stateDB, privVals := makeState(t, 1, height) + stateStore := sm.NewStore(stateDB) + + evpool := &mocks.EvidencePool{} + evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0)) + + txs := factory.MakeTenTxs(height) + mp := &mpmocks.Mempool{} + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs)) + + trs := txsToTxRecords(types.Txs(txs)) + trs[0].Action = abci.TxRecord_REMOVED + trs[1].Action = abci.TxRecord_REMOVED + mp.On("RemoveTxByKey", mock.Anything).Return(nil).Twice() + + app := abcimocks.NewBaseMock() + app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{ + ModifiedTx: true, + TxRecords: trs, + }, nil) + + cc := abciclient.NewLocalClient(logger, app) + proxyApp := proxy.New(cc, logger, proxy.NopMetrics()) + err := proxyApp.Start(ctx) + require.NoError(t, err) + + blockExec := sm.NewBlockExecutor( + stateStore, + logger, + proxyApp, + mp, + evpool, + nil, + eventBus, + ) + pa, _ := state.Validators.GetByIndex(0) + commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals) + block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil) + require.NoError(t, err) + require.Len(t, block.Data.Txs.ToSliceOfBytes(), len(trs)-2) + + require.Equal(t, -1, block.Data.Txs.Index(types.Tx(trs[0].Tx))) + require.Equal(t, -1, block.Data.Txs.Index(types.Tx(trs[1].Tx))) + + mp.AssertCalled(t, "RemoveTxByKey", types.Tx(trs[0].Tx).Key()) + mp.AssertCalled(t, "RemoveTxByKey", types.Tx(trs[1].Tx).Key()) + mp.AssertExpectations(t) +} + +// TestPrepareProposalAddedTxsIncluded tests that any transactions marked as ADDED +// in the prepare proposal response are included in the block. The test also +// ensures that any transactions added are also checked into the mempool. +func TestPrepareProposalAddedTxsIncluded(t *testing.T) { + const height = 2 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + logger := log.TestingLogger() + eventBus := eventbus.NewDefault(logger) + require.NoError(t, eventBus.Start(ctx)) + + state, stateDB, privVals := makeState(t, 1, height) + stateStore := sm.NewStore(stateDB) + + evpool := &mocks.EvidencePool{} + evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0)) + + txs := factory.MakeTenTxs(height) + mp := &mpmocks.Mempool{} + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs[2:])) + mp.On("CheckTx", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Twice() + + trs := txsToTxRecords(types.Txs(txs)) + trs[0].Action = abci.TxRecord_ADDED + trs[1].Action = abci.TxRecord_ADDED + + app := abcimocks.NewBaseMock() + app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{ + ModifiedTx: true, + TxRecords: trs, + }, nil) + + cc := abciclient.NewLocalClient(logger, app) + proxyApp := proxy.New(cc, logger, proxy.NopMetrics()) + err := proxyApp.Start(ctx) + require.NoError(t, err) + + blockExec := sm.NewBlockExecutor( + stateStore, + logger, + proxyApp, + mp, + evpool, + nil, + eventBus, + ) + pa, _ := state.Validators.GetByIndex(0) + commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals) + block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil) + require.NoError(t, err) + + require.Equal(t, txs[0], block.Data.Txs[0]) + require.Equal(t, txs[1], block.Data.Txs[1]) + + mp.AssertExpectations(t) + mp.AssertCalled(t, "CheckTx", mock.Anything, types.Tx(trs[0].Tx), mock.Anything, mock.Anything) + mp.AssertCalled(t, "CheckTx", mock.Anything, types.Tx(trs[1].Tx), mock.Anything, mock.Anything) +} + +// TestPrepareProposalReorderTxs tests that CreateBlock produces a block with transactions +// in the order matching the order they are returned from PrepareProposal. +func TestPrepareProposalReorderTxs(t *testing.T) { + const height = 2 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + logger := log.TestingLogger() + eventBus := eventbus.NewDefault(logger) + require.NoError(t, eventBus.Start(ctx)) + + state, stateDB, privVals := makeState(t, 1, height) + stateStore := sm.NewStore(stateDB) + + evpool := &mocks.EvidencePool{} + evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0)) + + txs := factory.MakeTenTxs(height) + mp := &mpmocks.Mempool{} + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs)) + + trs := txsToTxRecords(types.Txs(txs)) + trs = trs[2:] + trs = append(trs[len(trs)/2:], trs[:len(trs)/2]...) + + app := abcimocks.NewBaseMock() + app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{ + ModifiedTx: true, + TxRecords: trs, + }, nil) + + cc := abciclient.NewLocalClient(logger, app) + proxyApp := proxy.New(cc, logger, proxy.NopMetrics()) + err := proxyApp.Start(ctx) + require.NoError(t, err) + + blockExec := sm.NewBlockExecutor( + stateStore, + logger, + proxyApp, + mp, + evpool, + nil, + eventBus, + ) + pa, _ := state.Validators.GetByIndex(0) + commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals) + block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil) + require.NoError(t, err) + for i, tx := range block.Data.Txs { + require.Equal(t, types.Tx(trs[i].Tx), tx) + } + + mp.AssertExpectations(t) + +} + +// TestPrepareProposalModifiedTxFalse tests that CreateBlock correctly ignores +// the ResponsePrepareProposal TxRecords if ResponsePrepareProposal does not +// set ModifiedTx to true. +func TestPrepareProposalModifiedTxFalse(t *testing.T) { + const height = 2 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + logger := log.TestingLogger() + eventBus := eventbus.NewDefault(logger) + require.NoError(t, eventBus.Start(ctx)) + + state, stateDB, privVals := makeState(t, 1, height) + stateStore := sm.NewStore(stateDB) + + evpool := &mocks.EvidencePool{} + evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0)) + + txs := factory.MakeTenTxs(height) + mp := &mpmocks.Mempool{} + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs)) + + trs := txsToTxRecords(types.Txs(txs)) + trs = append(trs[len(trs)/2:], trs[:len(trs)/2]...) + trs = trs[1:] + trs[0].Action = abci.TxRecord_REMOVED + trs[1] = &abci.TxRecord{ + Tx: []byte("new"), + Action: abci.TxRecord_ADDED, + } + + app := abcimocks.NewBaseMock() + app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{ + ModifiedTx: false, + TxRecords: trs, + }, nil) + + cc := abciclient.NewLocalClient(logger, app) + proxyApp := proxy.New(cc, logger, proxy.NopMetrics()) + err := proxyApp.Start(ctx) + require.NoError(t, err) + + blockExec := sm.NewBlockExecutor( + stateStore, + logger, + proxyApp, + mp, + evpool, + nil, + eventBus, + ) + pa, _ := state.Validators.GetByIndex(0) + commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals) + block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil) + require.NoError(t, err) + for i, tx := range block.Data.Txs { + require.Equal(t, txs[i], tx) + } + + mp.AssertExpectations(t) +} + func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.BlockID { var ( h = make([]byte, tmhash.Size) @@ -581,3 +905,14 @@ func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.Bloc }, } } + +func txsToTxRecords(txs []types.Tx) []*abci.TxRecord { + trs := make([]*abci.TxRecord, len(txs)) + for i, tx := range txs { + trs[i] = &abci.TxRecord{ + Action: abci.TxRecord_UNMODIFIED, + Tx: tx, + } + } + return trs +} diff --git a/internal/state/helpers_test.go b/internal/state/helpers_test.go index 6df958908..dffb6f256 100644 --- a/internal/state/helpers_test.go +++ b/internal/state/helpers_test.go @@ -18,7 +18,6 @@ import ( sm "github.com/tendermint/tendermint/internal/state" sf "github.com/tendermint/tendermint/internal/state/test/factory" "github.com/tendermint/tendermint/internal/test/factory" - tmrand "github.com/tendermint/tendermint/libs/rand" tmtime "github.com/tendermint/tendermint/libs/time" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -63,12 +62,13 @@ func makeAndApplyGoodBlock( evidence []types.Evidence, ) (sm.State, types.BlockID) { t.Helper() - block, _, err := state.MakeBlock(height, factory.MakeTenTxs(height), lastCommit, evidence, proposerAddr) + block := state.MakeBlock(height, factory.MakeTenTxs(height), lastCommit, evidence, proposerAddr) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) require.NoError(t, blockExec.ValidateBlock(ctx, state, block)) blockID := types.BlockID{Hash: block.Hash(), - PartSetHeader: types.PartSetHeader{Total: 3, Hash: tmrand.Bytes(32)}} + PartSetHeader: partSet.Header()} state, err = blockExec.ApplyBlock(ctx, state, blockID, block) require.NoError(t, err) @@ -144,8 +144,7 @@ func makeHeaderPartsResponsesValPubKeyChange( pubkey crypto.PubKey, ) (types.Header, types.BlockID, *tmstate.ABCIResponses) { - block, err := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) abciResponses := &tmstate.ABCIResponses{} // If the pubkey is new, remove the old and add the new. _, val := state.NextValidators.GetByIndex(0) @@ -173,8 +172,7 @@ func makeHeaderPartsResponsesValPowerChange( ) (types.Header, types.BlockID, *tmstate.ABCIResponses) { t.Helper() - block, err := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) abciResponses := &tmstate.ABCIResponses{} @@ -202,8 +200,7 @@ func makeHeaderPartsResponsesParams( ) (types.Header, types.BlockID, *tmstate.ABCIResponses) { t.Helper() - block, err := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) pbParams := params.ToProto() abciResponses := &tmstate.ABCIResponses{ FinalizeBlock: &abci.ResponseFinalizeBlock{ConsensusParamUpdates: &pbParams}, diff --git a/internal/state/state.go b/internal/state/state.go index 6a39e2c08..727adcef7 100644 --- a/internal/state/state.go +++ b/internal/state/state.go @@ -260,7 +260,7 @@ func (state State) MakeBlock( commit *types.Commit, evidence []types.Evidence, proposerAddress []byte, -) (*types.Block, *types.PartSet, error) { +) *types.Block { // Build base block with block data. block := types.MakeBlock(height, txs, commit, evidence) @@ -274,12 +274,7 @@ func (state State) MakeBlock( proposerAddress, ) - bps, err := block.MakePartSet(types.BlockPartSizeBytes) - if err != nil { - return nil, nil, err - } - - return block, bps, nil + return block } //------------------------------------------------------------------------ diff --git a/internal/state/state_test.go b/internal/state/state_test.go index 9c2f6e3db..18c419e4f 100644 --- a/internal/state/state_test.go +++ b/internal/state/state_test.go @@ -18,6 +18,7 @@ import ( "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/encoding" + "github.com/tendermint/tendermint/crypto/merkle" sm "github.com/tendermint/tendermint/internal/state" statefactory "github.com/tendermint/tendermint/internal/state/test/factory" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" @@ -103,8 +104,7 @@ func TestABCIResponsesSaveLoad1(t *testing.T) { state.LastBlockHeight++ // Build mock responses. - block, err := statefactory.MakeBlock(state, 2, new(types.Commit)) - require.NoError(t, err) + block := statefactory.MakeBlock(state, 2, new(types.Commit)) abciResponses := new(tmstate.ABCIResponses) dtxs := make([]*abci.ExecTxResult, 2) @@ -205,14 +205,13 @@ func TestABCIResponsesSaveLoad2(t *testing.T) { res, err := stateStore.LoadABCIResponses(h) if assert.NoError(t, err, "%d", i) { t.Log(res) - responses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - TxResults: tc.expected, - }, - } - sm.ABCIResponsesResultsHash(res) - sm.ABCIResponsesResultsHash(responses) - assert.Equal(t, sm.ABCIResponsesResultsHash(responses), sm.ABCIResponsesResultsHash(res), "%d", i) + e, err := abci.MarshalTxResults(tc.expected) + require.NoError(t, err) + he := merkle.HashFromByteSlices(e) + rs, err := abci.MarshalTxResults(res.FinalizeBlock.TxResults) + hrs := merkle.HashFromByteSlices(rs) + require.NoError(t, err) + assert.Equal(t, he, hrs, "%d", i) } } } @@ -278,9 +277,12 @@ func TestOneValidatorChangesSaveLoad(t *testing.T) { header, blockID, responses := makeHeaderPartsResponsesValPowerChange(t, state, power) validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.FinalizeBlock.ValidatorUpdates) require.NoError(t, err) - state, err = state.Update(blockID, &header, sm.ABCIResponsesResultsHash(responses), responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(responses.FinalizeBlock.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + state, err = state.Update(blockID, &header, h, responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) - err := stateStore.Save(state) + err = stateStore.Save(state) require.NoError(t, err) } @@ -451,19 +453,19 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { // NewValidatorSet calls IncrementProposerPriority but uses on a copy of val1 assert.EqualValues(t, 0, val1.ProposerPriority) - block, err := statefactory.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := statefactory.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - abciResponses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: nil, - }, + fb := &abci.ResponseFinalizeBlock{ + ValidatorUpdates: nil, } - validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) + validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) + require.NoError(t, err) + rs, err := abci.MarshalTxResults(fb.TxResults) require.NoError(t, err) - updatedState, err := state.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + h := merkle.HashFromByteSlices(rs) + updatedState, err := state.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) assert.NoError(t, err) curTotal := val1VotingPower // one increment step and one validator: 0 + power - total_power == 0 @@ -478,7 +480,10 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val2VotingPower} validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal}) assert.NoError(t, err) - updatedState2, err := updatedState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err = abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h = merkle.HashFromByteSlices(rs) + updatedState2, err := updatedState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) assert.NoError(t, err) require.Equal(t, len(updatedState2.NextValidators.Validators), 2) @@ -517,7 +522,10 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { // this will cause the diff of priorities (77) // to be larger than threshold == 2*totalVotingPower (22): - updatedState3, err := updatedState2.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err = abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h = merkle.HashFromByteSlices(rs) + updatedState3, err := updatedState2.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) assert.NoError(t, err) require.Equal(t, len(updatedState3.NextValidators.Validators), 2) @@ -569,21 +577,21 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { // we only have one validator: assert.Equal(t, val1PubKey.Address(), state.Validators.Proposer.Address) - block, err := statefactory.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := statefactory.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} // no updates: - abciResponses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: nil, - }, + fb := &abci.ResponseFinalizeBlock{ + ValidatorUpdates: nil, } - validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) + validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) require.NoError(t, err) - updatedState, err := state.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + updatedState, err := state.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) assert.NoError(t, err) // 0 + 10 (initial prio) - 10 (avg) - 10 (mostest - total) = -10 @@ -600,7 +608,10 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal}) assert.NoError(t, err) - updatedState2, err := updatedState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err = abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h = merkle.HashFromByteSlices(rs) + updatedState2, err := updatedState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) assert.NoError(t, err) require.Equal(t, len(updatedState2.NextValidators.Validators), 2) @@ -640,10 +651,13 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { updatedVal2, ) - validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) + validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) require.NoError(t, err) - updatedState3, err := updatedState2.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err = abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h = merkle.HashFromByteSlices(rs) + updatedState3, err := updatedState2.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) assert.NoError(t, err) assert.Equal(t, updatedState3.Validators.Proposer.Address, updatedState3.NextValidators.Proposer.Address) @@ -679,15 +693,16 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { // no changes in voting power and both validators have same voting power // -> proposers should alternate: oldState := updatedState3 - abciResponses = &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: nil, - }, + fb = &abci.ResponseFinalizeBlock{ + ValidatorUpdates: nil, } - validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) + validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) require.NoError(t, err) - oldState, err = oldState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err = abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h = merkle.HashFromByteSlices(rs) + oldState, err = oldState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) assert.NoError(t, err) expectedVal1Prio2 = 1 expectedVal2Prio2 = -1 @@ -696,15 +711,16 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { for i := 0; i < 1000; i++ { // no validator updates: - abciResponses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: nil, - }, + fb := &abci.ResponseFinalizeBlock{ + ValidatorUpdates: nil, } - validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) + validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) require.NoError(t, err) - updatedState, err := oldState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + updatedState, err := oldState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) assert.NoError(t, err) // alternate (and cyclic priorities): assert.NotEqual( @@ -755,21 +771,21 @@ func TestLargeGenesisValidator(t *testing.T) { oldState := state for i := 0; i < 10; i++ { // no updates: - abciResponses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: nil, - }, + fb := &abci.ResponseFinalizeBlock{ + ValidatorUpdates: nil, } - validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) + validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) require.NoError(t, err) - block, err := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - updatedState, err := oldState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + updatedState, err := oldState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) // no changes in voting power (ProposerPrio += VotingPower == Voting in 1st round; than shiftByAvg == 0, // than -Total == -Voting) @@ -791,41 +807,41 @@ func TestLargeGenesisValidator(t *testing.T) { firstAddedVal := abci.ValidatorUpdate{PubKey: fvp, Power: firstAddedValVotingPower} validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{firstAddedVal}) assert.NoError(t, err) - abciResponses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: []abci.ValidatorUpdate{firstAddedVal}, - }, + fb := &abci.ResponseFinalizeBlock{ + ValidatorUpdates: []abci.ValidatorUpdate{firstAddedVal}, } - block, err := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - updatedState, err := oldState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + updatedState, err := oldState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) lastState := updatedState for i := 0; i < 200; i++ { // no updates: - abciResponses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: nil, - }, + fb := &abci.ResponseFinalizeBlock{ + ValidatorUpdates: nil, } - validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) + validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) require.NoError(t, err) - block, err := statefactory.MakeBlock(lastState, lastState.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := statefactory.MakeBlock(lastState, lastState.LastBlockHeight+1, new(types.Commit)) bps, err = block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - updatedStateInner, err := lastState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + updatedStateInner, err := lastState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) lastState = updatedStateInner } @@ -851,18 +867,18 @@ func TestLargeGenesisValidator(t *testing.T) { validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{addedVal}) assert.NoError(t, err) - abciResponses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: []abci.ValidatorUpdate{addedVal}, - }, + fb := &abci.ResponseFinalizeBlock{ + ValidatorUpdates: []abci.ValidatorUpdate{addedVal}, } - block, err := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - state, err = state.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + state, err = state.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) } require.Equal(t, 10+2, len(state.NextValidators.Validators)) @@ -871,22 +887,23 @@ func TestLargeGenesisValidator(t *testing.T) { gp, err := encoding.PubKeyToProto(genesisPubKey) require.NoError(t, err) removeGenesisVal := abci.ValidatorUpdate{PubKey: gp, Power: 0} - abciResponses = &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal}, - }, + fb = &abci.ResponseFinalizeBlock{ + ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal}, } - block, err = statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) + block = statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) require.NoError(t, err) bps, err = block.MakePartSet(testPartSize) require.NoError(t, err) blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) + validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) require.NoError(t, err) - updatedState, err = state.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err = abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h = merkle.HashFromByteSlices(rs) + updatedState, err = state.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) // only the first added val (not the genesis val) should be left assert.Equal(t, 11, len(updatedState.NextValidators.Validators)) @@ -897,21 +914,21 @@ func TestLargeGenesisValidator(t *testing.T) { count := 0 isProposerUnchanged := true for isProposerUnchanged { - abciResponses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: nil, - }, + fb = &abci.ResponseFinalizeBlock{ + ValidatorUpdates: nil, } - validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) - require.NoError(t, err) - block, err = statefactory.MakeBlock(curState, curState.LastBlockHeight+1, new(types.Commit)) + validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) require.NoError(t, err) + block = statefactory.MakeBlock(curState, curState.LastBlockHeight+1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - curState, err = curState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + curState, err = curState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) if !bytes.Equal(curState.Validators.Proposer.Address, curState.NextValidators.Proposer.Address) { isProposerUnchanged = false @@ -927,23 +944,23 @@ func TestLargeGenesisValidator(t *testing.T) { proposers := make([]*types.Validator, numVals) for i := 0; i < 100; i++ { // no updates: - abciResponses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - ValidatorUpdates: nil, - }, + fb := &abci.ResponseFinalizeBlock{ + ValidatorUpdates: nil, } - validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates) + validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates) require.NoError(t, err) - block, err := statefactory.MakeBlock(updatedState, updatedState.LastBlockHeight+1, new(types.Commit)) - require.NoError(t, err) + block := statefactory.MakeBlock(updatedState, updatedState.LastBlockHeight+1, new(types.Commit)) bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - updatedState, err = updatedState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(fb.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + updatedState, err = updatedState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) if i > numVals { // expect proposers to cycle through after the first iteration (of numVals blocks): if proposers[i%numVals] == nil { @@ -1002,7 +1019,10 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) { var validatorUpdates []*types.Validator validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.FinalizeBlock.ValidatorUpdates) require.NoError(t, err) - state, err = state.Update(blockID, &header, sm.ABCIResponsesResultsHash(responses), responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(responses.FinalizeBlock.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + state, err = state.Update(blockID, &header, h, responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) nextHeight := state.LastBlockHeight + 1 err = stateStore.Save(state) @@ -1035,8 +1055,7 @@ func TestStateMakeBlock(t *testing.T) { proposerAddress := state.Validators.GetProposer().Address stateVersion := state.Version.Consensus - block, err := statefactory.MakeBlock(state, 2, new(types.Commit)) - require.NoError(t, err) + block := statefactory.MakeBlock(state, 2, new(types.Commit)) // test we set some fields assert.Equal(t, stateVersion, block.Version) @@ -1080,10 +1099,13 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) { header, blockID, responses := makeHeaderPartsResponsesParams(t, state, &cp) validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.FinalizeBlock.ValidatorUpdates) require.NoError(t, err) - state, err = state.Update(blockID, &header, sm.ABCIResponsesResultsHash(responses), responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) + rs, err := abci.MarshalTxResults(responses.FinalizeBlock.TxResults) + require.NoError(t, err) + h := merkle.HashFromByteSlices(rs) + state, err = state.Update(blockID, &header, h, responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates) require.NoError(t, err) - err := stateStore.Save(state) + err = stateStore.Save(state) require.NoError(t, err) } diff --git a/internal/state/store.go b/internal/state/store.go index dbde5e0d1..d9a591f6a 100644 --- a/internal/state/store.go +++ b/internal/state/store.go @@ -396,14 +396,6 @@ func (store dbStore) reverseBatchDelete(batch dbm.Batch, start, end []byte) ([]b //------------------------------------------------------------------------ -// ABCIResponsesResultsHash returns the root hash of a Merkle tree of -// ResponseDeliverTx responses (see ABCIResults.Hash) -// -// See merkle.SimpleHashFromByteSlices -func ABCIResponsesResultsHash(ar *tmstate.ABCIResponses) []byte { - return types.NewResults(ar.FinalizeBlock.TxResults).Hash() -} - // LoadABCIResponses loads the ABCIResponses for the given height from the // database. If not found, ErrNoABCIResponsesForHeight is returned. // diff --git a/internal/state/store_test.go b/internal/state/store_test.go index 0134d5987..59084fd10 100644 --- a/internal/state/store_test.go +++ b/internal/state/store_test.go @@ -7,7 +7,6 @@ import ( "os" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" dbm "github.com/tendermint/tm-db" @@ -299,25 +298,3 @@ func TestPruneStates(t *testing.T) { }) } } - -func TestABCIResponsesResultsHash(t *testing.T) { - responses := &tmstate.ABCIResponses{ - FinalizeBlock: &abci.ResponseFinalizeBlock{ - TxResults: []*abci.ExecTxResult{ - {Code: 32, Data: []byte("Hello"), Log: "Huh?"}, - }, - }, - } - - root := sm.ABCIResponsesResultsHash(responses) - - // root should be Merkle tree root of FinalizeBlock tx responses - results := types.NewResults(responses.FinalizeBlock.TxResults) - assert.Equal(t, root, results.Hash()) - - // test we can prove first tx in FinalizeBlock - proof := results.ProveResult(0) - bz, err := results[0].Marshal() - require.NoError(t, err) - assert.NoError(t, proof.Verify(root, bz)) -} diff --git a/internal/state/test/factory/block.go b/internal/state/test/factory/block.go index 5154d170a..14f49e2d5 100644 --- a/internal/state/test/factory/block.go +++ b/internal/state/test/factory/block.go @@ -42,19 +42,14 @@ func MakeBlocks(ctx context.Context, t *testing.T, n int, state *sm.State, privV return blocks } -func MakeBlock(state sm.State, height int64, c *types.Commit) (*types.Block, error) { - block, _, err := state.MakeBlock( +func MakeBlock(state sm.State, height int64, c *types.Commit) *types.Block { + return state.MakeBlock( height, factory.MakeTenTxs(state.LastBlockHeight), c, nil, state.Validators.GetProposer().Address, ) - if err != nil { - return nil, err - } - - return block, nil } func makeBlockAndPartSet( @@ -82,7 +77,8 @@ func makeBlockAndPartSet( lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()}) } - block, partSet, err := state.MakeBlock(height, []types.Tx{}, lastCommit, nil, state.Validators.GetProposer().Address) + block := state.MakeBlock(height, []types.Tx{}, lastCommit, nil, state.Validators.GetProposer().Address) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) return block, partSet diff --git a/internal/state/validation_test.go b/internal/state/validation_test.go index 74a41fdf9..62d2051cb 100644 --- a/internal/state/validation_test.go +++ b/internal/state/validation_test.go @@ -15,7 +15,7 @@ import ( "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/internal/eventbus" - memmock "github.com/tendermint/tendermint/internal/mempool/mock" + mpmocks "github.com/tendermint/tendermint/internal/mempool/mocks" "github.com/tendermint/tendermint/internal/proxy" sm "github.com/tendermint/tendermint/internal/state" "github.com/tendermint/tendermint/internal/state/mocks" @@ -42,12 +42,24 @@ func TestValidateBlockHeader(t *testing.T) { state, stateDB, privVals := makeState(t, 3, 1) stateStore := sm.NewStore(stateDB) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + blockStore := store.NewBlockStore(dbm.NewMemDB()) blockExec := sm.NewBlockExecutor( stateStore, logger, proxyApp, - memmock.Mempool{}, + mp, sm.EmptyEvidencePool{}, blockStore, eventBus, @@ -98,10 +110,9 @@ func TestValidateBlockHeader(t *testing.T) { Invalid blocks don't pass */ for _, tc := range testCases { - block, err := statefactory.MakeBlock(state, height, lastCommit) - require.NoError(t, err) + block := statefactory.MakeBlock(state, height, lastCommit) tc.malleateBlock(block) - err = blockExec.ValidateBlock(ctx, state, block) + err := blockExec.ValidateBlock(ctx, state, block) t.Logf("%s: %v", tc.name, err) require.Error(t, err, tc.name) } @@ -114,10 +125,9 @@ func TestValidateBlockHeader(t *testing.T) { } nextHeight := validationTestsStopHeight - block, err := statefactory.MakeBlock(state, nextHeight, lastCommit) - require.NoError(t, err) + block := statefactory.MakeBlock(state, nextHeight, lastCommit) state.InitialHeight = nextHeight + 1 - err = blockExec.ValidateBlock(ctx, state, block) + err := blockExec.ValidateBlock(ctx, state, block) require.Error(t, err, "expected an error when state is ahead of block") assert.Contains(t, err.Error(), "lower than initial height") } @@ -135,12 +145,24 @@ func TestValidateBlockCommit(t *testing.T) { state, stateDB, privVals := makeState(t, 1, 1) stateStore := sm.NewStore(stateDB) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) + blockStore := store.NewBlockStore(dbm.NewMemDB()) blockExec := sm.NewBlockExecutor( stateStore, logger, proxyApp, - memmock.Mempool{}, + mp, sm.EmptyEvidencePool{}, blockStore, eventBus, @@ -174,8 +196,7 @@ func TestValidateBlockCommit(t *testing.T) { state.LastBlockID, []types.CommitSig{wrongHeightVote.CommitSig()}, ) - block, err := statefactory.MakeBlock(state, height, wrongHeightCommit) - require.NoError(t, err) + block := statefactory.MakeBlock(state, height, wrongHeightCommit) err = blockExec.ValidateBlock(ctx, state, block) _, isErrInvalidCommitHeight := err.(types.ErrInvalidCommitHeight) require.True(t, isErrInvalidCommitHeight, "expected ErrInvalidCommitHeight at height %d but got: %v", height, err) @@ -183,8 +204,7 @@ func TestValidateBlockCommit(t *testing.T) { /* #2589: test len(block.LastCommit.Signatures) == state.LastValidators.Size() */ - block, err = statefactory.MakeBlock(state, height, wrongSigsCommit) - require.NoError(t, err) + block = statefactory.MakeBlock(state, height, wrongSigsCommit) err = blockExec.ValidateBlock(ctx, state, block) _, isErrInvalidCommitSignatures := err.(types.ErrInvalidCommitSignatures) require.True(t, isErrInvalidCommitSignatures, @@ -274,13 +294,24 @@ func TestValidateBlockEvidence(t *testing.T) { eventBus := eventbus.NewDefault(logger) require.NoError(t, eventBus.Start(ctx)) + mp := &mpmocks.Mempool{} + mp.On("Lock").Return() + mp.On("Unlock").Return() + mp.On("FlushAppConn", mock.Anything).Return(nil) + mp.On("Update", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything).Return(nil) state.ConsensusParams.Evidence.MaxBytes = 1000 blockExec := sm.NewBlockExecutor( stateStore, log.TestingLogger(), proxyApp, - memmock.Mempool{}, + mp, evpool, blockStore, eventBus, @@ -304,10 +335,9 @@ func TestValidateBlockEvidence(t *testing.T) { evidence = append(evidence, newEv) currentBytes += int64(len(newEv.Bytes())) } - block, _, err := state.MakeBlock(height, testfactory.MakeTenTxs(height), lastCommit, evidence, proposerAddr) - require.NoError(t, err) + block := state.MakeBlock(height, testfactory.MakeTenTxs(height), lastCommit, evidence, proposerAddr) - err = blockExec.ValidateBlock(ctx, state, block) + err := blockExec.ValidateBlock(ctx, state, block) if assert.Error(t, err) { _, ok := err.(*types.ErrEvidenceOverflow) require.True(t, ok, "expected error to be of type ErrEvidenceOverflow at height %d but got %v", height, err) diff --git a/internal/store/store_test.go b/internal/store/store_test.go index 8e1ee2db3..82949b103 100644 --- a/internal/store/store_test.go +++ b/internal/store/store_test.go @@ -86,11 +86,8 @@ func TestMain(m *testing.M) { stdlog.Fatal(err) } - block, err = factory.MakeBlock(state, 1, new(types.Commit)) + block = factory.MakeBlock(state, 1, new(types.Commit)) - if err != nil { - stdlog.Fatal(err) - } partSet, err = block.MakePartSet(2) if err != nil { stdlog.Fatal(err) @@ -121,8 +118,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { } // save a block - block, err := factory.MakeBlock(state, bs.Height()+1, new(types.Commit)) - require.NoError(t, err) + block := factory.MakeBlock(state, bs.Height()+1, new(types.Commit)) validPartSet, err := block.MakePartSet(2) require.NoError(t, err) seenCommit := makeTestCommit(10, tmtime.Now()) @@ -326,8 +322,7 @@ func TestLoadBaseMeta(t *testing.T) { bs := NewBlockStore(dbm.NewMemDB()) for h := int64(1); h <= 10; h++ { - block, err := factory.MakeBlock(state, h, new(types.Commit)) - require.NoError(t, err) + block := factory.MakeBlock(state, h, new(types.Commit)) partSet, err := block.MakePartSet(2) require.NoError(t, err) seenCommit := makeTestCommit(h, tmtime.Now()) @@ -394,8 +389,7 @@ func TestPruneBlocks(t *testing.T) { // make more than 1000 blocks, to test batch deletions for h := int64(1); h <= 1500; h++ { - block, err := factory.MakeBlock(state, h, new(types.Commit)) - require.NoError(t, err) + block := factory.MakeBlock(state, h, new(types.Commit)) partSet, err := block.MakePartSet(2) require.NoError(t, err) seenCommit := makeTestCommit(h, tmtime.Now()) @@ -502,8 +496,7 @@ func TestBlockFetchAtHeight(t *testing.T) { defer cleanup() require.NoError(t, err) require.Equal(t, bs.Height(), int64(0), "initially the height should be zero") - block, err := factory.MakeBlock(state, bs.Height()+1, new(types.Commit)) - require.NoError(t, err) + block := factory.MakeBlock(state, bs.Height()+1, new(types.Commit)) partSet, err := block.MakePartSet(2) require.NoError(t, err) @@ -545,8 +538,7 @@ func TestSeenAndCanonicalCommit(t *testing.T) { // are persisted. for h := int64(3); h <= 5; h++ { blockCommit := makeTestCommit(h-1, tmtime.Now()) - block, err := factory.MakeBlock(state, h, blockCommit) - require.NoError(t, err) + block := factory.MakeBlock(state, h, blockCommit) partSet, err := block.MakePartSet(2) require.NoError(t, err) seenCommit := makeTestCommit(h, tmtime.Now()) diff --git a/light/rpc/client.go b/light/rpc/client.go index 54b0a6258..f1c21c994 100644 --- a/light/rpc/client.go +++ b/light/rpc/client.go @@ -458,16 +458,17 @@ func (c *Client) BlockResults(ctx context.Context, height *int64) (*coretypes.Re return nil, err } - // Build a Merkle tree of proto-encoded FinalizeBlock tx results and get a hash. - results := types.NewResults(res.TxsResults) - // Build a Merkle tree out of the slice. - rH := merkle.HashFromByteSlices([][]byte{bbeBytes, results.Hash()}) + rs, err := abci.MarshalTxResults(res.TxsResults) + if err != nil { + return nil, err + } + mh := merkle.HashFromByteSlices(append([][]byte{bbeBytes}, rs...)) // Verify block results. - if !bytes.Equal(rH, trustedBlock.LastResultsHash) { + if !bytes.Equal(mh, trustedBlock.LastResultsHash) { return nil, fmt.Errorf("last results %X does not match with trusted last results %X", - rH, trustedBlock.LastResultsHash) + mh, trustedBlock.LastResultsHash) } return res, nil diff --git a/node/node_test.go b/node/node_test.go index f5b978418..fcd633d71 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -336,7 +336,7 @@ func TestCreateProposalBlock(t *testing.T) { ) commit := types.NewCommit(height-1, 0, types.BlockID{}, nil) - block, _, err := blockExec.CreateProposalBlock( + block, err := blockExec.CreateProposalBlock( ctx, height, state, commit, @@ -415,7 +415,7 @@ func TestMaxTxsProposalBlockSize(t *testing.T) { ) commit := types.NewCommit(height-1, 0, types.BlockID{}, nil) - block, _, err := blockExec.CreateProposalBlock( + block, err := blockExec.CreateProposalBlock( ctx, height, state, commit, @@ -497,10 +497,16 @@ func TestMaxProposalBlockSize(t *testing.T) { }, } + // save the updated validator set for use by the block executor. + state.LastBlockHeight = math.MaxInt64 - 3 + state.LastHeightValidatorsChanged = math.MaxInt64 - 1 + state.NextValidators = state.Validators.Copy() + require.NoError(t, stateStore.Save(state)) + timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) // change state in order to produce the largest accepted header state.LastBlockID = blockID - state.LastBlockHeight = math.MaxInt64 - 1 + state.LastBlockHeight = math.MaxInt64 - 2 state.LastBlockTime = timestamp state.LastResultsHash = tmhash.Sum([]byte("last_results_hash")) state.AppHash = tmhash.Sum([]byte("app_hash")) @@ -530,7 +536,7 @@ func TestMaxProposalBlockSize(t *testing.T) { commit.Signatures = append(commit.Signatures, cs) } - block, partSet, err := blockExec.CreateProposalBlock( + block, err := blockExec.CreateProposalBlock( ctx, math.MaxInt64, state, commit, @@ -538,6 +544,8 @@ func TestMaxProposalBlockSize(t *testing.T) { nil, ) require.NoError(t, err) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) // this ensures that the header is at max size block.Header.Time = timestamp diff --git a/proto/tendermint/abci/types.proto.intermediate b/proto/tendermint/abci/types.proto.intermediate index b84f4c910..d710ed06f 100644 --- a/proto/tendermint/abci/types.proto.intermediate +++ b/proto/tendermint/abci/types.proto.intermediate @@ -8,9 +8,8 @@ import "tendermint/types/params.proto"; import "google/protobuf/timestamp.proto"; import "gogoproto/gogo.proto"; - // This file is a temporary workaround to enable development during the ABCI++ -// project. This file should be deleted and any references to it removed when +// project. This file should be deleted and any references to it removed when // the ongoing work on ABCI++ is completed. // // For the duration of ABCI++, this file should be able to build the `abci/types/types.pb.go` @@ -23,25 +22,25 @@ import "gogoproto/gogo.proto"; message Request { oneof value { - RequestEcho echo = 1; - RequestFlush flush = 2; - RequestInfo info = 3; - RequestInitChain init_chain = 4; - RequestQuery query = 5; - RequestBeginBlock begin_block = 6 [deprecated = true]; - RequestCheckTx check_tx = 7; - RequestDeliverTx deliver_tx = 8 [deprecated = true]; - RequestEndBlock end_block = 9 [deprecated = true]; - RequestCommit commit = 10; - RequestListSnapshots list_snapshots = 11; - RequestOfferSnapshot offer_snapshot = 12; - RequestLoadSnapshotChunk load_snapshot_chunk = 13; - RequestApplySnapshotChunk apply_snapshot_chunk = 14; - RequestPrepareProposal prepare_proposal = 15; - RequestProcessProposal process_proposal = 16; + RequestEcho echo = 1; + RequestFlush flush = 2; + RequestInfo info = 3; + RequestInitChain init_chain = 4; + RequestQuery query = 5; + RequestBeginBlock begin_block = 6 [deprecated = true]; + RequestCheckTx check_tx = 7; + RequestDeliverTx deliver_tx = 8 [deprecated = true]; + RequestEndBlock end_block = 9 [deprecated = true]; + RequestCommit commit = 10; + RequestListSnapshots list_snapshots = 11; + RequestOfferSnapshot offer_snapshot = 12; + RequestLoadSnapshotChunk load_snapshot_chunk = 13; + RequestApplySnapshotChunk apply_snapshot_chunk = 14; + RequestPrepareProposal prepare_proposal = 15; + RequestProcessProposal process_proposal = 16; RequestExtendVote extend_vote = 17; RequestVerifyVoteExtension verify_vote_extension = 18; - RequestFinalizeBlock finalize_block = 19; + RequestFinalizeBlock finalize_block = 19; } } @@ -135,18 +134,17 @@ message RequestVerifyVoteExtension { } message RequestPrepareProposal { - // block_data is an array of transactions that will be included in a block, + bytes hash = 1; + tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; + // txs is an array of transactions that will be included in a block, // sent to the app for possible modifications. - // applications can not exceed the size of the data passed to it. - repeated bytes block_data = 1; - // If an application decides to populate block_data with extra information, they can not exceed this value. - int64 block_data_size = 2; - // votes includes all votes from the previous block. This contains vote extension data that can be used in proposal - // preparation. The votes here will then form the last commit that gets sent in the proposed block. - repeated tendermint.types.Vote votes = 3; + repeated bytes txs = 3; + ExtendedCommitInfo local_last_commit = 4 [(gogoproto.nullable) = false]; + repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false]; + // the modified transactions cannot exceed this size. + int64 max_tx_bytes = 6; } - message RequestProcessProposal { bytes hash = 1; tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; @@ -168,26 +166,26 @@ message RequestFinalizeBlock { message Response { oneof value { - ResponseException exception = 1; - ResponseEcho echo = 2; - ResponseFlush flush = 3; - ResponseInfo info = 4; - ResponseInitChain init_chain = 5; - ResponseQuery query = 6; - ResponseBeginBlock begin_block = 7 [deprecated = true]; - ResponseCheckTx check_tx = 8; - ResponseDeliverTx deliver_tx = 9 [deprecated = true]; - ResponseEndBlock end_block = 10 [deprecated = true]; - ResponseCommit commit = 11; - ResponseListSnapshots list_snapshots = 12; - ResponseOfferSnapshot offer_snapshot = 13; - ResponseLoadSnapshotChunk load_snapshot_chunk = 14; - ResponseApplySnapshotChunk apply_snapshot_chunk = 15; - ResponsePrepareProposal prepare_proposal = 16; - ResponseProcessProposal process_proposal = 17; + ResponseException exception = 1; + ResponseEcho echo = 2; + ResponseFlush flush = 3; + ResponseInfo info = 4; + ResponseInitChain init_chain = 5; + ResponseQuery query = 6; + ResponseBeginBlock begin_block = 7 [deprecated = true]; + ResponseCheckTx check_tx = 8; + ResponseDeliverTx deliver_tx = 9 [deprecated = true]; + ResponseEndBlock end_block = 10 [deprecated = true]; + ResponseCommit commit = 11; + ResponseListSnapshots list_snapshots = 12; + ResponseOfferSnapshot offer_snapshot = 13; + ResponseLoadSnapshotChunk load_snapshot_chunk = 14; + ResponseApplySnapshotChunk apply_snapshot_chunk = 15; + ResponsePrepareProposal prepare_proposal = 16; + ResponseProcessProposal process_proposal = 17; ResponseExtendVote extend_vote = 18; ResponseVerifyVoteExtension verify_vote_extension = 19; - ResponseFinalizeBlock finalize_block = 20; + ResponseFinalizeBlock finalize_block = 20; } } @@ -330,7 +328,12 @@ message ResponseVerifyVoteExtension { } message ResponsePrepareProposal { - repeated bytes block_data = 1; + bool modified_tx = 1; + repeated TxRecord tx_records = 2; + bytes app_hash = 3; + repeated ExecTxResult tx_results = 4; + repeated ValidatorUpdate validator_updates = 5; + tendermint.types.ConsensusParams consensus_param_updates = 6; } message ResponseProcessProposal { @@ -359,6 +362,11 @@ message CommitInfo { repeated VoteInfo votes = 2 [(gogoproto.nullable) = false]; } +message ExtendedCommitInfo { + int32 round = 1; + repeated ExtendedVoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + // Event allows application developers to attach additional information to // ResponseBeginBlock, ResponseEndBlock, ResponseCheckTx and ResponseDeliverTx. // Later, transactions may be queried using these events. @@ -384,7 +392,7 @@ message ExecTxResult { string info = 4; // nondeterministic int64 gas_wanted = 5; int64 gas_used = 6; - repeated Event events = 7 + repeated Event events = 7 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; // nondeterministic string codespace = 8; } @@ -393,12 +401,25 @@ message ExecTxResult { // // One usage is indexing transaction results. message TxResult { - int64 height = 1; - uint32 index = 2; - bytes tx = 3; + int64 height = 1; + uint32 index = 2; + bytes tx = 3; ExecTxResult result = 4 [(gogoproto.nullable) = false]; } +message TxRecord { + TxAction action = 1; + bytes tx = 2; + + // TxAction contains App-provided information on what to do with a transaction that is part of a raw proposal + enum TxAction { + UNKNOWN = 0; // Unknown action + UNMODIFIED = 1; // The Application did not modify this transaction. + ADDED = 2; // The Application added this transaction. + REMOVED = 3; // The Application wants this transaction removed from the proposal and the mempool. + } +} + //---------------------------------------- // Blockchain Types @@ -423,6 +444,12 @@ message VoteInfo { reserved 4; // Placeholder for app_signed_extension in v0.37 } +message ExtendedVoteInfo { + Validator validator = 1 [(gogoproto.nullable) = false]; + bool signed_last_block = 2; + bytes vote_extension = 3; +} + enum EvidenceType { UNKNOWN = 0; DUPLICATE_VOTE = 1; diff --git a/test/e2e/app/app.go b/test/e2e/app/app.go index 098da250e..5739f06e5 100644 --- a/test/e2e/app/app.go +++ b/test/e2e/app/app.go @@ -305,7 +305,8 @@ func (app *Application) ApplySnapshotChunk(req abci.RequestApplySnapshotChunk) a } func (app *Application) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { - return abci.ResponsePrepareProposal{BlockData: req.BlockData} + // None of the transactions are modified by this application. + return abci.ResponsePrepareProposal{ModifiedTx: false} } // ProcessProposal implements part of the Application interface. diff --git a/types/results.go b/types/results.go deleted file mode 100644 index 511364000..000000000 --- a/types/results.go +++ /dev/null @@ -1,54 +0,0 @@ -package types - -import ( - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto/merkle" -) - -// ABCIResults wraps the deliver tx results to return a proof. -type ABCIResults []*abci.ExecTxResult - -// NewResults strips non-deterministic fields from ResponseDeliverTx responses -// and returns ABCIResults. -func NewResults(responses []*abci.ExecTxResult) ABCIResults { - res := make(ABCIResults, len(responses)) - for i, d := range responses { - res[i] = deterministicExecTxResult(d) - } - return res -} - -// Hash returns a merkle hash of all results. -func (a ABCIResults) Hash() []byte { - return merkle.HashFromByteSlices(a.toByteSlices()) -} - -// ProveResult returns a merkle proof of one result from the set -func (a ABCIResults) ProveResult(i int) merkle.Proof { - _, proofs := merkle.ProofsFromByteSlices(a.toByteSlices()) - return *proofs[i] -} - -func (a ABCIResults) toByteSlices() [][]byte { - l := len(a) - bzs := make([][]byte, l) - for i := 0; i < l; i++ { - bz, err := a[i].Marshal() - if err != nil { - panic(err) - } - bzs[i] = bz - } - return bzs -} - -// deterministicExecTxResult strips non-deterministic fields from -// ResponseDeliverTx and returns another ResponseDeliverTx. -func deterministicExecTxResult(response *abci.ExecTxResult) *abci.ExecTxResult { - return &abci.ExecTxResult{ - Code: response.Code, - Data: response.Data, - GasWanted: response.GasWanted, - GasUsed: response.GasUsed, - } -} diff --git a/types/results_test.go b/types/results_test.go deleted file mode 100644 index da7eebed0..000000000 --- a/types/results_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - abci "github.com/tendermint/tendermint/abci/types" -) - -func TestABCIResults(t *testing.T) { - a := &abci.ExecTxResult{Code: 0, Data: nil} - b := &abci.ExecTxResult{Code: 0, Data: []byte{}} - c := &abci.ExecTxResult{Code: 0, Data: []byte("one")} - d := &abci.ExecTxResult{Code: 14, Data: nil} - e := &abci.ExecTxResult{Code: 14, Data: []byte("foo")} - f := &abci.ExecTxResult{Code: 14, Data: []byte("bar")} - - // Nil and []byte{} should produce the same bytes - bzA, err := a.Marshal() - require.NoError(t, err) - bzB, err := b.Marshal() - require.NoError(t, err) - - require.Equal(t, bzA, bzB) - - // a and b should be the same, don't go in results. - results := ABCIResults{a, c, d, e, f} - - // Make sure each result serializes differently - last := []byte{} - assert.Equal(t, last, bzA) // first one is empty - for i, res := range results[1:] { - bz, err := res.Marshal() - require.NoError(t, err) - - assert.NotEqual(t, last, bz, "%d", i) - last = bz - } - - // Make sure that we can get a root hash from results and verify proofs. - root := results.Hash() - assert.NotEmpty(t, root) - - for i, res := range results { - bz, err := res.Marshal() - require.NoError(t, err) - - proof := results.ProveResult(i) - valid := proof.Verify(root, bz) - assert.NoError(t, valid, "%d", i) - } -} diff --git a/types/tx.go b/types/tx.go index 746252238..2dd7d3a51 100644 --- a/types/tx.go +++ b/types/tx.go @@ -5,7 +5,9 @@ import ( "crypto/sha256" "errors" "fmt" + "sort" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/crypto/tmhash" tmbytes "github.com/tendermint/tendermint/libs/bytes" @@ -32,13 +34,8 @@ type Txs []Tx // Hash returns the Merkle root hash of the transaction hashes. // i.e. the leaves of the tree are the hashes of the txs. func (txs Txs) Hash() []byte { - // These allocations will be removed once Txs is switched to [][]byte, - // ref #2603. This is because golang does not allow type casting slices without unsafe - txBzs := make([][]byte, len(txs)) - for i := 0; i < len(txs); i++ { - txBzs[i] = txs[i].Hash() - } - return merkle.HashFromByteSlices(txBzs) + hl := txs.hashList() + return merkle.HashFromByteSlices(hl) } // Index returns the index of this transaction in the list, or -1 if not found @@ -61,16 +58,9 @@ func (txs Txs) IndexByHash(hash []byte) int { return -1 } -// Proof returns a simple merkle proof for this node. -// Panics if i < 0 or i >= len(txs) -// TODO: optimize this! func (txs Txs) Proof(i int) TxProof { - l := len(txs) - bzs := make([][]byte, l) - for i := 0; i < l; i++ { - bzs[i] = txs[i].Hash() - } - root, proofs := merkle.ProofsFromByteSlices(bzs) + hl := txs.hashList() + root, proofs := merkle.ProofsFromByteSlices(hl) return TxProof{ RootHash: root, @@ -79,11 +69,23 @@ func (txs Txs) Proof(i int) TxProof { } } +func (txs Txs) hashList() [][]byte { + hl := make([][]byte, len(txs)) + for i := 0; i < len(txs); i++ { + hl[i] = txs[i].Hash() + } + return hl +} + +// Txs is a slice of transactions. Sorting a Txs value orders the transactions +// lexicographically. +func (txs Txs) Len() int { return len(txs) } +func (txs Txs) Swap(i, j int) { txs[i], txs[j] = txs[j], txs[i] } +func (txs Txs) Less(i, j int) bool { + return bytes.Compare(txs[i], txs[j]) == -1 +} + // ToSliceOfBytes converts a Txs to slice of byte slices. -// -// NOTE: This method should become obsolete once Txs is switched to [][]byte. -// ref: #2603 -// TODO This function is to disappear when TxRecord is introduced func (txs Txs) ToSliceOfBytes() [][]byte { txBzs := make([][]byte, len(txs)) for i := 0; i < len(txs); i++ { @@ -92,14 +94,182 @@ func (txs Txs) ToSliceOfBytes() [][]byte { return txBzs } -// ToTxs converts a raw slice of byte slices into a Txs type. -// TODO This function is to disappear when TxRecord is introduced -func ToTxs(txs [][]byte) Txs { - txBzs := make(Txs, len(txs)) - for i := 0; i < len(txs); i++ { - txBzs[i] = txs[i] +// TxRecordSet contains indexes into an underlying set of transactions. +// These indexes are useful for validating and working with a list of TxRecords +// from the PrepareProposal response. +// +// Only one copy of the original data is referenced by all of the indexes but a +// transaction may appear in multiple indexes. +type TxRecordSet struct { + // all holds the complete list of all transactions from the original list of + // TxRecords. + all Txs + + // included is an index of the transactions that will be included in the block + // and is constructed from the list of both added and unmodified transactions. + // included maintains the original order that the transactions were present + // in the list of TxRecords. + included Txs + + // added, unmodified, removed, and unknown are indexes for each of the actions + // that may be supplied with a transaction. + // + // Because each transaction only has one action, it can be referenced by + // at most 3 indexes in this data structure: the action-specific index, the + // included index, and the all index. + added Txs + unmodified Txs + removed Txs + unknown Txs +} + +// NewTxRecordSet constructs a new set from the given transaction records. +// The contents of the input transactions are shared by the set, and must not +// be modified during the lifetime of the set. +func NewTxRecordSet(trs []*abci.TxRecord) TxRecordSet { + txrSet := TxRecordSet{ + all: make([]Tx, len(trs)), } - return txBzs + for i, tr := range trs { + + txrSet.all[i] = Tx(tr.Tx) + + // The following set of assignments do not allocate new []byte, they create + // pointers to the already allocated slice. + switch tr.GetAction() { + case abci.TxRecord_UNKNOWN: + txrSet.unknown = append(txrSet.unknown, txrSet.all[i]) + case abci.TxRecord_UNMODIFIED: + txrSet.unmodified = append(txrSet.unmodified, txrSet.all[i]) + txrSet.included = append(txrSet.included, txrSet.all[i]) + case abci.TxRecord_ADDED: + txrSet.added = append(txrSet.added, txrSet.all[i]) + txrSet.included = append(txrSet.included, txrSet.all[i]) + case abci.TxRecord_REMOVED: + txrSet.removed = append(txrSet.removed, txrSet.all[i]) + } + } + return txrSet +} + +// IncludedTxs returns the transactions marked for inclusion in a block. This +// list maintains the order that the transactions were included in the list of +// TxRecords that were used to construct the TxRecordSet. +func (t TxRecordSet) IncludedTxs() []Tx { + return t.included +} + +// AddedTxs returns the transactions added by the application. +func (t TxRecordSet) AddedTxs() []Tx { + return t.added +} + +// RemovedTxs returns the transactions marked for removal by the application. +func (t TxRecordSet) RemovedTxs() []Tx { + return t.removed +} + +// Validate checks that the record set was correctly constructed from the original +// list of transactions. +func (t TxRecordSet) Validate(maxSizeBytes int64, otxs Txs) error { + if len(t.unknown) > 0 { + return fmt.Errorf("%d transactions marked unknown (first unknown hash: %x)", len(t.unknown), t.unknown[0].Hash()) + } + + // The following validation logic performs a set of sorts on the data in the TxRecordSet indexes. + // It sorts the original transaction list, otxs, once. + // It sorts the new transaction list twice: once when sorting 'all', the total list, + // and once by sorting the set of the added, removed, and unmodified transactions indexes, + // which, when combined, comprise the complete list of modified transactions. + // + // Each of the added, removed, and unmodified indices is then iterated and once + // and each value index is checked against the sorted original list for containment. + // Asymptotically, this yields a total runtime of O(N*log(N) + 2*M*log(M) + M*log(N)). + // in the input size of the original list, N, and the input size of the new list, M, respectively. + // Performance gains are likely possible, but this was preferred for readability and maintainability. + + // Sort a copy of the complete transaction slice so we can check for + // duplication. The copy is so we do not change the original ordering. + // Only the slices are copied, the transaction contents are shared. + allCopy := sortedCopy(t.all) + + var size int64 + for i, cur := range allCopy { + size += int64(len(cur)) + if size > maxSizeBytes { + return fmt.Errorf("transaction data size %d exceeds maximum %d", size, maxSizeBytes) + } + + // allCopy is sorted, so any duplicated data will be adjacent. + if i+1 < len(allCopy) && bytes.Equal(cur, allCopy[i+1]) { + return fmt.Errorf("found duplicate transaction with hash: %x", cur.Hash()) + } + } + + // create copies of each of the action-specific indexes so that order of the original + // indexes can be preserved. + addedCopy := sortedCopy(t.added) + removedCopy := sortedCopy(t.removed) + unmodifiedCopy := sortedCopy(t.unmodified) + + // make a defensive copy of otxs so that the order of + // the caller's data is not altered. + otxsCopy := sortedCopy(otxs) + + if ix, ok := containsAll(otxsCopy, unmodifiedCopy); !ok { + return fmt.Errorf("new transaction incorrectly marked as removed, transaction hash: %x", unmodifiedCopy[ix].Hash()) + } + + if ix, ok := containsAll(otxsCopy, removedCopy); !ok { + return fmt.Errorf("new transaction incorrectly marked as removed, transaction hash: %x", removedCopy[ix].Hash()) + } + if ix, ok := containsAny(otxsCopy, addedCopy); ok { + return fmt.Errorf("existing transaction incorrectly marked as added, transaction hash: %x", addedCopy[ix].Hash()) + } + return nil +} + +func sortedCopy(txs Txs) Txs { + cp := make(Txs, len(txs)) + copy(cp, txs) + sort.Sort(cp) + return cp +} + +// containsAny checks that list a contains one of the transactions in list +// b. If a match is found, the index in b of the matching transaction is returned. +// Both lists must be sorted. +func containsAny(a, b []Tx) (int, bool) { + for i, cur := range b { + if _, ok := contains(a, cur); ok { + return i, true + } + } + return -1, false +} + +// containsAll checks that super contains all of the transactions in the sub +// list. If not all values in sub are present in super, the index in sub of the +// first Tx absent from super is returned. +func containsAll(super, sub Txs) (int, bool) { + for i, cur := range sub { + if _, ok := contains(super, cur); !ok { + return i, false + } + } + return -1, true +} + +// contains checks that the sorted list, set contains elem. If set does contain elem, then the +// index in set of elem is returned. +func contains(set []Tx, elem Tx) (int, bool) { + n := sort.Search(len(set), func(i int) bool { + return bytes.Compare(elem, set[i]) <= 0 + }) + if n == len(set) || !bytes.Equal(elem, set[n]) { + return -1, false + } + return n, true } // TxProof represents a Merkle proof of the presence of a transaction in the Merkle tree. diff --git a/types/tx_test.go b/types/tx_test.go index e2f12772a..d8737e9f0 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -2,12 +2,13 @@ package types import ( "bytes" - mrand "math/rand" + "math/rand" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" ctest "github.com/tendermint/tendermint/internal/libs/test" tmrand "github.com/tendermint/tendermint/libs/rand" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -21,11 +22,6 @@ func makeTxs(cnt, size int) Txs { return txs } -func randInt(low, high int) int { - off := mrand.Int() % (high - low) - return low + off -} - func TestTxIndex(t *testing.T) { for i := 0; i < 20; i++ { txs := makeTxs(15, 60) @@ -52,6 +48,160 @@ func TestTxIndexByHash(t *testing.T) { } } +func TestValidateTxRecordSet(t *testing.T) { + t.Run("should error on total transaction size exceeding max data size", func(t *testing.T) { + trs := []*abci.TxRecord{ + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{1, 2, 3, 4, 5}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{6, 7, 8, 9, 10}), + }, + } + txrSet := NewTxRecordSet(trs) + err := txrSet.Validate(9, []Tx{}) + require.Error(t, err) + }) + t.Run("should error on duplicate transactions with the same action", func(t *testing.T) { + trs := []*abci.TxRecord{ + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{1, 2, 3, 4, 5}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{100}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{1, 2, 3, 4, 5}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{200}), + }, + } + txrSet := NewTxRecordSet(trs) + err := txrSet.Validate(100, []Tx{}) + require.Error(t, err) + }) + t.Run("should error on duplicate transactions with mixed actions", func(t *testing.T) { + trs := []*abci.TxRecord{ + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{1, 2, 3, 4, 5}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{100}), + }, + { + Action: abci.TxRecord_REMOVED, + Tx: Tx([]byte{1, 2, 3, 4, 5}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{200}), + }, + } + txrSet := NewTxRecordSet(trs) + err := txrSet.Validate(100, []Tx{}) + require.Error(t, err) + }) + t.Run("should error on new transactions marked UNMODIFIED", func(t *testing.T) { + trs := []*abci.TxRecord{ + { + Action: abci.TxRecord_UNMODIFIED, + Tx: Tx([]byte{1, 2, 3, 4, 5}), + }, + } + txrSet := NewTxRecordSet(trs) + err := txrSet.Validate(100, []Tx{}) + require.Error(t, err) + }) + t.Run("should error on new transactions marked REMOVED", func(t *testing.T) { + trs := []*abci.TxRecord{ + { + Action: abci.TxRecord_REMOVED, + Tx: Tx([]byte{1, 2, 3, 4, 5}), + }, + } + txrSet := NewTxRecordSet(trs) + err := txrSet.Validate(100, []Tx{}) + require.Error(t, err) + }) + t.Run("should error on existing transaction marked as ADDED", func(t *testing.T) { + trs := []*abci.TxRecord{ + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{5, 4, 3, 2, 1}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{6}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{1, 2, 3, 4, 5}), + }, + } + txrSet := NewTxRecordSet(trs) + err := txrSet.Validate(100, []Tx{{0}, {1, 2, 3, 4, 5}}) + require.Error(t, err) + }) + t.Run("should error if any transaction marked as UNKNOWN", func(t *testing.T) { + trs := []*abci.TxRecord{ + { + Action: abci.TxRecord_UNKNOWN, + Tx: Tx([]byte{1, 2, 3, 4, 5}), + }, + } + txrSet := NewTxRecordSet(trs) + err := txrSet.Validate(100, []Tx{}) + require.Error(t, err) + }) + t.Run("TxRecordSet preserves order", func(t *testing.T) { + trs := []*abci.TxRecord{ + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{100}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{99}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{55}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{12}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{66}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{9}), + }, + { + Action: abci.TxRecord_ADDED, + Tx: Tx([]byte{17}), + }, + } + txrSet := NewTxRecordSet(trs) + err := txrSet.Validate(100, []Tx{}) + require.NoError(t, err) + for i, tx := range txrSet.IncludedTxs() { + require.Equal(t, Tx(trs[i].Tx), tx) + } + }) +} + func TestValidTxProof(t *testing.T) { cases := []struct { txs Txs @@ -150,3 +300,7 @@ func assertBadProof(t *testing.T, root []byte, bad []byte, good TxProof) { } } } + +func randInt(low, high int) int { + return rand.Intn(high-low) + low +} diff --git a/types/vote_set.go b/types/vote_set.go index bb675e110..438d089b3 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -227,6 +227,9 @@ func (voteSet *VoteSet) getVote(valIndex int32, blockKey string) (vote *Vote, ok } func (voteSet *VoteSet) GetVotes() []*Vote { + if voteSet == nil { + return nil + } return voteSet.votes }