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.

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