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.

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