You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
8.4 KiB

max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 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")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 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")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 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")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 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")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 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")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
  1. package types
  2. import (
  3. "math"
  4. "testing"
  5. "time"
  6. "github.com/gogo/protobuf/proto"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. "github.com/tendermint/tendermint/crypto"
  10. "github.com/tendermint/tendermint/crypto/ed25519"
  11. "github.com/tendermint/tendermint/crypto/tmhash"
  12. tmproto "github.com/tendermint/tendermint/proto/types"
  13. )
  14. func examplePrevote() *Vote {
  15. return exampleVote(byte(tmproto.PrevoteType))
  16. }
  17. func examplePrecommit() *Vote {
  18. return exampleVote(byte(tmproto.PrecommitType))
  19. }
  20. func exampleVote(t byte) *Vote {
  21. var stamp, err = time.Parse(TimeFormat, "2017-12-25T03:00:01.234Z")
  22. if err != nil {
  23. panic(err)
  24. }
  25. return &Vote{
  26. Type: tmproto.SignedMsgType(t),
  27. Height: 12345,
  28. Round: 2,
  29. Timestamp: stamp,
  30. BlockID: BlockID{
  31. Hash: tmhash.Sum([]byte("blockID_hash")),
  32. PartsHeader: PartSetHeader{
  33. Total: 1000000,
  34. Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
  35. },
  36. },
  37. ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
  38. ValidatorIndex: 56789,
  39. }
  40. }
  41. func TestVoteSignable(t *testing.T) {
  42. vote := examplePrecommit()
  43. v := vote.ToProto()
  44. signBytes := VoteSignBytes("test_chain_id", v)
  45. pb := CanonicalizeVote("test_chain_id", v)
  46. expected, err := proto.Marshal(&pb)
  47. require.NoError(t, err)
  48. require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Vote.")
  49. }
  50. func TestVoteSignBytesTestVectors(t *testing.T) {
  51. tests := []struct {
  52. chainID string
  53. vote *Vote
  54. want []byte
  55. }{
  56. 0: {
  57. "", &Vote{},
  58. // NOTE: Height and Round are skipped here. This case needs to be considered while parsing.
  59. []byte{0x2a, 0x2, 0x12, 0x0, 0x32, 0xb, 0x8, 0x80, 0x92, 0xb8,
  60. 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
  61. },
  62. // with proper (fixed size) height and round (PreCommit):
  63. 1: {
  64. "", &Vote{Height: 1, Round: 1, Type: tmproto.PrecommitType},
  65. []byte{0x8, 0x2, 0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32,
  66. 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
  67. },
  68. // with proper (fixed size) height and round (PreVote):
  69. 2: {
  70. "", &Vote{Height: 1, Round: 1, Type: tmproto.PrevoteType},
  71. []byte{0x8, 0x1, 0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0,
  72. 0x32, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
  73. },
  74. 3: {
  75. "", &Vote{Height: 1, Round: 1},
  76. []byte{0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32, 0xb,
  77. 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
  78. },
  79. // containing non-empty chain_id:
  80. 4: {
  81. "test_chain_id", &Vote{Height: 1, Round: 1},
  82. []byte{0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32, 0xb, 0x8,
  83. 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, 0x3a, 0xd,
  84. 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64},
  85. },
  86. }
  87. for i, tc := range tests {
  88. v := tc.vote.ToProto()
  89. got := VoteSignBytes(tc.chainID, v)
  90. require.Equal(t, tc.want, got, "test case #%v: got unexpected sign bytes for Vote.", i)
  91. }
  92. }
  93. func TestVoteProposalNotEq(t *testing.T) {
  94. cv := CanonicalizeVote("", &tmproto.Vote{Height: 1, Round: 1})
  95. p := CanonicalizeProposal("", &tmproto.Proposal{Height: 1, Round: 1})
  96. vb, err := proto.Marshal(&cv)
  97. require.NoError(t, err)
  98. pb, err := proto.Marshal(&p)
  99. require.NoError(t, err)
  100. require.NotEqual(t, vb, pb)
  101. }
  102. func TestVoteVerifySignature(t *testing.T) {
  103. privVal := NewMockPV()
  104. pubkey, err := privVal.GetPubKey()
  105. require.NoError(t, err)
  106. vote := examplePrecommit()
  107. v := vote.ToProto()
  108. signBytes := VoteSignBytes("test_chain_id", v)
  109. // sign it
  110. err = privVal.SignVote("test_chain_id", v)
  111. require.NoError(t, err)
  112. // verify the same vote
  113. valid := pubkey.VerifyBytes(VoteSignBytes("test_chain_id", v), v.Signature)
  114. require.True(t, valid)
  115. // serialize, deserialize and verify again....
  116. precommit := new(tmproto.Vote)
  117. bs, err := proto.Marshal(v)
  118. require.NoError(t, err)
  119. err = proto.Unmarshal(bs, precommit)
  120. require.NoError(t, err)
  121. // verify the transmitted vote
  122. newSignBytes := VoteSignBytes("test_chain_id", precommit)
  123. require.Equal(t, string(signBytes), string(newSignBytes))
  124. valid = pubkey.VerifyBytes(newSignBytes, precommit.Signature)
  125. require.True(t, valid)
  126. }
  127. func TestIsVoteTypeValid(t *testing.T) {
  128. tc := []struct {
  129. name string
  130. in tmproto.SignedMsgType
  131. out bool
  132. }{
  133. {"Prevote", tmproto.PrevoteType, true},
  134. {"Precommit", tmproto.PrecommitType, true},
  135. {"InvalidType", tmproto.SignedMsgType(0x3), false},
  136. }
  137. for _, tt := range tc {
  138. tt := tt
  139. t.Run(tt.name, func(st *testing.T) {
  140. if rs := IsVoteTypeValid(tt.in); rs != tt.out {
  141. t.Errorf("got unexpected Vote type. Expected:\n%v\nGot:\n%v", rs, tt.out)
  142. }
  143. })
  144. }
  145. }
  146. func TestVoteVerify(t *testing.T) {
  147. privVal := NewMockPV()
  148. pubkey, err := privVal.GetPubKey()
  149. require.NoError(t, err)
  150. vote := examplePrevote()
  151. vote.ValidatorAddress = pubkey.Address()
  152. err = vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey())
  153. if assert.Error(t, err) {
  154. assert.Equal(t, ErrVoteInvalidValidatorAddress, err)
  155. }
  156. err = vote.Verify("test_chain_id", pubkey)
  157. if assert.Error(t, err) {
  158. assert.Equal(t, ErrVoteInvalidSignature, err)
  159. }
  160. }
  161. func TestMaxVoteBytes(t *testing.T) {
  162. // time is varint encoded so need to pick the max.
  163. // year int, month Month, day, hour, min, sec, nsec int, loc *Location
  164. timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
  165. vote := &Vote{
  166. ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
  167. ValidatorIndex: math.MaxInt32,
  168. Height: math.MaxInt64,
  169. Round: math.MaxInt32,
  170. Timestamp: timestamp,
  171. Type: tmproto.PrevoteType,
  172. BlockID: BlockID{
  173. Hash: tmhash.Sum([]byte("blockID_hash")),
  174. PartsHeader: PartSetHeader{
  175. Total: math.MaxInt32,
  176. Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
  177. },
  178. },
  179. }
  180. v := vote.ToProto()
  181. privVal := NewMockPV()
  182. err := privVal.SignVote("test_chain_id", v)
  183. require.NoError(t, err)
  184. bz, err := proto.Marshal(v)
  185. require.NoError(t, err)
  186. assert.EqualValues(t, MaxVoteBytes, len(bz))
  187. }
  188. func TestVoteString(t *testing.T) {
  189. str := examplePrecommit().String()
  190. expected := `Vote{56789:6AF1F4111082 12345/02/PRECOMMIT_TYPE(Precommit) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests
  191. if str != expected {
  192. t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str)
  193. }
  194. str2 := examplePrevote().String()
  195. expected = `Vote{56789:6AF1F4111082 12345/02/PREVOTE_TYPE(Prevote) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests
  196. if str2 != expected {
  197. t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str2)
  198. }
  199. }
  200. func TestVoteValidateBasic(t *testing.T) {
  201. privVal := NewMockPV()
  202. testCases := []struct {
  203. testName string
  204. malleateVote func(*Vote)
  205. expectErr bool
  206. }{
  207. {"Good Vote", func(v *Vote) {}, false},
  208. {"Negative Height", func(v *Vote) { v.Height = -1 }, true},
  209. {"Negative Round", func(v *Vote) { v.Round = -1 }, true},
  210. {"Invalid BlockID", func(v *Vote) {
  211. v.BlockID = BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}}
  212. }, true},
  213. {"Invalid Address", func(v *Vote) { v.ValidatorAddress = make([]byte, 1) }, true},
  214. {"Invalid ValidatorIndex", func(v *Vote) { v.ValidatorIndex = -1 }, true},
  215. {"Invalid Signature", func(v *Vote) { v.Signature = nil }, true},
  216. {"Too big Signature", func(v *Vote) { v.Signature = make([]byte, MaxSignatureSize+1) }, true},
  217. }
  218. for _, tc := range testCases {
  219. tc := tc
  220. t.Run(tc.testName, func(t *testing.T) {
  221. vote := examplePrecommit()
  222. v := vote.ToProto()
  223. err := privVal.SignVote("test_chain_id", v)
  224. vote.Signature = v.Signature
  225. require.NoError(t, err)
  226. tc.malleateVote(vote)
  227. assert.Equal(t, tc.expectErr, vote.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  228. })
  229. }
  230. }
  231. func TestVoteProtobuf(t *testing.T) {
  232. privVal := NewMockPV()
  233. vote := examplePrecommit()
  234. v := vote.ToProto()
  235. err := privVal.SignVote("test_chain_id", v)
  236. vote.Signature = v.Signature
  237. require.NoError(t, err)
  238. testCases := []struct {
  239. msg string
  240. v1 *Vote
  241. expPass bool
  242. }{
  243. {"success", vote, true},
  244. {"fail vote validate basic", &Vote{}, false},
  245. {"failure nil", nil, false},
  246. }
  247. for _, tc := range testCases {
  248. protoProposal := tc.v1.ToProto()
  249. v, err := VoteFromProto(protoProposal)
  250. if tc.expPass {
  251. require.NoError(t, err)
  252. require.Equal(t, tc.v1, v, tc.msg)
  253. } else {
  254. require.Error(t, err)
  255. }
  256. }
  257. }