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.

346 lines
11 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. tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
  13. "github.com/tendermint/tendermint/version"
  14. )
  15. var defaultVoteTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
  16. func TestEvidenceList(t *testing.T) {
  17. ev := randomDuplicateVoteEvidence(t)
  18. evl := EvidenceList([]Evidence{ev})
  19. assert.NotNil(t, evl.Hash())
  20. assert.True(t, evl.Has(ev))
  21. assert.False(t, evl.Has(&DuplicateVoteEvidence{}))
  22. }
  23. func TestMaxEvidenceBytes(t *testing.T) {
  24. val := NewMockPV()
  25. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  26. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  27. maxTime := time.Date(9999, 0, 0, 0, 0, 0, 0, time.UTC)
  28. const chainID = "mychain"
  29. ev := &DuplicateVoteEvidence{
  30. VoteA: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, math.MaxInt64, blockID, maxTime),
  31. VoteB: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, math.MaxInt64, blockID2, maxTime),
  32. }
  33. //TODO: Add other types of evidence to test and set MaxEvidenceBytes accordingly
  34. testCases := []struct {
  35. testName string
  36. evidence Evidence
  37. }{
  38. {"DuplicateVote", ev},
  39. }
  40. for _, tt := range testCases {
  41. pb, err := EvidenceToProto(tt.evidence)
  42. require.NoError(t, err, tt.testName)
  43. bz, err := pb.Marshal()
  44. require.NoError(t, err, tt.testName)
  45. assert.LessOrEqual(t, int64(len(bz)), MaxEvidenceBytes, tt.testName)
  46. }
  47. }
  48. func randomDuplicateVoteEvidence(t *testing.T) *DuplicateVoteEvidence {
  49. val := NewMockPV()
  50. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  51. blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
  52. const chainID = "mychain"
  53. return &DuplicateVoteEvidence{
  54. VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime),
  55. VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, defaultVoteTime.Add(1*time.Minute)),
  56. }
  57. }
  58. func TestDuplicateVoteEvidence(t *testing.T) {
  59. const height = int64(13)
  60. ev := NewMockDuplicateVoteEvidence(height, time.Now(), "mock-chain-id")
  61. assert.Equal(t, ev.Hash(), tmhash.Sum(ev.Bytes()))
  62. assert.NotNil(t, ev.String())
  63. assert.Equal(t, ev.Height(), height)
  64. }
  65. func TestDuplicateVoteEvidenceValidation(t *testing.T) {
  66. val := NewMockPV()
  67. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  68. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  69. const chainID = "mychain"
  70. testCases := []struct {
  71. testName string
  72. malleateEvidence func(*DuplicateVoteEvidence)
  73. expectErr bool
  74. }{
  75. {"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false},
  76. {"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true},
  77. {"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true},
  78. {"Nil votes", func(ev *DuplicateVoteEvidence) {
  79. ev.VoteA = nil
  80. ev.VoteB = nil
  81. }, true},
  82. {"Invalid vote type", func(ev *DuplicateVoteEvidence) {
  83. ev.VoteA = makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0, blockID2, defaultVoteTime)
  84. }, true},
  85. {"Invalid vote order", func(ev *DuplicateVoteEvidence) {
  86. swap := ev.VoteA.Copy()
  87. ev.VoteA = ev.VoteB.Copy()
  88. ev.VoteB = swap
  89. }, true},
  90. }
  91. for _, tc := range testCases {
  92. tc := tc
  93. t.Run(tc.testName, func(t *testing.T) {
  94. vote1 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID, defaultVoteTime)
  95. vote2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID2, defaultVoteTime)
  96. ev := NewDuplicateVoteEvidence(vote1, vote2)
  97. tc.malleateEvidence(ev)
  98. assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  99. })
  100. }
  101. }
  102. func TestLightClientAttackEvidence(t *testing.T) {
  103. height := int64(5)
  104. voteSet, valSet, privVals := randVoteSet(height, 1, tmproto.PrecommitType, 10, 1)
  105. header := makeHeaderRandom()
  106. header.Height = height
  107. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  108. commit, err := MakeCommit(blockID, height, 1, voteSet, privVals, defaultVoteTime)
  109. require.NoError(t, err)
  110. lcae := &LightClientAttackEvidence{
  111. ConflictingBlock: &LightBlock{
  112. SignedHeader: &SignedHeader{
  113. Header: header,
  114. Commit: commit,
  115. },
  116. ValidatorSet: valSet,
  117. },
  118. CommonHeight: height - 1,
  119. }
  120. assert.NotNil(t, lcae.String())
  121. assert.NotNil(t, lcae.Hash())
  122. // only 7 validators sign
  123. differentCommit, err := MakeCommit(blockID, height, 1, voteSet, privVals[:7], defaultVoteTime)
  124. require.NoError(t, err)
  125. differentEv := &LightClientAttackEvidence{
  126. ConflictingBlock: &LightBlock{
  127. SignedHeader: &SignedHeader{
  128. Header: header,
  129. Commit: differentCommit,
  130. },
  131. ValidatorSet: valSet,
  132. },
  133. CommonHeight: height - 1,
  134. }
  135. assert.Equal(t, lcae.Hash(), differentEv.Hash())
  136. // different header hash
  137. differentHeader := makeHeaderRandom()
  138. differentEv = &LightClientAttackEvidence{
  139. ConflictingBlock: &LightBlock{
  140. SignedHeader: &SignedHeader{
  141. Header: differentHeader,
  142. Commit: differentCommit,
  143. },
  144. ValidatorSet: valSet,
  145. },
  146. CommonHeight: height - 1,
  147. }
  148. assert.NotEqual(t, lcae.Hash(), differentEv.Hash())
  149. // different common height should produce a different header
  150. differentEv = &LightClientAttackEvidence{
  151. ConflictingBlock: &LightBlock{
  152. SignedHeader: &SignedHeader{
  153. Header: header,
  154. Commit: differentCommit,
  155. },
  156. ValidatorSet: valSet,
  157. },
  158. CommonHeight: height - 2,
  159. }
  160. assert.NotEqual(t, lcae.Hash(), differentEv.Hash())
  161. assert.Equal(t, lcae.Height(), int64(4)) // Height should be the common Height
  162. assert.NotNil(t, lcae.Bytes())
  163. }
  164. func TestLightClientAttackEvidenceValidation(t *testing.T) {
  165. height := int64(5)
  166. voteSet, valSet, privVals := randVoteSet(height, 1, tmproto.PrecommitType, 10, 1)
  167. header := makeHeaderRandom()
  168. header.Height = height
  169. header.ValidatorsHash = valSet.Hash()
  170. blockID := makeBlockID(header.Hash(), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  171. commit, err := MakeCommit(blockID, height, 1, voteSet, privVals, time.Now())
  172. require.NoError(t, err)
  173. lcae := &LightClientAttackEvidence{
  174. ConflictingBlock: &LightBlock{
  175. SignedHeader: &SignedHeader{
  176. Header: header,
  177. Commit: commit,
  178. },
  179. ValidatorSet: valSet,
  180. },
  181. CommonHeight: height - 1,
  182. }
  183. assert.NoError(t, lcae.ValidateBasic())
  184. testCases := []struct {
  185. testName string
  186. malleateEvidence func(*LightClientAttackEvidence)
  187. expectErr bool
  188. }{
  189. {"Good DuplicateVoteEvidence", func(ev *LightClientAttackEvidence) {}, false},
  190. {"Negative height", func(ev *LightClientAttackEvidence) { ev.CommonHeight = -10 }, true},
  191. {"Height is greater than divergent block", func(ev *LightClientAttackEvidence) {
  192. ev.CommonHeight = height + 1
  193. }, true},
  194. {"Nil conflicting header", func(ev *LightClientAttackEvidence) { ev.ConflictingBlock.Header = nil }, true},
  195. {"Nil conflicting blocl", func(ev *LightClientAttackEvidence) { ev.ConflictingBlock = nil }, true},
  196. {"Nil validator set", func(ev *LightClientAttackEvidence) {
  197. ev.ConflictingBlock.ValidatorSet = &ValidatorSet{}
  198. }, true},
  199. }
  200. for _, tc := range testCases {
  201. tc := tc
  202. t.Run(tc.testName, func(t *testing.T) {
  203. lcae := &LightClientAttackEvidence{
  204. ConflictingBlock: &LightBlock{
  205. SignedHeader: &SignedHeader{
  206. Header: header,
  207. Commit: commit,
  208. },
  209. ValidatorSet: valSet,
  210. },
  211. CommonHeight: height - 1,
  212. }
  213. tc.malleateEvidence(lcae)
  214. if tc.expectErr {
  215. assert.Error(t, lcae.ValidateBasic(), tc.testName)
  216. } else {
  217. assert.NoError(t, lcae.ValidateBasic(), tc.testName)
  218. }
  219. })
  220. }
  221. }
  222. func TestMockEvidenceValidateBasic(t *testing.T) {
  223. goodEvidence := NewMockDuplicateVoteEvidence(int64(1), time.Now(), "mock-chain-id")
  224. assert.Nil(t, goodEvidence.ValidateBasic())
  225. }
  226. func makeVote(
  227. t *testing.T, val PrivValidator, chainID string, valIndex int32, height int64, round int32, step int, blockID BlockID,
  228. time time.Time) *Vote {
  229. pubKey, err := val.GetPubKey()
  230. require.NoError(t, err)
  231. v := &Vote{
  232. ValidatorAddress: pubKey.Address(),
  233. ValidatorIndex: valIndex,
  234. Height: height,
  235. Round: round,
  236. Type: tmproto.SignedMsgType(step),
  237. BlockID: blockID,
  238. Timestamp: time,
  239. }
  240. vpb := v.ToProto()
  241. err = val.SignVote(chainID, vpb)
  242. if err != nil {
  243. panic(err)
  244. }
  245. v.Signature = vpb.Signature
  246. return v
  247. }
  248. func makeHeaderRandom() *Header {
  249. return &Header{
  250. Version: tmversion.Consensus{Block: version.BlockProtocol, App: 1},
  251. ChainID: tmrand.Str(12),
  252. Height: int64(tmrand.Uint16()) + 1,
  253. Time: time.Now(),
  254. LastBlockID: makeBlockIDRandom(),
  255. LastCommitHash: crypto.CRandBytes(tmhash.Size),
  256. DataHash: crypto.CRandBytes(tmhash.Size),
  257. ValidatorsHash: crypto.CRandBytes(tmhash.Size),
  258. NextValidatorsHash: crypto.CRandBytes(tmhash.Size),
  259. ConsensusHash: crypto.CRandBytes(tmhash.Size),
  260. AppHash: crypto.CRandBytes(tmhash.Size),
  261. LastResultsHash: crypto.CRandBytes(tmhash.Size),
  262. EvidenceHash: crypto.CRandBytes(tmhash.Size),
  263. ProposerAddress: crypto.CRandBytes(crypto.AddressSize),
  264. }
  265. }
  266. func TestEvidenceProto(t *testing.T) {
  267. // -------- Votes --------
  268. val := NewMockPV()
  269. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  270. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
  271. const chainID = "mychain"
  272. v := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 1, 0x01, blockID, defaultVoteTime)
  273. v2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 2, 0x01, blockID2, defaultVoteTime)
  274. // -------- SignedHeaders --------
  275. const height int64 = 37
  276. var (
  277. header1 = makeHeaderRandom()
  278. header2 = makeHeaderRandom()
  279. )
  280. header1.Height = height
  281. header1.LastBlockID = blockID
  282. header1.ChainID = chainID
  283. header2.Height = height
  284. header2.LastBlockID = blockID
  285. header2.ChainID = chainID
  286. tests := []struct {
  287. testName string
  288. evidence Evidence
  289. toProtoErr bool
  290. fromProtoErr bool
  291. }{
  292. {"nil fail", nil, true, true},
  293. {"DuplicateVoteEvidence empty fail", &DuplicateVoteEvidence{}, false, true},
  294. {"DuplicateVoteEvidence nil voteB", &DuplicateVoteEvidence{VoteA: v, VoteB: nil}, false, true},
  295. {"DuplicateVoteEvidence nil voteA", &DuplicateVoteEvidence{VoteA: nil, VoteB: v}, false, true},
  296. {"DuplicateVoteEvidence success", &DuplicateVoteEvidence{VoteA: v2, VoteB: v}, false, false},
  297. }
  298. for _, tt := range tests {
  299. tt := tt
  300. t.Run(tt.testName, func(t *testing.T) {
  301. pb, err := EvidenceToProto(tt.evidence)
  302. if tt.toProtoErr {
  303. assert.Error(t, err, tt.testName)
  304. return
  305. }
  306. assert.NoError(t, err, tt.testName)
  307. evi, err := EvidenceFromProto(pb)
  308. if tt.fromProtoErr {
  309. assert.Error(t, err, tt.testName)
  310. return
  311. }
  312. require.Equal(t, tt.evidence, evi, tt.testName)
  313. })
  314. }
  315. }