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.

277 lines
9.3 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
  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/tmhash"
  10. tmrand "github.com/tendermint/tendermint/libs/rand"
  11. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  12. )
  13. type voteData struct {
  14. vote1 *Vote
  15. vote2 *Vote
  16. valid bool
  17. }
  18. var defaultVoteTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
  19. func TestDuplicateVoteEvidence(t *testing.T) {
  20. val := NewMockPV()
  21. val2 := NewMockPV()
  22. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  23. blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
  24. blockID3 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash"))
  25. blockID4 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash2"))
  26. const chainID = "mychain"
  27. vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime)
  28. v1 := vote1.ToProto()
  29. err := val.SignVote(chainID, v1)
  30. require.NoError(t, err)
  31. badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime)
  32. bv := badVote.ToProto()
  33. err = val2.SignVote(chainID, bv)
  34. require.NoError(t, err)
  35. vote1.Signature = v1.Signature
  36. badVote.Signature = bv.Signature
  37. cases := []voteData{
  38. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, defaultVoteTime), true}, // different block ids
  39. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3, defaultVoteTime), true},
  40. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID4, defaultVoteTime), true},
  41. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime), false}, // wrong block id
  42. {vote1, makeVote(t, val, "mychain2", 0, 10, 2, 1, blockID2, defaultVoteTime), false}, // wrong chain id
  43. {vote1, makeVote(t, val, chainID, 0, 11, 2, 1, blockID2, defaultVoteTime), false}, // wrong height
  44. {vote1, makeVote(t, val, chainID, 0, 10, 3, 1, blockID2, defaultVoteTime), false}, // wrong round
  45. {vote1, makeVote(t, val, chainID, 0, 10, 2, 2, blockID2, defaultVoteTime), false}, // wrong step
  46. {vote1, makeVote(t, val2, chainID, 0, 10, 2, 1, blockID, defaultVoteTime), false}, // wrong validator
  47. {vote1, makeVote(t, val2, chainID, 0, 10, 2, 1, blockID, time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)), false},
  48. {vote1, badVote, false}, // signed by wrong key
  49. }
  50. pubKey, err := val.GetPubKey()
  51. require.NoError(t, err)
  52. for _, c := range cases {
  53. ev := &DuplicateVoteEvidence{
  54. VoteA: c.vote1,
  55. VoteB: c.vote2,
  56. Timestamp: defaultVoteTime,
  57. }
  58. if c.valid {
  59. assert.Nil(t, ev.Verify(chainID, pubKey), "evidence should be valid")
  60. } else {
  61. assert.NotNil(t, ev.Verify(chainID, pubKey), "evidence should be invalid")
  62. }
  63. }
  64. ev := randomDuplicatedVoteEvidence(t)
  65. assert.True(t, ev.Equal(ev))
  66. assert.False(t, ev.Equal(&DuplicateVoteEvidence{}))
  67. }
  68. func TestEvidenceList(t *testing.T) {
  69. ev := randomDuplicatedVoteEvidence(t)
  70. evl := EvidenceList([]Evidence{ev})
  71. assert.NotNil(t, evl.Hash())
  72. assert.True(t, evl.Has(ev))
  73. assert.False(t, evl.Has(&DuplicateVoteEvidence{}))
  74. }
  75. func TestMaxEvidenceBytes(t *testing.T) {
  76. val := NewMockPV()
  77. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  78. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  79. maxTime := time.Date(9999, 0, 0, 0, 0, 0, 0, time.UTC)
  80. const chainID = "mychain"
  81. ev := &DuplicateVoteEvidence{
  82. VoteA: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, math.MaxInt64, blockID, maxTime),
  83. VoteB: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, math.MaxInt64, blockID2, maxTime),
  84. }
  85. //TODO: Add other types of evidence to test and set MaxEvidenceBytes accordingly
  86. testCases := []struct {
  87. testName string
  88. evidence Evidence
  89. }{
  90. {"DuplicateVote", ev},
  91. }
  92. for _, tt := range testCases {
  93. pb, err := EvidenceToProto(tt.evidence)
  94. require.NoError(t, err, tt.testName)
  95. bz, err := pb.Marshal()
  96. require.NoError(t, err, tt.testName)
  97. assert.LessOrEqual(t, int64(len(bz)), MaxEvidenceBytes, tt.testName)
  98. }
  99. }
  100. func randomDuplicatedVoteEvidence(t *testing.T) *DuplicateVoteEvidence {
  101. val := NewMockPV()
  102. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  103. blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
  104. const chainID = "mychain"
  105. return &DuplicateVoteEvidence{
  106. VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime),
  107. VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, defaultVoteTime.Add(1*time.Minute)),
  108. }
  109. }
  110. func TestDuplicateVoteEvidenceValidation(t *testing.T) {
  111. val := NewMockPV()
  112. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  113. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  114. const chainID = "mychain"
  115. testCases := []struct {
  116. testName string
  117. malleateEvidence func(*DuplicateVoteEvidence)
  118. expectErr bool
  119. }{
  120. {"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false},
  121. {"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true},
  122. {"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true},
  123. {"Nil votes", func(ev *DuplicateVoteEvidence) {
  124. ev.VoteA = nil
  125. ev.VoteB = nil
  126. }, true},
  127. {"Invalid vote type", func(ev *DuplicateVoteEvidence) {
  128. ev.VoteA = makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0, blockID2, defaultVoteTime)
  129. }, true},
  130. {"Invalid vote order", func(ev *DuplicateVoteEvidence) {
  131. swap := ev.VoteA.Copy()
  132. ev.VoteA = ev.VoteB.Copy()
  133. ev.VoteB = swap
  134. }, true},
  135. }
  136. for _, tc := range testCases {
  137. tc := tc
  138. t.Run(tc.testName, func(t *testing.T) {
  139. vote1 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID, defaultVoteTime)
  140. vote2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID2, defaultVoteTime)
  141. ev := NewDuplicateVoteEvidence(vote1, vote2, vote1.Timestamp)
  142. tc.malleateEvidence(ev)
  143. assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  144. })
  145. }
  146. }
  147. func TestMockEvidenceValidateBasic(t *testing.T) {
  148. goodEvidence := NewMockDuplicateVoteEvidence(int64(1), time.Now(), "mock-chain-id")
  149. assert.Nil(t, goodEvidence.ValidateBasic())
  150. }
  151. func makeVote(
  152. t *testing.T, val PrivValidator, chainID string, valIndex int32, height int64, round int32, step int, blockID BlockID,
  153. time time.Time) *Vote {
  154. pubKey, err := val.GetPubKey()
  155. require.NoError(t, err)
  156. v := &Vote{
  157. ValidatorAddress: pubKey.Address(),
  158. ValidatorIndex: valIndex,
  159. Height: height,
  160. Round: round,
  161. Type: tmproto.SignedMsgType(step),
  162. BlockID: blockID,
  163. Timestamp: time,
  164. }
  165. vpb := v.ToProto()
  166. err = val.SignVote(chainID, vpb)
  167. if err != nil {
  168. panic(err)
  169. }
  170. v.Signature = vpb.Signature
  171. return v
  172. }
  173. func makeHeaderRandom() *Header {
  174. return &Header{
  175. ChainID: tmrand.Str(12),
  176. Height: int64(tmrand.Uint16()) + 1,
  177. Time: time.Now(),
  178. LastBlockID: makeBlockIDRandom(),
  179. LastCommitHash: crypto.CRandBytes(tmhash.Size),
  180. DataHash: crypto.CRandBytes(tmhash.Size),
  181. ValidatorsHash: crypto.CRandBytes(tmhash.Size),
  182. NextValidatorsHash: crypto.CRandBytes(tmhash.Size),
  183. ConsensusHash: crypto.CRandBytes(tmhash.Size),
  184. AppHash: crypto.CRandBytes(tmhash.Size),
  185. LastResultsHash: crypto.CRandBytes(tmhash.Size),
  186. EvidenceHash: crypto.CRandBytes(tmhash.Size),
  187. ProposerAddress: crypto.CRandBytes(crypto.AddressSize),
  188. }
  189. }
  190. func TestEvidenceProto(t *testing.T) {
  191. // -------- Votes --------
  192. val := NewMockPV()
  193. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  194. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  195. const chainID = "mychain"
  196. v := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 1, 0x01, blockID, defaultVoteTime)
  197. v2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 2, 0x01, blockID2, defaultVoteTime)
  198. // -------- SignedHeaders --------
  199. const height int64 = 37
  200. var (
  201. header1 = makeHeaderRandom()
  202. header2 = makeHeaderRandom()
  203. )
  204. header1.Height = height
  205. header1.LastBlockID = blockID
  206. header1.ChainID = chainID
  207. header2.Height = height
  208. header2.LastBlockID = blockID
  209. header2.ChainID = chainID
  210. tests := []struct {
  211. testName string
  212. evidence Evidence
  213. toProtoErr bool
  214. fromProtoErr bool
  215. }{
  216. {"nil fail", nil, true, true},
  217. {"DuplicateVoteEvidence empty fail", &DuplicateVoteEvidence{}, false, true},
  218. {"DuplicateVoteEvidence nil voteB", &DuplicateVoteEvidence{VoteA: v, VoteB: nil}, false, true},
  219. {"DuplicateVoteEvidence nil voteA", &DuplicateVoteEvidence{VoteA: nil, VoteB: v}, false, true},
  220. {"DuplicateVoteEvidence success", &DuplicateVoteEvidence{VoteA: v2, VoteB: v}, false, false},
  221. }
  222. for _, tt := range tests {
  223. tt := tt
  224. t.Run(tt.testName, func(t *testing.T) {
  225. pb, err := EvidenceToProto(tt.evidence)
  226. if tt.toProtoErr {
  227. assert.Error(t, err, tt.testName)
  228. return
  229. }
  230. assert.NoError(t, err, tt.testName)
  231. evi, err := EvidenceFromProto(pb)
  232. if tt.fromProtoErr {
  233. assert.Error(t, err, tt.testName)
  234. return
  235. }
  236. require.Equal(t, tt.evidence, evi, tt.testName)
  237. })
  238. }
  239. }