From 055d7adffbb58b676841eb48d436ad3ead0e391d Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 18 Oct 2018 20:03:45 +0400 Subject: [PATCH 01/35] add tm-abci python ABCI server (fork of py-abci) (#2658) It utilises async IO -> greater performance. --- docs/app-dev/ecosystem.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/app-dev/ecosystem.json b/docs/app-dev/ecosystem.json index 67aca2efb..1c2bc2b25 100644 --- a/docs/app-dev/ecosystem.json +++ b/docs/app-dev/ecosystem.json @@ -163,6 +163,12 @@ "language": "Python", "author": "Dave Bryson" }, + { + "name": "tm-abci", + "url": "https://github.com/SoftblocksCo/tm-abci", + "language": "Python", + "author": "Softblocks" + }, { "name": "Spearmint", "url": "https://github.com/dennismckinnon/spearmint", From ed4ce5ff6cc455114d749bd2121096c81098a84f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 18 Oct 2018 16:51:17 -0400 Subject: [PATCH 02/35] ADR-016: Update ABCI Info method for versions (#2662) * abci: update RequestInfo for versions * abci: update ResponseInfo for versions * compile fix * fix test * software_version -> version * comment fix * update spec * add test * comments and fix test --- CHANGELOG_PENDING.md | 3 + abci/example/kvstore/kvstore.go | 9 +- abci/types/types.pb.go | 484 ++++++++++++++++++++------------ abci/types/types.proto | 9 +- consensus/replay.go | 14 +- consensus/replay_test.go | 12 +- consensus/wal_generator.go | 4 +- docs/spec/abci/abci.md | 8 +- node/node.go | 20 +- node/node_test.go | 22 ++ p2p/node_info.go | 17 +- proxy/app_conn_test.go | 2 +- proxy/version.go | 15 + rpc/client/mock/abci.go | 4 +- rpc/core/abci.go | 4 +- state/state.go | 4 + version/version.go | 6 + 17 files changed, 425 insertions(+), 212 deletions(-) create mode 100644 proxy/version.go diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index f4858d953..99c389974 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -21,6 +21,8 @@ BREAKING CHANGES: * [abci] \#2298 ResponseQuery.Proof is now a structured merkle.Proof, not just arbitrary bytes * [abci] \#2644 Add Version to Header and shift all fields by one + * [abci] \#2662 Bump the field numbers for some `ResponseInfo` fields to make room for + `AppVersion` * Go API * [node] Remove node.RunForever @@ -52,6 +54,7 @@ BREAKING CHANGES: FEATURES: - [crypto/merkle] \#2298 General Merkle Proof scheme for chaining various types of Merkle trees together - [abci] \#2557 Add `Codespace` field to `Response{CheckTx, DeliverTx, Query}` +- [abci] \#2662 Add `BlockVersion` and `P2PVersion` to `RequestInfo` IMPROVEMENTS: - Additional Metrics diff --git a/abci/example/kvstore/kvstore.go b/abci/example/kvstore/kvstore.go index 9523bf746..955baefb4 100644 --- a/abci/example/kvstore/kvstore.go +++ b/abci/example/kvstore/kvstore.go @@ -10,11 +10,14 @@ import ( "github.com/tendermint/tendermint/abci/types" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/version" ) var ( stateKey = []byte("stateKey") kvPairPrefixKey = []byte("kvPairKey:") + + ProtocolVersion version.Protocol = 0x1 ) type State struct { @@ -65,7 +68,11 @@ func NewKVStoreApplication() *KVStoreApplication { } func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size)} + return types.ResponseInfo{ + Data: fmt.Sprintf("{\"size\":%v}", app.state.Size), + Version: version.ABCIVersion, + AppVersion: ProtocolVersion.Uint64(), + } } // tx is either "key=value" or just arbitrary bytes diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index 81fb74b42..6a70bb979 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -61,7 +61,7 @@ func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{0} + return fileDescriptor_types_4449c1011851ea19, []int{0} } func (m *Request) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -483,7 +483,7 @@ func (m *RequestEcho) Reset() { *m = RequestEcho{} } func (m *RequestEcho) String() string { return proto.CompactTextString(m) } func (*RequestEcho) ProtoMessage() {} func (*RequestEcho) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{1} + return fileDescriptor_types_4449c1011851ea19, []int{1} } func (m *RequestEcho) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -529,7 +529,7 @@ func (m *RequestFlush) Reset() { *m = RequestFlush{} } func (m *RequestFlush) String() string { return proto.CompactTextString(m) } func (*RequestFlush) ProtoMessage() {} func (*RequestFlush) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{2} + return fileDescriptor_types_4449c1011851ea19, []int{2} } func (m *RequestFlush) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -560,6 +560,8 @@ var xxx_messageInfo_RequestFlush proto.InternalMessageInfo type RequestInfo struct { Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + BlockVersion uint64 `protobuf:"varint,2,opt,name=block_version,json=blockVersion,proto3" json:"block_version,omitempty"` + P2PVersion uint64 `protobuf:"varint,3,opt,name=p2p_version,json=p2pVersion,proto3" json:"p2p_version,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -569,7 +571,7 @@ func (m *RequestInfo) Reset() { *m = RequestInfo{} } func (m *RequestInfo) String() string { return proto.CompactTextString(m) } func (*RequestInfo) ProtoMessage() {} func (*RequestInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{3} + return fileDescriptor_types_4449c1011851ea19, []int{3} } func (m *RequestInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -605,6 +607,20 @@ func (m *RequestInfo) GetVersion() string { return "" } +func (m *RequestInfo) GetBlockVersion() uint64 { + if m != nil { + return m.BlockVersion + } + return 0 +} + +func (m *RequestInfo) GetP2PVersion() uint64 { + if m != nil { + return m.P2PVersion + } + return 0 +} + // nondeterministic type RequestSetOption struct { Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` @@ -618,7 +634,7 @@ func (m *RequestSetOption) Reset() { *m = RequestSetOption{} } func (m *RequestSetOption) String() string { return proto.CompactTextString(m) } func (*RequestSetOption) ProtoMessage() {} func (*RequestSetOption) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{4} + return fileDescriptor_types_4449c1011851ea19, []int{4} } func (m *RequestSetOption) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -676,7 +692,7 @@ func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } func (*RequestInitChain) ProtoMessage() {} func (*RequestInitChain) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{5} + return fileDescriptor_types_4449c1011851ea19, []int{5} } func (m *RequestInitChain) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -754,7 +770,7 @@ func (m *RequestQuery) Reset() { *m = RequestQuery{} } func (m *RequestQuery) String() string { return proto.CompactTextString(m) } func (*RequestQuery) ProtoMessage() {} func (*RequestQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{6} + return fileDescriptor_types_4449c1011851ea19, []int{6} } func (m *RequestQuery) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -826,7 +842,7 @@ func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } func (*RequestBeginBlock) ProtoMessage() {} func (*RequestBeginBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{7} + return fileDescriptor_types_4449c1011851ea19, []int{7} } func (m *RequestBeginBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -894,7 +910,7 @@ func (m *RequestCheckTx) Reset() { *m = RequestCheckTx{} } func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) } func (*RequestCheckTx) ProtoMessage() {} func (*RequestCheckTx) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{8} + return fileDescriptor_types_4449c1011851ea19, []int{8} } func (m *RequestCheckTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -941,7 +957,7 @@ func (m *RequestDeliverTx) Reset() { *m = RequestDeliverTx{} } func (m *RequestDeliverTx) String() string { return proto.CompactTextString(m) } func (*RequestDeliverTx) ProtoMessage() {} func (*RequestDeliverTx) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{9} + return fileDescriptor_types_4449c1011851ea19, []int{9} } func (m *RequestDeliverTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -988,7 +1004,7 @@ func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) } func (*RequestEndBlock) ProtoMessage() {} func (*RequestEndBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{10} + return fileDescriptor_types_4449c1011851ea19, []int{10} } func (m *RequestEndBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1034,7 +1050,7 @@ func (m *RequestCommit) Reset() { *m = RequestCommit{} } func (m *RequestCommit) String() string { return proto.CompactTextString(m) } func (*RequestCommit) ProtoMessage() {} func (*RequestCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{11} + return fileDescriptor_types_4449c1011851ea19, []int{11} } func (m *RequestCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1087,7 +1103,7 @@ func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{12} + return fileDescriptor_types_4449c1011851ea19, []int{12} } func (m *Response) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1540,7 +1556,7 @@ func (m *ResponseException) Reset() { *m = ResponseException{} } func (m *ResponseException) String() string { return proto.CompactTextString(m) } func (*ResponseException) ProtoMessage() {} func (*ResponseException) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{13} + return fileDescriptor_types_4449c1011851ea19, []int{13} } func (m *ResponseException) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1587,7 +1603,7 @@ func (m *ResponseEcho) Reset() { *m = ResponseEcho{} } func (m *ResponseEcho) String() string { return proto.CompactTextString(m) } func (*ResponseEcho) ProtoMessage() {} func (*ResponseEcho) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{14} + return fileDescriptor_types_4449c1011851ea19, []int{14} } func (m *ResponseEcho) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1633,7 +1649,7 @@ func (m *ResponseFlush) Reset() { *m = ResponseFlush{} } func (m *ResponseFlush) String() string { return proto.CompactTextString(m) } func (*ResponseFlush) ProtoMessage() {} func (*ResponseFlush) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{15} + return fileDescriptor_types_4449c1011851ea19, []int{15} } func (m *ResponseFlush) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1665,8 +1681,9 @@ var xxx_messageInfo_ResponseFlush proto.InternalMessageInfo type ResponseInfo struct { Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - LastBlockHeight int64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` - LastBlockAppHash []byte `protobuf:"bytes,4,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"` + AppVersion uint64 `protobuf:"varint,3,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` + LastBlockHeight int64 `protobuf:"varint,4,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` + LastBlockAppHash []byte `protobuf:"bytes,5,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1676,7 +1693,7 @@ func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } func (m *ResponseInfo) String() string { return proto.CompactTextString(m) } func (*ResponseInfo) ProtoMessage() {} func (*ResponseInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{16} + return fileDescriptor_types_4449c1011851ea19, []int{16} } func (m *ResponseInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1719,6 +1736,13 @@ func (m *ResponseInfo) GetVersion() string { return "" } +func (m *ResponseInfo) GetAppVersion() uint64 { + if m != nil { + return m.AppVersion + } + return 0 +} + func (m *ResponseInfo) GetLastBlockHeight() int64 { if m != nil { return m.LastBlockHeight @@ -1748,7 +1772,7 @@ func (m *ResponseSetOption) Reset() { *m = ResponseSetOption{} } func (m *ResponseSetOption) String() string { return proto.CompactTextString(m) } func (*ResponseSetOption) ProtoMessage() {} func (*ResponseSetOption) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{17} + return fileDescriptor_types_4449c1011851ea19, []int{17} } func (m *ResponseSetOption) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1810,7 +1834,7 @@ func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } func (*ResponseInitChain) ProtoMessage() {} func (*ResponseInitChain) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{18} + return fileDescriptor_types_4449c1011851ea19, []int{18} } func (m *ResponseInitChain) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1873,7 +1897,7 @@ func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } func (*ResponseQuery) ProtoMessage() {} func (*ResponseQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{19} + return fileDescriptor_types_4449c1011851ea19, []int{19} } func (m *ResponseQuery) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1976,7 +2000,7 @@ func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } func (*ResponseBeginBlock) ProtoMessage() {} func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{20} + return fileDescriptor_types_4449c1011851ea19, []int{20} } func (m *ResponseBeginBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2030,7 +2054,7 @@ func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } func (*ResponseCheckTx) ProtoMessage() {} func (*ResponseCheckTx) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{21} + return fileDescriptor_types_4449c1011851ea19, []int{21} } func (m *ResponseCheckTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2133,7 +2157,7 @@ func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } func (*ResponseDeliverTx) ProtoMessage() {} func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{22} + return fileDescriptor_types_4449c1011851ea19, []int{22} } func (m *ResponseDeliverTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2231,7 +2255,7 @@ func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } func (*ResponseEndBlock) ProtoMessage() {} func (*ResponseEndBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{23} + return fileDescriptor_types_4449c1011851ea19, []int{23} } func (m *ResponseEndBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2293,7 +2317,7 @@ func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } func (*ResponseCommit) ProtoMessage() {} func (*ResponseCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{24} + return fileDescriptor_types_4449c1011851ea19, []int{24} } func (m *ResponseCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2343,7 +2367,7 @@ func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } func (m *ConsensusParams) String() string { return proto.CompactTextString(m) } func (*ConsensusParams) ProtoMessage() {} func (*ConsensusParams) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{25} + return fileDescriptor_types_4449c1011851ea19, []int{25} } func (m *ConsensusParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2401,7 +2425,7 @@ func (m *BlockSize) Reset() { *m = BlockSize{} } func (m *BlockSize) String() string { return proto.CompactTextString(m) } func (*BlockSize) ProtoMessage() {} func (*BlockSize) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{26} + return fileDescriptor_types_4449c1011851ea19, []int{26} } func (m *BlockSize) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2457,7 +2481,7 @@ func (m *EvidenceParams) Reset() { *m = EvidenceParams{} } func (m *EvidenceParams) String() string { return proto.CompactTextString(m) } func (*EvidenceParams) ProtoMessage() {} func (*EvidenceParams) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{27} + return fileDescriptor_types_4449c1011851ea19, []int{27} } func (m *EvidenceParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2505,7 +2529,7 @@ func (m *LastCommitInfo) Reset() { *m = LastCommitInfo{} } func (m *LastCommitInfo) String() string { return proto.CompactTextString(m) } func (*LastCommitInfo) ProtoMessage() {} func (*LastCommitInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{28} + return fileDescriptor_types_4449c1011851ea19, []int{28} } func (m *LastCommitInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2579,7 +2603,7 @@ func (m *Header) Reset() { *m = Header{} } func (m *Header) String() string { return proto.CompactTextString(m) } func (*Header) ProtoMessage() {} func (*Header) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{29} + return fileDescriptor_types_4449c1011851ea19, []int{29} } func (m *Header) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2732,7 +2756,7 @@ func (m *Version) Reset() { *m = Version{} } func (m *Version) String() string { return proto.CompactTextString(m) } func (*Version) ProtoMessage() {} func (*Version) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{30} + return fileDescriptor_types_4449c1011851ea19, []int{30} } func (m *Version) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2787,7 +2811,7 @@ func (m *BlockID) Reset() { *m = BlockID{} } func (m *BlockID) String() string { return proto.CompactTextString(m) } func (*BlockID) ProtoMessage() {} func (*BlockID) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{31} + return fileDescriptor_types_4449c1011851ea19, []int{31} } func (m *BlockID) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2842,7 +2866,7 @@ func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } func (*PartSetHeader) ProtoMessage() {} func (*PartSetHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{32} + return fileDescriptor_types_4449c1011851ea19, []int{32} } func (m *PartSetHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2899,7 +2923,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_types_07d64ea985a686e2, []int{33} + return fileDescriptor_types_4449c1011851ea19, []int{33} } func (m *Validator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2955,7 +2979,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_types_07d64ea985a686e2, []int{34} + return fileDescriptor_types_4449c1011851ea19, []int{34} } func (m *ValidatorUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3011,7 +3035,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_types_07d64ea985a686e2, []int{35} + return fileDescriptor_types_4449c1011851ea19, []int{35} } func (m *VoteInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3066,7 +3090,7 @@ func (m *PubKey) Reset() { *m = PubKey{} } func (m *PubKey) String() string { return proto.CompactTextString(m) } func (*PubKey) ProtoMessage() {} func (*PubKey) Descriptor() ([]byte, []int) { - return fileDescriptor_types_07d64ea985a686e2, []int{36} + return fileDescriptor_types_4449c1011851ea19, []int{36} } func (m *PubKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3124,7 +3148,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_types_07d64ea985a686e2, []int{37} + return fileDescriptor_types_4449c1011851ea19, []int{37} } func (m *Evidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3636,6 +3660,12 @@ func (this *RequestInfo) Equal(that interface{}) bool { if this.Version != that1.Version { return false } + if this.BlockVersion != that1.BlockVersion { + return false + } + if this.P2PVersion != that1.P2PVersion { + return false + } if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { return false } @@ -4321,6 +4351,9 @@ func (this *ResponseInfo) Equal(that interface{}) bool { if this.Version != that1.Version { return false } + if this.AppVersion != that1.AppVersion { + return false + } if this.LastBlockHeight != that1.LastBlockHeight { return false } @@ -5758,6 +5791,16 @@ func (m *RequestInfo) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintTypes(dAtA, i, uint64(len(m.Version))) i += copy(dAtA[i:], m.Version) } + if m.BlockVersion != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.BlockVersion)) + } + if m.P2PVersion != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.P2PVersion)) + } if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } @@ -6362,13 +6405,18 @@ func (m *ResponseInfo) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintTypes(dAtA, i, uint64(len(m.Version))) i += copy(dAtA[i:], m.Version) } - if m.LastBlockHeight != 0 { + if m.AppVersion != 0 { dAtA[i] = 0x18 i++ + i = encodeVarintTypes(dAtA, i, uint64(m.AppVersion)) + } + if m.LastBlockHeight != 0 { + dAtA[i] = 0x20 + i++ i = encodeVarintTypes(dAtA, i, uint64(m.LastBlockHeight)) } if len(m.LastBlockAppHash) > 0 { - dAtA[i] = 0x22 + dAtA[i] = 0x2a i++ i = encodeVarintTypes(dAtA, i, uint64(len(m.LastBlockAppHash))) i += copy(dAtA[i:], m.LastBlockAppHash) @@ -7459,8 +7507,10 @@ func NewPopulatedRequestFlush(r randyTypes, easy bool) *RequestFlush { func NewPopulatedRequestInfo(r randyTypes, easy bool) *RequestInfo { this := &RequestInfo{} this.Version = string(randStringTypes(r)) + this.BlockVersion = uint64(uint64(r.Uint32())) + this.P2PVersion = uint64(uint64(r.Uint32())) if !easy && r.Intn(10) != 0 { - this.XXX_unrecognized = randUnrecognizedTypes(r, 2) + this.XXX_unrecognized = randUnrecognizedTypes(r, 4) } return this } @@ -7717,6 +7767,7 @@ func NewPopulatedResponseInfo(r randyTypes, easy bool) *ResponseInfo { this := &ResponseInfo{} this.Data = string(randStringTypes(r)) this.Version = string(randStringTypes(r)) + this.AppVersion = uint64(uint64(r.Uint32())) this.LastBlockHeight = int64(r.Int63()) if r.Intn(2) == 0 { this.LastBlockHeight *= -1 @@ -7727,7 +7778,7 @@ func NewPopulatedResponseInfo(r randyTypes, easy bool) *ResponseInfo { this.LastBlockAppHash[i] = byte(r.Intn(256)) } if !easy && r.Intn(10) != 0 { - this.XXX_unrecognized = randUnrecognizedTypes(r, 5) + this.XXX_unrecognized = randUnrecognizedTypes(r, 6) } return this } @@ -8382,6 +8433,12 @@ func (m *RequestInfo) Size() (n int) { if l > 0 { n += 1 + l + sovTypes(uint64(l)) } + if m.BlockVersion != 0 { + n += 1 + sovTypes(uint64(m.BlockVersion)) + } + if m.P2PVersion != 0 { + n += 1 + sovTypes(uint64(m.P2PVersion)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -8693,6 +8750,9 @@ func (m *ResponseInfo) Size() (n int) { if l > 0 { n += 1 + l + sovTypes(uint64(l)) } + if m.AppVersion != 0 { + n += 1 + sovTypes(uint64(m.AppVersion)) + } if m.LastBlockHeight != 0 { n += 1 + sovTypes(uint64(m.LastBlockHeight)) } @@ -9781,6 +9841,44 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { } m.Version = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockVersion", wireType) + } + m.BlockVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockVersion |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field P2PVersion", wireType) + } + m.P2PVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.P2PVersion |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -11459,6 +11557,25 @@ func (m *ResponseInfo) Unmarshal(dAtA []byte) error { m.Version = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AppVersion", wireType) + } + m.AppVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.AppVersion |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field LastBlockHeight", wireType) } @@ -11477,7 +11594,7 @@ func (m *ResponseInfo) Unmarshal(dAtA []byte) error { break } } - case 4: + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field LastBlockAppHash", wireType) } @@ -14768,145 +14885,148 @@ var ( ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") ) -func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_07d64ea985a686e2) } +func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_4449c1011851ea19) } func init() { - golang_proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_07d64ea985a686e2) + golang_proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_4449c1011851ea19) } -var fileDescriptor_types_07d64ea985a686e2 = []byte{ - // 2133 bytes of a gzipped FileDescriptorProto +var fileDescriptor_types_4449c1011851ea19 = []byte{ + // 2177 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0xcd, 0x93, 0x1b, 0x47, - 0x15, 0xdf, 0xd1, 0x6a, 0x25, 0xcd, 0xdb, 0x5d, 0x49, 0x6e, 0x7f, 0xc9, 0x22, 0xac, 0x5d, 0x13, - 0x48, 0xbc, 0xc4, 0xd1, 0x06, 0x87, 0x50, 0xeb, 0x38, 0xa4, 0x6a, 0x65, 0x1b, 0x76, 0x2b, 0x01, - 0x96, 0xf1, 0x07, 0x17, 0xaa, 0xa6, 0x5a, 0x9a, 0xb6, 0x34, 0x65, 0x69, 0x66, 0x32, 0xd3, 0xda, - 0x68, 0x7d, 0xcc, 0x39, 0x87, 0x1c, 0xa8, 0xe2, 0x5f, 0xe0, 0x4f, 0xe0, 0xc8, 0x89, 0xca, 0x91, - 0x03, 0x67, 0x03, 0x4b, 0x71, 0x80, 0x2b, 0x45, 0x15, 0x47, 0xea, 0xbd, 0xee, 0xf9, 0xdc, 0x91, - 0x89, 0x03, 0x27, 0x2e, 0xd2, 0xf4, 0xfb, 0xe8, 0x8f, 0xd7, 0xef, 0xbd, 0xdf, 0x7b, 0x0d, 0x57, - 0xf8, 0x68, 0xec, 0xed, 0xc9, 0xd3, 0x50, 0xc4, 0xea, 0x77, 0x10, 0x46, 0x81, 0x0c, 0xd8, 0x06, - 0x0d, 0xfa, 0x6f, 0x4f, 0x3c, 0x39, 0x5d, 0x8c, 0x06, 0xe3, 0x60, 0xbe, 0x37, 0x09, 0x26, 0xc1, - 0x1e, 0x71, 0x47, 0x8b, 0xa7, 0x34, 0xa2, 0x01, 0x7d, 0x29, 0xad, 0xfe, 0xf5, 0x49, 0x10, 0x4c, - 0x66, 0x22, 0x93, 0x92, 0xde, 0x5c, 0xc4, 0x92, 0xcf, 0x43, 0x2d, 0xb0, 0x9f, 0x9b, 0x4f, 0x0a, - 0xdf, 0x15, 0xd1, 0xdc, 0xf3, 0x65, 0xfe, 0x73, 0xe6, 0x8d, 0xe2, 0xbd, 0x71, 0x30, 0x9f, 0x07, - 0x7e, 0x7e, 0x43, 0xfd, 0xbb, 0xff, 0x51, 0x73, 0x1c, 0x9d, 0x86, 0x32, 0xd8, 0x9b, 0x8b, 0xe8, - 0xd9, 0x4c, 0xe8, 0x3f, 0xa5, 0x6c, 0xfd, 0xae, 0x0e, 0x4d, 0x5b, 0x7c, 0xb2, 0x10, 0xb1, 0x64, - 0x37, 0xa1, 0x2e, 0xc6, 0xd3, 0xa0, 0x57, 0xbb, 0x61, 0xdc, 0xdc, 0xbc, 0xcd, 0x06, 0x6a, 0x11, - 0xcd, 0x7d, 0x30, 0x9e, 0x06, 0x87, 0x6b, 0x36, 0x49, 0xb0, 0xb7, 0x60, 0xe3, 0xe9, 0x6c, 0x11, - 0x4f, 0x7b, 0xeb, 0x24, 0x7a, 0xb1, 0x28, 0xfa, 0x43, 0x64, 0x1d, 0xae, 0xd9, 0x4a, 0x06, 0xa7, - 0xf5, 0xfc, 0xa7, 0x41, 0xaf, 0x5e, 0x35, 0xed, 0x91, 0xff, 0x94, 0xa6, 0x45, 0x09, 0xb6, 0x0f, - 0x10, 0x0b, 0xe9, 0x04, 0xa1, 0xf4, 0x02, 0xbf, 0xb7, 0x41, 0xf2, 0x57, 0x8b, 0xf2, 0x0f, 0x85, - 0xfc, 0x29, 0xb1, 0x0f, 0xd7, 0x6c, 0x33, 0x4e, 0x06, 0xa8, 0xe9, 0xf9, 0x9e, 0x74, 0xc6, 0x53, - 0xee, 0xf9, 0xbd, 0x46, 0x95, 0xe6, 0x91, 0xef, 0xc9, 0x7b, 0xc8, 0x46, 0x4d, 0x2f, 0x19, 0xe0, - 0x51, 0x3e, 0x59, 0x88, 0xe8, 0xb4, 0xd7, 0xac, 0x3a, 0xca, 0xcf, 0x90, 0x85, 0x47, 0x21, 0x19, - 0x76, 0x17, 0x36, 0x47, 0x62, 0xe2, 0xf9, 0xce, 0x68, 0x16, 0x8c, 0x9f, 0xf5, 0x5a, 0xa4, 0xd2, - 0x2b, 0xaa, 0x0c, 0x51, 0x60, 0x88, 0xfc, 0xc3, 0x35, 0x1b, 0x46, 0xe9, 0x88, 0xdd, 0x86, 0xd6, - 0x78, 0x2a, 0xc6, 0xcf, 0x1c, 0xb9, 0xec, 0x99, 0xa4, 0x79, 0xb9, 0xa8, 0x79, 0x0f, 0xb9, 0x8f, - 0x96, 0x87, 0x6b, 0x76, 0x73, 0xac, 0x3e, 0xd9, 0x7b, 0x60, 0x0a, 0xdf, 0xd5, 0xcb, 0x6d, 0x92, - 0xd2, 0x95, 0xd2, 0xbd, 0xf8, 0x6e, 0xb2, 0x58, 0x4b, 0xe8, 0x6f, 0x36, 0x80, 0x06, 0x3a, 0x8a, - 0x27, 0x7b, 0x5b, 0xa4, 0x73, 0xa9, 0xb4, 0x10, 0xf1, 0x0e, 0xd7, 0x6c, 0x2d, 0x85, 0xe6, 0x73, - 0xc5, 0xcc, 0x3b, 0x11, 0x11, 0x6e, 0xee, 0x62, 0x95, 0xf9, 0xee, 0x2b, 0x3e, 0x6d, 0xcf, 0x74, - 0x93, 0xc1, 0xb0, 0x09, 0x1b, 0x27, 0x7c, 0xb6, 0x10, 0xd6, 0x9b, 0xb0, 0x99, 0xf3, 0x14, 0xd6, - 0x83, 0xe6, 0x5c, 0xc4, 0x31, 0x9f, 0x88, 0x9e, 0x71, 0xc3, 0xb8, 0x69, 0xda, 0xc9, 0xd0, 0x6a, - 0xc3, 0x56, 0xde, 0x4f, 0x72, 0x8a, 0xe8, 0x0b, 0xa8, 0x78, 0x22, 0xa2, 0x18, 0x1d, 0x40, 0x2b, - 0xea, 0xa1, 0xf5, 0x3e, 0x74, 0xcb, 0x4e, 0xc0, 0xba, 0xb0, 0xfe, 0x4c, 0x9c, 0x6a, 0x49, 0xfc, - 0x64, 0x97, 0xf4, 0x86, 0xc8, 0x8b, 0x4d, 0x5b, 0xef, 0xee, 0x8b, 0x5a, 0xaa, 0x9c, 0xfa, 0x01, - 0xdb, 0x87, 0x3a, 0x46, 0x21, 0x69, 0x6f, 0xde, 0xee, 0x0f, 0x54, 0x88, 0x0e, 0x92, 0x10, 0x1d, - 0x3c, 0x4a, 0x42, 0x74, 0xd8, 0xfa, 0xf2, 0xc5, 0xf5, 0xb5, 0x2f, 0xfe, 0x78, 0xdd, 0xb0, 0x49, - 0x83, 0x5d, 0xc3, 0xab, 0xe4, 0x9e, 0xef, 0x78, 0xae, 0x5e, 0xa7, 0x49, 0xe3, 0x23, 0x97, 0x1d, - 0x40, 0x77, 0x1c, 0xf8, 0xb1, 0xf0, 0xe3, 0x45, 0xec, 0x84, 0x3c, 0xe2, 0xf3, 0x58, 0x47, 0x49, - 0x72, 0x71, 0xf7, 0x12, 0xf6, 0x31, 0x71, 0xed, 0xce, 0xb8, 0x48, 0x60, 0x1f, 0x00, 0x9c, 0xf0, - 0x99, 0xe7, 0x72, 0x19, 0x44, 0x71, 0xaf, 0x7e, 0x63, 0x3d, 0xa7, 0xfc, 0x24, 0x61, 0x3c, 0x0e, - 0x5d, 0x2e, 0xc5, 0xb0, 0x8e, 0x3b, 0xb3, 0x73, 0xf2, 0xec, 0x0d, 0xe8, 0xf0, 0x30, 0x74, 0x62, - 0xc9, 0xa5, 0x70, 0x46, 0xa7, 0x52, 0xc4, 0x14, 0x49, 0x5b, 0xf6, 0x36, 0x0f, 0xc3, 0x87, 0x48, - 0x1d, 0x22, 0xd1, 0x72, 0xd3, 0x7b, 0x20, 0x27, 0x67, 0x0c, 0xea, 0x2e, 0x97, 0x9c, 0xac, 0xb1, - 0x65, 0xd3, 0x37, 0xd2, 0x42, 0x2e, 0xa7, 0xfa, 0x8c, 0xf4, 0xcd, 0xae, 0x40, 0x63, 0x2a, 0xbc, - 0xc9, 0x54, 0xd2, 0xb1, 0xd6, 0x6d, 0x3d, 0x42, 0xc3, 0x87, 0x51, 0x70, 0x22, 0x28, 0xce, 0x5b, - 0xb6, 0x1a, 0x58, 0x7f, 0x35, 0xe0, 0xc2, 0xb9, 0xc0, 0xc0, 0x79, 0xa7, 0x3c, 0x9e, 0x26, 0x6b, - 0xe1, 0x37, 0x7b, 0x0b, 0xe7, 0xe5, 0xae, 0x88, 0x74, 0xfe, 0xd9, 0xd6, 0x27, 0x3e, 0x24, 0xa2, - 0x3e, 0xa8, 0x16, 0x61, 0x0f, 0xa0, 0x3b, 0xe3, 0xb1, 0x74, 0x94, 0xff, 0x3a, 0x94, 0x5f, 0xd6, - 0x0b, 0x31, 0xf5, 0x31, 0x4f, 0xfc, 0x1c, 0xdd, 0x4a, 0xab, 0xb7, 0x67, 0x05, 0x2a, 0x3b, 0x84, - 0x4b, 0xa3, 0xd3, 0xe7, 0xdc, 0x97, 0x9e, 0x2f, 0x9c, 0x73, 0x36, 0xef, 0xe8, 0xa9, 0x1e, 0x9c, - 0x78, 0xae, 0xf0, 0xc7, 0x89, 0xb1, 0x2f, 0xa6, 0x2a, 0xe9, 0x65, 0xc4, 0xd6, 0x0d, 0x68, 0x17, - 0xa3, 0x98, 0xb5, 0xa1, 0x26, 0x97, 0xfa, 0x84, 0x35, 0xb9, 0xb4, 0xac, 0xd4, 0x03, 0xd3, 0x50, - 0x3a, 0x27, 0xb3, 0x0b, 0x9d, 0x52, 0x58, 0xe7, 0xcc, 0x6d, 0xe4, 0xcd, 0x6d, 0x75, 0x60, 0xbb, - 0x10, 0xcd, 0xd6, 0xe7, 0x1b, 0xd0, 0xb2, 0x45, 0x1c, 0xa2, 0x33, 0xb1, 0x7d, 0x30, 0xc5, 0x72, - 0x2c, 0x54, 0x22, 0x35, 0x4a, 0x69, 0x4a, 0xc9, 0x3c, 0x48, 0xf8, 0x18, 0xd0, 0xa9, 0x30, 0xdb, - 0x2d, 0x80, 0xc0, 0xc5, 0xb2, 0x52, 0x1e, 0x05, 0x6e, 0x15, 0x51, 0xe0, 0x52, 0x49, 0xb6, 0x04, - 0x03, 0xbb, 0x05, 0x18, 0x28, 0x4f, 0x5c, 0xc0, 0x81, 0x3b, 0x15, 0x38, 0x50, 0xde, 0xfe, 0x0a, - 0x20, 0xb8, 0x53, 0x01, 0x04, 0xbd, 0x73, 0x6b, 0x55, 0x22, 0xc1, 0xad, 0x22, 0x12, 0x94, 0x8f, - 0x53, 0x82, 0x82, 0x0f, 0xaa, 0xa0, 0xe0, 0x5a, 0x49, 0x67, 0x25, 0x16, 0xbc, 0x7b, 0x0e, 0x0b, - 0xae, 0x94, 0x54, 0x2b, 0xc0, 0xe0, 0x4e, 0x21, 0x4b, 0x43, 0xe5, 0xd9, 0xaa, 0xd3, 0x34, 0xfb, - 0xfe, 0x79, 0x1c, 0xb9, 0x5a, 0xbe, 0xda, 0x2a, 0x20, 0xd9, 0x2b, 0x01, 0xc9, 0xe5, 0xf2, 0x2e, - 0x4b, 0x48, 0x92, 0xe1, 0xc1, 0x2e, 0xc6, 0x7d, 0xc9, 0xd3, 0x30, 0x47, 0x88, 0x28, 0x0a, 0x22, - 0x9d, 0xb0, 0xd5, 0xc0, 0xba, 0x89, 0x99, 0x28, 0xf3, 0xaf, 0x97, 0x60, 0x07, 0x39, 0x7d, 0xce, - 0xbb, 0xac, 0x5f, 0x19, 0x99, 0x2e, 0x45, 0x74, 0x3e, 0x8b, 0x99, 0x3a, 0x8b, 0xe5, 0x20, 0xa5, - 0x56, 0x80, 0x14, 0xf6, 0x1d, 0xb8, 0x40, 0x69, 0x84, 0xec, 0xe2, 0x14, 0xd2, 0x5a, 0x07, 0x19, - 0xca, 0x20, 0x2a, 0xbf, 0xbd, 0x0d, 0x17, 0x73, 0xb2, 0x98, 0x62, 0x29, 0x85, 0xd5, 0x29, 0x78, - 0xbb, 0xa9, 0xf4, 0x41, 0x18, 0x1e, 0xf2, 0x78, 0x6a, 0xfd, 0x38, 0x3b, 0x7f, 0x06, 0x57, 0x0c, - 0xea, 0xe3, 0xc0, 0x55, 0xc7, 0xda, 0xb6, 0xe9, 0x1b, 0x21, 0x6c, 0x16, 0x4c, 0x68, 0x55, 0xd3, - 0xc6, 0x4f, 0x94, 0x4a, 0x23, 0xc5, 0x54, 0x21, 0x61, 0xfd, 0xd2, 0xc8, 0xe6, 0xcb, 0x10, 0xac, - 0x0a, 0x6c, 0x8c, 0xff, 0x06, 0x6c, 0x6a, 0xaf, 0x06, 0x36, 0xd6, 0x99, 0x91, 0xdd, 0x48, 0x0a, - 0x23, 0x5f, 0xef, 0x88, 0xe8, 0x1c, 0x9e, 0xef, 0x8a, 0x25, 0x05, 0xfc, 0xba, 0xad, 0x06, 0x09, - 0xc2, 0x37, 0xc8, 0xcc, 0x45, 0x84, 0x6f, 0x12, 0x4d, 0x0d, 0xd8, 0xeb, 0x04, 0x3f, 0xc1, 0x53, - 0x1d, 0x89, 0xdb, 0x03, 0x5d, 0xe6, 0x1e, 0x23, 0xd1, 0x56, 0xbc, 0x5c, 0x32, 0x35, 0x0b, 0xd8, - 0xf5, 0x1a, 0x98, 0xb8, 0xd1, 0x38, 0xe4, 0x63, 0x41, 0x81, 0x65, 0xda, 0x19, 0xc1, 0x3a, 0x06, - 0x76, 0x3e, 0xa0, 0xd9, 0xfb, 0x50, 0x97, 0x7c, 0x82, 0xf6, 0x46, 0x93, 0xb5, 0x07, 0xaa, 0x32, - 0x1f, 0x7c, 0xf4, 0xe4, 0x98, 0x7b, 0xd1, 0xf0, 0x0a, 0x9a, 0xea, 0xef, 0x2f, 0xae, 0xb7, 0x51, - 0xe6, 0x56, 0x30, 0xf7, 0xa4, 0x98, 0x87, 0xf2, 0xd4, 0x26, 0x1d, 0xeb, 0x1f, 0x06, 0x26, 0xfa, - 0x42, 0xa0, 0x57, 0x1a, 0x2e, 0xf1, 0xe6, 0x5a, 0x0e, 0x93, 0xbf, 0x9a, 0x31, 0xbf, 0x09, 0x30, - 0xe1, 0xb1, 0xf3, 0x29, 0xf7, 0xa5, 0x70, 0xb5, 0x45, 0xcd, 0x09, 0x8f, 0x7f, 0x4e, 0x04, 0x2c, - 0x60, 0x90, 0xbd, 0x88, 0x85, 0x4b, 0xa6, 0x5d, 0xb7, 0x9b, 0x13, 0x1e, 0x3f, 0x8e, 0x85, 0x9b, - 0x9e, 0xab, 0xf9, 0xea, 0xe7, 0x2a, 0xda, 0xb1, 0x55, 0xb6, 0xe3, 0x3f, 0x73, 0x3e, 0x9c, 0x61, - 0xe0, 0xff, 0xff, 0xb9, 0xff, 0x66, 0x20, 0xf4, 0x17, 0xb3, 0x2c, 0x3b, 0x82, 0x0b, 0x69, 0x1c, - 0x39, 0x0b, 0x8a, 0xaf, 0xc4, 0x97, 0x5e, 0x1e, 0x7e, 0xdd, 0x93, 0x22, 0x39, 0x66, 0x3f, 0x81, - 0xab, 0xa5, 0x2c, 0x90, 0x4e, 0x58, 0x7b, 0x69, 0x32, 0xb8, 0x5c, 0x4c, 0x06, 0xc9, 0x7c, 0x89, - 0x25, 0xd6, 0xbf, 0x86, 0x67, 0x7f, 0x0b, 0xeb, 0xa0, 0x3c, 0x36, 0x54, 0xdd, 0xa5, 0xf5, 0x99, - 0x01, 0x9d, 0xd2, 0x66, 0xd8, 0x1e, 0x80, 0x4a, 0xad, 0xb1, 0xf7, 0x3c, 0xa9, 0xc9, 0xbb, 0x7a, - 0xe3, 0x64, 0xb2, 0x87, 0xde, 0x73, 0x61, 0x9b, 0xa3, 0xe4, 0x93, 0x7d, 0x08, 0x1d, 0xa1, 0x2b, - 0xb3, 0x24, 0xf7, 0xd5, 0x0a, 0x20, 0x95, 0xd4, 0x6d, 0xfa, 0xb4, 0x6d, 0x51, 0x18, 0x5b, 0x07, - 0x60, 0xa6, 0xf3, 0xb2, 0x6f, 0x80, 0x39, 0xe7, 0x4b, 0x5d, 0x2f, 0xab, 0x4a, 0xab, 0x35, 0xe7, - 0x4b, 0x2a, 0x95, 0xd9, 0x55, 0x68, 0x22, 0x73, 0xc2, 0xd5, 0x0a, 0xeb, 0x76, 0x63, 0xce, 0x97, - 0x3f, 0xe2, 0xb1, 0xb5, 0x0b, 0xed, 0xe2, 0x22, 0x89, 0x68, 0x82, 0x5d, 0x4a, 0xf4, 0x60, 0x22, - 0xac, 0x87, 0xd0, 0x2e, 0x96, 0xa4, 0x98, 0xc7, 0xa2, 0x60, 0xe1, 0xbb, 0x24, 0xb8, 0x61, 0xab, - 0x01, 0xf6, 0xa3, 0x27, 0x81, 0xba, 0xba, 0x7c, 0x0d, 0xfa, 0x24, 0x90, 0x22, 0x57, 0xc8, 0x2a, - 0x19, 0xeb, 0xb3, 0x0d, 0x68, 0xa8, 0xfa, 0x98, 0x0d, 0x8a, 0x7d, 0x13, 0xde, 0x9b, 0xd6, 0x54, - 0x54, 0xad, 0x98, 0x42, 0xdf, 0x1b, 0xe5, 0x16, 0x66, 0xb8, 0x79, 0xf6, 0xe2, 0x7a, 0x93, 0x70, - 0xe5, 0xe8, 0x7e, 0xd6, 0xcf, 0xac, 0x2a, 0xf7, 0x93, 0xe6, 0xa9, 0xfe, 0xca, 0xcd, 0xd3, 0x55, - 0x68, 0xfa, 0x8b, 0xb9, 0x23, 0x97, 0xb1, 0x8e, 0xcf, 0x86, 0xbf, 0x98, 0x3f, 0x5a, 0xc6, 0x78, - 0x07, 0x32, 0x90, 0x7c, 0x46, 0x2c, 0x15, 0x9d, 0x2d, 0x22, 0x20, 0x73, 0x1f, 0xb6, 0x73, 0xf0, - 0xeb, 0xb9, 0xba, 0x4a, 0x6b, 0xe7, 0x3d, 0xe4, 0xe8, 0xbe, 0x3e, 0xe5, 0x66, 0x0a, 0xc7, 0x47, - 0x2e, 0xbb, 0x59, 0xec, 0x15, 0x08, 0xb5, 0x5b, 0xe4, 0x8c, 0xb9, 0x76, 0x00, 0x31, 0x1b, 0x37, - 0x80, 0xee, 0xa9, 0x44, 0x4c, 0x12, 0x69, 0x21, 0x81, 0x98, 0x6f, 0x42, 0x27, 0x03, 0x3e, 0x25, - 0x02, 0x6a, 0x96, 0x8c, 0x4c, 0x82, 0xef, 0xc0, 0x25, 0x5f, 0x2c, 0xa5, 0x53, 0x96, 0xde, 0x24, - 0x69, 0x86, 0xbc, 0x27, 0x45, 0x8d, 0x6f, 0x43, 0x3b, 0x0b, 0x60, 0x92, 0xdd, 0x52, 0x1d, 0x5b, - 0x4a, 0x25, 0xb1, 0x6b, 0xd0, 0x4a, 0xcb, 0x8e, 0x6d, 0x12, 0x68, 0x72, 0x55, 0x6d, 0xa4, 0x85, - 0x4c, 0x24, 0xe2, 0xc5, 0x4c, 0xea, 0x49, 0xda, 0x24, 0x43, 0x85, 0x8c, 0xad, 0xe8, 0x24, 0xfb, - 0x3a, 0x6c, 0xa7, 0x71, 0x43, 0x72, 0x1d, 0x92, 0xdb, 0x4a, 0x88, 0x24, 0xb4, 0x0b, 0xdd, 0x30, - 0x0a, 0xc2, 0x20, 0x16, 0x91, 0xc3, 0x5d, 0x37, 0x12, 0x71, 0xdc, 0xeb, 0xaa, 0xf9, 0x12, 0xfa, - 0x81, 0x22, 0x5b, 0xdf, 0x85, 0xa6, 0xf6, 0x31, 0x74, 0x69, 0xb2, 0x3a, 0xb9, 0x60, 0xdd, 0x56, - 0x03, 0xcc, 0xdc, 0x07, 0x61, 0x48, 0x5e, 0x56, 0xb7, 0xf1, 0xd3, 0xfa, 0x05, 0x34, 0xf5, 0x85, - 0x55, 0xb6, 0x82, 0x3f, 0x80, 0xad, 0x90, 0x47, 0x78, 0x8c, 0x7c, 0x43, 0x98, 0x14, 0xe4, 0xc7, - 0x3c, 0x92, 0x0f, 0x85, 0x2c, 0xf4, 0x85, 0x9b, 0x24, 0xaf, 0x48, 0xd6, 0x1d, 0xd8, 0x2e, 0xc8, - 0xe0, 0xb6, 0xc8, 0x8f, 0x92, 0x48, 0xa3, 0x41, 0xba, 0x72, 0x2d, 0x5b, 0xd9, 0xba, 0x0b, 0x66, - 0x7a, 0x37, 0x58, 0x37, 0x26, 0x47, 0x37, 0xb4, 0xb9, 0xd5, 0x90, 0x7a, 0xdd, 0xe0, 0x53, 0x11, - 0xe9, 0x98, 0x50, 0x03, 0xeb, 0x31, 0x74, 0x4a, 0x29, 0x9b, 0xdd, 0x82, 0x66, 0xb8, 0x18, 0x39, - 0xc9, 0x1b, 0x45, 0xd6, 0xd5, 0x1e, 0x2f, 0x46, 0x1f, 0x89, 0xd3, 0xa4, 0xab, 0x0d, 0x69, 0x94, - 0x4d, 0x5b, 0xcb, 0x4f, 0x3b, 0x83, 0x56, 0x12, 0xfd, 0xec, 0x7b, 0x60, 0xa6, 0x6e, 0x55, 0xca, - 0x91, 0xe9, 0xd2, 0x7a, 0xd2, 0x4c, 0x10, 0xbd, 0x23, 0xf6, 0x26, 0xbe, 0x70, 0x9d, 0x2c, 0x84, - 0x68, 0x8d, 0x96, 0xdd, 0x51, 0x8c, 0x8f, 0x93, 0x78, 0xb1, 0xde, 0x81, 0x86, 0xda, 0x1b, 0xda, - 0x07, 0x67, 0x4e, 0x4a, 0x69, 0xfc, 0xae, 0x4c, 0xe6, 0x7f, 0x30, 0xa0, 0x95, 0x64, 0xc1, 0x4a, - 0xa5, 0xc2, 0xa6, 0x6b, 0x5f, 0x75, 0xd3, 0xff, 0xfb, 0xc4, 0x73, 0x0b, 0x98, 0xca, 0x2f, 0x27, - 0x81, 0xf4, 0xfc, 0x89, 0xa3, 0x6c, 0xad, 0x72, 0x50, 0x97, 0x38, 0x4f, 0x88, 0x71, 0x8c, 0xf4, - 0xdb, 0x9f, 0x6f, 0x40, 0xe7, 0x60, 0x78, 0xef, 0xe8, 0x20, 0x0c, 0x67, 0xde, 0x98, 0x53, 0xfd, - 0xbe, 0x07, 0x75, 0xea, 0x50, 0x2a, 0xde, 0x46, 0xfb, 0x55, 0xad, 0x32, 0xbb, 0x0d, 0x1b, 0xd4, - 0xa8, 0xb0, 0xaa, 0x27, 0xd2, 0x7e, 0x65, 0xc7, 0x8c, 0x8b, 0xa8, 0x56, 0xe6, 0xfc, 0x4b, 0x69, - 0xbf, 0xaa, 0x6d, 0x66, 0x1f, 0x82, 0x99, 0xb5, 0x18, 0xab, 0xde, 0x4b, 0xfb, 0x2b, 0x1b, 0x68, - 0xd4, 0xcf, 0xca, 0xb1, 0x55, 0xcf, 0x7e, 0xfd, 0x95, 0x9d, 0x26, 0xdb, 0x87, 0x66, 0x52, 0xc4, - 0x56, 0xbf, 0x68, 0xf6, 0x57, 0x34, 0xb7, 0x68, 0x1e, 0xd5, 0x35, 0x54, 0x3d, 0xbb, 0xf6, 0x2b, - 0x3b, 0x70, 0xf6, 0x1e, 0x34, 0x74, 0x65, 0x51, 0xf9, 0xaa, 0xd9, 0xaf, 0x6e, 0x51, 0xf1, 0x90, - 0x59, 0xdf, 0xb4, 0xea, 0x69, 0xb8, 0xbf, 0xf2, 0xa9, 0x80, 0x1d, 0x00, 0xe4, 0x8a, 0xff, 0x95, - 0x6f, 0xbe, 0xfd, 0xd5, 0x4f, 0x00, 0xec, 0x2e, 0xb4, 0xb2, 0x67, 0x9d, 0xea, 0x57, 0xdc, 0xfe, - 0xaa, 0xae, 0x7c, 0xf8, 0xda, 0xbf, 0xfe, 0xbc, 0x63, 0xfc, 0xfa, 0x6c, 0xc7, 0xf8, 0xcd, 0xd9, - 0x8e, 0xf1, 0xe5, 0xd9, 0x8e, 0xf1, 0xfb, 0xb3, 0x1d, 0xe3, 0x4f, 0x67, 0x3b, 0xc6, 0x6f, 0xff, - 0xb2, 0x63, 0x8c, 0x1a, 0xe4, 0xfe, 0xef, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xf4, 0x43, 0x2c, - 0xa9, 0xb5, 0x18, 0x00, 0x00, + 0x15, 0xdf, 0xd1, 0x6a, 0x25, 0xcd, 0xd3, 0xea, 0x23, 0xed, 0xb5, 0x2d, 0x8b, 0xb0, 0xeb, 0x1a, + 0x43, 0xe2, 0x25, 0x8e, 0x36, 0x6c, 0x08, 0xb5, 0x8e, 0x43, 0xaa, 0x56, 0xb6, 0x61, 0xb7, 0x12, + 0x60, 0x19, 0xdb, 0xcb, 0x85, 0xaa, 0xa9, 0x96, 0xa6, 0x2d, 0x4d, 0x59, 0x9a, 0x99, 0xcc, 0xb4, + 0x36, 0x5a, 0x1f, 0x73, 0xce, 0x21, 0x07, 0xfe, 0x08, 0xfe, 0x84, 0x1c, 0x39, 0x51, 0x39, 0x72, + 0xe0, 0x6c, 0x60, 0x29, 0x0e, 0x70, 0xa5, 0xa8, 0xe2, 0x48, 0xf5, 0xeb, 0xee, 0xf9, 0xda, 0x91, + 0x89, 0x03, 0x27, 0x2e, 0x52, 0xf7, 0xfb, 0xe8, 0x8f, 0x37, 0xef, 0xbd, 0xdf, 0x7b, 0x0d, 0xd7, + 0xe8, 0x68, 0xec, 0xed, 0xf1, 0xf3, 0x90, 0xc5, 0xf2, 0x77, 0x10, 0x46, 0x01, 0x0f, 0xc8, 0x06, + 0x4e, 0xfa, 0x6f, 0x4f, 0x3c, 0x3e, 0x5d, 0x8c, 0x06, 0xe3, 0x60, 0xbe, 0x37, 0x09, 0x26, 0xc1, + 0x1e, 0x72, 0x47, 0x8b, 0xa7, 0x38, 0xc3, 0x09, 0x8e, 0xa4, 0x56, 0x7f, 0x67, 0x12, 0x04, 0x93, + 0x19, 0x4b, 0xa5, 0xb8, 0x37, 0x67, 0x31, 0xa7, 0xf3, 0x50, 0x09, 0x1c, 0x64, 0xd6, 0xe3, 0xcc, + 0x77, 0x59, 0x34, 0xf7, 0x7c, 0x9e, 0x1d, 0xce, 0xbc, 0x51, 0xbc, 0x37, 0x0e, 0xe6, 0xf3, 0xc0, + 0xcf, 0x1e, 0xa8, 0x7f, 0xef, 0x3f, 0x6a, 0x8e, 0xa3, 0xf3, 0x90, 0x07, 0x7b, 0x73, 0x16, 0x3d, + 0x9b, 0x31, 0xf5, 0x27, 0x95, 0xad, 0xdf, 0x55, 0xa1, 0x6e, 0xb3, 0x4f, 0x16, 0x2c, 0xe6, 0xe4, + 0x36, 0x54, 0xd9, 0x78, 0x1a, 0xf4, 0x2a, 0x37, 0x8d, 0xdb, 0xcd, 0x7d, 0x32, 0x90, 0x9b, 0x28, + 0xee, 0xc3, 0xf1, 0x34, 0x38, 0x5a, 0xb3, 0x51, 0x82, 0xbc, 0x05, 0x1b, 0x4f, 0x67, 0x8b, 0x78, + 0xda, 0x5b, 0x47, 0xd1, 0x2b, 0x79, 0xd1, 0x1f, 0x0b, 0xd6, 0xd1, 0x9a, 0x2d, 0x65, 0xc4, 0xb2, + 0x9e, 0xff, 0x34, 0xe8, 0x55, 0xcb, 0x96, 0x3d, 0xf6, 0x9f, 0xe2, 0xb2, 0x42, 0x82, 0x1c, 0x00, + 0xc4, 0x8c, 0x3b, 0x41, 0xc8, 0xbd, 0xc0, 0xef, 0x6d, 0xa0, 0xfc, 0xf5, 0xbc, 0xfc, 0x23, 0xc6, + 0x7f, 0x8e, 0xec, 0xa3, 0x35, 0xdb, 0x8c, 0xf5, 0x44, 0x68, 0x7a, 0xbe, 0xc7, 0x9d, 0xf1, 0x94, + 0x7a, 0x7e, 0xaf, 0x56, 0xa6, 0x79, 0xec, 0x7b, 0xfc, 0xbe, 0x60, 0x0b, 0x4d, 0x4f, 0x4f, 0xc4, + 0x55, 0x3e, 0x59, 0xb0, 0xe8, 0xbc, 0x57, 0x2f, 0xbb, 0xca, 0x2f, 0x04, 0x4b, 0x5c, 0x05, 0x65, + 0xc8, 0x3d, 0x68, 0x8e, 0xd8, 0xc4, 0xf3, 0x9d, 0xd1, 0x2c, 0x18, 0x3f, 0xeb, 0x35, 0x50, 0xa5, + 0x97, 0x57, 0x19, 0x0a, 0x81, 0xa1, 0xe0, 0x1f, 0xad, 0xd9, 0x30, 0x4a, 0x66, 0x64, 0x1f, 0x1a, + 0xe3, 0x29, 0x1b, 0x3f, 0x73, 0xf8, 0xb2, 0x67, 0xa2, 0xe6, 0xd5, 0xbc, 0xe6, 0x7d, 0xc1, 0x7d, + 0xbc, 0x3c, 0x5a, 0xb3, 0xeb, 0x63, 0x39, 0x24, 0xef, 0x81, 0xc9, 0x7c, 0x57, 0x6d, 0xd7, 0x44, + 0xa5, 0x6b, 0x85, 0xef, 0xe2, 0xbb, 0x7a, 0xb3, 0x06, 0x53, 0x63, 0x32, 0x80, 0x9a, 0x70, 0x14, + 0x8f, 0xf7, 0x36, 0x51, 0x67, 0xab, 0xb0, 0x11, 0xf2, 0x8e, 0xd6, 0x6c, 0x25, 0x25, 0xcc, 0xe7, + 0xb2, 0x99, 0x77, 0xc6, 0x22, 0x71, 0xb8, 0x2b, 0x65, 0xe6, 0x7b, 0x20, 0xf9, 0x78, 0x3c, 0xd3, + 0xd5, 0x93, 0x61, 0x1d, 0x36, 0xce, 0xe8, 0x6c, 0xc1, 0xac, 0x37, 0xa1, 0x99, 0xf1, 0x14, 0xd2, + 0x83, 0xfa, 0x9c, 0xc5, 0x31, 0x9d, 0xb0, 0x9e, 0x71, 0xd3, 0xb8, 0x6d, 0xda, 0x7a, 0x6a, 0xb5, + 0x61, 0x33, 0xeb, 0x27, 0xd6, 0x3c, 0x51, 0x14, 0xbe, 0x20, 0x14, 0xcf, 0x58, 0x14, 0x0b, 0x07, + 0x50, 0x8a, 0x6a, 0x4a, 0x6e, 0x41, 0x0b, 0xed, 0xe0, 0x68, 0xbe, 0xf0, 0xd3, 0xaa, 0xbd, 0x89, + 0xc4, 0x53, 0x25, 0xb4, 0x03, 0xcd, 0x70, 0x3f, 0x4c, 0x44, 0xd6, 0x51, 0x04, 0xc2, 0xfd, 0x50, + 0x09, 0x58, 0xef, 0x43, 0xb7, 0xe8, 0x4a, 0xa4, 0x0b, 0xeb, 0xcf, 0xd8, 0xb9, 0xda, 0x4f, 0x0c, + 0xc9, 0x96, 0xba, 0x16, 0xee, 0x61, 0xda, 0xea, 0x8e, 0x5f, 0x54, 0x12, 0xe5, 0xc4, 0x9b, 0xc8, + 0x01, 0x54, 0x45, 0x2c, 0xa3, 0x76, 0x73, 0xbf, 0x3f, 0x90, 0x81, 0x3e, 0xd0, 0x81, 0x3e, 0x78, + 0xac, 0x03, 0x7d, 0xd8, 0xf8, 0xea, 0xc5, 0xce, 0xda, 0x17, 0x7f, 0xdc, 0x31, 0x6c, 0xd4, 0x20, + 0x37, 0x84, 0x43, 0x50, 0xcf, 0x77, 0x3c, 0x57, 0xed, 0x53, 0xc7, 0xf9, 0xb1, 0x4b, 0x0e, 0xa1, + 0x3b, 0x0e, 0xfc, 0x98, 0xf9, 0xf1, 0x22, 0x76, 0x42, 0x1a, 0xd1, 0x79, 0xac, 0x62, 0x4d, 0x7f, + 0xfe, 0xfb, 0x9a, 0x7d, 0x82, 0x5c, 0xbb, 0x33, 0xce, 0x13, 0xc8, 0x07, 0x00, 0x67, 0x74, 0xe6, + 0xb9, 0x94, 0x07, 0x51, 0xdc, 0xab, 0xde, 0x5c, 0xcf, 0x28, 0x9f, 0x6a, 0xc6, 0x93, 0xd0, 0xa5, + 0x9c, 0x0d, 0xab, 0xe2, 0x64, 0x76, 0x46, 0x9e, 0xbc, 0x01, 0x1d, 0x1a, 0x86, 0x4e, 0xcc, 0x29, + 0x67, 0xce, 0xe8, 0x9c, 0xb3, 0x18, 0xe3, 0x71, 0xd3, 0x6e, 0xd1, 0x30, 0x7c, 0x24, 0xa8, 0x43, + 0x41, 0xb4, 0xdc, 0xe4, 0x6b, 0x62, 0xa8, 0x10, 0x02, 0x55, 0x97, 0x72, 0x8a, 0xd6, 0xd8, 0xb4, + 0x71, 0x2c, 0x68, 0x21, 0xe5, 0x53, 0x75, 0x47, 0x1c, 0x93, 0x6b, 0x50, 0x9b, 0x32, 0x6f, 0x32, + 0xe5, 0x78, 0xad, 0x75, 0x5b, 0xcd, 0x84, 0xe1, 0xc3, 0x28, 0x38, 0x63, 0x98, 0x2d, 0x1a, 0xb6, + 0x9c, 0x58, 0x7f, 0x35, 0xe0, 0xb5, 0x4b, 0xe1, 0x25, 0xd6, 0x9d, 0xd2, 0x78, 0xaa, 0xf7, 0x12, + 0x63, 0xf2, 0x96, 0x58, 0x97, 0xba, 0x2c, 0x52, 0x59, 0xac, 0xa5, 0x6e, 0x7c, 0x84, 0x44, 0x75, + 0x51, 0x25, 0x42, 0x1e, 0x42, 0x77, 0x46, 0x63, 0xee, 0xc8, 0x28, 0x70, 0x30, 0x4b, 0xad, 0xe7, + 0x22, 0xf3, 0x63, 0xaa, 0xa3, 0x45, 0x38, 0xa7, 0x52, 0x6f, 0xcf, 0x72, 0x54, 0x72, 0x04, 0x5b, + 0xa3, 0xf3, 0xe7, 0xd4, 0xe7, 0x9e, 0xcf, 0x9c, 0x4b, 0x36, 0xef, 0xa8, 0xa5, 0x1e, 0x9e, 0x79, + 0x2e, 0xf3, 0xc7, 0xda, 0xd8, 0x57, 0x12, 0x95, 0xe4, 0x63, 0xc4, 0xd6, 0x4d, 0x68, 0xe7, 0x73, + 0x01, 0x69, 0x43, 0x85, 0x2f, 0xd5, 0x0d, 0x2b, 0x7c, 0x69, 0x59, 0x89, 0x07, 0x26, 0x01, 0x79, + 0x49, 0x66, 0x17, 0x3a, 0x85, 0xe4, 0x90, 0x31, 0xb7, 0x91, 0x35, 0xb7, 0xd5, 0x81, 0x56, 0x2e, + 0x27, 0x58, 0x9f, 0x6f, 0x40, 0xc3, 0x66, 0x71, 0x28, 0x9c, 0x89, 0x1c, 0x80, 0xc9, 0x96, 0x63, + 0x26, 0xd3, 0xb1, 0x51, 0x48, 0x76, 0x52, 0xe6, 0xa1, 0xe6, 0x8b, 0xb4, 0x90, 0x08, 0x93, 0xdd, + 0x1c, 0x94, 0x5c, 0x29, 0x2a, 0x65, 0xb1, 0xe4, 0x4e, 0x1e, 0x4b, 0xb6, 0x0a, 0xb2, 0x05, 0x30, + 0xd9, 0xcd, 0x81, 0x49, 0x71, 0xe1, 0x1c, 0x9a, 0xdc, 0x2d, 0x41, 0x93, 0xe2, 0xf1, 0x57, 0xc0, + 0xc9, 0xdd, 0x12, 0x38, 0xe9, 0x5d, 0xda, 0xab, 0x14, 0x4f, 0xee, 0xe4, 0xf1, 0xa4, 0x78, 0x9d, + 0x02, 0xa0, 0x7c, 0x50, 0x06, 0x28, 0x37, 0x0a, 0x3a, 0x2b, 0x11, 0xe5, 0xdd, 0x4b, 0x88, 0x72, + 0xad, 0xa0, 0x5a, 0x02, 0x29, 0x77, 0x73, 0xb9, 0x1e, 0x4a, 0xef, 0x56, 0x9e, 0xec, 0xc9, 0x0f, + 0x2f, 0xa3, 0xd1, 0xf5, 0xe2, 0xa7, 0x2d, 0x83, 0xa3, 0xbd, 0x02, 0x1c, 0x5d, 0x2d, 0x9e, 0xb2, + 0x80, 0x47, 0x29, 0xaa, 0xec, 0x8a, 0xb8, 0x2f, 0x78, 0x9a, 0xc8, 0x11, 0x2c, 0x8a, 0x82, 0x48, + 0x25, 0x6c, 0x39, 0xb1, 0x6e, 0x8b, 0x4c, 0x94, 0xfa, 0xd7, 0x4b, 0x10, 0x08, 0x9d, 0x3e, 0xe3, + 0x5d, 0xd6, 0x97, 0x46, 0xaa, 0x8b, 0x11, 0x9d, 0xcd, 0x62, 0xa6, 0xca, 0x62, 0x19, 0x60, 0xaa, + 0xe4, 0x81, 0x69, 0x07, 0x9a, 0x22, 0x57, 0x16, 0x30, 0x87, 0x86, 0x1a, 0x73, 0xc8, 0xf7, 0xe0, + 0x35, 0xcc, 0x33, 0x12, 0xbe, 0x54, 0x20, 0x56, 0x31, 0x10, 0x3b, 0x82, 0x21, 0x2d, 0x26, 0x13, + 0xe0, 0xdb, 0x70, 0x25, 0x23, 0x2b, 0xd6, 0xc5, 0x1c, 0x27, 0x93, 0x6f, 0x37, 0x91, 0x3e, 0x0c, + 0xc3, 0x23, 0x1a, 0x4f, 0xad, 0x9f, 0xa6, 0x06, 0x4a, 0xf1, 0x8c, 0x40, 0x75, 0x1c, 0xb8, 0xf2, + 0xde, 0x2d, 0x1b, 0xc7, 0x02, 0xe3, 0x66, 0xc1, 0x04, 0x0f, 0x67, 0xda, 0x62, 0x28, 0xa4, 0x92, + 0x50, 0x32, 0x65, 0xcc, 0x58, 0xbf, 0x36, 0xd2, 0xf5, 0x52, 0x88, 0x2b, 0x43, 0x23, 0xe3, 0xbf, + 0x41, 0xa3, 0xca, 0xab, 0xa1, 0x91, 0x75, 0x61, 0xa4, 0x9f, 0x2c, 0xc1, 0x99, 0x6f, 0x76, 0x45, + 0xe1, 0x3d, 0x9e, 0xef, 0xb2, 0x25, 0x9a, 0x74, 0xdd, 0x96, 0x13, 0x5d, 0x02, 0xd4, 0xd0, 0xcc, + 0xf9, 0x12, 0xa0, 0x8e, 0x34, 0x39, 0x21, 0xb7, 0x10, 0x9f, 0x82, 0xa7, 0x2a, 0x54, 0x5b, 0x03, + 0x55, 0x4d, 0x9f, 0x08, 0xa2, 0x2d, 0x79, 0x99, 0x6c, 0x6b, 0xe6, 0xc0, 0xed, 0x75, 0x30, 0xc5, + 0x41, 0xe3, 0x90, 0x8e, 0x19, 0x46, 0x9e, 0x69, 0xa7, 0x04, 0xeb, 0x04, 0xc8, 0xe5, 0x88, 0x27, + 0xef, 0x43, 0x95, 0xd3, 0x89, 0xb0, 0xb7, 0x30, 0x59, 0x7b, 0x20, 0x1b, 0x80, 0xc1, 0x47, 0xa7, + 0x27, 0xd4, 0x8b, 0x86, 0xd7, 0x84, 0xa9, 0xfe, 0xfe, 0x62, 0xa7, 0x2d, 0x64, 0xee, 0x04, 0x73, + 0x8f, 0xb3, 0x79, 0xc8, 0xcf, 0x6d, 0xd4, 0xb1, 0xfe, 0x61, 0x08, 0x24, 0xc8, 0x65, 0x82, 0x52, + 0xc3, 0x69, 0x77, 0xaf, 0x64, 0x40, 0xfb, 0xeb, 0x19, 0xf3, 0xdb, 0x00, 0x13, 0x1a, 0x3b, 0x9f, + 0x52, 0x9f, 0x33, 0x57, 0x59, 0xd4, 0x9c, 0xd0, 0xf8, 0x97, 0x48, 0x10, 0x15, 0x8e, 0x60, 0x2f, + 0x62, 0xe6, 0xa2, 0x69, 0xd7, 0xed, 0xfa, 0x84, 0xc6, 0x4f, 0x62, 0xe6, 0x26, 0xf7, 0xaa, 0xbf, + 0xfa, 0xbd, 0xf2, 0x76, 0x6c, 0x14, 0xed, 0xf8, 0xcf, 0x8c, 0x0f, 0xa7, 0x20, 0xf9, 0xff, 0x7f, + 0xef, 0xbf, 0x19, 0xa2, 0x36, 0xc8, 0xa7, 0x61, 0x72, 0x0c, 0xaf, 0x25, 0x71, 0xe4, 0x2c, 0x30, + 0xbe, 0xb4, 0x2f, 0xbd, 0x3c, 0xfc, 0xba, 0x67, 0x79, 0x72, 0x4c, 0x7e, 0x06, 0xd7, 0x0b, 0x59, + 0x20, 0x59, 0xb0, 0xf2, 0xd2, 0x64, 0x70, 0x35, 0x9f, 0x0c, 0xf4, 0x7a, 0xda, 0x12, 0xeb, 0xdf, + 0xc0, 0xb3, 0xbf, 0x23, 0x0a, 0xa5, 0x2c, 0x78, 0x94, 0x7d, 0x4b, 0xeb, 0x33, 0x03, 0x3a, 0x85, + 0xc3, 0x90, 0x3d, 0x00, 0x99, 0x5a, 0x63, 0xef, 0xb9, 0x2e, 0xda, 0xbb, 0xea, 0xe0, 0x68, 0xb2, + 0x47, 0xde, 0x73, 0x66, 0x9b, 0x23, 0x3d, 0x24, 0x1f, 0x42, 0x87, 0xa9, 0xd2, 0x4d, 0xe7, 0xbe, + 0x4a, 0x0e, 0xc5, 0x74, 0x61, 0xa7, 0x6e, 0xdb, 0x66, 0xb9, 0xb9, 0x75, 0x08, 0x66, 0xb2, 0x2e, + 0xf9, 0x16, 0x98, 0x73, 0xba, 0x54, 0x05, 0xb5, 0x2c, 0xc5, 0x1a, 0x73, 0xba, 0xc4, 0x5a, 0x9a, + 0x5c, 0x87, 0xba, 0x60, 0x4e, 0xa8, 0xdc, 0x61, 0xdd, 0xae, 0xcd, 0xe9, 0xf2, 0x27, 0x34, 0xb6, + 0x76, 0xa1, 0x9d, 0xdf, 0x44, 0x8b, 0x6a, 0x70, 0x93, 0xa2, 0x87, 0x13, 0x66, 0x3d, 0x82, 0x76, + 0xbe, 0x66, 0x15, 0x79, 0x2c, 0x0a, 0x16, 0xbe, 0x8b, 0x82, 0x1b, 0xb6, 0x9c, 0x88, 0xb6, 0xf7, + 0x2c, 0x90, 0x9f, 0x2e, 0x5b, 0xa4, 0x9e, 0x06, 0x9c, 0x65, 0x2a, 0x5d, 0x29, 0x63, 0x7d, 0xb6, + 0x01, 0x35, 0x59, 0x40, 0x93, 0x41, 0xbe, 0x3d, 0x13, 0xdf, 0x4d, 0x69, 0x4a, 0xaa, 0x52, 0x4c, + 0xb0, 0xf1, 0x8d, 0x62, 0x8f, 0x33, 0x6c, 0x5e, 0xbc, 0xd8, 0xa9, 0x23, 0xae, 0x1c, 0x3f, 0x48, + 0x1b, 0x9e, 0x55, 0xfd, 0x80, 0xee, 0xae, 0xaa, 0xaf, 0xdc, 0x5d, 0x5d, 0x87, 0xba, 0xbf, 0x98, + 0x3b, 0x7c, 0x19, 0xab, 0xf8, 0xac, 0xf9, 0x8b, 0xf9, 0xe3, 0x65, 0x2c, 0xbe, 0x01, 0x0f, 0x38, + 0x9d, 0x21, 0x4b, 0x46, 0x67, 0x03, 0x09, 0x82, 0x79, 0x00, 0xad, 0x0c, 0xfc, 0x7a, 0xae, 0x2a, + 0xe3, 0xda, 0x59, 0x0f, 0x39, 0x7e, 0xa0, 0x6e, 0xd9, 0x4c, 0xe0, 0xf8, 0xd8, 0x25, 0xb7, 0xf3, + 0xcd, 0x04, 0xa2, 0x76, 0x03, 0x9d, 0x31, 0xd3, 0x2f, 0x08, 0xcc, 0x16, 0x07, 0x10, 0xee, 0x29, + 0x45, 0x4c, 0x14, 0x69, 0x08, 0x02, 0x32, 0xdf, 0x84, 0x4e, 0x0a, 0x7c, 0x52, 0x04, 0xe4, 0x2a, + 0x29, 0x19, 0x05, 0xdf, 0x81, 0x2d, 0x9f, 0x2d, 0xb9, 0x53, 0x94, 0x6e, 0xa2, 0x34, 0x11, 0xbc, + 0xd3, 0xbc, 0xc6, 0x77, 0xa1, 0x9d, 0x06, 0x30, 0xca, 0x6e, 0xca, 0x96, 0x2e, 0xa1, 0xa2, 0xd8, + 0x0d, 0x68, 0x24, 0x65, 0x47, 0x0b, 0x05, 0xea, 0x54, 0x56, 0x1b, 0x49, 0x21, 0x13, 0xb1, 0x78, + 0x31, 0xe3, 0x6a, 0x91, 0x36, 0xca, 0x60, 0x21, 0x63, 0x4b, 0x3a, 0xca, 0xde, 0x82, 0x56, 0x12, + 0x37, 0x28, 0xd7, 0x41, 0xb9, 0x4d, 0x4d, 0x44, 0xa1, 0x5d, 0xe8, 0x86, 0x51, 0x10, 0x06, 0x31, + 0x8b, 0x1c, 0xea, 0xba, 0x11, 0x8b, 0xe3, 0x5e, 0x57, 0xae, 0xa7, 0xe9, 0x87, 0x92, 0x6c, 0x7d, + 0x1f, 0xea, 0xba, 0x9e, 0xda, 0x82, 0x0d, 0xb4, 0x3a, 0xba, 0x60, 0xd5, 0x96, 0x13, 0x91, 0xb9, + 0x0f, 0xc3, 0x50, 0xbd, 0x0a, 0x88, 0xa1, 0xf5, 0x2b, 0xa8, 0xab, 0x0f, 0x56, 0xda, 0x2b, 0xfe, + 0x08, 0x36, 0x43, 0x1a, 0x89, 0x6b, 0x64, 0x3b, 0x46, 0x5d, 0xb1, 0x9f, 0xd0, 0x88, 0x3f, 0x62, + 0x3c, 0xd7, 0x38, 0x36, 0x51, 0x5e, 0x92, 0xac, 0xbb, 0xd0, 0xca, 0xc9, 0x88, 0x63, 0xa1, 0x1f, + 0xe9, 0x48, 0xc3, 0x49, 0xb2, 0x73, 0x25, 0xdd, 0xd9, 0xba, 0x07, 0x66, 0xf2, 0x6d, 0x44, 0x61, + 0xa9, 0xaf, 0x6e, 0x28, 0x73, 0xcb, 0x29, 0x36, 0xc3, 0xc1, 0xa7, 0x2c, 0x52, 0x31, 0x21, 0x27, + 0xd6, 0x13, 0xe8, 0x14, 0x52, 0x36, 0xb9, 0x03, 0xf5, 0x70, 0x31, 0x72, 0xf4, 0x23, 0x46, 0xda, + 0xf6, 0x9e, 0x2c, 0x46, 0x1f, 0xb1, 0x73, 0xdd, 0xf6, 0x86, 0x38, 0x4b, 0x97, 0xad, 0x64, 0x97, + 0x9d, 0x41, 0x43, 0x47, 0x3f, 0xf9, 0x01, 0x98, 0x89, 0x5b, 0x15, 0x72, 0x64, 0xb2, 0xb5, 0x5a, + 0x34, 0x15, 0x14, 0xde, 0x11, 0x7b, 0x13, 0x9f, 0xb9, 0x4e, 0x1a, 0x42, 0xb8, 0x47, 0xc3, 0xee, + 0x48, 0xc6, 0xc7, 0x3a, 0x5e, 0xac, 0x77, 0xa0, 0x26, 0xcf, 0x26, 0xec, 0x23, 0x56, 0xd6, 0xb5, + 0xb6, 0x18, 0x97, 0x26, 0xf3, 0x3f, 0x18, 0xd0, 0xd0, 0x59, 0xb0, 0x54, 0x29, 0x77, 0xe8, 0xca, + 0xd7, 0x3d, 0xf4, 0xff, 0x3e, 0xf1, 0xdc, 0x01, 0x22, 0xf3, 0xcb, 0x59, 0xc0, 0x3d, 0x7f, 0xe2, + 0x48, 0x5b, 0xcb, 0x1c, 0xd4, 0x45, 0xce, 0x29, 0x32, 0x4e, 0x04, 0x7d, 0xff, 0xf3, 0x0d, 0xe8, + 0x1c, 0x0e, 0xef, 0x1f, 0x1f, 0x86, 0xe1, 0xcc, 0x1b, 0x53, 0xac, 0xdf, 0xf7, 0xa0, 0x8a, 0x2d, + 0x4c, 0xc9, 0x13, 0x6c, 0xbf, 0xac, 0x97, 0x26, 0xfb, 0xb0, 0x81, 0x9d, 0x0c, 0x29, 0x7b, 0x89, + 0xed, 0x97, 0xb6, 0xd4, 0x62, 0x13, 0xd9, 0xeb, 0x5c, 0x7e, 0x90, 0xed, 0x97, 0xf5, 0xd5, 0xe4, + 0x43, 0x30, 0xd3, 0x16, 0x63, 0xd5, 0xb3, 0x6c, 0x7f, 0x65, 0x87, 0x2d, 0xf4, 0xd3, 0x72, 0x6c, + 0xd5, 0xeb, 0x62, 0x7f, 0x65, 0x2b, 0x4a, 0x0e, 0xa0, 0xae, 0x8b, 0xd8, 0xf2, 0x87, 0xd3, 0xfe, + 0x8a, 0xee, 0x57, 0x98, 0x47, 0x76, 0x0d, 0x65, 0xaf, 0xbb, 0xfd, 0xd2, 0x16, 0x9d, 0xbc, 0x07, + 0x35, 0x55, 0x59, 0x94, 0x3e, 0x9e, 0xf6, 0xcb, 0x7b, 0x58, 0x71, 0xc9, 0xb4, 0x6f, 0x5a, 0xf5, + 0x02, 0xdd, 0x5f, 0xf9, 0x96, 0x40, 0x0e, 0x01, 0x32, 0xc5, 0xff, 0xca, 0xa7, 0xe5, 0xfe, 0xea, + 0x37, 0x02, 0x72, 0x0f, 0x1a, 0xe9, 0xbb, 0x4f, 0xf9, 0x63, 0x71, 0x7f, 0x55, 0xdb, 0x3e, 0x7c, + 0xfd, 0x5f, 0x7f, 0xde, 0x36, 0x7e, 0x73, 0xb1, 0x6d, 0x7c, 0x79, 0xb1, 0x6d, 0x7c, 0x75, 0xb1, + 0x6d, 0xfc, 0xfe, 0x62, 0xdb, 0xf8, 0xd3, 0xc5, 0xb6, 0xf1, 0xdb, 0xbf, 0x6c, 0x1b, 0xa3, 0x1a, + 0xba, 0xff, 0xbb, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x1a, 0x7c, 0xbd, 0x95, 0x1c, 0x19, 0x00, + 0x00, } diff --git a/abci/types/types.proto b/abci/types/types.proto index 517369b13..ffa321836 100644 --- a/abci/types/types.proto +++ b/abci/types/types.proto @@ -49,6 +49,8 @@ message RequestFlush { message RequestInfo { string version = 1; + uint64 block_version = 2; + uint64 p2p_version = 3; } // nondeterministic @@ -129,9 +131,12 @@ message ResponseFlush { message ResponseInfo { string data = 1; + string version = 2; - int64 last_block_height = 3; - bytes last_block_app_hash = 4; + uint64 app_version = 3; + + int64 last_block_height = 4; + bytes last_block_app_hash = 5; } // nondeterministic diff --git a/consensus/replay.go b/consensus/replay.go index af6369c3b..bffab8d28 100644 --- a/consensus/replay.go +++ b/consensus/replay.go @@ -11,6 +11,7 @@ import ( "time" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/version" //auto "github.com/tendermint/tendermint/libs/autofile" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" @@ -19,7 +20,6 @@ import ( "github.com/tendermint/tendermint/proxy" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" - "github.com/tendermint/tendermint/version" ) var crc32c = crc32.MakeTable(crc32.Castagnoli) @@ -227,7 +227,7 @@ func (h *Handshaker) NBlocks() int { func (h *Handshaker) Handshake(proxyApp proxy.AppConns) error { // Handshake is done via ABCI Info on the query conn. - res, err := proxyApp.Query().InfoSync(abci.RequestInfo{Version: version.Version}) + res, err := proxyApp.Query().InfoSync(proxy.RequestInfo) if err != nil { return fmt.Errorf("Error calling Info: %v", err) } @@ -238,9 +238,15 @@ func (h *Handshaker) Handshake(proxyApp proxy.AppConns) error { } appHash := res.LastBlockAppHash - h.logger.Info("ABCI Handshake", "appHeight", blockHeight, "appHash", fmt.Sprintf("%X", appHash)) + h.logger.Info("ABCI Handshake App Info", + "height", blockHeight, + "hash", fmt.Sprintf("%X", appHash), + "software-version", res.Version, + "protocol-version", res.AppVersion, + ) - // TODO: check app version. + // Set AppVersion on the state. + h.initialState.Version.Consensus.App = version.Protocol(res.AppVersion) // Replay blocks up to the latest in the blockstore. _, err = h.ReplayBlocks(h.initialState, appHash, blockHeight, proxyApp) diff --git a/consensus/replay_test.go b/consensus/replay_test.go index 160e777c3..4e1fa2b77 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -20,6 +20,7 @@ import ( crypto "github.com/tendermint/tendermint/crypto" auto "github.com/tendermint/tendermint/libs/autofile" dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/version" cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/libs/log" @@ -337,7 +338,7 @@ func testHandshakeReplay(t *testing.T, nBlocks int, mode uint) { t.Fatalf(err.Error()) } - stateDB, state, store := stateAndStore(config, privVal.GetPubKey()) + stateDB, state, store := stateAndStore(config, privVal.GetPubKey(), kvstore.ProtocolVersion) store.chain = chain store.commits = commits @@ -352,7 +353,7 @@ func testHandshakeReplay(t *testing.T, nBlocks int, mode uint) { // run nBlocks against a new client to build up the app state. // use a throwaway tendermint state proxyApp := proxy.NewAppConns(clientCreator2) - stateDB, state, _ := stateAndStore(config, privVal.GetPubKey()) + stateDB, state, _ := stateAndStore(config, privVal.GetPubKey(), kvstore.ProtocolVersion) buildAppStateFromChain(proxyApp, stateDB, state, chain, nBlocks, mode) } @@ -442,7 +443,7 @@ func buildAppStateFromChain(proxyApp proxy.AppConns, stateDB dbm.DB, func buildTMStateFromChain(config *cfg.Config, stateDB dbm.DB, state sm.State, chain []*types.Block, mode uint) sm.State { // run the whole chain against this client to build up the tendermint state clientCreator := proxy.NewLocalClientCreator(kvstore.NewPersistentKVStoreApplication(path.Join(config.DBDir(), "1"))) - proxyApp := proxy.NewAppConns(clientCreator) // sm.NewHandshaker(config, state, store, ReplayLastBlock)) + proxyApp := proxy.NewAppConns(clientCreator) if err := proxyApp.Start(); err != nil { panic(err) } @@ -588,9 +589,10 @@ func readPieceFromWAL(msg *TimedWALMessage) interface{} { } // fresh state and mock store -func stateAndStore(config *cfg.Config, pubKey crypto.PubKey) (dbm.DB, sm.State, *mockBlockStore) { +func stateAndStore(config *cfg.Config, pubKey crypto.PubKey, appVersion version.Protocol) (dbm.DB, sm.State, *mockBlockStore) { stateDB := dbm.NewMemDB() state, _ := sm.MakeGenesisStateFromFile(config.GenesisFile()) + state.Version.Consensus.App = appVersion store := NewMockBlockStore(config, state.ConsensusParams) return stateDB, state, store } @@ -639,7 +641,7 @@ func TestInitChainUpdateValidators(t *testing.T) { config := ResetConfig("proxy_test_") privVal := privval.LoadFilePV(config.PrivValidatorFile()) - stateDB, state, store := stateAndStore(config, privVal.GetPubKey()) + stateDB, state, store := stateAndStore(config, privVal.GetPubKey(), 0x0) oldValAddr := state.Validators.Validators[0].Address diff --git a/consensus/wal_generator.go b/consensus/wal_generator.go index 980a44892..5ff597a52 100644 --- a/consensus/wal_generator.go +++ b/consensus/wal_generator.go @@ -38,7 +38,8 @@ func WALGenerateNBlocks(wr io.Writer, numBlocks int) (err error) { ///////////////////////////////////////////////////////////////////////////// // COPY PASTE FROM node.go WITH A FEW MODIFICATIONS - // NOTE: we can't import node package because of circular dependency + // NOTE: we can't import node package because of circular dependency. + // NOTE: we don't do handshake so need to set state.Version.Consensus.App directly. privValidatorFile := config.PrivValidatorFile() privValidator := privval.LoadOrGenFilePV(privValidatorFile) genDoc, err := types.GenesisDocFromFile(config.GenesisFile()) @@ -51,6 +52,7 @@ func WALGenerateNBlocks(wr io.Writer, numBlocks int) (err error) { if err != nil { return errors.Wrap(err, "failed to make genesis state") } + state.Version.Consensus.App = kvstore.ProtocolVersion blockStore := bc.NewBlockStore(blockStoreDB) proxyApp := proxy.NewAppConns(proxy.NewLocalClientCreator(app)) proxyApp.SetLogger(logger.With("module", "proxy")) diff --git a/docs/spec/abci/abci.md b/docs/spec/abci/abci.md index 54b7c899d..afd726174 100644 --- a/docs/spec/abci/abci.md +++ b/docs/spec/abci/abci.md @@ -134,10 +134,13 @@ Commit are included in the header of the next block. ### Info - **Request**: - - `Version (string)`: The Tendermint version + - `Version (string)`: The Tendermint software semantic version + - `BlockVersion (uint64)`: The Tendermint Block Protocol version + - `P2PVersion (uint64)`: The Tendermint P2P Protocol version - **Response**: - `Data (string)`: Some arbitrary information - - `Version (Version)`: Version information + - `Version (string)`: The application software semantic version + - `AppVersion (uint64)`: The application protocol version - `LastBlockHeight (int64)`: Latest block for which the app has called Commit - `LastBlockAppHash ([]byte)`: Latest result of Commit @@ -145,6 +148,7 @@ Commit are included in the header of the next block. - Return information about the application state. - Used to sync Tendermint with the application during a handshake that happens on startup. + - The returned `AppVersion` will be included in the Header of every block. - Tendermint expects `LastBlockAppHash` and `LastBlockHeight` to be updated during `Commit`, ensuring that `Commit` is never called twice for the same block height. diff --git a/node/node.go b/node/node.go index 97de24736..522f18e91 100644 --- a/node/node.go +++ b/node/node.go @@ -195,8 +195,8 @@ func NewNode(config *cfg.Config, return nil, fmt.Errorf("Error starting proxy app connections: %v", err) } - // Create the handshaker, which calls RequestInfo and replays any blocks - // as necessary to sync tendermint with the app. + // Create the handshaker, which calls RequestInfo, sets the AppVersion on the state, + // and replays any blocks as necessary to sync tendermint with the app. consensusLogger := logger.With("module", "consensus") handshaker := cs.NewHandshaker(stateDB, state, blockStore, genDoc) handshaker.SetLogger(consensusLogger) @@ -204,9 +204,12 @@ func NewNode(config *cfg.Config, return nil, fmt.Errorf("Error during handshake: %v", err) } - // reload the state (it may have been updated by the handshake) + // Reload the state. It will have the Version.Consensus.App set by the + // Handshake, and may have other modifications as well (ie. depending on + // what happened during block replay). state = sm.LoadState(stateDB) + // Ensure the state's block version matches that of the software. if state.Version.Consensus.Block != version.BlockProtocol { return nil, fmt.Errorf( "Block version of the software does not match that of the state.\n"+ @@ -359,7 +362,13 @@ func NewNode(config *cfg.Config, var ( p2pLogger = logger.With("module", "p2p") - nodeInfo = makeNodeInfo(config, nodeKey.ID(), txIndexer, genDoc.ChainID) + nodeInfo = makeNodeInfo( + config, + nodeKey.ID(), + txIndexer, + genDoc.ChainID, + p2p.ProtocolVersionWithApp(state.Version.Consensus.App), + ) ) // Setup Transport. @@ -764,13 +773,14 @@ func makeNodeInfo( nodeID p2p.ID, txIndexer txindex.TxIndexer, chainID string, + protocolVersion p2p.ProtocolVersion, ) p2p.NodeInfo { txIndexerStatus := "on" if _, ok := txIndexer.(*null.TxIndex); ok { txIndexerStatus = "off" } nodeInfo := p2p.DefaultNodeInfo{ - ProtocolVersion: p2p.InitProtocolVersion, + ProtocolVersion: protocolVersion, ID_: nodeID, Network: chainID, Version: version.TMCoreSemVer, diff --git a/node/node_test.go b/node/node_test.go index f4c1f6a16..3a33e6bbb 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -10,7 +10,11 @@ import ( "github.com/stretchr/testify/assert" + "github.com/tendermint/tendermint/abci/example/kvstore" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/p2p" + sm "github.com/tendermint/tendermint/state" + "github.com/tendermint/tendermint/version" cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/types" @@ -91,3 +95,21 @@ func TestNodeDelayedStop(t *testing.T) { startTime := tmtime.Now() assert.Equal(t, true, startTime.After(n.GenesisDoc().GenesisTime)) } + +func TestNodeSetAppVersion(t *testing.T) { + config := cfg.ResetTestRoot("node_app_version_test") + + // create & start node + n, err := DefaultNewNode(config, log.TestingLogger()) + assert.NoError(t, err, "expected no err on DefaultNewNode") + + // default config uses the kvstore app + var appVersion version.Protocol = kvstore.ProtocolVersion + + // check version is set in state + state := sm.LoadState(n.stateDB) + assert.Equal(t, state.Version.Consensus.App, appVersion) + + // check version is set in node info + assert.Equal(t, n.nodeInfo.(p2p.DefaultNodeInfo).ProtocolVersion.App, appVersion) +} diff --git a/p2p/node_info.go b/p2p/node_info.go index 5874dc857..1d408eb68 100644 --- a/p2p/node_info.go +++ b/p2p/node_info.go @@ -49,10 +49,17 @@ type ProtocolVersion struct { App version.Protocol `json:"app"` } -var InitProtocolVersion = ProtocolVersion{ - P2P: version.P2PProtocol, - Block: version.BlockProtocol, - App: 0, +// InitProtocolVersion populates the Block and P2P versions, but not the App. +var InitProtocolVersion = ProtocolVersionWithApp(0) + +// ProtocolVersionWithApp returns a fully populated ProtocolVersion +// using the provided App version and the Block and P2P versions defined in the `version` package. +func ProtocolVersionWithApp(appVersion version.Protocol) ProtocolVersion { + return ProtocolVersion{ + P2P: version.P2PProtocol, + Block: version.BlockProtocol, + App: appVersion, + } } //------------------------------------------------------------- @@ -148,7 +155,7 @@ func (info DefaultNodeInfo) ValidateBasic() error { switch txIndex { case "", "on", "off": default: - return fmt.Errorf("info.Other.TxIndex should be either 'on' or 'off', got '%v'", txIndex) + return fmt.Errorf("info.Other.TxIndex should be either 'on', 'off', or empty string, got '%v'", txIndex) } // XXX: Should we be more strict about address formats? rpcAddr := other.RPCAddress diff --git a/proxy/app_conn_test.go b/proxy/app_conn_test.go index 5eadb032f..ca98f1be4 100644 --- a/proxy/app_conn_test.go +++ b/proxy/app_conn_test.go @@ -143,7 +143,7 @@ func TestInfo(t *testing.T) { proxy := NewAppConnTest(cli) t.Log("Connected") - resInfo, err := proxy.InfoSync(types.RequestInfo{Version: ""}) + resInfo, err := proxy.InfoSync(RequestInfo) if err != nil { t.Errorf("Unexpected error: %v", err) } diff --git a/proxy/version.go b/proxy/version.go new file mode 100644 index 000000000..fb506e659 --- /dev/null +++ b/proxy/version.go @@ -0,0 +1,15 @@ +package proxy + +import ( + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/version" +) + +// RequestInfo contains all the information for sending +// the abci.RequestInfo message during handshake with the app. +// It contains only compile-time version information. +var RequestInfo = abci.RequestInfo{ + Version: version.Version, + BlockVersion: version.BlockProtocol.Uint64(), + P2PVersion: version.P2PProtocol.Uint64(), +} diff --git a/rpc/client/mock/abci.go b/rpc/client/mock/abci.go index 3a0ed79cd..e63d22e0c 100644 --- a/rpc/client/mock/abci.go +++ b/rpc/client/mock/abci.go @@ -3,10 +3,10 @@ package mock import ( abci "github.com/tendermint/tendermint/abci/types" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" - "github.com/tendermint/tendermint/version" ) // ABCIApp will send all abci related request to the named app, @@ -23,7 +23,7 @@ var ( ) func (a ABCIApp) ABCIInfo() (*ctypes.ResultABCIInfo, error) { - return &ctypes.ResultABCIInfo{a.App.Info(abci.RequestInfo{Version: version.Version})}, nil + return &ctypes.ResultABCIInfo{a.App.Info(proxy.RequestInfo)}, nil } func (a ABCIApp) ABCIQuery(path string, data cmn.HexBytes) (*ctypes.ResultABCIQuery, error) { diff --git a/rpc/core/abci.go b/rpc/core/abci.go index 47219563c..2468a5f05 100644 --- a/rpc/core/abci.go +++ b/rpc/core/abci.go @@ -3,8 +3,8 @@ package core import ( abci "github.com/tendermint/tendermint/abci/types" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/proxy" ctypes "github.com/tendermint/tendermint/rpc/core/types" - "github.com/tendermint/tendermint/version" ) // Query the application for some information. @@ -87,7 +87,7 @@ func ABCIQuery(path string, data cmn.HexBytes, height int64, prove bool) (*ctype // } // ``` func ABCIInfo() (*ctypes.ResultABCIInfo, error) { - resInfo, err := proxyAppQuery.InfoSync(abci.RequestInfo{Version: version.Version}) + resInfo, err := proxyAppQuery.InfoSync(proxy.RequestInfo) if err != nil { return nil, err } diff --git a/state/state.go b/state/state.go index aedb2b001..5c1b68a26 100644 --- a/state/state.go +++ b/state/state.go @@ -27,6 +27,10 @@ type Version struct { Software string } +// initStateVersion sets the Consensus.Block and Software versions, +// but leaves the Consensus.App version blank. +// The Consensus.App version will be set during the Handshake, once +// we hear from the app what protocol version it is running. var initStateVersion = Version{ Consensus: version.Consensus{ Block: version.BlockProtocol, diff --git a/version/version.go b/version/version.go index 5a089141f..19b3f3da7 100644 --- a/version/version.go +++ b/version/version.go @@ -28,6 +28,12 @@ const ( // Protocol is used for implementation agnostic versioning. type Protocol uint64 +// Uint64 returns the Protocol version as a uint64, +// eg. for compatibility with ABCI types. +func (p Protocol) Uint64() uint64 { + return uint64(p) +} + var ( // P2PProtocol versions all p2p behaviour and msgs. P2PProtocol Protocol = 4 From c3384e88e5fee31ecf2d3c62b20204eae965bf02 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 18 Oct 2018 17:32:53 -0400 Subject: [PATCH 03/35] adr-016: update int64->uint64; add version to ConsensusParams (#2667) --- .../architecture/adr-016-protocol-versions.md | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/docs/architecture/adr-016-protocol-versions.md b/docs/architecture/adr-016-protocol-versions.md index 1ae1f467f..3a2351a56 100644 --- a/docs/architecture/adr-016-protocol-versions.md +++ b/docs/architecture/adr-016-protocol-versions.md @@ -96,7 +96,7 @@ Each component of the software is independently versioned in a modular way and i ## Proposal -Each of BlockVersion, AppVersion, P2PVersion, is a monotonically increasing int64. +Each of BlockVersion, AppVersion, P2PVersion, is a monotonically increasing uint64. To use these versions, we need to update the block Header, the p2p NodeInfo, and the ABCI. @@ -106,8 +106,8 @@ Block Header should include a `Version` struct as its first field like: ``` type Version struct { - Block int64 - App int64 + Block uint64 + App uint64 } ``` @@ -130,9 +130,9 @@ NodeInfo should include a Version struct as its first field like: ``` type Version struct { - P2P int64 - Block int64 - App int64 + P2P uint64 + Block uint64 + App uint64 Other []string } @@ -168,9 +168,9 @@ RequestInfo should add support for protocol versions like: ``` message RequestInfo { - string software_version - int64 block_version - int64 p2p_version + string version + uint64 block_version + uint64 p2p_version } ``` @@ -180,39 +180,46 @@ Similarly, ResponseInfo should return the versions: message ResponseInfo { string data - string software_version - int64 app_version + string version + uint64 app_version int64 last_block_height bytes last_block_app_hash } ``` +The existing `version` fields should be called `software_version` but we leave +them for now to reduce the number of breaking changes. + #### EndBlock Updating the version could be done either with new fields or by using the existing `tags`. Since we're trying to communicate information that will be included in Tendermint block Headers, it should be native to the ABCI, and not -something embedded through some scheme in the tags. +something embedded through some scheme in the tags. Thus, version updates should +be communicated through EndBlock. -ResponseEndBlock will include a new field `version_updates`: +EndBlock already contains `ConsensusParams`. We can add version information to +the ConsensusParams as well: ``` -message ResponseEndBlock { - repeated Validator validator_updates - ConsensusParams consensus_param_updates - repeated common.KVPair tags +message ConsensusParams { - VersionUpdate version_update + BlockSize block_size + EvidenceParams evidence_params + VersionParams version } -message VersionUpdate { - int64 app_version +message VersionParams { + uint64 block_version + uint64 app_version } ``` -Tendermint will use the information in VersionUpdate for the next block it -proposes. +For now, the `block_version` will be ignored, as we do not allow block version +to be updated live. If the `app_version` is set, it signals that the app's +protocol version has changed, and the new `app_version` will be included in the +`Block.Header.Version.App` for the next block. ### BlockVersion From e798766a27a0825f5e5deb460d755d2bf8813f96 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 18 Oct 2018 18:02:20 -0400 Subject: [PATCH 04/35] types: remove Version from CanonicalXxx (#2666) --- docs/spec/blockchain/encoding.md | 1 - types/canonical.go | 10 ++------ types/vote_test.go | 42 +++++++++++++++----------------- 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/docs/spec/blockchain/encoding.md b/docs/spec/blockchain/encoding.md index ed92739d0..5657784dc 100644 --- a/docs/spec/blockchain/encoding.md +++ b/docs/spec/blockchain/encoding.md @@ -307,7 +307,6 @@ We call this encoding the SignBytes. For instance, SignBytes for a vote is the A ```go type CanonicalVote struct { - Version uint64 `binary:"fixed64"` Height int64 `binary:"fixed64"` Round int64 `binary:"fixed64"` VoteType byte diff --git a/types/canonical.go b/types/canonical.go index 8a33debda..c40f35dd3 100644 --- a/types/canonical.go +++ b/types/canonical.go @@ -23,7 +23,6 @@ type CanonicalPartSetHeader struct { } type CanonicalProposal struct { - Version uint64 `binary:"fixed64"` Height int64 `binary:"fixed64"` Round int64 `binary:"fixed64"` Type SignedMsgType // type alias for byte @@ -35,7 +34,6 @@ type CanonicalProposal struct { } type CanonicalVote struct { - Version uint64 `binary:"fixed64"` Height int64 `binary:"fixed64"` Round int64 `binary:"fixed64"` Type SignedMsgType // type alias for byte @@ -45,9 +43,8 @@ type CanonicalVote struct { } type CanonicalHeartbeat struct { - Version uint64 `binary:"fixed64"` - Height int64 `binary:"fixed64"` - Round int `binary:"fixed64"` + Height int64 `binary:"fixed64"` + Round int `binary:"fixed64"` Type byte Sequence int `binary:"fixed64"` ValidatorAddress Address @@ -74,7 +71,6 @@ func CanonicalizePartSetHeader(psh PartSetHeader) CanonicalPartSetHeader { func CanonicalizeProposal(chainID string, proposal *Proposal) CanonicalProposal { return CanonicalProposal{ - Version: 0, // TODO Height: proposal.Height, Round: int64(proposal.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) Type: ProposalType, @@ -88,7 +84,6 @@ func CanonicalizeProposal(chainID string, proposal *Proposal) CanonicalProposal func CanonicalizeVote(chainID string, vote *Vote) CanonicalVote { return CanonicalVote{ - Version: 0, // TODO Height: vote.Height, Round: int64(vote.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) Type: vote.Type, @@ -100,7 +95,6 @@ func CanonicalizeVote(chainID string, vote *Vote) CanonicalVote { func CanonicalizeHeartbeat(chainID string, heartbeat *Heartbeat) CanonicalHeartbeat { return CanonicalHeartbeat{ - Version: 0, // TODO Height: heartbeat.Height, Round: heartbeat.Round, Type: byte(HeartbeatType), diff --git a/types/vote_test.go b/types/vote_test.go index 282953f46..066df4964 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -54,8 +54,7 @@ func TestVoteSignable(t *testing.T) { } func TestVoteSignableTestVectors(t *testing.T) { - voteWithVersion := CanonicalizeVote("", &Vote{Height: 1, Round: 1}) - voteWithVersion.Version = 123 + vote := CanonicalizeVote("", &Vote{Height: 1, Round: 1}) tests := []struct { canonicalVote CanonicalVote @@ -64,20 +63,20 @@ func TestVoteSignableTestVectors(t *testing.T) { { CanonicalizeVote("", &Vote{}), // NOTE: Height and Round are skipped here. This case needs to be considered while parsing. - []byte{0xb, 0x2a, 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, + []byte{0xb, 0x22, 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, }, // with proper (fixed size) height and round (PreCommit): { CanonicalizeVote("", &Vote{Height: 1, Round: 1, Type: PrecommitType}), []byte{ 0x1f, // total length - 0x11, // (field_number << 3) | wire_type (version is missing) + 0x9, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height - 0x19, // (field_number << 3) | wire_type + 0x11, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round - 0x20, // (field_number << 3) | wire_type + 0x18, // (field_number << 3) | wire_type 0x2, // PrecommitType - 0x2a, // (field_number << 3) | wire_type + 0x22, // (field_number << 3) | wire_type // remaining fields (timestamp): 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, }, @@ -86,29 +85,26 @@ func TestVoteSignableTestVectors(t *testing.T) { CanonicalizeVote("", &Vote{Height: 1, Round: 1, Type: PrevoteType}), []byte{ 0x1f, // total length - 0x11, // (field_number << 3) | wire_type (version is missing) + 0x9, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height - 0x19, // (field_number << 3) | wire_type + 0x11, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round - 0x20, // (field_number << 3) | wire_type + 0x18, // (field_number << 3) | wire_type 0x1, // PrevoteType - 0x2a, // (field_number << 3) | wire_type + 0x22, // (field_number << 3) | wire_type // remaining fields (timestamp): 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, }, - // containing version (empty type) { - voteWithVersion, + vote, []byte{ - 0x26, // total length - 0x9, // (field_number << 3) | wire_type - 0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // version (123) - 0x11, // (field_number << 3) | wire_type + 0x1d, // total length + 0x9, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height - 0x19, // (field_number << 3) | wire_type + 0x11, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round // remaining fields (timestamp): - 0x2a, + 0x22, 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, }, // containing non-empty chain_id: @@ -116,14 +112,14 @@ func TestVoteSignableTestVectors(t *testing.T) { CanonicalizeVote("test_chain_id", &Vote{Height: 1, Round: 1}), []byte{ 0x2c, // total length - 0x11, // (field_number << 3) | wire_type + 0x9, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height - 0x19, // (field_number << 3) | wire_type + 0x11, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round // remaining fields: - 0x2a, // (field_number << 3) | wire_type + 0x22, // (field_number << 3) | wire_type 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff, // timestamp - 0x3a, // (field_number << 3) | wire_type + 0x32, // (field_number << 3) | wire_type 0xd, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64}, // chainID }, } From 746d137f86f34ecdb5f2a1d2b94a66913c1c9efe Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 18 Oct 2018 18:26:32 -0400 Subject: [PATCH 05/35] p2p: Restore OriginalAddr (#2668) * p2p: bring back OriginalAddr * p2p: set OriginalAddr * update changelog --- CHANGELOG_PENDING.md | 2 ++ blockchain/reactor_test.go | 1 + p2p/dummy/peer.go | 5 +++++ p2p/peer.go | 28 ++++++++++++++++++++++++++++ p2p/peer_set_test.go | 1 + p2p/peer_test.go | 2 +- p2p/pex/pex_reactor_test.go | 1 + p2p/switch.go | 9 ++++++--- p2p/test_util.go | 12 +++++++----- p2p/transport.go | 21 +++++++++++++-------- 10 files changed, 65 insertions(+), 17 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 99c389974..758bfeb2f 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -82,3 +82,5 @@ Proposal or timeoutProposal before entering prevote - [p2p] \#2555 fix p2p switch FlushThrottle value (@goolAdapter) - [libs/event] \#2518 fix event concurrency flaw (@goolAdapter) - [state] \#2616 Pass nil to NewValidatorSet() when genesis file's Validators field is nil +- [p2p] \#2668 Reconnect to originally dialed address (not self-reported + address) for persistent peers diff --git a/blockchain/reactor_test.go b/blockchain/reactor_test.go index 7fc7ffb77..fca063e0c 100644 --- a/blockchain/reactor_test.go +++ b/blockchain/reactor_test.go @@ -206,3 +206,4 @@ func (tp *bcrTestPeer) IsPersistent() bool { return true } func (tp *bcrTestPeer) Get(s string) interface{} { return s } func (tp *bcrTestPeer) Set(string, interface{}) {} func (tp *bcrTestPeer) RemoteIP() net.IP { return []byte{127, 0, 0, 1} } +func (tp *bcrTestPeer) OriginalAddr() *p2p.NetAddress { return nil } diff --git a/p2p/dummy/peer.go b/p2p/dummy/peer.go index 4871719d4..65ff65fb2 100644 --- a/p2p/dummy/peer.go +++ b/p2p/dummy/peer.go @@ -78,3 +78,8 @@ func (p *peer) Get(key string) interface{} { } return nil } + +// OriginalAddr always returns nil. +func (p *peer) OriginalAddr() *p2p.NetAddress { + return nil +} diff --git a/p2p/peer.go b/p2p/peer.go index 009313141..944174b0e 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -26,6 +26,7 @@ type Peer interface { NodeInfo() NodeInfo // peer's info Status() tmconn.ConnectionStatus + OriginalAddr() *NetAddress Send(byte, []byte) bool TrySend(byte, []byte) bool @@ -43,10 +44,28 @@ type peerConn struct { config *config.P2PConfig conn net.Conn // source connection + originalAddr *NetAddress // nil for inbound connections + // cached RemoteIP() ip net.IP } +func newPeerConn( + outbound, persistent bool, + config *config.P2PConfig, + conn net.Conn, + originalAddr *NetAddress, +) peerConn { + + return peerConn{ + outbound: outbound, + persistent: persistent, + config: config, + conn: conn, + originalAddr: originalAddr, + } +} + // ID only exists for SecretConnection. // NOTE: Will panic if conn is not *SecretConnection. func (pc peerConn) ID() ID { @@ -195,6 +214,15 @@ func (p *peer) NodeInfo() NodeInfo { return p.nodeInfo } +// OriginalAddr returns the original address, which was used to connect with +// the peer. Returns nil for inbound peers. +func (p *peer) OriginalAddr() *NetAddress { + if p.peerConn.outbound { + return p.peerConn.originalAddr + } + return nil +} + // Status returns the peer's ConnectionStatus. func (p *peer) Status() tmconn.ConnectionStatus { return p.mconn.Status() diff --git a/p2p/peer_set_test.go b/p2p/peer_set_test.go index c0ad80005..daa9b2c82 100644 --- a/p2p/peer_set_test.go +++ b/p2p/peer_set_test.go @@ -28,6 +28,7 @@ func (mp *mockPeer) IsPersistent() bool { return true } func (mp *mockPeer) Get(s string) interface{} { return s } func (mp *mockPeer) Set(string, interface{}) {} func (mp *mockPeer) RemoteIP() net.IP { return mp.ip } +func (mp *mockPeer) OriginalAddr() *NetAddress { return nil } // Returns a mock peer func newMockPeer(ip net.IP) *mockPeer { diff --git a/p2p/peer_test.go b/p2p/peer_test.go index 9c330ee52..02f1d2c0f 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -114,7 +114,7 @@ func testOutboundPeerConn( return peerConn{}, cmn.ErrorWrap(err, "Error creating peer") } - pc, err := testPeerConn(conn, config, true, persistent, ourNodePrivKey) + pc, err := testPeerConn(conn, config, true, persistent, ourNodePrivKey, addr) if err != nil { if cerr := conn.Close(); cerr != nil { return peerConn{}, cmn.ErrorWrap(err, cerr.Error()) diff --git a/p2p/pex/pex_reactor_test.go b/p2p/pex/pex_reactor_test.go index b0338c3c2..9d3f49bba 100644 --- a/p2p/pex/pex_reactor_test.go +++ b/p2p/pex/pex_reactor_test.go @@ -402,6 +402,7 @@ func (mockPeer) Send(byte, []byte) bool { return false } func (mockPeer) TrySend(byte, []byte) bool { return false } func (mockPeer) Set(string, interface{}) {} func (mockPeer) Get(string) interface{} { return nil } +func (mockPeer) OriginalAddr() *p2p.NetAddress { return nil } func assertPeersWithTimeout( t *testing.T, diff --git a/p2p/switch.go b/p2p/switch.go index 64e248fc3..b1406b9b0 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -280,9 +280,12 @@ func (sw *Switch) StopPeerForError(peer Peer, reason interface{}) { sw.stopAndRemovePeer(peer, reason) if peer.IsPersistent() { - // TODO: use the original address dialed, not the self reported one - // See #2618. - addr := peer.NodeInfo().NetAddress() + addr := peer.OriginalAddr() + if addr == nil { + // FIXME: persistent peers can't be inbound right now. + // self-reported address for inbound persistent peers + addr = peer.NodeInfo().NetAddress() + } go sw.reconnectToPeer(addr) } } diff --git a/p2p/test_util.go b/p2p/test_util.go index 4d43175bb..e1f7b5040 100644 --- a/p2p/test_util.go +++ b/p2p/test_util.go @@ -206,7 +206,7 @@ func testInboundPeerConn( config *config.P2PConfig, ourNodePrivKey crypto.PrivKey, ) (peerConn, error) { - return testPeerConn(conn, config, false, false, ourNodePrivKey) + return testPeerConn(conn, config, false, false, ourNodePrivKey, nil) } func testPeerConn( @@ -214,6 +214,7 @@ func testPeerConn( cfg *config.P2PConfig, outbound, persistent bool, ourNodePrivKey crypto.PrivKey, + originalAddr *NetAddress, ) (pc peerConn, err error) { conn := rawConn @@ -231,10 +232,11 @@ func testPeerConn( // Only the information we already have return peerConn{ - config: cfg, - outbound: outbound, - persistent: persistent, - conn: conn, + config: cfg, + outbound: outbound, + persistent: persistent, + conn: conn, + originalAddr: originalAddr, }, nil } diff --git a/p2p/transport.go b/p2p/transport.go index b20f32f3d..10565d8a9 100644 --- a/p2p/transport.go +++ b/p2p/transport.go @@ -171,7 +171,7 @@ func (mt *MultiplexTransport) Accept(cfg peerConfig) (Peer, error) { cfg.outbound = false - return mt.wrapPeer(a.conn, a.nodeInfo, cfg), nil + return mt.wrapPeer(a.conn, a.nodeInfo, cfg, nil), nil case <-mt.closec: return nil, &ErrTransportClosed{} } @@ -199,7 +199,7 @@ func (mt *MultiplexTransport) Dial( cfg.outbound = true - p := mt.wrapPeer(secretConn, nodeInfo, cfg) + p := mt.wrapPeer(secretConn, nodeInfo, cfg, &addr) return p, nil } @@ -399,14 +399,19 @@ func (mt *MultiplexTransport) wrapPeer( c net.Conn, ni NodeInfo, cfg peerConfig, + dialedAddr *NetAddress, ) Peer { + + peerConn := newPeerConn( + cfg.outbound, + cfg.persistent, + &mt.p2pConfig, + c, + dialedAddr, + ) + p := newPeer( - peerConn{ - conn: c, - config: &mt.p2pConfig, - outbound: cfg.outbound, - persistent: cfg.persistent, - }, + peerConn, mt.mConfig, ni, cfg.reactorsByCh, From f536089f0b7ff7894df2d656c35bdb0508f4e7f2 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 19 Oct 2018 11:39:27 -0400 Subject: [PATCH 06/35] types: dont use SimpleHashFromMap for header. closes #1841 (#2670) * types: dont use SimpleHashFromMap for header. closes #1841 * changelog and spec * comments --- CHANGELOG_PENDING.md | 2 ++ docs/spec/blockchain/encoding.md | 2 +- types/block.go | 42 +++++++++++++++++--------------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 758bfeb2f..ed33be782 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -45,6 +45,8 @@ BREAKING CHANGES: * [types] \#2644 Add Version struct to Header * [state] \#2587 Require block.Time of the fist block to be genesis time * [state] \#2644 Require block.Version to match state.Version + * [types] \#2670 Header.Hash() builds Merkle tree out of fields in the same + order they appear in the header, instead of sorting by field name * P2P Protocol * [p2p] \#2654 Add `ProtocolVersion` struct with protocol versions to top of diff --git a/docs/spec/blockchain/encoding.md b/docs/spec/blockchain/encoding.md index 5657784dc..563b0a885 100644 --- a/docs/spec/blockchain/encoding.md +++ b/docs/spec/blockchain/encoding.md @@ -216,7 +216,7 @@ prefix) before being concatenated together and hashed. Note: we will abuse notion and invoke `SimpleMerkleRoot` with arguments of type `struct` or type `[]struct`. For `struct` arguments, we compute a `[][]byte` containing the hash of each -field in the struct sorted by the hash of the field name. +field in the struct, in the same order the fields appear in the struct. For `[]struct` arguments, we compute a `[][]byte` by hashing the individual `struct` elements. ### Simple Merkle Proof diff --git a/types/block.go b/types/block.go index 06ad55fcc..2a5b5fc4a 100644 --- a/types/block.go +++ b/types/block.go @@ -258,8 +258,10 @@ func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 { //----------------------------------------------------------------------------- // Header defines the structure of a Tendermint block header -// NOTE: changes to the Header should be duplicated in the abci Header -// and in /docs/spec/blockchain/blockchain.md +// NOTE: changes to the Header should be duplicated in: +// - header.Hash() +// - abci.Header +// - /docs/spec/blockchain/blockchain.md type Header struct { // basic block info Version version.Consensus `json:"version"` @@ -289,6 +291,8 @@ type Header struct { } // Hash returns the hash of the header. +// It computes a Merkle tree from the header fields +// ordered as they appear in the Header. // Returns nil if ValidatorHash is missing, // since a Header is not valid unless there is // a ValidatorsHash (corresponding to the validator set). @@ -296,23 +300,23 @@ func (h *Header) Hash() cmn.HexBytes { if h == nil || len(h.ValidatorsHash) == 0 { return nil } - return merkle.SimpleHashFromMap(map[string][]byte{ - "Version": cdcEncode(h.Version), - "ChainID": cdcEncode(h.ChainID), - "Height": cdcEncode(h.Height), - "Time": cdcEncode(h.Time), - "NumTxs": cdcEncode(h.NumTxs), - "TotalTxs": cdcEncode(h.TotalTxs), - "LastBlockID": cdcEncode(h.LastBlockID), - "LastCommitHash": cdcEncode(h.LastCommitHash), - "DataHash": cdcEncode(h.DataHash), - "ValidatorsHash": cdcEncode(h.ValidatorsHash), - "NextValidatorsHash": cdcEncode(h.NextValidatorsHash), - "AppHash": cdcEncode(h.AppHash), - "ConsensusHash": cdcEncode(h.ConsensusHash), - "LastResultsHash": cdcEncode(h.LastResultsHash), - "EvidenceHash": cdcEncode(h.EvidenceHash), - "ProposerAddress": cdcEncode(h.ProposerAddress), + return merkle.SimpleHashFromByteSlices([][]byte{ + cdcEncode(h.Version), + cdcEncode(h.ChainID), + cdcEncode(h.Height), + cdcEncode(h.Time), + cdcEncode(h.NumTxs), + cdcEncode(h.TotalTxs), + cdcEncode(h.LastBlockID), + cdcEncode(h.LastCommitHash), + cdcEncode(h.DataHash), + cdcEncode(h.ValidatorsHash), + cdcEncode(h.NextValidatorsHash), + cdcEncode(h.ConsensusHash), + cdcEncode(h.AppHash), + cdcEncode(h.LastResultsHash), + cdcEncode(h.EvidenceHash), + cdcEncode(h.ProposerAddress), }) } From 7c6519adbd62cdc4c1e3003e14bbb61e71725e02 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 19 Oct 2018 13:49:04 -0400 Subject: [PATCH 07/35] Bucky/changelog (#2673) * update changelog, add authors script * update changelog * update changelog --- CHANGELOG_PENDING.md | 59 +++++++++++++++++++++++++++++--------------- scripts/authors.sh | 16 ++++++++++++ 2 files changed, 55 insertions(+), 20 deletions(-) create mode 100755 scripts/authors.sh diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index ed33be782..5490ae77c 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -1,7 +1,23 @@ # Pending +## v0.26.0 + +*October 19, 2018* + Special thanks to external contributors on this release: -@goolAdapter, @bradyjoestar +@bradyjoestar, @connorwstein, @goolAdapter, @HaoyangLiu, +@james-ray, @overbool, @phymbert, @Slamper, @Uzair1995 + +This release is primarily about adding Version fields to various data structures, +optimizing consensus messages for signing and verification in +restricted environments (like HSMs and the Ethereum Virtual Machine), and +aligning the consensus code with the [specification](https://arxiv.org/abs/1807.04938). +It also includes our first take at a generalized merkle proof system. + +See the [UPGRADING.md](UPGRADING.md#v0.26.0) for details on upgrading to the new +version. + +Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint). BREAKING CHANGES: @@ -9,11 +25,11 @@ BREAKING CHANGES: * [config] \#2232 timeouts as time.Duration, not ints * [config] \#2505 Remove Mempool.RecheckEmpty (it was effectively useless anyways) * [config] `mempool.wal` is disabled by default - * [rpc] \#2298 `/abci_query` takes `prove` argument instead of `trusted` and switches the default - behaviour to `prove=false` * [privval] \#2459 Split `SocketPVMsg`s implementations into Request and Response, where the Response may contain a error message (returned by the remote signer) * [state] \#2644 Add Version field to State, breaking the format of State as encoded on disk. + * [rpc] \#2298 `/abci_query` takes `prove` argument instead of `trusted` and switches the default + behaviour to `prove=false` * [rpc] \#2654 Remove all `node_info.other.*_version` fields in `/status` and `/net_info` @@ -25,13 +41,13 @@ BREAKING CHANGES: `AppVersion` * Go API - * [node] Remove node.RunForever * [config] \#2232 timeouts as time.Duration, not ints - * [rpc/client] \#2298 `ABCIQueryOptions.Trusted` -> `ABCIQueryOptions.Prove` - * [types] \#2298 Remove `Index` and `Total` fields from `TxProof`. * [crypto/merkle & lite] \#2298 Various changes to accomodate General Merkle trees * [crypto/merkle] \#2595 Remove all Hasher objects in favor of byte slices * [crypto/merkle] \#2635 merkle.SimpleHashFromTwoHashes is no longer exported + * [node] Remove node.RunForever + * [rpc/client] \#2298 `ABCIQueryOptions.Trusted` -> `ABCIQueryOptions.Prove` + * [types] \#2298 Remove `Index` and `Total` fields from `TxProof`. * [types] \#2598 `VoteTypeXxx` are now of type `SignedMsgType byte` and named `XxxType`, eg. `PrevoteType`, `PrecommitType`. @@ -43,6 +59,8 @@ BREAKING CHANGES: `SignedMsgType` to enumerate. * [types] \#2512 Remove the pubkey field from the validator hash * [types] \#2644 Add Version struct to Header + * [types] \#2609 ConsensusParams.Hash() is the hash of the amino encoded + struct instead of the Merkle tree of the fields * [state] \#2587 Require block.Time of the fist block to be genesis time * [state] \#2644 Require block.Version to match state.Version * [types] \#2670 Header.Hash() builds Merkle tree out of fields in the same @@ -52,11 +70,10 @@ BREAKING CHANGES: * [p2p] \#2654 Add `ProtocolVersion` struct with protocol versions to top of DefaultNodeInfo and require `ProtocolVersion.Block` to match during peer handshake - FEATURES: -- [crypto/merkle] \#2298 General Merkle Proof scheme for chaining various types of Merkle trees together - [abci] \#2557 Add `Codespace` field to `Response{CheckTx, DeliverTx, Query}` - [abci] \#2662 Add `BlockVersion` and `P2PVersion` to `RequestInfo` +- [crypto/merkle] \#2298 General Merkle Proof scheme for chaining various types of Merkle trees together IMPROVEMENTS: - Additional Metrics @@ -66,23 +83,25 @@ IMPROVEMENTS: - [crypto/ed25519] \#2558 Switch to use latest `golang.org/x/crypto` through our fork at github.com/tendermint/crypto - [tools] \#2238 Binary dependencies are now locked to a specific git commit -- [crypto] \#2099 make crypto random use chacha, and have forward secrecy of generated randomness BUG FIXES: - [autofile] \#2428 Group.RotateFile need call Flush() before rename (@goolAdapter) -- [node] \#2434 Make node respond to signal interrupts while sleeping for genesis time -- [consensus] [\#1690](https://github.com/tendermint/tendermint/issues/1690) wait for -timeoutPrecommit before starting next round -- [consensus] [\#1745](https://github.com/tendermint/tendermint/issues/1745) wait for -Proposal or timeoutProposal before entering prevote -- [evidence] \#2515 fix db iter leak (@goolAdapter) -- [common/bit_array] Fixed a bug in the `Or` function -- [common/bit_array] Fixed a bug in the `Sub` function (@james-ray) -- [common] \#2534 Make bit array's PickRandom choose uniformly from true bits +- [common] Fixed a bug in the `BitArray.Or` method +- [common] Fixed a bug in the `BitArray.Sub` method (@james-ray) +- [common] \#2534 Fix `BitArray.PickRandom` to choose uniformly from true bits +- [consensus] [\#1690](https://github.com/tendermint/tendermint/issues/1690) Wait for + timeoutPrecommit before starting next round +- [consensus] [\#1745](https://github.com/tendermint/tendermint/issues/1745) Wait for + Proposal or timeoutProposal before entering prevote +- [consensus] \#2642 Only propose ValidBlock, not LockedBlock +- [consensus] \#2642 Initialized ValidRound and LockedRound to -1 - [consensus] \#1637 Limit the amount of evidence that can be included in a block -- [p2p] \#2555 fix p2p switch FlushThrottle value (@goolAdapter) -- [libs/event] \#2518 fix event concurrency flaw (@goolAdapter) +- [evidence] \#2515 Fix db iter leak (@goolAdapter) +- [libs/event] \#2518 Fix event concurrency flaw (@goolAdapter) +- [node] \#2434 Make node respond to signal interrupts while sleeping for genesis time - [state] \#2616 Pass nil to NewValidatorSet() when genesis file's Validators field is nil +- [p2p] \#2555 Fix p2p switch FlushThrottle value (@goolAdapter) - [p2p] \#2668 Reconnect to originally dialed address (not self-reported address) for persistent peers + diff --git a/scripts/authors.sh b/scripts/authors.sh new file mode 100755 index 000000000..7aafb0127 --- /dev/null +++ b/scripts/authors.sh @@ -0,0 +1,16 @@ +#! /bin/bash + +# Usage: +# `./authors.sh` +# Print a list of all authors who have committed to develop since master. +# +# `./authors.sh ` +# Lookup the email address on Github and print the associated username + +author=$1 + +if [[ "$author" == "" ]]; then + git log master..develop | grep Author | sort | uniq +else + curl -s "https://api.github.com/search/users?q=$author+in%3Aemail&type=Users&utf8=%E2%9C%93" | jq .items[0].login +fi From 30519e8361c19f4bf320ef4d26288ebc621ad725 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 19 Oct 2018 14:23:14 -0400 Subject: [PATCH 08/35] types: first field in Canonical structs is Type (#2675) * types: first field in Canonical structs is Type * fix spec --- docs/spec/blockchain/encoding.md | 4 ++-- types/canonical.go | 14 +++++++------- types/vote_test.go | 24 ++++++++++++------------ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/spec/blockchain/encoding.md b/docs/spec/blockchain/encoding.md index 563b0a885..2f9fcdca1 100644 --- a/docs/spec/blockchain/encoding.md +++ b/docs/spec/blockchain/encoding.md @@ -301,15 +301,15 @@ Where the `"value"` is the base64 encoding of the raw pubkey bytes, and the Signed messages (eg. votes, proposals) in the consensus are encoded using Amino. When signing, the elements of a message are re-ordered so the fixed-length fields -are first, making it easy to quickly check the version, height, round, and type. +are first, making it easy to quickly check the type, height, and round. The `ChainID` is also appended to the end. We call this encoding the SignBytes. For instance, SignBytes for a vote is the Amino encoding of the following struct: ```go type CanonicalVote struct { + Type byte Height int64 `binary:"fixed64"` Round int64 `binary:"fixed64"` - VoteType byte Timestamp time.Time BlockID CanonicalBlockID ChainID string diff --git a/types/canonical.go b/types/canonical.go index c40f35dd3..632dcb624 100644 --- a/types/canonical.go +++ b/types/canonical.go @@ -23,9 +23,9 @@ type CanonicalPartSetHeader struct { } type CanonicalProposal struct { + Type SignedMsgType // type alias for byte Height int64 `binary:"fixed64"` Round int64 `binary:"fixed64"` - Type SignedMsgType // type alias for byte POLRound int64 `binary:"fixed64"` Timestamp time.Time BlockPartsHeader CanonicalPartSetHeader @@ -34,19 +34,19 @@ type CanonicalProposal struct { } type CanonicalVote struct { + Type SignedMsgType // type alias for byte Height int64 `binary:"fixed64"` Round int64 `binary:"fixed64"` - Type SignedMsgType // type alias for byte Timestamp time.Time BlockID CanonicalBlockID ChainID string } type CanonicalHeartbeat struct { + Type byte Height int64 `binary:"fixed64"` Round int `binary:"fixed64"` - Type byte - Sequence int `binary:"fixed64"` + Sequence int `binary:"fixed64"` ValidatorAddress Address ValidatorIndex int ChainID string @@ -71,9 +71,9 @@ func CanonicalizePartSetHeader(psh PartSetHeader) CanonicalPartSetHeader { func CanonicalizeProposal(chainID string, proposal *Proposal) CanonicalProposal { return CanonicalProposal{ + Type: ProposalType, Height: proposal.Height, Round: int64(proposal.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) - Type: ProposalType, POLRound: int64(proposal.POLRound), Timestamp: proposal.Timestamp, BlockPartsHeader: CanonicalizePartSetHeader(proposal.BlockPartsHeader), @@ -84,9 +84,9 @@ func CanonicalizeProposal(chainID string, proposal *Proposal) CanonicalProposal func CanonicalizeVote(chainID string, vote *Vote) CanonicalVote { return CanonicalVote{ + Type: vote.Type, Height: vote.Height, Round: int64(vote.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) - Type: vote.Type, Timestamp: vote.Timestamp, BlockID: CanonicalizeBlockID(vote.BlockID), ChainID: chainID, @@ -95,9 +95,9 @@ func CanonicalizeVote(chainID string, vote *Vote) CanonicalVote { func CanonicalizeHeartbeat(chainID string, heartbeat *Heartbeat) CanonicalHeartbeat { return CanonicalHeartbeat{ + Type: byte(HeartbeatType), Height: heartbeat.Height, Round: heartbeat.Round, - Type: byte(HeartbeatType), Sequence: heartbeat.Sequence, ValidatorAddress: heartbeat.ValidatorAddress, ValidatorIndex: heartbeat.ValidatorIndex, diff --git a/types/vote_test.go b/types/vote_test.go index 066df4964..2172f0600 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -70,12 +70,12 @@ func TestVoteSignableTestVectors(t *testing.T) { CanonicalizeVote("", &Vote{Height: 1, Round: 1, Type: PrecommitType}), []byte{ 0x1f, // total length - 0x9, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height + 0x8, // (field_number << 3) | wire_type + 0x2, // PrecommitType 0x11, // (field_number << 3) | wire_type + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height + 0x19, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round - 0x18, // (field_number << 3) | wire_type - 0x2, // PrecommitType 0x22, // (field_number << 3) | wire_type // remaining fields (timestamp): 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, @@ -85,12 +85,12 @@ func TestVoteSignableTestVectors(t *testing.T) { CanonicalizeVote("", &Vote{Height: 1, Round: 1, Type: PrevoteType}), []byte{ 0x1f, // total length - 0x9, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height + 0x8, // (field_number << 3) | wire_type + 0x1, // PrevoteType 0x11, // (field_number << 3) | wire_type + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height + 0x19, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round - 0x18, // (field_number << 3) | wire_type - 0x1, // PrevoteType 0x22, // (field_number << 3) | wire_type // remaining fields (timestamp): 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, @@ -99,9 +99,9 @@ func TestVoteSignableTestVectors(t *testing.T) { vote, []byte{ 0x1d, // total length - 0x9, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height 0x11, // (field_number << 3) | wire_type + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height + 0x19, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round // remaining fields (timestamp): 0x22, @@ -112,9 +112,9 @@ func TestVoteSignableTestVectors(t *testing.T) { CanonicalizeVote("test_chain_id", &Vote{Height: 1, Round: 1}), []byte{ 0x2c, // total length - 0x9, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height 0x11, // (field_number << 3) | wire_type + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height + 0x19, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round // remaining fields: 0x22, // (field_number << 3) | wire_type From 9d62bd0ad3bf691002a815339b4dd675441bce93 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 19 Oct 2018 14:29:45 -0400 Subject: [PATCH 09/35] crypto: use stdlib crypto/rand. ref #2099 (#2669) * crypto: use stdlib crypto/rand. ref #2099 * comment --- crypto/random.go | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/crypto/random.go b/crypto/random.go index af3286427..914c321b7 100644 --- a/crypto/random.go +++ b/crypto/random.go @@ -9,10 +9,11 @@ import ( "sync" "golang.org/x/crypto/chacha20poly1305" - - . "github.com/tendermint/tendermint/libs/common" ) +// NOTE: This is ignored for now until we have time +// to properly review the MixEntropy function - https://github.com/tendermint/tendermint/issues/2099. +// // The randomness here is derived from xoring a chacha20 keystream with // output from crypto/rand's OS Entropy Reader. (Due to fears of the OS' // entropy being backdoored) @@ -23,9 +24,13 @@ var gRandInfo *randInfo func init() { gRandInfo = &randInfo{} - gRandInfo.MixEntropy(randBytes(32)) // Init + + // TODO: uncomment after reviewing MixEntropy - + // https://github.com/tendermint/tendermint/issues/2099 + // gRandInfo.MixEntropy(randBytes(32)) // Init } +// WARNING: This function needs review - https://github.com/tendermint/tendermint/issues/2099. // Mix additional bytes of randomness, e.g. from hardware, user-input, etc. // It is OK to call it multiple times. It does not diminish security. func MixEntropy(seedBytes []byte) { @@ -37,20 +42,28 @@ func randBytes(numBytes int) []byte { b := make([]byte, numBytes) _, err := crand.Read(b) if err != nil { - PanicCrisis(err) + panic(err) } return b } +// This only uses the OS's randomness +func CRandBytes(numBytes int) []byte { + return randBytes(numBytes) +} + +/* TODO: uncomment after reviewing MixEntropy - https://github.com/tendermint/tendermint/issues/2099 // This uses the OS and the Seed(s). func CRandBytes(numBytes int) []byte { - b := make([]byte, numBytes) - _, err := gRandInfo.Read(b) - if err != nil { - PanicCrisis(err) - } - return b + return randBytes(numBytes) + b := make([]byte, numBytes) + _, err := gRandInfo.Read(b) + if err != nil { + panic(err) + } + return b } +*/ // CRandHex returns a hex encoded string that's floor(numDigits/2) * 2 long. // @@ -60,10 +73,17 @@ func CRandHex(numDigits int) string { return hex.EncodeToString(CRandBytes(numDigits / 2)) } +// Returns a crand.Reader. +func CReader() io.Reader { + return crand.Reader +} + +/* TODO: uncomment after reviewing MixEntropy - https://github.com/tendermint/tendermint/issues/2099 // Returns a crand.Reader mixed with user-supplied entropy func CReader() io.Reader { return gRandInfo } +*/ //-------------------------------------------------------------------------------- @@ -75,7 +95,7 @@ type randInfo struct { } // You can call this as many times as you'd like. -// XXX TODO review +// XXX/TODO: review - https://github.com/tendermint/tendermint/issues/2099 func (ri *randInfo) MixEntropy(seedBytes []byte) { ri.mtx.Lock() defer ri.mtx.Unlock() From f94eb42ebe1c53db52b07e4080e060acc4077a5a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 19 Oct 2018 20:27:00 -0400 Subject: [PATCH 10/35] Version bump; Update Upgrading.md; linkify Changelog (#2679) * version bump * update UPGRADING.md * add missing pr numbers to changelog pending * linkify changelog --- CHANGELOG_PENDING.md | 94 ++++++++++++++++++++++---------------------- UPGRADING.md | 76 +++++++++++++++++++++++++++++++++++ version/version.go | 4 +- 3 files changed, 125 insertions(+), 49 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 5490ae77c..163c4649f 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -22,86 +22,86 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi BREAKING CHANGES: * CLI/RPC/Config - * [config] \#2232 timeouts as time.Duration, not ints - * [config] \#2505 Remove Mempool.RecheckEmpty (it was effectively useless anyways) - * [config] `mempool.wal` is disabled by default - * [privval] \#2459 Split `SocketPVMsg`s implementations into Request and Response, where the Response may contain a error message (returned by the remote signer) - * [state] \#2644 Add Version field to State, breaking the format of State as + * [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) timeouts as time.Duration, not ints + * [config] [\#2505](https://github.com/tendermint/tendermint/issues/2505) Remove Mempool.RecheckEmpty (it was effectively useless anyways) + * [config] [\#2490](https://github.com/tendermint/tendermint/issues/2490) `mempool.wal` is disabled by default + * [privval] [\#2459](https://github.com/tendermint/tendermint/issues/2459) Split `SocketPVMsg`s implementations into Request and Response, where the Response may contain a error message (returned by the remote signer) + * [state] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Add Version field to State, breaking the format of State as encoded on disk. - * [rpc] \#2298 `/abci_query` takes `prove` argument instead of `trusted` and switches the default + * [rpc] [\#2298](https://github.com/tendermint/tendermint/issues/2298) `/abci_query` takes `prove` argument instead of `trusted` and switches the default behaviour to `prove=false` - * [rpc] \#2654 Remove all `node_info.other.*_version` fields in `/status` and + * [rpc] [\#2654](https://github.com/tendermint/tendermint/issues/2654) Remove all `node_info.other.*_version` fields in `/status` and `/net_info` * Apps - * [abci] \#2298 ResponseQuery.Proof is now a structured merkle.Proof, not just + * [abci] [\#2298](https://github.com/tendermint/tendermint/issues/2298) ResponseQuery.Proof is now a structured merkle.Proof, not just arbitrary bytes - * [abci] \#2644 Add Version to Header and shift all fields by one - * [abci] \#2662 Bump the field numbers for some `ResponseInfo` fields to make room for + * [abci] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Add Version to Header and shift all fields by one + * [abci] [\#2662](https://github.com/tendermint/tendermint/issues/2662) Bump the field numbers for some `ResponseInfo` fields to make room for `AppVersion` * Go API - * [config] \#2232 timeouts as time.Duration, not ints - * [crypto/merkle & lite] \#2298 Various changes to accomodate General Merkle trees - * [crypto/merkle] \#2595 Remove all Hasher objects in favor of byte slices - * [crypto/merkle] \#2635 merkle.SimpleHashFromTwoHashes is no longer exported - * [node] Remove node.RunForever - * [rpc/client] \#2298 `ABCIQueryOptions.Trusted` -> `ABCIQueryOptions.Prove` - * [types] \#2298 Remove `Index` and `Total` fields from `TxProof`. - * [types] \#2598 `VoteTypeXxx` are now of type `SignedMsgType byte` and named `XxxType`, eg. `PrevoteType`, + * [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) timeouts as time.Duration, not ints + * [crypto/merkle & lite] [\#2298](https://github.com/tendermint/tendermint/issues/2298) Various changes to accomodate General Merkle trees + * [crypto/merkle] [\#2595](https://github.com/tendermint/tendermint/issues/2595) Remove all Hasher objects in favor of byte slices + * [crypto/merkle] [\#2635](https://github.com/tendermint/tendermint/issues/2635) merkle.SimpleHashFromTwoHashes is no longer exported + * [node] [\#2479](https://github.com/tendermint/tendermint/issues/2479) Remove node.RunForever + * [rpc/client] [\#2298](https://github.com/tendermint/tendermint/issues/2298) `ABCIQueryOptions.Trusted` -> `ABCIQueryOptions.Prove` + * [types] [\#2298](https://github.com/tendermint/tendermint/issues/2298) Remove `Index` and `Total` fields from `TxProof`. + * [types] [\#2598](https://github.com/tendermint/tendermint/issues/2598) `VoteTypeXxx` are now of type `SignedMsgType byte` and named `XxxType`, eg. `PrevoteType`, `PrecommitType`. * Blockchain Protocol * [types] Update SignBytes for `Vote`/`Proposal`/`Heartbeat`: - * \#2459 Use amino encoding instead of JSON in `SignBytes`. - * \#2598 Reorder fields and use fixed sized encoding. - * \#2598 Change `Type` field fromt `string` to `byte` and use new + * [\#2459](https://github.com/tendermint/tendermint/issues/2459) Use amino encoding instead of JSON in `SignBytes`. + * [\#2598](https://github.com/tendermint/tendermint/issues/2598) Reorder fields and use fixed sized encoding. + * [\#2598](https://github.com/tendermint/tendermint/issues/2598) Change `Type` field fromt `string` to `byte` and use new `SignedMsgType` to enumerate. - * [types] \#2512 Remove the pubkey field from the validator hash - * [types] \#2644 Add Version struct to Header - * [types] \#2609 ConsensusParams.Hash() is the hash of the amino encoded + * [types] [\#2512](https://github.com/tendermint/tendermint/issues/2512) Remove the pubkey field from the validator hash + * [types] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Add Version struct to Header + * [types] [\#2609](https://github.com/tendermint/tendermint/issues/2609) ConsensusParams.Hash() is the hash of the amino encoded struct instead of the Merkle tree of the fields - * [state] \#2587 Require block.Time of the fist block to be genesis time - * [state] \#2644 Require block.Version to match state.Version - * [types] \#2670 Header.Hash() builds Merkle tree out of fields in the same + * [state] [\#2587](https://github.com/tendermint/tendermint/issues/2587) Require block.Time of the fist block to be genesis time + * [state] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Require block.Version to match state.Version + * [types] [\#2670](https://github.com/tendermint/tendermint/issues/2670) Header.Hash() builds Merkle tree out of fields in the same order they appear in the header, instead of sorting by field name * P2P Protocol - * [p2p] \#2654 Add `ProtocolVersion` struct with protocol versions to top of + * [p2p] [\#2654](https://github.com/tendermint/tendermint/issues/2654) Add `ProtocolVersion` struct with protocol versions to top of DefaultNodeInfo and require `ProtocolVersion.Block` to match during peer handshake FEATURES: -- [abci] \#2557 Add `Codespace` field to `Response{CheckTx, DeliverTx, Query}` -- [abci] \#2662 Add `BlockVersion` and `P2PVersion` to `RequestInfo` -- [crypto/merkle] \#2298 General Merkle Proof scheme for chaining various types of Merkle trees together +- [abci] [\#2557](https://github.com/tendermint/tendermint/issues/2557) Add `Codespace` field to `Response{CheckTx, DeliverTx, Query}` +- [abci] [\#2662](https://github.com/tendermint/tendermint/issues/2662) Add `BlockVersion` and `P2PVersion` to `RequestInfo` +- [crypto/merkle] [\#2298](https://github.com/tendermint/tendermint/issues/2298) General Merkle Proof scheme for chaining various types of Merkle trees together IMPROVEMENTS: - Additional Metrics - [consensus] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) - [p2p] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) -- [config] \#2232 Added ValidateBasic method, which performs basic checks -- [crypto/ed25519] \#2558 Switch to use latest `golang.org/x/crypto` through our fork at +- [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) Added ValidateBasic method, which performs basic checks +- [crypto/ed25519] [\#2558](https://github.com/tendermint/tendermint/issues/2558) Switch to use latest `golang.org/x/crypto` through our fork at github.com/tendermint/crypto -- [tools] \#2238 Binary dependencies are now locked to a specific git commit +- [tools] [\#2238](https://github.com/tendermint/tendermint/issues/2238) Binary dependencies are now locked to a specific git commit BUG FIXES: -- [autofile] \#2428 Group.RotateFile need call Flush() before rename (@goolAdapter) -- [common] Fixed a bug in the `BitArray.Or` method -- [common] Fixed a bug in the `BitArray.Sub` method (@james-ray) -- [common] \#2534 Fix `BitArray.PickRandom` to choose uniformly from true bits +- [autofile] [\#2428](https://github.com/tendermint/tendermint/issues/2428) Group.RotateFile need call Flush() before rename (@goolAdapter) +- [common] [\#2533](https://github.com/tendermint/tendermint/issues/2533) Fixed a bug in the `BitArray.Or` method +- [common] [\#2506](https://github.com/tendermint/tendermint/issues/2506) Fixed a bug in the `BitArray.Sub` method (@james-ray) +- [common] [\#2534](https://github.com/tendermint/tendermint/issues/2534) Fix `BitArray.PickRandom` to choose uniformly from true bits - [consensus] [\#1690](https://github.com/tendermint/tendermint/issues/1690) Wait for timeoutPrecommit before starting next round - [consensus] [\#1745](https://github.com/tendermint/tendermint/issues/1745) Wait for Proposal or timeoutProposal before entering prevote -- [consensus] \#2642 Only propose ValidBlock, not LockedBlock -- [consensus] \#2642 Initialized ValidRound and LockedRound to -1 -- [consensus] \#1637 Limit the amount of evidence that can be included in a +- [consensus] [\#2642](https://github.com/tendermint/tendermint/issues/2642) Only propose ValidBlock, not LockedBlock +- [consensus] [\#2642](https://github.com/tendermint/tendermint/issues/2642) Initialized ValidRound and LockedRound to -1 +- [consensus] [\#1637](https://github.com/tendermint/tendermint/issues/1637) Limit the amount of evidence that can be included in a block -- [evidence] \#2515 Fix db iter leak (@goolAdapter) -- [libs/event] \#2518 Fix event concurrency flaw (@goolAdapter) -- [node] \#2434 Make node respond to signal interrupts while sleeping for genesis time -- [state] \#2616 Pass nil to NewValidatorSet() when genesis file's Validators field is nil -- [p2p] \#2555 Fix p2p switch FlushThrottle value (@goolAdapter) -- [p2p] \#2668 Reconnect to originally dialed address (not self-reported +- [evidence] [\#2515](https://github.com/tendermint/tendermint/issues/2515) Fix db iter leak (@goolAdapter) +- [libs/event] [\#2518](https://github.com/tendermint/tendermint/issues/2518) Fix event concurrency flaw (@goolAdapter) +- [node] [\#2434](https://github.com/tendermint/tendermint/issues/2434) Make node respond to signal interrupts while sleeping for genesis time +- [state] [\#2616](https://github.com/tendermint/tendermint/issues/2616) Pass nil to NewValidatorSet() when genesis file's Validators field is nil +- [p2p] [\#2555](https://github.com/tendermint/tendermint/issues/2555) Fix p2p switch FlushThrottle value (@goolAdapter) +- [p2p] [\#2668](https://github.com/tendermint/tendermint/issues/2668) Reconnect to originally dialed address (not self-reported address) for persistent peers diff --git a/UPGRADING.md b/UPGRADING.md index 81e56e588..cb0830a45 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -3,6 +3,82 @@ This guide provides steps to be followed when you upgrade your applications to a newer version of Tendermint Core. +## v0.26.0 + +New 0.26.0 release contains a lot of changes to core data types. It is not +compatible to the old versions and there is no straight forward way to update +old data to be compatible with the new version. + +To reset the state do: + +``` +$ tendermint unsafe_reset_all +``` + +Here we summarize some other notable changes to be mindful of. + +### Config Changes + +All timeouts must be changed from integers to strings with their duration, for +instance `flush_throttle_timeout = 100` would be changed to +`flush_throttle_timeout = "100ms"` and `timeout_propose = 3000` would be changed +to `timeout_propose = "3s"`. + +### RPC Changes + +The default behaviour of `/abci_query` has been changed to not return a proof, +and the name of the parameter that controls this has been changed from `trusted` +to `prove`. To get proofs with your queries, ensure you set `prove=true`. + +Various version fields like `amino_version`, `p2p_version`, `consensus_version`, +and `rpc_version` have been removed from the `node_info.other` and are +consolidated under the tendermint semantic version (ie. `node_info.version`) and +the new `block` and `p2p` protocol versions under `node_info.protocol_version`.. + +### ABCI Changes + +Field numbers were bumped in the `Header` and `ResponseInfo` messages to make +room for new `version` fields. It should be straight forward to recompile the +protobuf file for these changes. + +#### Proofs + +The `ResponseQuery.Proof` field is now structured as a `[]ProofOp` to support +generalized Merkle tree constructions where the leaves of one Merkle tree are +the root of another. If you don't need this functionaluty, and you used to +return `` here, you should instead return a single `ProofOp` with +just the `Data` field set: + +``` +[]ProofOp{ + ProofOp{ + Data: , + } +} +``` + +For more information, see: + +- [ADR-026](https://github.com/tendermint/tendermint/blob/30519e8361c19f4bf320ef4d26288ebc621ad725/docs/architecture/adr-026-general-merkle-proof.md) +- [Relevant ABCI + documentation](https://github.com/tendermint/tendermint/blob/30519e8361c19f4bf320ef4d26288ebc621ad725/docs/spec/abci/apps.md#query-proofs) +- [Description of + keys](https://github.com/tendermint/tendermint/blob/30519e8361c19f4bf320ef4d26288ebc621ad725/crypto/merkle/proof_key_path.go#L14) + +### Go API Changes + +#### crypto.merkle + +The `merkle.Hasher` interface was removed. Functions which used to take `Hasher` +now simply take `[]byte`. This means that any objects being Merklized should be +serialized before they are passed in. + +#### node + +The `node.RunForever` function was removed. Signal handling and running forever +should instead be explicitly configured by the caller. See how we do it +[here](https://github.com/tendermint/tendermint/blob/30519e8361c19f4bf320ef4d26288ebc621ad725/cmd/tendermint/commands/run_node.go#L60). + ## v0.25.0 This release has minimal impact. diff --git a/version/version.go b/version/version.go index 19b3f3da7..b4664fd77 100644 --- a/version/version.go +++ b/version/version.go @@ -18,10 +18,10 @@ const ( // TMCoreSemVer is the current version of Tendermint Core. // It's the Semantic Version of the software. // Must be a string because scripts like dist.sh read this file. - TMCoreSemVer = "0.25.0" + TMCoreSemVer = "0.26.0" // ABCISemVer is the semantic version of the ABCI library - ABCISemVer = "0.14.0" + ABCISemVer = "0.15.0" ABCIVersion = ABCISemVer ) From fe1d59ab7b80c04ddaaa60f93b0f8656c1ed8f4b Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 22 Oct 2018 17:55:49 -0400 Subject: [PATCH 11/35] Set protocol versions in NodeInfo from state (#2686) * use types.NewValidator * node: set p2p.ProtocolVersion from state, not globals --- benchmarks/codec_test.go | 2 +- node/node.go | 6 +++++- p2p/node_info.go | 20 ++++++++++++-------- p2p/peer_test.go | 2 +- p2p/test_util.go | 2 +- state/state.go | 11 +---------- types/protobuf_test.go | 18 +++--------------- 7 files changed, 24 insertions(+), 37 deletions(-) diff --git a/benchmarks/codec_test.go b/benchmarks/codec_test.go index 2be1db156..3e0270286 100644 --- a/benchmarks/codec_test.go +++ b/benchmarks/codec_test.go @@ -14,7 +14,7 @@ import ( func testNodeInfo(id p2p.ID) p2p.DefaultNodeInfo { return p2p.DefaultNodeInfo{ - ProtocolVersion: p2p.InitProtocolVersion, + ProtocolVersion: p2p.ProtocolVersion{1, 2, 3}, ID_: id, Moniker: "SOMENAME", Network: "SOMENAME", diff --git a/node/node.go b/node/node.go index 522f18e91..f62a8b472 100644 --- a/node/node.go +++ b/node/node.go @@ -367,7 +367,11 @@ func NewNode(config *cfg.Config, nodeKey.ID(), txIndexer, genDoc.ChainID, - p2p.ProtocolVersionWithApp(state.Version.Consensus.App), + p2p.NewProtocolVersion( + version.P2PProtocol, // global + state.Version.Consensus.Block, + state.Version.Consensus.App, + ), ) ) diff --git a/p2p/node_info.go b/p2p/node_info.go index 1d408eb68..e46174e07 100644 --- a/p2p/node_info.go +++ b/p2p/node_info.go @@ -49,16 +49,20 @@ type ProtocolVersion struct { App version.Protocol `json:"app"` } -// InitProtocolVersion populates the Block and P2P versions, but not the App. -var InitProtocolVersion = ProtocolVersionWithApp(0) +// defaultProtocolVersion populates the Block and P2P versions using +// the global values, but not the App. +var defaultProtocolVersion = NewProtocolVersion( + version.P2PProtocol, + version.BlockProtocol, + 0, +) -// ProtocolVersionWithApp returns a fully populated ProtocolVersion -// using the provided App version and the Block and P2P versions defined in the `version` package. -func ProtocolVersionWithApp(appVersion version.Protocol) ProtocolVersion { +// NewProtocolVersion returns a fully populated ProtocolVersion. +func NewProtocolVersion(p2p, block, app version.Protocol) ProtocolVersion { return ProtocolVersion{ - P2P: version.P2PProtocol, - Block: version.BlockProtocol, - App: appVersion, + P2P: p2p, + Block: block, + App: app, } } diff --git a/p2p/peer_test.go b/p2p/peer_test.go index 02f1d2c0f..d3d9f0c72 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -207,7 +207,7 @@ func (rp *remotePeer) accept(l net.Listener) { func (rp *remotePeer) nodeInfo(l net.Listener) NodeInfo { return DefaultNodeInfo{ - ProtocolVersion: InitProtocolVersion, + ProtocolVersion: defaultProtocolVersion, ID_: rp.Addr().ID, ListenAddr: l.Addr().String(), Network: "testing", diff --git a/p2p/test_util.go b/p2p/test_util.go index e1f7b5040..d72c0c760 100644 --- a/p2p/test_util.go +++ b/p2p/test_util.go @@ -249,7 +249,7 @@ func testNodeInfo(id ID, name string) NodeInfo { func testNodeInfoWithNetwork(id ID, name, network string) NodeInfo { return DefaultNodeInfo{ - ProtocolVersion: InitProtocolVersion, + ProtocolVersion: defaultProtocolVersion, ID_: id, ListenAddr: fmt.Sprintf("127.0.0.1:%d", cmn.RandIntn(64512)+1023), Network: network, diff --git a/state/state.go b/state/state.go index 5c1b68a26..d6ec6f0be 100644 --- a/state/state.go +++ b/state/state.go @@ -222,7 +222,6 @@ func MakeGenesisState(genDoc *types.GenesisDoc) (State, error) { return State{}, fmt.Errorf("Error in genesis file: %v", err) } - // Make validators slice var validatorSet, nextValidatorSet *types.ValidatorSet if genDoc.Validators == nil { validatorSet = types.NewValidatorSet(nil) @@ -230,15 +229,7 @@ func MakeGenesisState(genDoc *types.GenesisDoc) (State, error) { } else { validators := make([]*types.Validator, len(genDoc.Validators)) for i, val := range genDoc.Validators { - pubKey := val.PubKey - address := pubKey.Address() - - // Make validator - validators[i] = &types.Validator{ - Address: address, - PubKey: pubKey, - VotingPower: val.Power, - } + validators[i] = types.NewValidator(val.PubKey, val.Power) } validatorSet = types.NewValidatorSet(validators) nextValidatorSet = types.NewValidatorSet(validators).CopyIncrementAccum(1) diff --git a/types/protobuf_test.go b/types/protobuf_test.go index f8682abf8..c940f1b42 100644 --- a/types/protobuf_test.go +++ b/types/protobuf_test.go @@ -30,17 +30,9 @@ func TestABCIValidators(t *testing.T) { pkEd := ed25519.GenPrivKey().PubKey() // correct validator - tmValExpected := &Validator{ - Address: pkEd.Address(), - PubKey: pkEd, - VotingPower: 10, - } + tmValExpected := NewValidator(pkEd, 10) - tmVal := &Validator{ - Address: pkEd.Address(), - PubKey: pkEd, - VotingPower: 10, - } + tmVal := NewValidator(pkEd, 10) abciVal := TM2PB.ValidatorUpdate(tmVal) tmVals, err := PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{abciVal}) @@ -127,11 +119,7 @@ func TestABCIValidatorFromPubKeyAndPower(t *testing.T) { func TestABCIValidatorWithoutPubKey(t *testing.T) { pkEd := ed25519.GenPrivKey().PubKey() - abciVal := TM2PB.Validator(&Validator{ - Address: pkEd.Address(), - PubKey: pkEd, - VotingPower: 10, - }) + abciVal := TM2PB.Validator(NewValidator(pkEd, 10)) // pubkey must be nil tmValExpected := abci.Validator{ From be929acd6a726b322fe9dcc61fc6713dfc668349 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 23 Oct 2018 13:21:47 -0400 Subject: [PATCH 12/35] Update to Amino v0.13.0-rc0 (#2687) * types: test tm2pm on fully populated header * upgrade for amino v0.13.0-rc0 * fix lint * comment out final test --- Gopkg.lock | 6 ++-- Gopkg.toml | 2 +- state/state.go | 33 +++++++---------- types/block.go | 32 ++++++++++++++--- types/block_test.go | 18 ++++++---- types/evidence.go | 2 +- types/evidence_test.go | 2 +- types/proto3/block.pb.go | 63 ++++++++++++++++---------------- types/proto3/block.proto | 11 +++--- types/protobuf.go | 13 ++++--- types/protobuf_test.go | 78 ++++++++++++++++++++++++++++++++++------ types/results_test.go | 2 +- types/vote.go | 2 +- types/vote_test.go | 26 +++++++------- 14 files changed, 187 insertions(+), 103 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 0f70bb2f7..d5d6c1b28 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -365,12 +365,12 @@ revision = "e5840949ff4fff0c56f9b6a541e22b63581ea9df" [[projects]] - digest = "1:e0a2a4be1e20c305badc2b0a7a9ab7fef6da500763bec23ab81df3b5f9eec9ee" + digest = "1:3ff2c9d4def5ec999ab672b9059d0ba41a1351913ea78e63b5402e4ba4ef8da4" name = "github.com/tendermint/go-amino" packages = ["."] pruneopts = "UT" - revision = "a8328986c1608950fa5d3d1c0472cccc4f8fc02c" - version = "v0.12.0-rc0" + revision = "ff047d9e357e66d937d6900d4a2e04501cc62c70" + version = "v0.13.0-rc0" [[projects]] digest = "1:72b71e3a29775e5752ed7a8012052a3dee165e27ec18cedddae5288058f09acf" diff --git a/Gopkg.toml b/Gopkg.toml index 07ff3c534..622ca00e0 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -58,7 +58,7 @@ [[constraint]] name = "github.com/tendermint/go-amino" - version = "v0.12.0-rc0" + version = "v0.13.0-rc0" [[constraint]] name = "google.golang.org/grpc" diff --git a/state/state.go b/state/state.go index d6ec6f0be..0dbd718da 100644 --- a/state/state.go +++ b/state/state.go @@ -128,7 +128,7 @@ func (state State) IsEmpty() bool { // MakeBlock builds a block from the current state with the given txs, commit, // and evidence. Note it also takes a proposerAddress because the state does not -// track rounds, and hence doesn't know the correct proposer. TODO: alleviate this! +// track rounds, and hence does not know the correct proposer. TODO: fix this! func (state State) MakeBlock( height int64, txs []types.Tx, @@ -140,29 +140,22 @@ func (state State) MakeBlock( // Build base block with block data. block := types.MakeBlock(height, txs, commit, evidence) - // Fill rest of header with state data. - block.Version = state.Version.Consensus - block.ChainID = state.ChainID - - // Set time + // Set time. + var timestamp time.Time if height == 1 { - block.Time = state.LastBlockTime // genesis time + timestamp = state.LastBlockTime // genesis time } else { - block.Time = MedianTime(commit, state.LastValidators) + timestamp = MedianTime(commit, state.LastValidators) } - block.LastBlockID = state.LastBlockID - block.TotalTxs = state.LastBlockTotalTx + block.NumTxs - - block.ValidatorsHash = state.Validators.Hash() - block.NextValidatorsHash = state.NextValidators.Hash() - block.ConsensusHash = state.ConsensusParams.Hash() - block.AppHash = state.AppHash - block.LastResultsHash = state.LastResultsHash - - // NOTE: we can't use the state.Validators because we don't - // IncrementAccum for rounds there. - block.ProposerAddress = proposerAddress + // Fill rest of header with state data. + block.Header.Populate( + state.Version.Consensus, state.ChainID, + timestamp, state.LastBlockID, state.LastBlockTotalTx+block.NumTxs, + state.Validators.Hash(), state.NextValidators.Hash(), + state.ConsensusParams.Hash(), state.AppHash, state.LastResultsHash, + proposerAddress, + ) return block, block.MakePartSet(types.BlockPartSizeBytes) } diff --git a/types/block.go b/types/block.go index 2a5b5fc4a..ce605263c 100644 --- a/types/block.go +++ b/types/block.go @@ -15,7 +15,7 @@ import ( const ( // MaxHeaderBytes is a maximum header size (including amino overhead). - MaxHeaderBytes int64 = 534 + MaxHeaderBytes int64 = 537 // MaxAminoOverheadForBlock - maximum amino overhead to encode a block (up to // MaxBlockSizeBytes in size) not including it's parts except Data. @@ -257,11 +257,11 @@ func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 { //----------------------------------------------------------------------------- -// Header defines the structure of a Tendermint block header +// Header defines the structure of a Tendermint block header. // NOTE: changes to the Header should be duplicated in: -// - header.Hash() -// - abci.Header -// - /docs/spec/blockchain/blockchain.md +// - header.Hash() +// - abci.Header +// - /docs/spec/blockchain/blockchain.md type Header struct { // basic block info Version version.Consensus `json:"version"` @@ -290,6 +290,28 @@ type Header struct { ProposerAddress Address `json:"proposer_address"` // original proposer of the block } +// Populate the Header with state-derived data. +// Call this after MakeBlock to complete the Header. +func (h *Header) Populate( + version version.Consensus, chainID string, + timestamp time.Time, lastBlockID BlockID, totalTxs int64, + valHash, nextValHash []byte, + consensusHash, appHash, lastResultsHash []byte, + proposerAddress Address, +) { + h.Version = version + h.ChainID = chainID + h.Time = timestamp + h.LastBlockID = lastBlockID + h.TotalTxs = totalTxs + h.ValidatorsHash = valHash + h.NextValidatorsHash = nextValHash + h.ConsensusHash = consensusHash + h.AppHash = appHash + h.LastResultsHash = lastResultsHash + h.ProposerAddress = proposerAddress +} + // Hash returns the hash of the header. // It computes a Merkle tree from the header fields // ordered as they appear in the Header. diff --git a/types/block_test.go b/types/block_test.go index d268e411e..e34ba29b8 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -242,11 +242,15 @@ func TestMaxHeaderBytes(t *testing.T) { maxChainID += "𠜎" } + // time is varint encoded so need to pick the max. + // year int, month Month, day, hour, min, sec, nsec int, loc *Location + timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) + h := Header{ Version: version.Consensus{math.MaxInt64, math.MaxInt64}, ChainID: maxChainID, Height: math.MaxInt64, - Time: time.Now().UTC(), + Time: timestamp, NumTxs: math.MaxInt64, TotalTxs: math.MaxInt64, LastBlockID: makeBlockID(make([]byte, tmhash.Size), math.MaxInt64, make([]byte, tmhash.Size)), @@ -288,9 +292,9 @@ func TestBlockMaxDataBytes(t *testing.T) { }{ 0: {-10, 1, 0, true, 0}, 1: {10, 1, 0, true, 0}, - 2: {744, 1, 0, true, 0}, - 3: {745, 1, 0, false, 0}, - 4: {746, 1, 0, false, 1}, + 2: {750, 1, 0, true, 0}, + 3: {751, 1, 0, false, 0}, + 4: {752, 1, 0, false, 1}, } for i, tc := range testCases { @@ -316,9 +320,9 @@ func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) { }{ 0: {-10, 1, true, 0}, 1: {10, 1, true, 0}, - 2: {826, 1, true, 0}, - 3: {827, 1, false, 0}, - 4: {828, 1, false, 1}, + 2: {833, 1, true, 0}, + 3: {834, 1, false, 0}, + 4: {835, 1, false, 1}, } for i, tc := range testCases { diff --git a/types/evidence.go b/types/evidence.go index 57523ab1e..6d42ed22c 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -14,7 +14,7 @@ import ( const ( // MaxEvidenceBytes is a maximum size of any evidence (including amino overhead). - MaxEvidenceBytes int64 = 440 + MaxEvidenceBytes int64 = 444 ) // ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid. diff --git a/types/evidence_test.go b/types/evidence_test.go index a8d7efff8..79805691c 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -61,7 +61,7 @@ func TestEvidence(t *testing.T) { {vote1, makeVote(val, chainID, 0, 10, 3, 1, blockID2), false}, // wrong round {vote1, makeVote(val, chainID, 0, 10, 2, 2, blockID2), false}, // wrong step {vote1, makeVote(val2, chainID, 0, 10, 2, 1, blockID), false}, // wrong validator - {vote1, badVote, false}, // signed by wrong key + {vote1, badVote, false}, // signed by wrong key } pubKey := val.GetPubKey() diff --git a/types/proto3/block.pb.go b/types/proto3/block.pb.go index 446b39197..7efc7ca7d 100644 --- a/types/proto3/block.pb.go +++ b/types/proto3/block.pb.go @@ -244,13 +244,14 @@ func (m *Version) GetApp() uint64 { return 0 } -// Timestamp wraps how amino encodes time. Note that this is different from the protobuf well-known type -// protobuf/timestamp.proto in the sense that there seconds and nanos are varint encoded. See: +// Timestamp wraps how amino encodes time. +// This is the protobuf well-known type protobuf/timestamp.proto +// See: // https://github.com/google/protobuf/blob/d2980062c859649523d5fd51d6b55ab310e47482/src/google/protobuf/timestamp.proto#L123-L135 -// Also nanos do not get skipped if they are zero in amino. +// NOTE/XXX: nanos do not get skipped if they are zero in amino. type Timestamp struct { - Seconds int64 `protobuf:"fixed64,1,opt,name=seconds" json:"seconds,omitempty"` - Nanos int32 `protobuf:"fixed32,2,opt,name=nanos" json:"nanos,omitempty"` + Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` + Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` } func (m *Timestamp) Reset() { *m = Timestamp{} } @@ -285,31 +286,31 @@ func init() { proto.RegisterFile("block.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ // 443 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0xcd, 0x6a, 0xdb, 0x40, - 0x10, 0x46, 0x8d, 0x62, 0xc7, 0x23, 0x3b, 0x76, 0x86, 0xb6, 0x88, 0x9e, 0x8c, 0x68, 0x8b, 0x7b, + 0x10, 0x46, 0xb5, 0x6c, 0xc7, 0x23, 0x3b, 0x4e, 0x86, 0xb6, 0x88, 0x9e, 0x8c, 0x68, 0x8b, 0x7b, 0x31, 0x24, 0x39, 0x94, 0xd2, 0x93, 0x6b, 0x17, 0x12, 0x28, 0x21, 0x6c, 0x8d, 0xef, 0x1b, 0x6b, - 0xa9, 0x45, 0x2d, 0xad, 0xd0, 0xac, 0x4b, 0xde, 0xb0, 0xaf, 0x55, 0x66, 0x56, 0x52, 0x2d, 0x93, - 0x93, 0xf7, 0xfb, 0x99, 0x6f, 0x76, 0xc7, 0x23, 0x88, 0x9e, 0xf6, 0x76, 0xfb, 0x7b, 0x5e, 0x56, - 0xd6, 0x59, 0xec, 0xc9, 0xcf, 0x6d, 0xf2, 0x05, 0x46, 0x8f, 0xba, 0x72, 0x3f, 0x8d, 0xbb, 0x33, - 0x3a, 0x35, 0x15, 0xbe, 0x86, 0xf3, 0xb5, 0x75, 0x7a, 0x1f, 0x07, 0xd3, 0x60, 0x76, 0xa5, 0x3c, - 0x40, 0x84, 0xf0, 0x4e, 0xd3, 0x2e, 0x7e, 0x35, 0x0d, 0x66, 0x43, 0x25, 0xe7, 0x64, 0x03, 0xfd, - 0x6f, 0x9c, 0x78, 0xbf, 0x6a, 0xe5, 0xe0, 0xbf, 0x8c, 0x9f, 0x21, 0xe2, 0x64, 0xf2, 0xb9, 0x52, - 0x19, 0xdd, 0xbc, 0xf1, 0xed, 0x6f, 0xe7, 0x9d, 0xa6, 0xea, 0xd8, 0x99, 0xfc, 0x0d, 0xa1, 0x57, - 0x5f, 0xe6, 0x13, 0xf4, 0x37, 0xa6, 0xa2, 0xcc, 0x16, 0x12, 0x1d, 0xdd, 0x8c, 0x9b, 0xfa, 0x9a, - 0x56, 0x8d, 0x8e, 0x31, 0xf4, 0x97, 0x3b, 0x9d, 0x15, 0xf7, 0x2b, 0x69, 0x35, 0x50, 0x0d, 0xc4, - 0xb7, 0x1c, 0x97, 0xfd, 0xda, 0xb9, 0xf8, 0x6c, 0x1a, 0xcc, 0x50, 0xd5, 0x08, 0x3f, 0x40, 0xb8, - 0xce, 0x72, 0x13, 0x87, 0x92, 0x7c, 0xd5, 0x24, 0x33, 0x47, 0x4e, 0xe7, 0xa5, 0x12, 0x99, 0xcb, - 0x1f, 0x0e, 0xf9, 0xfa, 0x99, 0xe2, 0x73, 0x5f, 0xee, 0x11, 0xbe, 0x83, 0x0b, 0x99, 0x0d, 0x2b, - 0x3d, 0x51, 0x5a, 0x8c, 0xd7, 0x10, 0xfd, 0xd0, 0xe4, 0xea, 0xf1, 0xc4, 0xfd, 0xee, 0xdd, 0x6b, - 0x5a, 0x1d, 0x7b, 0xf0, 0x23, 0x5c, 0x32, 0x5c, 0xda, 0x3c, 0xcf, 0x9c, 0x0c, 0xf3, 0x42, 0x86, - 0x79, 0xc2, 0x72, 0xdb, 0x95, 0x76, 0x5a, 0x1c, 0x03, 0x71, 0xb4, 0x98, 0x33, 0x36, 0x7a, 0x9f, - 0xa5, 0xda, 0xd9, 0x8a, 0xc4, 0x01, 0x3e, 0xa3, 0xcb, 0xe2, 0x1c, 0xf0, 0xc1, 0x3c, 0xbb, 0x13, - 0x6f, 0x24, 0xde, 0x17, 0x14, 0x7c, 0x0f, 0xa3, 0xa5, 0x2d, 0xc8, 0x14, 0x74, 0xf0, 0xd6, 0xa1, - 0x58, 0xbb, 0x24, 0xff, 0x03, 0x8b, 0xb2, 0x14, 0x7d, 0x24, 0x7a, 0x03, 0x71, 0x06, 0x63, 0x7e, - 0x85, 0x32, 0x74, 0xd8, 0x3b, 0x9f, 0x70, 0x29, 0x8e, 0x53, 0x1a, 0x13, 0x18, 0x7e, 0xff, 0x93, - 0xa5, 0xa6, 0xd8, 0x1a, 0xb1, 0x8d, 0xc5, 0xd6, 0xe1, 0x38, 0xed, 0xb1, 0xb2, 0xa5, 0x25, 0x53, - 0x2d, 0xd2, 0xb4, 0x32, 0x44, 0xf1, 0xc4, 0xa7, 0x9d, 0xd0, 0xc9, 0x75, 0xbb, 0x3e, 0xbc, 0xd6, - 0x32, 0x69, 0xd9, 0xa3, 0x50, 0x79, 0x80, 0x13, 0x38, 0x5b, 0x94, 0xa5, 0x2c, 0x4c, 0xa8, 0xf8, - 0x98, 0x7c, 0x85, 0x41, 0xbb, 0x00, 0xfc, 0x22, 0x32, 0x5b, 0x5b, 0xa4, 0x24, 0x65, 0x13, 0xd5, - 0x40, 0x8e, 0x2b, 0x74, 0x61, 0x49, 0x4a, 0xc7, 0xca, 0x83, 0xa7, 0xfa, 0xa3, 0xfa, 0x17, 0x00, - 0x00, 0xff, 0xff, 0xd5, 0x8b, 0x28, 0x26, 0x6a, 0x03, 0x00, 0x00, + 0xa9, 0x45, 0x2d, 0xad, 0xd0, 0xac, 0x4b, 0xde, 0xb0, 0xaf, 0x55, 0x66, 0x56, 0x52, 0x23, 0x93, + 0x93, 0xf7, 0xfb, 0x99, 0x6f, 0x76, 0xc7, 0x23, 0x88, 0x1e, 0x0f, 0x76, 0xf7, 0x7b, 0x51, 0x56, + 0xd6, 0x59, 0x1c, 0xc8, 0xcf, 0x4d, 0xf2, 0x05, 0x26, 0x0f, 0xba, 0x72, 0x3f, 0x8d, 0xbb, 0x35, + 0x3a, 0x35, 0x15, 0xbe, 0x86, 0xfe, 0xc6, 0x3a, 0x7d, 0x88, 0x83, 0x59, 0x30, 0xbf, 0x54, 0x1e, + 0x20, 0x42, 0x78, 0xab, 0x69, 0x1f, 0xbf, 0x9a, 0x05, 0xf3, 0xb1, 0x92, 0x73, 0xb2, 0x85, 0xe1, + 0x37, 0x4e, 0xbc, 0x5b, 0xb7, 0x72, 0xf0, 0x5f, 0xc6, 0xcf, 0x10, 0x71, 0x32, 0xf9, 0x5c, 0xa9, + 0x8c, 0xae, 0xdf, 0xf8, 0xf6, 0x37, 0x8b, 0x4e, 0x53, 0xf5, 0xdc, 0x99, 0xfc, 0x0d, 0x61, 0x50, + 0x5f, 0xe6, 0x13, 0x0c, 0xb7, 0xa6, 0xa2, 0xcc, 0x16, 0x12, 0x1d, 0x5d, 0x4f, 0x9b, 0xfa, 0x9a, + 0x56, 0x8d, 0x8e, 0x31, 0x0c, 0x57, 0x7b, 0x9d, 0x15, 0x77, 0x6b, 0x69, 0x35, 0x52, 0x0d, 0xc4, + 0xb7, 0x1c, 0x97, 0xfd, 0xda, 0xbb, 0xb8, 0x37, 0x0b, 0xe6, 0xa8, 0x6a, 0x84, 0x1f, 0x20, 0xdc, + 0x64, 0xb9, 0x89, 0x43, 0x49, 0xbe, 0x6c, 0x92, 0x99, 0x23, 0xa7, 0xf3, 0x52, 0x89, 0xcc, 0xe5, + 0xf7, 0xc7, 0x7c, 0xf3, 0x44, 0x71, 0xdf, 0x97, 0x7b, 0x84, 0xef, 0xe0, 0x4c, 0x66, 0xc3, 0xca, + 0x40, 0x94, 0x16, 0xe3, 0x15, 0x44, 0x3f, 0x34, 0xb9, 0x7a, 0x3c, 0xf1, 0xb0, 0x7b, 0xf7, 0x9a, + 0x56, 0xcf, 0x3d, 0xf8, 0x11, 0xce, 0x19, 0xae, 0x6c, 0x9e, 0x67, 0x4e, 0x86, 0x79, 0x26, 0xc3, + 0x3c, 0x61, 0xb9, 0xed, 0x5a, 0x3b, 0x2d, 0x8e, 0x91, 0x38, 0x5a, 0xcc, 0x19, 0x5b, 0x7d, 0xc8, + 0x52, 0xed, 0x6c, 0x45, 0xe2, 0x00, 0x9f, 0xd1, 0x65, 0x71, 0x01, 0x78, 0x6f, 0x9e, 0xdc, 0x89, + 0x37, 0x12, 0xef, 0x0b, 0x0a, 0xbe, 0x87, 0xc9, 0xca, 0x16, 0x64, 0x0a, 0x3a, 0x7a, 0xeb, 0x58, + 0xac, 0x5d, 0x92, 0xff, 0x81, 0x65, 0x59, 0x8a, 0x3e, 0x11, 0xbd, 0x81, 0x38, 0x87, 0x29, 0xbf, + 0x42, 0x19, 0x3a, 0x1e, 0x9c, 0x4f, 0x38, 0x17, 0xc7, 0x29, 0x8d, 0x09, 0x8c, 0xbf, 0xff, 0xc9, + 0x52, 0x53, 0xec, 0x8c, 0xd8, 0xa6, 0x62, 0xeb, 0x70, 0x9c, 0xf6, 0x50, 0xd9, 0xd2, 0x92, 0xa9, + 0x96, 0x69, 0x5a, 0x19, 0xa2, 0xf8, 0xc2, 0xa7, 0x9d, 0xd0, 0xc9, 0x55, 0xbb, 0x3e, 0xbc, 0xd6, + 0x32, 0x69, 0xd9, 0xa3, 0x50, 0x79, 0x80, 0x17, 0xd0, 0x5b, 0x96, 0xa5, 0x2c, 0x4c, 0xa8, 0xf8, + 0x98, 0x7c, 0x85, 0x51, 0xbb, 0x00, 0xfc, 0x22, 0x32, 0x3b, 0x5b, 0xa4, 0x24, 0x65, 0x3d, 0xd5, + 0x40, 0x8e, 0x2b, 0x74, 0x61, 0x49, 0x4a, 0xfb, 0xca, 0x83, 0xc7, 0xfa, 0xa3, 0xfa, 0x17, 0x00, + 0x00, 0xff, 0xff, 0x8f, 0x82, 0xc0, 0x0c, 0x6a, 0x03, 0x00, 0x00, } diff --git a/types/proto3/block.proto b/types/proto3/block.proto index dd64a9e98..1c76746c2 100644 --- a/types/proto3/block.proto +++ b/types/proto3/block.proto @@ -46,11 +46,12 @@ message Version { uint64 App = 2; } -// Timestamp wraps how amino encodes time. Note that this is different from the protobuf well-known type -// protobuf/timestamp.proto in the sense that there seconds and nanos are varint encoded. See: +// Timestamp wraps how amino encodes time. +// This is the protobuf well-known type protobuf/timestamp.proto +// See: // https://github.com/google/protobuf/blob/d2980062c859649523d5fd51d6b55ab310e47482/src/google/protobuf/timestamp.proto#L123-L135 -// Also nanos do not get skipped if they are zero in amino. +// NOTE/XXX: nanos do not get skipped if they are zero in amino. message Timestamp { - sfixed64 seconds = 1; - sfixed32 nanos = 2; + int64 seconds = 1; + int32 nanos = 2; } diff --git a/types/protobuf.go b/types/protobuf.go index c9c429c80..e1ec81e82 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -34,6 +34,10 @@ type tm2pb struct{} func (tm2pb) Header(header *Header) abci.Header { return abci.Header{ + Version: abci.Version{ + Block: header.Version.Block.Uint64(), + App: header.Version.App.Uint64(), + }, ChainID: header.ChainID, Height: header.Height, Time: header.Time, @@ -45,10 +49,11 @@ func (tm2pb) Header(header *Header) abci.Header { LastCommitHash: header.LastCommitHash, DataHash: header.DataHash, - ValidatorsHash: header.ValidatorsHash, - ConsensusHash: header.ConsensusHash, - AppHash: header.AppHash, - LastResultsHash: header.LastResultsHash, + ValidatorsHash: header.ValidatorsHash, + NextValidatorsHash: header.NextValidatorsHash, + ConsensusHash: header.ConsensusHash, + AppHash: header.AppHash, + LastResultsHash: header.LastResultsHash, EvidenceHash: header.EvidenceHash, ProposerAddress: header.ProposerAddress, diff --git a/types/protobuf_test.go b/types/protobuf_test.go index c940f1b42..7e7f55a1d 100644 --- a/types/protobuf_test.go +++ b/types/protobuf_test.go @@ -4,12 +4,16 @@ import ( "testing" "time" + "github.com/golang/protobuf/proto" "github.com/stretchr/testify/assert" + + "github.com/tendermint/go-amino" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/secp256k1" - tmtime "github.com/tendermint/tendermint/types/time" + "github.com/tendermint/tendermint/version" ) func TestABCIPubKey(t *testing.T) { @@ -67,17 +71,71 @@ func TestABCIConsensusParams(t *testing.T) { assert.Equal(t, *cp, cp2) } -func TestABCIHeader(t *testing.T) { - header := &Header{ - Height: int64(3), - Time: tmtime.Now(), - NumTxs: int64(10), - ProposerAddress: []byte("cloak"), +func newHeader( + height, numTxs int64, + commitHash, dataHash, evidenceHash []byte, +) *Header { + return &Header{ + Height: height, + NumTxs: numTxs, + LastCommitHash: commitHash, + DataHash: dataHash, + EvidenceHash: evidenceHash, } - abciHeader := TM2PB.Header(header) +} + +func TestABCIHeader(t *testing.T) { + // build a full header + var height int64 = 5 + var numTxs int64 = 3 + header := newHeader( + height, numTxs, + []byte("lastCommitHash"), []byte("dataHash"), []byte("evidenceHash"), + ) + protocolVersion := version.Consensus{7, 8} + timestamp := time.Now() + lastBlockID := BlockID{ + Hash: []byte("hash"), + PartsHeader: PartSetHeader{ + Total: 10, + Hash: []byte("hash"), + }, + } + var totalTxs int64 = 100 + header.Populate( + protocolVersion, "chainID", + timestamp, lastBlockID, totalTxs, + []byte("valHash"), []byte("nextValHash"), + []byte("consHash"), []byte("appHash"), []byte("lastResultsHash"), + []byte("proposerAddress"), + ) + + cdc := amino.NewCodec() + headerBz := cdc.MustMarshalBinaryBare(header) + + pbHeader := TM2PB.Header(header) + pbHeaderBz, err := proto.Marshal(&pbHeader) + assert.NoError(t, err) + + // assert some fields match + assert.EqualValues(t, protocolVersion.Block, pbHeader.Version.Block) + assert.EqualValues(t, protocolVersion.App, pbHeader.Version.App) + assert.EqualValues(t, "chainID", pbHeader.ChainID) + assert.EqualValues(t, height, pbHeader.Height) + assert.EqualValues(t, timestamp, pbHeader.Time) + assert.EqualValues(t, numTxs, pbHeader.NumTxs) + assert.EqualValues(t, totalTxs, pbHeader.TotalTxs) + assert.EqualValues(t, lastBlockID.Hash, pbHeader.LastBlockId.Hash) + assert.EqualValues(t, []byte("lastCommitHash"), pbHeader.LastCommitHash) + assert.Equal(t, []byte("proposerAddress"), pbHeader.ProposerAddress) + + // assert the encodings match + // NOTE: they don't yet because Amino encodes + // int64 as zig-zag and we're using non-zigzag in the protobuf. + // See https://github.com/tendermint/tendermint/issues/2682 + _, _ = headerBz, pbHeaderBz + // assert.EqualValues(t, headerBz, pbHeaderBz) - assert.Equal(t, int64(3), abciHeader.Height) - assert.Equal(t, []byte("cloak"), abciHeader.ProposerAddress) } func TestABCIEvidence(t *testing.T) { diff --git a/types/results_test.go b/types/results_test.go index 808033850..4e57e5804 100644 --- a/types/results_test.go +++ b/types/results_test.go @@ -43,7 +43,7 @@ func TestABCIResults(t *testing.T) { } } -func TestABCIBytes(t *testing.T) { +func TestABCIResultsBytes(t *testing.T) { results := NewResults([]*abci.ResponseDeliverTx{ {Code: 0, Data: []byte{}}, {Code: 0, Data: []byte("one")}, diff --git a/types/vote.go b/types/vote.go index 2d70e21b2..2a7133099 100644 --- a/types/vote.go +++ b/types/vote.go @@ -12,7 +12,7 @@ import ( const ( // MaxVoteBytes is a maximum vote size (including amino overhead). - MaxVoteBytes int64 = 200 + MaxVoteBytes int64 = 203 ) var ( diff --git a/types/vote_test.go b/types/vote_test.go index 2172f0600..3b2f08488 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/tmhash" - tmtime "github.com/tendermint/tendermint/types/time" ) func examplePrevote() *Vote { @@ -63,13 +62,13 @@ func TestVoteSignableTestVectors(t *testing.T) { { CanonicalizeVote("", &Vote{}), // NOTE: Height and Round are skipped here. This case needs to be considered while parsing. - []byte{0xb, 0x22, 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, + // []byte{0x22, 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, + []byte{0x22, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, }, // with proper (fixed size) height and round (PreCommit): { CanonicalizeVote("", &Vote{Height: 1, Round: 1, Type: PrecommitType}), []byte{ - 0x1f, // total length 0x8, // (field_number << 3) | wire_type 0x2, // PrecommitType 0x11, // (field_number << 3) | wire_type @@ -78,13 +77,12 @@ func TestVoteSignableTestVectors(t *testing.T) { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round 0x22, // (field_number << 3) | wire_type // remaining fields (timestamp): - 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, + 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, }, // with proper (fixed size) height and round (PreVote): { CanonicalizeVote("", &Vote{Height: 1, Round: 1, Type: PrevoteType}), []byte{ - 0x1f, // total length 0x8, // (field_number << 3) | wire_type 0x1, // PrevoteType 0x11, // (field_number << 3) | wire_type @@ -93,38 +91,36 @@ func TestVoteSignableTestVectors(t *testing.T) { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round 0x22, // (field_number << 3) | wire_type // remaining fields (timestamp): - 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, + 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, }, { vote, []byte{ - 0x1d, // total length 0x11, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height 0x19, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round // remaining fields (timestamp): 0x22, - 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff}, + 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, }, // containing non-empty chain_id: { CanonicalizeVote("test_chain_id", &Vote{Height: 1, Round: 1}), []byte{ - 0x2c, // total length 0x11, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height 0x19, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round // remaining fields: - 0x22, // (field_number << 3) | wire_type - 0x9, 0x9, 0x0, 0x9, 0x6e, 0x88, 0xf1, 0xff, 0xff, 0xff, // timestamp + 0x22, // (field_number << 3) | wire_type + 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, // timestamp 0x32, // (field_number << 3) | wire_type 0xd, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64}, // chainID }, } for i, tc := range tests { - got, err := cdc.MarshalBinary(tc.canonicalVote) + got, err := cdc.MarshalBinaryBare(tc.canonicalVote) require.NoError(t, err) require.Equal(t, tc.want, got, "test case #%v: got unexpected sign bytes for Vote.", i) @@ -210,12 +206,16 @@ func TestVoteVerify(t *testing.T) { } func TestMaxVoteBytes(t *testing.T) { + // time is varint encoded so need to pick the max. + // year int, month Month, day, hour, min, sec, nsec int, loc *Location + timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) + vote := &Vote{ ValidatorAddress: tmhash.Sum([]byte("validator_address")), ValidatorIndex: math.MaxInt64, Height: math.MaxInt64, Round: math.MaxInt64, - Timestamp: tmtime.Now(), + Timestamp: timestamp, Type: PrevoteType, BlockID: BlockID{ Hash: tmhash.Sum([]byte("blockID_hash")), From 9795e12ef2eae822733e5add1300bdd37caf5d7c Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Wed, 24 Oct 2018 17:07:33 +0900 Subject: [PATCH 13/35] fix `RecoverAndLogHandler` not to call multiple writeheader (#2688) --- rpc/lib/server/http_server.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rpc/lib/server/http_server.go b/rpc/lib/server/http_server.go index 8069a81d4..6de376c29 100644 --- a/rpc/lib/server/http_server.go +++ b/rpc/lib/server/http_server.go @@ -173,8 +173,7 @@ func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler "Panic in RPC HTTP handler", "err", e, "stack", string(debug.Stack()), ) - rww.WriteHeader(http.StatusInternalServerError) - WriteRPCResponseHTTP(rww, types.RPCInternalError("", e.(error))) + WriteRPCResponseHTTPError(rww, http.StatusInternalServerError, types.RPCInternalError("", e.(error))) } } From 6643c5dd1151fdee803eb1a27e54b5dd81c65be5 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Thu, 25 Oct 2018 03:34:01 +0200 Subject: [PATCH 14/35] Catch up with amino 0.13.0 (#2690) * catch up with amino changes in https://github.com/tendermint/go-amino/pull/222 * WIP: update to amino v0.13.0 * update to fixed amino release --- Gopkg.lock | 72 ++++++++++++++--------------- Gopkg.toml | 2 +- blockchain/store.go | 2 +- consensus/reactor.go | 6 +-- consensus/replay_test.go | 4 +- consensus/state.go | 2 +- crypto/merkle/proof_simple_value.go | 4 +- libs/common/errors_test.go | 2 +- lite/dbprovider.go | 10 ++-- p2p/conn/connection.go | 10 ++-- p2p/conn/connection_test.go | 38 +++++++-------- p2p/conn/secret_connection.go | 8 ++-- p2p/metrics.go | 2 +- p2p/transport.go | 4 +- p2p/transport_test.go | 4 +- privval/priv_validator.go | 12 ++--- privval/remote_signer.go | 4 +- types/block.go | 2 +- types/block_test.go | 2 +- types/evidence_test.go | 2 +- types/heartbeat.go | 2 +- types/heartbeat_test.go | 4 +- types/proposal.go | 2 +- types/proposal_test.go | 6 +-- types/results.go | 2 +- types/tx_test.go | 8 ++-- types/validator_set_test.go | 4 +- types/vote.go | 2 +- types/vote_test.go | 12 ++--- 29 files changed, 117 insertions(+), 117 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index d5d6c1b28..566fed4a2 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -11,11 +11,11 @@ [[projects]] branch = "master" - digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" + digest = "1:c0decf632843204d2b8781de7b26e7038584e2dcccc7e2f401e88ae85b1df2b7" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" - revision = "f5e261fc9ec3437697fb31d8b38453c293204b29" + revision = "67e573d211ace594f1366b4ce9d39726c4b19bd0" [[projects]] digest = "1:1d8e1cb71c33a9470bbbae09bfec09db43c6bf358dfcae13cd8807c4e2a9a2bf" @@ -28,12 +28,12 @@ revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" [[projects]] - digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" name = "github.com/davecgh/go-spew" packages = ["spew"] pruneopts = "UT" - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" [[projects]] digest = "1:c7644c73a3d23741fdba8a99b1464e021a224b7e205be497271a8003a15ca41b" @@ -83,12 +83,12 @@ version = "v0.3.0" [[projects]] - digest = "1:c4a2528ccbcabf90f9f3c464a5fc9e302d592861bbfd0b7135a7de8a943d0406" + digest = "1:586ea76dbd0374d6fb649a91d70d652b7fe0ccffb8910a77468e7702e7901f3d" name = "github.com/go-stack/stack" packages = ["."] pruneopts = "UT" - revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" - version = "v1.7.0" + revision = "2fee6af1a9795aafbe0253a0cfbdf668e1fb8a9a" + version = "v1.8.0" [[projects]] digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" @@ -136,8 +136,7 @@ version = "v1.2.0" [[projects]] - branch = "master" - digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" + digest = "1:ea40c24cdbacd054a6ae9de03e62c5f252479b96c716375aace5c120d68647c8" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -151,7 +150,8 @@ "json/token", ] pruneopts = "UT" - revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" + revision = "8cb6e5b959231cc1119e43259c4a608f9c51a241" + version = "v1.0.0" [[projects]] digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" @@ -193,12 +193,12 @@ version = "v1.0.1" [[projects]] - branch = "master" - digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355" + digest = "1:53bc4cd4914cd7cd52139990d5170d6dc99067ae31c56530621b18b35fc30318" name = "github.com/mitchellh/mapstructure" packages = ["."] pruneopts = "UT" - revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" + revision = "3536a929edddb9a5b34bd6861dc4a9647cb459fe" + version = "v1.1.2" [[projects]] digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e" @@ -244,7 +244,7 @@ [[projects]] branch = "master" - digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" + digest = "1:db712fde5d12d6cdbdf14b777f0c230f4ff5ab0be8e35b239fc319953ed577a4" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -252,11 +252,11 @@ "model", ] pruneopts = "UT" - revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" + revision = "7e9e6cabbd393fc208072eedef99188d0ce788b6" [[projects]] branch = "master" - digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" + digest = "1:ef74914912f99c79434d9c09658274678bc85080ebe3ab32bec3940ebce5e1fc" name = "github.com/prometheus/procfs" packages = [ ".", @@ -265,7 +265,7 @@ "xfs", ] pruneopts = "UT" - revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" + revision = "185b4288413d2a0dd0806f78c90dde719829e5ae" [[projects]] digest = "1:c4556a44e350b50a490544d9b06e9fba9c286c21d6c0e47f54f3a9214597298c" @@ -275,15 +275,15 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" + digest = "1:6a4a11ba764a56d2758899ec6f3848d24698d48442ebce85ee7a3f63284526cd" name = "github.com/spf13/afero" packages = [ ".", "mem", ] pruneopts = "UT" - revision = "787d034dfe70e44075ccc060d346146ef53270ad" - version = "v1.1.1" + revision = "d40851caa0d747393da1ffb28f7f9d8b4eeffebd" + version = "v1.1.2" [[projects]] digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f" @@ -302,20 +302,20 @@ version = "v0.0.1" [[projects]] - branch = "master" - digest = "1:080e5f630945ad754f4b920e60b4d3095ba0237ebf88dc462eb28002932e3805" + digest = "1:68ea4e23713989dc20b1bded5d9da2c5f9be14ff9885beef481848edd18c26cb" name = "github.com/spf13/jwalterweatherman" packages = ["."] pruneopts = "UT" - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + revision = "4a4406e478ca629068e7768fc33f3f044173c0a6" + version = "v1.0.0" [[projects]] - digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7" + digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2" name = "github.com/spf13/pflag" packages = ["."] pruneopts = "UT" - revision = "583c0c0531f06d5278b7d917446061adc344b5cd" - version = "v1.0.1" + revision = "298182f68c66c05229eb03ac171abe6e309ee79a" + version = "v1.0.3" [[projects]] digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96" @@ -338,7 +338,7 @@ [[projects]] branch = "master" - digest = "1:b3cfb8d82b1601a846417c3f31c03a7961862cb2c98dcf0959c473843e6d9a2b" + digest = "1:59483b8e8183f10ab21a85ba1f4cbb4a2335d48891801f79ed7b9499f44d383c" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -355,7 +355,7 @@ "leveldb/util", ] pruneopts = "UT" - revision = "c4c61651e9e37fa117f53c5a906d3b63090d8445" + revision = "6b91fda63f2e36186f1c9d0e48578defb69c5d43" [[projects]] digest = "1:605b6546f3f43745695298ec2d342d3e952b6d91cdf9f349bea9315f677d759f" @@ -365,12 +365,12 @@ revision = "e5840949ff4fff0c56f9b6a541e22b63581ea9df" [[projects]] - digest = "1:3ff2c9d4def5ec999ab672b9059d0ba41a1351913ea78e63b5402e4ba4ef8da4" + digest = "1:5f52e817b6c9d52ddba70dece0ea31134d82a52c05bce98fbc739ab2a832df28" name = "github.com/tendermint/go-amino" packages = ["."] pruneopts = "UT" - revision = "ff047d9e357e66d937d6900d4a2e04501cc62c70" - version = "v0.13.0-rc0" + revision = "cb07448b240918aa8d8df4505153549b86b77134" + version = "v0.13.0" [[projects]] digest = "1:72b71e3a29775e5752ed7a8012052a3dee165e27ec18cedddae5288058f09acf" @@ -415,14 +415,14 @@ [[projects]] branch = "master" - digest = "1:bb0fe59917bdd5b89f49b9a8b26e5f465e325d9223b3a8e32254314bdf51e0f1" + digest = "1:d1da39c9bac61327dbef1d8ef9f210425e99fd2924b6fb5f0bc587a193353637" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "3dc4335d56c789b04b0ba99b7a37249d9b614314" + revision = "8a28ead16f52c8aaeffbf79239b251dfdf6c4f96" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" @@ -449,11 +449,11 @@ [[projects]] branch = "master" - digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" + digest = "1:56b0bca90b7e5d1facf5fbdacba23e4e0ce069d25381b8e2f70ef1e7ebfb9c1a" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "daca94659cb50e9f37c1b834680f2e46358f10b0" + revision = "94acd270e44e65579b9ee3cdab25034d33fed608" [[projects]] digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" diff --git a/Gopkg.toml b/Gopkg.toml index 622ca00e0..e24965dc1 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -58,7 +58,7 @@ [[constraint]] name = "github.com/tendermint/go-amino" - version = "v0.13.0-rc0" + version = "v0.13.0" [[constraint]] name = "google.golang.org/grpc" diff --git a/blockchain/store.go b/blockchain/store.go index fa9ee5189..498cca68d 100644 --- a/blockchain/store.go +++ b/blockchain/store.go @@ -63,7 +63,7 @@ func (bs *BlockStore) LoadBlock(height int64) *types.Block { part := bs.LoadBlockPart(height, i) buf = append(buf, part.Bytes...) } - err := cdc.UnmarshalBinary(buf, block) + err := cdc.UnmarshalBinaryLengthPrefixed(buf, block) if err != nil { // NOTE: The existence of meta should imply the existence of the // block. So, make sure meta is only saved after blocks are saved. diff --git a/consensus/reactor.go b/consensus/reactor.go index bcf77fb3a..6643273cb 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -429,9 +429,9 @@ func (conR *ConsensusReactor) broadcastHasVoteMessage(vote *types.Vote) { func makeRoundStepMessages(rs *cstypes.RoundState) (nrsMsg *NewRoundStepMessage, csMsg *CommitStepMessage) { nrsMsg = &NewRoundStepMessage{ - Height: rs.Height, - Round: rs.Round, - Step: rs.Step, + Height: rs.Height, + Round: rs.Round, + Step: rs.Step, SecondsSinceStartTime: int(time.Since(rs.StartTime).Seconds()), LastCommitRound: rs.LastCommit.Round(), } diff --git a/consensus/replay_test.go b/consensus/replay_test.go index 4e1fa2b77..d6691103e 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -520,7 +520,7 @@ func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.Commit, error) { // if its not the first one, we have a full block if thisBlockParts != nil { var block = new(types.Block) - _, err = cdc.UnmarshalBinaryReader(thisBlockParts.GetReader(), block, 0) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(thisBlockParts.GetReader(), block, 0) if err != nil { panic(err) } @@ -553,7 +553,7 @@ func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.Commit, error) { } // grab the last block too var block = new(types.Block) - _, err = cdc.UnmarshalBinaryReader(thisBlockParts.GetReader(), block, 0) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(thisBlockParts.GetReader(), block, 0) if err != nil { panic(err) } diff --git a/consensus/state.go b/consensus/state.go index 375674008..0b079f13d 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1468,7 +1468,7 @@ func (cs *ConsensusState) addProposalBlockPart(msg *BlockPartMessage, peerID p2p } if added && cs.ProposalBlockParts.IsComplete() { // Added and completed! - _, err = cdc.UnmarshalBinaryReader( + _, err = cdc.UnmarshalBinaryLengthPrefixedReader( cs.ProposalBlockParts.GetReader(), &cs.ProposalBlock, int64(cs.state.ConsensusParams.BlockSize.MaxBytes), diff --git a/crypto/merkle/proof_simple_value.go b/crypto/merkle/proof_simple_value.go index 5b7b52329..904b6e5ec 100644 --- a/crypto/merkle/proof_simple_value.go +++ b/crypto/merkle/proof_simple_value.go @@ -42,7 +42,7 @@ func SimpleValueOpDecoder(pop ProofOp) (ProofOperator, error) { return nil, cmn.NewError("unexpected ProofOp.Type; got %v, want %v", pop.Type, ProofOpSimpleValue) } var op SimpleValueOp // a bit strange as we'll discard this, but it works. - err := cdc.UnmarshalBinary(pop.Data, &op) + err := cdc.UnmarshalBinaryLengthPrefixed(pop.Data, &op) if err != nil { return nil, cmn.ErrorWrap(err, "decoding ProofOp.Data into SimpleValueOp") } @@ -50,7 +50,7 @@ func SimpleValueOpDecoder(pop ProofOp) (ProofOperator, error) { } func (op SimpleValueOp) ProofOp() ProofOp { - bz := cdc.MustMarshalBinary(op) + bz := cdc.MustMarshalBinaryLengthPrefixed(op) return ProofOp{ Type: ProofOpSimpleValue, Key: op.key, diff --git a/libs/common/errors_test.go b/libs/common/errors_test.go index 326468c94..b85936dd5 100644 --- a/libs/common/errors_test.go +++ b/libs/common/errors_test.go @@ -24,7 +24,7 @@ func TestErrorPanic(t *testing.T) { var err = capturePanic() assert.Equal(t, pnk{"something"}, err.Data()) -assert.Equal(t, "{something}", fmt.Sprintf("%v", err)) + assert.Equal(t, "{something}", fmt.Sprintf("%v", err)) assert.Contains(t, fmt.Sprintf("%#v", err), "This is the message in ErrorWrap(r, message).") assert.Contains(t, fmt.Sprintf("%#v", err), "Stack Trace:\n 0") } diff --git a/lite/dbprovider.go b/lite/dbprovider.go index cab695b4a..e0c4e65b4 100644 --- a/lite/dbprovider.go +++ b/lite/dbprovider.go @@ -56,7 +56,7 @@ func (dbp *DBProvider) SaveFullCommit(fc FullCommit) error { // We might be overwriting what we already have, but // it makes the logic easier for now. vsKey := validatorSetKey(fc.ChainID(), fc.Height()) - vsBz, err := dbp.cdc.MarshalBinary(fc.Validators) + vsBz, err := dbp.cdc.MarshalBinaryLengthPrefixed(fc.Validators) if err != nil { return err } @@ -64,7 +64,7 @@ func (dbp *DBProvider) SaveFullCommit(fc FullCommit) error { // Save the fc.NextValidators. nvsKey := validatorSetKey(fc.ChainID(), fc.Height()+1) - nvsBz, err := dbp.cdc.MarshalBinary(fc.NextValidators) + nvsBz, err := dbp.cdc.MarshalBinaryLengthPrefixed(fc.NextValidators) if err != nil { return err } @@ -72,7 +72,7 @@ func (dbp *DBProvider) SaveFullCommit(fc FullCommit) error { // Save the fc.SignedHeader shKey := signedHeaderKey(fc.ChainID(), fc.Height()) - shBz, err := dbp.cdc.MarshalBinary(fc.SignedHeader) + shBz, err := dbp.cdc.MarshalBinaryLengthPrefixed(fc.SignedHeader) if err != nil { return err } @@ -121,7 +121,7 @@ func (dbp *DBProvider) LatestFullCommit(chainID string, minHeight, maxHeight int // Found the latest full commit signed header. shBz := itr.Value() sh := types.SignedHeader{} - err := dbp.cdc.UnmarshalBinary(shBz, &sh) + err := dbp.cdc.UnmarshalBinaryLengthPrefixed(shBz, &sh) if err != nil { return FullCommit{}, err } else { @@ -150,7 +150,7 @@ func (dbp *DBProvider) getValidatorSet(chainID string, height int64) (valset *ty err = lerr.ErrUnknownValidators(chainID, height) return } - err = dbp.cdc.UnmarshalBinary(vsBz, &valset) + err = dbp.cdc.UnmarshalBinaryLengthPrefixed(vsBz, &valset) if err != nil { return } diff --git a/p2p/conn/connection.go b/p2p/conn/connection.go index 0e33adab9..80fc53ddb 100644 --- a/p2p/conn/connection.go +++ b/p2p/conn/connection.go @@ -337,7 +337,7 @@ FOR_LOOP: } case <-c.pingTimer.Chan(): c.Logger.Debug("Send Ping") - _n, err = cdc.MarshalBinaryWriter(c.bufConnWriter, PacketPing{}) + _n, err = cdc.MarshalBinaryLengthPrefixedWriter(c.bufConnWriter, PacketPing{}) if err != nil { break SELECTION } @@ -359,7 +359,7 @@ FOR_LOOP: } case <-c.pong: c.Logger.Debug("Send Pong") - _n, err = cdc.MarshalBinaryWriter(c.bufConnWriter, PacketPong{}) + _n, err = cdc.MarshalBinaryLengthPrefixedWriter(c.bufConnWriter, PacketPong{}) if err != nil { break SELECTION } @@ -477,7 +477,7 @@ FOR_LOOP: var packet Packet var _n int64 var err error - _n, err = cdc.UnmarshalBinaryReader(c.bufConnReader, &packet, int64(c._maxPacketMsgSize)) + _n, err = cdc.UnmarshalBinaryLengthPrefixedReader(c.bufConnReader, &packet, int64(c._maxPacketMsgSize)) c.recvMonitor.Update(int(_n)) if err != nil { if c.IsRunning() { @@ -553,7 +553,7 @@ func (c *MConnection) stopPongTimer() { // maxPacketMsgSize returns a maximum size of PacketMsg, including the overhead // of amino encoding. func (c *MConnection) maxPacketMsgSize() int { - return len(cdc.MustMarshalBinary(PacketMsg{ + return len(cdc.MustMarshalBinaryLengthPrefixed(PacketMsg{ ChannelID: 0x01, EOF: 1, Bytes: make([]byte, c.config.MaxPacketMsgPayloadSize), @@ -723,7 +723,7 @@ func (ch *Channel) nextPacketMsg() PacketMsg { // Not goroutine-safe func (ch *Channel) writePacketMsgTo(w io.Writer) (n int64, err error) { var packet = ch.nextPacketMsg() - n, err = cdc.MarshalBinaryWriter(w, packet) + n, err = cdc.MarshalBinaryLengthPrefixedWriter(w, packet) atomic.AddInt64(&ch.recentlySent, n) return } diff --git a/p2p/conn/connection_test.go b/p2p/conn/connection_test.go index 95b5488a4..59fe0d1df 100644 --- a/p2p/conn/connection_test.go +++ b/p2p/conn/connection_test.go @@ -140,7 +140,7 @@ func TestMConnectionPongTimeoutResultsInError(t *testing.T) { go func() { // read ping var pkt PacketPing - _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) assert.Nil(t, err) serverGotPing <- struct{}{} }() @@ -176,22 +176,22 @@ func TestMConnectionMultiplePongsInTheBeginning(t *testing.T) { defer mconn.Stop() // sending 3 pongs in a row (abuse) - _, err = server.Write(cdc.MustMarshalBinary(PacketPong{})) + _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) require.Nil(t, err) - _, err = server.Write(cdc.MustMarshalBinary(PacketPong{})) + _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) require.Nil(t, err) - _, err = server.Write(cdc.MustMarshalBinary(PacketPong{})) + _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) require.Nil(t, err) serverGotPing := make(chan struct{}) go func() { // read ping (one byte) var packet, err = Packet(nil), error(nil) - _, err = cdc.UnmarshalBinaryReader(server, &packet, maxPingPongPacketSize) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &packet, maxPingPongPacketSize) require.Nil(t, err) serverGotPing <- struct{}{} // respond with pong - _, err = server.Write(cdc.MustMarshalBinary(PacketPong{})) + _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) require.Nil(t, err) }() <-serverGotPing @@ -227,18 +227,18 @@ func TestMConnectionMultiplePings(t *testing.T) { // sending 3 pings in a row (abuse) // see https://github.com/tendermint/tendermint/issues/1190 - _, err = server.Write(cdc.MustMarshalBinary(PacketPing{})) + _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPing{})) require.Nil(t, err) var pkt PacketPong - _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) - _, err = server.Write(cdc.MustMarshalBinary(PacketPing{})) + _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPing{})) require.Nil(t, err) - _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) - _, err = server.Write(cdc.MustMarshalBinary(PacketPing{})) + _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPing{})) require.Nil(t, err) - _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) assert.True(t, mconn.IsRunning()) @@ -270,20 +270,20 @@ func TestMConnectionPingPongs(t *testing.T) { go func() { // read ping var pkt PacketPing - _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) serverGotPing <- struct{}{} // respond with pong - _, err = server.Write(cdc.MustMarshalBinary(PacketPong{})) + _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) require.Nil(t, err) time.Sleep(mconn.config.PingInterval) // read ping - _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) // respond with pong - _, err = server.Write(cdc.MustMarshalBinary(PacketPong{})) + _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) require.Nil(t, err) }() <-serverGotPing @@ -380,7 +380,7 @@ func TestMConnectionReadErrorBadEncoding(t *testing.T) { client := mconnClient.conn // send badly encoded msgPacket - bz := cdc.MustMarshalBinary(PacketMsg{}) + bz := cdc.MustMarshalBinaryLengthPrefixed(PacketMsg{}) bz[4] += 0x01 // Invalid prefix bytes. // Write it. @@ -428,7 +428,7 @@ func TestMConnectionReadErrorLongMessage(t *testing.T) { EOF: 1, Bytes: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize), } - _, err = cdc.MarshalBinaryWriter(buf, packet) + _, err = cdc.MarshalBinaryLengthPrefixedWriter(buf, packet) assert.Nil(t, err) _, err = client.Write(buf.Bytes()) assert.Nil(t, err) @@ -441,7 +441,7 @@ func TestMConnectionReadErrorLongMessage(t *testing.T) { EOF: 1, Bytes: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize+100), } - _, err = cdc.MarshalBinaryWriter(buf, packet) + _, err = cdc.MarshalBinaryLengthPrefixedWriter(buf, packet) assert.Nil(t, err) _, err = client.Write(buf.Bytes()) assert.NotNil(t, err) diff --git a/p2p/conn/secret_connection.go b/p2p/conn/secret_connection.go index acdd96de4..1dc66afff 100644 --- a/p2p/conn/secret_connection.go +++ b/p2p/conn/secret_connection.go @@ -211,7 +211,7 @@ func shareEphPubKey(conn io.ReadWriteCloser, locEphPub *[32]byte) (remEphPub *[3 // Send our pubkey and receive theirs in tandem. var trs, _ = cmn.Parallel( func(_ int) (val interface{}, err error, abort bool) { - var _, err1 = cdc.MarshalBinaryWriter(conn, locEphPub) + var _, err1 = cdc.MarshalBinaryLengthPrefixedWriter(conn, locEphPub) if err1 != nil { return nil, err1, true // abort } @@ -219,7 +219,7 @@ func shareEphPubKey(conn io.ReadWriteCloser, locEphPub *[32]byte) (remEphPub *[3 }, func(_ int) (val interface{}, err error, abort bool) { var _remEphPub [32]byte - var _, err2 = cdc.UnmarshalBinaryReader(conn, &_remEphPub, 1024*1024) // TODO + var _, err2 = cdc.UnmarshalBinaryLengthPrefixedReader(conn, &_remEphPub, 1024*1024) // TODO if err2 != nil { return nil, err2, true // abort } @@ -305,7 +305,7 @@ func shareAuthSignature(sc *SecretConnection, pubKey crypto.PubKey, signature [] // Send our info and receive theirs in tandem. var trs, _ = cmn.Parallel( func(_ int) (val interface{}, err error, abort bool) { - var _, err1 = cdc.MarshalBinaryWriter(sc, authSigMessage{pubKey, signature}) + var _, err1 = cdc.MarshalBinaryLengthPrefixedWriter(sc, authSigMessage{pubKey, signature}) if err1 != nil { return nil, err1, true // abort } @@ -313,7 +313,7 @@ func shareAuthSignature(sc *SecretConnection, pubKey crypto.PubKey, signature [] }, func(_ int) (val interface{}, err error, abort bool) { var _recvMsg authSigMessage - var _, err2 = cdc.UnmarshalBinaryReader(sc, &_recvMsg, 1024*1024) // TODO + var _, err2 = cdc.UnmarshalBinaryLengthPrefixedReader(sc, &_recvMsg, 1024*1024) // TODO if err2 != nil { return nil, err2, true // abort } diff --git a/p2p/metrics.go b/p2p/metrics.go index ed26d1192..b066fb317 100644 --- a/p2p/metrics.go +++ b/p2p/metrics.go @@ -62,7 +62,7 @@ func PrometheusMetrics(namespace string) *Metrics { // NopMetrics returns no-op Metrics. func NopMetrics() *Metrics { return &Metrics{ - Peers: discard.NewGauge(), + Peers: discard.NewGauge(), PeerReceiveBytesTotal: discard.NewCounter(), PeerSendBytesTotal: discard.NewCounter(), PeerPendingSendBytes: discard.NewGauge(), diff --git a/p2p/transport.go b/p2p/transport.go index 10565d8a9..0b9b436f0 100644 --- a/p2p/transport.go +++ b/p2p/transport.go @@ -446,11 +446,11 @@ func handshake( ) go func(errc chan<- error, c net.Conn) { - _, err := cdc.MarshalBinaryWriter(c, ourNodeInfo) + _, err := cdc.MarshalBinaryLengthPrefixedWriter(c, ourNodeInfo) errc <- err }(errc, c) go func(errc chan<- error, c net.Conn) { - _, err := cdc.UnmarshalBinaryReader( + _, err := cdc.UnmarshalBinaryLengthPrefixedReader( c, &peerNodeInfo, int64(MaxNodeInfoSize()), diff --git a/p2p/transport_test.go b/p2p/transport_test.go index cce223a3e..8a5c06bc3 100644 --- a/p2p/transport_test.go +++ b/p2p/transport_test.go @@ -516,7 +516,7 @@ func TestTransportHandshake(t *testing.T) { } go func(c net.Conn) { - _, err := cdc.MarshalBinaryWriter(c, peerNodeInfo.(DefaultNodeInfo)) + _, err := cdc.MarshalBinaryLengthPrefixedWriter(c, peerNodeInfo.(DefaultNodeInfo)) if err != nil { t.Error(err) } @@ -524,7 +524,7 @@ func TestTransportHandshake(t *testing.T) { go func(c net.Conn) { var ni DefaultNodeInfo - _, err := cdc.UnmarshalBinaryReader( + _, err := cdc.UnmarshalBinaryLengthPrefixedReader( c, &ni, int64(MaxNodeInfoSize()), diff --git a/privval/priv_validator.go b/privval/priv_validator.go index c5fba509f..a13f5426b 100644 --- a/privval/priv_validator.go +++ b/privval/priv_validator.go @@ -314,10 +314,10 @@ func (pv *FilePV) String() string { // returns true if the only difference in the votes is their timestamp. func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.Time, bool) { var lastVote, newVote types.CanonicalVote - if err := cdc.UnmarshalBinary(lastSignBytes, &lastVote); err != nil { + if err := cdc.UnmarshalBinaryLengthPrefixed(lastSignBytes, &lastVote); err != nil { panic(fmt.Sprintf("LastSignBytes cannot be unmarshalled into vote: %v", err)) } - if err := cdc.UnmarshalBinary(newSignBytes, &newVote); err != nil { + if err := cdc.UnmarshalBinaryLengthPrefixed(newSignBytes, &newVote); err != nil { panic(fmt.Sprintf("signBytes cannot be unmarshalled into vote: %v", err)) } @@ -337,10 +337,10 @@ func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.T // returns true if the only difference in the proposals is their timestamp func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.Time, bool) { var lastProposal, newProposal types.CanonicalProposal - if err := cdc.UnmarshalBinary(lastSignBytes, &lastProposal); err != nil { + if err := cdc.UnmarshalBinaryLengthPrefixed(lastSignBytes, &lastProposal); err != nil { panic(fmt.Sprintf("LastSignBytes cannot be unmarshalled into proposal: %v", err)) } - if err := cdc.UnmarshalBinary(newSignBytes, &newProposal); err != nil { + if err := cdc.UnmarshalBinaryLengthPrefixed(newSignBytes, &newProposal); err != nil { panic(fmt.Sprintf("signBytes cannot be unmarshalled into proposal: %v", err)) } @@ -349,8 +349,8 @@ func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (ti now := tmtime.Now() lastProposal.Timestamp = now newProposal.Timestamp = now - lastProposalBytes, _ := cdc.MarshalBinary(lastProposal) - newProposalBytes, _ := cdc.MarshalBinary(newProposal) + lastProposalBytes, _ := cdc.MarshalBinaryLengthPrefixed(lastProposal) + newProposalBytes, _ := cdc.MarshalBinaryLengthPrefixed(newProposal) return lastTime, bytes.Equal(newProposalBytes, lastProposalBytes) } diff --git a/privval/remote_signer.go b/privval/remote_signer.go index 399ee7905..eacc840c5 100644 --- a/privval/remote_signer.go +++ b/privval/remote_signer.go @@ -248,7 +248,7 @@ func (e *RemoteSignerError) Error() string { func readMsg(r io.Reader) (msg RemoteSignerMsg, err error) { const maxRemoteSignerMsgSize = 1024 * 10 - _, err = cdc.UnmarshalBinaryReader(r, &msg, maxRemoteSignerMsgSize) + _, err = cdc.UnmarshalBinaryLengthPrefixedReader(r, &msg, maxRemoteSignerMsgSize) if _, ok := err.(timeoutError); ok { err = cmn.ErrorWrap(ErrConnTimeout, err.Error()) } @@ -256,7 +256,7 @@ func readMsg(r io.Reader) (msg RemoteSignerMsg, err error) { } func writeMsg(w io.Writer, msg interface{}) (err error) { - _, err = cdc.MarshalBinaryWriter(w, msg) + _, err = cdc.MarshalBinaryLengthPrefixedWriter(w, msg) if _, ok := err.(timeoutError); ok { err = cmn.ErrorWrap(ErrConnTimeout, err.Error()) } diff --git a/types/block.go b/types/block.go index ce605263c..70b840c63 100644 --- a/types/block.go +++ b/types/block.go @@ -149,7 +149,7 @@ func (b *Block) MakePartSet(partSize int) *PartSet { // We prefix the byte length, so that unmarshaling // can easily happen via a reader. - bz, err := cdc.MarshalBinary(b) + bz, err := cdc.MarshalBinaryLengthPrefixed(b) if err != nil { panic(err) } diff --git a/types/block_test.go b/types/block_test.go index e34ba29b8..341073980 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -265,7 +265,7 @@ func TestMaxHeaderBytes(t *testing.T) { ProposerAddress: tmhash.Sum([]byte("proposer_address")), } - bz, err := cdc.MarshalBinary(h) + bz, err := cdc.MarshalBinaryLengthPrefixed(h) require.NoError(t, err) assert.EqualValues(t, MaxHeaderBytes, len(bz)) diff --git a/types/evidence_test.go b/types/evidence_test.go index 79805691c..44276ab18 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -105,7 +105,7 @@ func TestMaxEvidenceBytes(t *testing.T) { VoteB: makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2), } - bz, err := cdc.MarshalBinary(ev) + bz, err := cdc.MarshalBinaryLengthPrefixed(ev) require.NoError(t, err) assert.EqualValues(t, MaxEvidenceBytes, len(bz)) diff --git a/types/heartbeat.go b/types/heartbeat.go index de03d5cc4..9dea039e0 100644 --- a/types/heartbeat.go +++ b/types/heartbeat.go @@ -23,7 +23,7 @@ type Heartbeat struct { // SignBytes returns the Heartbeat bytes for signing. // It panics if the Heartbeat is nil. func (heartbeat *Heartbeat) SignBytes(chainID string) []byte { - bz, err := cdc.MarshalBinary(CanonicalizeHeartbeat(chainID, heartbeat)) + bz, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeHeartbeat(chainID, heartbeat)) if err != nil { panic(err) } diff --git a/types/heartbeat_test.go b/types/heartbeat_test.go index 550bcc739..e1ffdd6f1 100644 --- a/types/heartbeat_test.go +++ b/types/heartbeat_test.go @@ -39,7 +39,7 @@ func TestHeartbeatWriteSignBytes(t *testing.T) { { testHeartbeat := &Heartbeat{ValidatorIndex: 1, Height: 10, Round: 1} signBytes := testHeartbeat.SignBytes(chainID) - expected, err := cdc.MarshalBinary(CanonicalizeHeartbeat(chainID, testHeartbeat)) + expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeHeartbeat(chainID, testHeartbeat)) require.NoError(t, err) require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Heartbeat") } @@ -47,7 +47,7 @@ func TestHeartbeatWriteSignBytes(t *testing.T) { { testHeartbeat := &Heartbeat{} signBytes := testHeartbeat.SignBytes(chainID) - expected, err := cdc.MarshalBinary(CanonicalizeHeartbeat(chainID, testHeartbeat)) + expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeHeartbeat(chainID, testHeartbeat)) require.NoError(t, err) require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Heartbeat") } diff --git a/types/proposal.go b/types/proposal.go index a2bc8e367..5d70a3c84 100644 --- a/types/proposal.go +++ b/types/proposal.go @@ -52,7 +52,7 @@ func (p *Proposal) String() string { // SignBytes returns the Proposal bytes for signing func (p *Proposal) SignBytes(chainID string) []byte { - bz, err := cdc.MarshalBinary(CanonicalizeProposal(chainID, p)) + bz, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeProposal(chainID, p)) if err != nil { panic(err) } diff --git a/types/proposal_test.go b/types/proposal_test.go index 5f9433083..8ae1f3e5a 100644 --- a/types/proposal_test.go +++ b/types/proposal_test.go @@ -27,7 +27,7 @@ func TestProposalSignable(t *testing.T) { chainID := "test_chain_id" signBytes := testProposal.SignBytes(chainID) - expected, err := cdc.MarshalBinary(CanonicalizeProposal(chainID, testProposal)) + expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeProposal(chainID, testProposal)) require.NoError(t, err) require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Proposal") } @@ -57,9 +57,9 @@ func TestProposalVerifySignature(t *testing.T) { // serialize, deserialize and verify again.... newProp := new(Proposal) - bs, err := cdc.MarshalBinary(prop) + bs, err := cdc.MarshalBinaryLengthPrefixed(prop) require.NoError(t, err) - err = cdc.UnmarshalBinary(bs, &newProp) + err = cdc.UnmarshalBinaryLengthPrefixed(bs, &newProp) require.NoError(t, err) // verify the transmitted proposal diff --git a/types/results.go b/types/results.go index 6b5b82d27..db7811684 100644 --- a/types/results.go +++ b/types/results.go @@ -48,7 +48,7 @@ func NewResultFromResponse(response *abci.ResponseDeliverTx) ABCIResult { // Bytes serializes the ABCIResponse using wire func (a ABCIResults) Bytes() []byte { - bz, err := cdc.MarshalBinary(a) + bz, err := cdc.MarshalBinaryLengthPrefixed(a) if err != nil { panic(err) } diff --git a/types/tx_test.go b/types/tx_test.go index 9fb8ff34d..6ce23d6f5 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -79,9 +79,9 @@ func TestValidTxProof(t *testing.T) { // read-write must also work var p2 TxProof - bin, err := cdc.MarshalBinary(proof) + bin, err := cdc.MarshalBinaryLengthPrefixed(proof) assert.Nil(t, err) - err = cdc.UnmarshalBinary(bin, &p2) + err = cdc.UnmarshalBinaryLengthPrefixed(bin, &p2) if assert.Nil(t, err, "%d: %d: %+v", h, i, err) { assert.Nil(t, p2.Validate(root), "%d: %d", h, i) } @@ -105,7 +105,7 @@ func testTxProofUnchangable(t *testing.T) { // make sure it is valid to start with assert.Nil(t, proof.Validate(root)) - bin, err := cdc.MarshalBinary(proof) + bin, err := cdc.MarshalBinaryLengthPrefixed(proof) assert.Nil(t, err) // try mutating the data and make sure nothing breaks @@ -120,7 +120,7 @@ func testTxProofUnchangable(t *testing.T) { // This makes sure that the proof doesn't deserialize into something valid. func assertBadProof(t *testing.T, root []byte, bad []byte, good TxProof) { var proof TxProof - err := cdc.UnmarshalBinary(bad, &proof) + err := cdc.UnmarshalBinaryLengthPrefixed(bad, &proof) if err == nil { err = proof.Validate(root) if err == nil { diff --git a/types/validator_set_test.go b/types/validator_set_test.go index d886b419c..aad9d85a8 100644 --- a/types/validator_set_test.go +++ b/types/validator_set_test.go @@ -272,7 +272,7 @@ func randValidatorSet(numValidators int) *ValidatorSet { } func (valSet *ValidatorSet) toBytes() []byte { - bz, err := cdc.MarshalBinary(valSet) + bz, err := cdc.MarshalBinaryLengthPrefixed(valSet) if err != nil { panic(err) } @@ -280,7 +280,7 @@ func (valSet *ValidatorSet) toBytes() []byte { } func (valSet *ValidatorSet) fromBytes(b []byte) { - err := cdc.UnmarshalBinary(b, &valSet) + err := cdc.UnmarshalBinaryLengthPrefixed(b, &valSet) if err != nil { // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED panic(err) diff --git a/types/vote.go b/types/vote.go index 2a7133099..e1095bf15 100644 --- a/types/vote.go +++ b/types/vote.go @@ -59,7 +59,7 @@ type Vote struct { } func (vote *Vote) SignBytes(chainID string) []byte { - bz, err := cdc.MarshalBinary(CanonicalizeVote(chainID, vote)) + bz, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeVote(chainID, vote)) if err != nil { panic(err) } diff --git a/types/vote_test.go b/types/vote_test.go index 3b2f08488..1d7e3daf0 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -46,7 +46,7 @@ func TestVoteSignable(t *testing.T) { vote := examplePrecommit() signBytes := vote.SignBytes("test_chain_id") - expected, err := cdc.MarshalBinary(CanonicalizeVote("test_chain_id", vote)) + expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeVote("test_chain_id", vote)) require.NoError(t, err) require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Vote.") @@ -130,9 +130,9 @@ func TestVoteSignableTestVectors(t *testing.T) { func TestVoteProposalNotEq(t *testing.T) { cv := CanonicalizeVote("", &Vote{Height: 1, Round: 1}) p := CanonicalizeProposal("", &Proposal{Height: 1, Round: 1}) - vb, err := cdc.MarshalBinary(cv) + vb, err := cdc.MarshalBinaryLengthPrefixed(cv) require.NoError(t, err) - pb, err := cdc.MarshalBinary(p) + pb, err := cdc.MarshalBinaryLengthPrefixed(p) require.NoError(t, err) require.NotEqual(t, vb, pb) } @@ -154,9 +154,9 @@ func TestVoteVerifySignature(t *testing.T) { // serialize, deserialize and verify again.... precommit := new(Vote) - bs, err := cdc.MarshalBinary(vote) + bs, err := cdc.MarshalBinaryLengthPrefixed(vote) require.NoError(t, err) - err = cdc.UnmarshalBinary(bs, &precommit) + err = cdc.UnmarshalBinaryLengthPrefixed(bs, &precommit) require.NoError(t, err) // verify the transmitted vote @@ -230,7 +230,7 @@ func TestMaxVoteBytes(t *testing.T) { err := privVal.SignVote("test_chain_id", vote) require.NoError(t, err) - bz, err := cdc.MarshalBinary(vote) + bz, err := cdc.MarshalBinaryLengthPrefixed(vote) require.NoError(t, err) assert.EqualValues(t, MaxVoteBytes, len(bz)) From bbf15b3d09ac05ff2cfd58b53313ec612e1a9b07 Mon Sep 17 00:00:00 2001 From: zhangzheng Date: Thu, 25 Oct 2018 18:27:32 +0800 Subject: [PATCH 15/35] tm-monitor: update health after we added / removed node (#2694) Refs #2693 --- tools/tm-monitor/monitor/network.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/tm-monitor/monitor/network.go b/tools/tm-monitor/monitor/network.go index 9b147c06b..bb5dd0baa 100644 --- a/tools/tm-monitor/monitor/network.go +++ b/tools/tm-monitor/monitor/network.go @@ -140,14 +140,22 @@ func (n *Network) NodeIsOnline(name string) { // NewNode is called when the new node is added to the monitor. func (n *Network) NewNode(name string) { + n.mu.Lock() + defer n.mu.Unlock() + n.NumNodesMonitored++ n.NumNodesMonitoredOnline++ + n.updateHealth() } // NodeDeleted is called when the node is deleted from under the monitor. func (n *Network) NodeDeleted(name string) { + n.mu.Lock() + defer n.mu.Unlock() + n.NumNodesMonitored-- n.NumNodesMonitoredOnline-- + n.updateHealth() } func (n *Network) updateHealth() { From a67ae814698b76206049e378a9ed64e7a2ed3832 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 25 Oct 2018 16:40:20 +0200 Subject: [PATCH 16/35] if some process locks a block in round 0, then 0 is valid proposal.POLRound in rounds > 0 This condition is really hard to get. Initially, lockedRound and validRound are set to -1 as we start with round 0. Refs #2702 --- consensus/state.go | 6 +++--- types/vote_set.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/consensus/state.go b/consensus/state.go index 0b079f13d..c6efe98f0 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1425,9 +1425,9 @@ func (cs *ConsensusState) defaultSetProposal(proposal *types.Proposal) error { return nil } - // Verify POLRound, which must be -1 or between 0 and proposal.Round exclusive. - if proposal.POLRound != -1 && - (proposal.POLRound < 0 || proposal.Round <= proposal.POLRound) { + // Verify POLRound, which must be -1 or between 0 inclusive and proposal.Round exclusive. + if proposal.POLRound < -1 || + (proposal.POLRound >= 0 && proposal.POLRound >= proposal.Round) { return ErrInvalidProposalPOLRound } diff --git a/types/vote_set.go b/types/vote_set.go index cdfa3d40d..0cf6cbb7f 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -158,7 +158,7 @@ func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) { if (vote.Height != voteSet.height) || (vote.Round != voteSet.round) || (vote.Type != voteSet.type_) { - return false, errors.Wrapf(ErrVoteUnexpectedStep, "Got %d/%d/%d, expected %d/%d/%d", + return false, errors.Wrapf(ErrVoteUnexpectedStep, "Expected %d/%d/%d, but got %d/%d/%d", voteSet.height, voteSet.round, voteSet.type_, vote.Height, vote.Round, vote.Type) } From b6d5b8b74574269e5c51ed9d14477e8b9e07def1 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Mon, 29 Oct 2018 14:16:50 +0100 Subject: [PATCH 17/35] Update to amino 0.14.0 (#2710) * WIP: update to amino 0.14.0 * update Changelog * Update to latest amino version (v0.14.0) --- CHANGELOG_PENDING.md | 1 + Gopkg.lock | 16 +-- Gopkg.toml | 2 +- Makefile | 4 +- types/block.go | 2 +- types/block_test.go | 12 +- types/evidence.go | 2 +- types/proto3/block.pb.go | 262 +++++++++++++++++++++++++++------------ types/proto3/block.proto | 8 +- types/vote.go | 2 +- 10 files changed, 206 insertions(+), 105 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 163c4649f..a56487ff1 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -50,6 +50,7 @@ BREAKING CHANGES: * [types] [\#2298](https://github.com/tendermint/tendermint/issues/2298) Remove `Index` and `Total` fields from `TxProof`. * [types] [\#2598](https://github.com/tendermint/tendermint/issues/2598) `VoteTypeXxx` are now of type `SignedMsgType byte` and named `XxxType`, eg. `PrevoteType`, `PrecommitType`. + * [types] [\#2682](https://github.com/tendermint/tendermint/issues/2682) Use proto3 `varint` encoding for ints that are usually unsigned (instead of zigzag encoding). * Blockchain Protocol * [types] Update SignBytes for `Vote`/`Proposal`/`Heartbeat`: diff --git a/Gopkg.lock b/Gopkg.lock index 566fed4a2..513e0bd7a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -286,12 +286,12 @@ version = "v1.1.2" [[projects]] - digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f" + digest = "1:08d65904057412fc0270fc4812a1c90c594186819243160dc779a402d4b6d0bc" name = "github.com/spf13/cast" packages = ["."] pruneopts = "UT" - revision = "8965335b8c7107321228e3e3702cab9832751bac" - version = "v1.2.0" + revision = "8c9545af88b134710ab1cd196795e7f2388358d7" + version = "v1.3.0" [[projects]] digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" @@ -365,12 +365,12 @@ revision = "e5840949ff4fff0c56f9b6a541e22b63581ea9df" [[projects]] - digest = "1:5f52e817b6c9d52ddba70dece0ea31134d82a52c05bce98fbc739ab2a832df28" + digest = "1:10b3a599325740c84a7c81f3f3cb2e1fdb70b3ea01b7fa28495567a2519df431" name = "github.com/tendermint/go-amino" packages = ["."] pruneopts = "UT" - revision = "cb07448b240918aa8d8df4505153549b86b77134" - version = "v0.13.0" + revision = "6dcc6ddc143e116455c94b25c1004c99e0d0ca12" + version = "v0.14.0" [[projects]] digest = "1:72b71e3a29775e5752ed7a8012052a3dee165e27ec18cedddae5288058f09acf" @@ -415,14 +415,14 @@ [[projects]] branch = "master" - digest = "1:d1da39c9bac61327dbef1d8ef9f210425e99fd2924b6fb5f0bc587a193353637" + digest = "1:fd98d154bf152ad5a49600ede7d7341851bcdfe358b9b82e5ccdba818618167c" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "8a28ead16f52c8aaeffbf79239b251dfdf6c4f96" + revision = "2772b66316d2c587efeb188dcd5ebc6987656e84" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" diff --git a/Gopkg.toml b/Gopkg.toml index e24965dc1..955d6c6d1 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -58,7 +58,7 @@ [[constraint]] name = "github.com/tendermint/go-amino" - version = "v0.13.0" + version = "v0.14.0" [[constraint]] name = "google.golang.org/grpc" diff --git a/Makefile b/Makefile index 0b78574b9..4390b1fbb 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ install: ######################################## ### Protobuf -protoc_all: protoc_libs protoc_merkle protoc_abci protoc_grpc +protoc_all: protoc_libs protoc_merkle protoc_abci protoc_grpc protoc_proto3types %.pb.go: %.proto ## If you get the following error, @@ -52,6 +52,8 @@ protoc_all: protoc_libs protoc_merkle protoc_abci protoc_grpc # see protobuf section above protoc_abci: abci/types/types.pb.go +protoc_proto3types: types/proto3/block.pb.go + build_abci: @go build -i ./abci/cmd/... diff --git a/types/block.go b/types/block.go index 70b840c63..477e39997 100644 --- a/types/block.go +++ b/types/block.go @@ -15,7 +15,7 @@ import ( const ( // MaxHeaderBytes is a maximum header size (including amino overhead). - MaxHeaderBytes int64 = 537 + MaxHeaderBytes int64 = 533 // MaxAminoOverheadForBlock - maximum amino overhead to encode a block (up to // MaxBlockSizeBytes in size) not including it's parts except Data. diff --git a/types/block_test.go b/types/block_test.go index 341073980..28e73f661 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -292,9 +292,9 @@ func TestBlockMaxDataBytes(t *testing.T) { }{ 0: {-10, 1, 0, true, 0}, 1: {10, 1, 0, true, 0}, - 2: {750, 1, 0, true, 0}, - 3: {751, 1, 0, false, 0}, - 4: {752, 1, 0, false, 1}, + 2: {742, 1, 0, true, 0}, + 3: {743, 1, 0, false, 0}, + 4: {744, 1, 0, false, 1}, } for i, tc := range testCases { @@ -320,9 +320,9 @@ func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) { }{ 0: {-10, 1, true, 0}, 1: {10, 1, true, 0}, - 2: {833, 1, true, 0}, - 3: {834, 1, false, 0}, - 4: {835, 1, false, 1}, + 2: {824, 1, true, 0}, + 3: {825, 1, false, 0}, + 4: {826, 1, false, 1}, } for i, tc := range testCases { diff --git a/types/evidence.go b/types/evidence.go index 6d42ed22c..7a808d57b 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -14,7 +14,7 @@ import ( const ( // MaxEvidenceBytes is a maximum size of any evidence (including amino overhead). - MaxEvidenceBytes int64 = 444 + MaxEvidenceBytes int64 = 436 ) // ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid. diff --git a/types/proto3/block.pb.go b/types/proto3/block.pb.go index 7efc7ca7d..99dadac16 100644 --- a/types/proto3/block.pb.go +++ b/types/proto3/block.pb.go @@ -1,22 +1,9 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: block.proto +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: types/proto3/block.proto -/* -Package proto3 is a generated protocol buffer package. - -It is generated from these files: - block.proto - -It has these top-level messages: - PartSetHeader - BlockID - Header - Version - Timestamp -*/ package proto3 -import proto "github.com/golang/protobuf/proto" +import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" @@ -29,17 +16,39 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package type PartSetHeader struct { - Total int32 `protobuf:"zigzag32,1,opt,name=Total" json:"Total,omitempty"` - Hash []byte `protobuf:"bytes,2,opt,name=Hash,proto3" json:"Hash,omitempty"` + Total int32 `protobuf:"varint,1,opt,name=Total,proto3" json:"Total,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=Hash,proto3" json:"Hash,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } -func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } -func (*PartSetHeader) ProtoMessage() {} -func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } +func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } +func (*PartSetHeader) ProtoMessage() {} +func (*PartSetHeader) Descriptor() ([]byte, []int) { + return fileDescriptor_block_57c41dfc0fc285b3, []int{0} +} +func (m *PartSetHeader) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PartSetHeader.Unmarshal(m, b) +} +func (m *PartSetHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PartSetHeader.Marshal(b, m, deterministic) +} +func (dst *PartSetHeader) XXX_Merge(src proto.Message) { + xxx_messageInfo_PartSetHeader.Merge(dst, src) +} +func (m *PartSetHeader) XXX_Size() int { + return xxx_messageInfo_PartSetHeader.Size(m) +} +func (m *PartSetHeader) XXX_DiscardUnknown() { + xxx_messageInfo_PartSetHeader.DiscardUnknown(m) +} + +var xxx_messageInfo_PartSetHeader proto.InternalMessageInfo func (m *PartSetHeader) GetTotal() int32 { if m != nil { @@ -56,14 +65,36 @@ func (m *PartSetHeader) GetHash() []byte { } type BlockID struct { - Hash []byte `protobuf:"bytes,1,opt,name=Hash,proto3" json:"Hash,omitempty"` - PartsHeader *PartSetHeader `protobuf:"bytes,2,opt,name=PartsHeader" json:"PartsHeader,omitempty"` + Hash []byte `protobuf:"bytes,1,opt,name=Hash,proto3" json:"Hash,omitempty"` + PartsHeader *PartSetHeader `protobuf:"bytes,2,opt,name=PartsHeader" json:"PartsHeader,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *BlockID) Reset() { *m = BlockID{} } -func (m *BlockID) String() string { return proto.CompactTextString(m) } -func (*BlockID) ProtoMessage() {} -func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (m *BlockID) Reset() { *m = BlockID{} } +func (m *BlockID) String() string { return proto.CompactTextString(m) } +func (*BlockID) ProtoMessage() {} +func (*BlockID) Descriptor() ([]byte, []int) { + return fileDescriptor_block_57c41dfc0fc285b3, []int{1} +} +func (m *BlockID) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BlockID.Unmarshal(m, b) +} +func (m *BlockID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BlockID.Marshal(b, m, deterministic) +} +func (dst *BlockID) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockID.Merge(dst, src) +} +func (m *BlockID) XXX_Size() int { + return xxx_messageInfo_BlockID.Size(m) +} +func (m *BlockID) XXX_DiscardUnknown() { + xxx_messageInfo_BlockID.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockID proto.InternalMessageInfo func (m *BlockID) GetHash() []byte { if m != nil { @@ -82,11 +113,11 @@ func (m *BlockID) GetPartsHeader() *PartSetHeader { type Header struct { // basic block info Version *Version `protobuf:"bytes,1,opt,name=Version" json:"Version,omitempty"` - ChainID string `protobuf:"bytes,2,opt,name=ChainID" json:"ChainID,omitempty"` - Height int64 `protobuf:"zigzag64,3,opt,name=Height" json:"Height,omitempty"` + ChainID string `protobuf:"bytes,2,opt,name=ChainID,proto3" json:"ChainID,omitempty"` + Height int64 `protobuf:"varint,3,opt,name=Height,proto3" json:"Height,omitempty"` Time *Timestamp `protobuf:"bytes,4,opt,name=Time" json:"Time,omitempty"` - NumTxs int64 `protobuf:"zigzag64,5,opt,name=NumTxs" json:"NumTxs,omitempty"` - TotalTxs int64 `protobuf:"zigzag64,6,opt,name=TotalTxs" json:"TotalTxs,omitempty"` + NumTxs int64 `protobuf:"varint,5,opt,name=NumTxs,proto3" json:"NumTxs,omitempty"` + TotalTxs int64 `protobuf:"varint,6,opt,name=TotalTxs,proto3" json:"TotalTxs,omitempty"` // prev block info LastBlockID *BlockID `protobuf:"bytes,7,opt,name=LastBlockID" json:"LastBlockID,omitempty"` // hashes of block data @@ -99,14 +130,36 @@ type Header struct { AppHash []byte `protobuf:"bytes,13,opt,name=AppHash,proto3" json:"AppHash,omitempty"` LastResultsHash []byte `protobuf:"bytes,14,opt,name=LastResultsHash,proto3" json:"LastResultsHash,omitempty"` // consensus info - EvidenceHash []byte `protobuf:"bytes,15,opt,name=EvidenceHash,proto3" json:"EvidenceHash,omitempty"` - ProposerAddress []byte `protobuf:"bytes,16,opt,name=ProposerAddress,proto3" json:"ProposerAddress,omitempty"` + EvidenceHash []byte `protobuf:"bytes,15,opt,name=EvidenceHash,proto3" json:"EvidenceHash,omitempty"` + ProposerAddress []byte `protobuf:"bytes,16,opt,name=ProposerAddress,proto3" json:"ProposerAddress,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Header) Reset() { *m = Header{} } -func (m *Header) String() string { return proto.CompactTextString(m) } -func (*Header) ProtoMessage() {} -func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (m *Header) Reset() { *m = Header{} } +func (m *Header) String() string { return proto.CompactTextString(m) } +func (*Header) ProtoMessage() {} +func (*Header) Descriptor() ([]byte, []int) { + return fileDescriptor_block_57c41dfc0fc285b3, []int{2} +} +func (m *Header) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Header.Unmarshal(m, b) +} +func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Header.Marshal(b, m, deterministic) +} +func (dst *Header) XXX_Merge(src proto.Message) { + xxx_messageInfo_Header.Merge(dst, src) +} +func (m *Header) XXX_Size() int { + return xxx_messageInfo_Header.Size(m) +} +func (m *Header) XXX_DiscardUnknown() { + xxx_messageInfo_Header.DiscardUnknown(m) +} + +var xxx_messageInfo_Header proto.InternalMessageInfo func (m *Header) GetVersion() *Version { if m != nil { @@ -221,14 +274,36 @@ func (m *Header) GetProposerAddress() []byte { } type Version struct { - Block uint64 `protobuf:"varint,1,opt,name=Block" json:"Block,omitempty"` - App uint64 `protobuf:"varint,2,opt,name=App" json:"App,omitempty"` + Block uint64 `protobuf:"varint,1,opt,name=Block,proto3" json:"Block,omitempty"` + App uint64 `protobuf:"varint,2,opt,name=App,proto3" json:"App,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Version) Reset() { *m = Version{} } -func (m *Version) String() string { return proto.CompactTextString(m) } -func (*Version) ProtoMessage() {} -func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (m *Version) Reset() { *m = Version{} } +func (m *Version) String() string { return proto.CompactTextString(m) } +func (*Version) ProtoMessage() {} +func (*Version) Descriptor() ([]byte, []int) { + return fileDescriptor_block_57c41dfc0fc285b3, []int{3} +} +func (m *Version) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Version.Unmarshal(m, b) +} +func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Version.Marshal(b, m, deterministic) +} +func (dst *Version) XXX_Merge(src proto.Message) { + xxx_messageInfo_Version.Merge(dst, src) +} +func (m *Version) XXX_Size() int { + return xxx_messageInfo_Version.Size(m) +} +func (m *Version) XXX_DiscardUnknown() { + xxx_messageInfo_Version.DiscardUnknown(m) +} + +var xxx_messageInfo_Version proto.InternalMessageInfo func (m *Version) GetBlock() uint64 { if m != nil { @@ -250,14 +325,36 @@ func (m *Version) GetApp() uint64 { // https://github.com/google/protobuf/blob/d2980062c859649523d5fd51d6b55ab310e47482/src/google/protobuf/timestamp.proto#L123-L135 // NOTE/XXX: nanos do not get skipped if they are zero in amino. type Timestamp struct { - Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` - Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` + Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"` + Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Timestamp) Reset() { *m = Timestamp{} } -func (m *Timestamp) String() string { return proto.CompactTextString(m) } -func (*Timestamp) ProtoMessage() {} -func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (m *Timestamp) Reset() { *m = Timestamp{} } +func (m *Timestamp) String() string { return proto.CompactTextString(m) } +func (*Timestamp) ProtoMessage() {} +func (*Timestamp) Descriptor() ([]byte, []int) { + return fileDescriptor_block_57c41dfc0fc285b3, []int{4} +} +func (m *Timestamp) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Timestamp.Unmarshal(m, b) +} +func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic) +} +func (dst *Timestamp) XXX_Merge(src proto.Message) { + xxx_messageInfo_Timestamp.Merge(dst, src) +} +func (m *Timestamp) XXX_Size() int { + return xxx_messageInfo_Timestamp.Size(m) +} +func (m *Timestamp) XXX_DiscardUnknown() { + xxx_messageInfo_Timestamp.DiscardUnknown(m) +} + +var xxx_messageInfo_Timestamp proto.InternalMessageInfo func (m *Timestamp) GetSeconds() int64 { if m != nil { @@ -281,36 +378,37 @@ func init() { proto.RegisterType((*Timestamp)(nil), "proto3.Timestamp") } -func init() { proto.RegisterFile("block.proto", fileDescriptor0) } +func init() { proto.RegisterFile("types/proto3/block.proto", fileDescriptor_block_57c41dfc0fc285b3) } -var fileDescriptor0 = []byte{ - // 443 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0xcd, 0x6a, 0xdb, 0x40, - 0x10, 0x46, 0xb5, 0x6c, 0xc7, 0x23, 0x3b, 0x4e, 0x86, 0xb6, 0x88, 0x9e, 0x8c, 0x68, 0x8b, 0x7b, - 0x31, 0x24, 0x39, 0x94, 0xd2, 0x93, 0x6b, 0x17, 0x12, 0x28, 0x21, 0x6c, 0x8d, 0xef, 0x1b, 0x6b, - 0xa9, 0x45, 0x2d, 0xad, 0xd0, 0xac, 0x4b, 0xde, 0xb0, 0xaf, 0x55, 0x66, 0x56, 0x52, 0x23, 0x93, - 0x93, 0xf7, 0xfb, 0x99, 0x6f, 0x76, 0xc7, 0x23, 0x88, 0x1e, 0x0f, 0x76, 0xf7, 0x7b, 0x51, 0x56, - 0xd6, 0x59, 0x1c, 0xc8, 0xcf, 0x4d, 0xf2, 0x05, 0x26, 0x0f, 0xba, 0x72, 0x3f, 0x8d, 0xbb, 0x35, - 0x3a, 0x35, 0x15, 0xbe, 0x86, 0xfe, 0xc6, 0x3a, 0x7d, 0x88, 0x83, 0x59, 0x30, 0xbf, 0x54, 0x1e, - 0x20, 0x42, 0x78, 0xab, 0x69, 0x1f, 0xbf, 0x9a, 0x05, 0xf3, 0xb1, 0x92, 0x73, 0xb2, 0x85, 0xe1, - 0x37, 0x4e, 0xbc, 0x5b, 0xb7, 0x72, 0xf0, 0x5f, 0xc6, 0xcf, 0x10, 0x71, 0x32, 0xf9, 0x5c, 0xa9, - 0x8c, 0xae, 0xdf, 0xf8, 0xf6, 0x37, 0x8b, 0x4e, 0x53, 0xf5, 0xdc, 0x99, 0xfc, 0x0d, 0x61, 0x50, - 0x5f, 0xe6, 0x13, 0x0c, 0xb7, 0xa6, 0xa2, 0xcc, 0x16, 0x12, 0x1d, 0x5d, 0x4f, 0x9b, 0xfa, 0x9a, - 0x56, 0x8d, 0x8e, 0x31, 0x0c, 0x57, 0x7b, 0x9d, 0x15, 0x77, 0x6b, 0x69, 0x35, 0x52, 0x0d, 0xc4, - 0xb7, 0x1c, 0x97, 0xfd, 0xda, 0xbb, 0xb8, 0x37, 0x0b, 0xe6, 0xa8, 0x6a, 0x84, 0x1f, 0x20, 0xdc, - 0x64, 0xb9, 0x89, 0x43, 0x49, 0xbe, 0x6c, 0x92, 0x99, 0x23, 0xa7, 0xf3, 0x52, 0x89, 0xcc, 0xe5, - 0xf7, 0xc7, 0x7c, 0xf3, 0x44, 0x71, 0xdf, 0x97, 0x7b, 0x84, 0xef, 0xe0, 0x4c, 0x66, 0xc3, 0xca, - 0x40, 0x94, 0x16, 0xe3, 0x15, 0x44, 0x3f, 0x34, 0xb9, 0x7a, 0x3c, 0xf1, 0xb0, 0x7b, 0xf7, 0x9a, - 0x56, 0xcf, 0x3d, 0xf8, 0x11, 0xce, 0x19, 0xae, 0x6c, 0x9e, 0x67, 0x4e, 0x86, 0x79, 0x26, 0xc3, - 0x3c, 0x61, 0xb9, 0xed, 0x5a, 0x3b, 0x2d, 0x8e, 0x91, 0x38, 0x5a, 0xcc, 0x19, 0x5b, 0x7d, 0xc8, - 0x52, 0xed, 0x6c, 0x45, 0xe2, 0x00, 0x9f, 0xd1, 0x65, 0x71, 0x01, 0x78, 0x6f, 0x9e, 0xdc, 0x89, - 0x37, 0x12, 0xef, 0x0b, 0x0a, 0xbe, 0x87, 0xc9, 0xca, 0x16, 0x64, 0x0a, 0x3a, 0x7a, 0xeb, 0x58, - 0xac, 0x5d, 0x92, 0xff, 0x81, 0x65, 0x59, 0x8a, 0x3e, 0x11, 0xbd, 0x81, 0x38, 0x87, 0x29, 0xbf, - 0x42, 0x19, 0x3a, 0x1e, 0x9c, 0x4f, 0x38, 0x17, 0xc7, 0x29, 0x8d, 0x09, 0x8c, 0xbf, 0xff, 0xc9, - 0x52, 0x53, 0xec, 0x8c, 0xd8, 0xa6, 0x62, 0xeb, 0x70, 0x9c, 0xf6, 0x50, 0xd9, 0xd2, 0x92, 0xa9, - 0x96, 0x69, 0x5a, 0x19, 0xa2, 0xf8, 0xc2, 0xa7, 0x9d, 0xd0, 0xc9, 0x55, 0xbb, 0x3e, 0xbc, 0xd6, - 0x32, 0x69, 0xd9, 0xa3, 0x50, 0x79, 0x80, 0x17, 0xd0, 0x5b, 0x96, 0xa5, 0x2c, 0x4c, 0xa8, 0xf8, - 0x98, 0x7c, 0x85, 0x51, 0xbb, 0x00, 0xfc, 0x22, 0x32, 0x3b, 0x5b, 0xa4, 0x24, 0x65, 0x3d, 0xd5, - 0x40, 0x8e, 0x2b, 0x74, 0x61, 0x49, 0x4a, 0xfb, 0xca, 0x83, 0xc7, 0xfa, 0xa3, 0xfa, 0x17, 0x00, - 0x00, 0xff, 0xff, 0x8f, 0x82, 0xc0, 0x0c, 0x6a, 0x03, 0x00, 0x00, +var fileDescriptor_block_57c41dfc0fc285b3 = []byte{ + // 451 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0x5f, 0x6f, 0xd3, 0x30, + 0x10, 0x57, 0x68, 0xda, 0xae, 0x97, 0x76, 0x1d, 0x27, 0x40, 0x16, 0x4f, 0x55, 0x04, 0xa8, 0xbc, + 0x74, 0xda, 0xf6, 0x80, 0x10, 0x4f, 0xa5, 0x45, 0xda, 0x24, 0x34, 0x4d, 0xa6, 0xea, 0xbb, 0xd7, + 0x58, 0x34, 0xa2, 0x89, 0xa3, 0x9c, 0x8b, 0xc6, 0x27, 0xe4, 0x6b, 0x21, 0x9f, 0x93, 0xd0, 0x44, + 0x7b, 0xf3, 0xef, 0xcf, 0xfd, 0xce, 0xbe, 0x5c, 0x40, 0xd8, 0x3f, 0x85, 0xa6, 0xcb, 0xa2, 0x34, + 0xd6, 0xdc, 0x5c, 0x3e, 0x1e, 0xcc, 0xee, 0xd7, 0x82, 0x01, 0x0e, 0x3c, 0x17, 0x7f, 0x86, 0xc9, + 0x83, 0x2a, 0xed, 0x0f, 0x6d, 0x6f, 0xb5, 0x4a, 0x74, 0x89, 0xaf, 0xa0, 0xbf, 0x31, 0x56, 0x1d, + 0x44, 0x30, 0x0b, 0xe6, 0x7d, 0xe9, 0x01, 0x22, 0x84, 0xb7, 0x8a, 0xf6, 0xe2, 0xc5, 0x2c, 0x98, + 0x8f, 0x25, 0x9f, 0xe3, 0x2d, 0x0c, 0xbf, 0xba, 0xc4, 0xbb, 0x75, 0x23, 0x07, 0xff, 0x65, 0xfc, + 0x04, 0x91, 0x4b, 0x26, 0x9f, 0xcb, 0x95, 0xd1, 0xf5, 0x6b, 0xdf, 0xfe, 0x66, 0xd1, 0x6a, 0x2a, + 0x4f, 0x9d, 0xf1, 0xdf, 0x10, 0x06, 0xd5, 0x65, 0x3e, 0xc2, 0x70, 0xab, 0x4b, 0x4a, 0x4d, 0xce, + 0xd1, 0xd1, 0xf5, 0xb4, 0xae, 0xaf, 0x68, 0x59, 0xeb, 0x28, 0x60, 0xb8, 0xda, 0xab, 0x34, 0xbf, + 0x5b, 0x73, 0xab, 0x91, 0xac, 0x21, 0xbe, 0x71, 0x71, 0xe9, 0xcf, 0xbd, 0x15, 0xbd, 0x59, 0x30, + 0xef, 0xc9, 0x0a, 0xe1, 0x7b, 0x08, 0x37, 0x69, 0xa6, 0x45, 0xc8, 0xc9, 0x2f, 0xeb, 0x64, 0xc7, + 0x91, 0x55, 0x59, 0x21, 0x59, 0x76, 0xe5, 0xf7, 0xc7, 0x6c, 0xf3, 0x44, 0xa2, 0xef, 0xcb, 0x3d, + 0xc2, 0xb7, 0x70, 0xc6, 0xb3, 0x71, 0xca, 0x80, 0x95, 0x06, 0xe3, 0x15, 0x44, 0xdf, 0x15, 0xd9, + 0x6a, 0x3c, 0x62, 0xd8, 0xbe, 0x7b, 0x45, 0xcb, 0x53, 0x0f, 0x7e, 0x80, 0x73, 0x07, 0x57, 0x26, + 0xcb, 0x52, 0xcb, 0xc3, 0x3c, 0xe3, 0x61, 0x76, 0x58, 0xd7, 0x76, 0xad, 0xac, 0x62, 0xc7, 0x88, + 0x1d, 0x0d, 0x76, 0x19, 0x5b, 0x75, 0x48, 0x13, 0x65, 0x4d, 0x49, 0xec, 0x00, 0x9f, 0xd1, 0x66, + 0x71, 0x01, 0x78, 0xaf, 0x9f, 0x6c, 0xc7, 0x1b, 0xb1, 0xf7, 0x19, 0x05, 0xdf, 0xc1, 0x64, 0x65, + 0x72, 0xd2, 0x39, 0x1d, 0xbd, 0x75, 0xcc, 0xd6, 0x36, 0xe9, 0xbe, 0xc0, 0xb2, 0x28, 0x58, 0x9f, + 0xb0, 0x5e, 0x43, 0x9c, 0xc3, 0xd4, 0xbd, 0x42, 0x6a, 0x3a, 0x1e, 0xac, 0x4f, 0x38, 0x67, 0x47, + 0x97, 0xc6, 0x18, 0xc6, 0xdf, 0x7e, 0xa7, 0x89, 0xce, 0x77, 0x9a, 0x6d, 0x53, 0xb6, 0xb5, 0x38, + 0x97, 0xf6, 0x50, 0x9a, 0xc2, 0x90, 0x2e, 0x97, 0x49, 0x52, 0x6a, 0x22, 0x71, 0xe1, 0xd3, 0x3a, + 0x74, 0x7c, 0xd5, 0xac, 0x8f, 0x5b, 0x6b, 0x9e, 0x34, 0xef, 0x51, 0x28, 0x3d, 0xc0, 0x0b, 0xe8, + 0x2d, 0x8b, 0x82, 0x17, 0x26, 0x94, 0xee, 0x18, 0x7f, 0x81, 0x51, 0xb3, 0x00, 0xee, 0x45, 0xa4, + 0x77, 0x26, 0x4f, 0x88, 0xcb, 0x7a, 0xb2, 0x86, 0x2e, 0x2e, 0x57, 0xb9, 0x21, 0x2e, 0xed, 0x4b, + 0x0f, 0x1e, 0xab, 0x9f, 0xea, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4f, 0x84, 0xb5, 0xf8, 0x77, + 0x03, 0x00, 0x00, } diff --git a/types/proto3/block.proto b/types/proto3/block.proto index 1c76746c2..93cf1bc75 100644 --- a/types/proto3/block.proto +++ b/types/proto3/block.proto @@ -4,7 +4,7 @@ package proto3; message PartSetHeader { - sint32 Total = 1; + int32 Total = 1; bytes Hash = 2; } @@ -17,10 +17,10 @@ message Header { // basic block info Version Version = 1; string ChainID = 2; - sint64 Height = 3; + int64 Height = 3; Timestamp Time = 4; - sint64 NumTxs = 5; - sint64 TotalTxs = 6; + int64 NumTxs = 5; + int64 TotalTxs = 6; // prev block info BlockID LastBlockID = 7; diff --git a/types/vote.go b/types/vote.go index e1095bf15..333684fc2 100644 --- a/types/vote.go +++ b/types/vote.go @@ -12,7 +12,7 @@ import ( const ( // MaxVoteBytes is a maximum vote size (including amino overhead). - MaxVoteBytes int64 = 203 + MaxVoteBytes int64 = 199 ) var ( From b24de1c01cc8627cf72b4f5c1295f436a9904aed Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 29 Oct 2018 10:13:11 -0400 Subject: [PATCH 18/35] update changelog pending and readme (#2725) --- CHANGELOG_PENDING.md | 17 +++++++++++------ README.md | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index a56487ff1..b8a9102af 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -2,7 +2,7 @@ ## v0.26.0 -*October 19, 2018* +*October 29, 2018* Special thanks to external contributors on this release: @bradyjoestar, @connorwstein, @goolAdapter, @HaoyangLiu, @@ -17,9 +17,14 @@ It also includes our first take at a generalized merkle proof system. See the [UPGRADING.md](UPGRADING.md#v0.26.0) for details on upgrading to the new version. +Please note that we are still making breaking changes to the protocols. +While the new Version fields should help us to keep the software backwards compatible +even while upgrading the protocols, we cannot guarantee that new releases will +be compatible with old chains just yet. Thanks for bearing with us! + Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint). -BREAKING CHANGES: +### BREAKING CHANGES: * CLI/RPC/Config * [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) timeouts as time.Duration, not ints @@ -50,7 +55,6 @@ BREAKING CHANGES: * [types] [\#2298](https://github.com/tendermint/tendermint/issues/2298) Remove `Index` and `Total` fields from `TxProof`. * [types] [\#2598](https://github.com/tendermint/tendermint/issues/2598) `VoteTypeXxx` are now of type `SignedMsgType byte` and named `XxxType`, eg. `PrevoteType`, `PrecommitType`. - * [types] [\#2682](https://github.com/tendermint/tendermint/issues/2682) Use proto3 `varint` encoding for ints that are usually unsigned (instead of zigzag encoding). * Blockchain Protocol * [types] Update SignBytes for `Vote`/`Proposal`/`Heartbeat`: @@ -66,17 +70,18 @@ BREAKING CHANGES: * [state] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Require block.Version to match state.Version * [types] [\#2670](https://github.com/tendermint/tendermint/issues/2670) Header.Hash() builds Merkle tree out of fields in the same order they appear in the header, instead of sorting by field name + * [types] [\#2682](https://github.com/tendermint/tendermint/issues/2682) Use proto3 `varint` encoding for ints that are usually unsigned (instead of zigzag encoding). * P2P Protocol * [p2p] [\#2654](https://github.com/tendermint/tendermint/issues/2654) Add `ProtocolVersion` struct with protocol versions to top of DefaultNodeInfo and require `ProtocolVersion.Block` to match during peer handshake -FEATURES: +### FEATURES: - [abci] [\#2557](https://github.com/tendermint/tendermint/issues/2557) Add `Codespace` field to `Response{CheckTx, DeliverTx, Query}` - [abci] [\#2662](https://github.com/tendermint/tendermint/issues/2662) Add `BlockVersion` and `P2PVersion` to `RequestInfo` - [crypto/merkle] [\#2298](https://github.com/tendermint/tendermint/issues/2298) General Merkle Proof scheme for chaining various types of Merkle trees together -IMPROVEMENTS: +### IMPROVEMENTS: - Additional Metrics - [consensus] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) - [p2p] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) @@ -85,7 +90,7 @@ IMPROVEMENTS: github.com/tendermint/crypto - [tools] [\#2238](https://github.com/tendermint/tendermint/issues/2238) Binary dependencies are now locked to a specific git commit -BUG FIXES: +### BUG FIXES: - [autofile] [\#2428](https://github.com/tendermint/tendermint/issues/2428) Group.RotateFile need call Flush() before rename (@goolAdapter) - [common] [\#2533](https://github.com/tendermint/tendermint/issues/2533) Fixed a bug in the `BitArray.Or` method - [common] [\#2506](https://github.com/tendermint/tendermint/issues/2506) Fixed a bug in the `BitArray.Sub` method (@james-ray) diff --git a/README.md b/README.md index 069f9f13e..328557ae3 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ We are also still making breaking changes to the protocol and the APIs. Thus, we tag the releases as *alpha software*. In any case, if you intend to run Tendermint in production, -please [contact us](https://riot.im/app/#/room/#tendermint:matrix.org) :) +please [contact us](mailto:partners@tendermint.com) and [join the chat](https://riot.im/app/#/room/#tendermint:matrix.org). ## Security From cdc252b8182deb749150c33a2cc985e12e3c8437 Mon Sep 17 00:00:00 2001 From: Zach Date: Tue, 30 Oct 2018 10:34:51 -0400 Subject: [PATCH 19/35] add fail-test file instead of dep, closes #2638 (#2728) original author of this file is @ebuchman: https://github.com/ebuchman/fail-test --- Gopkg.lock | 8 ----- Gopkg.toml | 4 --- consensus/state.go | 2 +- libs/fail/fail.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++ state/execution.go | 2 +- 5 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 libs/fail/fail.go diff --git a/Gopkg.lock b/Gopkg.lock index 513e0bd7a..f4656e6ba 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -35,13 +35,6 @@ revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" version = "v1.1.1" -[[projects]] - digest = "1:c7644c73a3d23741fdba8a99b1464e021a224b7e205be497271a8003a15ca41b" - name = "github.com/ebuchman/fail-test" - packages = ["."] - pruneopts = "UT" - revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" - [[projects]] digest = "1:544229a3ca0fb2dd5ebc2896d3d2ff7ce096d9751635301e44e37e761349ee70" name = "github.com/fortytw2/leaktest" @@ -503,7 +496,6 @@ input-imports = [ "github.com/btcsuite/btcutil/base58", "github.com/btcsuite/btcutil/bech32", - "github.com/ebuchman/fail-test", "github.com/fortytw2/leaktest", "github.com/go-kit/kit/log", "github.com/go-kit/kit/log/level", diff --git a/Gopkg.toml b/Gopkg.toml index 955d6c6d1..47418bef3 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -81,10 +81,6 @@ name = "github.com/jmhodges/levigo" revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" -[[constraint]] - name = "github.com/ebuchman/fail-test" - revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" - # last revision used by go-crypto [[constraint]] name = "github.com/btcsuite/btcutil" diff --git a/consensus/state.go b/consensus/state.go index 0b079f13d..40aeeb7a4 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -9,8 +9,8 @@ import ( "sync" "time" - fail "github.com/ebuchman/fail-test" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/libs/fail" "github.com/tendermint/tendermint/libs/log" tmtime "github.com/tendermint/tendermint/types/time" diff --git a/libs/fail/fail.go b/libs/fail/fail.go new file mode 100644 index 000000000..edfca13e3 --- /dev/null +++ b/libs/fail/fail.go @@ -0,0 +1,78 @@ +package fail + +import ( + "fmt" + "math/rand" + "os" + "strconv" +) + +var callIndexToFail int + +func init() { + callIndexToFailS := os.Getenv("FAIL_TEST_INDEX") + + if callIndexToFailS == "" { + callIndexToFail = -1 + } else { + var err error + callIndexToFail, err = strconv.Atoi(callIndexToFailS) + if err != nil { + callIndexToFail = -1 + } + } +} + +// Fail when FAIL_TEST_INDEX == callIndex +var ( + callIndex int //indexes Fail calls + + callRandIndex int // indexes a run of FailRand calls + callRandIndexToFail = -1 // the callRandIndex to fail on in FailRand +) + +func Fail() { + if callIndexToFail < 0 { + return + } + + if callIndex == callIndexToFail { + Exit() + } + + callIndex += 1 +} + +// FailRand should be called n successive times. +// It will fail on a random one of those calls +// n must be greater than 0 +func FailRand(n int) { + if callIndexToFail < 0 { + return + } + + if callRandIndexToFail < 0 { + // first call in the loop, pick a random index to fail at + callRandIndexToFail = rand.Intn(n) + callRandIndex = 0 + } + + if callIndex == callIndexToFail { + if callRandIndex == callRandIndexToFail { + Exit() + } + } + + callRandIndex += 1 + + if callRandIndex == n { + callIndex += 1 + } +} + +func Exit() { + fmt.Printf("*** fail-test %d ***\n", callIndex) + proc, _ := os.FindProcess(os.Getpid()) + proc.Signal(os.Interrupt) + // panic(fmt.Sprintf("*** fail-test %d ***", callIndex)) +} diff --git a/state/execution.go b/state/execution.go index 68298a8d2..72f6cc978 100644 --- a/state/execution.go +++ b/state/execution.go @@ -4,9 +4,9 @@ import ( "fmt" "time" - "github.com/ebuchman/fail-test" abci "github.com/tendermint/tendermint/abci/types" dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/libs/fail" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/mempool" "github.com/tendermint/tendermint/proxy" From 56d7160606b16dc0a3d56c9b9b9d2b9aeb2c6484 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 30 Oct 2018 08:36:53 -0700 Subject: [PATCH 20/35] Add ValidatorPubkeyTypes as a consensus param (#2636) * Add ValidatorPubkeyTypes as a consensus param Ref #2414 * update spec * address anton's comment * Switch to Validator and Validator Params * Correct changelog entry * Address bucky's comments! * forgot to update changelog * fix typo * fix Params naming --- CHANGELOG_PENDING.md | 2 + abci/types/types.pb.go | 914 ++++++++++++++++++++++++------------- abci/types/types.proto | 13 +- abci/types/typespb_test.go | 158 ++++++- docs/spec/abci/abci.md | 13 +- evidence/pool.go | 2 +- evidence/pool_test.go | 2 +- evidence/reactor.go | 2 +- state/execution.go | 2 +- state/state_test.go | 8 +- state/store.go | 2 +- state/validation.go | 2 +- types/params.go | 72 ++- types/params_test.go | 69 +-- types/protobuf.go | 24 +- types/protobuf_test.go | 1 - 16 files changed, 893 insertions(+), 393 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index b8a9102af..5c25a4b19 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -57,6 +57,8 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi `PrecommitType`. * Blockchain Protocol + * [abci] [\#2636](https://github.com/tendermint/tendermint/issues/2636) Add ValidatorParams field to ConsensusParams. + (Used to control which pubkey types validators can use, by abci type) * [types] Update SignBytes for `Vote`/`Proposal`/`Heartbeat`: * [\#2459](https://github.com/tendermint/tendermint/issues/2459) Use amino encoding instead of JSON in `SignBytes`. * [\#2598](https://github.com/tendermint/tendermint/issues/2598) Reorder fields and use fixed sized encoding. diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index 6a70bb979..c867dffc8 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -61,7 +61,7 @@ func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{0} + return fileDescriptor_types_5b877df1938afe10, []int{0} } func (m *Request) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -483,7 +483,7 @@ func (m *RequestEcho) Reset() { *m = RequestEcho{} } func (m *RequestEcho) String() string { return proto.CompactTextString(m) } func (*RequestEcho) ProtoMessage() {} func (*RequestEcho) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{1} + return fileDescriptor_types_5b877df1938afe10, []int{1} } func (m *RequestEcho) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -529,7 +529,7 @@ func (m *RequestFlush) Reset() { *m = RequestFlush{} } func (m *RequestFlush) String() string { return proto.CompactTextString(m) } func (*RequestFlush) ProtoMessage() {} func (*RequestFlush) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{2} + return fileDescriptor_types_5b877df1938afe10, []int{2} } func (m *RequestFlush) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -571,7 +571,7 @@ func (m *RequestInfo) Reset() { *m = RequestInfo{} } func (m *RequestInfo) String() string { return proto.CompactTextString(m) } func (*RequestInfo) ProtoMessage() {} func (*RequestInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{3} + return fileDescriptor_types_5b877df1938afe10, []int{3} } func (m *RequestInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -634,7 +634,7 @@ func (m *RequestSetOption) Reset() { *m = RequestSetOption{} } func (m *RequestSetOption) String() string { return proto.CompactTextString(m) } func (*RequestSetOption) ProtoMessage() {} func (*RequestSetOption) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{4} + return fileDescriptor_types_5b877df1938afe10, []int{4} } func (m *RequestSetOption) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -692,7 +692,7 @@ func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } func (*RequestInitChain) ProtoMessage() {} func (*RequestInitChain) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{5} + return fileDescriptor_types_5b877df1938afe10, []int{5} } func (m *RequestInitChain) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -770,7 +770,7 @@ func (m *RequestQuery) Reset() { *m = RequestQuery{} } func (m *RequestQuery) String() string { return proto.CompactTextString(m) } func (*RequestQuery) ProtoMessage() {} func (*RequestQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{6} + return fileDescriptor_types_5b877df1938afe10, []int{6} } func (m *RequestQuery) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -827,7 +827,6 @@ func (m *RequestQuery) GetProve() bool { return false } -// NOTE: validators here have empty pubkeys. type RequestBeginBlock struct { Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` Header Header `protobuf:"bytes,2,opt,name=header" json:"header"` @@ -842,7 +841,7 @@ func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } func (*RequestBeginBlock) ProtoMessage() {} func (*RequestBeginBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{7} + return fileDescriptor_types_5b877df1938afe10, []int{7} } func (m *RequestBeginBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -910,7 +909,7 @@ func (m *RequestCheckTx) Reset() { *m = RequestCheckTx{} } func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) } func (*RequestCheckTx) ProtoMessage() {} func (*RequestCheckTx) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{8} + return fileDescriptor_types_5b877df1938afe10, []int{8} } func (m *RequestCheckTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -957,7 +956,7 @@ func (m *RequestDeliverTx) Reset() { *m = RequestDeliverTx{} } func (m *RequestDeliverTx) String() string { return proto.CompactTextString(m) } func (*RequestDeliverTx) ProtoMessage() {} func (*RequestDeliverTx) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{9} + return fileDescriptor_types_5b877df1938afe10, []int{9} } func (m *RequestDeliverTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1004,7 +1003,7 @@ func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) } func (*RequestEndBlock) ProtoMessage() {} func (*RequestEndBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{10} + return fileDescriptor_types_5b877df1938afe10, []int{10} } func (m *RequestEndBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1050,7 +1049,7 @@ func (m *RequestCommit) Reset() { *m = RequestCommit{} } func (m *RequestCommit) String() string { return proto.CompactTextString(m) } func (*RequestCommit) ProtoMessage() {} func (*RequestCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{11} + return fileDescriptor_types_5b877df1938afe10, []int{11} } func (m *RequestCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1103,7 +1102,7 @@ func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{12} + return fileDescriptor_types_5b877df1938afe10, []int{12} } func (m *Response) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1556,7 +1555,7 @@ func (m *ResponseException) Reset() { *m = ResponseException{} } func (m *ResponseException) String() string { return proto.CompactTextString(m) } func (*ResponseException) ProtoMessage() {} func (*ResponseException) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{13} + return fileDescriptor_types_5b877df1938afe10, []int{13} } func (m *ResponseException) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1603,7 +1602,7 @@ func (m *ResponseEcho) Reset() { *m = ResponseEcho{} } func (m *ResponseEcho) String() string { return proto.CompactTextString(m) } func (*ResponseEcho) ProtoMessage() {} func (*ResponseEcho) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{14} + return fileDescriptor_types_5b877df1938afe10, []int{14} } func (m *ResponseEcho) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1649,7 +1648,7 @@ func (m *ResponseFlush) Reset() { *m = ResponseFlush{} } func (m *ResponseFlush) String() string { return proto.CompactTextString(m) } func (*ResponseFlush) ProtoMessage() {} func (*ResponseFlush) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{15} + return fileDescriptor_types_5b877df1938afe10, []int{15} } func (m *ResponseFlush) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1693,7 +1692,7 @@ func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } func (m *ResponseInfo) String() string { return proto.CompactTextString(m) } func (*ResponseInfo) ProtoMessage() {} func (*ResponseInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{16} + return fileDescriptor_types_5b877df1938afe10, []int{16} } func (m *ResponseInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1772,7 +1771,7 @@ func (m *ResponseSetOption) Reset() { *m = ResponseSetOption{} } func (m *ResponseSetOption) String() string { return proto.CompactTextString(m) } func (*ResponseSetOption) ProtoMessage() {} func (*ResponseSetOption) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{17} + return fileDescriptor_types_5b877df1938afe10, []int{17} } func (m *ResponseSetOption) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1834,7 +1833,7 @@ func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } func (*ResponseInitChain) ProtoMessage() {} func (*ResponseInitChain) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{18} + return fileDescriptor_types_5b877df1938afe10, []int{18} } func (m *ResponseInitChain) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1897,7 +1896,7 @@ func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } func (*ResponseQuery) ProtoMessage() {} func (*ResponseQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{19} + return fileDescriptor_types_5b877df1938afe10, []int{19} } func (m *ResponseQuery) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2000,7 +1999,7 @@ func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } func (*ResponseBeginBlock) ProtoMessage() {} func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{20} + return fileDescriptor_types_5b877df1938afe10, []int{20} } func (m *ResponseBeginBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2054,7 +2053,7 @@ func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } func (*ResponseCheckTx) ProtoMessage() {} func (*ResponseCheckTx) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{21} + return fileDescriptor_types_5b877df1938afe10, []int{21} } func (m *ResponseCheckTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2157,7 +2156,7 @@ func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } func (*ResponseDeliverTx) ProtoMessage() {} func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{22} + return fileDescriptor_types_5b877df1938afe10, []int{22} } func (m *ResponseDeliverTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2255,7 +2254,7 @@ func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } func (*ResponseEndBlock) ProtoMessage() {} func (*ResponseEndBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{23} + return fileDescriptor_types_5b877df1938afe10, []int{23} } func (m *ResponseEndBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2317,7 +2316,7 @@ func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } func (*ResponseCommit) ProtoMessage() {} func (*ResponseCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{24} + return fileDescriptor_types_5b877df1938afe10, []int{24} } func (m *ResponseCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2356,18 +2355,19 @@ func (m *ResponseCommit) GetData() []byte { // ConsensusParams contains all consensus-relevant parameters // that can be adjusted by the abci app type ConsensusParams struct { - BlockSize *BlockSize `protobuf:"bytes,1,opt,name=block_size,json=blockSize" json:"block_size,omitempty"` - EvidenceParams *EvidenceParams `protobuf:"bytes,2,opt,name=evidence_params,json=evidenceParams" json:"evidence_params,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + BlockSize *BlockSizeParams `protobuf:"bytes,1,opt,name=block_size,json=blockSize" json:"block_size,omitempty"` + Evidence *EvidenceParams `protobuf:"bytes,2,opt,name=evidence" json:"evidence,omitempty"` + Validator *ValidatorParams `protobuf:"bytes,3,opt,name=validator" json:"validator,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } func (m *ConsensusParams) String() string { return proto.CompactTextString(m) } func (*ConsensusParams) ProtoMessage() {} func (*ConsensusParams) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{25} + return fileDescriptor_types_5b877df1938afe10, []int{25} } func (m *ConsensusParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2396,22 +2396,29 @@ func (m *ConsensusParams) XXX_DiscardUnknown() { var xxx_messageInfo_ConsensusParams proto.InternalMessageInfo -func (m *ConsensusParams) GetBlockSize() *BlockSize { +func (m *ConsensusParams) GetBlockSize() *BlockSizeParams { if m != nil { return m.BlockSize } return nil } -func (m *ConsensusParams) GetEvidenceParams() *EvidenceParams { +func (m *ConsensusParams) GetEvidence() *EvidenceParams { if m != nil { - return m.EvidenceParams + return m.Evidence + } + return nil +} + +func (m *ConsensusParams) GetValidator() *ValidatorParams { + if m != nil { + return m.Validator } return nil } // BlockSize contains limits on the block size. -type BlockSize struct { +type BlockSizeParams struct { // Note: must be greater than 0 MaxBytes int64 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` // Note: must be greater or equal to -1 @@ -2421,18 +2428,18 @@ type BlockSize struct { XXX_sizecache int32 `json:"-"` } -func (m *BlockSize) Reset() { *m = BlockSize{} } -func (m *BlockSize) String() string { return proto.CompactTextString(m) } -func (*BlockSize) ProtoMessage() {} -func (*BlockSize) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{26} +func (m *BlockSizeParams) Reset() { *m = BlockSizeParams{} } +func (m *BlockSizeParams) String() string { return proto.CompactTextString(m) } +func (*BlockSizeParams) ProtoMessage() {} +func (*BlockSizeParams) Descriptor() ([]byte, []int) { + return fileDescriptor_types_5b877df1938afe10, []int{26} } -func (m *BlockSize) XXX_Unmarshal(b []byte) error { +func (m *BlockSizeParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *BlockSize) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *BlockSizeParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_BlockSize.Marshal(b, m, deterministic) + return xxx_messageInfo_BlockSizeParams.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalTo(b) @@ -2442,26 +2449,26 @@ func (m *BlockSize) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return b[:n], nil } } -func (dst *BlockSize) XXX_Merge(src proto.Message) { - xxx_messageInfo_BlockSize.Merge(dst, src) +func (dst *BlockSizeParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockSizeParams.Merge(dst, src) } -func (m *BlockSize) XXX_Size() int { +func (m *BlockSizeParams) XXX_Size() int { return m.Size() } -func (m *BlockSize) XXX_DiscardUnknown() { - xxx_messageInfo_BlockSize.DiscardUnknown(m) +func (m *BlockSizeParams) XXX_DiscardUnknown() { + xxx_messageInfo_BlockSizeParams.DiscardUnknown(m) } -var xxx_messageInfo_BlockSize proto.InternalMessageInfo +var xxx_messageInfo_BlockSizeParams proto.InternalMessageInfo -func (m *BlockSize) GetMaxBytes() int64 { +func (m *BlockSizeParams) GetMaxBytes() int64 { if m != nil { return m.MaxBytes } return 0 } -func (m *BlockSize) GetMaxGas() int64 { +func (m *BlockSizeParams) GetMaxGas() int64 { if m != nil { return m.MaxGas } @@ -2481,7 +2488,7 @@ func (m *EvidenceParams) Reset() { *m = EvidenceParams{} } func (m *EvidenceParams) String() string { return proto.CompactTextString(m) } func (*EvidenceParams) ProtoMessage() {} func (*EvidenceParams) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{27} + return fileDescriptor_types_5b877df1938afe10, []int{27} } func (m *EvidenceParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2517,6 +2524,54 @@ func (m *EvidenceParams) GetMaxAge() int64 { return 0 } +// ValidatorParams contains limits on validators. +type ValidatorParams struct { + PubKeyTypes []string `protobuf:"bytes,1,rep,name=pub_key_types,json=pubKeyTypes" json:"pub_key_types,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ValidatorParams) Reset() { *m = ValidatorParams{} } +func (m *ValidatorParams) String() string { return proto.CompactTextString(m) } +func (*ValidatorParams) ProtoMessage() {} +func (*ValidatorParams) Descriptor() ([]byte, []int) { + return fileDescriptor_types_5b877df1938afe10, []int{28} +} +func (m *ValidatorParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ValidatorParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ValidatorParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (dst *ValidatorParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_ValidatorParams.Merge(dst, src) +} +func (m *ValidatorParams) XXX_Size() int { + return m.Size() +} +func (m *ValidatorParams) XXX_DiscardUnknown() { + xxx_messageInfo_ValidatorParams.DiscardUnknown(m) +} + +var xxx_messageInfo_ValidatorParams proto.InternalMessageInfo + +func (m *ValidatorParams) GetPubKeyTypes() []string { + if m != nil { + return m.PubKeyTypes + } + return nil +} + type LastCommitInfo struct { Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` Votes []VoteInfo `protobuf:"bytes,2,rep,name=votes" json:"votes"` @@ -2529,7 +2584,7 @@ func (m *LastCommitInfo) Reset() { *m = LastCommitInfo{} } func (m *LastCommitInfo) String() string { return proto.CompactTextString(m) } func (*LastCommitInfo) ProtoMessage() {} func (*LastCommitInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{28} + return fileDescriptor_types_5b877df1938afe10, []int{29} } func (m *LastCommitInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2603,7 +2658,7 @@ func (m *Header) Reset() { *m = Header{} } func (m *Header) String() string { return proto.CompactTextString(m) } func (*Header) ProtoMessage() {} func (*Header) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{29} + return fileDescriptor_types_5b877df1938afe10, []int{30} } func (m *Header) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2756,7 +2811,7 @@ func (m *Version) Reset() { *m = Version{} } func (m *Version) String() string { return proto.CompactTextString(m) } func (*Version) ProtoMessage() {} func (*Version) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{30} + return fileDescriptor_types_5b877df1938afe10, []int{31} } func (m *Version) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2811,7 +2866,7 @@ func (m *BlockID) Reset() { *m = BlockID{} } func (m *BlockID) String() string { return proto.CompactTextString(m) } func (*BlockID) ProtoMessage() {} func (*BlockID) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{31} + return fileDescriptor_types_5b877df1938afe10, []int{32} } func (m *BlockID) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2866,7 +2921,7 @@ func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } func (*PartSetHeader) ProtoMessage() {} func (*PartSetHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{32} + return fileDescriptor_types_5b877df1938afe10, []int{33} } func (m *PartSetHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2923,7 +2978,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_types_4449c1011851ea19, []int{33} + return fileDescriptor_types_5b877df1938afe10, []int{34} } func (m *Validator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2979,7 +3034,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_types_4449c1011851ea19, []int{34} + return fileDescriptor_types_5b877df1938afe10, []int{35} } func (m *ValidatorUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3035,7 +3090,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_types_4449c1011851ea19, []int{35} + return fileDescriptor_types_5b877df1938afe10, []int{36} } func (m *VoteInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3090,7 +3145,7 @@ func (m *PubKey) Reset() { *m = PubKey{} } func (m *PubKey) String() string { return proto.CompactTextString(m) } func (*PubKey) ProtoMessage() {} func (*PubKey) Descriptor() ([]byte, []int) { - return fileDescriptor_types_4449c1011851ea19, []int{36} + return fileDescriptor_types_5b877df1938afe10, []int{37} } func (m *PubKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3148,7 +3203,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_types_4449c1011851ea19, []int{37} + return fileDescriptor_types_5b877df1938afe10, []int{38} } func (m *Evidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3265,10 +3320,12 @@ func init() { golang_proto.RegisterType((*ResponseCommit)(nil), "types.ResponseCommit") proto.RegisterType((*ConsensusParams)(nil), "types.ConsensusParams") golang_proto.RegisterType((*ConsensusParams)(nil), "types.ConsensusParams") - proto.RegisterType((*BlockSize)(nil), "types.BlockSize") - golang_proto.RegisterType((*BlockSize)(nil), "types.BlockSize") + proto.RegisterType((*BlockSizeParams)(nil), "types.BlockSizeParams") + golang_proto.RegisterType((*BlockSizeParams)(nil), "types.BlockSizeParams") proto.RegisterType((*EvidenceParams)(nil), "types.EvidenceParams") golang_proto.RegisterType((*EvidenceParams)(nil), "types.EvidenceParams") + proto.RegisterType((*ValidatorParams)(nil), "types.ValidatorParams") + golang_proto.RegisterType((*ValidatorParams)(nil), "types.ValidatorParams") proto.RegisterType((*LastCommitInfo)(nil), "types.LastCommitInfo") golang_proto.RegisterType((*LastCommitInfo)(nil), "types.LastCommitInfo") proto.RegisterType((*Header)(nil), "types.Header") @@ -4714,7 +4771,10 @@ func (this *ConsensusParams) Equal(that interface{}) bool { if !this.BlockSize.Equal(that1.BlockSize) { return false } - if !this.EvidenceParams.Equal(that1.EvidenceParams) { + if !this.Evidence.Equal(that1.Evidence) { + return false + } + if !this.Validator.Equal(that1.Validator) { return false } if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { @@ -4722,14 +4782,14 @@ func (this *ConsensusParams) Equal(that interface{}) bool { } return true } -func (this *BlockSize) Equal(that interface{}) bool { +func (this *BlockSizeParams) Equal(that interface{}) bool { if that == nil { return this == nil } - that1, ok := that.(*BlockSize) + that1, ok := that.(*BlockSizeParams) if !ok { - that2, ok := that.(BlockSize) + that2, ok := that.(BlockSizeParams) if ok { that1 = &that2 } else { @@ -4779,6 +4839,38 @@ func (this *EvidenceParams) Equal(that interface{}) bool { } return true } +func (this *ValidatorParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ValidatorParams) + if !ok { + that2, ok := that.(ValidatorParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.PubKeyTypes) != len(that1.PubKeyTypes) { + return false + } + for i := range this.PubKeyTypes { + if this.PubKeyTypes[i] != that1.PubKeyTypes[i] { + return false + } + } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } + return true +} func (this *LastCommitInfo) Equal(that interface{}) bool { if that == nil { return this == nil @@ -6868,23 +6960,33 @@ func (m *ConsensusParams) MarshalTo(dAtA []byte) (int, error) { } i += n33 } - if m.EvidenceParams != nil { + if m.Evidence != nil { dAtA[i] = 0x12 i++ - i = encodeVarintTypes(dAtA, i, uint64(m.EvidenceParams.Size())) - n34, err := m.EvidenceParams.MarshalTo(dAtA[i:]) + i = encodeVarintTypes(dAtA, i, uint64(m.Evidence.Size())) + n34, err := m.Evidence.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n34 } + if m.Validator != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Validator.Size())) + n35, err := m.Validator.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n35 + } if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } return i, nil } -func (m *BlockSize) Marshal() (dAtA []byte, err error) { +func (m *BlockSizeParams) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalTo(dAtA) @@ -6894,7 +6996,7 @@ func (m *BlockSize) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *BlockSize) MarshalTo(dAtA []byte) (int, error) { +func (m *BlockSizeParams) MarshalTo(dAtA []byte) (int, error) { var i int _ = i var l int @@ -6941,6 +7043,42 @@ func (m *EvidenceParams) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ValidatorParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ValidatorParams) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.PubKeyTypes) > 0 { + for _, s := range m.PubKeyTypes { + dAtA[i] = 0xa + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if m.XXX_unrecognized != nil { + i += copy(dAtA[i:], m.XXX_unrecognized) + } + return i, nil +} + func (m *LastCommitInfo) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -6997,11 +7135,11 @@ func (m *Header) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintTypes(dAtA, i, uint64(m.Version.Size())) - n35, err := m.Version.MarshalTo(dAtA[i:]) + n36, err := m.Version.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n36 if len(m.ChainID) > 0 { dAtA[i] = 0x12 i++ @@ -7016,11 +7154,11 @@ func (m *Header) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintTypes(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Time))) - n36, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i:]) + n37, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n37 if m.NumTxs != 0 { dAtA[i] = 0x28 i++ @@ -7034,11 +7172,11 @@ func (m *Header) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintTypes(dAtA, i, uint64(m.LastBlockId.Size())) - n37, err := m.LastBlockId.MarshalTo(dAtA[i:]) + n38, err := m.LastBlockId.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n38 if len(m.LastCommitHash) > 0 { dAtA[i] = 0x42 i++ @@ -7156,11 +7294,11 @@ func (m *BlockID) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintTypes(dAtA, i, uint64(m.PartsHeader.Size())) - n38, err := m.PartsHeader.MarshalTo(dAtA[i:]) + n39, err := m.PartsHeader.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n39 if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } @@ -7249,11 +7387,11 @@ func (m *ValidatorUpdate) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintTypes(dAtA, i, uint64(m.PubKey.Size())) - n39, err := m.PubKey.MarshalTo(dAtA[i:]) + n40, err := m.PubKey.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n40 if m.Power != 0 { dAtA[i] = 0x10 i++ @@ -7283,11 +7421,11 @@ func (m *VoteInfo) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintTypes(dAtA, i, uint64(m.Validator.Size())) - n40, err := m.Validator.MarshalTo(dAtA[i:]) + n41, err := m.Validator.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n41 if m.SignedLastBlock { dAtA[i] = 0x10 i++ @@ -7361,11 +7499,11 @@ func (m *Evidence) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintTypes(dAtA, i, uint64(m.Validator.Size())) - n41, err := m.Validator.MarshalTo(dAtA[i:]) + n42, err := m.Validator.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n41 + i += n42 if m.Height != 0 { dAtA[i] = 0x18 i++ @@ -7374,11 +7512,11 @@ func (m *Evidence) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintTypes(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Time))) - n42, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i:]) + n43, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i:]) if err != nil { return 0, err } - i += n42 + i += n43 if m.TotalVotingPower != 0 { dAtA[i] = 0x28 i++ @@ -7971,19 +8109,22 @@ func NewPopulatedResponseCommit(r randyTypes, easy bool) *ResponseCommit { func NewPopulatedConsensusParams(r randyTypes, easy bool) *ConsensusParams { this := &ConsensusParams{} if r.Intn(10) != 0 { - this.BlockSize = NewPopulatedBlockSize(r, easy) + this.BlockSize = NewPopulatedBlockSizeParams(r, easy) } if r.Intn(10) != 0 { - this.EvidenceParams = NewPopulatedEvidenceParams(r, easy) + this.Evidence = NewPopulatedEvidenceParams(r, easy) + } + if r.Intn(10) != 0 { + this.Validator = NewPopulatedValidatorParams(r, easy) } if !easy && r.Intn(10) != 0 { - this.XXX_unrecognized = randUnrecognizedTypes(r, 3) + this.XXX_unrecognized = randUnrecognizedTypes(r, 4) } return this } -func NewPopulatedBlockSize(r randyTypes, easy bool) *BlockSize { - this := &BlockSize{} +func NewPopulatedBlockSizeParams(r randyTypes, easy bool) *BlockSizeParams { + this := &BlockSizeParams{} this.MaxBytes = int64(r.Int63()) if r.Intn(2) == 0 { this.MaxBytes *= -1 @@ -8010,6 +8151,19 @@ func NewPopulatedEvidenceParams(r randyTypes, easy bool) *EvidenceParams { return this } +func NewPopulatedValidatorParams(r randyTypes, easy bool) *ValidatorParams { + this := &ValidatorParams{} + v31 := r.Intn(10) + this.PubKeyTypes = make([]string, v31) + for i := 0; i < v31; i++ { + this.PubKeyTypes[i] = string(randStringTypes(r)) + } + if !easy && r.Intn(10) != 0 { + this.XXX_unrecognized = randUnrecognizedTypes(r, 2) + } + return this +} + func NewPopulatedLastCommitInfo(r randyTypes, easy bool) *LastCommitInfo { this := &LastCommitInfo{} this.Round = int32(r.Int31()) @@ -8017,11 +8171,11 @@ func NewPopulatedLastCommitInfo(r randyTypes, easy bool) *LastCommitInfo { this.Round *= -1 } if r.Intn(10) != 0 { - v31 := r.Intn(5) - this.Votes = make([]VoteInfo, v31) - for i := 0; i < v31; i++ { - v32 := NewPopulatedVoteInfo(r, easy) - this.Votes[i] = *v32 + v32 := r.Intn(5) + this.Votes = make([]VoteInfo, v32) + for i := 0; i < v32; i++ { + v33 := NewPopulatedVoteInfo(r, easy) + this.Votes[i] = *v33 } } if !easy && r.Intn(10) != 0 { @@ -8032,15 +8186,15 @@ func NewPopulatedLastCommitInfo(r randyTypes, easy bool) *LastCommitInfo { func NewPopulatedHeader(r randyTypes, easy bool) *Header { this := &Header{} - v33 := NewPopulatedVersion(r, easy) - this.Version = *v33 + v34 := NewPopulatedVersion(r, easy) + this.Version = *v34 this.ChainID = string(randStringTypes(r)) this.Height = int64(r.Int63()) if r.Intn(2) == 0 { this.Height *= -1 } - v34 := github_com_gogo_protobuf_types.NewPopulatedStdTime(r, easy) - this.Time = *v34 + v35 := github_com_gogo_protobuf_types.NewPopulatedStdTime(r, easy) + this.Time = *v35 this.NumTxs = int64(r.Int63()) if r.Intn(2) == 0 { this.NumTxs *= -1 @@ -8049,51 +8203,51 @@ func NewPopulatedHeader(r randyTypes, easy bool) *Header { if r.Intn(2) == 0 { this.TotalTxs *= -1 } - v35 := NewPopulatedBlockID(r, easy) - this.LastBlockId = *v35 - v36 := r.Intn(100) - this.LastCommitHash = make([]byte, v36) - for i := 0; i < v36; i++ { + v36 := NewPopulatedBlockID(r, easy) + this.LastBlockId = *v36 + v37 := r.Intn(100) + this.LastCommitHash = make([]byte, v37) + for i := 0; i < v37; i++ { this.LastCommitHash[i] = byte(r.Intn(256)) } - v37 := r.Intn(100) - this.DataHash = make([]byte, v37) - for i := 0; i < v37; i++ { + v38 := r.Intn(100) + this.DataHash = make([]byte, v38) + for i := 0; i < v38; i++ { this.DataHash[i] = byte(r.Intn(256)) } - v38 := r.Intn(100) - this.ValidatorsHash = make([]byte, v38) - for i := 0; i < v38; i++ { + v39 := r.Intn(100) + this.ValidatorsHash = make([]byte, v39) + for i := 0; i < v39; i++ { this.ValidatorsHash[i] = byte(r.Intn(256)) } - v39 := r.Intn(100) - this.NextValidatorsHash = make([]byte, v39) - for i := 0; i < v39; i++ { + v40 := r.Intn(100) + this.NextValidatorsHash = make([]byte, v40) + for i := 0; i < v40; i++ { this.NextValidatorsHash[i] = byte(r.Intn(256)) } - v40 := r.Intn(100) - this.ConsensusHash = make([]byte, v40) - for i := 0; i < v40; i++ { + v41 := r.Intn(100) + this.ConsensusHash = make([]byte, v41) + for i := 0; i < v41; i++ { this.ConsensusHash[i] = byte(r.Intn(256)) } - v41 := r.Intn(100) - this.AppHash = make([]byte, v41) - for i := 0; i < v41; i++ { + v42 := r.Intn(100) + this.AppHash = make([]byte, v42) + for i := 0; i < v42; i++ { this.AppHash[i] = byte(r.Intn(256)) } - v42 := r.Intn(100) - this.LastResultsHash = make([]byte, v42) - for i := 0; i < v42; i++ { + v43 := r.Intn(100) + this.LastResultsHash = make([]byte, v43) + for i := 0; i < v43; i++ { this.LastResultsHash[i] = byte(r.Intn(256)) } - v43 := r.Intn(100) - this.EvidenceHash = make([]byte, v43) - for i := 0; i < v43; i++ { + v44 := r.Intn(100) + this.EvidenceHash = make([]byte, v44) + for i := 0; i < v44; i++ { this.EvidenceHash[i] = byte(r.Intn(256)) } - v44 := r.Intn(100) - this.ProposerAddress = make([]byte, v44) - for i := 0; i < v44; i++ { + v45 := r.Intn(100) + this.ProposerAddress = make([]byte, v45) + for i := 0; i < v45; i++ { this.ProposerAddress[i] = byte(r.Intn(256)) } if !easy && r.Intn(10) != 0 { @@ -8114,13 +8268,13 @@ func NewPopulatedVersion(r randyTypes, easy bool) *Version { func NewPopulatedBlockID(r randyTypes, easy bool) *BlockID { this := &BlockID{} - v45 := r.Intn(100) - this.Hash = make([]byte, v45) - for i := 0; i < v45; i++ { + v46 := r.Intn(100) + this.Hash = make([]byte, v46) + for i := 0; i < v46; i++ { this.Hash[i] = byte(r.Intn(256)) } - v46 := NewPopulatedPartSetHeader(r, easy) - this.PartsHeader = *v46 + v47 := NewPopulatedPartSetHeader(r, easy) + this.PartsHeader = *v47 if !easy && r.Intn(10) != 0 { this.XXX_unrecognized = randUnrecognizedTypes(r, 3) } @@ -8133,9 +8287,9 @@ func NewPopulatedPartSetHeader(r randyTypes, easy bool) *PartSetHeader { if r.Intn(2) == 0 { this.Total *= -1 } - v47 := r.Intn(100) - this.Hash = make([]byte, v47) - for i := 0; i < v47; i++ { + v48 := r.Intn(100) + this.Hash = make([]byte, v48) + for i := 0; i < v48; i++ { this.Hash[i] = byte(r.Intn(256)) } if !easy && r.Intn(10) != 0 { @@ -8146,9 +8300,9 @@ func NewPopulatedPartSetHeader(r randyTypes, easy bool) *PartSetHeader { func NewPopulatedValidator(r randyTypes, easy bool) *Validator { this := &Validator{} - v48 := r.Intn(100) - this.Address = make([]byte, v48) - for i := 0; i < v48; i++ { + v49 := r.Intn(100) + this.Address = make([]byte, v49) + for i := 0; i < v49; i++ { this.Address[i] = byte(r.Intn(256)) } this.Power = int64(r.Int63()) @@ -8163,8 +8317,8 @@ func NewPopulatedValidator(r randyTypes, easy bool) *Validator { func NewPopulatedValidatorUpdate(r randyTypes, easy bool) *ValidatorUpdate { this := &ValidatorUpdate{} - v49 := NewPopulatedPubKey(r, easy) - this.PubKey = *v49 + v50 := NewPopulatedPubKey(r, easy) + this.PubKey = *v50 this.Power = int64(r.Int63()) if r.Intn(2) == 0 { this.Power *= -1 @@ -8177,8 +8331,8 @@ func NewPopulatedValidatorUpdate(r randyTypes, easy bool) *ValidatorUpdate { func NewPopulatedVoteInfo(r randyTypes, easy bool) *VoteInfo { this := &VoteInfo{} - v50 := NewPopulatedValidator(r, easy) - this.Validator = *v50 + v51 := NewPopulatedValidator(r, easy) + this.Validator = *v51 this.SignedLastBlock = bool(bool(r.Intn(2) == 0)) if !easy && r.Intn(10) != 0 { this.XXX_unrecognized = randUnrecognizedTypes(r, 3) @@ -8189,9 +8343,9 @@ func NewPopulatedVoteInfo(r randyTypes, easy bool) *VoteInfo { func NewPopulatedPubKey(r randyTypes, easy bool) *PubKey { this := &PubKey{} this.Type = string(randStringTypes(r)) - v51 := r.Intn(100) - this.Data = make([]byte, v51) - for i := 0; i < v51; i++ { + v52 := r.Intn(100) + this.Data = make([]byte, v52) + for i := 0; i < v52; i++ { this.Data[i] = byte(r.Intn(256)) } if !easy && r.Intn(10) != 0 { @@ -8203,14 +8357,14 @@ func NewPopulatedPubKey(r randyTypes, easy bool) *PubKey { func NewPopulatedEvidence(r randyTypes, easy bool) *Evidence { this := &Evidence{} this.Type = string(randStringTypes(r)) - v52 := NewPopulatedValidator(r, easy) - this.Validator = *v52 + v53 := NewPopulatedValidator(r, easy) + this.Validator = *v53 this.Height = int64(r.Int63()) if r.Intn(2) == 0 { this.Height *= -1 } - v53 := github_com_gogo_protobuf_types.NewPopulatedStdTime(r, easy) - this.Time = *v53 + v54 := github_com_gogo_protobuf_types.NewPopulatedStdTime(r, easy) + this.Time = *v54 this.TotalVotingPower = int64(r.Int63()) if r.Intn(2) == 0 { this.TotalVotingPower *= -1 @@ -8240,9 +8394,9 @@ func randUTF8RuneTypes(r randyTypes) rune { return rune(ru + 61) } func randStringTypes(r randyTypes) string { - v54 := r.Intn(100) - tmps := make([]rune, v54) - for i := 0; i < v54; i++ { + v55 := r.Intn(100) + tmps := make([]rune, v55) + for i := 0; i < v55; i++ { tmps[i] = randUTF8RuneTypes(r) } return string(tmps) @@ -8264,11 +8418,11 @@ func randFieldTypes(dAtA []byte, r randyTypes, fieldNumber int, wire int) []byte switch wire { case 0: dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) - v55 := r.Int63() + v56 := r.Int63() if r.Intn(2) == 0 { - v55 *= -1 + v56 *= -1 } - dAtA = encodeVarintPopulateTypes(dAtA, uint64(v55)) + dAtA = encodeVarintPopulateTypes(dAtA, uint64(v56)) case 1: dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) @@ -8987,8 +9141,12 @@ func (m *ConsensusParams) Size() (n int) { l = m.BlockSize.Size() n += 1 + l + sovTypes(uint64(l)) } - if m.EvidenceParams != nil { - l = m.EvidenceParams.Size() + if m.Evidence != nil { + l = m.Evidence.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Validator != nil { + l = m.Validator.Size() n += 1 + l + sovTypes(uint64(l)) } if m.XXX_unrecognized != nil { @@ -8997,7 +9155,7 @@ func (m *ConsensusParams) Size() (n int) { return n } -func (m *BlockSize) Size() (n int) { +func (m *BlockSizeParams) Size() (n int) { var l int _ = l if m.MaxBytes != 0 { @@ -9024,6 +9182,21 @@ func (m *EvidenceParams) Size() (n int) { return n } +func (m *ValidatorParams) Size() (n int) { + var l int + _ = l + if len(m.PubKeyTypes) > 0 { + for _, s := range m.PubKeyTypes { + l = len(s) + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func (m *LastCommitInfo) Size() (n int) { var l int _ = l @@ -13060,7 +13233,7 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.BlockSize == nil { - m.BlockSize = &BlockSize{} + m.BlockSize = &BlockSizeParams{} } if err := m.BlockSize.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -13068,7 +13241,7 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field EvidenceParams", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -13092,10 +13265,43 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.EvidenceParams == nil { - m.EvidenceParams = &EvidenceParams{} + if m.Evidence == nil { + m.Evidence = &EvidenceParams{} } - if err := m.EvidenceParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Validator == nil { + m.Validator = &ValidatorParams{} + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -13121,7 +13327,7 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { } return nil } -func (m *BlockSize) Unmarshal(dAtA []byte) error { +func (m *BlockSizeParams) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13144,10 +13350,10 @@ func (m *BlockSize) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: BlockSize: wiretype end group for non-group") + return fmt.Errorf("proto: BlockSizeParams: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: BlockSize: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: BlockSizeParams: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -13280,6 +13486,86 @@ func (m *EvidenceParams) Unmarshal(dAtA []byte) error { } return nil } +func (m *ValidatorParams) 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: ValidatorParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ValidatorParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKeyTypes", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PubKeyTypes = append(m.PubKeyTypes, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *LastCommitInfo) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -14885,148 +15171,150 @@ var ( ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") ) -func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_4449c1011851ea19) } +func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_5b877df1938afe10) } func init() { - golang_proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_4449c1011851ea19) + golang_proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_5b877df1938afe10) } -var fileDescriptor_types_4449c1011851ea19 = []byte{ - // 2177 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0xcd, 0x93, 0x1b, 0x47, - 0x15, 0xdf, 0xd1, 0x6a, 0x25, 0xcd, 0xd3, 0xea, 0x23, 0xed, 0xb5, 0x2d, 0x8b, 0xb0, 0xeb, 0x1a, - 0x43, 0xe2, 0x25, 0x8e, 0x36, 0x6c, 0x08, 0xb5, 0x8e, 0x43, 0xaa, 0x56, 0xb6, 0x61, 0xb7, 0x12, - 0x60, 0x19, 0xdb, 0xcb, 0x85, 0xaa, 0xa9, 0x96, 0xa6, 0x2d, 0x4d, 0x59, 0x9a, 0x99, 0xcc, 0xb4, - 0x36, 0x5a, 0x1f, 0x73, 0xce, 0x21, 0x07, 0xfe, 0x08, 0xfe, 0x84, 0x1c, 0x39, 0x51, 0x39, 0x72, - 0xe0, 0x6c, 0x60, 0x29, 0x0e, 0x70, 0xa5, 0xa8, 0xe2, 0x48, 0xf5, 0xeb, 0xee, 0xf9, 0xda, 0x91, - 0x89, 0x03, 0x27, 0x2e, 0x52, 0xf7, 0xfb, 0xe8, 0x8f, 0x37, 0xef, 0xbd, 0xdf, 0x7b, 0x0d, 0xd7, - 0xe8, 0x68, 0xec, 0xed, 0xf1, 0xf3, 0x90, 0xc5, 0xf2, 0x77, 0x10, 0x46, 0x01, 0x0f, 0xc8, 0x06, - 0x4e, 0xfa, 0x6f, 0x4f, 0x3c, 0x3e, 0x5d, 0x8c, 0x06, 0xe3, 0x60, 0xbe, 0x37, 0x09, 0x26, 0xc1, - 0x1e, 0x72, 0x47, 0x8b, 0xa7, 0x38, 0xc3, 0x09, 0x8e, 0xa4, 0x56, 0x7f, 0x67, 0x12, 0x04, 0x93, - 0x19, 0x4b, 0xa5, 0xb8, 0x37, 0x67, 0x31, 0xa7, 0xf3, 0x50, 0x09, 0x1c, 0x64, 0xd6, 0xe3, 0xcc, - 0x77, 0x59, 0x34, 0xf7, 0x7c, 0x9e, 0x1d, 0xce, 0xbc, 0x51, 0xbc, 0x37, 0x0e, 0xe6, 0xf3, 0xc0, - 0xcf, 0x1e, 0xa8, 0x7f, 0xef, 0x3f, 0x6a, 0x8e, 0xa3, 0xf3, 0x90, 0x07, 0x7b, 0x73, 0x16, 0x3d, - 0x9b, 0x31, 0xf5, 0x27, 0x95, 0xad, 0xdf, 0x55, 0xa1, 0x6e, 0xb3, 0x4f, 0x16, 0x2c, 0xe6, 0xe4, - 0x36, 0x54, 0xd9, 0x78, 0x1a, 0xf4, 0x2a, 0x37, 0x8d, 0xdb, 0xcd, 0x7d, 0x32, 0x90, 0x9b, 0x28, - 0xee, 0xc3, 0xf1, 0x34, 0x38, 0x5a, 0xb3, 0x51, 0x82, 0xbc, 0x05, 0x1b, 0x4f, 0x67, 0x8b, 0x78, - 0xda, 0x5b, 0x47, 0xd1, 0x2b, 0x79, 0xd1, 0x1f, 0x0b, 0xd6, 0xd1, 0x9a, 0x2d, 0x65, 0xc4, 0xb2, - 0x9e, 0xff, 0x34, 0xe8, 0x55, 0xcb, 0x96, 0x3d, 0xf6, 0x9f, 0xe2, 0xb2, 0x42, 0x82, 0x1c, 0x00, - 0xc4, 0x8c, 0x3b, 0x41, 0xc8, 0xbd, 0xc0, 0xef, 0x6d, 0xa0, 0xfc, 0xf5, 0xbc, 0xfc, 0x23, 0xc6, - 0x7f, 0x8e, 0xec, 0xa3, 0x35, 0xdb, 0x8c, 0xf5, 0x44, 0x68, 0x7a, 0xbe, 0xc7, 0x9d, 0xf1, 0x94, - 0x7a, 0x7e, 0xaf, 0x56, 0xa6, 0x79, 0xec, 0x7b, 0xfc, 0xbe, 0x60, 0x0b, 0x4d, 0x4f, 0x4f, 0xc4, - 0x55, 0x3e, 0x59, 0xb0, 0xe8, 0xbc, 0x57, 0x2f, 0xbb, 0xca, 0x2f, 0x04, 0x4b, 0x5c, 0x05, 0x65, - 0xc8, 0x3d, 0x68, 0x8e, 0xd8, 0xc4, 0xf3, 0x9d, 0xd1, 0x2c, 0x18, 0x3f, 0xeb, 0x35, 0x50, 0xa5, - 0x97, 0x57, 0x19, 0x0a, 0x81, 0xa1, 0xe0, 0x1f, 0xad, 0xd9, 0x30, 0x4a, 0x66, 0x64, 0x1f, 0x1a, - 0xe3, 0x29, 0x1b, 0x3f, 0x73, 0xf8, 0xb2, 0x67, 0xa2, 0xe6, 0xd5, 0xbc, 0xe6, 0x7d, 0xc1, 0x7d, - 0xbc, 0x3c, 0x5a, 0xb3, 0xeb, 0x63, 0x39, 0x24, 0xef, 0x81, 0xc9, 0x7c, 0x57, 0x6d, 0xd7, 0x44, - 0xa5, 0x6b, 0x85, 0xef, 0xe2, 0xbb, 0x7a, 0xb3, 0x06, 0x53, 0x63, 0x32, 0x80, 0x9a, 0x70, 0x14, - 0x8f, 0xf7, 0x36, 0x51, 0x67, 0xab, 0xb0, 0x11, 0xf2, 0x8e, 0xd6, 0x6c, 0x25, 0x25, 0xcc, 0xe7, - 0xb2, 0x99, 0x77, 0xc6, 0x22, 0x71, 0xb8, 0x2b, 0x65, 0xe6, 0x7b, 0x20, 0xf9, 0x78, 0x3c, 0xd3, - 0xd5, 0x93, 0x61, 0x1d, 0x36, 0xce, 0xe8, 0x6c, 0xc1, 0xac, 0x37, 0xa1, 0x99, 0xf1, 0x14, 0xd2, - 0x83, 0xfa, 0x9c, 0xc5, 0x31, 0x9d, 0xb0, 0x9e, 0x71, 0xd3, 0xb8, 0x6d, 0xda, 0x7a, 0x6a, 0xb5, - 0x61, 0x33, 0xeb, 0x27, 0xd6, 0x3c, 0x51, 0x14, 0xbe, 0x20, 0x14, 0xcf, 0x58, 0x14, 0x0b, 0x07, - 0x50, 0x8a, 0x6a, 0x4a, 0x6e, 0x41, 0x0b, 0xed, 0xe0, 0x68, 0xbe, 0xf0, 0xd3, 0xaa, 0xbd, 0x89, - 0xc4, 0x53, 0x25, 0xb4, 0x03, 0xcd, 0x70, 0x3f, 0x4c, 0x44, 0xd6, 0x51, 0x04, 0xc2, 0xfd, 0x50, - 0x09, 0x58, 0xef, 0x43, 0xb7, 0xe8, 0x4a, 0xa4, 0x0b, 0xeb, 0xcf, 0xd8, 0xb9, 0xda, 0x4f, 0x0c, - 0xc9, 0x96, 0xba, 0x16, 0xee, 0x61, 0xda, 0xea, 0x8e, 0x5f, 0x54, 0x12, 0xe5, 0xc4, 0x9b, 0xc8, - 0x01, 0x54, 0x45, 0x2c, 0xa3, 0x76, 0x73, 0xbf, 0x3f, 0x90, 0x81, 0x3e, 0xd0, 0x81, 0x3e, 0x78, - 0xac, 0x03, 0x7d, 0xd8, 0xf8, 0xea, 0xc5, 0xce, 0xda, 0x17, 0x7f, 0xdc, 0x31, 0x6c, 0xd4, 0x20, - 0x37, 0x84, 0x43, 0x50, 0xcf, 0x77, 0x3c, 0x57, 0xed, 0x53, 0xc7, 0xf9, 0xb1, 0x4b, 0x0e, 0xa1, - 0x3b, 0x0e, 0xfc, 0x98, 0xf9, 0xf1, 0x22, 0x76, 0x42, 0x1a, 0xd1, 0x79, 0xac, 0x62, 0x4d, 0x7f, - 0xfe, 0xfb, 0x9a, 0x7d, 0x82, 0x5c, 0xbb, 0x33, 0xce, 0x13, 0xc8, 0x07, 0x00, 0x67, 0x74, 0xe6, - 0xb9, 0x94, 0x07, 0x51, 0xdc, 0xab, 0xde, 0x5c, 0xcf, 0x28, 0x9f, 0x6a, 0xc6, 0x93, 0xd0, 0xa5, - 0x9c, 0x0d, 0xab, 0xe2, 0x64, 0x76, 0x46, 0x9e, 0xbc, 0x01, 0x1d, 0x1a, 0x86, 0x4e, 0xcc, 0x29, - 0x67, 0xce, 0xe8, 0x9c, 0xb3, 0x18, 0xe3, 0x71, 0xd3, 0x6e, 0xd1, 0x30, 0x7c, 0x24, 0xa8, 0x43, - 0x41, 0xb4, 0xdc, 0xe4, 0x6b, 0x62, 0xa8, 0x10, 0x02, 0x55, 0x97, 0x72, 0x8a, 0xd6, 0xd8, 0xb4, - 0x71, 0x2c, 0x68, 0x21, 0xe5, 0x53, 0x75, 0x47, 0x1c, 0x93, 0x6b, 0x50, 0x9b, 0x32, 0x6f, 0x32, - 0xe5, 0x78, 0xad, 0x75, 0x5b, 0xcd, 0x84, 0xe1, 0xc3, 0x28, 0x38, 0x63, 0x98, 0x2d, 0x1a, 0xb6, - 0x9c, 0x58, 0x7f, 0x35, 0xe0, 0xb5, 0x4b, 0xe1, 0x25, 0xd6, 0x9d, 0xd2, 0x78, 0xaa, 0xf7, 0x12, - 0x63, 0xf2, 0x96, 0x58, 0x97, 0xba, 0x2c, 0x52, 0x59, 0xac, 0xa5, 0x6e, 0x7c, 0x84, 0x44, 0x75, - 0x51, 0x25, 0x42, 0x1e, 0x42, 0x77, 0x46, 0x63, 0xee, 0xc8, 0x28, 0x70, 0x30, 0x4b, 0xad, 0xe7, - 0x22, 0xf3, 0x63, 0xaa, 0xa3, 0x45, 0x38, 0xa7, 0x52, 0x6f, 0xcf, 0x72, 0x54, 0x72, 0x04, 0x5b, - 0xa3, 0xf3, 0xe7, 0xd4, 0xe7, 0x9e, 0xcf, 0x9c, 0x4b, 0x36, 0xef, 0xa8, 0xa5, 0x1e, 0x9e, 0x79, - 0x2e, 0xf3, 0xc7, 0xda, 0xd8, 0x57, 0x12, 0x95, 0xe4, 0x63, 0xc4, 0xd6, 0x4d, 0x68, 0xe7, 0x73, - 0x01, 0x69, 0x43, 0x85, 0x2f, 0xd5, 0x0d, 0x2b, 0x7c, 0x69, 0x59, 0x89, 0x07, 0x26, 0x01, 0x79, - 0x49, 0x66, 0x17, 0x3a, 0x85, 0xe4, 0x90, 0x31, 0xb7, 0x91, 0x35, 0xb7, 0xd5, 0x81, 0x56, 0x2e, - 0x27, 0x58, 0x9f, 0x6f, 0x40, 0xc3, 0x66, 0x71, 0x28, 0x9c, 0x89, 0x1c, 0x80, 0xc9, 0x96, 0x63, - 0x26, 0xd3, 0xb1, 0x51, 0x48, 0x76, 0x52, 0xe6, 0xa1, 0xe6, 0x8b, 0xb4, 0x90, 0x08, 0x93, 0xdd, - 0x1c, 0x94, 0x5c, 0x29, 0x2a, 0x65, 0xb1, 0xe4, 0x4e, 0x1e, 0x4b, 0xb6, 0x0a, 0xb2, 0x05, 0x30, - 0xd9, 0xcd, 0x81, 0x49, 0x71, 0xe1, 0x1c, 0x9a, 0xdc, 0x2d, 0x41, 0x93, 0xe2, 0xf1, 0x57, 0xc0, - 0xc9, 0xdd, 0x12, 0x38, 0xe9, 0x5d, 0xda, 0xab, 0x14, 0x4f, 0xee, 0xe4, 0xf1, 0xa4, 0x78, 0x9d, - 0x02, 0xa0, 0x7c, 0x50, 0x06, 0x28, 0x37, 0x0a, 0x3a, 0x2b, 0x11, 0xe5, 0xdd, 0x4b, 0x88, 0x72, - 0xad, 0xa0, 0x5a, 0x02, 0x29, 0x77, 0x73, 0xb9, 0x1e, 0x4a, 0xef, 0x56, 0x9e, 0xec, 0xc9, 0x0f, - 0x2f, 0xa3, 0xd1, 0xf5, 0xe2, 0xa7, 0x2d, 0x83, 0xa3, 0xbd, 0x02, 0x1c, 0x5d, 0x2d, 0x9e, 0xb2, - 0x80, 0x47, 0x29, 0xaa, 0xec, 0x8a, 0xb8, 0x2f, 0x78, 0x9a, 0xc8, 0x11, 0x2c, 0x8a, 0x82, 0x48, - 0x25, 0x6c, 0x39, 0xb1, 0x6e, 0x8b, 0x4c, 0x94, 0xfa, 0xd7, 0x4b, 0x10, 0x08, 0x9d, 0x3e, 0xe3, - 0x5d, 0xd6, 0x97, 0x46, 0xaa, 0x8b, 0x11, 0x9d, 0xcd, 0x62, 0xa6, 0xca, 0x62, 0x19, 0x60, 0xaa, - 0xe4, 0x81, 0x69, 0x07, 0x9a, 0x22, 0x57, 0x16, 0x30, 0x87, 0x86, 0x1a, 0x73, 0xc8, 0xf7, 0xe0, - 0x35, 0xcc, 0x33, 0x12, 0xbe, 0x54, 0x20, 0x56, 0x31, 0x10, 0x3b, 0x82, 0x21, 0x2d, 0x26, 0x13, - 0xe0, 0xdb, 0x70, 0x25, 0x23, 0x2b, 0xd6, 0xc5, 0x1c, 0x27, 0x93, 0x6f, 0x37, 0x91, 0x3e, 0x0c, - 0xc3, 0x23, 0x1a, 0x4f, 0xad, 0x9f, 0xa6, 0x06, 0x4a, 0xf1, 0x8c, 0x40, 0x75, 0x1c, 0xb8, 0xf2, - 0xde, 0x2d, 0x1b, 0xc7, 0x02, 0xe3, 0x66, 0xc1, 0x04, 0x0f, 0x67, 0xda, 0x62, 0x28, 0xa4, 0x92, - 0x50, 0x32, 0x65, 0xcc, 0x58, 0xbf, 0x36, 0xd2, 0xf5, 0x52, 0x88, 0x2b, 0x43, 0x23, 0xe3, 0xbf, - 0x41, 0xa3, 0xca, 0xab, 0xa1, 0x91, 0x75, 0x61, 0xa4, 0x9f, 0x2c, 0xc1, 0x99, 0x6f, 0x76, 0x45, - 0xe1, 0x3d, 0x9e, 0xef, 0xb2, 0x25, 0x9a, 0x74, 0xdd, 0x96, 0x13, 0x5d, 0x02, 0xd4, 0xd0, 0xcc, - 0xf9, 0x12, 0xa0, 0x8e, 0x34, 0x39, 0x21, 0xb7, 0x10, 0x9f, 0x82, 0xa7, 0x2a, 0x54, 0x5b, 0x03, - 0x55, 0x4d, 0x9f, 0x08, 0xa2, 0x2d, 0x79, 0x99, 0x6c, 0x6b, 0xe6, 0xc0, 0xed, 0x75, 0x30, 0xc5, - 0x41, 0xe3, 0x90, 0x8e, 0x19, 0x46, 0x9e, 0x69, 0xa7, 0x04, 0xeb, 0x04, 0xc8, 0xe5, 0x88, 0x27, - 0xef, 0x43, 0x95, 0xd3, 0x89, 0xb0, 0xb7, 0x30, 0x59, 0x7b, 0x20, 0x1b, 0x80, 0xc1, 0x47, 0xa7, - 0x27, 0xd4, 0x8b, 0x86, 0xd7, 0x84, 0xa9, 0xfe, 0xfe, 0x62, 0xa7, 0x2d, 0x64, 0xee, 0x04, 0x73, - 0x8f, 0xb3, 0x79, 0xc8, 0xcf, 0x6d, 0xd4, 0xb1, 0xfe, 0x61, 0x08, 0x24, 0xc8, 0x65, 0x82, 0x52, - 0xc3, 0x69, 0x77, 0xaf, 0x64, 0x40, 0xfb, 0xeb, 0x19, 0xf3, 0xdb, 0x00, 0x13, 0x1a, 0x3b, 0x9f, - 0x52, 0x9f, 0x33, 0x57, 0x59, 0xd4, 0x9c, 0xd0, 0xf8, 0x97, 0x48, 0x10, 0x15, 0x8e, 0x60, 0x2f, - 0x62, 0xe6, 0xa2, 0x69, 0xd7, 0xed, 0xfa, 0x84, 0xc6, 0x4f, 0x62, 0xe6, 0x26, 0xf7, 0xaa, 0xbf, - 0xfa, 0xbd, 0xf2, 0x76, 0x6c, 0x14, 0xed, 0xf8, 0xcf, 0x8c, 0x0f, 0xa7, 0x20, 0xf9, 0xff, 0x7f, - 0xef, 0xbf, 0x19, 0xa2, 0x36, 0xc8, 0xa7, 0x61, 0x72, 0x0c, 0xaf, 0x25, 0x71, 0xe4, 0x2c, 0x30, - 0xbe, 0xb4, 0x2f, 0xbd, 0x3c, 0xfc, 0xba, 0x67, 0x79, 0x72, 0x4c, 0x7e, 0x06, 0xd7, 0x0b, 0x59, - 0x20, 0x59, 0xb0, 0xf2, 0xd2, 0x64, 0x70, 0x35, 0x9f, 0x0c, 0xf4, 0x7a, 0xda, 0x12, 0xeb, 0xdf, - 0xc0, 0xb3, 0xbf, 0x23, 0x0a, 0xa5, 0x2c, 0x78, 0x94, 0x7d, 0x4b, 0xeb, 0x33, 0x03, 0x3a, 0x85, - 0xc3, 0x90, 0x3d, 0x00, 0x99, 0x5a, 0x63, 0xef, 0xb9, 0x2e, 0xda, 0xbb, 0xea, 0xe0, 0x68, 0xb2, - 0x47, 0xde, 0x73, 0x66, 0x9b, 0x23, 0x3d, 0x24, 0x1f, 0x42, 0x87, 0xa9, 0xd2, 0x4d, 0xe7, 0xbe, - 0x4a, 0x0e, 0xc5, 0x74, 0x61, 0xa7, 0x6e, 0xdb, 0x66, 0xb9, 0xb9, 0x75, 0x08, 0x66, 0xb2, 0x2e, - 0xf9, 0x16, 0x98, 0x73, 0xba, 0x54, 0x05, 0xb5, 0x2c, 0xc5, 0x1a, 0x73, 0xba, 0xc4, 0x5a, 0x9a, - 0x5c, 0x87, 0xba, 0x60, 0x4e, 0xa8, 0xdc, 0x61, 0xdd, 0xae, 0xcd, 0xe9, 0xf2, 0x27, 0x34, 0xb6, - 0x76, 0xa1, 0x9d, 0xdf, 0x44, 0x8b, 0x6a, 0x70, 0x93, 0xa2, 0x87, 0x13, 0x66, 0x3d, 0x82, 0x76, - 0xbe, 0x66, 0x15, 0x79, 0x2c, 0x0a, 0x16, 0xbe, 0x8b, 0x82, 0x1b, 0xb6, 0x9c, 0x88, 0xb6, 0xf7, - 0x2c, 0x90, 0x9f, 0x2e, 0x5b, 0xa4, 0x9e, 0x06, 0x9c, 0x65, 0x2a, 0x5d, 0x29, 0x63, 0x7d, 0xb6, - 0x01, 0x35, 0x59, 0x40, 0x93, 0x41, 0xbe, 0x3d, 0x13, 0xdf, 0x4d, 0x69, 0x4a, 0xaa, 0x52, 0x4c, - 0xb0, 0xf1, 0x8d, 0x62, 0x8f, 0x33, 0x6c, 0x5e, 0xbc, 0xd8, 0xa9, 0x23, 0xae, 0x1c, 0x3f, 0x48, - 0x1b, 0x9e, 0x55, 0xfd, 0x80, 0xee, 0xae, 0xaa, 0xaf, 0xdc, 0x5d, 0x5d, 0x87, 0xba, 0xbf, 0x98, - 0x3b, 0x7c, 0x19, 0xab, 0xf8, 0xac, 0xf9, 0x8b, 0xf9, 0xe3, 0x65, 0x2c, 0xbe, 0x01, 0x0f, 0x38, - 0x9d, 0x21, 0x4b, 0x46, 0x67, 0x03, 0x09, 0x82, 0x79, 0x00, 0xad, 0x0c, 0xfc, 0x7a, 0xae, 0x2a, - 0xe3, 0xda, 0x59, 0x0f, 0x39, 0x7e, 0xa0, 0x6e, 0xd9, 0x4c, 0xe0, 0xf8, 0xd8, 0x25, 0xb7, 0xf3, - 0xcd, 0x04, 0xa2, 0x76, 0x03, 0x9d, 0x31, 0xd3, 0x2f, 0x08, 0xcc, 0x16, 0x07, 0x10, 0xee, 0x29, - 0x45, 0x4c, 0x14, 0x69, 0x08, 0x02, 0x32, 0xdf, 0x84, 0x4e, 0x0a, 0x7c, 0x52, 0x04, 0xe4, 0x2a, - 0x29, 0x19, 0x05, 0xdf, 0x81, 0x2d, 0x9f, 0x2d, 0xb9, 0x53, 0x94, 0x6e, 0xa2, 0x34, 0x11, 0xbc, - 0xd3, 0xbc, 0xc6, 0x77, 0xa1, 0x9d, 0x06, 0x30, 0xca, 0x6e, 0xca, 0x96, 0x2e, 0xa1, 0xa2, 0xd8, - 0x0d, 0x68, 0x24, 0x65, 0x47, 0x0b, 0x05, 0xea, 0x54, 0x56, 0x1b, 0x49, 0x21, 0x13, 0xb1, 0x78, - 0x31, 0xe3, 0x6a, 0x91, 0x36, 0xca, 0x60, 0x21, 0x63, 0x4b, 0x3a, 0xca, 0xde, 0x82, 0x56, 0x12, - 0x37, 0x28, 0xd7, 0x41, 0xb9, 0x4d, 0x4d, 0x44, 0xa1, 0x5d, 0xe8, 0x86, 0x51, 0x10, 0x06, 0x31, - 0x8b, 0x1c, 0xea, 0xba, 0x11, 0x8b, 0xe3, 0x5e, 0x57, 0xae, 0xa7, 0xe9, 0x87, 0x92, 0x6c, 0x7d, - 0x1f, 0xea, 0xba, 0x9e, 0xda, 0x82, 0x0d, 0xb4, 0x3a, 0xba, 0x60, 0xd5, 0x96, 0x13, 0x91, 0xb9, - 0x0f, 0xc3, 0x50, 0xbd, 0x0a, 0x88, 0xa1, 0xf5, 0x2b, 0xa8, 0xab, 0x0f, 0x56, 0xda, 0x2b, 0xfe, - 0x08, 0x36, 0x43, 0x1a, 0x89, 0x6b, 0x64, 0x3b, 0x46, 0x5d, 0xb1, 0x9f, 0xd0, 0x88, 0x3f, 0x62, - 0x3c, 0xd7, 0x38, 0x36, 0x51, 0x5e, 0x92, 0xac, 0xbb, 0xd0, 0xca, 0xc9, 0x88, 0x63, 0xa1, 0x1f, - 0xe9, 0x48, 0xc3, 0x49, 0xb2, 0x73, 0x25, 0xdd, 0xd9, 0xba, 0x07, 0x66, 0xf2, 0x6d, 0x44, 0x61, - 0xa9, 0xaf, 0x6e, 0x28, 0x73, 0xcb, 0x29, 0x36, 0xc3, 0xc1, 0xa7, 0x2c, 0x52, 0x31, 0x21, 0x27, - 0xd6, 0x13, 0xe8, 0x14, 0x52, 0x36, 0xb9, 0x03, 0xf5, 0x70, 0x31, 0x72, 0xf4, 0x23, 0x46, 0xda, - 0xf6, 0x9e, 0x2c, 0x46, 0x1f, 0xb1, 0x73, 0xdd, 0xf6, 0x86, 0x38, 0x4b, 0x97, 0xad, 0x64, 0x97, - 0x9d, 0x41, 0x43, 0x47, 0x3f, 0xf9, 0x01, 0x98, 0x89, 0x5b, 0x15, 0x72, 0x64, 0xb2, 0xb5, 0x5a, - 0x34, 0x15, 0x14, 0xde, 0x11, 0x7b, 0x13, 0x9f, 0xb9, 0x4e, 0x1a, 0x42, 0xb8, 0x47, 0xc3, 0xee, - 0x48, 0xc6, 0xc7, 0x3a, 0x5e, 0xac, 0x77, 0xa0, 0x26, 0xcf, 0x26, 0xec, 0x23, 0x56, 0xd6, 0xb5, - 0xb6, 0x18, 0x97, 0x26, 0xf3, 0x3f, 0x18, 0xd0, 0xd0, 0x59, 0xb0, 0x54, 0x29, 0x77, 0xe8, 0xca, - 0xd7, 0x3d, 0xf4, 0xff, 0x3e, 0xf1, 0xdc, 0x01, 0x22, 0xf3, 0xcb, 0x59, 0xc0, 0x3d, 0x7f, 0xe2, - 0x48, 0x5b, 0xcb, 0x1c, 0xd4, 0x45, 0xce, 0x29, 0x32, 0x4e, 0x04, 0x7d, 0xff, 0xf3, 0x0d, 0xe8, - 0x1c, 0x0e, 0xef, 0x1f, 0x1f, 0x86, 0xe1, 0xcc, 0x1b, 0x53, 0xac, 0xdf, 0xf7, 0xa0, 0x8a, 0x2d, - 0x4c, 0xc9, 0x13, 0x6c, 0xbf, 0xac, 0x97, 0x26, 0xfb, 0xb0, 0x81, 0x9d, 0x0c, 0x29, 0x7b, 0x89, - 0xed, 0x97, 0xb6, 0xd4, 0x62, 0x13, 0xd9, 0xeb, 0x5c, 0x7e, 0x90, 0xed, 0x97, 0xf5, 0xd5, 0xe4, - 0x43, 0x30, 0xd3, 0x16, 0x63, 0xd5, 0xb3, 0x6c, 0x7f, 0x65, 0x87, 0x2d, 0xf4, 0xd3, 0x72, 0x6c, - 0xd5, 0xeb, 0x62, 0x7f, 0x65, 0x2b, 0x4a, 0x0e, 0xa0, 0xae, 0x8b, 0xd8, 0xf2, 0x87, 0xd3, 0xfe, - 0x8a, 0xee, 0x57, 0x98, 0x47, 0x76, 0x0d, 0x65, 0xaf, 0xbb, 0xfd, 0xd2, 0x16, 0x9d, 0xbc, 0x07, - 0x35, 0x55, 0x59, 0x94, 0x3e, 0x9e, 0xf6, 0xcb, 0x7b, 0x58, 0x71, 0xc9, 0xb4, 0x6f, 0x5a, 0xf5, - 0x02, 0xdd, 0x5f, 0xf9, 0x96, 0x40, 0x0e, 0x01, 0x32, 0xc5, 0xff, 0xca, 0xa7, 0xe5, 0xfe, 0xea, - 0x37, 0x02, 0x72, 0x0f, 0x1a, 0xe9, 0xbb, 0x4f, 0xf9, 0x63, 0x71, 0x7f, 0x55, 0xdb, 0x3e, 0x7c, - 0xfd, 0x5f, 0x7f, 0xde, 0x36, 0x7e, 0x73, 0xb1, 0x6d, 0x7c, 0x79, 0xb1, 0x6d, 0x7c, 0x75, 0xb1, - 0x6d, 0xfc, 0xfe, 0x62, 0xdb, 0xf8, 0xd3, 0xc5, 0xb6, 0xf1, 0xdb, 0xbf, 0x6c, 0x1b, 0xa3, 0x1a, - 0xba, 0xff, 0xbb, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x1a, 0x7c, 0xbd, 0x95, 0x1c, 0x19, 0x00, - 0x00, +var fileDescriptor_types_5b877df1938afe10 = []byte{ + // 2214 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0xcb, 0x73, 0x1b, 0xc7, + 0xd1, 0xe7, 0x82, 0x20, 0x81, 0x6d, 0x10, 0x0f, 0x8d, 0x28, 0x09, 0xc2, 0xe7, 0x8f, 0x54, 0xad, + 0x12, 0x5b, 0x8c, 0x65, 0xd0, 0xa6, 0xa3, 0x14, 0x65, 0x39, 0xa9, 0x22, 0x24, 0xc5, 0x64, 0xd9, + 0x49, 0x98, 0x95, 0xc4, 0x5c, 0x52, 0xb5, 0x35, 0xc0, 0x8e, 0x80, 0x2d, 0x02, 0xbb, 0xeb, 0xdd, + 0x01, 0x0d, 0xea, 0x98, 0xb3, 0x0f, 0x3e, 0xe4, 0x8f, 0xc8, 0x35, 0x37, 0x1f, 0x73, 0x4a, 0xf9, + 0x98, 0x43, 0xce, 0x4a, 0xc2, 0x54, 0x0e, 0xc9, 0x35, 0x95, 0xaa, 0x1c, 0x53, 0xd3, 0x33, 0xb3, + 0x2f, 0x2e, 0x14, 0xcb, 0xc9, 0x29, 0x17, 0x60, 0xa6, 0x1f, 0xf3, 0xe8, 0xed, 0xee, 0x5f, 0xf7, + 0xc0, 0x75, 0x3a, 0x1c, 0x79, 0xbb, 0xfc, 0x3c, 0x64, 0xb1, 0xfc, 0xed, 0x87, 0x51, 0xc0, 0x03, + 0xb2, 0x86, 0x93, 0xde, 0x3b, 0x63, 0x8f, 0x4f, 0xe6, 0xc3, 0xfe, 0x28, 0x98, 0xed, 0x8e, 0x83, + 0x71, 0xb0, 0x8b, 0xdc, 0xe1, 0xfc, 0x39, 0xce, 0x70, 0x82, 0x23, 0xa9, 0xd5, 0xdb, 0x1e, 0x07, + 0xc1, 0x78, 0xca, 0x52, 0x29, 0xee, 0xcd, 0x58, 0xcc, 0xe9, 0x2c, 0x54, 0x02, 0xfb, 0x99, 0xf5, + 0x38, 0xf3, 0x5d, 0x16, 0xcd, 0x3c, 0x9f, 0x67, 0x87, 0x53, 0x6f, 0x18, 0xef, 0x8e, 0x82, 0xd9, + 0x2c, 0xf0, 0xb3, 0x07, 0xea, 0x3d, 0xf8, 0xb7, 0x9a, 0xa3, 0xe8, 0x3c, 0xe4, 0xc1, 0xee, 0x8c, + 0x45, 0xa7, 0x53, 0xa6, 0xfe, 0xa4, 0xb2, 0xf5, 0xdb, 0x2a, 0xd4, 0x6c, 0xf6, 0xe9, 0x9c, 0xc5, + 0x9c, 0xdc, 0x81, 0x2a, 0x1b, 0x4d, 0x82, 0x6e, 0xe5, 0x96, 0x71, 0xa7, 0xb1, 0x47, 0xfa, 0x72, + 0x13, 0xc5, 0x7d, 0x3c, 0x9a, 0x04, 0x87, 0x2b, 0x36, 0x4a, 0x90, 0xb7, 0x61, 0xed, 0xf9, 0x74, + 0x1e, 0x4f, 0xba, 0xab, 0x28, 0x7a, 0x35, 0x2f, 0xfa, 0x43, 0xc1, 0x3a, 0x5c, 0xb1, 0xa5, 0x8c, + 0x58, 0xd6, 0xf3, 0x9f, 0x07, 0xdd, 0x6a, 0xd9, 0xb2, 0x47, 0xfe, 0x73, 0x5c, 0x56, 0x48, 0x90, + 0x7d, 0x80, 0x98, 0x71, 0x27, 0x08, 0xb9, 0x17, 0xf8, 0xdd, 0x35, 0x94, 0xbf, 0x91, 0x97, 0x7f, + 0xc2, 0xf8, 0x4f, 0x90, 0x7d, 0xb8, 0x62, 0x9b, 0xb1, 0x9e, 0x08, 0x4d, 0xcf, 0xf7, 0xb8, 0x33, + 0x9a, 0x50, 0xcf, 0xef, 0xae, 0x97, 0x69, 0x1e, 0xf9, 0x1e, 0x7f, 0x28, 0xd8, 0x42, 0xd3, 0xd3, + 0x13, 0x71, 0x95, 0x4f, 0xe7, 0x2c, 0x3a, 0xef, 0xd6, 0xca, 0xae, 0xf2, 0x53, 0xc1, 0x12, 0x57, + 0x41, 0x19, 0xf2, 0x00, 0x1a, 0x43, 0x36, 0xf6, 0x7c, 0x67, 0x38, 0x0d, 0x46, 0xa7, 0xdd, 0x3a, + 0xaa, 0x74, 0xf3, 0x2a, 0x03, 0x21, 0x30, 0x10, 0xfc, 0xc3, 0x15, 0x1b, 0x86, 0xc9, 0x8c, 0xec, + 0x41, 0x7d, 0x34, 0x61, 0xa3, 0x53, 0x87, 0x2f, 0xba, 0x26, 0x6a, 0x5e, 0xcb, 0x6b, 0x3e, 0x14, + 0xdc, 0xa7, 0x8b, 0xc3, 0x15, 0xbb, 0x36, 0x92, 0x43, 0x72, 0x0f, 0x4c, 0xe6, 0xbb, 0x6a, 0xbb, + 0x06, 0x2a, 0x5d, 0x2f, 0x7c, 0x17, 0xdf, 0xd5, 0x9b, 0xd5, 0x99, 0x1a, 0x93, 0x3e, 0xac, 0x0b, + 0x47, 0xf1, 0x78, 0x77, 0x03, 0x75, 0x36, 0x0b, 0x1b, 0x21, 0xef, 0x70, 0xc5, 0x56, 0x52, 0xc2, + 0x7c, 0x2e, 0x9b, 0x7a, 0x67, 0x2c, 0x12, 0x87, 0xbb, 0x5a, 0x66, 0xbe, 0x47, 0x92, 0x8f, 0xc7, + 0x33, 0x5d, 0x3d, 0x19, 0xd4, 0x60, 0xed, 0x8c, 0x4e, 0xe7, 0xcc, 0x7a, 0x0b, 0x1a, 0x19, 0x4f, + 0x21, 0x5d, 0xa8, 0xcd, 0x58, 0x1c, 0xd3, 0x31, 0xeb, 0x1a, 0xb7, 0x8c, 0x3b, 0xa6, 0xad, 0xa7, + 0x56, 0x0b, 0x36, 0xb2, 0x7e, 0x62, 0xcd, 0x12, 0x45, 0xe1, 0x0b, 0x42, 0xf1, 0x8c, 0x45, 0xb1, + 0x70, 0x00, 0xa5, 0xa8, 0xa6, 0xe4, 0x36, 0x34, 0xd1, 0x0e, 0x8e, 0xe6, 0x0b, 0x3f, 0xad, 0xda, + 0x1b, 0x48, 0x3c, 0x51, 0x42, 0xdb, 0xd0, 0x08, 0xf7, 0xc2, 0x44, 0x64, 0x15, 0x45, 0x20, 0xdc, + 0x0b, 0x95, 0x80, 0xf5, 0x01, 0x74, 0x8a, 0xae, 0x44, 0x3a, 0xb0, 0x7a, 0xca, 0xce, 0xd5, 0x7e, + 0x62, 0x48, 0x36, 0xd5, 0xb5, 0x70, 0x0f, 0xd3, 0x56, 0x77, 0xfc, 0xa2, 0x92, 0x28, 0x27, 0xde, + 0x44, 0xf6, 0xa1, 0x2a, 0x62, 0x19, 0xb5, 0x1b, 0x7b, 0xbd, 0xbe, 0x0c, 0xf4, 0xbe, 0x0e, 0xf4, + 0xfe, 0x53, 0x1d, 0xe8, 0x83, 0xfa, 0x57, 0x2f, 0xb7, 0x57, 0xbe, 0xf8, 0xc3, 0xb6, 0x61, 0xa3, + 0x06, 0xb9, 0x29, 0x1c, 0x82, 0x7a, 0xbe, 0xe3, 0xb9, 0x6a, 0x9f, 0x1a, 0xce, 0x8f, 0x5c, 0x72, + 0x00, 0x9d, 0x51, 0xe0, 0xc7, 0xcc, 0x8f, 0xe7, 0xb1, 0x13, 0xd2, 0x88, 0xce, 0x62, 0x15, 0x6b, + 0xfa, 0xf3, 0x3f, 0xd4, 0xec, 0x63, 0xe4, 0xda, 0xed, 0x51, 0x9e, 0x40, 0x3e, 0x04, 0x38, 0xa3, + 0x53, 0xcf, 0xa5, 0x3c, 0x88, 0xe2, 0x6e, 0xf5, 0xd6, 0x6a, 0x46, 0xf9, 0x44, 0x33, 0x9e, 0x85, + 0x2e, 0xe5, 0x6c, 0x50, 0x15, 0x27, 0xb3, 0x33, 0xf2, 0xe4, 0x4d, 0x68, 0xd3, 0x30, 0x74, 0x62, + 0x4e, 0x39, 0x73, 0x86, 0xe7, 0x9c, 0xc5, 0x18, 0x8f, 0x1b, 0x76, 0x93, 0x86, 0xe1, 0x13, 0x41, + 0x1d, 0x08, 0xa2, 0xe5, 0x26, 0x5f, 0x13, 0x43, 0x85, 0x10, 0xa8, 0xba, 0x94, 0x53, 0xb4, 0xc6, + 0x86, 0x8d, 0x63, 0x41, 0x0b, 0x29, 0x9f, 0xa8, 0x3b, 0xe2, 0x98, 0x5c, 0x87, 0xf5, 0x09, 0xf3, + 0xc6, 0x13, 0x8e, 0xd7, 0x5a, 0xb5, 0xd5, 0x4c, 0x18, 0x3e, 0x8c, 0x82, 0x33, 0x86, 0xd9, 0xa2, + 0x6e, 0xcb, 0x89, 0xf5, 0x17, 0x03, 0xae, 0x5c, 0x0a, 0x2f, 0xb1, 0xee, 0x84, 0xc6, 0x13, 0xbd, + 0x97, 0x18, 0x93, 0xb7, 0xc5, 0xba, 0xd4, 0x65, 0x91, 0xca, 0x62, 0x4d, 0x75, 0xe3, 0x43, 0x24, + 0xaa, 0x8b, 0x2a, 0x11, 0xf2, 0x18, 0x3a, 0x53, 0x1a, 0x73, 0x47, 0x46, 0x81, 0x83, 0x59, 0x6a, + 0x35, 0x17, 0x99, 0x9f, 0x50, 0x1d, 0x2d, 0xc2, 0x39, 0x95, 0x7a, 0x6b, 0x9a, 0xa3, 0x92, 0x43, + 0xd8, 0x1c, 0x9e, 0xbf, 0xa0, 0x3e, 0xf7, 0x7c, 0xe6, 0x5c, 0xb2, 0x79, 0x5b, 0x2d, 0xf5, 0xf8, + 0xcc, 0x73, 0x99, 0x3f, 0xd2, 0xc6, 0xbe, 0x9a, 0xa8, 0x24, 0x1f, 0x23, 0xb6, 0x6e, 0x41, 0x2b, + 0x9f, 0x0b, 0x48, 0x0b, 0x2a, 0x7c, 0xa1, 0x6e, 0x58, 0xe1, 0x0b, 0xcb, 0x4a, 0x3c, 0x30, 0x09, + 0xc8, 0x4b, 0x32, 0x3b, 0xd0, 0x2e, 0x24, 0x87, 0x8c, 0xb9, 0x8d, 0xac, 0xb9, 0xad, 0x36, 0x34, + 0x73, 0x39, 0xc1, 0xfa, 0x7c, 0x0d, 0xea, 0x36, 0x8b, 0x43, 0xe1, 0x4c, 0x64, 0x1f, 0x4c, 0xb6, + 0x18, 0x31, 0x99, 0x8e, 0x8d, 0x42, 0xb2, 0x93, 0x32, 0x8f, 0x35, 0x5f, 0xa4, 0x85, 0x44, 0x98, + 0xec, 0xe4, 0xa0, 0xe4, 0x6a, 0x51, 0x29, 0x8b, 0x25, 0x77, 0xf3, 0x58, 0xb2, 0x59, 0x90, 0x2d, + 0x80, 0xc9, 0x4e, 0x0e, 0x4c, 0x8a, 0x0b, 0xe7, 0xd0, 0xe4, 0x7e, 0x09, 0x9a, 0x14, 0x8f, 0xbf, + 0x04, 0x4e, 0xee, 0x97, 0xc0, 0x49, 0xf7, 0xd2, 0x5e, 0xa5, 0x78, 0x72, 0x37, 0x8f, 0x27, 0xc5, + 0xeb, 0x14, 0x00, 0xe5, 0xc3, 0x32, 0x40, 0xb9, 0x59, 0xd0, 0x59, 0x8a, 0x28, 0xef, 0x5f, 0x42, + 0x94, 0xeb, 0x05, 0xd5, 0x12, 0x48, 0xb9, 0x9f, 0xcb, 0xf5, 0x50, 0x7a, 0xb7, 0xf2, 0x64, 0x4f, + 0xbe, 0x77, 0x19, 0x8d, 0x6e, 0x14, 0x3f, 0x6d, 0x19, 0x1c, 0xed, 0x16, 0xe0, 0xe8, 0x5a, 0xf1, + 0x94, 0x05, 0x3c, 0x4a, 0x51, 0x65, 0x47, 0xc4, 0x7d, 0xc1, 0xd3, 0x44, 0x8e, 0x60, 0x51, 0x14, + 0x44, 0x2a, 0x61, 0xcb, 0x89, 0x75, 0x47, 0x64, 0xa2, 0xd4, 0xbf, 0x5e, 0x81, 0x40, 0xe8, 0xf4, + 0x19, 0xef, 0xb2, 0xbe, 0x34, 0x52, 0x5d, 0x8c, 0xe8, 0x6c, 0x16, 0x33, 0x55, 0x16, 0xcb, 0x00, + 0x53, 0x25, 0x0f, 0x4c, 0xdb, 0xd0, 0x10, 0xb9, 0xb2, 0x80, 0x39, 0x34, 0xd4, 0x98, 0x43, 0xbe, + 0x03, 0x57, 0x30, 0xcf, 0x48, 0xf8, 0x52, 0x81, 0x58, 0xc5, 0x40, 0x6c, 0x0b, 0x86, 0xb4, 0x98, + 0x4c, 0x80, 0xef, 0xc0, 0xd5, 0x8c, 0xac, 0x58, 0x17, 0x73, 0x9c, 0x4c, 0xbe, 0x9d, 0x44, 0xfa, + 0x20, 0x0c, 0x0f, 0x69, 0x3c, 0xb1, 0x7e, 0x94, 0x1a, 0x28, 0xc5, 0x33, 0x02, 0xd5, 0x51, 0xe0, + 0xca, 0x7b, 0x37, 0x6d, 0x1c, 0x0b, 0x8c, 0x9b, 0x06, 0x63, 0x3c, 0x9c, 0x69, 0x8b, 0xa1, 0x90, + 0x4a, 0x42, 0xc9, 0x94, 0x31, 0x63, 0xfd, 0xd2, 0x48, 0xd7, 0x4b, 0x21, 0xae, 0x0c, 0x8d, 0x8c, + 0xff, 0x04, 0x8d, 0x2a, 0xaf, 0x87, 0x46, 0xd6, 0x85, 0x91, 0x7e, 0xb2, 0x04, 0x67, 0xbe, 0xd9, + 0x15, 0x85, 0xf7, 0x78, 0xbe, 0xcb, 0x16, 0x68, 0xd2, 0x55, 0x5b, 0x4e, 0x74, 0x09, 0xb0, 0x8e, + 0x66, 0xce, 0x97, 0x00, 0x35, 0xa4, 0xc9, 0x09, 0xb9, 0x8d, 0xf8, 0x14, 0x3c, 0x57, 0xa1, 0xda, + 0xec, 0xab, 0x6a, 0xfa, 0x58, 0x10, 0x6d, 0xc9, 0xcb, 0x64, 0x5b, 0x33, 0x07, 0x6e, 0x6f, 0x80, + 0x29, 0x0e, 0x1a, 0x87, 0x74, 0xc4, 0x30, 0xf2, 0x4c, 0x3b, 0x25, 0x58, 0xc7, 0x40, 0x2e, 0x47, + 0x3c, 0xf9, 0x00, 0xaa, 0x9c, 0x8e, 0x85, 0xbd, 0x85, 0xc9, 0x5a, 0x7d, 0xd9, 0x00, 0xf4, 0x3f, + 0x3e, 0x39, 0xa6, 0x5e, 0x34, 0xb8, 0x2e, 0x4c, 0xf5, 0xb7, 0x97, 0xdb, 0x2d, 0x21, 0x73, 0x37, + 0x98, 0x79, 0x9c, 0xcd, 0x42, 0x7e, 0x6e, 0xa3, 0x8e, 0xf5, 0x77, 0x43, 0x20, 0x41, 0x2e, 0x13, + 0x94, 0x1a, 0x4e, 0xbb, 0x7b, 0x25, 0x03, 0xda, 0x5f, 0xcf, 0x98, 0xff, 0x0f, 0x30, 0xa6, 0xb1, + 0xf3, 0x19, 0xf5, 0x39, 0x73, 0x95, 0x45, 0xcd, 0x31, 0x8d, 0x7f, 0x86, 0x04, 0x51, 0xe1, 0x08, + 0xf6, 0x3c, 0x66, 0x2e, 0x9a, 0x76, 0xd5, 0xae, 0x8d, 0x69, 0xfc, 0x2c, 0x66, 0x6e, 0x72, 0xaf, + 0xda, 0xeb, 0xdf, 0x2b, 0x6f, 0xc7, 0x7a, 0xd1, 0x8e, 0xff, 0xc8, 0xf8, 0x70, 0x0a, 0x92, 0xff, + 0xfb, 0xf7, 0xfe, 0xab, 0x21, 0x6a, 0x83, 0x7c, 0x1a, 0x26, 0x47, 0x70, 0x25, 0x89, 0x23, 0x67, + 0x8e, 0xf1, 0xa5, 0x7d, 0xe9, 0xd5, 0xe1, 0xd7, 0x39, 0xcb, 0x93, 0x63, 0xf2, 0x63, 0xb8, 0x51, + 0xc8, 0x02, 0xc9, 0x82, 0x95, 0x57, 0x26, 0x83, 0x6b, 0xf9, 0x64, 0xa0, 0xd7, 0xd3, 0x96, 0x58, + 0xfd, 0x06, 0x9e, 0xfd, 0x2d, 0x51, 0x28, 0x65, 0xc1, 0xa3, 0xec, 0x5b, 0x5a, 0xbf, 0x36, 0xa0, + 0x5d, 0x38, 0x0c, 0xb9, 0x07, 0x20, 0x53, 0x6b, 0xec, 0xbd, 0x60, 0x85, 0x2c, 0x86, 0x26, 0x7b, + 0xe2, 0xbd, 0x60, 0xea, 0xe0, 0xe6, 0x50, 0x13, 0xc8, 0x7b, 0x50, 0x67, 0xaa, 0x80, 0x53, 0xb7, + 0xbd, 0x56, 0xa8, 0xeb, 0x94, 0x4e, 0x22, 0x46, 0xbe, 0x0b, 0x66, 0x62, 0xc3, 0x42, 0xf1, 0x9e, + 0x98, 0x5c, 0x6f, 0x94, 0x08, 0x5a, 0x1f, 0x41, 0xbb, 0x70, 0x0c, 0xf2, 0x7f, 0x60, 0xce, 0xe8, + 0x42, 0x55, 0xe1, 0xb2, 0x7e, 0xab, 0xcf, 0xe8, 0x02, 0x0b, 0x70, 0x72, 0x03, 0x6a, 0x82, 0x39, + 0xa6, 0xf2, 0x2b, 0xac, 0xda, 0xeb, 0x33, 0xba, 0xf8, 0x88, 0xc6, 0xd6, 0x0e, 0xb4, 0xf2, 0x47, + 0xd3, 0xa2, 0x1a, 0x11, 0xa5, 0xe8, 0xc1, 0x98, 0x59, 0xf7, 0xa0, 0x5d, 0x38, 0x11, 0xb1, 0xa0, + 0x19, 0xce, 0x87, 0xce, 0x29, 0x3b, 0x77, 0xf0, 0xc8, 0xe8, 0x33, 0xa6, 0xdd, 0x08, 0xe7, 0xc3, + 0x8f, 0xd9, 0xf9, 0x53, 0x41, 0xb2, 0x9e, 0x40, 0x2b, 0x5f, 0x1f, 0x8b, 0x9c, 0x19, 0x05, 0x73, + 0xdf, 0xc5, 0xf5, 0xd7, 0x6c, 0x39, 0x11, 0x2d, 0xf6, 0x59, 0x20, 0xdd, 0x24, 0x5b, 0x10, 0x9f, + 0x04, 0x9c, 0x65, 0xaa, 0x6a, 0x29, 0x63, 0xfd, 0x62, 0x0d, 0xd6, 0x65, 0xb1, 0x4e, 0xfa, 0xf9, + 0x56, 0x50, 0xf8, 0x88, 0xd2, 0x94, 0x54, 0xa5, 0x98, 0xe0, 0xf0, 0x9b, 0xc5, 0x7e, 0x6a, 0xd0, + 0xb8, 0x78, 0xb9, 0x5d, 0x43, 0x0c, 0x3b, 0x7a, 0x94, 0x36, 0x57, 0xcb, 0x7a, 0x0f, 0xdd, 0xc9, + 0x55, 0x5f, 0xbb, 0x93, 0xbb, 0x01, 0x35, 0x7f, 0x3e, 0x73, 0xf8, 0x22, 0x56, 0xb9, 0x60, 0xdd, + 0x9f, 0xcf, 0x9e, 0x2e, 0xf0, 0xd3, 0xf1, 0x80, 0xd3, 0x29, 0xb2, 0x64, 0x26, 0xa8, 0x23, 0x41, + 0x30, 0xf7, 0xa1, 0x99, 0x81, 0x7a, 0xcf, 0x55, 0x25, 0x63, 0x2b, 0xeb, 0x8d, 0x47, 0x8f, 0xd4, + 0x2d, 0x1b, 0x09, 0xf4, 0x1f, 0xb9, 0xe4, 0x4e, 0xbe, 0x71, 0xc1, 0x0a, 0xa1, 0x8e, 0x8e, 0x9f, + 0xe9, 0x4d, 0x44, 0x7d, 0x20, 0x0e, 0x20, 0x42, 0x41, 0x8a, 0x98, 0x28, 0x52, 0x17, 0x04, 0x64, + 0xbe, 0x05, 0xed, 0x14, 0x64, 0xa5, 0x08, 0xc8, 0x55, 0x52, 0x32, 0x0a, 0xbe, 0x0b, 0x9b, 0x3e, + 0x5b, 0x70, 0xa7, 0x28, 0xdd, 0x40, 0x69, 0x22, 0x78, 0x27, 0x79, 0x8d, 0x6f, 0x43, 0x2b, 0x4d, + 0x16, 0x28, 0xbb, 0x21, 0xdb, 0xc7, 0x84, 0x8a, 0x62, 0x37, 0xa1, 0x9e, 0x94, 0x38, 0x4d, 0x14, + 0xa8, 0x51, 0x59, 0xd9, 0x24, 0x45, 0x53, 0xc4, 0xe2, 0xf9, 0x94, 0xab, 0x45, 0x5a, 0x28, 0x83, + 0x45, 0x93, 0x2d, 0xe9, 0x28, 0x7b, 0x1b, 0x9a, 0x3a, 0xec, 0xa4, 0x5c, 0x1b, 0xe5, 0x36, 0x34, + 0x11, 0x85, 0x76, 0xa0, 0x13, 0x46, 0x41, 0x18, 0xc4, 0x2c, 0x72, 0xa8, 0xeb, 0x46, 0x2c, 0x8e, + 0xbb, 0x1d, 0xb9, 0x9e, 0xa6, 0x1f, 0x48, 0xb2, 0xf5, 0x1e, 0xd4, 0x74, 0xed, 0xb6, 0x09, 0x6b, + 0x68, 0x75, 0x74, 0xc1, 0xaa, 0x2d, 0x27, 0x02, 0x25, 0x0e, 0xc2, 0x50, 0xbd, 0x40, 0x88, 0xa1, + 0xf5, 0x73, 0xa8, 0xa9, 0x0f, 0x56, 0xda, 0x97, 0x7e, 0x1f, 0x36, 0x42, 0x1a, 0x89, 0x6b, 0x64, + 0xbb, 0x53, 0xdd, 0x1d, 0x1c, 0xd3, 0x88, 0x3f, 0x61, 0x3c, 0xd7, 0xa4, 0x36, 0x50, 0x5e, 0x92, + 0xac, 0xfb, 0xd0, 0xcc, 0xc9, 0x88, 0x63, 0xa1, 0x1f, 0xe9, 0x48, 0xc3, 0x49, 0xb2, 0x73, 0x25, + 0xdd, 0xd9, 0x7a, 0x00, 0x66, 0xf2, 0x6d, 0x44, 0x11, 0xab, 0xaf, 0x6e, 0x28, 0x73, 0xcb, 0x29, + 0x36, 0xde, 0xc1, 0x67, 0x2c, 0x52, 0x31, 0x21, 0x27, 0xd6, 0xb3, 0x4c, 0x66, 0x90, 0x79, 0x9b, + 0xdc, 0x85, 0x9a, 0xca, 0x0c, 0x2a, 0x2a, 0x75, 0x8b, 0x7d, 0x8c, 0xa9, 0x41, 0xb7, 0xd8, 0x32, + 0x51, 0xa4, 0xcb, 0x56, 0xb2, 0xcb, 0x4e, 0xa1, 0xae, 0xa3, 0x3f, 0x9f, 0x26, 0xe5, 0x8a, 0x9d, + 0x62, 0x9a, 0x54, 0x8b, 0xa6, 0x82, 0xc2, 0x3b, 0x62, 0x6f, 0xec, 0x33, 0xd7, 0x49, 0x43, 0x08, + 0xf7, 0xa8, 0xdb, 0x6d, 0xc9, 0xf8, 0x44, 0xc7, 0x8b, 0xf5, 0x2e, 0xac, 0xcb, 0xb3, 0x09, 0xfb, + 0x88, 0x95, 0x75, 0x5d, 0x2f, 0xc6, 0xa5, 0xc0, 0xf1, 0x7b, 0x03, 0xea, 0x3a, 0x79, 0x96, 0x2a, + 0xe5, 0x0e, 0x5d, 0xf9, 0xba, 0x87, 0xfe, 0xef, 0x27, 0x9e, 0xbb, 0x40, 0x64, 0x7e, 0x39, 0x0b, + 0xb8, 0xe7, 0x8f, 0x1d, 0x69, 0x6b, 0x99, 0x83, 0x3a, 0xc8, 0x39, 0x41, 0xc6, 0xb1, 0xa0, 0xef, + 0x7d, 0xbe, 0x06, 0xed, 0x83, 0xc1, 0xc3, 0xa3, 0x83, 0x30, 0x9c, 0x7a, 0x23, 0x8a, 0xbd, 0xc2, + 0x2e, 0x54, 0xb1, 0x5d, 0x2a, 0x79, 0xee, 0xed, 0x95, 0xf5, 0xed, 0x64, 0x0f, 0xd6, 0xb0, 0x6b, + 0x22, 0x65, 0xaf, 0xbe, 0xbd, 0xd2, 0xf6, 0x5d, 0x6c, 0x22, 0xfb, 0xaa, 0xcb, 0x8f, 0xbf, 0xbd, + 0xb2, 0x1e, 0x9e, 0xfc, 0x00, 0xcc, 0xb4, 0x9d, 0x59, 0xf6, 0x04, 0xdc, 0x5b, 0xda, 0xcd, 0x0b, + 0xfd, 0xb4, 0xf4, 0x5b, 0xf6, 0x92, 0xd9, 0x5b, 0xda, 0xf6, 0x92, 0x7d, 0xa8, 0xe9, 0x82, 0xb9, + 0xfc, 0x91, 0xb6, 0xb7, 0xa4, 0xd3, 0x16, 0xe6, 0x91, 0x1d, 0x4a, 0xd9, 0x4b, 0x72, 0xaf, 0xf4, + 0x39, 0x80, 0xdc, 0x83, 0x75, 0x55, 0xc5, 0x94, 0x3e, 0xd4, 0xf6, 0xca, 0xfb, 0x65, 0x71, 0xc9, + 0xb4, 0x47, 0x5b, 0xf6, 0xda, 0xdd, 0x5b, 0xfa, 0x6e, 0x41, 0x0e, 0x00, 0x32, 0x8d, 0xc6, 0xd2, + 0x67, 0xec, 0xde, 0xf2, 0xf7, 0x08, 0xf2, 0x00, 0xea, 0xe9, 0x1b, 0x53, 0xf9, 0xc3, 0x74, 0x6f, + 0xd9, 0x13, 0xc1, 0xe0, 0x8d, 0x7f, 0xfe, 0x69, 0xcb, 0xf8, 0xd5, 0xc5, 0x96, 0xf1, 0xe5, 0xc5, + 0x96, 0xf1, 0xd5, 0xc5, 0x96, 0xf1, 0xbb, 0x8b, 0x2d, 0xe3, 0x8f, 0x17, 0x5b, 0xc6, 0x6f, 0xfe, + 0xbc, 0x65, 0x0c, 0xd7, 0xd1, 0xfd, 0xdf, 0xff, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x8d, + 0xcb, 0x04, 0x88, 0x19, 0x00, 0x00, } diff --git a/abci/types/types.proto b/abci/types/types.proto index ffa321836..b48ff1e8b 100644 --- a/abci/types/types.proto +++ b/abci/types/types.proto @@ -74,7 +74,6 @@ message RequestQuery { bool prove = 4; } -// NOTE: validators here have empty pubkeys. message RequestBeginBlock { bytes hash = 1; Header header = 2 [(gogoproto.nullable)=false]; @@ -208,12 +207,13 @@ message ResponseCommit { // ConsensusParams contains all consensus-relevant parameters // that can be adjusted by the abci app message ConsensusParams { - BlockSize block_size = 1; - EvidenceParams evidence_params = 2; + BlockSizeParams block_size = 1; + EvidenceParams evidence = 2; + ValidatorParams validator = 3; } // BlockSize contains limits on the block size. -message BlockSize { +message BlockSizeParams { // Note: must be greater than 0 int64 max_bytes = 1; // Note: must be greater or equal to -1 @@ -226,6 +226,11 @@ message EvidenceParams { int64 max_age = 1; } +// ValidatorParams contains limits on validators. +message ValidatorParams { + repeated string pub_key_types = 1; +} + message LastCommitInfo { int32 round = 1; repeated VoteInfo votes = 2 [(gogoproto.nullable)=false]; diff --git a/abci/types/typespb_test.go b/abci/types/typespb_test.go index 53c5cd94a..9375cc7f1 100644 --- a/abci/types/typespb_test.go +++ b/abci/types/typespb_test.go @@ -1479,15 +1479,15 @@ func TestConsensusParamsMarshalTo(t *testing.T) { } } -func TestBlockSizeProto(t *testing.T) { +func TestBlockSizeParamsProto(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) - p := NewPopulatedBlockSize(popr, false) + p := NewPopulatedBlockSizeParams(popr, false) dAtA, err := github_com_gogo_protobuf_proto.Marshal(p) if err != nil { t.Fatalf("seed = %d, err = %v", seed, err) } - msg := &BlockSize{} + msg := &BlockSizeParams{} if err := github_com_gogo_protobuf_proto.Unmarshal(dAtA, msg); err != nil { t.Fatalf("seed = %d, err = %v", seed, err) } @@ -1510,10 +1510,10 @@ func TestBlockSizeProto(t *testing.T) { } } -func TestBlockSizeMarshalTo(t *testing.T) { +func TestBlockSizeParamsMarshalTo(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) - p := NewPopulatedBlockSize(popr, false) + p := NewPopulatedBlockSizeParams(popr, false) size := p.Size() dAtA := make([]byte, size) for i := range dAtA { @@ -1523,7 +1523,7 @@ func TestBlockSizeMarshalTo(t *testing.T) { if err != nil { t.Fatalf("seed = %d, err = %v", seed, err) } - msg := &BlockSize{} + msg := &BlockSizeParams{} if err := github_com_gogo_protobuf_proto.Unmarshal(dAtA, msg); err != nil { t.Fatalf("seed = %d, err = %v", seed, err) } @@ -1591,6 +1591,62 @@ func TestEvidenceParamsMarshalTo(t *testing.T) { } } +func TestValidatorParamsProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := math_rand.New(math_rand.NewSource(seed)) + p := NewPopulatedValidatorParams(popr, false) + dAtA, err := github_com_gogo_protobuf_proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ValidatorParams{} + if err := github_com_gogo_protobuf_proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = github_com_gogo_protobuf_proto.Unmarshal(littlefuzz, msg) + } +} + +func TestValidatorParamsMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := math_rand.New(math_rand.NewSource(seed)) + p := NewPopulatedValidatorParams(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ValidatorParams{} + if err := github_com_gogo_protobuf_proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + func TestLastCommitInfoProto(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) @@ -2619,16 +2675,16 @@ func TestConsensusParamsJSON(t *testing.T) { t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) } } -func TestBlockSizeJSON(t *testing.T) { +func TestBlockSizeParamsJSON(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) - p := NewPopulatedBlockSize(popr, true) + p := NewPopulatedBlockSizeParams(popr, true) marshaler := github_com_gogo_protobuf_jsonpb.Marshaler{} jsondata, err := marshaler.MarshalToString(p) if err != nil { t.Fatalf("seed = %d, err = %v", seed, err) } - msg := &BlockSize{} + msg := &BlockSizeParams{} err = github_com_gogo_protobuf_jsonpb.UnmarshalString(jsondata, msg) if err != nil { t.Fatalf("seed = %d, err = %v", seed, err) @@ -2655,6 +2711,24 @@ func TestEvidenceParamsJSON(t *testing.T) { t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) } } +func TestValidatorParamsJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := math_rand.New(math_rand.NewSource(seed)) + p := NewPopulatedValidatorParams(popr, true) + marshaler := github_com_gogo_protobuf_jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ValidatorParams{} + err = github_com_gogo_protobuf_jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} func TestLastCommitInfoJSON(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) @@ -3563,12 +3637,12 @@ func TestConsensusParamsProtoCompactText(t *testing.T) { } } -func TestBlockSizeProtoText(t *testing.T) { +func TestBlockSizeParamsProtoText(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) - p := NewPopulatedBlockSize(popr, true) + p := NewPopulatedBlockSizeParams(popr, true) dAtA := github_com_gogo_protobuf_proto.MarshalTextString(p) - msg := &BlockSize{} + msg := &BlockSizeParams{} if err := github_com_gogo_protobuf_proto.UnmarshalText(dAtA, msg); err != nil { t.Fatalf("seed = %d, err = %v", seed, err) } @@ -3577,12 +3651,12 @@ func TestBlockSizeProtoText(t *testing.T) { } } -func TestBlockSizeProtoCompactText(t *testing.T) { +func TestBlockSizeParamsProtoCompactText(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) - p := NewPopulatedBlockSize(popr, true) + p := NewPopulatedBlockSizeParams(popr, true) dAtA := github_com_gogo_protobuf_proto.CompactTextString(p) - msg := &BlockSize{} + msg := &BlockSizeParams{} if err := github_com_gogo_protobuf_proto.UnmarshalText(dAtA, msg); err != nil { t.Fatalf("seed = %d, err = %v", seed, err) } @@ -3619,6 +3693,34 @@ func TestEvidenceParamsProtoCompactText(t *testing.T) { } } +func TestValidatorParamsProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := math_rand.New(math_rand.NewSource(seed)) + p := NewPopulatedValidatorParams(popr, true) + dAtA := github_com_gogo_protobuf_proto.MarshalTextString(p) + msg := &ValidatorParams{} + if err := github_com_gogo_protobuf_proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestValidatorParamsProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := math_rand.New(math_rand.NewSource(seed)) + p := NewPopulatedValidatorParams(popr, true) + dAtA := github_com_gogo_protobuf_proto.CompactTextString(p) + msg := &ValidatorParams{} + if err := github_com_gogo_protobuf_proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + func TestLastCommitInfoProtoText(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) @@ -4471,10 +4573,10 @@ func TestConsensusParamsSize(t *testing.T) { } } -func TestBlockSizeSize(t *testing.T) { +func TestBlockSizeParamsSize(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) - p := NewPopulatedBlockSize(popr, true) + p := NewPopulatedBlockSizeParams(popr, true) size2 := github_com_gogo_protobuf_proto.Size(p) dAtA, err := github_com_gogo_protobuf_proto.Marshal(p) if err != nil { @@ -4515,6 +4617,28 @@ func TestEvidenceParamsSize(t *testing.T) { } } +func TestValidatorParamsSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := math_rand.New(math_rand.NewSource(seed)) + p := NewPopulatedValidatorParams(popr, true) + size2 := github_com_gogo_protobuf_proto.Size(p) + dAtA, err := github_com_gogo_protobuf_proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := github_com_gogo_protobuf_proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + func TestLastCommitInfoSize(t *testing.T) { seed := time.Now().UnixNano() popr := math_rand.New(math_rand.NewSource(seed)) diff --git a/docs/spec/abci/abci.md b/docs/spec/abci/abci.md index afd726174..f057002ef 100644 --- a/docs/spec/abci/abci.md +++ b/docs/spec/abci/abci.md @@ -441,11 +441,12 @@ Commit are included in the header of the next block. ### ConsensusParams - **Fields**: - - `BlockSize (BlockSize)`: Parameters limiting the size of a block. - - `EvidenceParams (EvidenceParams)`: Parameters limiting the validity of + - `BlockSize (BlockSizeParams)`: Parameters limiting the size of a block. + - `Evidence (EvidenceParams)`: Parameters limiting the validity of evidence of byzantine behaviour. + - `Validator (ValidatorParams)`: Parameters limitng the types of pubkeys validators can use. -### BlockSize +### BlockSizeParams - **Fields**: - `MaxBytes (int64)`: Max size of a block, in bytes. @@ -463,6 +464,12 @@ Commit are included in the header of the next block. similar mechanism for handling Nothing-At-Stake attacks. - NOTE: this should change to time (instead of blocks)! +### ValidatorParams + +- **Fields**: + - `PubKeyTypes ([]string)`: List of accepted pubkey types. Uses same + naming as `PubKey.Type`. + ### Proof - **Fields**: diff --git a/evidence/pool.go b/evidence/pool.go index 0f3d482af..da00a3481 100644 --- a/evidence/pool.go +++ b/evidence/pool.go @@ -127,7 +127,7 @@ func (evpool *EvidencePool) MarkEvidenceAsCommitted(height int64, evidence []typ } // remove committed evidence from the clist - maxAge := evpool.State().ConsensusParams.EvidenceParams.MaxAge + maxAge := evpool.State().ConsensusParams.Evidence.MaxAge evpool.removeEvidence(height, maxAge, blockEvidenceMap) } diff --git a/evidence/pool_test.go b/evidence/pool_test.go index c3ed569e1..4e69596bf 100644 --- a/evidence/pool_test.go +++ b/evidence/pool_test.go @@ -38,7 +38,7 @@ func initializeValidatorState(valAddr []byte, height int64) dbm.DB { NextValidators: valSet.CopyIncrementAccum(1), LastHeightValidatorsChanged: 1, ConsensusParams: types.ConsensusParams{ - EvidenceParams: types.EvidenceParams{ + Evidence: types.EvidenceParams{ MaxAge: 1000000, }, }, diff --git a/evidence/reactor.go b/evidence/reactor.go index cfe47364c..52eb4a56f 100644 --- a/evidence/reactor.go +++ b/evidence/reactor.go @@ -164,7 +164,7 @@ func (evR EvidenceReactor) checkSendEvidenceMessage(peer p2p.Peer, ev types.Evid // NOTE: We only send evidence to peers where // peerHeight - maxAge < evidenceHeight < peerHeight - maxAge := evR.evpool.State().ConsensusParams.EvidenceParams.MaxAge + maxAge := evR.evpool.State().ConsensusParams.Evidence.MaxAge peerHeight := peerState.GetHeight() if peerHeight < evHeight { // peer is behind. sleep while he catches up diff --git a/state/execution.go b/state/execution.go index 72f6cc978..cc8e7e75f 100644 --- a/state/execution.go +++ b/state/execution.go @@ -186,7 +186,7 @@ func (blockExec *BlockExecutor) Commit( state.Validators.Size(), ), ), - mempool.PostCheckMaxGas(state.ConsensusParams.MaxGas), + mempool.PostCheckMaxGas(state.ConsensusParams.BlockSize.MaxGas), ) return res.Data, err diff --git a/state/state_test.go b/state/state_test.go index b1f24d301..88200e17e 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -390,11 +390,11 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) { func makeParams(blockBytes, blockGas, evidenceAge int64) types.ConsensusParams { return types.ConsensusParams{ - BlockSize: types.BlockSize{ + BlockSize: types.BlockSizeParams{ MaxBytes: blockBytes, MaxGas: blockGas, }, - EvidenceParams: types.EvidenceParams{ + Evidence: types.EvidenceParams{ MaxAge: evidenceAge, }, } @@ -416,7 +416,7 @@ func TestApplyUpdates(t *testing.T) { 1: {initParams, abci.ConsensusParams{}, initParams}, 2: {initParams, abci.ConsensusParams{ - BlockSize: &abci.BlockSize{ + BlockSize: &abci.BlockSizeParams{ MaxBytes: 44, MaxGas: 55, }, @@ -424,7 +424,7 @@ func TestApplyUpdates(t *testing.T) { makeParams(44, 55, 3)}, 3: {initParams, abci.ConsensusParams{ - EvidenceParams: &abci.EvidenceParams{ + Evidence: &abci.EvidenceParams{ MaxAge: 66, }, }, diff --git a/state/store.go b/state/store.go index 2f90c747e..7a0ef255a 100644 --- a/state/store.go +++ b/state/store.go @@ -251,7 +251,7 @@ func LoadConsensusParams(db dbm.DB, height int64) (types.ConsensusParams, error) return empty, ErrNoConsensusParamsForHeight{height} } - if paramsInfo.ConsensusParams == empty { + if paramsInfo.ConsensusParams.Equals(&empty) { paramsInfo2 := loadConsensusParamsInfo(db, paramsInfo.LastHeightChanged) if paramsInfo2 == nil { panic( diff --git a/state/validation.go b/state/validation.go index ff1791e2b..a12919847 100644 --- a/state/validation.go +++ b/state/validation.go @@ -178,7 +178,7 @@ func VerifyEvidence(stateDB dbm.DB, state State, evidence types.Evidence) error height := state.LastBlockHeight evidenceAge := height - evidence.Height() - maxAge := state.ConsensusParams.EvidenceParams.MaxAge + maxAge := state.ConsensusParams.Evidence.MaxAge if evidenceAge > maxAge { return fmt.Errorf("Evidence from height %d is too old. Min height is %d", evidence.Height(), height-maxAge) diff --git a/types/params.go b/types/params.go index ed1e7963b..81cf429ff 100644 --- a/types/params.go +++ b/types/params.go @@ -17,12 +17,13 @@ const ( // ConsensusParams contains consensus critical parameters that determine the // validity of blocks. type ConsensusParams struct { - BlockSize `json:"block_size_params"` - EvidenceParams `json:"evidence_params"` + BlockSize BlockSizeParams `json:"block_size"` + Evidence EvidenceParams `json:"evidence"` + Validator ValidatorParams `json:"validator"` } -// BlockSize contain limits on the block size. -type BlockSize struct { +// BlockSizeParams define limits on the block size. +type BlockSizeParams struct { MaxBytes int64 `json:"max_bytes"` MaxGas int64 `json:"max_gas"` } @@ -32,17 +33,24 @@ type EvidenceParams struct { MaxAge int64 `json:"max_age"` // only accept new evidence more recent than this } +// ValidatorParams restrict the public key types validators can use. +// NOTE: uses ABCI pubkey naming, not Amino routes. +type ValidatorParams struct { + PubKeyTypes []string `json:"pub_key_types"` +} + // DefaultConsensusParams returns a default ConsensusParams. func DefaultConsensusParams() *ConsensusParams { return &ConsensusParams{ - DefaultBlockSize(), + DefaultBlockSizeParams(), DefaultEvidenceParams(), + DefaultValidatorParams(), } } -// DefaultBlockSize returns a default BlockSize. -func DefaultBlockSize() BlockSize { - return BlockSize{ +// DefaultBlockSizeParams returns a default BlockSizeParams. +func DefaultBlockSizeParams() BlockSizeParams { + return BlockSizeParams{ MaxBytes: 22020096, // 21MB MaxGas: -1, } @@ -55,6 +63,12 @@ func DefaultEvidenceParams() EvidenceParams { } } +// DefaultValidatorParams returns a default ValidatorParams, which allows +// only ed25519 pubkeys. +func DefaultValidatorParams() ValidatorParams { + return ValidatorParams{[]string{ABCIPubKeyTypeEd25519}} +} + // Validate validates the ConsensusParams to ensure all values are within their // allowed limits, and returns an error if they are not. func (params *ConsensusParams) Validate() error { @@ -72,9 +86,22 @@ func (params *ConsensusParams) Validate() error { params.BlockSize.MaxGas) } - if params.EvidenceParams.MaxAge <= 0 { + if params.Evidence.MaxAge <= 0 { return cmn.NewError("EvidenceParams.MaxAge must be greater than 0. Got %d", - params.EvidenceParams.MaxAge) + params.Evidence.MaxAge) + } + + if len(params.Validator.PubKeyTypes) == 0 { + return cmn.NewError("len(Validator.PubKeyTypes) must be greater than 0") + } + + // Check if keyType is a known ABCIPubKeyType + for i := 0; i < len(params.Validator.PubKeyTypes); i++ { + keyType := params.Validator.PubKeyTypes[i] + if _, ok := ABCIPubKeyTypesToAminoRoutes[keyType]; !ok { + return cmn.NewError("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type", + i, keyType) + } } return nil @@ -94,6 +121,24 @@ func (params *ConsensusParams) Hash() []byte { return hasher.Sum(nil) } +func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool { + return params.BlockSize == params2.BlockSize && + params.Evidence == params2.Evidence && + stringSliceEqual(params.Validator.PubKeyTypes, params2.Validator.PubKeyTypes) +} + +func stringSliceEqual(a, b []string) bool { + if len(a) != len(b) { + return false + } + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false + } + } + return true +} + // Update returns a copy of the params with updates from the non-zero fields of p2. // NOTE: note: must not modify the original func (params ConsensusParams) Update(params2 *abci.ConsensusParams) ConsensusParams { @@ -108,8 +153,11 @@ func (params ConsensusParams) Update(params2 *abci.ConsensusParams) ConsensusPar res.BlockSize.MaxBytes = params2.BlockSize.MaxBytes res.BlockSize.MaxGas = params2.BlockSize.MaxGas } - if params2.EvidenceParams != nil { - res.EvidenceParams.MaxAge = params2.EvidenceParams.MaxAge + if params2.Evidence != nil { + res.Evidence.MaxAge = params2.Evidence.MaxAge + } + if params2.Validator != nil { + res.Validator.PubKeyTypes = params2.Validator.PubKeyTypes } return res } diff --git a/types/params_test.go b/types/params_test.go index 2936e5a4e..dc1936fbf 100644 --- a/types/params_test.go +++ b/types/params_test.go @@ -9,23 +9,32 @@ import ( abci "github.com/tendermint/tendermint/abci/types" ) +var ( + valEd25519 = []string{ABCIPubKeyTypeEd25519} + valSecp256k1 = []string{ABCIPubKeyTypeSecp256k1} +) + func TestConsensusParamsValidation(t *testing.T) { testCases := []struct { params ConsensusParams valid bool }{ // test block size - 0: {makeParams(1, 0, 1), true}, - 1: {makeParams(0, 0, 1), false}, - 2: {makeParams(47*1024*1024, 0, 1), true}, - 3: {makeParams(10, 0, 1), true}, - 4: {makeParams(100*1024*1024, 0, 1), true}, - 5: {makeParams(101*1024*1024, 0, 1), false}, - 6: {makeParams(1024*1024*1024, 0, 1), false}, - 7: {makeParams(1024*1024*1024, 0, -1), false}, + 0: {makeParams(1, 0, 1, valEd25519), true}, + 1: {makeParams(0, 0, 1, valEd25519), false}, + 2: {makeParams(47*1024*1024, 0, 1, valEd25519), true}, + 3: {makeParams(10, 0, 1, valEd25519), true}, + 4: {makeParams(100*1024*1024, 0, 1, valEd25519), true}, + 5: {makeParams(101*1024*1024, 0, 1, valEd25519), false}, + 6: {makeParams(1024*1024*1024, 0, 1, valEd25519), false}, + 7: {makeParams(1024*1024*1024, 0, -1, valEd25519), false}, // test evidence age - 8: {makeParams(1, 0, 0), false}, - 9: {makeParams(1, 0, -1), false}, + 8: {makeParams(1, 0, 0, valEd25519), false}, + 9: {makeParams(1, 0, -1, valEd25519), false}, + // test no pubkey type provided + 10: {makeParams(1, 0, 1, []string{}), false}, + // test invalid pubkey type provided + 11: {makeParams(1, 0, 1, []string{"potatoes make good pubkeys"}), false}, } for i, tc := range testCases { if tc.valid { @@ -36,28 +45,31 @@ func TestConsensusParamsValidation(t *testing.T) { } } -func makeParams(blockBytes, blockGas, evidenceAge int64) ConsensusParams { +func makeParams(blockBytes, blockGas, evidenceAge int64, pubkeyTypes []string) ConsensusParams { return ConsensusParams{ - BlockSize: BlockSize{ + BlockSize: BlockSizeParams{ MaxBytes: blockBytes, MaxGas: blockGas, }, - EvidenceParams: EvidenceParams{ + Evidence: EvidenceParams{ MaxAge: evidenceAge, }, + Validator: ValidatorParams{ + PubKeyTypes: pubkeyTypes, + }, } } func TestConsensusParamsHash(t *testing.T) { params := []ConsensusParams{ - makeParams(4, 2, 3), - makeParams(1, 4, 3), - makeParams(1, 2, 4), - makeParams(2, 5, 7), - makeParams(1, 7, 6), - makeParams(9, 5, 4), - makeParams(7, 8, 9), - makeParams(4, 6, 5), + makeParams(4, 2, 3, valEd25519), + makeParams(1, 4, 3, valEd25519), + makeParams(1, 2, 4, valEd25519), + makeParams(2, 5, 7, valEd25519), + makeParams(1, 7, 6, valEd25519), + makeParams(9, 5, 4, valEd25519), + makeParams(7, 8, 9, valEd25519), + makeParams(4, 6, 5, valEd25519), } hashes := make([][]byte, len(params)) @@ -83,23 +95,26 @@ func TestConsensusParamsUpdate(t *testing.T) { }{ // empty updates { - makeParams(1, 2, 3), + makeParams(1, 2, 3, valEd25519), &abci.ConsensusParams{}, - makeParams(1, 2, 3), + makeParams(1, 2, 3, valEd25519), }, // fine updates { - makeParams(1, 2, 3), + makeParams(1, 2, 3, valEd25519), &abci.ConsensusParams{ - BlockSize: &abci.BlockSize{ + BlockSize: &abci.BlockSizeParams{ MaxBytes: 100, MaxGas: 200, }, - EvidenceParams: &abci.EvidenceParams{ + Evidence: &abci.EvidenceParams{ MaxAge: 300, }, + Validator: &abci.ValidatorParams{ + PubKeyTypes: valSecp256k1, + }, }, - makeParams(100, 200, 300), + makeParams(100, 200, 300, valSecp256k1), }, } for _, tc := range testCases { diff --git a/types/protobuf.go b/types/protobuf.go index e1ec81e82..1535c1e37 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -24,6 +24,12 @@ const ( ABCIPubKeyTypeSecp256k1 = "secp256k1" ) +// TODO: Make non-global by allowing for registration of more pubkey types +var ABCIPubKeyTypesToAminoRoutes = map[string]string{ + ABCIPubKeyTypeEd25519: ed25519.PubKeyAminoRoute, + ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyAminoRoute, +} + //------------------------------------------------------- // TM2PB is used for converting Tendermint ABCI to protobuf ABCI. @@ -119,12 +125,15 @@ func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate { func (tm2pb) ConsensusParams(params *ConsensusParams) *abci.ConsensusParams { return &abci.ConsensusParams{ - BlockSize: &abci.BlockSize{ + BlockSize: &abci.BlockSizeParams{ MaxBytes: params.BlockSize.MaxBytes, MaxGas: params.BlockSize.MaxGas, }, - EvidenceParams: &abci.EvidenceParams{ - MaxAge: params.EvidenceParams.MaxAge, + Evidence: &abci.EvidenceParams{ + MaxAge: params.Evidence.MaxAge, + }, + Validator: &abci.ValidatorParams{ + PubKeyTypes: params.Validator.PubKeyTypes, }, } } @@ -215,12 +224,15 @@ func (pb2tm) ValidatorUpdates(vals []abci.ValidatorUpdate) ([]*Validator, error) func (pb2tm) ConsensusParams(csp *abci.ConsensusParams) ConsensusParams { return ConsensusParams{ - BlockSize: BlockSize{ + BlockSize: BlockSizeParams{ MaxBytes: csp.BlockSize.MaxBytes, MaxGas: csp.BlockSize.MaxGas, }, - EvidenceParams: EvidenceParams{ - MaxAge: csp.EvidenceParams.MaxAge, + Evidence: EvidenceParams{ + MaxAge: csp.Evidence.MaxAge, + }, + Validator: ValidatorParams{ + PubKeyTypes: csp.Validator.PubKeyTypes, }, } } diff --git a/types/protobuf_test.go b/types/protobuf_test.go index 7e7f55a1d..f5a2ce5d4 100644 --- a/types/protobuf_test.go +++ b/types/protobuf_test.go @@ -64,7 +64,6 @@ func TestABCIValidators(t *testing.T) { func TestABCIConsensusParams(t *testing.T) { cp := DefaultConsensusParams() - cp.EvidenceParams.MaxAge = 0 // TODO add this to ABCI abciCP := TM2PB.ConsensusParams(cp) cp2 := PB2TM.ConsensusParams(abciCP) From 60437953ac0a99cabf6589e3d60fdb5b77b136d1 Mon Sep 17 00:00:00 2001 From: yutianwu Date: Tue, 30 Oct 2018 23:46:55 +0800 Subject: [PATCH 21/35] [R4R] libs/log: add year to log format (#2707) * add year to log format * update documentation --- CHANGELOG_PENDING.md | 1 + docs/architecture/adr-001-logging.md | 8 ++++---- libs/log/tmfmt_logger.go | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 5c25a4b19..c8c55f532 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -91,6 +91,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [crypto/ed25519] [\#2558](https://github.com/tendermint/tendermint/issues/2558) Switch to use latest `golang.org/x/crypto` through our fork at github.com/tendermint/crypto - [tools] [\#2238](https://github.com/tendermint/tendermint/issues/2238) Binary dependencies are now locked to a specific git commit +- [libs/log] [\#2706](https://github.com/tendermint/tendermint/issues/2706) Add year to log format ### BUG FIXES: - [autofile] [\#2428](https://github.com/tendermint/tendermint/issues/2428) Group.RotateFile need call Flush() before rename (@goolAdapter) diff --git a/docs/architecture/adr-001-logging.md b/docs/architecture/adr-001-logging.md index a11a49e14..77e5d39a8 100644 --- a/docs/architecture/adr-001-logging.md +++ b/docs/architecture/adr-001-logging.md @@ -52,13 +52,13 @@ On top of this interface, we will need to implement a stdout logger, which will Many people say that they like the current output, so let's stick with it. ``` -NOTE[04-25|14:45:08] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 +NOTE[2017-04-25|14:45:08] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 ``` Couple of minor changes: ``` -I[04-25|14:45:08.322] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 +I[2017-04-25|14:45:08.322] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 ``` Notice the level is encoded using only one char plus milliseconds. @@ -155,14 +155,14 @@ Important keyvals should go first. Example: ``` correct -I[04-25|14:45:08.322] ABCI Replay Blocks module=consensus instance=1 appHeight=0 storeHeight=0 stateHeight=0 +I[2017-04-25|14:45:08.322] ABCI Replay Blocks module=consensus instance=1 appHeight=0 storeHeight=0 stateHeight=0 ``` not ``` wrong -I[04-25|14:45:08.322] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 instance=1 +I[2017-04-25|14:45:08.322] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 instance=1 ``` for that in most cases you'll need to add `instance` field to a logger upon creating, not when u log a particular message: diff --git a/libs/log/tmfmt_logger.go b/libs/log/tmfmt_logger.go index de155fefa..247ce8fc0 100644 --- a/libs/log/tmfmt_logger.go +++ b/libs/log/tmfmt_logger.go @@ -84,13 +84,13 @@ func (l tmfmtLogger) Log(keyvals ...interface{}) error { // Form a custom Tendermint line // // Example: - // D[05-02|11:06:44.322] Stopping AddrBook (ignoring: already stopped) + // D[2016-05-02|11:06:44.322] Stopping AddrBook (ignoring: already stopped) // // Description: // D - first character of the level, uppercase (ASCII only) - // [05-02|11:06:44.322] - our time format (see https://golang.org/src/time/format.go) + // [2016-05-02|11:06:44.322] - our time format (see https://golang.org/src/time/format.go) // Stopping ... - message - enc.buf.WriteString(fmt.Sprintf("%c[%s] %-44s ", lvl[0]-32, time.Now().Format("01-02|15:04:05.000"), msg)) + enc.buf.WriteString(fmt.Sprintf("%c[%s] %-44s ", lvl[0]-32, time.Now().Format("2016-01-02|15:04:05.000"), msg)) if module != unknown { enc.buf.WriteString("module=" + module + " ") From a530352f6165ac4c9dc64921fae2ab7500c9bc39 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Tue, 30 Oct 2018 17:16:55 +0100 Subject: [PATCH 22/35] Align Vote/Proposal fields with canonical order and fields (#2730) * reorder fields * add TestVoteString & update tests * remove redundant info from Proposal.String() * update spec * revert changes on vote.String() -> more human friendly --- Gopkg.lock | 6 +++--- docs/spec/blockchain/blockchain.md | 16 ++++++++-------- types/proposal.go | 14 ++++++++++---- types/vote.go | 9 +++++---- types/vote_test.go | 26 ++++++++++++++++++++------ 5 files changed, 46 insertions(+), 25 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index f4656e6ba..59e42f920 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -408,14 +408,14 @@ [[projects]] branch = "master" - digest = "1:fd98d154bf152ad5a49600ede7d7341851bcdfe358b9b82e5ccdba818618167c" + digest = "1:5207b4bc950fd0e45544263103af3e119c94fba6717f9d61931f7a19a7c0706a" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "2772b66316d2c587efeb188dcd5ebc6987656e84" + revision = "f7626d0b1519d8323581a047ca8b372ebf28de9a" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" @@ -446,7 +446,7 @@ name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "94acd270e44e65579b9ee3cdab25034d33fed608" + revision = "b69ba1387ce2108ac9bc8e8e5e5a46e7d5c72313" [[projects]] digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" diff --git a/docs/spec/blockchain/blockchain.md b/docs/spec/blockchain/blockchain.md index c5291ed45..061685378 100644 --- a/docs/spec/blockchain/blockchain.md +++ b/docs/spec/blockchain/blockchain.md @@ -146,14 +146,14 @@ The vote includes information about the validator signing it. ```go type Vote struct { - ValidatorAddress []byte - ValidatorIndex int - Height int64 - Round int - Timestamp Time - Type int8 - BlockID BlockID - Signature []byte + Type SignedMsgType // byte + Height int64 + Round int + Timestamp time.Time + BlockID BlockID + ValidatorAddress Address + ValidatorIndex int + Signature []byte } ``` diff --git a/types/proposal.go b/types/proposal.go index 5d70a3c84..fa82fdbb5 100644 --- a/types/proposal.go +++ b/types/proposal.go @@ -20,11 +20,12 @@ var ( // to be considered valid. It may depend on votes from a previous round, // a so-called Proof-of-Lock (POL) round, as noted in the POLRound and POLBlockID. type Proposal struct { + Type SignedMsgType Height int64 `json:"height"` Round int `json:"round"` + POLRound int `json:"pol_round"` // -1 if null. Timestamp time.Time `json:"timestamp"` BlockPartsHeader PartSetHeader `json:"block_parts_header"` - POLRound int `json:"pol_round"` // -1 if null. POLBlockID BlockID `json:"pol_block_id"` // zero if null. Signature []byte `json:"signature"` } @@ -33,11 +34,12 @@ type Proposal struct { // If there is no POLRound, polRound should be -1. func NewProposal(height int64, round int, blockPartsHeader PartSetHeader, polRound int, polBlockID BlockID) *Proposal { return &Proposal{ + Type: ProposalType, Height: height, Round: round, + POLRound: polRound, Timestamp: tmtime.Now(), BlockPartsHeader: blockPartsHeader, - POLRound: polRound, POLBlockID: polBlockID, } } @@ -45,9 +47,13 @@ func NewProposal(height int64, round int, blockPartsHeader PartSetHeader, polRou // String returns a string representation of the Proposal. func (p *Proposal) String() string { return fmt.Sprintf("Proposal{%v/%v %v (%v,%v) %X @ %s}", - p.Height, p.Round, p.BlockPartsHeader, p.POLRound, + p.Height, + p.Round, + p.BlockPartsHeader, + p.POLRound, p.POLBlockID, - cmn.Fingerprint(p.Signature), CanonicalTime(p.Timestamp)) + cmn.Fingerprint(p.Signature), + CanonicalTime(p.Timestamp)) } // SignBytes returns the Proposal bytes for signing diff --git a/types/vote.go b/types/vote.go index 333684fc2..826330d5c 100644 --- a/types/vote.go +++ b/types/vote.go @@ -48,13 +48,13 @@ type Address = crypto.Address // Represents a prevote, precommit, or commit vote from validators for consensus. type Vote struct { - ValidatorAddress Address `json:"validator_address"` - ValidatorIndex int `json:"validator_index"` + Type SignedMsgType `json:"type"` Height int64 `json:"height"` Round int `json:"round"` Timestamp time.Time `json:"timestamp"` - Type SignedMsgType `json:"type"` BlockID BlockID `json:"block_id"` // zero if vote is nil. + ValidatorAddress Address `json:"validator_address"` + ValidatorIndex int `json:"validator_index"` Signature []byte `json:"signature"` } @@ -94,7 +94,8 @@ func (vote *Vote) String() string { typeString, cmn.Fingerprint(vote.BlockID.Hash), cmn.Fingerprint(vote.Signature), - CanonicalTime(vote.Timestamp)) + CanonicalTime(vote.Timestamp), + ) } func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error { diff --git a/types/vote_test.go b/types/vote_test.go index 1d7e3daf0..572735858 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -26,12 +26,10 @@ func exampleVote(t byte) *Vote { } return &Vote{ - ValidatorAddress: tmhash.Sum([]byte("validator_address")), - ValidatorIndex: 56789, - Height: 12345, - Round: 2, - Timestamp: stamp, - Type: SignedMsgType(t), + Type: SignedMsgType(t), + Height: 12345, + Round: 2, + Timestamp: stamp, BlockID: BlockID{ Hash: tmhash.Sum([]byte("blockID_hash")), PartsHeader: PartSetHeader{ @@ -39,6 +37,8 @@ func exampleVote(t byte) *Vote { Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")), }, }, + ValidatorAddress: tmhash.Sum([]byte("validator_address")), + ValidatorIndex: 56789, } } @@ -235,3 +235,17 @@ func TestMaxVoteBytes(t *testing.T) { assert.EqualValues(t, MaxVoteBytes, len(bz)) } + +func TestVoteString(t *testing.T) { + str := examplePrecommit().String() + expected := `Vote{56789:6AF1F4111082 12345/02/2(Precommit) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` + if str != expected { + t.Errorf("Got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str) + } + + str2 := examplePrevote().String() + expected = `Vote{56789:6AF1F4111082 12345/02/1(Prevote) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` + if str2 != expected { + t.Errorf("Got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str2) + } +} From 7a033444800843cdba95a86eb02ab07de1bcf41d Mon Sep 17 00:00:00 2001 From: Zarko Milosevic Date: Wed, 31 Oct 2018 14:20:36 +0100 Subject: [PATCH 23/35] Introduce EventValidBlock for informing peers about wanted block (#2652) * Introduce EventValidBlock for informing peer about wanted block * Merge with develop * Add isCommit flag to NewValidBlock message - Add test for the case of +2/3 Precommit from the previous round --- CHANGELOG_PENDING.md | 2 + consensus/byzantine_test.go | 2 +- consensus/common_test.go | 5 + consensus/reactor.go | 87 ++++---- consensus/state.go | 61 +++--- consensus/state_test.go | 185 ++++++++++++++++++ .../reactors/consensus/consensus-reactor.md | 8 +- p2p/metrics.go | 2 +- types/event_bus.go | 4 + types/events.go | 2 + types/evidence_test.go | 2 +- 11 files changed, 285 insertions(+), 75 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index c8c55f532..ce0cf247a 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -102,6 +102,8 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi timeoutPrecommit before starting next round - [consensus] [\#1745](https://github.com/tendermint/tendermint/issues/1745) Wait for Proposal or timeoutProposal before entering prevote +- [consensus] [\#2583](https://github.com/tendermint/tendermint/issues/2583) ensure valid + block property with faulty proposer - [consensus] [\#2642](https://github.com/tendermint/tendermint/issues/2642) Only propose ValidBlock, not LockedBlock - [consensus] [\#2642](https://github.com/tendermint/tendermint/issues/2642) Initialized ValidRound and LockedRound to -1 - [consensus] [\#1637](https://github.com/tendermint/tendermint/issues/1637) Limit the amount of evidence that can be included in a diff --git a/consensus/byzantine_test.go b/consensus/byzantine_test.go index 60c2b0dbd..ed4cc90cc 100644 --- a/consensus/byzantine_test.go +++ b/consensus/byzantine_test.go @@ -263,7 +263,7 @@ func (br *ByzantineReactor) AddPeer(peer p2p.Peer) { // Send our state to peer. // If we're fast_syncing, broadcast a RoundStepMessage later upon SwitchToConsensus(). if !br.reactor.fastSync { - br.reactor.sendNewRoundStepMessages(peer) + br.reactor.sendNewRoundStepMessage(peer) } } func (br *ByzantineReactor) RemovePeer(peer p2p.Peer, reason interface{}) { diff --git a/consensus/common_test.go b/consensus/common_test.go index ca14a2926..c949922fe 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -420,6 +420,11 @@ func ensureNewProposal(proposalCh <-chan interface{}, height int64, round int) { "Timeout expired while waiting for NewProposal event") } +func ensureNewValidBlock(validBlockCh <-chan interface{}, height int64, round int) { + ensureNewEvent(validBlockCh, height, round, ensureTimeout, + "Timeout expired while waiting for NewValidBlock event") +} + func ensureNewBlock(blockCh <-chan interface{}, height int64) { select { case <-time.After(ensureTimeout): diff --git a/consensus/reactor.go b/consensus/reactor.go index 6643273cb..8d5e726f7 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -174,7 +174,7 @@ func (conR *ConsensusReactor) AddPeer(peer p2p.Peer) { // Send our state to peer. // If we're fast_syncing, broadcast a RoundStepMessage later upon SwitchToConsensus(). if !conR.FastSync() { - conR.sendNewRoundStepMessages(peer) + conR.sendNewRoundStepMessage(peer) } } @@ -215,8 +215,8 @@ func (conR *ConsensusReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) switch msg := msg.(type) { case *NewRoundStepMessage: ps.ApplyNewRoundStepMessage(msg) - case *CommitStepMessage: - ps.ApplyCommitStepMessage(msg) + case *NewValidBlockMessage: + ps.ApplyNewValidBlockMessage(msg) case *HasVoteMessage: ps.ApplyHasVoteMessage(msg) case *VoteSetMaj23Message: @@ -365,7 +365,12 @@ func (conR *ConsensusReactor) subscribeToBroadcastEvents() { const subscriber = "consensus-reactor" conR.conS.evsw.AddListenerForEvent(subscriber, types.EventNewRoundStep, func(data tmevents.EventData) { - conR.broadcastNewRoundStepMessages(data.(*cstypes.RoundState)) + conR.broadcastNewRoundStepMessage(data.(*cstypes.RoundState)) + }) + + conR.conS.evsw.AddListenerForEvent(subscriber, types.EventValidBlock, + func(data tmevents.EventData) { + conR.broadcastNewValidBlockMessage(data.(*cstypes.RoundState)) }) conR.conS.evsw.AddListenerForEvent(subscriber, types.EventVote, @@ -391,14 +396,20 @@ func (conR *ConsensusReactor) broadcastProposalHeartbeatMessage(hb *types.Heartb conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(msg)) } -func (conR *ConsensusReactor) broadcastNewRoundStepMessages(rs *cstypes.RoundState) { - nrsMsg, csMsg := makeRoundStepMessages(rs) - if nrsMsg != nil { - conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg)) - } - if csMsg != nil { - conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(csMsg)) +func (conR *ConsensusReactor) broadcastNewRoundStepMessage(rs *cstypes.RoundState) { + nrsMsg := makeRoundStepMessage(rs) + conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg)) +} + +func (conR *ConsensusReactor) broadcastNewValidBlockMessage(rs *cstypes.RoundState) { + csMsg := &NewValidBlockMessage{ + Height: rs.Height, + Round: rs.Round, + BlockPartsHeader: rs.ProposalBlockParts.Header(), + BlockParts: rs.ProposalBlockParts.BitArray(), + IsCommit: rs.Step == cstypes.RoundStepCommit, } + conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(csMsg)) } // Broadcasts HasVoteMessage to peers that care. @@ -427,33 +438,21 @@ func (conR *ConsensusReactor) broadcastHasVoteMessage(vote *types.Vote) { */ } -func makeRoundStepMessages(rs *cstypes.RoundState) (nrsMsg *NewRoundStepMessage, csMsg *CommitStepMessage) { +func makeRoundStepMessage(rs *cstypes.RoundState) (nrsMsg *NewRoundStepMessage) { nrsMsg = &NewRoundStepMessage{ - Height: rs.Height, - Round: rs.Round, - Step: rs.Step, + Height: rs.Height, + Round: rs.Round, + Step: rs.Step, SecondsSinceStartTime: int(time.Since(rs.StartTime).Seconds()), LastCommitRound: rs.LastCommit.Round(), } - if rs.Step == cstypes.RoundStepCommit { - csMsg = &CommitStepMessage{ - Height: rs.Height, - BlockPartsHeader: rs.ProposalBlockParts.Header(), - BlockParts: rs.ProposalBlockParts.BitArray(), - } - } return } -func (conR *ConsensusReactor) sendNewRoundStepMessages(peer p2p.Peer) { +func (conR *ConsensusReactor) sendNewRoundStepMessage(peer p2p.Peer) { rs := conR.conS.GetRoundState() - nrsMsg, csMsg := makeRoundStepMessages(rs) - if nrsMsg != nil { - peer.Send(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg)) - } - if csMsg != nil { - peer.Send(StateChannel, cdc.MustMarshalBinaryBare(csMsg)) - } + nrsMsg := makeRoundStepMessage(rs) + peer.Send(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg)) } func (conR *ConsensusReactor) gossipDataRoutine(peer p2p.Peer, ps *PeerState) { @@ -524,6 +523,7 @@ OUTER_LOOP: msg := &ProposalMessage{Proposal: rs.Proposal} logger.Debug("Sending proposal", "height", prs.Height, "round", prs.Round) if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) { + // NOTE[ZM]: A peer might have received different proposal msg so this Proposal msg will be rejected! ps.SetHasProposal(rs.Proposal) } } @@ -964,11 +964,18 @@ func (ps *PeerState) SetHasProposal(proposal *types.Proposal) { if ps.PRS.Height != proposal.Height || ps.PRS.Round != proposal.Round { return } + if ps.PRS.Proposal { return } ps.PRS.Proposal = true + + // ps.PRS.ProposalBlockParts is set due to NewValidBlockMessage + if ps.PRS.ProposalBlockParts != nil { + return + } + ps.PRS.ProposalBlockPartsHeader = proposal.BlockPartsHeader ps.PRS.ProposalBlockParts = cmn.NewBitArray(proposal.BlockPartsHeader.Total) ps.PRS.ProposalPOLRound = proposal.POLRound @@ -1211,7 +1218,6 @@ func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage) { // Just remember these values. psHeight := ps.PRS.Height psRound := ps.PRS.Round - //psStep := ps.PRS.Step psCatchupCommitRound := ps.PRS.CatchupCommitRound psCatchupCommit := ps.PRS.CatchupCommit @@ -1252,8 +1258,8 @@ func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage) { } } -// ApplyCommitStepMessage updates the peer state for the new commit. -func (ps *PeerState) ApplyCommitStepMessage(msg *CommitStepMessage) { +// ApplyNewValidBlockMessage updates the peer state for the new valid block. +func (ps *PeerState) ApplyNewValidBlockMessage(msg *NewValidBlockMessage) { ps.mtx.Lock() defer ps.mtx.Unlock() @@ -1261,6 +1267,10 @@ func (ps *PeerState) ApplyCommitStepMessage(msg *CommitStepMessage) { return } + if ps.PRS.Round != msg.Round && !msg.IsCommit { + return + } + ps.PRS.ProposalBlockPartsHeader = msg.BlockPartsHeader ps.PRS.ProposalBlockParts = msg.BlockParts } @@ -1344,7 +1354,7 @@ type ConsensusMessage interface{} func RegisterConsensusMessages(cdc *amino.Codec) { cdc.RegisterInterface((*ConsensusMessage)(nil), nil) cdc.RegisterConcrete(&NewRoundStepMessage{}, "tendermint/NewRoundStepMessage", nil) - cdc.RegisterConcrete(&CommitStepMessage{}, "tendermint/CommitStep", nil) + cdc.RegisterConcrete(&NewValidBlockMessage{}, "tendermint/NewValidBlockMessage", nil) cdc.RegisterConcrete(&ProposalMessage{}, "tendermint/Proposal", nil) cdc.RegisterConcrete(&ProposalPOLMessage{}, "tendermint/ProposalPOL", nil) cdc.RegisterConcrete(&BlockPartMessage{}, "tendermint/BlockPart", nil) @@ -1384,15 +1394,18 @@ func (m *NewRoundStepMessage) String() string { //------------------------------------- // CommitStepMessage is sent when a block is committed. -type CommitStepMessage struct { +type NewValidBlockMessage struct { Height int64 + Round int BlockPartsHeader types.PartSetHeader BlockParts *cmn.BitArray + IsCommit bool } // String returns a string representation. -func (m *CommitStepMessage) String() string { - return fmt.Sprintf("[CommitStep H:%v BP:%v BA:%v]", m.Height, m.BlockPartsHeader, m.BlockParts) +func (m *NewValidBlockMessage) String() string { + return fmt.Sprintf("[ValidBlockMessage H:%v R:%v BP:%v BA:%v IsCommit:%v]", + m.Height, m.Round, m.BlockPartsHeader, m.BlockParts, m.IsCommit) } //------------------------------------- diff --git a/consensus/state.go b/consensus/state.go index 40aeeb7a4..3048ee3dd 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -904,13 +904,6 @@ func (cs *ConsensusState) defaultDecideProposal(height int64, round int) { polRound, polBlockID := cs.Votes.POLInfo() proposal := types.NewProposal(height, round, blockParts.Header(), polRound, polBlockID) if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal); err == nil { - // Set fields - /* fields set by setProposal and addBlockPart - cs.Proposal = proposal - cs.ProposalBlock = block - cs.ProposalBlockParts = blockParts - */ - // send proposal and block parts on internal msg queue cs.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, ""}) for i := 0; i < blockParts.Total(); i++ { @@ -994,14 +987,6 @@ func (cs *ConsensusState) enterPrevote(height int64, round int) { cs.newStep() }() - // fire event for how we got here - if cs.isProposalComplete() { - cs.eventBus.PublishEventCompleteProposal(cs.RoundStateEvent()) - } else { - // we received +2/3 prevotes for a future round - // TODO: catchup event? - } - cs.Logger.Info(fmt.Sprintf("enterPrevote(%v/%v). Current: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step)) // Sign and broadcast vote as necessary @@ -1240,6 +1225,8 @@ func (cs *ConsensusState) enterCommit(height int64, commitRound int) { // Set up ProposalBlockParts and keep waiting. cs.ProposalBlock = nil cs.ProposalBlockParts = types.NewPartSetFromHeader(blockID.PartsHeader) + cs.eventBus.PublishEventValidBlock(cs.RoundStateEvent()) + cs.evsw.FireEvent(types.EventValidBlock, &cs.RoundState) } else { // We just need to keep waiting. } @@ -1420,11 +1407,6 @@ func (cs *ConsensusState) defaultSetProposal(proposal *types.Proposal) error { return nil } - // We don't care about the proposal if we're already in cstypes.RoundStepCommit. - if cstypes.RoundStepCommit <= cs.Step { - return nil - } - // Verify POLRound, which must be -1 or between 0 and proposal.Round exclusive. if proposal.POLRound != -1 && (proposal.POLRound < 0 || proposal.Round <= proposal.POLRound) { @@ -1437,7 +1419,12 @@ func (cs *ConsensusState) defaultSetProposal(proposal *types.Proposal) error { } cs.Proposal = proposal - cs.ProposalBlockParts = types.NewPartSetFromHeader(proposal.BlockPartsHeader) + // We don't update cs.ProposalBlockParts if it is already set. + // This happens if we're already in cstypes.RoundStepCommit or if there is a valid block in the current round. + // TODO: We can check if Proposal is for a different block as this is a sign of misbehavior! + if cs.ProposalBlockParts == nil { + cs.ProposalBlockParts = types.NewPartSetFromHeader(proposal.BlockPartsHeader) + } cs.Logger.Info("Received proposal", "proposal", proposal) return nil } @@ -1478,6 +1465,7 @@ func (cs *ConsensusState) addProposalBlockPart(msg *BlockPartMessage, peerID p2p } // NOTE: it's possible to receive complete proposal blocks for future rounds without having the proposal cs.Logger.Info("Received complete proposal block", "height", cs.ProposalBlock.Height, "hash", cs.ProposalBlock.Hash()) + cs.eventBus.PublishEventCompleteProposal(cs.RoundStateEvent()) // Update Valid* if we can. prevotes := cs.Votes.Prevotes(cs.Round) @@ -1616,16 +1604,26 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool, // Update Valid* if we can. // NOTE: our proposal block may be nil or not what received a polka.. - // TODO: we may want to still update the ValidBlock and obtain it via gossipping - if len(blockID.Hash) != 0 && - (cs.ValidRound < vote.Round) && - (vote.Round <= cs.Round) && - cs.ProposalBlock.HashesTo(blockID.Hash) { + if len(blockID.Hash) != 0 && (cs.ValidRound < vote.Round) && (vote.Round == cs.Round) { - cs.Logger.Info("Updating ValidBlock because of POL.", "validRound", cs.ValidRound, "POLRound", vote.Round) - cs.ValidRound = vote.Round - cs.ValidBlock = cs.ProposalBlock - cs.ValidBlockParts = cs.ProposalBlockParts + if cs.ProposalBlock.HashesTo(blockID.Hash) { + cs.Logger.Info( + "Updating ValidBlock because of POL.", "validRound", cs.ValidRound, "POLRound", vote.Round) + cs.ValidRound = vote.Round + cs.ValidBlock = cs.ProposalBlock + cs.ValidBlockParts = cs.ProposalBlockParts + } else { + cs.Logger.Info( + "Valid block we don't know about. Set ProposalBlock=nil", + "proposal", cs.ProposalBlock.Hash(), "blockId", blockID.Hash) + // We're getting the wrong block. + cs.ProposalBlock = nil + } + if !cs.ProposalBlockParts.HasHeader(blockID.PartsHeader) { + cs.ProposalBlockParts = types.NewPartSetFromHeader(blockID.PartsHeader) + } + cs.evsw.FireEvent(types.EventValidBlock, &cs.RoundState) + cs.eventBus.PublishEventValidBlock(cs.RoundStateEvent()) } } @@ -1634,7 +1632,8 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool, // Round-skip if there is any 2/3+ of votes ahead of us cs.enterNewRound(height, vote.Round) } else if cs.Round == vote.Round && cstypes.RoundStepPrevote <= cs.Step { // current round - if prevotes.HasTwoThirdsMajority() { + blockID, ok := prevotes.TwoThirdsMajority() + if ok && (cs.isProposalComplete() || len(blockID.Hash) == 0) { cs.enterPrecommit(height, vote.Round) } else if prevotes.HasTwoThirdsAny() { cs.enterPrevoteWait(height, vote.Round) diff --git a/consensus/state_test.go b/consensus/state_test.go index 83c4bb142..87c8b285a 100644 --- a/consensus/state_test.go +++ b/consensus/state_test.go @@ -966,6 +966,117 @@ func TestProposeValidBlock(t *testing.T) { assert.True(t, bytes.Equal(rs.ProposalBlock.Hash(), rs.ValidBlock.Hash())) } +// What we want: +// P0 miss to lock B but set valid block to B after receiving delayed prevote. +func TestSetValidBlockOnDelayedPrevote(t *testing.T) { + cs1, vss := randConsensusState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round := cs1.Height, cs1.Round + + partSize := types.BlockPartSizeBytes + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress()) + + // start round and wait for propose and prevote + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + propBlock := rs.ProposalBlock + propBlockHash := propBlock.Hash() + propBlockParts := propBlock.MakePartSet(partSize) + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], propBlockHash) + + // vs2 send prevote for propBlock + signAddVotes(cs1, types.PrevoteType, propBlockHash, propBlockParts.Header(), vs2) + + // vs3 send prevote nil + signAddVotes(cs1, types.PrevoteType, nil, types.PartSetHeader{}, vs3) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.TimeoutPrevote.Nanoseconds()) + + ensurePrecommit(voteCh, height, round) + // we should have precommitted + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) + + rs = cs1.GetRoundState() + + assert.True(t, rs.ValidBlock == nil) + assert.True(t, rs.ValidBlockParts == nil) + assert.True(t, rs.ValidRound == -1) + + // vs2 send (delayed) prevote for propBlock + signAddVotes(cs1, types.PrevoteType, propBlockHash, propBlockParts.Header(), vs4) + + ensureNewValidBlock(validBlockCh, height, round) + + rs = cs1.GetRoundState() + + assert.True(t, bytes.Equal(rs.ValidBlock.Hash(), propBlockHash)) + assert.True(t, rs.ValidBlockParts.Header().Equals(propBlockParts.Header())) + assert.True(t, rs.ValidRound == round) +} + +// What we want: +// P0 miss to lock B as Proposal Block is missing, but set valid block to B after +// receiving delayed Block Proposal. +func TestSetValidBlockOnDelayedProposal(t *testing.T) { + cs1, vss := randConsensusState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round := cs1.Height, cs1.Round + + partSize := types.BlockPartSizeBytes + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress()) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + + round = round + 1 // move to round in which P0 is not proposer + incrementRound(vs2, vs3, vs4) + + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.TimeoutPropose.Nanoseconds()) + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1) + propBlockHash := propBlock.Hash() + propBlockParts := propBlock.MakePartSet(partSize) + + // vs2, vs3 and vs4 send prevote for propBlock + signAddVotes(cs1, types.PrevoteType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4) + ensureNewValidBlock(validBlockCh, height, round) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.TimeoutPrevote.Nanoseconds()) + + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) + + if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { + t.Fatal(err) + } + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + + assert.True(t, bytes.Equal(rs.ValidBlock.Hash(), propBlockHash)) + assert.True(t, rs.ValidBlockParts.Header().Equals(propBlockParts.Header())) + assert.True(t, rs.ValidRound == round) +} + // 4 vals, 3 Nil Precommits at P0 // What we want: // P0 waits for timeoutPrecommit before starting next round @@ -1078,6 +1189,80 @@ func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) { validatePrevote(t, cs1, round, vss[0], nil) } +// What we want: +// P0 emit NewValidBlock event upon receiving 2/3+ Precommit for B but hasn't received block B yet +func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) { + cs1, vss := randConsensusState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round := cs1.Height, 1 + + incrementRound(vs2, vs3, vs4) + + partSize := types.BlockPartSizeBytes + + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + + _, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round) + propBlockHash := propBlock.Hash() + propBlockParts := propBlock.MakePartSet(partSize) + + // start round in which PO is not proposer + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + // vs2, vs3 and vs4 send precommit for propBlock + signAddVotes(cs1, types.PrecommitType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4) + ensureNewValidBlock(validBlockCh, height, round) + + rs := cs1.GetRoundState() + assert.True(t, rs.Step == cstypes.RoundStepCommit) + assert.True(t, rs.ProposalBlock == nil) + assert.True(t, rs.ProposalBlockParts.Header().Equals(propBlockParts.Header())) + +} + +// What we want: +// P0 receives 2/3+ Precommit for B for round 0, while being in round 1. It emits NewValidBlock event. +// After receiving block, it executes block and moves to the next height. +func TestCommitFromPreviousRound(t *testing.T) { + cs1, vss := randConsensusState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round := cs1.Height, 1 + + partSize := types.BlockPartSizeBytes + + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + + prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round) + propBlockHash := propBlock.Hash() + propBlockParts := propBlock.MakePartSet(partSize) + + // start round in which PO is not proposer + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + // vs2, vs3 and vs4 send precommit for propBlock for the previous round + signAddVotes(cs1, types.PrecommitType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4) + + ensureNewValidBlock(validBlockCh, height, round) + + rs := cs1.GetRoundState() + assert.True(t, rs.Step == cstypes.RoundStepCommit) + assert.True(t, rs.CommitRound == vs2.Round) + assert.True(t, rs.ProposalBlock == nil) + assert.True(t, rs.ProposalBlockParts.Header().Equals(propBlockParts.Header())) + + if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { + t.Fatal(err) + } + + ensureNewProposal(proposalCh, height, round) + ensureNewRound(newRoundCh, height+1, 0) +} + //------------------------------------------------------------------------------------------ // SlashingSuite // TODO: Slashing diff --git a/docs/spec/reactors/consensus/consensus-reactor.md b/docs/spec/reactors/consensus/consensus-reactor.md index 7be350322..5ba03322d 100644 --- a/docs/spec/reactors/consensus/consensus-reactor.md +++ b/docs/spec/reactors/consensus/consensus-reactor.md @@ -129,11 +129,11 @@ handleMessage(msg): Reset prs.CatchupCommitRound and prs.CatchupCommit ``` -### CommitStepMessage handler +### NewValidBlockMessage handler ``` handleMessage(msg): - if prs.Height == msg.Height then + if prs.Height == msg.Height && prs.Round == msg.Round then prs.ProposalBlockPartsHeader = msg.BlockPartsHeader prs.ProposalBlockParts = msg.BlockParts ``` @@ -161,8 +161,8 @@ handleMessage(msg): handleMessage(msg): if prs.Height != msg.Height || prs.Round != msg.Round || prs.Proposal then return prs.Proposal = true - prs.ProposalBlockPartsHeader = msg.BlockPartsHeader - prs.ProposalBlockParts = empty set + if prs.ProposalBlockParts == empty set then // otherwise it is set in NewValidBlockMessage handler + prs.ProposalBlockPartsHeader = msg.BlockPartsHeader prs.ProposalPOLRound = msg.POLRound prs.ProposalPOL = nil Send msg through internal peerMsgQueue to ConsensusState service diff --git a/p2p/metrics.go b/p2p/metrics.go index b066fb317..ed26d1192 100644 --- a/p2p/metrics.go +++ b/p2p/metrics.go @@ -62,7 +62,7 @@ func PrometheusMetrics(namespace string) *Metrics { // NopMetrics returns no-op Metrics. func NopMetrics() *Metrics { return &Metrics{ - Peers: discard.NewGauge(), + Peers: discard.NewGauge(), PeerReceiveBytesTotal: discard.NewCounter(), PeerSendBytesTotal: discard.NewCounter(), PeerPendingSendBytes: discard.NewGauge(), diff --git a/types/event_bus.go b/types/event_bus.go index 269d5ab1f..65206e938 100644 --- a/types/event_bus.go +++ b/types/event_bus.go @@ -83,6 +83,10 @@ func (b *EventBus) PublishEventVote(data EventDataVote) error { return b.Publish(EventVote, data) } +func (b *EventBus) PublishEventValidBlock(data EventDataRoundState) error { + return b.Publish(EventValidBlock, data) +} + // PublishEventTx publishes tx event with tags from Result. Note it will add // predefined tags (EventTypeKey, TxHashKey). Existing tags with the same names // will be overwritten. diff --git a/types/events.go b/types/events.go index 09f7216e9..33aa712ef 100644 --- a/types/events.go +++ b/types/events.go @@ -23,6 +23,7 @@ const ( EventTimeoutWait = "TimeoutWait" EventTx = "Tx" EventUnlock = "Unlock" + EventValidBlock = "ValidBlock" EventValidatorSetUpdates = "ValidatorSetUpdates" EventVote = "Vote" ) @@ -119,6 +120,7 @@ var ( EventQueryTx = QueryForEvent(EventTx) EventQueryUnlock = QueryForEvent(EventUnlock) EventQueryValidatorSetUpdates = QueryForEvent(EventValidatorSetUpdates) + EventQueryValidBlock = QueryForEvent(EventValidBlock) EventQueryVote = QueryForEvent(EventVote) ) diff --git a/types/evidence_test.go b/types/evidence_test.go index 44276ab18..033b51e5d 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -61,7 +61,7 @@ func TestEvidence(t *testing.T) { {vote1, makeVote(val, chainID, 0, 10, 3, 1, blockID2), false}, // wrong round {vote1, makeVote(val, chainID, 0, 10, 2, 2, blockID2), false}, // wrong step {vote1, makeVote(val2, chainID, 0, 10, 2, 1, blockID), false}, // wrong validator - {vote1, badVote, false}, // signed by wrong key + {vote1, badVote, false}, // signed by wrong key } pubKey := val.GetPubKey() From c5905900eb26d0af7297faee97f1861cee840c00 Mon Sep 17 00:00:00 2001 From: Zarko Milosevic Date: Wed, 31 Oct 2018 15:27:11 +0100 Subject: [PATCH 24/35] Simplify proposal msg (#2735) * Align Proposal message with spec * Update spec --- CHANGELOG_PENDING.md | 1 + Gopkg.lock | 4 +-- consensus/byzantine_test.go | 8 ++--- consensus/common_test.go | 4 +-- consensus/reactor.go | 4 +-- consensus/replay.go | 2 +- consensus/replay_test.go | 2 +- consensus/state.go | 7 ++-- consensus/state_test.go | 12 ++++--- consensus/types/round_state_test.go | 7 ++-- docs/spec/reactors/consensus/consensus.md | 14 +++----- privval/priv_validator_test.go | 16 ++++----- types/canonical.go | 30 ++++++++--------- types/proposal.go | 40 +++++++++++------------ types/proposal_test.go | 16 +++++---- 15 files changed, 82 insertions(+), 85 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index ce0cf247a..f28b46089 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -108,6 +108,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [consensus] [\#2642](https://github.com/tendermint/tendermint/issues/2642) Initialized ValidRound and LockedRound to -1 - [consensus] [\#1637](https://github.com/tendermint/tendermint/issues/1637) Limit the amount of evidence that can be included in a block +- [consensus] [\#2646](https://github.com/tendermint/tendermint/issues/2646) Simplify Proposal message (align with spec) - [evidence] [\#2515](https://github.com/tendermint/tendermint/issues/2515) Fix db iter leak (@goolAdapter) - [libs/event] [\#2518](https://github.com/tendermint/tendermint/issues/2518) Fix event concurrency flaw (@goolAdapter) - [node] [\#2434](https://github.com/tendermint/tendermint/issues/2434) Make node respond to signal interrupts while sleeping for genesis time diff --git a/Gopkg.lock b/Gopkg.lock index 59e42f920..35542bf62 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -408,14 +408,14 @@ [[projects]] branch = "master" - digest = "1:5207b4bc950fd0e45544263103af3e119c94fba6717f9d61931f7a19a7c0706a" + digest = "1:6f86e2f2e2217cd4d74dec6786163cf80e4d2b99adb341ecc60a45113b844dca" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "f7626d0b1519d8323581a047ca8b372ebf28de9a" + revision = "7e31e0c00fa05cb5fbf4347b585621d6709e19a4" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" diff --git a/consensus/byzantine_test.go b/consensus/byzantine_test.go index ed4cc90cc..6f46c04d3 100644 --- a/consensus/byzantine_test.go +++ b/consensus/byzantine_test.go @@ -179,16 +179,16 @@ func byzantineDecideProposalFunc(t *testing.T, height int64, round int, cs *Cons // Create a new proposal block from state/txs from the mempool. block1, blockParts1 := cs.createProposalBlock() - polRound, polBlockID := cs.Votes.POLInfo() - proposal1 := types.NewProposal(height, round, blockParts1.Header(), polRound, polBlockID) + polRound, propBlockID := cs.ValidRound, types.BlockID{block1.Hash(), blockParts1.Header()} + proposal1 := types.NewProposal(height, round, polRound, propBlockID) if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal1); err != nil { t.Error(err) } // Create a new proposal block from state/txs from the mempool. block2, blockParts2 := cs.createProposalBlock() - polRound, polBlockID = cs.Votes.POLInfo() - proposal2 := types.NewProposal(height, round, blockParts2.Header(), polRound, polBlockID) + polRound, propBlockID = cs.ValidRound, types.BlockID{block2.Hash(), blockParts2.Header()} + proposal2 := types.NewProposal(height, round, polRound, propBlockID) if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal2); err != nil { t.Error(err) } diff --git a/consensus/common_test.go b/consensus/common_test.go index c949922fe..ae8bb6bfe 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -130,8 +130,8 @@ func decideProposal(cs1 *ConsensusState, vs *validatorStub, height int64, round } // Make proposal - polRound, polBlockID := cs1.Votes.POLInfo() - proposal = types.NewProposal(height, round, blockParts.Header(), polRound, polBlockID) + polRound, propBlockID := cs1.ValidRound, types.BlockID{block.Hash(), blockParts.Header()} + proposal = types.NewProposal(height, round, polRound, propBlockID) if err := vs.SignProposal(cs1.state.ChainID, proposal); err != nil { panic(err) } diff --git a/consensus/reactor.go b/consensus/reactor.go index 8d5e726f7..e8c7adc7f 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -976,8 +976,8 @@ func (ps *PeerState) SetHasProposal(proposal *types.Proposal) { return } - ps.PRS.ProposalBlockPartsHeader = proposal.BlockPartsHeader - ps.PRS.ProposalBlockParts = cmn.NewBitArray(proposal.BlockPartsHeader.Total) + ps.PRS.ProposalBlockPartsHeader = proposal.BlockID.PartsHeader + ps.PRS.ProposalBlockParts = cmn.NewBitArray(proposal.BlockID.PartsHeader.Total) ps.PRS.ProposalPOLRound = proposal.POLRound ps.PRS.ProposalPOL = nil // Nil until ProposalPOLMessage received. } diff --git a/consensus/replay.go b/consensus/replay.go index bffab8d28..fcff877fd 100644 --- a/consensus/replay.go +++ b/consensus/replay.go @@ -73,7 +73,7 @@ func (cs *ConsensusState) readReplayMessage(msg *TimedWALMessage, newStepCh chan case *ProposalMessage: p := msg.Proposal cs.Logger.Info("Replay: Proposal", "height", p.Height, "round", p.Round, "header", - p.BlockPartsHeader, "pol", p.POLRound, "peer", peerID) + p.BlockID.PartsHeader, "pol", p.POLRound, "peer", peerID) case *BlockPartMessage: cs.Logger.Info("Replay: BlockPart", "height", msg.Height, "round", msg.Round, "peer", peerID) case *VoteMessage: diff --git a/consensus/replay_test.go b/consensus/replay_test.go index d6691103e..70c4ba332 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -575,7 +575,7 @@ func readPieceFromWAL(msg *TimedWALMessage) interface{} { case msgInfo: switch msg := m.Msg.(type) { case *ProposalMessage: - return &msg.Proposal.BlockPartsHeader + return &msg.Proposal.BlockID.PartsHeader case *BlockPartMessage: return msg.Part case *VoteMessage: diff --git a/consensus/state.go b/consensus/state.go index 3048ee3dd..5b1448983 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -901,9 +901,10 @@ func (cs *ConsensusState) defaultDecideProposal(height int64, round int) { } // Make proposal - polRound, polBlockID := cs.Votes.POLInfo() - proposal := types.NewProposal(height, round, blockParts.Header(), polRound, polBlockID) + propBlockId := types.BlockID{block.Hash(), blockParts.Header()} + proposal := types.NewProposal(height, round, cs.ValidRound, propBlockId) if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal); err == nil { + // send proposal and block parts on internal msg queue cs.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, ""}) for i := 0; i < blockParts.Total(); i++ { @@ -1423,7 +1424,7 @@ func (cs *ConsensusState) defaultSetProposal(proposal *types.Proposal) error { // This happens if we're already in cstypes.RoundStepCommit or if there is a valid block in the current round. // TODO: We can check if Proposal is for a different block as this is a sign of misbehavior! if cs.ProposalBlockParts == nil { - cs.ProposalBlockParts = types.NewPartSetFromHeader(proposal.BlockPartsHeader) + cs.ProposalBlockParts = types.NewPartSetFromHeader(proposal.BlockID.PartsHeader) } cs.Logger.Info("Received proposal", "proposal", proposal) return nil diff --git a/consensus/state_test.go b/consensus/state_test.go index 87c8b285a..9bf4fada5 100644 --- a/consensus/state_test.go +++ b/consensus/state_test.go @@ -197,7 +197,9 @@ func TestStateBadProposal(t *testing.T) { stateHash[0] = byte((stateHash[0] + 1) % 255) propBlock.AppHash = stateHash propBlockParts := propBlock.MakePartSet(partSize) - proposal := types.NewProposal(vs2.Height, round, propBlockParts.Header(), -1, types.BlockID{}) + proposal := types.NewProposal( + vs2.Height, round, -1, + types.BlockID{propBlock.Hash(), propBlockParts.Header()}) if err := vs2.SignProposal(config.ChainID(), proposal); err != nil { t.Fatal("failed to sign bad proposal", err) } @@ -811,6 +813,7 @@ func TestStateLockPOLSafety2(t *testing.T) { _, propBlock0 := decideProposal(cs1, vss[0], height, round) propBlockHash0 := propBlock0.Hash() propBlockParts0 := propBlock0.MakePartSet(partSize) + propBlockID0 := types.BlockID{propBlockHash0, propBlockParts0.Header()} // the others sign a polka but we don't see it prevotes := signVotes(types.PrevoteType, propBlockHash0, propBlockParts0.Header(), vs2, vs3, vs4) @@ -819,7 +822,6 @@ func TestStateLockPOLSafety2(t *testing.T) { prop1, propBlock1 := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1) propBlockHash1 := propBlock1.Hash() propBlockParts1 := propBlock1.MakePartSet(partSize) - propBlockID1 := types.BlockID{propBlockHash1, propBlockParts1.Header()} incrementRound(vs2, vs3, vs4) @@ -854,7 +856,7 @@ func TestStateLockPOLSafety2(t *testing.T) { round = round + 1 // moving to the next round // in round 2 we see the polkad block from round 0 - newProp := types.NewProposal(height, round, propBlockParts0.Header(), 0, propBlockID1) + newProp := types.NewProposal(height, round, 0, propBlockID0) if err := vs3.SignProposal(config.ChainID(), newProp); err != nil { t.Fatal(err) } @@ -909,7 +911,7 @@ func TestProposeValidBlock(t *testing.T) { ensurePrevote(voteCh, height, round) validatePrevote(t, cs1, round, vss[0], propBlockHash) - // the others sign a polka but we don't see it + // the others sign a polka signAddVotes(cs1, types.PrevoteType, propBlockHash, propBlock.MakePartSet(partSize).Header(), vs2, vs3, vs4) ensurePrecommit(voteCh, height, round) @@ -964,6 +966,8 @@ func TestProposeValidBlock(t *testing.T) { rs = cs1.GetRoundState() assert.True(t, bytes.Equal(rs.ProposalBlock.Hash(), propBlockHash)) assert.True(t, bytes.Equal(rs.ProposalBlock.Hash(), rs.ValidBlock.Hash())) + assert.True(t, rs.Proposal.POLRound == rs.ValidRound) + assert.True(t, bytes.Equal(rs.Proposal.BlockID.Hash, rs.ValidBlock.Hash())) } // What we want: diff --git a/consensus/types/round_state_test.go b/consensus/types/round_state_test.go index a330981f6..6a1c4533a 100644 --- a/consensus/types/round_state_test.go +++ b/consensus/types/round_state_test.go @@ -63,11 +63,8 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) { // Random Proposal proposal := &types.Proposal{ Timestamp: tmtime.Now(), - BlockPartsHeader: types.PartSetHeader{ - Hash: cmn.RandBytes(20), - }, - POLBlockID: blockID, - Signature: sig, + BlockID: blockID, + Signature: sig, } // Random HeightVoteSet // TODO: hvs := diff --git a/docs/spec/reactors/consensus/consensus.md b/docs/spec/reactors/consensus/consensus.md index a1cf17bcb..0f1922303 100644 --- a/docs/spec/reactors/consensus/consensus.md +++ b/docs/spec/reactors/consensus/consensus.md @@ -47,25 +47,21 @@ type ProposalMessage struct { ### Proposal Proposal contains height and round for which this proposal is made, BlockID as a unique identifier -of proposed block, timestamp, and two fields (POLRound and POLBlockID) that are needed for -termination of the consensus. The message is signed by the validator private key. +of proposed block, timestamp, and POLRound (a so-called Proof-of-Lock (POL) round) that is needed for +termination of the consensus. If POLRound >= 0, then BlockID corresponds to the block that +is locked in POLRound. The message is signed by the validator private key. ```go type Proposal struct { Height int64 Round int - Timestamp Time - BlockID BlockID POLRound int - POLBlockID BlockID + BlockID BlockID + Timestamp Time Signature Signature } ``` -NOTE: In the current version of the Tendermint, the consensus value in proposal is represented with -PartSetHeader, and with BlockID in vote message. It should be aligned as suggested in this spec as -BlockID contains PartSetHeader. - ## VoteMessage VoteMessage is sent to vote for some block (or to inform others that a process does not vote in the diff --git a/privval/priv_validator_test.go b/privval/priv_validator_test.go index 90796ddfc..4f4eed97b 100644 --- a/privval/priv_validator_test.go +++ b/privval/priv_validator_test.go @@ -140,8 +140,8 @@ func TestSignProposal(t *testing.T) { require.Nil(t, err) privVal := GenFilePV(tempFile.Name()) - block1 := types.PartSetHeader{5, []byte{1, 2, 3}} - block2 := types.PartSetHeader{10, []byte{3, 2, 1}} + block1 := types.BlockID{[]byte{1, 2, 3}, types.PartSetHeader{5, []byte{1, 2, 3}}} + block2 := types.BlockID{[]byte{3, 2, 1}, types.PartSetHeader{10, []byte{3, 2, 1}}} height, round := int64(10), 1 // sign a proposal for first time @@ -179,7 +179,7 @@ func TestDifferByTimestamp(t *testing.T) { require.Nil(t, err) privVal := GenFilePV(tempFile.Name()) - block1 := types.PartSetHeader{5, []byte{1, 2, 3}} + block1 := types.BlockID{[]byte{1, 2, 3}, types.PartSetHeader{5, []byte{1, 2, 3}}} height, round := int64(10), 1 chainID := "mychainid" @@ -241,11 +241,11 @@ func newVote(addr types.Address, idx int, height int64, round int, typ byte, blo } } -func newProposal(height int64, round int, partsHeader types.PartSetHeader) *types.Proposal { +func newProposal(height int64, round int, blockID types.BlockID) *types.Proposal { return &types.Proposal{ - Height: height, - Round: round, - BlockPartsHeader: partsHeader, - Timestamp: tmtime.Now(), + Height: height, + Round: round, + BlockID: blockID, + Timestamp: tmtime.Now(), } } diff --git a/types/canonical.go b/types/canonical.go index 632dcb624..a4f6f214d 100644 --- a/types/canonical.go +++ b/types/canonical.go @@ -23,14 +23,13 @@ type CanonicalPartSetHeader struct { } type CanonicalProposal struct { - Type SignedMsgType // type alias for byte - Height int64 `binary:"fixed64"` - Round int64 `binary:"fixed64"` - POLRound int64 `binary:"fixed64"` - Timestamp time.Time - BlockPartsHeader CanonicalPartSetHeader - POLBlockID CanonicalBlockID - ChainID string + Type SignedMsgType // type alias for byte + Height int64 `binary:"fixed64"` + Round int64 `binary:"fixed64"` + POLRound int64 `binary:"fixed64"` + BlockID CanonicalBlockID + Timestamp time.Time + ChainID string } type CanonicalVote struct { @@ -71,14 +70,13 @@ func CanonicalizePartSetHeader(psh PartSetHeader) CanonicalPartSetHeader { func CanonicalizeProposal(chainID string, proposal *Proposal) CanonicalProposal { return CanonicalProposal{ - Type: ProposalType, - Height: proposal.Height, - Round: int64(proposal.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) - POLRound: int64(proposal.POLRound), - Timestamp: proposal.Timestamp, - BlockPartsHeader: CanonicalizePartSetHeader(proposal.BlockPartsHeader), - POLBlockID: CanonicalizeBlockID(proposal.POLBlockID), - ChainID: chainID, + Type: ProposalType, + Height: proposal.Height, + Round: int64(proposal.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) + POLRound: int64(proposal.POLRound), + BlockID: CanonicalizeBlockID(proposal.BlockID), + Timestamp: proposal.Timestamp, + ChainID: chainID, } } diff --git a/types/proposal.go b/types/proposal.go index fa82fdbb5..09cfd1967 100644 --- a/types/proposal.go +++ b/types/proposal.go @@ -15,43 +15,41 @@ var ( ) // Proposal defines a block proposal for the consensus. -// It refers to the block only by its PartSetHeader. +// It refers to the block by BlockID field. // It must be signed by the correct proposer for the given Height/Round // to be considered valid. It may depend on votes from a previous round, -// a so-called Proof-of-Lock (POL) round, as noted in the POLRound and POLBlockID. +// a so-called Proof-of-Lock (POL) round, as noted in the POLRound. +// If POLRound >= 0, then BlockID corresponds to the block that is locked in POLRound. type Proposal struct { - Type SignedMsgType - Height int64 `json:"height"` - Round int `json:"round"` - POLRound int `json:"pol_round"` // -1 if null. - Timestamp time.Time `json:"timestamp"` - BlockPartsHeader PartSetHeader `json:"block_parts_header"` - POLBlockID BlockID `json:"pol_block_id"` // zero if null. - Signature []byte `json:"signature"` + Type SignedMsgType + Height int64 `json:"height"` + Round int `json:"round"` + POLRound int `json:"pol_round"` // -1 if null. + BlockID BlockID `json:"block_id"` + Timestamp time.Time `json:"timestamp"` + Signature []byte `json:"signature"` } // NewProposal returns a new Proposal. // If there is no POLRound, polRound should be -1. -func NewProposal(height int64, round int, blockPartsHeader PartSetHeader, polRound int, polBlockID BlockID) *Proposal { +func NewProposal(height int64, round int, polRound int, blockID BlockID) *Proposal { return &Proposal{ - Type: ProposalType, - Height: height, - Round: round, - POLRound: polRound, - Timestamp: tmtime.Now(), - BlockPartsHeader: blockPartsHeader, - POLBlockID: polBlockID, + Type: ProposalType, + Height: height, + Round: round, + BlockID: blockID, + POLRound: polRound, + Timestamp: tmtime.Now(), } } // String returns a string representation of the Proposal. func (p *Proposal) String() string { - return fmt.Sprintf("Proposal{%v/%v %v (%v,%v) %X @ %s}", + return fmt.Sprintf("Proposal{%v/%v (%v, %v) %X @ %s}", p.Height, p.Round, - p.BlockPartsHeader, + p.BlockID, p.POLRound, - p.POLBlockID, cmn.Fingerprint(p.Signature), CanonicalTime(p.Timestamp)) } diff --git a/types/proposal_test.go b/types/proposal_test.go index 8ae1f3e5a..9738db2d2 100644 --- a/types/proposal_test.go +++ b/types/proposal_test.go @@ -15,11 +15,11 @@ func init() { panic(err) } testProposal = &Proposal{ - Height: 12345, - Round: 23456, - BlockPartsHeader: PartSetHeader{111, []byte("blockparts")}, - POLRound: -1, - Timestamp: stamp, + Height: 12345, + Round: 23456, + BlockID: BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}}, + POLRound: -1, + Timestamp: stamp, } } @@ -34,7 +34,7 @@ func TestProposalSignable(t *testing.T) { func TestProposalString(t *testing.T) { str := testProposal.String() - expected := `Proposal{12345/23456 111:626C6F636B70 (-1,:0:000000000000) 000000000000 @ 2018-02-11T07:09:22.765Z}` + expected := `Proposal{12345/23456 (010203:111:626C6F636B70, -1) 000000000000 @ 2018-02-11T07:09:22.765Z}` if str != expected { t.Errorf("Got unexpected string for Proposal. Expected:\n%v\nGot:\n%v", expected, str) } @@ -44,7 +44,9 @@ func TestProposalVerifySignature(t *testing.T) { privVal := NewMockPV() pubKey := privVal.GetPubKey() - prop := NewProposal(4, 2, PartSetHeader{777, []byte("proper")}, 2, BlockID{}) + prop := NewProposal( + 4, 2, 2, + BlockID{[]byte{1, 2, 3}, PartSetHeader{777, []byte("proper")}}) signBytes := prop.SignBytes("test_chain_id") // sign it From a83c268d7f1e33249c4acff514eef5901efb66e0 Mon Sep 17 00:00:00 2001 From: Zarko Milosevic Date: Wed, 31 Oct 2018 15:59:01 +0100 Subject: [PATCH 25/35] Fix spec (#2736) --- consensus/reactor.go | 4 +++- .../reactors/consensus/consensus-reactor.md | 9 ++++++--- docs/spec/reactors/consensus/consensus.md | 19 +++++++++++-------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/consensus/reactor.go b/consensus/reactor.go index e8c7adc7f..bf6f7ba77 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -1393,7 +1393,9 @@ func (m *NewRoundStepMessage) String() string { //------------------------------------- -// CommitStepMessage is sent when a block is committed. +// NewValidBlockMessage is sent when a validator observes a valid block B in some round r, +//i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. +// In case the block is also committed, then IsCommit flag is set to true. type NewValidBlockMessage struct { Height int64 Round int diff --git a/docs/spec/reactors/consensus/consensus-reactor.md b/docs/spec/reactors/consensus/consensus-reactor.md index 5ba03322d..23275b122 100644 --- a/docs/spec/reactors/consensus/consensus-reactor.md +++ b/docs/spec/reactors/consensus/consensus-reactor.md @@ -133,9 +133,12 @@ handleMessage(msg): ``` handleMessage(msg): - if prs.Height == msg.Height && prs.Round == msg.Round then - prs.ProposalBlockPartsHeader = msg.BlockPartsHeader - prs.ProposalBlockParts = msg.BlockParts + if prs.Height != msg.Height then return + + if prs.Round != msg.Round && !msg.IsCommit then return + + prs.ProposalBlockPartsHeader = msg.BlockPartsHeader + prs.ProposalBlockParts = msg.BlockParts ``` ### HasVoteMessage handler diff --git a/docs/spec/reactors/consensus/consensus.md b/docs/spec/reactors/consensus/consensus.md index 0f1922303..e5d1f4cc3 100644 --- a/docs/spec/reactors/consensus/consensus.md +++ b/docs/spec/reactors/consensus/consensus.md @@ -26,7 +26,7 @@ only to a subset of processes called peers. By the gossiping protocol, a validat all needed information (`ProposalMessage`, `VoteMessage` and `BlockPartMessage`) so they can reach agreement on some block, and also obtain the content of the chosen block (block parts). As part of the gossiping protocol, processes also send auxiliary messages that inform peers about the -executed steps of the core consensus algorithm (`NewRoundStepMessage` and `CommitStepMessage`), and +executed steps of the core consensus algorithm (`NewRoundStepMessage` and `NewValidBlockMessage`), and also messages that inform peers what votes the process has seen (`HasVoteMessage`, `VoteSetMaj23Message` and `VoteSetBitsMessage`). These messages are then used in the gossiping protocol to determine what messages a process should send to its peers. @@ -132,23 +132,26 @@ type NewRoundStepMessage struct { } ``` -## CommitStepMessage +## NewValidBlockMessage -CommitStepMessage is sent when an agreement on some block is reached. It contains height for which -agreement is reached, block parts header that describes the decided block and is used to obtain all +NewValidBlockMessage is sent when a validator observes a valid block B in some round r, +i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. +It contains height and round in which valid block is observed, block parts header that describes +the valid block and is used to obtain all block parts, and a bit array of the block parts a process currently has, so its peers can know what parts it is missing so they can send them. +In case the block is also committed, then IsCommit flag is set to true. ```go -type CommitStepMessage struct { +type NewValidBlockMessage struct { Height int64 - BlockID BlockID + Round int + BlockPartsHeader PartSetHeader BlockParts BitArray + IsCommit bool } ``` -TODO: We use BlockID instead of BlockPartsHeader (in current implementation) for symmetry. - ## ProposalPOLMessage ProposalPOLMessage is sent when a previous block is re-proposed. From 1660e30ffe077773014ab11b3745b8b4b6933c8f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 31 Oct 2018 08:02:13 -0700 Subject: [PATCH 26/35] Fix general merkle keypath to start w/ last op's key (#2733) * Fix general merkle keypath to start w/ last op's key * Update CHANGELOG_PENDING.md --- CHANGELOG_PENDING.md | 1 + crypto/merkle/proof.go | 9 +-- crypto/merkle/proof_test.go | 136 ++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 crypto/merkle/proof_test.go diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index f28b46089..2d970e407 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -109,6 +109,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [consensus] [\#1637](https://github.com/tendermint/tendermint/issues/1637) Limit the amount of evidence that can be included in a block - [consensus] [\#2646](https://github.com/tendermint/tendermint/issues/2646) Simplify Proposal message (align with spec) +- [crypto] [\#2733](https://github.com/tendermint/tendermint/pull/2733) Fix general merkle keypath to start w/ last op's key - [evidence] [\#2515](https://github.com/tendermint/tendermint/issues/2515) Fix db iter leak (@goolAdapter) - [libs/event] [\#2518](https://github.com/tendermint/tendermint/issues/2518) Fix event concurrency flaw (@goolAdapter) - [node] [\#2434](https://github.com/tendermint/tendermint/issues/2434) Make node respond to signal interrupts while sleeping for genesis time diff --git a/crypto/merkle/proof.go b/crypto/merkle/proof.go index 3059ed3b7..5705c96bd 100644 --- a/crypto/merkle/proof.go +++ b/crypto/merkle/proof.go @@ -43,10 +43,11 @@ func (poz ProofOperators) Verify(root []byte, keypath string, args [][]byte) (er for i, op := range poz { key := op.GetKey() if len(key) != 0 { - if !bytes.Equal(keys[0], key) { - return cmn.NewError("Key mismatch on operation #%d: expected %+v but %+v", i, []byte(keys[0]), []byte(key)) + lastKey := keys[len(keys)-1] + if !bytes.Equal(lastKey, key) { + return cmn.NewError("Key mismatch on operation #%d: expected %+v but got %+v", i, string(lastKey), string(key)) } - keys = keys[1:] + keys = keys[:len(keys)-1] } args, err = op.Run(args) if err != nil { @@ -54,7 +55,7 @@ func (poz ProofOperators) Verify(root []byte, keypath string, args [][]byte) (er } } if !bytes.Equal(root, args[0]) { - return cmn.NewError("Calculated root hash is invalid: expected %+v but %+v", root, args[0]) + return cmn.NewError("Calculated root hash is invalid: expected %+v but got %+v", root, args[0]) } if len(keys) != 0 { return cmn.NewError("Keypath not consumed all") diff --git a/crypto/merkle/proof_test.go b/crypto/merkle/proof_test.go new file mode 100644 index 000000000..cc208e9a1 --- /dev/null +++ b/crypto/merkle/proof_test.go @@ -0,0 +1,136 @@ +package merkle + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/tendermint/go-amino" + cmn "github.com/tendermint/tendermint/libs/common" +) + +const ProofOpDomino = "test:domino" + +// Expects given input, produces given output. +// Like the game dominos. +type DominoOp struct { + key string // unexported, may be empty + Input string + Output string +} + +func NewDominoOp(key, input, output string) DominoOp { + return DominoOp{ + key: key, + Input: input, + Output: output, + } +} + +func DominoOpDecoder(pop ProofOp) (ProofOperator, error) { + if pop.Type != ProofOpDomino { + panic("unexpected proof op type") + } + var op DominoOp // a bit strange as we'll discard this, but it works. + err := amino.UnmarshalBinaryLengthPrefixed(pop.Data, &op) + if err != nil { + return nil, cmn.ErrorWrap(err, "decoding ProofOp.Data into SimpleValueOp") + } + return NewDominoOp(string(pop.Key), op.Input, op.Output), nil +} + +func (dop DominoOp) ProofOp() ProofOp { + bz := amino.MustMarshalBinaryLengthPrefixed(dop) + return ProofOp{ + Type: ProofOpDomino, + Key: []byte(dop.key), + Data: bz, + } +} + +func (dop DominoOp) Run(input [][]byte) (output [][]byte, err error) { + if len(input) != 1 { + return nil, cmn.NewError("Expected input of length 1") + } + if string(input[0]) != dop.Input { + return nil, cmn.NewError("Expected input %v, got %v", + dop.Input, string(input[0])) + } + return [][]byte{[]byte(dop.Output)}, nil +} + +func (dop DominoOp) GetKey() []byte { + return []byte(dop.key) +} + +//---------------------------------------- + +func TestProofOperators(t *testing.T) { + var err error + + // ProofRuntime setup + // TODO test this somehow. + // prt := NewProofRuntime() + // prt.RegisterOpDecoder(ProofOpDomino, DominoOpDecoder) + + // ProofOperators setup + op1 := NewDominoOp("KEY1", "INPUT1", "INPUT2") + op2 := NewDominoOp("KEY2", "INPUT2", "INPUT3") + op3 := NewDominoOp("", "INPUT3", "INPUT4") + op4 := NewDominoOp("KEY4", "INPUT4", "OUTPUT4") + + // Good + popz := ProofOperators([]ProofOperator{op1, op2, op3, op4}) + err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.Nil(t, err) + err = popz.VerifyValue(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", bz("INPUT1")) + assert.Nil(t, err) + + // BAD INPUT + err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1_WRONG")}) + assert.NotNil(t, err) + err = popz.VerifyValue(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", bz("INPUT1_WRONG")) + assert.NotNil(t, err) + + // BAD KEY 1 + err = popz.Verify(bz("OUTPUT4"), "/KEY3/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) + + // BAD KEY 2 + err = popz.Verify(bz("OUTPUT4"), "KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) + + // BAD KEY 3 + err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1/", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) + + // BAD KEY 4 + err = popz.Verify(bz("OUTPUT4"), "//KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) + + // BAD OUTPUT 1 + err = popz.Verify(bz("OUTPUT4_WRONG"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) + + // BAD OUTPUT 2 + err = popz.Verify(bz(""), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) + + // BAD POPZ 1 + popz = []ProofOperator{op1, op2, op4} + err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) + + // BAD POPZ 2 + popz = []ProofOperator{op4, op3, op2, op1} + err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) + + // BAD POPZ 3 + popz = []ProofOperator{} + err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) +} + +func bz(s string) []byte { + return []byte(s) +} From a22c962e28053f9f51d71d3394e0c62bf551fb99 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 31 Oct 2018 12:42:05 -0400 Subject: [PATCH 27/35] TMHASH is 32 bytes. Closes #1990 (#2732) * tmhash is fully 32 bytes. closes #1990 * AddressSize * fix tests * fix max sizes --- crypto/crypto.go | 21 +++++++++++++------ crypto/ed25519/ed25519.go | 2 +- crypto/merkle/simple_map_test.go | 12 +++++------ crypto/tmhash/hash.go | 33 ++++++++++++++++++++++-------- crypto/tmhash/hash_test.go | 23 +++++++++++++++++++-- docs/spec/blockchain/blockchain.md | 2 +- docs/spec/blockchain/encoding.md | 7 +++---- docs/spec/blockchain/state.md | 4 ++-- p2p/key.go | 3 +-- state/validation.go | 4 ++-- types/block.go | 2 +- types/block_test.go | 17 +++++++-------- types/evidence.go | 2 +- types/validator.go | 8 ++++---- types/vote.go | 2 +- types/vote_test.go | 5 +++-- 16 files changed, 96 insertions(+), 51 deletions(-) diff --git a/crypto/crypto.go b/crypto/crypto.go index 09c12ff76..2462b0a98 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -1,21 +1,23 @@ package crypto import ( + "github.com/tendermint/tendermint/crypto/tmhash" cmn "github.com/tendermint/tendermint/libs/common" ) -type PrivKey interface { - Bytes() []byte - Sign(msg []byte) ([]byte, error) - PubKey() PubKey - Equals(PrivKey) bool -} +const ( + AddressSize = tmhash.TruncatedSize +) // An address is a []byte, but hex-encoded even in JSON. // []byte leaves us the option to change the address length. // Use an alias so Unmarshal methods (with ptr receivers) are available too. type Address = cmn.HexBytes +func AddressHash(bz []byte) Address { + return Address(tmhash.SumTruncated(bz)) +} + type PubKey interface { Address() Address Bytes() []byte @@ -23,6 +25,13 @@ type PubKey interface { Equals(PubKey) bool } +type PrivKey interface { + Bytes() []byte + Sign(msg []byte) ([]byte, error) + PubKey() PubKey + Equals(PrivKey) bool +} + type Symmetric interface { Keygen() []byte Encrypt(plaintext []byte, secret []byte) (ciphertext []byte) diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go index 61872d98d..e077cbda4 100644 --- a/crypto/ed25519/ed25519.go +++ b/crypto/ed25519/ed25519.go @@ -136,7 +136,7 @@ type PubKeyEd25519 [PubKeyEd25519Size]byte // Address is the SHA256-20 of the raw pubkey bytes. func (pubKey PubKeyEd25519) Address() crypto.Address { - return crypto.Address(tmhash.Sum(pubKey[:])) + return crypto.Address(tmhash.SumTruncated(pubKey[:])) } // Bytes marshals the PubKey using amino encoding. diff --git a/crypto/merkle/simple_map_test.go b/crypto/merkle/simple_map_test.go index bc095c003..7abde119d 100644 --- a/crypto/merkle/simple_map_test.go +++ b/crypto/merkle/simple_map_test.go @@ -13,14 +13,14 @@ func TestSimpleMap(t *testing.T) { values []string // each string gets converted to []byte in test want string }{ - {[]string{"key1"}, []string{"value1"}, "fa9bc106ffd932d919bee935ceb6cf2b3dd72d8f"}, - {[]string{"key1"}, []string{"value2"}, "e00e7dcfe54e9fafef5111e813a587f01ba9c3e8"}, + {[]string{"key1"}, []string{"value1"}, "321d150de16dceb51c72981b432b115045383259b1a550adf8dc80f927508967"}, + {[]string{"key1"}, []string{"value2"}, "2a9e4baf321eac99f6eecc3406603c14bc5e85bb7b80483cbfc75b3382d24a2f"}, // swap order with 2 keys - {[]string{"key1", "key2"}, []string{"value1", "value2"}, "eff12d1c703a1022ab509287c0f196130123d786"}, - {[]string{"key2", "key1"}, []string{"value2", "value1"}, "eff12d1c703a1022ab509287c0f196130123d786"}, + {[]string{"key1", "key2"}, []string{"value1", "value2"}, "c4d8913ab543ba26aa970646d4c99a150fd641298e3367cf68ca45fb45a49881"}, + {[]string{"key2", "key1"}, []string{"value2", "value1"}, "c4d8913ab543ba26aa970646d4c99a150fd641298e3367cf68ca45fb45a49881"}, // swap order with 3 keys - {[]string{"key1", "key2", "key3"}, []string{"value1", "value2", "value3"}, "b2c62a277c08dbd2ad73ca53cd1d6bfdf5830d26"}, - {[]string{"key1", "key3", "key2"}, []string{"value1", "value3", "value2"}, "b2c62a277c08dbd2ad73ca53cd1d6bfdf5830d26"}, + {[]string{"key1", "key2", "key3"}, []string{"value1", "value2", "value3"}, "b23cef00eda5af4548a213a43793f2752d8d9013b3f2b64bc0523a4791196268"}, + {[]string{"key1", "key3", "key2"}, []string{"value1", "value3", "value2"}, "b23cef00eda5af4548a213a43793f2752d8d9013b3f2b64bc0523a4791196268"}, } for i, tc := range tests { db := newSimpleMap() diff --git a/crypto/tmhash/hash.go b/crypto/tmhash/hash.go index 1b29d8680..f9b958242 100644 --- a/crypto/tmhash/hash.go +++ b/crypto/tmhash/hash.go @@ -6,10 +6,27 @@ import ( ) const ( - Size = 20 + Size = sha256.Size BlockSize = sha256.BlockSize ) +// New returns a new hash.Hash. +func New() hash.Hash { + return sha256.New() +} + +// Sum returns the SHA256 of the bz. +func Sum(bz []byte) []byte { + h := sha256.Sum256(bz) + return h[:] +} + +//------------------------------------------------------------- + +const ( + TruncatedSize = 20 +) + type sha256trunc struct { sha256 hash.Hash } @@ -19,7 +36,7 @@ func (h sha256trunc) Write(p []byte) (n int, err error) { } func (h sha256trunc) Sum(b []byte) []byte { shasum := h.sha256.Sum(b) - return shasum[:Size] + return shasum[:TruncatedSize] } func (h sha256trunc) Reset() { @@ -27,22 +44,22 @@ func (h sha256trunc) Reset() { } func (h sha256trunc) Size() int { - return Size + return TruncatedSize } func (h sha256trunc) BlockSize() int { return h.sha256.BlockSize() } -// New returns a new hash.Hash. -func New() hash.Hash { +// NewTruncated returns a new hash.Hash. +func NewTruncated() hash.Hash { return sha256trunc{ sha256: sha256.New(), } } -// Sum returns the first 20 bytes of SHA256 of the bz. -func Sum(bz []byte) []byte { +// SumTruncated returns the first 20 bytes of SHA256 of the bz. +func SumTruncated(bz []byte) []byte { hash := sha256.Sum256(bz) - return hash[:Size] + return hash[:TruncatedSize] } diff --git a/crypto/tmhash/hash_test.go b/crypto/tmhash/hash_test.go index 27938039a..89a779801 100644 --- a/crypto/tmhash/hash_test.go +++ b/crypto/tmhash/hash_test.go @@ -14,10 +14,29 @@ func TestHash(t *testing.T) { hasher.Write(testVector) bz := hasher.Sum(nil) + bz2 := tmhash.Sum(testVector) + hasher = sha256.New() hasher.Write(testVector) - bz2 := hasher.Sum(nil) - bz2 = bz2[:20] + bz3 := hasher.Sum(nil) assert.Equal(t, bz, bz2) + assert.Equal(t, bz, bz3) +} + +func TestHashTruncated(t *testing.T) { + testVector := []byte("abc") + hasher := tmhash.NewTruncated() + hasher.Write(testVector) + bz := hasher.Sum(nil) + + bz2 := tmhash.SumTruncated(testVector) + + hasher = sha256.New() + hasher.Write(testVector) + bz3 := hasher.Sum(nil) + bz3 = bz3[:tmhash.TruncatedSize] + + assert.Equal(t, bz, bz2) + assert.Equal(t, bz, bz3) } diff --git a/docs/spec/blockchain/blockchain.md b/docs/spec/blockchain/blockchain.md index 061685378..d96a3c7b8 100644 --- a/docs/spec/blockchain/blockchain.md +++ b/docs/spec/blockchain/blockchain.md @@ -344,7 +344,7 @@ next validator sets Merkle root. ### ConsensusParamsHash ```go -block.ConsensusParamsHash == tmhash(amino(state.ConsensusParams)) +block.ConsensusParamsHash == TMHASH(amino(state.ConsensusParams)) ``` Hash of the amino-encoded consensus parameters. diff --git a/docs/spec/blockchain/encoding.md b/docs/spec/blockchain/encoding.md index 2f9fcdca1..f5120cdd4 100644 --- a/docs/spec/blockchain/encoding.md +++ b/docs/spec/blockchain/encoding.md @@ -176,13 +176,12 @@ greater, for example: h0 h1 h3 h4 h0 h1 h2 h3 h4 h5 ``` -Tendermint always uses the `TMHASH` hash function, which is the first 20-bytes -of the SHA256: +Tendermint always uses the `TMHASH` hash function, which is equivalent to +SHA256: ``` func TMHASH(bz []byte) []byte { - shasum := SHA256(bz) - return shasum[:20] + return SHA256(bz) } ``` diff --git a/docs/spec/blockchain/state.md b/docs/spec/blockchain/state.md index a0badd718..502f9d696 100644 --- a/docs/spec/blockchain/state.md +++ b/docs/spec/blockchain/state.md @@ -56,8 +56,8 @@ type Validator struct { } ``` -When hashing the Validator struct, the pubkey is not hashed, -because the address is already the hash of the pubkey. +When hashing the Validator struct, the address is not included, +because it is redundant with the pubkey. The `state.Validators`, `state.LastValidators`, and `state.NextValidators`, must always by sorted by validator address, so that there is a canonical order for computing the SimpleMerkleRoot. diff --git a/p2p/key.go b/p2p/key.go index 3f38b48a9..fc64f27bb 100644 --- a/p2p/key.go +++ b/p2p/key.go @@ -8,7 +8,6 @@ import ( crypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" - "github.com/tendermint/tendermint/crypto/tmhash" cmn "github.com/tendermint/tendermint/libs/common" ) @@ -17,7 +16,7 @@ type ID string // IDByteLength is the length of a crypto.Address. Currently only 20. // TODO: support other length addresses ? -const IDByteLength = tmhash.Size +const IDByteLength = crypto.AddressSize //------------------------------------------------------------------------------ // Persistent peer ID diff --git a/state/validation.go b/state/validation.go index a12919847..345224843 100644 --- a/state/validation.go +++ b/state/validation.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/tendermint/tendermint/crypto/tmhash" + "github.com/tendermint/tendermint/crypto" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/types" ) @@ -158,7 +158,7 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error { // NOTE: We can't actually verify it's the right proposer because we dont // know what round the block was first proposed. So just check that it's // a legit address and a known validator. - if len(block.ProposerAddress) != tmhash.Size || + if len(block.ProposerAddress) != crypto.AddressSize || !state.Validators.HasAddress(block.ProposerAddress) { return fmt.Errorf( "Block.Header.ProposerAddress, %X, is not a validator", diff --git a/types/block.go b/types/block.go index 477e39997..46ad73a71 100644 --- a/types/block.go +++ b/types/block.go @@ -15,7 +15,7 @@ import ( const ( // MaxHeaderBytes is a maximum header size (including amino overhead). - MaxHeaderBytes int64 = 533 + MaxHeaderBytes int64 = 653 // MaxAminoOverheadForBlock - maximum amino overhead to encode a block (up to // MaxBlockSizeBytes in size) not including it's parts except Data. diff --git a/types/block_test.go b/types/block_test.go index 28e73f661..46881a099 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/tmhash" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/version" @@ -116,7 +117,7 @@ func TestBlockMakePartSetWithEvidence(t *testing.T) { partSet := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(1024) assert.NotNil(t, partSet) - assert.Equal(t, 2, partSet.Total()) + assert.Equal(t, 3, partSet.Total()) } func TestBlockHashesTo(t *testing.T) { @@ -262,7 +263,7 @@ func TestMaxHeaderBytes(t *testing.T) { AppHash: tmhash.Sum([]byte("app_hash")), LastResultsHash: tmhash.Sum([]byte("last_results_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")), - ProposerAddress: tmhash.Sum([]byte("proposer_address")), + ProposerAddress: crypto.AddressHash([]byte("proposer_address")), } bz, err := cdc.MarshalBinaryLengthPrefixed(h) @@ -292,9 +293,9 @@ func TestBlockMaxDataBytes(t *testing.T) { }{ 0: {-10, 1, 0, true, 0}, 1: {10, 1, 0, true, 0}, - 2: {742, 1, 0, true, 0}, - 3: {743, 1, 0, false, 0}, - 4: {744, 1, 0, false, 1}, + 2: {886, 1, 0, true, 0}, + 3: {887, 1, 0, false, 0}, + 4: {888, 1, 0, false, 1}, } for i, tc := range testCases { @@ -320,9 +321,9 @@ func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) { }{ 0: {-10, 1, true, 0}, 1: {10, 1, true, 0}, - 2: {824, 1, true, 0}, - 3: {825, 1, false, 0}, - 4: {826, 1, false, 1}, + 2: {984, 1, true, 0}, + 3: {985, 1, false, 0}, + 4: {986, 1, false, 1}, } for i, tc := range testCases { diff --git a/types/evidence.go b/types/evidence.go index 7a808d57b..d1e15c819 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -14,7 +14,7 @@ import ( const ( // MaxEvidenceBytes is a maximum size of any evidence (including amino overhead). - MaxEvidenceBytes int64 = 436 + MaxEvidenceBytes int64 = 484 ) // ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid. diff --git a/types/validator.go b/types/validator.go index af3471848..4bfd78a6d 100644 --- a/types/validator.go +++ b/types/validator.go @@ -77,15 +77,15 @@ func (v *Validator) Hash() []byte { } // Bytes computes the unique encoding of a validator with a given voting power. -// These are the bytes that gets hashed in consensus. It excludes pubkey -// as its redundant with the address. This also excludes accum which changes +// These are the bytes that gets hashed in consensus. It excludes address +// as its redundant with the pubkey. This also excludes accum which changes // every round. func (v *Validator) Bytes() []byte { return cdcEncode((struct { - Address Address + PubKey crypto.PubKey VotingPower int64 }{ - v.Address, + v.PubKey, v.VotingPower, })) } diff --git a/types/vote.go b/types/vote.go index 826330d5c..1d7e9cf6f 100644 --- a/types/vote.go +++ b/types/vote.go @@ -12,7 +12,7 @@ import ( const ( // MaxVoteBytes is a maximum vote size (including amino overhead). - MaxVoteBytes int64 = 199 + MaxVoteBytes int64 = 223 ) var ( diff --git a/types/vote_test.go b/types/vote_test.go index 572735858..cda54f898 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/tmhash" ) @@ -37,7 +38,7 @@ func exampleVote(t byte) *Vote { Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")), }, }, - ValidatorAddress: tmhash.Sum([]byte("validator_address")), + ValidatorAddress: crypto.AddressHash([]byte("validator_address")), ValidatorIndex: 56789, } } @@ -211,7 +212,7 @@ func TestMaxVoteBytes(t *testing.T) { timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) vote := &Vote{ - ValidatorAddress: tmhash.Sum([]byte("validator_address")), + ValidatorAddress: crypto.AddressHash([]byte("validator_address")), ValidatorIndex: math.MaxInt64, Height: math.MaxInt64, Round: math.MaxInt64, From fb91ef7462b421349a56c32733724d920fce3ad4 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 1 Nov 2018 07:07:18 +0100 Subject: [PATCH 28/35] validate reactor messages (#2711) * validate reactor messages Refs #2683 * validate blockchain messages Refs #2683 * validate evidence messages Refs #2683 * todo * check ProposalPOL and signature sizes * add a changelog entry * check addr is valid when we add it to the addrbook * validate incoming netAddr (not just nil check!) * fixes after Bucky's review * check timestamps * beef up block#ValidateBasic * move some checks into bcBlockResponseMessage * update Gopkg.lock Fix ``` grouped write of manifest, lock and vendor: failed to export github.com/tendermint/go-amino: fatal: failed to unpack tree object 6dcc6ddc143e116455c94b25c1004c99e0d0ca12 ``` by running `dep ensure -update` * bump year since now we check it * generate test/p2p/data on the fly using tendermint testnet * allow sync chains older than 1 year * use full path when creating a testnet * move testnet gen to test/docker/Dockerfile * relax LastCommitRound check Refs #2737 * fix conflicts after merge * add small comment * some ValidateBasic updates * fixes * AppHash length is not fixed --- CHANGELOG_PENDING.md | 4 + blockchain/reactor.go | 53 +++++- config/toml.go | 2 +- consensus/common_test.go | 2 - consensus/mempool_test.go | 1 - consensus/reactor.go | 161 ++++++++++++++++-- consensus/replay.go | 8 +- consensus/types/round_state.go | 7 + crypto/crypto.go | 1 + evidence/reactor.go | 23 ++- p2p/pex/addrbook.go | 4 + p2p/pex/errors.go | 8 + p2p/pex/pex_reactor.go | 28 ++- state/validation.go | 50 +++--- test/docker/Dockerfile | 11 +- test/p2p/README.md | 9 +- test/p2p/data/mach1/core/config/genesis.json | 39 ----- test/p2p/data/mach1/core/config/node_key.json | 6 - .../mach1/core/config/priv_validator.json | 14 -- test/p2p/data/mach2/core/config/genesis.json | 39 ----- test/p2p/data/mach2/core/config/node_key.json | 6 - .../mach2/core/config/priv_validator.json | 14 -- test/p2p/data/mach3/core/config/genesis.json | 39 ----- test/p2p/data/mach3/core/config/node_key.json | 6 - .../mach3/core/config/priv_validator.json | 14 -- test/p2p/data/mach4/core/config/genesis.json | 39 ----- test/p2p/data/mach4/core/config/node_key.json | 6 - .../mach4/core/config/priv_validator.json | 14 -- test/p2p/ip_plus_id.sh | 2 +- test/p2p/peer.sh | 6 +- test/p2p/pex/test_addrbook.sh | 6 +- types/block.go | 117 ++++++++++--- types/block_test.go | 6 +- types/evidence.go | 21 +++ types/heartbeat.go | 31 ++++ types/part_set.go | 26 ++- types/proposal.go | 29 ++++ types/signable.go | 12 ++ types/signed_msg_type.go | 9 +- types/validation.go | 40 +++++ types/vote.go | 38 ++++- 41 files changed, 614 insertions(+), 337 deletions(-) delete mode 100644 test/p2p/data/mach1/core/config/genesis.json delete mode 100644 test/p2p/data/mach1/core/config/node_key.json delete mode 100644 test/p2p/data/mach1/core/config/priv_validator.json delete mode 100644 test/p2p/data/mach2/core/config/genesis.json delete mode 100644 test/p2p/data/mach2/core/config/node_key.json delete mode 100644 test/p2p/data/mach2/core/config/priv_validator.json delete mode 100644 test/p2p/data/mach3/core/config/genesis.json delete mode 100644 test/p2p/data/mach3/core/config/node_key.json delete mode 100644 test/p2p/data/mach3/core/config/priv_validator.json delete mode 100644 test/p2p/data/mach4/core/config/genesis.json delete mode 100644 test/p2p/data/mach4/core/config/node_key.json delete mode 100644 test/p2p/data/mach4/core/config/priv_validator.json create mode 100644 types/validation.go diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 2d970e407..cad2f444a 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -92,6 +92,10 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi github.com/tendermint/crypto - [tools] [\#2238](https://github.com/tendermint/tendermint/issues/2238) Binary dependencies are now locked to a specific git commit - [libs/log] [\#2706](https://github.com/tendermint/tendermint/issues/2706) Add year to log format +- [consensus] [\#2683] validate all incoming messages +- [evidence] [\#2683] validate all incoming messages +- [blockchain] [\#2683] validate all incoming messages +- [p2p/pex] [\#2683] validate pexAddrsMessage addresses ### BUG FIXES: - [autofile] [\#2428](https://github.com/tendermint/tendermint/issues/2428) Group.RotateFile need call Flush() before rename (@goolAdapter) diff --git a/blockchain/reactor.go b/blockchain/reactor.go index fc1b1f4d3..59318dcc5 100644 --- a/blockchain/reactor.go +++ b/blockchain/reactor.go @@ -1,6 +1,7 @@ package blockchain import ( + "errors" "fmt" "reflect" "time" @@ -180,6 +181,12 @@ func (bcR *BlockchainReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) return } + if err = msg.ValidateBasic(); err != nil { + bcR.Logger.Error("Peer sent us invalid msg", "peer", src, "msg", msg, "err", err) + bcR.Switch.StopPeerForError(src, err) + return + } + bcR.Logger.Debug("Receive", "src", src, "chID", chID, "msg", msg) switch msg := msg.(type) { @@ -188,7 +195,6 @@ func (bcR *BlockchainReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) // Unfortunately not queued since the queue is full. } case *bcBlockResponseMessage: - // Got a block. bcR.pool.AddBlock(src.ID(), msg.Block, len(msgBytes)) case *bcStatusRequestMessage: // Send peer our state. @@ -352,7 +358,9 @@ func (bcR *BlockchainReactor) BroadcastStatusRequest() error { // Messages // BlockchainMessage is a generic message for this reactor. -type BlockchainMessage interface{} +type BlockchainMessage interface { + ValidateBasic() error +} func RegisterBlockchainMessages(cdc *amino.Codec) { cdc.RegisterInterface((*BlockchainMessage)(nil), nil) @@ -377,6 +385,14 @@ type bcBlockRequestMessage struct { Height int64 } +// ValidateBasic performs basic validation. +func (m *bcBlockRequestMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + return nil +} + func (m *bcBlockRequestMessage) String() string { return fmt.Sprintf("[bcBlockRequestMessage %v]", m.Height) } @@ -385,6 +401,14 @@ type bcNoBlockResponseMessage struct { Height int64 } +// ValidateBasic performs basic validation. +func (m *bcNoBlockResponseMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + return nil +} + func (brm *bcNoBlockResponseMessage) String() string { return fmt.Sprintf("[bcNoBlockResponseMessage %d]", brm.Height) } @@ -395,6 +419,15 @@ type bcBlockResponseMessage struct { Block *types.Block } +// ValidateBasic performs basic validation. +func (m *bcBlockResponseMessage) ValidateBasic() error { + if err := m.Block.ValidateBasic(); err != nil { + return err + } + + return nil +} + func (m *bcBlockResponseMessage) String() string { return fmt.Sprintf("[bcBlockResponseMessage %v]", m.Block.Height) } @@ -405,6 +438,14 @@ type bcStatusRequestMessage struct { Height int64 } +// ValidateBasic performs basic validation. +func (m *bcStatusRequestMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + return nil +} + func (m *bcStatusRequestMessage) String() string { return fmt.Sprintf("[bcStatusRequestMessage %v]", m.Height) } @@ -415,6 +456,14 @@ type bcStatusResponseMessage struct { Height int64 } +// ValidateBasic performs basic validation. +func (m *bcStatusResponseMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + return nil +} + func (m *bcStatusResponseMessage) String() string { return fmt.Sprintf("[bcStatusResponseMessage %v]", m.Height) } diff --git a/config/toml.go b/config/toml.go index 62e5fa978..d73b9c81d 100644 --- a/config/toml.go +++ b/config/toml.go @@ -342,7 +342,7 @@ func ResetTestRoot(testName string) *Config { } var testGenesis = `{ - "genesis_time": "2017-10-10T08:20:13.695936996Z", + "genesis_time": "2018-10-10T08:20:13.695936996Z", "chain_id": "tendermint_test", "validators": [ { diff --git a/consensus/common_test.go b/consensus/common_test.go index ae8bb6bfe..4f48f4424 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -615,8 +615,6 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G func randGenesisState(numValidators int, randPower bool, minPower int64) (sm.State, []types.PrivValidator) { genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower) s0, _ := sm.MakeGenesisState(genDoc) - db := dbm.NewMemDB() // remove this ? - sm.SaveState(db, s0) return s0, privValidators } diff --git a/consensus/mempool_test.go b/consensus/mempool_test.go index ed97ae681..3dc1cd5ff 100644 --- a/consensus/mempool_test.go +++ b/consensus/mempool_test.go @@ -10,7 +10,6 @@ import ( "github.com/tendermint/tendermint/abci/example/code" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/types" ) diff --git a/consensus/reactor.go b/consensus/reactor.go index bf6f7ba77..fc41e5734 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -8,8 +8,7 @@ import ( "github.com/pkg/errors" - "github.com/tendermint/go-amino" - + amino "github.com/tendermint/go-amino" cstypes "github.com/tendermint/tendermint/consensus/types" cmn "github.com/tendermint/tendermint/libs/common" tmevents "github.com/tendermint/tendermint/libs/events" @@ -205,6 +204,13 @@ func (conR *ConsensusReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) conR.Switch.StopPeerForError(src, err) return } + + if err = msg.ValidateBasic(); err != nil { + conR.Logger.Error("Peer sent us invalid msg", "peer", src, "msg", msg, "err", err) + conR.Switch.StopPeerForError(src, err) + return + } + conR.Logger.Debug("Receive", "src", src, "chId", chID, "msg", msg) // Get peer states @@ -242,8 +248,7 @@ func (conR *ConsensusReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) case types.PrecommitType: ourVotes = votes.Precommits(msg.Round).BitArrayByBlockID(msg.BlockID) default: - conR.Logger.Error("Bad VoteSetBitsMessage field Type") - return + panic("Bad VoteSetBitsMessage field Type. Forgot to add a check in ValidateBasic?") } src.TrySend(VoteSetBitsChannel, cdc.MustMarshalBinaryBare(&VoteSetBitsMessage{ Height: msg.Height, @@ -322,8 +327,7 @@ func (conR *ConsensusReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) case types.PrecommitType: ourVotes = votes.Precommits(msg.Round).BitArrayByBlockID(msg.BlockID) default: - conR.Logger.Error("Bad VoteSetBitsMessage field Type") - return + panic("Bad VoteSetBitsMessage field Type. Forgot to add a check in ValidateBasic?") } ps.ApplyVoteSetBitsMessage(msg, ourVotes) } else { @@ -440,9 +444,9 @@ func (conR *ConsensusReactor) broadcastHasVoteMessage(vote *types.Vote) { func makeRoundStepMessage(rs *cstypes.RoundState) (nrsMsg *NewRoundStepMessage) { nrsMsg = &NewRoundStepMessage{ - Height: rs.Height, - Round: rs.Round, - Step: rs.Step, + Height: rs.Height, + Round: rs.Round, + Step: rs.Step, SecondsSinceStartTime: int(time.Since(rs.StartTime).Seconds()), LastCommitRound: rs.LastCommit.Round(), } @@ -1349,7 +1353,9 @@ func (ps *PeerState) StringIndented(indent string) string { // Messages // ConsensusMessage is a message that can be sent and received on the ConsensusReactor -type ConsensusMessage interface{} +type ConsensusMessage interface { + ValidateBasic() error +} func RegisterConsensusMessages(cdc *amino.Codec) { cdc.RegisterInterface((*ConsensusMessage)(nil), nil) @@ -1385,6 +1391,27 @@ type NewRoundStepMessage struct { LastCommitRound int } +// ValidateBasic performs basic validation. +func (m *NewRoundStepMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + if m.Round < 0 { + return errors.New("Negative Round") + } + if !m.Step.IsValid() { + return errors.New("Invalid Step") + } + + // NOTE: SecondsSinceStartTime may be negative + + if (m.Height == 1 && m.LastCommitRound != -1) || + (m.Height > 1 && m.LastCommitRound < -1) { // TODO: #2737 LastCommitRound should always be >= 0 for heights > 1 + return errors.New("Invalid LastCommitRound (for 1st block: -1, for others: >= 0)") + } + return nil +} + // String returns a string representation. func (m *NewRoundStepMessage) String() string { return fmt.Sprintf("[NewRoundStep H:%v R:%v S:%v LCR:%v]", @@ -1404,6 +1431,25 @@ type NewValidBlockMessage struct { IsCommit bool } +// ValidateBasic performs basic validation. +func (m *NewValidBlockMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + if m.Round < 0 { + return errors.New("Negative Round") + } + if err := m.BlockPartsHeader.ValidateBasic(); err != nil { + return fmt.Errorf("Wrong BlockPartsHeader: %v", err) + } + if m.BlockParts.Size() != m.BlockPartsHeader.Total { + return fmt.Errorf("BlockParts bit array size %d not equal to BlockPartsHeader.Total %d", + m.BlockParts.Size(), + m.BlockPartsHeader.Total) + } + return nil +} + // String returns a string representation. func (m *NewValidBlockMessage) String() string { return fmt.Sprintf("[ValidBlockMessage H:%v R:%v BP:%v BA:%v IsCommit:%v]", @@ -1417,6 +1463,11 @@ type ProposalMessage struct { Proposal *types.Proposal } +// ValidateBasic performs basic validation. +func (m *ProposalMessage) ValidateBasic() error { + return m.Proposal.ValidateBasic() +} + // String returns a string representation. func (m *ProposalMessage) String() string { return fmt.Sprintf("[Proposal %v]", m.Proposal) @@ -1431,6 +1482,20 @@ type ProposalPOLMessage struct { ProposalPOL *cmn.BitArray } +// ValidateBasic performs basic validation. +func (m *ProposalPOLMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + if m.ProposalPOLRound < 0 { + return errors.New("Negative ProposalPOLRound") + } + if m.ProposalPOL.Size() == 0 { + return errors.New("Empty ProposalPOL bit array") + } + return nil +} + // String returns a string representation. func (m *ProposalPOLMessage) String() string { return fmt.Sprintf("[ProposalPOL H:%v POLR:%v POL:%v]", m.Height, m.ProposalPOLRound, m.ProposalPOL) @@ -1445,6 +1510,20 @@ type BlockPartMessage struct { Part *types.Part } +// ValidateBasic performs basic validation. +func (m *BlockPartMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + if m.Round < 0 { + return errors.New("Negative Round") + } + if err := m.Part.ValidateBasic(); err != nil { + return fmt.Errorf("Wrong Part: %v", err) + } + return nil +} + // String returns a string representation. func (m *BlockPartMessage) String() string { return fmt.Sprintf("[BlockPart H:%v R:%v P:%v]", m.Height, m.Round, m.Part) @@ -1457,6 +1536,11 @@ type VoteMessage struct { Vote *types.Vote } +// ValidateBasic performs basic validation. +func (m *VoteMessage) ValidateBasic() error { + return m.Vote.ValidateBasic() +} + // String returns a string representation. func (m *VoteMessage) String() string { return fmt.Sprintf("[Vote %v]", m.Vote) @@ -1472,6 +1556,23 @@ type HasVoteMessage struct { Index int } +// ValidateBasic performs basic validation. +func (m *HasVoteMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + if m.Round < 0 { + return errors.New("Negative Round") + } + if !types.IsVoteTypeValid(m.Type) { + return errors.New("Invalid Type") + } + if m.Index < 0 { + return errors.New("Negative Index") + } + return nil +} + // String returns a string representation. func (m *HasVoteMessage) String() string { return fmt.Sprintf("[HasVote VI:%v V:{%v/%02d/%v}]", m.Index, m.Height, m.Round, m.Type) @@ -1487,6 +1588,23 @@ type VoteSetMaj23Message struct { BlockID types.BlockID } +// ValidateBasic performs basic validation. +func (m *VoteSetMaj23Message) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + if m.Round < 0 { + return errors.New("Negative Round") + } + if !types.IsVoteTypeValid(m.Type) { + return errors.New("Invalid Type") + } + if err := m.BlockID.ValidateBasic(); err != nil { + return fmt.Errorf("Wrong BlockID: %v", err) + } + return nil +} + // String returns a string representation. func (m *VoteSetMaj23Message) String() string { return fmt.Sprintf("[VSM23 %v/%02d/%v %v]", m.Height, m.Round, m.Type, m.BlockID) @@ -1503,6 +1621,24 @@ type VoteSetBitsMessage struct { Votes *cmn.BitArray } +// ValidateBasic performs basic validation. +func (m *VoteSetBitsMessage) ValidateBasic() error { + if m.Height < 0 { + return errors.New("Negative Height") + } + if m.Round < 0 { + return errors.New("Negative Round") + } + if !types.IsVoteTypeValid(m.Type) { + return errors.New("Invalid Type") + } + if err := m.BlockID.ValidateBasic(); err != nil { + return fmt.Errorf("Wrong BlockID: %v", err) + } + // NOTE: Votes.Size() can be zero if the node does not have any + return nil +} + // String returns a string representation. func (m *VoteSetBitsMessage) String() string { return fmt.Sprintf("[VSB %v/%02d/%v %v %v]", m.Height, m.Round, m.Type, m.BlockID, m.Votes) @@ -1515,6 +1651,11 @@ type ProposalHeartbeatMessage struct { Heartbeat *types.Heartbeat } +// ValidateBasic performs basic validation. +func (m *ProposalHeartbeatMessage) ValidateBasic() error { + return m.Heartbeat.ValidateBasic() +} + // String returns a string representation. func (m *ProposalHeartbeatMessage) String() string { return fmt.Sprintf("[HEARTBEAT %v]", m.Heartbeat) diff --git a/consensus/replay.go b/consensus/replay.go index fcff877fd..abc43eb57 100644 --- a/consensus/replay.go +++ b/consensus/replay.go @@ -264,8 +264,12 @@ func (h *Handshaker) Handshake(proxyApp proxy.AppConns) error { // Replay all blocks since appBlockHeight and ensure the result matches the current state. // Returns the final AppHash or an error. -func (h *Handshaker) ReplayBlocks(state sm.State, appHash []byte, appBlockHeight int64, proxyApp proxy.AppConns) ([]byte, error) { - +func (h *Handshaker) ReplayBlocks( + state sm.State, + appHash []byte, + appBlockHeight int64, + proxyApp proxy.AppConns, +) ([]byte, error) { storeBlockHeight := h.store.Height() stateBlockHeight := state.LastBlockHeight h.logger.Info("ABCI Replay Blocks", "appHeight", appBlockHeight, "storeHeight", storeBlockHeight, "stateHeight", stateBlockHeight) diff --git a/consensus/types/round_state.go b/consensus/types/round_state.go index d3f6468bf..ef4236118 100644 --- a/consensus/types/round_state.go +++ b/consensus/types/round_state.go @@ -26,8 +26,15 @@ const ( RoundStepPrecommitWait = RoundStepType(0x07) // Did receive any +2/3 precommits, start timeout RoundStepCommit = RoundStepType(0x08) // Entered commit state machine // NOTE: RoundStepNewHeight acts as RoundStepCommitWait. + + // NOTE: Update IsValid method if you change this! ) +// IsValid returns true if the step is valid, false if unknown/undefined. +func (rs RoundStepType) IsValid() bool { + return uint8(rs) >= 0x01 && uint8(rs) <= 0x08 +} + // String returns a string func (rs RoundStepType) String() string { switch rs { diff --git a/crypto/crypto.go b/crypto/crypto.go index 2462b0a98..b3526f881 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -6,6 +6,7 @@ import ( ) const ( + // AddressSize is the size of a pubkey address. AddressSize = tmhash.TruncatedSize ) diff --git a/evidence/reactor.go b/evidence/reactor.go index 52eb4a56f..32753b2b9 100644 --- a/evidence/reactor.go +++ b/evidence/reactor.go @@ -74,6 +74,13 @@ func (evR *EvidenceReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) { evR.Switch.StopPeerForError(src, err) return } + + if err = msg.ValidateBasic(); err != nil { + evR.Logger.Error("Peer sent us invalid msg", "peer", src, "msg", msg, "err", err) + evR.Switch.StopPeerForError(src, err) + return + } + evR.Logger.Debug("Receive", "src", src, "chId", chID, "msg", msg) switch msg := msg.(type) { @@ -191,7 +198,9 @@ type PeerState interface { // Messages // EvidenceMessage is a message sent or received by the EvidenceReactor. -type EvidenceMessage interface{} +type EvidenceMessage interface { + ValidateBasic() error +} func RegisterEvidenceMessages(cdc *amino.Codec) { cdc.RegisterInterface((*EvidenceMessage)(nil), nil) @@ -209,11 +218,21 @@ func decodeMsg(bz []byte) (msg EvidenceMessage, err error) { //------------------------------------- -// EvidenceMessage contains a list of evidence. +// EvidenceListMessage contains a list of evidence. type EvidenceListMessage struct { Evidence []types.Evidence } +// ValidateBasic performs basic validation. +func (m *EvidenceListMessage) ValidateBasic() error { + for i, ev := range m.Evidence { + if err := ev.ValidateBasic(); err != nil { + return fmt.Errorf("Invalid evidence (#%d): %v", i, err) + } + } + return nil +} + // String returns a string representation of the EvidenceListMessage. func (m *EvidenceListMessage) String() string { return fmt.Sprintf("[EvidenceListMessage %v]", m.Evidence) diff --git a/p2p/pex/addrbook.go b/p2p/pex/addrbook.go index e0c0e0b9c..61710bbf2 100644 --- a/p2p/pex/addrbook.go +++ b/p2p/pex/addrbook.go @@ -648,6 +648,10 @@ func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error { return ErrAddrBookNonRoutable{addr} } + if !addr.Valid() { + return ErrAddrBookInvalidAddr{addr} + } + // TODO: we should track ourAddrs by ID and by IP:PORT and refuse both. if _, ok := a.ourAddrs[addr.String()]; ok { return ErrAddrBookSelf{addr} diff --git a/p2p/pex/errors.go b/p2p/pex/errors.go index 7f660bdc5..fbee748ac 100644 --- a/p2p/pex/errors.go +++ b/p2p/pex/errors.go @@ -46,3 +46,11 @@ type ErrAddrBookNilAddr struct { func (err ErrAddrBookNilAddr) Error() string { return fmt.Sprintf("Cannot add a nil address. Got (addr, src) = (%v, %v)", err.Addr, err.Src) } + +type ErrAddrBookInvalidAddr struct { + Addr *p2p.NetAddress +} + +func (err ErrAddrBookInvalidAddr) Error() string { + return fmt.Sprintf("Cannot add invalid address %v", err.Addr) +} diff --git a/p2p/pex/pex_reactor.go b/p2p/pex/pex_reactor.go index c919794ab..46a12c488 100644 --- a/p2p/pex/pex_reactor.go +++ b/p2p/pex/pex_reactor.go @@ -288,21 +288,37 @@ func (r *PEXReactor) RequestAddrs(p Peer) { func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error { id := string(src.ID()) if !r.requestsSent.Has(id) { - return cmn.NewError("Received unsolicited pexAddrsMessage") + return errors.New("Unsolicited pexAddrsMessage") } r.requestsSent.Delete(id) srcAddr := src.NodeInfo().NetAddress() for _, netAddr := range addrs { - // NOTE: GetSelection methods should never return nil addrs + // Validate netAddr. Disconnect from a peer if it sends us invalid data. if netAddr == nil { - return cmn.NewError("received nil addr") + return errors.New("nil address in pexAddrsMessage") + } + // TODO: extract validating logic from NewNetAddressStringWithOptionalID + // and put it in netAddr#Valid (#2722) + na, err := p2p.NewNetAddressString(netAddr.String()) + if err != nil { + return fmt.Errorf("%s address in pexAddrsMessage is invalid: %v", + netAddr.String(), + err, + ) } - err := r.book.AddAddress(netAddr, srcAddr) - r.logErrAddrBook(err) + // NOTE: we check netAddr validity and routability in book#AddAddress. + err = r.book.AddAddress(na, srcAddr) + if err != nil { + r.logErrAddrBook(err) + // XXX: should we be strict about incoming data and disconnect from a + // peer here too? + continue + } - // If this address came from a seed node, try to connect to it without waiting. + // If this address came from a seed node, try to connect to it without + // waiting. for _, seedAddr := range r.seedAddrs { if seedAddr.Equals(srcAddr) { r.ensurePeers() diff --git a/state/validation.go b/state/validation.go index 345224843..e28d40e8b 100644 --- a/state/validation.go +++ b/state/validation.go @@ -21,22 +21,19 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error { // Validate basic info. if block.Version != state.Version.Consensus { - return fmt.Errorf( - "Wrong Block.Header.Version. Expected %v, got %v", + return fmt.Errorf("Wrong Block.Header.Version. Expected %v, got %v", state.Version.Consensus, block.Version, ) } if block.ChainID != state.ChainID { - return fmt.Errorf( - "Wrong Block.Header.ChainID. Expected %v, got %v", + return fmt.Errorf("Wrong Block.Header.ChainID. Expected %v, got %v", state.ChainID, block.ChainID, ) } if block.Height != state.LastBlockHeight+1 { - return fmt.Errorf( - "Wrong Block.Header.Height. Expected %v, got %v", + return fmt.Errorf("Wrong Block.Header.Height. Expected %v, got %v", state.LastBlockHeight+1, block.Height, ) @@ -44,16 +41,15 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error { // Validate prev block info. if !block.LastBlockID.Equals(state.LastBlockID) { - return fmt.Errorf( - "Wrong Block.Header.LastBlockID. Expected %v, got %v", + return fmt.Errorf("Wrong Block.Header.LastBlockID. Expected %v, got %v", state.LastBlockID, block.LastBlockID, ) } + newTxs := int64(len(block.Data.Txs)) if block.TotalTxs != state.LastBlockTotalTx+newTxs { - return fmt.Errorf( - "Wrong Block.Header.TotalTxs. Expected %v, got %v", + return fmt.Errorf("Wrong Block.Header.TotalTxs. Expected %v, got %v", state.LastBlockTotalTx+newTxs, block.TotalTxs, ) @@ -61,46 +57,44 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error { // Validate app info if !bytes.Equal(block.AppHash, state.AppHash) { - return fmt.Errorf( - "Wrong Block.Header.AppHash. Expected %X, got %v", + return fmt.Errorf("Wrong Block.Header.AppHash. Expected %X, got %v", state.AppHash, block.AppHash, ) } if !bytes.Equal(block.ConsensusHash, state.ConsensusParams.Hash()) { - return fmt.Errorf( - "Wrong Block.Header.ConsensusHash. Expected %X, got %v", + return fmt.Errorf("Wrong Block.Header.ConsensusHash. Expected %X, got %v", state.ConsensusParams.Hash(), block.ConsensusHash, ) } if !bytes.Equal(block.LastResultsHash, state.LastResultsHash) { - return fmt.Errorf( - "Wrong Block.Header.LastResultsHash. Expected %X, got %v", + return fmt.Errorf("Wrong Block.Header.LastResultsHash. Expected %X, got %v", state.LastResultsHash, block.LastResultsHash, ) } if !bytes.Equal(block.ValidatorsHash, state.Validators.Hash()) { - return fmt.Errorf( - "Wrong Block.Header.ValidatorsHash. Expected %X, got %v", + return fmt.Errorf("Wrong Block.Header.ValidatorsHash. Expected %X, got %v", state.Validators.Hash(), block.ValidatorsHash, ) } if !bytes.Equal(block.NextValidatorsHash, state.NextValidators.Hash()) { - return fmt.Errorf("Wrong Block.Header.NextValidatorsHash. Expected %X, got %v", state.NextValidators.Hash(), block.NextValidatorsHash) + return fmt.Errorf("Wrong Block.Header.NextValidatorsHash. Expected %X, got %v", + state.NextValidators.Hash(), + block.NextValidatorsHash, + ) } // Validate block LastCommit. if block.Height == 1 { if len(block.LastCommit.Precommits) != 0 { - return errors.New("Block at height 1 (first block) should have no LastCommit precommits") + return errors.New("Block at height 1 can't have LastCommit precommits") } } else { if len(block.LastCommit.Precommits) != state.LastValidators.Size() { - return fmt.Errorf( - "Invalid block commit size. Expected %v, got %v", + return fmt.Errorf("Invalid block commit size. Expected %v, got %v", state.LastValidators.Size(), len(block.LastCommit.Precommits), ) @@ -115,8 +109,7 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error { // Validate block Time if block.Height > 1 { if !block.Time.After(state.LastBlockTime) { - return fmt.Errorf( - "Block time %v not greater than last block time %v", + return fmt.Errorf("Block time %v not greater than last block time %v", block.Time, state.LastBlockTime, ) @@ -124,8 +117,7 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error { medianTime := MedianTime(block.LastCommit, state.LastValidators) if !block.Time.Equal(medianTime) { - return fmt.Errorf( - "Invalid block time. Expected %v, got %v", + return fmt.Errorf("Invalid block time. Expected %v, got %v", medianTime, block.Time, ) @@ -133,8 +125,7 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error { } else if block.Height == 1 { genesisTime := state.LastBlockTime if !block.Time.Equal(genesisTime) { - return fmt.Errorf( - "Block time %v is not equal to genesis time %v", + return fmt.Errorf("Block time %v is not equal to genesis time %v", block.Time, genesisTime, ) @@ -160,8 +151,7 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error { // a legit address and a known validator. if len(block.ProposerAddress) != crypto.AddressSize || !state.Validators.HasAddress(block.ProposerAddress) { - return fmt.Errorf( - "Block.Header.ProposerAddress, %X, is not a validator", + return fmt.Errorf("Block.Header.ProposerAddress, %X, is not a validator", block.ProposerAddress, ) } diff --git a/test/docker/Dockerfile b/test/docker/Dockerfile index 6bb320be8..1a64d4173 100644 --- a/test/docker/Dockerfile +++ b/test/docker/Dockerfile @@ -14,6 +14,7 @@ ENV GOBIN $GOPATH/bin WORKDIR $REPO # Copy in the code +# TODO: rewrite to only copy Makefile & other files? COPY . $REPO # Install the vendored dependencies @@ -21,16 +22,18 @@ COPY . $REPO RUN make get_tools RUN make get_vendor_deps -# Now copy in the code -# NOTE: this will overwrite whatever is in vendor/ -COPY . $REPO - # install ABCI CLI RUN make install_abci # install Tendermint RUN make install +RUN tendermint testnet --node-dir-prefix="mach" --v=4 --populate-persistent-peers=false --o=$REPO/test/p2p/data + +# Now copy in the code +# NOTE: this will overwrite whatever is in vendor/ +COPY . $REPO + # expose the volume for debugging VOLUME $REPO diff --git a/test/p2p/README.md b/test/p2p/README.md index 4ee3690af..956ce906c 100644 --- a/test/p2p/README.md +++ b/test/p2p/README.md @@ -19,7 +19,7 @@ docker network create --driver bridge --subnet 172.57.0.0/16 my_testnet ``` This gives us a new network with IP addresses in the rage `172.57.0.0 - 172.57.255.255`. -Peers on the network can have any IP address in this range. +Peers on the network can have any IP address in this range. For our four node network, let's pick `172.57.0.101 - 172.57.0.104`. Since we use Tendermint's default listening port of 26656, our list of seed nodes will look like: @@ -37,7 +37,7 @@ for i in $(seq 1 4); do --ip="172.57.0.$((100 + $i))" \ --name local_testnet_$i \ --entrypoint tendermint \ - -e TMHOME=/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$i/core \ + -e TMHOME=/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$((i-1)) \ tendermint_tester node --p2p.persistent_peers 172.57.0.101:26656,172.57.0.102:26656,172.57.0.103:26656,172.57.0.104:26656 --proxy_app=kvstore done ``` @@ -47,8 +47,5 @@ If you now run `docker ps`, you'll see your containers! We can confirm they are making blocks by checking the `/status` message using `curl` and `jq` to pretty print the output json: ``` -curl 172.57.0.101:26657/status | jq . +curl 172.57.0.101:26657/status | jq . ``` - - - diff --git a/test/p2p/data/mach1/core/config/genesis.json b/test/p2p/data/mach1/core/config/genesis.json deleted file mode 100644 index 515c10714..000000000 --- a/test/p2p/data/mach1/core/config/genesis.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "genesis_time": "2016-06-24T20:01:19.322Z", - "chain_id": "chain-9ujDWI", - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" - }, - "power": "1", - "name": "mach1" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" - }, - "power": "1", - "name": "mach2" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" - }, - "power": "1", - "name": "mach3" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" - }, - "power": "1", - "name": "mach4" - } - ], - "app_hash": "" -} diff --git a/test/p2p/data/mach1/core/config/node_key.json b/test/p2p/data/mach1/core/config/node_key.json deleted file mode 100644 index 4fa960850..000000000 --- a/test/p2p/data/mach1/core/config/node_key.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "BpYtFp8xSrudBa5aBLRuSPD72PGDAUm0dJORDL3Kd5YJbluUzRefVFrjwoHZv1yeDj2P9xkEi2L3hJCUz/qFkQ==" - } -} diff --git a/test/p2p/data/mach1/core/config/priv_validator.json b/test/p2p/data/mach1/core/config/priv_validator.json deleted file mode 100644 index ea2a01f5c..000000000 --- a/test/p2p/data/mach1/core/config/priv_validator.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "address": "AE47BBD4B3ACD80BFE17F6E0C66C5B8492A81AE4", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" - }, - "last_height": "0", - "last_round": "0", - "last_step": 0, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "VHqgfHqM4WxcsqQMbCbRWwoylgQQqfHqblC2NvGrOJq+iTPf8WAMAm40cY8XhaTN6rkMNWmLOU44tpR66R3hFg==" - } -} diff --git a/test/p2p/data/mach2/core/config/genesis.json b/test/p2p/data/mach2/core/config/genesis.json deleted file mode 100644 index 515c10714..000000000 --- a/test/p2p/data/mach2/core/config/genesis.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "genesis_time": "2016-06-24T20:01:19.322Z", - "chain_id": "chain-9ujDWI", - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" - }, - "power": "1", - "name": "mach1" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" - }, - "power": "1", - "name": "mach2" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" - }, - "power": "1", - "name": "mach3" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" - }, - "power": "1", - "name": "mach4" - } - ], - "app_hash": "" -} diff --git a/test/p2p/data/mach2/core/config/node_key.json b/test/p2p/data/mach2/core/config/node_key.json deleted file mode 100644 index 6eb151106..000000000 --- a/test/p2p/data/mach2/core/config/node_key.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "uM6LDVE4wQIIUmq9rc6RxzX8zEGG4G4Jcuw15klzQopF68YfJM4bkbPSavurEcJ4nvBMusKBg2GcARFrZqnFKA==" - } -} diff --git a/test/p2p/data/mach2/core/config/priv_validator.json b/test/p2p/data/mach2/core/config/priv_validator.json deleted file mode 100644 index 6e0cd7f8f..000000000 --- a/test/p2p/data/mach2/core/config/priv_validator.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "address": "5D61EE46CCE91F579086522D7FD8CEC3F854E946", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" - }, - "last_height": "0", - "last_round": "0", - "last_step": 0, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "0EeInmBQL8MSnQq38zSxg47Z7R7Nmcu5a3GtWr9agUNtxTRGUyMSZYfSoqk7WdaJtxcHOx3paKJabvE9WVMYrQ==" - } -} diff --git a/test/p2p/data/mach3/core/config/genesis.json b/test/p2p/data/mach3/core/config/genesis.json deleted file mode 100644 index 515c10714..000000000 --- a/test/p2p/data/mach3/core/config/genesis.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "genesis_time": "2016-06-24T20:01:19.322Z", - "chain_id": "chain-9ujDWI", - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" - }, - "power": "1", - "name": "mach1" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" - }, - "power": "1", - "name": "mach2" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" - }, - "power": "1", - "name": "mach3" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" - }, - "power": "1", - "name": "mach4" - } - ], - "app_hash": "" -} diff --git a/test/p2p/data/mach3/core/config/node_key.json b/test/p2p/data/mach3/core/config/node_key.json deleted file mode 100644 index 0885bcf9c..000000000 --- a/test/p2p/data/mach3/core/config/node_key.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "kT3orG0YkipT9rAZbvAjtGk/7Pu1ZeCE8LSUF2jz2uiSs1rdlUVi/gccRlvCRLKvrtSicOyEkmk0FHPOGS3mgg==" - } -} diff --git a/test/p2p/data/mach3/core/config/priv_validator.json b/test/p2p/data/mach3/core/config/priv_validator.json deleted file mode 100644 index ec68ca7bb..000000000 --- a/test/p2p/data/mach3/core/config/priv_validator.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "address": "705F9DA2CC7D7AF5F4519455ED99622E40E439A1", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" - }, - "last_height": "0", - "last_round": "0", - "last_step": 0, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "waTkfzSfxfVW9Kmie6d2uUQkwxK6ps9u5EuGc0jXw/KuZ6xpfRNaoLRgHqV+qrP+v0uqTyKcRaWYwphbEvzRoQ==" - } -} diff --git a/test/p2p/data/mach4/core/config/genesis.json b/test/p2p/data/mach4/core/config/genesis.json deleted file mode 100644 index 515c10714..000000000 --- a/test/p2p/data/mach4/core/config/genesis.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "genesis_time": "2016-06-24T20:01:19.322Z", - "chain_id": "chain-9ujDWI", - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" - }, - "power": "1", - "name": "mach1" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" - }, - "power": "1", - "name": "mach2" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" - }, - "power": "1", - "name": "mach3" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" - }, - "power": "1", - "name": "mach4" - } - ], - "app_hash": "" -} diff --git a/test/p2p/data/mach4/core/config/node_key.json b/test/p2p/data/mach4/core/config/node_key.json deleted file mode 100644 index d6a5d79c2..000000000 --- a/test/p2p/data/mach4/core/config/node_key.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "QIIm8/QEEawiJi3Zozv+J9b+1CufCEkGs3lxGMlRy4L4FVIXCoXJTwYIrotZtwoMqLYEqQV1hbKKJmFA3GFelw==" - } -} diff --git a/test/p2p/data/mach4/core/config/priv_validator.json b/test/p2p/data/mach4/core/config/priv_validator.json deleted file mode 100644 index 468550ea8..000000000 --- a/test/p2p/data/mach4/core/config/priv_validator.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "address": "D1054266EC9EEA511ED9A76DEFD520BBE1B5E850", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" - }, - "last_height": "0", - "last_round": "0", - "last_step": 0, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "xMw+0o8CDC29qYvNvwjDztNwRw508l6TjV0pXo49KwyevI9YztS0bc1auKulkd0lPNfLUDcnP9oyvAtkYcTv2Q==" - } -} diff --git a/test/p2p/ip_plus_id.sh b/test/p2p/ip_plus_id.sh index 0d2248fe0..95871d3f1 100755 --- a/test/p2p/ip_plus_id.sh +++ b/test/p2p/ip_plus_id.sh @@ -3,5 +3,5 @@ set -eu ID=$1 DOCKER_IMAGE=$2 -NODEID="$(docker run --rm -e TMHOME=/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$ID/core $DOCKER_IMAGE tendermint show_node_id)" +NODEID="$(docker run --rm -e TMHOME=/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$((ID-1)) $DOCKER_IMAGE tendermint show_node_id)" echo "$NODEID@172.57.0.$((100+$ID))" diff --git a/test/p2p/peer.sh b/test/p2p/peer.sh index ad04d000f..63d46f8d5 100644 --- a/test/p2p/peer.sh +++ b/test/p2p/peer.sh @@ -15,13 +15,15 @@ echo "starting tendermint peer ID=$ID" # NOTE: $NODE_FLAGS should be unescaped (no quotes). otherwise it will be # treated as one flag. +# test/p2p/data/mach$((ID-1)) data is generated in test/docker/Dockerfile using +# the tendermint testnet command. if [[ "$ID" == "x" ]]; then # Set "x" to "1" to print to console. docker run \ --net="$NETWORK_NAME" \ --ip=$(test/p2p/ip.sh "$ID") \ --name "local_testnet_$ID" \ --entrypoint tendermint \ - -e TMHOME="/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$ID/core" \ + -e TMHOME="/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$((ID-1))" \ -e GOMAXPROCS=1 \ --log-driver=syslog \ --log-opt syslog-address=udp://127.0.0.1:5514 \ @@ -34,7 +36,7 @@ else --ip=$(test/p2p/ip.sh "$ID") \ --name "local_testnet_$ID" \ --entrypoint tendermint \ - -e TMHOME="/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$ID/core" \ + -e TMHOME="/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$((ID-1))" \ -e GOMAXPROCS=1 \ --log-driver=syslog \ --log-opt syslog-address=udp://127.0.0.1:5514 \ diff --git a/test/p2p/pex/test_addrbook.sh b/test/p2p/pex/test_addrbook.sh index 9c58db30c..06f9212fd 100644 --- a/test/p2p/pex/test_addrbook.sh +++ b/test/p2p/pex/test_addrbook.sh @@ -18,7 +18,7 @@ echo "1. restart peer $ID" docker stop "local_testnet_$ID" echo "stopped local_testnet_$ID" # preserve addrbook.json -docker cp "local_testnet_$ID:/go/src/github.com/tendermint/tendermint/test/p2p/data/mach1/core/config/addrbook.json" "/tmp/addrbook.json" +docker cp "local_testnet_$ID:/go/src/github.com/tendermint/tendermint/test/p2p/data/mach0/config/addrbook.json" "/tmp/addrbook.json" set +e #CIRCLE docker rm -vf "local_testnet_$ID" set -e @@ -32,11 +32,11 @@ bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$CLIENT_NAME" "test/p2p # Now we know that the node is up. -docker cp "/tmp/addrbook.json" "local_testnet_$ID:/go/src/github.com/tendermint/tendermint/test/p2p/data/mach1/core/config/addrbook.json" +docker cp "/tmp/addrbook.json" "local_testnet_$ID:/go/src/github.com/tendermint/tendermint/test/p2p/data/mach0/config/addrbook.json" echo "with the following addrbook:" cat /tmp/addrbook.json # exec doesn't work on circle -# docker exec "local_testnet_$ID" cat "/go/src/github.com/tendermint/tendermint/test/p2p/data/mach1/core/config/addrbook.json" +# docker exec "local_testnet_$ID" cat "/go/src/github.com/tendermint/tendermint/test/p2p/data/mach0/config/addrbook.json" echo "" echo "----------------------------------------------------------------------" diff --git a/types/block.go b/types/block.go index 46ad73a71..4ae51d4df 100644 --- a/types/block.go +++ b/types/block.go @@ -2,12 +2,14 @@ package types import ( "bytes" - "errors" "fmt" "strings" "sync" "time" + "github.com/pkg/errors" + + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/merkle" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/version" @@ -57,54 +59,117 @@ func MakeBlock(height int64, txs []Tx, lastCommit *Commit, evidence []Evidence) // ValidateBasic performs basic validation that doesn't involve state data. // It checks the internal consistency of the block. +// Further validation is done using state#ValidateBlock. func (b *Block) ValidateBasic() error { if b == nil { - return errors.New("Nil blocks are invalid") + return errors.New("nil block") } b.mtx.Lock() defer b.mtx.Unlock() - if b.Height < 0 { - return fmt.Errorf( - "Negative Block.Header.Height: %v", - b.Height, - ) + if len(b.ChainID) > MaxChainIDLen { + return fmt.Errorf("ChainID is too long. Max is %d, got %d", MaxChainIDLen, len(b.ChainID)) } + if b.Height < 0 { + return errors.New("Negative Header.Height") + } else if b.Height == 0 { + return errors.New("Zero Header.Height") + } + + // NOTE: Timestamp validation is subtle and handled elsewhere. + newTxs := int64(len(b.Data.Txs)) if b.NumTxs != newTxs { - return fmt.Errorf( - "Wrong Block.Header.NumTxs. Expected %v, got %v", + return fmt.Errorf("Wrong Header.NumTxs. Expected %v, got %v", newTxs, b.NumTxs, ) } + + // TODO: fix tests so we can do this + /*if b.TotalTxs < b.NumTxs { + return fmt.Errorf("Header.TotalTxs (%d) is less than Header.NumTxs (%d)", b.TotalTxs, b.NumTxs) + }*/ + if b.TotalTxs < 0 { + return errors.New("Negative Header.TotalTxs") + } + + if err := b.LastBlockID.ValidateBasic(); err != nil { + return fmt.Errorf("Wrong Header.LastBlockID: %v", err) + } + + // Validate the last commit and its hash. + if b.Header.Height > 1 { + if b.LastCommit == nil { + return errors.New("nil LastCommit") + } + if err := b.LastCommit.ValidateBasic(); err != nil { + return fmt.Errorf("Wrong LastCommit") + } + } + if err := ValidateHash(b.LastCommitHash); err != nil { + return fmt.Errorf("Wrong Header.LastCommitHash: %v", err) + } if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) { - return fmt.Errorf( - "Wrong Block.Header.LastCommitHash. Expected %v, got %v", - b.LastCommitHash, + return fmt.Errorf("Wrong Header.LastCommitHash. Expected %v, got %v", b.LastCommit.Hash(), + b.LastCommitHash, ) } - if b.Header.Height != 1 { - if err := b.LastCommit.ValidateBasic(); err != nil { - return err - } + + // Validate the hash of the transactions. + // NOTE: b.Data.Txs may be nil, but b.Data.Hash() + // still works fine + if err := ValidateHash(b.DataHash); err != nil { + return fmt.Errorf("Wrong Header.DataHash: %v", err) } if !bytes.Equal(b.DataHash, b.Data.Hash()) { return fmt.Errorf( - "Wrong Block.Header.DataHash. Expected %v, got %v", - b.DataHash, + "Wrong Header.DataHash. Expected %v, got %v", b.Data.Hash(), + b.DataHash, ) } + + // Basic validation of hashes related to application data. + // Will validate fully against state in state#ValidateBlock. + if err := ValidateHash(b.ValidatorsHash); err != nil { + return fmt.Errorf("Wrong Header.ValidatorsHash: %v", err) + } + if err := ValidateHash(b.NextValidatorsHash); err != nil { + return fmt.Errorf("Wrong Header.NextValidatorsHash: %v", err) + } + if err := ValidateHash(b.ConsensusHash); err != nil { + return fmt.Errorf("Wrong Header.ConsensusHash: %v", err) + } + // NOTE: AppHash is arbitrary length + if err := ValidateHash(b.LastResultsHash); err != nil { + return fmt.Errorf("Wrong Header.LastResultsHash: %v", err) + } + + // Validate evidence and its hash. + if err := ValidateHash(b.EvidenceHash); err != nil { + return fmt.Errorf("Wrong Header.EvidenceHash: %v", err) + } + // NOTE: b.Evidence.Evidence may be nil, but we're just looping. + for i, ev := range b.Evidence.Evidence { + if err := ev.ValidateBasic(); err != nil { + return fmt.Errorf("Invalid evidence (#%d): %v", i, err) + } + } if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) { - return fmt.Errorf( - "Wrong Block.Header.EvidenceHash. Expected %v, got %v", + return fmt.Errorf("Wrong Header.EvidenceHash. Expected %v, got %v", b.EvidenceHash, b.Evidence.Hash(), ) } + + if len(b.ProposerAddress) != crypto.AddressSize { + return fmt.Errorf("Expected len(Header.ProposerAddress) to be %d, got %d", + crypto.AddressSize, len(b.ProposerAddress)) + } + return nil } @@ -719,6 +784,18 @@ func (blockID BlockID) Key() string { return string(blockID.Hash) + string(bz) } +// ValidateBasic performs basic validation. +func (blockID BlockID) ValidateBasic() error { + // Hash can be empty in case of POLBlockID in Proposal. + if err := ValidateHash(blockID.Hash); err != nil { + return fmt.Errorf("Wrong Hash") + } + if err := blockID.PartsHeader.ValidateBasic(); err != nil { + return fmt.Errorf("Wrong PartsHeader: %v", err) + } + return nil +} + // String returns a human readable string representation of the BlockID func (blockID BlockID) String() string { return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader) diff --git a/types/block_test.go b/types/block_test.go index 46881a099..cdea293f0 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -80,11 +80,13 @@ func TestBlockValidateBasic(t *testing.T) { blk.EvidenceHash = []byte("something else") }, true}, } - for _, tc := range testCases { + for i, tc := range testCases { t.Run(tc.testName, func(t *testing.T) { block := MakeBlock(h, txs, commit, evList) + block.ProposerAddress = valSet.GetProposer().Address tc.malleateBlock(block) - assert.Equal(t, tc.expErr, block.ValidateBasic() != nil, "ValidateBasic had an unexpected result") + err = block.ValidateBasic() + assert.Equal(t, tc.expErr, err != nil, "#%d: %v", i, err) }) } } diff --git a/types/evidence.go b/types/evidence.go index d1e15c819..fb2423458 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" + "github.com/pkg/errors" "github.com/tendermint/tendermint/crypto/tmhash" amino "github.com/tendermint/go-amino" @@ -60,6 +61,7 @@ type Evidence interface { Verify(chainID string, pubKey crypto.PubKey) error // verify the evidence Equal(Evidence) bool // check equality of evidence + ValidateBasic() error String() string } @@ -172,6 +174,23 @@ func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool { return bytes.Equal(dveHash, evHash) } +// ValidateBasic performs basic validation. +func (dve *DuplicateVoteEvidence) ValidateBasic() error { + if len(dve.PubKey.Bytes()) == 0 { + return errors.New("Empty PubKey") + } + if dve.VoteA == nil || dve.VoteB == nil { + return fmt.Errorf("One or both of the votes are empty %v, %v", dve.VoteA, dve.VoteB) + } + if err := dve.VoteA.ValidateBasic(); err != nil { + return fmt.Errorf("Invalid VoteA: %v", err) + } + if err := dve.VoteB.ValidateBasic(); err != nil { + return fmt.Errorf("Invalid VoteB: %v", err) + } + return nil +} + //----------------------------------------------------------------- // UNSTABLE @@ -201,6 +220,7 @@ func (e MockGoodEvidence) Equal(ev Evidence) bool { return e.Height_ == e2.Height_ && bytes.Equal(e.Address_, e2.Address_) } +func (e MockGoodEvidence) ValidateBasic() error { return nil } func (e MockGoodEvidence) String() string { return fmt.Sprintf("GoodEvidence: %d/%s", e.Height_, e.Address_) } @@ -218,6 +238,7 @@ func (e MockBadEvidence) Equal(ev Evidence) bool { return e.Height_ == e2.Height_ && bytes.Equal(e.Address_, e2.Address_) } +func (e MockBadEvidence) ValidateBasic() error { return nil } func (e MockBadEvidence) String() string { return fmt.Sprintf("BadEvidence: %d/%s", e.Height_, e.Address_) } diff --git a/types/heartbeat.go b/types/heartbeat.go index 9dea039e0..986e9384f 100644 --- a/types/heartbeat.go +++ b/types/heartbeat.go @@ -3,6 +3,8 @@ package types import ( "fmt" + "github.com/pkg/errors" + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tendermint/libs/common" ) @@ -50,3 +52,32 @@ func (heartbeat *Heartbeat) String() string { heartbeat.Height, heartbeat.Round, heartbeat.Sequence, fmt.Sprintf("/%X.../", cmn.Fingerprint(heartbeat.Signature[:]))) } + +// ValidateBasic performs basic validation. +func (heartbeat *Heartbeat) ValidateBasic() error { + if len(heartbeat.ValidatorAddress) != crypto.AddressSize { + return fmt.Errorf("Expected ValidatorAddress size to be %d bytes, got %d bytes", + crypto.AddressSize, + len(heartbeat.ValidatorAddress), + ) + } + if heartbeat.ValidatorIndex < 0 { + return errors.New("Negative ValidatorIndex") + } + if heartbeat.Height < 0 { + return errors.New("Negative Height") + } + if heartbeat.Round < 0 { + return errors.New("Negative Round") + } + if heartbeat.Sequence < 0 { + return errors.New("Negative Sequence") + } + if len(heartbeat.Signature) == 0 { + return errors.New("Signature is missing") + } + if len(heartbeat.Signature) > MaxSignatureSize { + return fmt.Errorf("Signature is too big (max: %d)", MaxSignatureSize) + } + return nil +} diff --git a/types/part_set.go b/types/part_set.go index 812b1c2fd..af59851c9 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -2,11 +2,12 @@ package types import ( "bytes" - "errors" "fmt" "io" "sync" + "github.com/pkg/errors" + "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/crypto/tmhash" cmn "github.com/tendermint/tendermint/libs/common" @@ -36,6 +37,17 @@ func (part *Part) Hash() []byte { return part.hash } +// ValidateBasic performs basic validation. +func (part *Part) ValidateBasic() error { + if part.Index < 0 { + return errors.New("Negative Index") + } + if len(part.Bytes) > BlockPartSizeBytes { + return fmt.Errorf("Too big (max: %d)", BlockPartSizeBytes) + } + return nil +} + func (part *Part) String() string { return part.StringIndented("") } @@ -70,6 +82,18 @@ func (psh PartSetHeader) Equals(other PartSetHeader) bool { return psh.Total == other.Total && bytes.Equal(psh.Hash, other.Hash) } +// ValidateBasic performs basic validation. +func (psh PartSetHeader) ValidateBasic() error { + if psh.Total < 0 { + return errors.New("Negative Total") + } + // Hash can be empty in case of POLBlockID.PartsHeader in Proposal. + if err := ValidateHash(psh.Hash); err != nil { + return errors.Wrap(err, "Wrong Hash") + } + return nil +} + //------------------------------------- type PartSet struct { diff --git a/types/proposal.go b/types/proposal.go index 09cfd1967..f3b62aae7 100644 --- a/types/proposal.go +++ b/types/proposal.go @@ -43,6 +43,35 @@ func NewProposal(height int64, round int, polRound int, blockID BlockID) *Propos } } +// ValidateBasic performs basic validation. +func (p *Proposal) ValidateBasic() error { + if p.Type != ProposalType { + return errors.New("Invalid Type") + } + if p.Height < 0 { + return errors.New("Negative Height") + } + if p.Round < 0 { + return errors.New("Negative Round") + } + if p.POLRound < -1 { + return errors.New("Negative POLRound (exception: -1)") + } + if err := p.BlockID.ValidateBasic(); err != nil { + return fmt.Errorf("Wrong BlockID: %v", err) + } + + // NOTE: Timestamp validation is subtle and handled elsewhere. + + if len(p.Signature) == 0 { + return errors.New("Signature is missing") + } + if len(p.Signature) > MaxSignatureSize { + return fmt.Errorf("Signature is too big (max: %d)", MaxSignatureSize) + } + return nil +} + // String returns a string representation of the Proposal. func (p *Proposal) String() string { return fmt.Sprintf("Proposal{%v/%v (%v, %v) %X @ %s}", diff --git a/types/signable.go b/types/signable.go index cc6498882..baabdff08 100644 --- a/types/signable.go +++ b/types/signable.go @@ -1,5 +1,17 @@ package types +import ( + "github.com/tendermint/tendermint/crypto/ed25519" + cmn "github.com/tendermint/tendermint/libs/common" +) + +var ( + // MaxSignatureSize is a maximum allowed signature size for the Heartbeat, + // Proposal and Vote. + // XXX: secp256k1 does not have Size nor MaxSize defined. + MaxSignatureSize = cmn.MaxInt(ed25519.SignatureSize, 64) +) + // Signable is an interface for all signable things. // It typically removes signatures before serializing. // SignBytes returns the bytes to be signed diff --git a/types/signed_msg_type.go b/types/signed_msg_type.go index cc3ddbdc1..10e7c70c0 100644 --- a/types/signed_msg_type.go +++ b/types/signed_msg_type.go @@ -15,11 +15,10 @@ const ( HeartbeatType SignedMsgType = 0x30 ) -func IsVoteTypeValid(type_ SignedMsgType) bool { - switch type_ { - case PrevoteType: - return true - case PrecommitType: +// IsVoteTypeValid returns true if t is a valid vote type. +func IsVoteTypeValid(t SignedMsgType) bool { + switch t { + case PrevoteType, PrecommitType: return true default: return false diff --git a/types/validation.go b/types/validation.go new file mode 100644 index 000000000..1271cfd94 --- /dev/null +++ b/types/validation.go @@ -0,0 +1,40 @@ +package types + +import ( + "fmt" + "time" + + "github.com/tendermint/tendermint/crypto/tmhash" + tmtime "github.com/tendermint/tendermint/types/time" +) + +// ValidateTime does a basic time validation ensuring time does not drift too +// much: +/- one year. +// TODO: reduce this to eg 1 day +// NOTE: DO NOT USE in ValidateBasic methods in this package. This function +// can only be used for real time validation, like on proposals and votes +// in the consensus. If consensus is stuck, and rounds increase for more than a day, +// having only a 1-day band here could break things... +// Can't use for validating blocks because we may be syncing years worth of history. +func ValidateTime(t time.Time) error { + var ( + now = tmtime.Now() + oneYear = 8766 * time.Hour + ) + if t.Before(now.Add(-oneYear)) || t.After(now.Add(oneYear)) { + return fmt.Errorf("Time drifted too much. Expected: -1 < %v < 1 year", now) + } + return nil +} + +// ValidateHash returns an error if the hash is not empty, but its +// size != tmhash.Size. +func ValidateHash(h []byte) error { + if len(h) > 0 && len(h) != tmhash.Size { + return fmt.Errorf("Expected size to be %d bytes, got %d bytes", + tmhash.Size, + len(h), + ) + } + return nil +} diff --git a/types/vote.go b/types/vote.go index 1d7e9cf6f..bf14d403b 100644 --- a/types/vote.go +++ b/types/vote.go @@ -46,7 +46,8 @@ func NewConflictingVoteError(val *Validator, voteA, voteB *Vote) *ErrVoteConflic // Address is hex bytes. type Address = crypto.Address -// Represents a prevote, precommit, or commit vote from validators for consensus. +// Vote represents a prevote, precommit, or commit vote from validators for +// consensus. type Vote struct { Type SignedMsgType `json:"type"` Height int64 `json:"height"` @@ -108,3 +109,38 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error { } return nil } + +// ValidateBasic performs basic validation. +func (vote *Vote) ValidateBasic() error { + if !IsVoteTypeValid(vote.Type) { + return errors.New("Invalid Type") + } + if vote.Height < 0 { + return errors.New("Negative Height") + } + if vote.Round < 0 { + return errors.New("Negative Round") + } + + // NOTE: Timestamp validation is subtle and handled elsewhere. + + if err := vote.BlockID.ValidateBasic(); err != nil { + return fmt.Errorf("Wrong BlockID: %v", err) + } + if len(vote.ValidatorAddress) != crypto.AddressSize { + return fmt.Errorf("Expected ValidatorAddress size to be %d bytes, got %d bytes", + crypto.AddressSize, + len(vote.ValidatorAddress), + ) + } + if vote.ValidatorIndex < 0 { + return errors.New("Negative ValidatorIndex") + } + if len(vote.Signature) == 0 { + return errors.New("Signature is missing") + } + if len(vote.Signature) > MaxSignatureSize { + return fmt.Errorf("Signature is too big (max: %d)", MaxSignatureSize) + } + return nil +} From 80e4fe6c0d72df0a41ff6909cd0d626d5980894b Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Fri, 2 Nov 2018 10:16:29 +0100 Subject: [PATCH 29/35] [ADR] [DRAFT] pubsub 2.0 (#2532) * pubsub adr Refs #951, #1879, #1880 * highlight question * fix typos after Ismail's review --- docs/architecture/adr-033-pubsub.md | 122 ++++++++++++++++++++++++++++ docs/architecture/adr-template.md | 4 + 2 files changed, 126 insertions(+) create mode 100644 docs/architecture/adr-033-pubsub.md diff --git a/docs/architecture/adr-033-pubsub.md b/docs/architecture/adr-033-pubsub.md new file mode 100644 index 000000000..0ef0cae62 --- /dev/null +++ b/docs/architecture/adr-033-pubsub.md @@ -0,0 +1,122 @@ +# ADR 033: pubsub 2.0 + +Author: Anton Kaliaev (@melekes) + +## Changelog + +02-10-2018: Initial draft + +## Context + +Since the initial version of the pubsub, there's been a number of issues +raised: #951, #1879, #1880. Some of them are high-level issues questioning the +core design choices made. Others are minor and mostly about the interface of +`Subscribe()` / `Publish()` functions. + +### Sync vs Async + +Now, when publishing a message to subscribers, we can do it in a goroutine: + +_using channels for data transmission_ +```go +for each subscriber { + out := subscriber.outc + go func() { + out <- msg + } +} +``` + +_by invoking callback functions_ +```go +for each subscriber { + go subscriber.callbackFn() +} +``` + +This gives us greater performance and allows us to avoid "slow client problem" +(when other subscribers have to wait for a slow subscriber). A pool of +goroutines can be used to avoid uncontrolled memory growth. + +In certain cases, this is what you want. But in our case, because we need +strict ordering of events (if event A was published before B, the guaranteed +delivery order will be A -> B), we can't use goroutines. + +There is also a question whenever we should have a non-blocking send: + +```go +for each subscriber { + out := subscriber.outc + select { + case out <- msg: + default: + log("subscriber %v buffer is full, skipping...") + } +} +``` + +This fixes the "slow client problem", but there is no way for a slow client to +know if it had missed a message. On the other hand, if we're going to stick +with blocking send, **devs must always ensure subscriber's handling code does not +block**. As you can see, there is an implicit choice between ordering guarantees +and using goroutines. + +The interim option is to run goroutines pool for a single message, wait for all +goroutines to finish. This will solve "slow client problem", but we'd still +have to wait `max(goroutine_X_time)` before we can publish the next message. +My opinion: not worth doing. + +### Channels vs Callbacks + +Yet another question is whether we should use channels for message transmission or +call subscriber-defined callback functions. Callback functions give subscribers +more flexibility - you can use mutexes in there, channels, spawn goroutines, +anything you really want. But they also carry local scope, which can result in +memory leaks and/or memory usage increase. + +Go channels are de-facto standard for carrying data between goroutines. + +**Question: Is it worth switching to callback functions?** + +### Why `Subscribe()` accepts an `out` channel? + +Because in our tests, we create buffered channels (cap: 1). Alternatively, we +can make capacity an argument. + +## Decision + +Change Subscribe() function to return out channel: + +```go +// outCap can be used to set capacity of out channel (unbuffered by default). +Subscribe(ctx context.Context, clientID string, query Query, outCap... int) (out <-chan interface{}, err error) { +``` + +It's more idiomatic since we're closing it during Unsubscribe/UnsubscribeAll calls. + +Also, we should make tags available to subscribers: + +```go +type MsgAndTags struct { + Msg interface{} + Tags TagMap +} + +// outCap can be used to set capacity of out channel (unbuffered by default). +Subscribe(ctx context.Context, clientID string, query Query, outCap... int) (out <-chan MsgAndTags, err error) { +``` + +## Status + +In review + +## Consequences + +### Positive + +- more idiomatic interface +- subscribers know what tags msg was published with + +### Negative + +### Neutral diff --git a/docs/architecture/adr-template.md b/docs/architecture/adr-template.md index d47c7f558..4879afc40 100644 --- a/docs/architecture/adr-template.md +++ b/docs/architecture/adr-template.md @@ -1,5 +1,9 @@ # ADR 000: Template for an ADR +Author: + +## Changelog + ## Context ## Decision From 322cee9156a4b99980f5c7d256877eaa3f4dc85e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 2 Nov 2018 13:55:09 -0400 Subject: [PATCH 30/35] Release/v0.26.0 (#2726) * changelog_pending -> changelog * update changelog * update changelog * update changelog and upgrading --- CHANGELOG.md | 143 +++++++++++++++++++++++++++++++++++++++++++ CHANGELOG_PENDING.md | 101 +----------------------------- UPGRADING.md | 10 ++- 3 files changed, 152 insertions(+), 102 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6032fc204..792386e5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,148 @@ # Changelog +## v0.26.0 + +*November 2, 2018* + +Special thanks to external contributors on this release: +@bradyjoestar, @connorwstein, @goolAdapter, @HaoyangLiu, +@james-ray, @overbool, @phymbert, @Slamper, @Uzair1995, @yutianwu. + +Special thanks to @Slamper for a series of bug reports in our [bug bounty +program](https://hackerone.com/tendermint) which are fixed in this release. + +This release is primarily about adding Version fields to various data structures, +optimizing consensus messages for signing and verification in +restricted environments (like HSMs and the Ethereum Virtual Machine), and +aligning the consensus code with the [specification](https://arxiv.org/abs/1807.04938). +It also includes our first take at a generalized merkle proof system, and +changes the length of hashes used for hashing data structures from 20 to 32 +bytes. + +See the [UPGRADING.md](UPGRADING.md#v0.26.0) for details on upgrading to the new +version. + +Please note that we are still making breaking changes to the protocols. +While the new Version fields should help us to keep the software backwards compatible +even while upgrading the protocols, we cannot guarantee that new releases will +be compatible with old chains just yet. We expect there will be another breaking +release or two before the Cosmos Hub launch, but we will otherwise be paying +increasing attention to backwards compatibility. Thanks for bearing with us! + +### BREAKING CHANGES: + +* CLI/RPC/Config + * [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) Timeouts are now strings like "3s" and "100ms", not ints + * [config] [\#2505](https://github.com/tendermint/tendermint/issues/2505) Remove Mempool.RecheckEmpty (it was effectively useless anyways) + * [config] [\#2490](https://github.com/tendermint/tendermint/issues/2490) `mempool.wal` is disabled by default + * [privval] [\#2459](https://github.com/tendermint/tendermint/issues/2459) Split `SocketPVMsg`s implementations into Request and Response, where the Response may contain a error message (returned by the remote signer) + * [state] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Add Version field to State, breaking the format of State as + encoded on disk. + * [rpc] [\#2298](https://github.com/tendermint/tendermint/issues/2298) `/abci_query` takes `prove` argument instead of `trusted` and switches the default + behaviour to `prove=false` + * [rpc] [\#2654](https://github.com/tendermint/tendermint/issues/2654) Remove all `node_info.other.*_version` fields in `/status` and + `/net_info` + * [rpc] [\#2636](https://github.com/tendermint/tendermint/issues/2636) Remove + `_params` suffix from fields in `consensus_params`. + +* Apps + * [abci] [\#2298](https://github.com/tendermint/tendermint/issues/2298) ResponseQuery.Proof is now a structured merkle.Proof, not just + arbitrary bytes + * [abci] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Add Version to Header and shift all fields by one + * [abci] [\#2662](https://github.com/tendermint/tendermint/issues/2662) Bump the field numbers for some `ResponseInfo` fields to make room for + `AppVersion` + * [abci] [\#2636](https://github.com/tendermint/tendermint/issues/2636) Updates to ConsensusParams + * Remove `Params` suffix from field names + * Add `Params` suffix to message types + * Add new field and type, `Validator ValidatorParams`, to control what types of validator keys are allowed. + +* Go API + * [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) Timeouts are time.Duration, not ints + * [crypto/merkle & lite] [\#2298](https://github.com/tendermint/tendermint/issues/2298) Various changes to accomodate General Merkle trees + * [crypto/merkle] [\#2595](https://github.com/tendermint/tendermint/issues/2595) Remove all Hasher objects in favor of byte slices + * [crypto/merkle] [\#2635](https://github.com/tendermint/tendermint/issues/2635) merkle.SimpleHashFromTwoHashes is no longer exported + * [node] [\#2479](https://github.com/tendermint/tendermint/issues/2479) Remove node.RunForever + * [rpc/client] [\#2298](https://github.com/tendermint/tendermint/issues/2298) `ABCIQueryOptions.Trusted` -> `ABCIQueryOptions.Prove` + * [types] [\#2298](https://github.com/tendermint/tendermint/issues/2298) Remove `Index` and `Total` fields from `TxProof`. + * [types] [\#2598](https://github.com/tendermint/tendermint/issues/2598) + `VoteTypeXxx` are now of type `SignedMsgType byte` and named `XxxType`, eg. + `PrevoteType`, `PrecommitType`. + * [types] [\#2636](https://github.com/tendermint/tendermint/issues/2636) Rename fields in ConsensusParams to remove `Params` suffixes + * [types] [\#2735](https://github.com/tendermint/tendermint/issues/2735) Simplify Proposal message to align with spec + +* Blockchain Protocol + * [crypto/tmhash] [\#2732](https://github.com/tendermint/tendermint/issues/2732) TMHASH is now full 32-byte SHA256 + * All hashes in the block header and Merkle trees are now 32-bytes + * PubKey Addresses are still only 20-bytes + * [state] [\#2587](https://github.com/tendermint/tendermint/issues/2587) Require block.Time of the fist block to be genesis time + * [state] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Require block.Version to match state.Version + * [types] Update SignBytes for `Vote`/`Proposal`/`Heartbeat`: + * [\#2459](https://github.com/tendermint/tendermint/issues/2459) Use amino encoding instead of JSON in `SignBytes`. + * [\#2598](https://github.com/tendermint/tendermint/issues/2598) Reorder fields and use fixed sized encoding. + * [\#2598](https://github.com/tendermint/tendermint/issues/2598) Change `Type` field from `string` to `byte` and use new + `SignedMsgType` to enumerate. + * [types] [\#2730](https://github.com/tendermint/tendermint/issues/2730) Use + same order for fields in `Vote` as in the SignBytes + * [types] [\#2732](https://github.com/tendermint/tendermint/issues/2732) Remove the address field from the validator hash + * [types] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Add Version struct to Header + * [types] [\#2609](https://github.com/tendermint/tendermint/issues/2609) ConsensusParams.Hash() is the hash of the amino encoded + struct instead of the Merkle tree of the fields + * [types] [\#2670](https://github.com/tendermint/tendermint/issues/2670) Header.Hash() builds Merkle tree out of fields in the same + order they appear in the header, instead of sorting by field name + * [types] [\#2682](https://github.com/tendermint/tendermint/issues/2682) Use proto3 `varint` encoding for ints that are usually unsigned (instead of zigzag encoding). + * [types] [\#2636](https://github.com/tendermint/tendermint/issues/2636) Add Validator field to ConsensusParams + (Used to control which pubkey types validators can use, by abci type). + +* P2P Protocol + * [consensus] [\#2652](https://github.com/tendermint/tendermint/issues/2652) + Replace `CommitStepMessage` with `NewValidBlockMessage` + * [consensus] [\#2735](https://github.com/tendermint/tendermint/issues/2735) Simplify `Proposal` message to align with spec + * [consensus] [\#2730](https://github.com/tendermint/tendermint/issues/2730) + Add `Type` field to `Proposal` and use same order of fields as in the + SignBytes for both `Proposal` and `Vote` + * [p2p] [\#2654](https://github.com/tendermint/tendermint/issues/2654) Add `ProtocolVersion` struct with protocol versions to top of + DefaultNodeInfo and require `ProtocolVersion.Block` to match during peer handshake + + +### FEATURES: +- [abci] [\#2557](https://github.com/tendermint/tendermint/issues/2557) Add `Codespace` field to `Response{CheckTx, DeliverTx, Query}` +- [abci] [\#2662](https://github.com/tendermint/tendermint/issues/2662) Add `BlockVersion` and `P2PVersion` to `RequestInfo` +- [crypto/merkle] [\#2298](https://github.com/tendermint/tendermint/issues/2298) General Merkle Proof scheme for chaining various types of Merkle trees together + +### IMPROVEMENTS: +- Additional Metrics + - [consensus] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) + - [p2p] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) +- [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) Added ValidateBasic method, which performs basic checks +- [crypto/ed25519] [\#2558](https://github.com/tendermint/tendermint/issues/2558) Switch to use latest `golang.org/x/crypto` through our fork at + github.com/tendermint/crypto +- [libs/log] [\#2707](https://github.com/tendermint/tendermint/issues/2707) Add year to log format (@yutianwu) +- [tools] [\#2238](https://github.com/tendermint/tendermint/issues/2238) Binary dependencies are now locked to a specific git commit + +### BUG FIXES: +- [\#2711](https://github.com/tendermint/tendermint/issues/2711) Validate all incoming reactor messages. Fixes various bugs due to negative ints. +- [autofile] [\#2428](https://github.com/tendermint/tendermint/issues/2428) Group.RotateFile need call Flush() before rename (@goolAdapter) +- [common] [\#2533](https://github.com/tendermint/tendermint/issues/2533) Fixed a bug in the `BitArray.Or` method +- [common] [\#2506](https://github.com/tendermint/tendermint/issues/2506) Fixed a bug in the `BitArray.Sub` method (@james-ray) +- [common] [\#2534](https://github.com/tendermint/tendermint/issues/2534) Fix `BitArray.PickRandom` to choose uniformly from true bits +- [consensus] [\#1690](https://github.com/tendermint/tendermint/issues/1690) Wait for + timeoutPrecommit before starting next round +- [consensus] [\#1745](https://github.com/tendermint/tendermint/issues/1745) Wait for + Proposal or timeoutProposal before entering prevote +- [consensus] [\#2642](https://github.com/tendermint/tendermint/issues/2642) Only propose ValidBlock, not LockedBlock +- [consensus] [\#2642](https://github.com/tendermint/tendermint/issues/2642) Initialized ValidRound and LockedRound to -1 +- [consensus] [\#1637](https://github.com/tendermint/tendermint/issues/1637) Limit the amount of evidence that can be included in a + block +- [consensus] [\#2652](https://github.com/tendermint/tendermint/issues/2652) Ensure valid block property with faulty proposer +- [evidence] [\#2515](https://github.com/tendermint/tendermint/issues/2515) Fix db iter leak (@goolAdapter) +- [libs/event] [\#2518](https://github.com/tendermint/tendermint/issues/2518) Fix event concurrency flaw (@goolAdapter) +- [node] [\#2434](https://github.com/tendermint/tendermint/issues/2434) Make node respond to signal interrupts while sleeping for genesis time +- [state] [\#2616](https://github.com/tendermint/tendermint/issues/2616) Pass nil to NewValidatorSet() when genesis file's Validators field is nil +- [p2p] [\#2555](https://github.com/tendermint/tendermint/issues/2555) Fix p2p switch FlushThrottle value (@goolAdapter) +- [p2p] [\#2668](https://github.com/tendermint/tendermint/issues/2668) Reconnect to originally dialed address (not self-reported + address) for persistent peers + + ## v0.25.0 *September 22, 2018* diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index cad2f444a..f5e56a123 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -1,124 +1,27 @@ # Pending -## v0.26.0 +## v0.26.1 -*October 29, 2018* +*TBA* Special thanks to external contributors on this release: -@bradyjoestar, @connorwstein, @goolAdapter, @HaoyangLiu, -@james-ray, @overbool, @phymbert, @Slamper, @Uzair1995 - -This release is primarily about adding Version fields to various data structures, -optimizing consensus messages for signing and verification in -restricted environments (like HSMs and the Ethereum Virtual Machine), and -aligning the consensus code with the [specification](https://arxiv.org/abs/1807.04938). -It also includes our first take at a generalized merkle proof system. - -See the [UPGRADING.md](UPGRADING.md#v0.26.0) for details on upgrading to the new -version. - -Please note that we are still making breaking changes to the protocols. -While the new Version fields should help us to keep the software backwards compatible -even while upgrading the protocols, we cannot guarantee that new releases will -be compatible with old chains just yet. Thanks for bearing with us! Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint). ### BREAKING CHANGES: * CLI/RPC/Config - * [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) timeouts as time.Duration, not ints - * [config] [\#2505](https://github.com/tendermint/tendermint/issues/2505) Remove Mempool.RecheckEmpty (it was effectively useless anyways) - * [config] [\#2490](https://github.com/tendermint/tendermint/issues/2490) `mempool.wal` is disabled by default - * [privval] [\#2459](https://github.com/tendermint/tendermint/issues/2459) Split `SocketPVMsg`s implementations into Request and Response, where the Response may contain a error message (returned by the remote signer) - * [state] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Add Version field to State, breaking the format of State as - encoded on disk. - * [rpc] [\#2298](https://github.com/tendermint/tendermint/issues/2298) `/abci_query` takes `prove` argument instead of `trusted` and switches the default - behaviour to `prove=false` - * [rpc] [\#2654](https://github.com/tendermint/tendermint/issues/2654) Remove all `node_info.other.*_version` fields in `/status` and - `/net_info` * Apps - * [abci] [\#2298](https://github.com/tendermint/tendermint/issues/2298) ResponseQuery.Proof is now a structured merkle.Proof, not just - arbitrary bytes - * [abci] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Add Version to Header and shift all fields by one - * [abci] [\#2662](https://github.com/tendermint/tendermint/issues/2662) Bump the field numbers for some `ResponseInfo` fields to make room for - `AppVersion` * Go API - * [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) timeouts as time.Duration, not ints - * [crypto/merkle & lite] [\#2298](https://github.com/tendermint/tendermint/issues/2298) Various changes to accomodate General Merkle trees - * [crypto/merkle] [\#2595](https://github.com/tendermint/tendermint/issues/2595) Remove all Hasher objects in favor of byte slices - * [crypto/merkle] [\#2635](https://github.com/tendermint/tendermint/issues/2635) merkle.SimpleHashFromTwoHashes is no longer exported - * [node] [\#2479](https://github.com/tendermint/tendermint/issues/2479) Remove node.RunForever - * [rpc/client] [\#2298](https://github.com/tendermint/tendermint/issues/2298) `ABCIQueryOptions.Trusted` -> `ABCIQueryOptions.Prove` - * [types] [\#2298](https://github.com/tendermint/tendermint/issues/2298) Remove `Index` and `Total` fields from `TxProof`. - * [types] [\#2598](https://github.com/tendermint/tendermint/issues/2598) `VoteTypeXxx` are now of type `SignedMsgType byte` and named `XxxType`, eg. `PrevoteType`, - `PrecommitType`. * Blockchain Protocol - * [abci] [\#2636](https://github.com/tendermint/tendermint/issues/2636) Add ValidatorParams field to ConsensusParams. - (Used to control which pubkey types validators can use, by abci type) - * [types] Update SignBytes for `Vote`/`Proposal`/`Heartbeat`: - * [\#2459](https://github.com/tendermint/tendermint/issues/2459) Use amino encoding instead of JSON in `SignBytes`. - * [\#2598](https://github.com/tendermint/tendermint/issues/2598) Reorder fields and use fixed sized encoding. - * [\#2598](https://github.com/tendermint/tendermint/issues/2598) Change `Type` field fromt `string` to `byte` and use new - `SignedMsgType` to enumerate. - * [types] [\#2512](https://github.com/tendermint/tendermint/issues/2512) Remove the pubkey field from the validator hash - * [types] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Add Version struct to Header - * [types] [\#2609](https://github.com/tendermint/tendermint/issues/2609) ConsensusParams.Hash() is the hash of the amino encoded - struct instead of the Merkle tree of the fields - * [state] [\#2587](https://github.com/tendermint/tendermint/issues/2587) Require block.Time of the fist block to be genesis time - * [state] [\#2644](https://github.com/tendermint/tendermint/issues/2644) Require block.Version to match state.Version - * [types] [\#2670](https://github.com/tendermint/tendermint/issues/2670) Header.Hash() builds Merkle tree out of fields in the same - order they appear in the header, instead of sorting by field name - * [types] [\#2682](https://github.com/tendermint/tendermint/issues/2682) Use proto3 `varint` encoding for ints that are usually unsigned (instead of zigzag encoding). * P2P Protocol - * [p2p] [\#2654](https://github.com/tendermint/tendermint/issues/2654) Add `ProtocolVersion` struct with protocol versions to top of - DefaultNodeInfo and require `ProtocolVersion.Block` to match during peer handshake ### FEATURES: -- [abci] [\#2557](https://github.com/tendermint/tendermint/issues/2557) Add `Codespace` field to `Response{CheckTx, DeliverTx, Query}` -- [abci] [\#2662](https://github.com/tendermint/tendermint/issues/2662) Add `BlockVersion` and `P2PVersion` to `RequestInfo` -- [crypto/merkle] [\#2298](https://github.com/tendermint/tendermint/issues/2298) General Merkle Proof scheme for chaining various types of Merkle trees together ### IMPROVEMENTS: -- Additional Metrics - - [consensus] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) - - [p2p] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) -- [config] [\#2232](https://github.com/tendermint/tendermint/issues/2232) Added ValidateBasic method, which performs basic checks -- [crypto/ed25519] [\#2558](https://github.com/tendermint/tendermint/issues/2558) Switch to use latest `golang.org/x/crypto` through our fork at - github.com/tendermint/crypto -- [tools] [\#2238](https://github.com/tendermint/tendermint/issues/2238) Binary dependencies are now locked to a specific git commit -- [libs/log] [\#2706](https://github.com/tendermint/tendermint/issues/2706) Add year to log format -- [consensus] [\#2683] validate all incoming messages -- [evidence] [\#2683] validate all incoming messages -- [blockchain] [\#2683] validate all incoming messages -- [p2p/pex] [\#2683] validate pexAddrsMessage addresses ### BUG FIXES: -- [autofile] [\#2428](https://github.com/tendermint/tendermint/issues/2428) Group.RotateFile need call Flush() before rename (@goolAdapter) -- [common] [\#2533](https://github.com/tendermint/tendermint/issues/2533) Fixed a bug in the `BitArray.Or` method -- [common] [\#2506](https://github.com/tendermint/tendermint/issues/2506) Fixed a bug in the `BitArray.Sub` method (@james-ray) -- [common] [\#2534](https://github.com/tendermint/tendermint/issues/2534) Fix `BitArray.PickRandom` to choose uniformly from true bits -- [consensus] [\#1690](https://github.com/tendermint/tendermint/issues/1690) Wait for - timeoutPrecommit before starting next round -- [consensus] [\#1745](https://github.com/tendermint/tendermint/issues/1745) Wait for - Proposal or timeoutProposal before entering prevote -- [consensus] [\#2583](https://github.com/tendermint/tendermint/issues/2583) ensure valid - block property with faulty proposer -- [consensus] [\#2642](https://github.com/tendermint/tendermint/issues/2642) Only propose ValidBlock, not LockedBlock -- [consensus] [\#2642](https://github.com/tendermint/tendermint/issues/2642) Initialized ValidRound and LockedRound to -1 -- [consensus] [\#1637](https://github.com/tendermint/tendermint/issues/1637) Limit the amount of evidence that can be included in a - block -- [consensus] [\#2646](https://github.com/tendermint/tendermint/issues/2646) Simplify Proposal message (align with spec) -- [crypto] [\#2733](https://github.com/tendermint/tendermint/pull/2733) Fix general merkle keypath to start w/ last op's key -- [evidence] [\#2515](https://github.com/tendermint/tendermint/issues/2515) Fix db iter leak (@goolAdapter) -- [libs/event] [\#2518](https://github.com/tendermint/tendermint/issues/2518) Fix event concurrency flaw (@goolAdapter) -- [node] [\#2434](https://github.com/tendermint/tendermint/issues/2434) Make node respond to signal interrupts while sleeping for genesis time -- [state] [\#2616](https://github.com/tendermint/tendermint/issues/2616) Pass nil to NewValidatorSet() when genesis file's Validators field is nil -- [p2p] [\#2555](https://github.com/tendermint/tendermint/issues/2555) Fix p2p switch FlushThrottle value (@goolAdapter) -- [p2p] [\#2668](https://github.com/tendermint/tendermint/issues/2668) Reconnect to originally dialed address (not self-reported - address) for persistent peers - diff --git a/UPGRADING.md b/UPGRADING.md index cb0830a45..055dbec47 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -5,7 +5,7 @@ a newer version of Tendermint Core. ## v0.26.0 -New 0.26.0 release contains a lot of changes to core data types. It is not +New 0.26.0 release contains a lot of changes to core data types and protocols. It is not compatible to the old versions and there is no straight forward way to update old data to be compatible with the new version. @@ -33,7 +33,7 @@ to `prove`. To get proofs with your queries, ensure you set `prove=true`. Various version fields like `amino_version`, `p2p_version`, `consensus_version`, and `rpc_version` have been removed from the `node_info.other` and are consolidated under the tendermint semantic version (ie. `node_info.version`) and -the new `block` and `p2p` protocol versions under `node_info.protocol_version`.. +the new `block` and `p2p` protocol versions under `node_info.protocol_version`. ### ABCI Changes @@ -45,7 +45,7 @@ protobuf file for these changes. The `ResponseQuery.Proof` field is now structured as a `[]ProofOp` to support generalized Merkle tree constructions where the leaves of one Merkle tree are -the root of another. If you don't need this functionaluty, and you used to +the root of another. If you don't need this functionality, and you used to return `` here, you should instead return a single `ProofOp` with just the `Data` field set: @@ -79,6 +79,10 @@ The `node.RunForever` function was removed. Signal handling and running forever should instead be explicitly configured by the caller. See how we do it [here](https://github.com/tendermint/tendermint/blob/30519e8361c19f4bf320ef4d26288ebc621ad725/cmd/tendermint/commands/run_node.go#L60). +### Other + +All hashes, except for public key addresses, are now 32-bytes. + ## v0.25.0 This release has minimal impact. From 7246ffc48fa5a45daa5acddcf5b726b7bb6f259c Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 5 Nov 2018 22:32:52 -0800 Subject: [PATCH 31/35] mempool: ErrPreCheck and more log info (#2724) * mempool: ErrPreCheck and more log info * change Pre/PostCheckFunc to return errors also, continue execution when checking txs in mempool_test if err=PreCheckErr --- mempool/mempool.go | 62 +++++++++++++++++++++++++++++++++-------- mempool/mempool_test.go | 54 +++++++++++++---------------------- 2 files changed, 69 insertions(+), 47 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 65cd55354..5e52989aa 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -25,12 +25,12 @@ import ( // PreCheckFunc is an optional filter executed before CheckTx and rejects // transaction if false is returned. An example would be to ensure that a // transaction doesn't exceeded the block size. -type PreCheckFunc func(types.Tx) bool +type PreCheckFunc func(types.Tx) error // PostCheckFunc is an optional filter executed after CheckTx and rejects // transaction if false is returned. An example would be to ensure a // transaction doesn't require more gas than available for the block. -type PostCheckFunc func(types.Tx, *abci.ResponseCheckTx) bool +type PostCheckFunc func(types.Tx, *abci.ResponseCheckTx) error /* @@ -68,24 +68,48 @@ var ( ErrMempoolIsFull = errors.New("Mempool is full") ) +// ErrPreCheck is returned when tx is too big +type ErrPreCheck struct { + Reason error +} + +func (e ErrPreCheck) Error() string { + return e.Reason.Error() +} + +// IsPreCheckError returns true if err is due to pre check failure. +func IsPreCheckError(err error) bool { + _, ok := err.(ErrPreCheck) + return ok +} + // PreCheckAminoMaxBytes checks that the size of the transaction plus the amino // overhead is smaller or equal to the expected maxBytes. func PreCheckAminoMaxBytes(maxBytes int64) PreCheckFunc { - return func(tx types.Tx) bool { + return func(tx types.Tx) error { // We have to account for the amino overhead in the tx size as well aminoOverhead := amino.UvarintSize(uint64(len(tx))) - return int64(len(tx)+aminoOverhead) <= maxBytes + txSize := int64(len(tx) + aminoOverhead) + if txSize > maxBytes { + return fmt.Errorf("Tx size (including amino overhead) is too big: %d, max: %d", + txSize, maxBytes) + } + return nil } } // PostCheckMaxGas checks that the wanted gas is smaller or equal to the passed -// maxGas. Returns true if maxGas is -1. +// maxGas. Returns nil if maxGas is -1. func PostCheckMaxGas(maxGas int64) PostCheckFunc { - return func(tx types.Tx, res *abci.ResponseCheckTx) bool { + return func(tx types.Tx, res *abci.ResponseCheckTx) error { if maxGas == -1 { - return true + return nil } - return res.GasWanted <= maxGas + if res.GasWanted > maxGas { + return fmt.Errorf("gas wanted %d is greater than max gas %d", + res.GasWanted, maxGas) + } + return nil } } @@ -285,8 +309,10 @@ func (mem *Mempool) CheckTx(tx types.Tx, cb func(*abci.Response)) (err error) { return ErrMempoolIsFull } - if mem.preCheck != nil && !mem.preCheck(tx) { - return + if mem.preCheck != nil { + if err := mem.preCheck(tx); err != nil { + return ErrPreCheck{err} + } } // CACHE @@ -346,7 +372,13 @@ func (mem *Mempool) resCbNormal(req *abci.Request, res *abci.Response) { tx: tx, } mem.txs.PushBack(memTx) - mem.logger.Info("Added good transaction", "tx", TxID(tx), "res", r, "total", mem.Size()) + mem.logger.Info("Added good transaction", + "tx", TxID(tx), + "res", r, + "height", memTx.height, + "total", mem.Size(), + "counter", memTx.counter, + ) mem.metrics.TxSizeBytes.Observe(float64(len(tx))) mem.notifyTxsAvailable() } else { @@ -566,7 +598,13 @@ func (mem *Mempool) recheckTxs(goodTxs []types.Tx) { } func (mem *Mempool) isPostCheckPass(tx types.Tx, r *abci.ResponseCheckTx) bool { - return mem.postCheck == nil || mem.postCheck(tx, r) + if mem.postCheck == nil { + return true + } + if err := mem.postCheck(tx, r); err != nil { + return false + } + return true } //-------------------------------------------------------------------------------- diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 5aabd00ee..44917afba 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -14,7 +14,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - amino "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/abci/example/counter" "github.com/tendermint/tendermint/abci/example/kvstore" abci "github.com/tendermint/tendermint/abci/types" @@ -66,7 +65,10 @@ func checkTxs(t *testing.T, mempool *Mempool, count int) types.Txs { t.Error(err) } if err := mempool.CheckTx(txBytes, nil); err != nil { - t.Fatalf("Error after CheckTx: %v", err) + if IsPreCheckError(err) { + continue + } + t.Fatalf("CheckTx failed: %v while checking #%d tx", err, i) } } return txs @@ -126,47 +128,29 @@ func TestMempoolFilters(t *testing.T) { mempool := newMempoolWithApp(cc) emptyTxArr := []types.Tx{[]byte{}} - nopPreFilter := func(tx types.Tx) bool { return true } - nopPostFilter := func(tx types.Tx, res *abci.ResponseCheckTx) bool { return true } - - // This is the same filter we expect to be used within node/node.go and state/execution.go - nBytePreFilter := func(n int) func(tx types.Tx) bool { - return func(tx types.Tx) bool { - // We have to account for the amino overhead in the tx size as well - aminoOverhead := amino.UvarintSize(uint64(len(tx))) - return (len(tx) + aminoOverhead) <= n - } - } - - nGasPostFilter := func(n int64) func(tx types.Tx, res *abci.ResponseCheckTx) bool { - return func(tx types.Tx, res *abci.ResponseCheckTx) bool { - if n == -1 { - return true - } - return res.GasWanted <= n - } - } + nopPreFilter := func(tx types.Tx) error { return nil } + nopPostFilter := func(tx types.Tx, res *abci.ResponseCheckTx) error { return nil } // each table driven test creates numTxsToCreate txs with checkTx, and at the end clears all remaining txs. // each tx has 20 bytes + amino overhead = 21 bytes, 1 gas tests := []struct { numTxsToCreate int - preFilter func(tx types.Tx) bool - postFilter func(tx types.Tx, res *abci.ResponseCheckTx) bool + preFilter PreCheckFunc + postFilter PostCheckFunc expectedNumTxs int }{ {10, nopPreFilter, nopPostFilter, 10}, - {10, nBytePreFilter(10), nopPostFilter, 0}, - {10, nBytePreFilter(20), nopPostFilter, 0}, - {10, nBytePreFilter(21), nopPostFilter, 10}, - {10, nopPreFilter, nGasPostFilter(-1), 10}, - {10, nopPreFilter, nGasPostFilter(0), 0}, - {10, nopPreFilter, nGasPostFilter(1), 10}, - {10, nopPreFilter, nGasPostFilter(3000), 10}, - {10, nBytePreFilter(10), nGasPostFilter(20), 0}, - {10, nBytePreFilter(30), nGasPostFilter(20), 10}, - {10, nBytePreFilter(21), nGasPostFilter(1), 10}, - {10, nBytePreFilter(21), nGasPostFilter(0), 0}, + {10, PreCheckAminoMaxBytes(10), nopPostFilter, 0}, + {10, PreCheckAminoMaxBytes(20), nopPostFilter, 0}, + {10, PreCheckAminoMaxBytes(21), nopPostFilter, 10}, + {10, nopPreFilter, PostCheckMaxGas(-1), 10}, + {10, nopPreFilter, PostCheckMaxGas(0), 0}, + {10, nopPreFilter, PostCheckMaxGas(1), 10}, + {10, nopPreFilter, PostCheckMaxGas(3000), 10}, + {10, PreCheckAminoMaxBytes(10), PostCheckMaxGas(20), 0}, + {10, PreCheckAminoMaxBytes(30), PostCheckMaxGas(20), 10}, + {10, PreCheckAminoMaxBytes(21), PostCheckMaxGas(1), 10}, + {10, PreCheckAminoMaxBytes(21), PostCheckMaxGas(0), 0}, } for tcIndex, tt := range tests { mempool.Update(1, emptyTxArr, tt.preFilter, tt.postFilter) From b8a9b0bf782c17d97af3fda46ddc73f7d35bd680 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 6 Nov 2018 07:39:05 +0100 Subject: [PATCH 32/35] Mempool WAL is still created by default in home directory, leads to permission errors (#2758) * only invoke InitWAL/CloseWAL if WalPath is not empty Closes #2717 * panic if WAL is not initialized when calling CloseWAL * add a changelog entry --- CHANGELOG_PENDING.md | 1 + config/config.go | 5 +++++ mempool/mempool.go | 46 ++++++++++++++++++----------------------- mempool/mempool_test.go | 7 ++----- node/node.go | 11 ++++++++-- 5 files changed, 37 insertions(+), 33 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index f5e56a123..ea0a666bd 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -25,3 +25,4 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi ### IMPROVEMENTS: ### BUG FIXES: +- [mempool] fix a bug where we create a WAL despite `wal_dir` being empty diff --git a/config/config.go b/config/config.go index ede57207c..fa6182114 100644 --- a/config/config.go +++ b/config/config.go @@ -497,6 +497,11 @@ func (cfg *MempoolConfig) WalDir() string { return rootify(cfg.WalPath, cfg.RootDir) } +// WalEnabled returns true if the WAL is enabled. +func (cfg *MempoolConfig) WalEnabled() bool { + return cfg.WalPath != "" +} + // ValidateBasic performs basic validation (checking param bounds, etc.) and // returns an error if any check fails. func (cfg *MempoolConfig) ValidateBasic() error { diff --git a/mempool/mempool.go b/mempool/mempool.go index 5e52989aa..9c9563165 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -213,39 +213,33 @@ func WithMetrics(metrics *Metrics) MempoolOption { return func(mem *Mempool) { mem.metrics = metrics } } +// InitWAL creates a directory for the WAL file and opens a file itself. +// +// *panics* if can't create directory or open file. +// *not thread safe* +func (mem *Mempool) InitWAL() { + walDir := mem.config.WalDir() + err := cmn.EnsureDir(walDir, 0700) + if err != nil { + panic(errors.Wrap(err, "Error ensuring Mempool WAL dir")) + } + af, err := auto.OpenAutoFile(walDir + "/wal") + if err != nil { + panic(errors.Wrap(err, "Error opening Mempool WAL file")) + } + mem.wal = af +} + // CloseWAL closes and discards the underlying WAL file. // Any further writes will not be relayed to disk. -func (mem *Mempool) CloseWAL() bool { - if mem == nil { - return false - } - +func (mem *Mempool) CloseWAL() { mem.proxyMtx.Lock() defer mem.proxyMtx.Unlock() - if mem.wal == nil { - return false - } - if err := mem.wal.Close(); err != nil && mem.logger != nil { - mem.logger.Error("Mempool.CloseWAL", "err", err) + if err := mem.wal.Close(); err != nil { + mem.logger.Error("Error closing WAL", "err", err) } mem.wal = nil - return true -} - -func (mem *Mempool) InitWAL() { - walDir := mem.config.WalDir() - if walDir != "" { - err := cmn.EnsureDir(walDir, 0700) - if err != nil { - cmn.PanicSanity(errors.Wrap(err, "Error ensuring Mempool wal dir")) - } - af, err := auto.OpenAutoFile(walDir + "/wal") - if err != nil { - cmn.PanicSanity(errors.Wrap(err, "Error opening Mempool wal file")) - } - mem.wal = af - } } // Lock locks the mempool. The consensus must be able to hold lock to safely update. diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 44917afba..b8df6f737 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -369,15 +369,12 @@ func TestMempoolCloseWAL(t *testing.T) { // 7. Invoke CloseWAL() and ensure it discards the // WAL thus any other write won't go through. - require.True(t, mempool.CloseWAL(), "CloseWAL should CloseWAL") + mempool.CloseWAL() mempool.CheckTx(types.Tx([]byte("bar")), nil) sum2 := checksumFile(walFilepath, t) require.Equal(t, sum1, sum2, "expected no change to the WAL after invoking CloseWAL() since it was discarded") - // 8. Second CloseWAL should do nothing - require.False(t, mempool.CloseWAL(), "CloseWAL should CloseWAL") - - // 9. Sanity check to ensure that the WAL file still exists + // 8. Sanity check to ensure that the WAL file still exists m3, err := filepath.Glob(filepath.Join(rootDir, "*")) require.Nil(t, err, "successful globbing expected") require.Equal(t, 1, len(m3), "expecting the wal match in") diff --git a/node/node.go b/node/node.go index f62a8b472..4710397fa 100644 --- a/node/node.go +++ b/node/node.go @@ -13,8 +13,8 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/tendermint/go-amino" + amino "github.com/tendermint/go-amino" abci "github.com/tendermint/tendermint/abci/types" bc "github.com/tendermint/tendermint/blockchain" cfg "github.com/tendermint/tendermint/config" @@ -279,7 +279,9 @@ func NewNode(config *cfg.Config, ) mempoolLogger := logger.With("module", "mempool") mempool.SetLogger(mempoolLogger) - mempool.InitWAL() // no need to have the mempool wal during tests + if config.Mempool.WalEnabled() { + mempool.InitWAL() // no need to have the mempool wal during tests + } mempoolReactor := mempl.NewMempoolReactor(config.Mempool, mempool) mempoolReactor.SetLogger(mempoolLogger) @@ -586,6 +588,11 @@ func (n *Node) OnStop() { // TODO: gracefully disconnect from peers. n.sw.Stop() + // stop mempool WAL + if n.config.Mempool.WalEnabled() { + n.mempoolReactor.Mempool.CloseWAL() + } + if err := n.transport.Close(); err != nil { n.Logger.Error("Error closing transport", "err", err) } From 03e42d2e3866f01a00625f608e3bbfaeb30690de Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 5 Nov 2018 22:53:44 -0800 Subject: [PATCH 33/35] =?UTF-8?q?Fix=20crypto/merkle=20ProofOperators.Veri?= =?UTF-8?q?fy=20to=20check=20bounds=20on=20keypath=20pa=E2=80=A6=20(#2756)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix crypto/merkle ProofOperators.Verify to check bounds on keypath parts. * Update PENDING --- CHANGELOG_PENDING.md | 2 ++ crypto/merkle/proof.go | 3 +++ crypto/merkle/proof_test.go | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index ea0a666bd..68a550398 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -25,4 +25,6 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi ### IMPROVEMENTS: ### BUG FIXES: + +- [crypto/merkle] [\#2756](https://github.com/tendermint/tendermint/issues/2756) Fix crypto/merkle ProofOperators.Verify to check bounds on keypath parts. - [mempool] fix a bug where we create a WAL despite `wal_dir` being empty diff --git a/crypto/merkle/proof.go b/crypto/merkle/proof.go index 5705c96bd..8f8b460c9 100644 --- a/crypto/merkle/proof.go +++ b/crypto/merkle/proof.go @@ -43,6 +43,9 @@ func (poz ProofOperators) Verify(root []byte, keypath string, args [][]byte) (er for i, op := range poz { key := op.GetKey() if len(key) != 0 { + if len(keys) == 0 { + return cmn.NewError("Key path has insufficient # of parts: expected no more keys but got %+v", string(key)) + } lastKey := keys[len(keys)-1] if !bytes.Equal(lastKey, key) { return cmn.NewError("Key mismatch on operation #%d: expected %+v but got %+v", i, string(lastKey), string(key)) diff --git a/crypto/merkle/proof_test.go b/crypto/merkle/proof_test.go index cc208e9a1..320b9188a 100644 --- a/crypto/merkle/proof_test.go +++ b/crypto/merkle/proof_test.go @@ -107,6 +107,10 @@ func TestProofOperators(t *testing.T) { err = popz.Verify(bz("OUTPUT4"), "//KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) assert.NotNil(t, err) + // BAD KEY 5 + err = popz.Verify(bz("OUTPUT4"), "/KEY2/KEY1", [][]byte{bz("INPUT1")}) + assert.NotNil(t, err) + // BAD OUTPUT 1 err = popz.Verify(bz("OUTPUT4_WRONG"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) assert.NotNil(t, err) From d460df1335fb3e0af2a9346c16cc35013552ba5d Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 7 Nov 2018 05:23:44 +0100 Subject: [PATCH 34/35] mempool: print postCheck error (#2762) This is a follow-up from https://github.com/tendermint/tendermint/pull/2724 Closes #2761 --- mempool/mempool.go | 29 ++++++++++++++--------------- mempool/mempool_test.go | 3 +++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 9c9563165..15e3119c4 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -356,8 +356,11 @@ func (mem *Mempool) resCbNormal(req *abci.Request, res *abci.Response) { switch r := res.Value.(type) { case *abci.Response_CheckTx: tx := req.GetCheckTx().Tx - if (r.CheckTx.Code == abci.CodeTypeOK) && - mem.isPostCheckPass(tx, r.CheckTx) { + var postCheckErr error + if mem.postCheck != nil { + postCheckErr = mem.postCheck(tx, r.CheckTx) + } + if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { mem.counter++ memTx := &mempoolTx{ counter: mem.counter, @@ -377,7 +380,7 @@ func (mem *Mempool) resCbNormal(req *abci.Request, res *abci.Response) { mem.notifyTxsAvailable() } else { // ignore bad transaction - mem.logger.Info("Rejected bad transaction", "tx", TxID(tx), "res", r) + mem.logger.Info("Rejected bad transaction", "tx", TxID(tx), "res", r, "err", postCheckErr) mem.metrics.FailedTxs.Add(1) // remove from cache (it might be good later) mem.cache.Remove(tx) @@ -390,6 +393,7 @@ func (mem *Mempool) resCbNormal(req *abci.Request, res *abci.Response) { func (mem *Mempool) resCbRecheck(req *abci.Request, res *abci.Response) { switch r := res.Value.(type) { case *abci.Response_CheckTx: + tx := req.GetCheckTx().Tx memTx := mem.recheckCursor.Value.(*mempoolTx) if !bytes.Equal(req.GetCheckTx().Tx, memTx.tx) { cmn.PanicSanity( @@ -400,15 +404,20 @@ func (mem *Mempool) resCbRecheck(req *abci.Request, res *abci.Response) { ), ) } - if (r.CheckTx.Code == abci.CodeTypeOK) && mem.isPostCheckPass(memTx.tx, r.CheckTx) { + var postCheckErr error + if mem.postCheck != nil { + postCheckErr = mem.postCheck(tx, r.CheckTx) + } + if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { // Good, nothing to do. } else { // Tx became invalidated due to newly committed block. + mem.logger.Info("Tx is no longer valid", "tx", TxID(tx), "res", r, "err", postCheckErr) mem.txs.Remove(mem.recheckCursor) mem.recheckCursor.DetachPrev() // remove from cache (it might be good later) - mem.cache.Remove(req.GetCheckTx().Tx) + mem.cache.Remove(tx) } if mem.recheckCursor == mem.recheckEnd { mem.recheckCursor = nil @@ -591,16 +600,6 @@ func (mem *Mempool) recheckTxs(goodTxs []types.Tx) { mem.proxyAppConn.FlushAsync() } -func (mem *Mempool) isPostCheckPass(tx types.Tx, r *abci.ResponseCheckTx) bool { - if mem.postCheck == nil { - return true - } - if err := mem.postCheck(tx, r); err != nil { - return false - } - return true -} - //-------------------------------------------------------------------------------- // mempoolTx is a transaction that successfully ran diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index b8df6f737..e25da7fed 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -65,6 +65,9 @@ func checkTxs(t *testing.T, mempool *Mempool, count int) types.Txs { t.Error(err) } if err := mempool.CheckTx(txBytes, nil); err != nil { + // Skip invalid txs. + // TestMempoolFilters will fail otherwise. It asserts a number of txs + // returned. if IsPreCheckError(err) { continue } From 6e9aee546061423864fef3f9fa332ef37c3dca96 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 6 Nov 2018 21:12:46 -0800 Subject: [PATCH 35/35] p2p: peer-id -> peer_id (#2771) * p2p: peer-id -> peer_id * update changelog --- CHANGELOG_PENDING.md | 1 + p2p/peer.go | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 68a550398..1996bfcc4 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -28,3 +28,4 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [crypto/merkle] [\#2756](https://github.com/tendermint/tendermint/issues/2756) Fix crypto/merkle ProofOperators.Verify to check bounds on keypath parts. - [mempool] fix a bug where we create a WAL despite `wal_dir` being empty +- [p2p] \#2771 Fix `peer-id` label name in prometheus metrics diff --git a/p2p/peer.go b/p2p/peer.go index 944174b0e..e98c16d26 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -240,7 +240,7 @@ func (p *peer) Send(chID byte, msgBytes []byte) bool { } res := p.mconn.Send(chID, msgBytes) if res { - p.metrics.PeerSendBytesTotal.With("peer-id", string(p.ID())).Add(float64(len(msgBytes))) + p.metrics.PeerSendBytesTotal.With("peer_id", string(p.ID())).Add(float64(len(msgBytes))) } return res } @@ -255,7 +255,7 @@ func (p *peer) TrySend(chID byte, msgBytes []byte) bool { } res := p.mconn.TrySend(chID, msgBytes) if res { - p.metrics.PeerSendBytesTotal.With("peer-id", string(p.ID())).Add(float64(len(msgBytes))) + p.metrics.PeerSendBytesTotal.With("peer_id", string(p.ID())).Add(float64(len(msgBytes))) } return res } @@ -330,7 +330,7 @@ func (p *peer) metricsReporter() { sendQueueSize += float64(chStatus.SendQueueSize) } - p.metrics.PeerPendingSendBytes.With("peer-id", string(p.ID())).Set(sendQueueSize) + p.metrics.PeerPendingSendBytes.With("peer_id", string(p.ID())).Set(sendQueueSize) case <-p.Quit(): return }