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.

405 lines
12 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
  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. tmrand "github.com/tendermint/tendermint/libs/rand"
  12. )
  13. type voteData struct {
  14. vote1 *Vote
  15. vote2 *Vote
  16. valid bool
  17. }
  18. func makeVote(
  19. t *testing.T, val PrivValidator, chainID string, valIndex int, height int64, round, step int, blockID BlockID,
  20. ) *Vote {
  21. pubKey, err := val.GetPubKey()
  22. require.NoError(t, err)
  23. v := &Vote{
  24. ValidatorAddress: pubKey.Address(),
  25. ValidatorIndex: valIndex,
  26. Height: height,
  27. Round: round,
  28. Type: SignedMsgType(step),
  29. BlockID: blockID,
  30. }
  31. err = val.SignVote(chainID, v)
  32. if err != nil {
  33. panic(err)
  34. }
  35. return v
  36. }
  37. func TestEvidence(t *testing.T) {
  38. val := NewMockPV()
  39. val2 := NewMockPV()
  40. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  41. blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
  42. blockID3 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash"))
  43. blockID4 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash2"))
  44. const chainID = "mychain"
  45. vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID)
  46. badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID)
  47. err := val2.SignVote(chainID, badVote)
  48. assert.NoError(t, err)
  49. cases := []voteData{
  50. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2), true}, // different block ids
  51. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3), true},
  52. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID4), true},
  53. {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID), false}, // wrong block id
  54. {vote1, makeVote(t, val, "mychain2", 0, 10, 2, 1, blockID2), false}, // wrong chain id
  55. {vote1, makeVote(t, val, chainID, 1, 10, 2, 1, blockID2), false}, // wrong val index
  56. {vote1, makeVote(t, val, chainID, 0, 11, 2, 1, blockID2), false}, // wrong height
  57. {vote1, makeVote(t, val, chainID, 0, 10, 3, 1, blockID2), false}, // wrong round
  58. {vote1, makeVote(t, val, chainID, 0, 10, 2, 2, blockID2), false}, // wrong step
  59. {vote1, makeVote(t, val2, chainID, 0, 10, 2, 1, blockID), false}, // wrong validator
  60. {vote1, badVote, false}, // signed by wrong key
  61. }
  62. pubKey, err := val.GetPubKey()
  63. require.NoError(t, err)
  64. for _, c := range cases {
  65. ev := &DuplicateVoteEvidence{
  66. VoteA: c.vote1,
  67. VoteB: c.vote2,
  68. }
  69. if c.valid {
  70. assert.Nil(t, ev.Verify(chainID, pubKey), "evidence should be valid")
  71. } else {
  72. assert.NotNil(t, ev.Verify(chainID, pubKey), "evidence should be invalid")
  73. }
  74. }
  75. }
  76. func TestDuplicatedVoteEvidence(t *testing.T) {
  77. ev := randomDuplicatedVoteEvidence(t)
  78. assert.True(t, ev.Equal(ev))
  79. assert.False(t, ev.Equal(&DuplicateVoteEvidence{}))
  80. }
  81. func TestEvidenceList(t *testing.T) {
  82. ev := randomDuplicatedVoteEvidence(t)
  83. evl := EvidenceList([]Evidence{ev})
  84. assert.NotNil(t, evl.Hash())
  85. assert.True(t, evl.Has(ev))
  86. assert.False(t, evl.Has(&DuplicateVoteEvidence{}))
  87. }
  88. func TestMaxEvidenceBytes(t *testing.T) {
  89. val := NewMockPV()
  90. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
  91. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
  92. const chainID = "mychain"
  93. ev := &DuplicateVoteEvidence{
  94. VoteA: makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID),
  95. VoteB: makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
  96. }
  97. //TODO: Add other types of evidence to test and set MaxEvidenceBytes accordingly
  98. // evl := &LunaticValidatorEvidence{
  99. // Header: makeHeaderRandom(),
  100. // Vote: makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
  101. // InvalidHeaderField: "",
  102. // }
  103. // evp := &PhantomValidatorEvidence{
  104. // Header: makeHeaderRandom(),
  105. // Vote: makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
  106. // LastHeightValidatorWasInSet: math.MaxInt64,
  107. // }
  108. // signedHeader := SignedHeader{Header: makeHeaderRandom(), Commit: randCommit(time.Now())}
  109. // evc := &ConflictingHeadersEvidence{
  110. // H1: &signedHeader,
  111. // H2: &signedHeader,
  112. // }
  113. testCases := []struct {
  114. testName string
  115. evidence Evidence
  116. }{
  117. {"DuplicateVote", ev},
  118. // {"LunaticValidatorEvidence", evl},
  119. // {"PhantomValidatorEvidence", evp},
  120. // {"ConflictingHeadersEvidence", evc},
  121. }
  122. for _, tt := range testCases {
  123. bz, err := cdc.MarshalBinaryLengthPrefixed(tt.evidence)
  124. require.NoError(t, err, tt.testName)
  125. assert.LessOrEqual(t, MaxEvidenceBytes, int64(len(bz)), tt.testName)
  126. }
  127. }
  128. func randomDuplicatedVoteEvidence(t *testing.T) *DuplicateVoteEvidence {
  129. val := NewMockPV()
  130. blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
  131. blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
  132. const chainID = "mychain"
  133. return &DuplicateVoteEvidence{
  134. VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID),
  135. VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2),
  136. }
  137. }
  138. func TestDuplicateVoteEvidenceValidation(t *testing.T) {
  139. val := NewMockPV()
  140. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
  141. blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
  142. const chainID = "mychain"
  143. testCases := []struct {
  144. testName string
  145. malleateEvidence func(*DuplicateVoteEvidence)
  146. expectErr bool
  147. }{
  148. {"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false},
  149. {"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true},
  150. {"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true},
  151. {"Nil votes", func(ev *DuplicateVoteEvidence) {
  152. ev.VoteA = nil
  153. ev.VoteB = nil
  154. }, true},
  155. {"Invalid vote type", func(ev *DuplicateVoteEvidence) {
  156. ev.VoteA = makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0, blockID2)
  157. }, true},
  158. {"Invalid vote order", func(ev *DuplicateVoteEvidence) {
  159. swap := ev.VoteA.Copy()
  160. ev.VoteA = ev.VoteB.Copy()
  161. ev.VoteB = swap
  162. }, true},
  163. }
  164. for _, tc := range testCases {
  165. tc := tc
  166. t.Run(tc.testName, func(t *testing.T) {
  167. vote1 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID)
  168. vote2 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID2)
  169. ev := NewDuplicateVoteEvidence(vote1, vote2)
  170. tc.malleateEvidence(ev)
  171. assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  172. })
  173. }
  174. }
  175. func TestMockGoodEvidenceValidateBasic(t *testing.T) {
  176. goodEvidence := NewMockEvidence(int64(1), time.Now(), []byte{1})
  177. assert.Nil(t, goodEvidence.ValidateBasic())
  178. }
  179. func TestMockBadEvidenceValidateBasic(t *testing.T) {
  180. badEvidence := NewMockEvidence(int64(1), time.Now(), []byte{1})
  181. assert.Nil(t, badEvidence.ValidateBasic())
  182. }
  183. func TestLunaticValidatorEvidence(t *testing.T) {
  184. var (
  185. blockID = makeBlockIDRandom()
  186. header = makeHeaderRandom()
  187. bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
  188. val = NewMockPV()
  189. vote = makeVote(t, val, header.ChainID, 0, header.Height, 0, 2, blockID)
  190. )
  191. header.Time = bTime
  192. ev := &LunaticValidatorEvidence{
  193. Header: header,
  194. Vote: vote,
  195. InvalidHeaderField: "AppHash",
  196. }
  197. assert.Equal(t, header.Height, ev.Height())
  198. assert.Equal(t, bTime, ev.Time())
  199. assert.EqualValues(t, vote.ValidatorAddress, ev.Address())
  200. assert.NotEmpty(t, ev.Hash())
  201. assert.NotEmpty(t, ev.Bytes())
  202. pubKey, err := val.GetPubKey()
  203. require.NoError(t, err)
  204. assert.NoError(t, ev.Verify(header.ChainID, pubKey))
  205. assert.Error(t, ev.Verify("other", pubKey))
  206. privKey2 := ed25519.GenPrivKey()
  207. pubKey2 := privKey2.PubKey()
  208. assert.Error(t, ev.Verify("other", pubKey2))
  209. assert.True(t, ev.Equal(ev))
  210. assert.NoError(t, ev.ValidateBasic())
  211. assert.NotEmpty(t, ev.String())
  212. }
  213. func TestPhantomValidatorEvidence(t *testing.T) {
  214. var (
  215. blockID = makeBlockIDRandom()
  216. header = makeHeaderRandom()
  217. bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
  218. val = NewMockPV()
  219. vote = makeVote(t, val, header.ChainID, 0, header.Height, 0, 2, blockID)
  220. )
  221. header.Time = bTime
  222. ev := &PhantomValidatorEvidence{
  223. Header: header,
  224. Vote: vote,
  225. LastHeightValidatorWasInSet: header.Height - 1,
  226. }
  227. assert.Equal(t, header.Height, ev.Height())
  228. assert.Equal(t, bTime, ev.Time())
  229. assert.EqualValues(t, vote.ValidatorAddress, ev.Address())
  230. assert.NotEmpty(t, ev.Hash())
  231. assert.NotEmpty(t, ev.Bytes())
  232. pubKey, err := val.GetPubKey()
  233. require.NoError(t, err)
  234. assert.NoError(t, ev.Verify(header.ChainID, pubKey))
  235. assert.Error(t, ev.Verify("other", pubKey))
  236. privKey2 := ed25519.GenPrivKey()
  237. pubKey2 := privKey2.PubKey()
  238. assert.Error(t, ev.Verify("other", pubKey2))
  239. assert.True(t, ev.Equal(ev))
  240. assert.NoError(t, ev.ValidateBasic())
  241. assert.NotEmpty(t, ev.String())
  242. }
  243. func TestConflictingHeadersEvidence(t *testing.T) {
  244. const (
  245. chainID = "TestConflictingHeadersEvidence"
  246. height int64 = 37
  247. )
  248. var (
  249. blockID = makeBlockIDRandom()
  250. header1 = makeHeaderRandom()
  251. header2 = makeHeaderRandom()
  252. )
  253. header1.Height = height
  254. header1.LastBlockID = blockID
  255. header1.ChainID = chainID
  256. header2.Height = height
  257. header2.LastBlockID = blockID
  258. header2.ChainID = chainID
  259. voteSet1, valSet, vals := randVoteSet(height, 1, PrecommitType, 10, 1)
  260. voteSet2 := NewVoteSet(chainID, height, 1, PrecommitType, valSet)
  261. commit1, err := MakeCommit(BlockID{
  262. Hash: header1.Hash(),
  263. PartsHeader: PartSetHeader{
  264. Total: 100,
  265. Hash: crypto.CRandBytes(tmhash.Size),
  266. },
  267. }, height, 1, voteSet1, vals, time.Now())
  268. require.NoError(t, err)
  269. commit2, err := MakeCommit(BlockID{
  270. Hash: header2.Hash(),
  271. PartsHeader: PartSetHeader{
  272. Total: 100,
  273. Hash: crypto.CRandBytes(tmhash.Size),
  274. },
  275. }, height, 1, voteSet2, vals, time.Now())
  276. require.NoError(t, err)
  277. ev := &ConflictingHeadersEvidence{
  278. H1: &SignedHeader{
  279. Header: header1,
  280. Commit: commit1,
  281. },
  282. H2: &SignedHeader{
  283. Header: header2,
  284. Commit: commit2,
  285. },
  286. }
  287. assert.Panics(t, func() {
  288. ev.Address()
  289. })
  290. assert.Panics(t, func() {
  291. pubKey, _ := vals[0].GetPubKey()
  292. ev.Verify(chainID, pubKey)
  293. })
  294. assert.Equal(t, height, ev.Height())
  295. // assert.Equal(t, bTime, ev.Time())
  296. assert.NotEmpty(t, ev.Hash())
  297. assert.NotEmpty(t, ev.Bytes())
  298. assert.NoError(t, ev.VerifyComposite(header1, valSet))
  299. assert.True(t, ev.Equal(ev))
  300. assert.NoError(t, ev.ValidateBasic())
  301. assert.NotEmpty(t, ev.String())
  302. }
  303. func TestPotentialAmnesiaEvidence(t *testing.T) {
  304. const (
  305. chainID = "TestPotentialAmnesiaEvidence"
  306. height int64 = 37
  307. )
  308. var (
  309. val = NewMockPV()
  310. blockID = makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
  311. blockID2 = makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
  312. vote1 = makeVote(t, val, chainID, 0, height, 0, 2, blockID)
  313. vote2 = makeVote(t, val, chainID, 0, height, 1, 2, blockID2)
  314. )
  315. ev := &PotentialAmnesiaEvidence{
  316. VoteA: vote2,
  317. VoteB: vote1,
  318. }
  319. assert.Equal(t, height, ev.Height())
  320. // assert.Equal(t, bTime, ev.Time())
  321. assert.EqualValues(t, vote1.ValidatorAddress, ev.Address())
  322. assert.NotEmpty(t, ev.Hash())
  323. assert.NotEmpty(t, ev.Bytes())
  324. pubKey, err := val.GetPubKey()
  325. require.NoError(t, err)
  326. assert.NoError(t, ev.Verify(chainID, pubKey))
  327. assert.Error(t, ev.Verify("other", pubKey))
  328. privKey2 := ed25519.GenPrivKey()
  329. pubKey2 := privKey2.PubKey()
  330. assert.Error(t, ev.Verify("other", pubKey2))
  331. assert.True(t, ev.Equal(ev))
  332. assert.NoError(t, ev.ValidateBasic())
  333. assert.NotEmpty(t, ev.String())
  334. }
  335. func makeHeaderRandom() *Header {
  336. return &Header{
  337. ChainID: tmrand.Str(12),
  338. Height: int64(tmrand.Uint16()) + 1,
  339. Time: time.Now(),
  340. LastBlockID: makeBlockIDRandom(),
  341. LastCommitHash: crypto.CRandBytes(tmhash.Size),
  342. DataHash: crypto.CRandBytes(tmhash.Size),
  343. ValidatorsHash: crypto.CRandBytes(tmhash.Size),
  344. NextValidatorsHash: crypto.CRandBytes(tmhash.Size),
  345. ConsensusHash: crypto.CRandBytes(tmhash.Size),
  346. AppHash: crypto.CRandBytes(tmhash.Size),
  347. LastResultsHash: crypto.CRandBytes(tmhash.Size),
  348. EvidenceHash: crypto.CRandBytes(tmhash.Size),
  349. ProposerAddress: crypto.CRandBytes(crypto.AddressSize),
  350. }
  351. }