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.

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