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.

733 lines
20 KiB

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