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.

738 lines
20 KiB

  1. package consensus
  2. import (
  3. "context"
  4. "encoding/hex"
  5. "fmt"
  6. "math"
  7. "testing"
  8. "time"
  9. "github.com/gogo/protobuf/proto"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/stretchr/testify/require"
  12. cstypes "github.com/tendermint/tendermint/consensus/types"
  13. "github.com/tendermint/tendermint/crypto/merkle"
  14. "github.com/tendermint/tendermint/crypto/tmhash"
  15. "github.com/tendermint/tendermint/libs/bits"
  16. "github.com/tendermint/tendermint/libs/bytes"
  17. tmrand "github.com/tendermint/tendermint/libs/rand"
  18. "github.com/tendermint/tendermint/p2p"
  19. tmcons "github.com/tendermint/tendermint/proto/tendermint/consensus"
  20. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  21. "github.com/tendermint/tendermint/types"
  22. )
  23. func TestMsgToProto(t *testing.T) {
  24. psh := types.PartSetHeader{
  25. Total: 1,
  26. Hash: tmrand.Bytes(32),
  27. }
  28. pbPsh := psh.ToProto()
  29. bi := types.BlockID{
  30. Hash: tmrand.Bytes(32),
  31. PartSetHeader: psh,
  32. }
  33. pbBi := bi.ToProto()
  34. bits := bits.NewBitArray(1)
  35. pbBits := bits.ToProto()
  36. parts := types.Part{
  37. Index: 1,
  38. Bytes: []byte("test"),
  39. Proof: merkle.Proof{
  40. Total: 1,
  41. Index: 1,
  42. LeafHash: tmrand.Bytes(32),
  43. Aunts: [][]byte{},
  44. },
  45. }
  46. pbParts, err := parts.ToProto()
  47. require.NoError(t, err)
  48. proposal := types.Proposal{
  49. Type: tmproto.ProposalType,
  50. Height: 1,
  51. Round: 1,
  52. POLRound: 1,
  53. BlockID: bi,
  54. Timestamp: time.Now(),
  55. Signature: tmrand.Bytes(20),
  56. }
  57. pbProposal := proposal.ToProto()
  58. pv := types.NewMockPV()
  59. pk, err := pv.GetPubKey(context.Background())
  60. require.NoError(t, err)
  61. val := types.NewValidator(pk, 100)
  62. vote, err := types.MakeVote(
  63. 1, types.BlockID{}, &types.ValidatorSet{Proposer: val, Validators: []*types.Validator{val}},
  64. pv, "chainID", time.Now())
  65. require.NoError(t, err)
  66. pbVote := vote.ToProto()
  67. testsCases := []struct {
  68. testName string
  69. msg Message
  70. want *tmcons.Message
  71. wantErr bool
  72. }{
  73. {"successful NewRoundStepMessage", &NewRoundStepMessage{
  74. Height: 2,
  75. Round: 1,
  76. Step: 1,
  77. SecondsSinceStartTime: 1,
  78. LastCommitRound: 2,
  79. }, &tmcons.Message{
  80. Sum: &tmcons.Message_NewRoundStep{
  81. NewRoundStep: &tmcons.NewRoundStep{
  82. Height: 2,
  83. Round: 1,
  84. Step: 1,
  85. SecondsSinceStartTime: 1,
  86. LastCommitRound: 2,
  87. },
  88. },
  89. }, false},
  90. {"successful NewValidBlockMessage", &NewValidBlockMessage{
  91. Height: 1,
  92. Round: 1,
  93. BlockPartSetHeader: psh,
  94. BlockParts: bits,
  95. IsCommit: false,
  96. }, &tmcons.Message{
  97. Sum: &tmcons.Message_NewValidBlock{
  98. NewValidBlock: &tmcons.NewValidBlock{
  99. Height: 1,
  100. Round: 1,
  101. BlockPartSetHeader: pbPsh,
  102. BlockParts: pbBits,
  103. IsCommit: false,
  104. },
  105. },
  106. }, false},
  107. {"successful BlockPartMessage", &BlockPartMessage{
  108. Height: 100,
  109. Round: 1,
  110. Part: &parts,
  111. }, &tmcons.Message{
  112. Sum: &tmcons.Message_BlockPart{
  113. BlockPart: &tmcons.BlockPart{
  114. Height: 100,
  115. Round: 1,
  116. Part: *pbParts,
  117. },
  118. },
  119. }, false},
  120. {"successful ProposalPOLMessage", &ProposalPOLMessage{
  121. Height: 1,
  122. ProposalPOLRound: 1,
  123. ProposalPOL: bits,
  124. }, &tmcons.Message{
  125. Sum: &tmcons.Message_ProposalPol{
  126. ProposalPol: &tmcons.ProposalPOL{
  127. Height: 1,
  128. ProposalPolRound: 1,
  129. ProposalPol: *pbBits,
  130. },
  131. }}, false},
  132. {"successful ProposalMessage", &ProposalMessage{
  133. Proposal: &proposal,
  134. }, &tmcons.Message{
  135. Sum: &tmcons.Message_Proposal{
  136. Proposal: &tmcons.Proposal{
  137. Proposal: *pbProposal,
  138. },
  139. },
  140. }, false},
  141. {"successful VoteMessage", &VoteMessage{
  142. Vote: vote,
  143. }, &tmcons.Message{
  144. Sum: &tmcons.Message_Vote{
  145. Vote: &tmcons.Vote{
  146. Vote: pbVote,
  147. },
  148. },
  149. }, false},
  150. {"successful VoteSetMaj23", &VoteSetMaj23Message{
  151. Height: 1,
  152. Round: 1,
  153. Type: 1,
  154. BlockID: bi,
  155. }, &tmcons.Message{
  156. Sum: &tmcons.Message_VoteSetMaj23{
  157. VoteSetMaj23: &tmcons.VoteSetMaj23{
  158. Height: 1,
  159. Round: 1,
  160. Type: 1,
  161. BlockID: pbBi,
  162. },
  163. },
  164. }, false},
  165. {"successful VoteSetBits", &VoteSetBitsMessage{
  166. Height: 1,
  167. Round: 1,
  168. Type: 1,
  169. BlockID: bi,
  170. Votes: bits,
  171. }, &tmcons.Message{
  172. Sum: &tmcons.Message_VoteSetBits{
  173. VoteSetBits: &tmcons.VoteSetBits{
  174. Height: 1,
  175. Round: 1,
  176. Type: 1,
  177. BlockID: pbBi,
  178. Votes: *pbBits,
  179. },
  180. },
  181. }, false},
  182. {"failure", nil, &tmcons.Message{}, true},
  183. }
  184. for _, tt := range testsCases {
  185. tt := tt
  186. t.Run(tt.testName, func(t *testing.T) {
  187. pb, err := MsgToProto(tt.msg)
  188. if tt.wantErr == true {
  189. assert.Equal(t, err != nil, tt.wantErr)
  190. return
  191. }
  192. assert.EqualValues(t, tt.want, pb, tt.testName)
  193. msg, err := MsgFromProto(pb)
  194. if !tt.wantErr {
  195. require.NoError(t, err)
  196. bcm := assert.Equal(t, tt.msg, msg, tt.testName)
  197. assert.True(t, bcm, tt.testName)
  198. } else {
  199. require.Error(t, err, tt.testName)
  200. }
  201. })
  202. }
  203. }
  204. func TestWALMsgProto(t *testing.T) {
  205. parts := types.Part{
  206. Index: 1,
  207. Bytes: []byte("test"),
  208. Proof: merkle.Proof{
  209. Total: 1,
  210. Index: 1,
  211. LeafHash: tmrand.Bytes(32),
  212. Aunts: [][]byte{},
  213. },
  214. }
  215. pbParts, err := parts.ToProto()
  216. require.NoError(t, err)
  217. testsCases := []struct {
  218. testName string
  219. msg WALMessage
  220. want *tmcons.WALMessage
  221. wantErr bool
  222. }{
  223. {"successful EventDataRoundState", types.EventDataRoundState{
  224. Height: 2,
  225. Round: 1,
  226. Step: "ronies",
  227. }, &tmcons.WALMessage{
  228. Sum: &tmcons.WALMessage_EventDataRoundState{
  229. EventDataRoundState: &tmproto.EventDataRoundState{
  230. Height: 2,
  231. Round: 1,
  232. Step: "ronies",
  233. },
  234. },
  235. }, false},
  236. {"successful msgInfo", msgInfo{
  237. Msg: &BlockPartMessage{
  238. Height: 100,
  239. Round: 1,
  240. Part: &parts,
  241. },
  242. PeerID: p2p.NodeID("string"),
  243. }, &tmcons.WALMessage{
  244. Sum: &tmcons.WALMessage_MsgInfo{
  245. MsgInfo: &tmcons.MsgInfo{
  246. Msg: tmcons.Message{
  247. Sum: &tmcons.Message_BlockPart{
  248. BlockPart: &tmcons.BlockPart{
  249. Height: 100,
  250. Round: 1,
  251. Part: *pbParts,
  252. },
  253. },
  254. },
  255. PeerID: "string",
  256. },
  257. },
  258. }, false},
  259. {"successful timeoutInfo", timeoutInfo{
  260. Duration: time.Duration(100),
  261. Height: 1,
  262. Round: 1,
  263. Step: 1,
  264. }, &tmcons.WALMessage{
  265. Sum: &tmcons.WALMessage_TimeoutInfo{
  266. TimeoutInfo: &tmcons.TimeoutInfo{
  267. Duration: time.Duration(100),
  268. Height: 1,
  269. Round: 1,
  270. Step: 1,
  271. },
  272. },
  273. }, false},
  274. {"successful EndHeightMessage", EndHeightMessage{
  275. Height: 1,
  276. }, &tmcons.WALMessage{
  277. Sum: &tmcons.WALMessage_EndHeight{
  278. EndHeight: &tmcons.EndHeight{
  279. Height: 1,
  280. },
  281. },
  282. }, false},
  283. {"failure", nil, &tmcons.WALMessage{}, true},
  284. }
  285. for _, tt := range testsCases {
  286. tt := tt
  287. t.Run(tt.testName, func(t *testing.T) {
  288. pb, err := WALToProto(tt.msg)
  289. if tt.wantErr == true {
  290. assert.Equal(t, err != nil, tt.wantErr)
  291. return
  292. }
  293. assert.EqualValues(t, tt.want, pb, tt.testName)
  294. msg, err := WALFromProto(pb)
  295. if !tt.wantErr {
  296. require.NoError(t, err)
  297. assert.Equal(t, tt.msg, msg, tt.testName) // need the concrete type as WAL Message is a empty interface
  298. } else {
  299. require.Error(t, err, tt.testName)
  300. }
  301. })
  302. }
  303. }
  304. // nolint:lll //ignore line length for tests
  305. func TestConsMsgsVectors(t *testing.T) {
  306. date := time.Date(2018, 8, 30, 12, 0, 0, 0, time.UTC)
  307. psh := types.PartSetHeader{
  308. Total: 1,
  309. Hash: []byte("add_more_exclamation_marks_code-"),
  310. }
  311. pbPsh := psh.ToProto()
  312. bi := types.BlockID{
  313. Hash: []byte("add_more_exclamation_marks_code-"),
  314. PartSetHeader: psh,
  315. }
  316. pbBi := bi.ToProto()
  317. bits := bits.NewBitArray(1)
  318. pbBits := bits.ToProto()
  319. parts := types.Part{
  320. Index: 1,
  321. Bytes: []byte("test"),
  322. Proof: merkle.Proof{
  323. Total: 1,
  324. Index: 1,
  325. LeafHash: []byte("add_more_exclamation_marks_code-"),
  326. Aunts: [][]byte{},
  327. },
  328. }
  329. pbParts, err := parts.ToProto()
  330. require.NoError(t, err)
  331. proposal := types.Proposal{
  332. Type: tmproto.ProposalType,
  333. Height: 1,
  334. Round: 1,
  335. POLRound: 1,
  336. BlockID: bi,
  337. Timestamp: date,
  338. Signature: []byte("add_more_exclamation"),
  339. }
  340. pbProposal := proposal.ToProto()
  341. v := &types.Vote{
  342. ValidatorAddress: []byte("add_more_exclamation"),
  343. ValidatorIndex: 1,
  344. Height: 1,
  345. Round: 0,
  346. Timestamp: date,
  347. Type: tmproto.PrecommitType,
  348. BlockID: bi,
  349. }
  350. vpb := v.ToProto()
  351. testCases := []struct {
  352. testName string
  353. cMsg proto.Message
  354. expBytes string
  355. }{
  356. {"NewRoundStep", &tmcons.Message{Sum: &tmcons.Message_NewRoundStep{NewRoundStep: &tmcons.NewRoundStep{
  357. Height: 1,
  358. Round: 1,
  359. Step: 1,
  360. SecondsSinceStartTime: 1,
  361. LastCommitRound: 1,
  362. }}}, "0a0a08011001180120012801"},
  363. {"NewRoundStep Max", &tmcons.Message{Sum: &tmcons.Message_NewRoundStep{NewRoundStep: &tmcons.NewRoundStep{
  364. Height: math.MaxInt64,
  365. Round: math.MaxInt32,
  366. Step: math.MaxUint32,
  367. SecondsSinceStartTime: math.MaxInt64,
  368. LastCommitRound: math.MaxInt32,
  369. }}}, "0a2608ffffffffffffffff7f10ffffffff0718ffffffff0f20ffffffffffffffff7f28ffffffff07"},
  370. {"NewValidBlock", &tmcons.Message{Sum: &tmcons.Message_NewValidBlock{
  371. NewValidBlock: &tmcons.NewValidBlock{
  372. Height: 1, Round: 1, BlockPartSetHeader: pbPsh, BlockParts: pbBits, IsCommit: false}}},
  373. "1231080110011a24080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d22050801120100"},
  374. {"Proposal", &tmcons.Message{Sum: &tmcons.Message_Proposal{Proposal: &tmcons.Proposal{Proposal: *pbProposal}}},
  375. "1a720a7008201001180120012a480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d320608c0b89fdc053a146164645f6d6f72655f6578636c616d6174696f6e"},
  376. {"ProposalPol", &tmcons.Message{Sum: &tmcons.Message_ProposalPol{
  377. ProposalPol: &tmcons.ProposalPOL{Height: 1, ProposalPolRound: 1}}},
  378. "2206080110011a00"},
  379. {"BlockPart", &tmcons.Message{Sum: &tmcons.Message_BlockPart{
  380. BlockPart: &tmcons.BlockPart{Height: 1, Round: 1, Part: *pbParts}}},
  381. "2a36080110011a3008011204746573741a26080110011a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d"},
  382. {"Vote", &tmcons.Message{Sum: &tmcons.Message_Vote{
  383. Vote: &tmcons.Vote{Vote: vpb}}},
  384. "32700a6e0802100122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a0608c0b89fdc0532146164645f6d6f72655f6578636c616d6174696f6e3801"},
  385. {"HasVote", &tmcons.Message{Sum: &tmcons.Message_HasVote{
  386. HasVote: &tmcons.HasVote{Height: 1, Round: 1, Type: tmproto.PrevoteType, Index: 1}}},
  387. "3a080801100118012001"},
  388. {"HasVote", &tmcons.Message{Sum: &tmcons.Message_HasVote{
  389. HasVote: &tmcons.HasVote{Height: math.MaxInt64, Round: math.MaxInt32,
  390. Type: tmproto.PrevoteType, Index: math.MaxInt32}}},
  391. "3a1808ffffffffffffffff7f10ffffffff07180120ffffffff07"},
  392. {"VoteSetMaj23", &tmcons.Message{Sum: &tmcons.Message_VoteSetMaj23{
  393. VoteSetMaj23: &tmcons.VoteSetMaj23{Height: 1, Round: 1, Type: tmproto.PrevoteType, BlockID: pbBi}}},
  394. "425008011001180122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d"},
  395. {"VoteSetBits", &tmcons.Message{Sum: &tmcons.Message_VoteSetBits{
  396. VoteSetBits: &tmcons.VoteSetBits{Height: 1, Round: 1, Type: tmproto.PrevoteType, BlockID: pbBi, Votes: *pbBits}}},
  397. "4a5708011001180122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a050801120100"},
  398. }
  399. for _, tc := range testCases {
  400. tc := tc
  401. t.Run(tc.testName, func(t *testing.T) {
  402. bz, err := proto.Marshal(tc.cMsg)
  403. require.NoError(t, err)
  404. require.Equal(t, tc.expBytes, hex.EncodeToString(bz))
  405. })
  406. }
  407. }
  408. func TestVoteSetMaj23MessageValidateBasic(t *testing.T) {
  409. const (
  410. validSignedMsgType tmproto.SignedMsgType = 0x01
  411. invalidSignedMsgType tmproto.SignedMsgType = 0x03
  412. )
  413. validBlockID := types.BlockID{}
  414. invalidBlockID := types.BlockID{
  415. Hash: bytes.HexBytes{},
  416. PartSetHeader: types.PartSetHeader{
  417. Total: 1,
  418. Hash: []byte{0},
  419. },
  420. }
  421. testCases := []struct { // nolint: maligned
  422. expectErr bool
  423. messageRound int32
  424. messageHeight int64
  425. testName string
  426. messageType tmproto.SignedMsgType
  427. messageBlockID types.BlockID
  428. }{
  429. {false, 0, 0, "Valid Message", validSignedMsgType, validBlockID},
  430. {true, -1, 0, "Invalid Message", validSignedMsgType, validBlockID},
  431. {true, 0, -1, "Invalid Message", validSignedMsgType, validBlockID},
  432. {true, 0, 0, "Invalid Message", invalidSignedMsgType, validBlockID},
  433. {true, 0, 0, "Invalid Message", validSignedMsgType, invalidBlockID},
  434. }
  435. for _, tc := range testCases {
  436. tc := tc
  437. t.Run(tc.testName, func(t *testing.T) {
  438. message := VoteSetMaj23Message{
  439. Height: tc.messageHeight,
  440. Round: tc.messageRound,
  441. Type: tc.messageType,
  442. BlockID: tc.messageBlockID,
  443. }
  444. assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  445. })
  446. }
  447. }
  448. func TestVoteSetBitsMessageValidateBasic(t *testing.T) {
  449. testCases := []struct {
  450. malleateFn func(*VoteSetBitsMessage)
  451. expErr string
  452. }{
  453. {func(msg *VoteSetBitsMessage) {}, ""},
  454. {func(msg *VoteSetBitsMessage) { msg.Height = -1 }, "negative Height"},
  455. {func(msg *VoteSetBitsMessage) { msg.Type = 0x03 }, "invalid Type"},
  456. {func(msg *VoteSetBitsMessage) {
  457. msg.BlockID = types.BlockID{
  458. Hash: bytes.HexBytes{},
  459. PartSetHeader: types.PartSetHeader{
  460. Total: 1,
  461. Hash: []byte{0},
  462. },
  463. }
  464. }, "wrong BlockID: wrong PartSetHeader: wrong Hash:"},
  465. {func(msg *VoteSetBitsMessage) { msg.Votes = bits.NewBitArray(types.MaxVotesCount + 1) },
  466. "votes bit array is too big: 10001, max: 10000"},
  467. }
  468. for i, tc := range testCases {
  469. tc := tc
  470. t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
  471. msg := &VoteSetBitsMessage{
  472. Height: 1,
  473. Round: 0,
  474. Type: 0x01,
  475. Votes: bits.NewBitArray(1),
  476. BlockID: types.BlockID{},
  477. }
  478. tc.malleateFn(msg)
  479. err := msg.ValidateBasic()
  480. if tc.expErr != "" && assert.Error(t, err) {
  481. assert.Contains(t, err.Error(), tc.expErr)
  482. }
  483. })
  484. }
  485. }
  486. func TestNewRoundStepMessageValidateBasic(t *testing.T) {
  487. testCases := []struct { // nolint: maligned
  488. expectErr bool
  489. messageRound int32
  490. messageLastCommitRound int32
  491. messageHeight int64
  492. testName string
  493. messageStep cstypes.RoundStepType
  494. }{
  495. {false, 0, 0, 0, "Valid Message", cstypes.RoundStepNewHeight},
  496. {true, -1, 0, 0, "Negative round", cstypes.RoundStepNewHeight},
  497. {true, 0, 0, -1, "Negative height", cstypes.RoundStepNewHeight},
  498. {true, 0, 0, 0, "Invalid Step", cstypes.RoundStepCommit + 1},
  499. // The following cases will be handled by ValidateHeight
  500. {false, 0, 0, 1, "H == 1 but LCR != -1 ", cstypes.RoundStepNewHeight},
  501. {false, 0, -1, 2, "H > 1 but LCR < 0", cstypes.RoundStepNewHeight},
  502. }
  503. for _, tc := range testCases {
  504. tc := tc
  505. t.Run(tc.testName, func(t *testing.T) {
  506. message := NewRoundStepMessage{
  507. Height: tc.messageHeight,
  508. Round: tc.messageRound,
  509. Step: tc.messageStep,
  510. LastCommitRound: tc.messageLastCommitRound,
  511. }
  512. err := message.ValidateBasic()
  513. if tc.expectErr {
  514. require.Error(t, err)
  515. } else {
  516. require.NoError(t, err)
  517. }
  518. })
  519. }
  520. }
  521. func TestNewRoundStepMessageValidateHeight(t *testing.T) {
  522. initialHeight := int64(10)
  523. testCases := []struct { // nolint: maligned
  524. expectErr bool
  525. messageLastCommitRound int32
  526. messageHeight int64
  527. testName string
  528. }{
  529. {false, 0, 11, "Valid Message"},
  530. {true, 0, -1, "Negative height"},
  531. {true, 0, 0, "Zero height"},
  532. {true, 0, 10, "Initial height but LCR != -1 "},
  533. {true, -1, 11, "Normal height but LCR < 0"},
  534. }
  535. for _, tc := range testCases {
  536. tc := tc
  537. t.Run(tc.testName, func(t *testing.T) {
  538. message := NewRoundStepMessage{
  539. Height: tc.messageHeight,
  540. Round: 0,
  541. Step: cstypes.RoundStepNewHeight,
  542. LastCommitRound: tc.messageLastCommitRound,
  543. }
  544. err := message.ValidateHeight(initialHeight)
  545. if tc.expectErr {
  546. require.Error(t, err)
  547. } else {
  548. require.NoError(t, err)
  549. }
  550. })
  551. }
  552. }
  553. func TestNewValidBlockMessageValidateBasic(t *testing.T) {
  554. testCases := []struct {
  555. malleateFn func(*NewValidBlockMessage)
  556. expErr string
  557. }{
  558. {func(msg *NewValidBlockMessage) {}, ""},
  559. {func(msg *NewValidBlockMessage) { msg.Height = -1 }, "negative Height"},
  560. {func(msg *NewValidBlockMessage) { msg.Round = -1 }, "negative Round"},
  561. {
  562. func(msg *NewValidBlockMessage) { msg.BlockPartSetHeader.Total = 2 },
  563. "blockParts bit array size 1 not equal to BlockPartSetHeader.Total 2",
  564. },
  565. {
  566. func(msg *NewValidBlockMessage) {
  567. msg.BlockPartSetHeader.Total = 0
  568. msg.BlockParts = bits.NewBitArray(0)
  569. },
  570. "empty blockParts",
  571. },
  572. {
  573. func(msg *NewValidBlockMessage) { msg.BlockParts = bits.NewBitArray(int(types.MaxBlockPartsCount) + 1) },
  574. "blockParts bit array size 1602 not equal to BlockPartSetHeader.Total 1",
  575. },
  576. }
  577. for i, tc := range testCases {
  578. tc := tc
  579. t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
  580. msg := &NewValidBlockMessage{
  581. Height: 1,
  582. Round: 0,
  583. BlockPartSetHeader: types.PartSetHeader{
  584. Total: 1,
  585. },
  586. BlockParts: bits.NewBitArray(1),
  587. }
  588. tc.malleateFn(msg)
  589. err := msg.ValidateBasic()
  590. if tc.expErr != "" && assert.Error(t, err) {
  591. assert.Contains(t, err.Error(), tc.expErr)
  592. }
  593. })
  594. }
  595. }
  596. func TestProposalPOLMessageValidateBasic(t *testing.T) {
  597. testCases := []struct {
  598. malleateFn func(*ProposalPOLMessage)
  599. expErr string
  600. }{
  601. {func(msg *ProposalPOLMessage) {}, ""},
  602. {func(msg *ProposalPOLMessage) { msg.Height = -1 }, "negative Height"},
  603. {func(msg *ProposalPOLMessage) { msg.ProposalPOLRound = -1 }, "negative ProposalPOLRound"},
  604. {func(msg *ProposalPOLMessage) { msg.ProposalPOL = bits.NewBitArray(0) }, "empty ProposalPOL bit array"},
  605. {func(msg *ProposalPOLMessage) { msg.ProposalPOL = bits.NewBitArray(types.MaxVotesCount + 1) },
  606. "proposalPOL bit array is too big: 10001, max: 10000"},
  607. }
  608. for i, tc := range testCases {
  609. tc := tc
  610. t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
  611. msg := &ProposalPOLMessage{
  612. Height: 1,
  613. ProposalPOLRound: 1,
  614. ProposalPOL: bits.NewBitArray(1),
  615. }
  616. tc.malleateFn(msg)
  617. err := msg.ValidateBasic()
  618. if tc.expErr != "" && assert.Error(t, err) {
  619. assert.Contains(t, err.Error(), tc.expErr)
  620. }
  621. })
  622. }
  623. }
  624. func TestBlockPartMessageValidateBasic(t *testing.T) {
  625. testPart := new(types.Part)
  626. testPart.Proof.LeafHash = tmhash.Sum([]byte("leaf"))
  627. testCases := []struct {
  628. testName string
  629. messageHeight int64
  630. messageRound int32
  631. messagePart *types.Part
  632. expectErr bool
  633. }{
  634. {"Valid Message", 0, 0, testPart, false},
  635. {"Invalid Message", -1, 0, testPart, true},
  636. {"Invalid Message", 0, -1, testPart, true},
  637. }
  638. for _, tc := range testCases {
  639. tc := tc
  640. t.Run(tc.testName, func(t *testing.T) {
  641. message := BlockPartMessage{
  642. Height: tc.messageHeight,
  643. Round: tc.messageRound,
  644. Part: tc.messagePart,
  645. }
  646. assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  647. })
  648. }
  649. message := BlockPartMessage{Height: 0, Round: 0, Part: new(types.Part)}
  650. message.Part.Index = 1
  651. assert.Equal(t, true, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  652. }
  653. func TestHasVoteMessageValidateBasic(t *testing.T) {
  654. const (
  655. validSignedMsgType tmproto.SignedMsgType = 0x01
  656. invalidSignedMsgType tmproto.SignedMsgType = 0x03
  657. )
  658. testCases := []struct { // nolint: maligned
  659. expectErr bool
  660. messageRound int32
  661. messageIndex int32
  662. messageHeight int64
  663. testName string
  664. messageType tmproto.SignedMsgType
  665. }{
  666. {false, 0, 0, 0, "Valid Message", validSignedMsgType},
  667. {true, -1, 0, 0, "Invalid Message", validSignedMsgType},
  668. {true, 0, -1, 0, "Invalid Message", validSignedMsgType},
  669. {true, 0, 0, 0, "Invalid Message", invalidSignedMsgType},
  670. {true, 0, 0, -1, "Invalid Message", validSignedMsgType},
  671. }
  672. for _, tc := range testCases {
  673. tc := tc
  674. t.Run(tc.testName, func(t *testing.T) {
  675. message := HasVoteMessage{
  676. Height: tc.messageHeight,
  677. Round: tc.messageRound,
  678. Type: tc.messageType,
  679. Index: tc.messageIndex,
  680. }
  681. assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  682. })
  683. }
  684. }