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.

704 lines
19 KiB

  1. package consensus
  2. import (
  3. "errors"
  4. "fmt"
  5. cstypes "github.com/tendermint/tendermint/internal/consensus/types"
  6. "github.com/tendermint/tendermint/internal/jsontypes"
  7. "github.com/tendermint/tendermint/libs/bits"
  8. tmmath "github.com/tendermint/tendermint/libs/math"
  9. tmcons "github.com/tendermint/tendermint/proto/tendermint/consensus"
  10. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  11. "github.com/tendermint/tendermint/types"
  12. )
  13. // Message defines an interface that the consensus domain types implement. When
  14. // a proto message is received on a consensus p2p Channel, it is wrapped and then
  15. // converted to a Message via MsgFromProto.
  16. type Message interface {
  17. ValidateBasic() error
  18. jsontypes.Tagged
  19. }
  20. func init() {
  21. jsontypes.MustRegister(&NewRoundStepMessage{})
  22. jsontypes.MustRegister(&NewValidBlockMessage{})
  23. jsontypes.MustRegister(&ProposalMessage{})
  24. jsontypes.MustRegister(&ProposalPOLMessage{})
  25. jsontypes.MustRegister(&BlockPartMessage{})
  26. jsontypes.MustRegister(&VoteMessage{})
  27. jsontypes.MustRegister(&HasVoteMessage{})
  28. jsontypes.MustRegister(&VoteSetMaj23Message{})
  29. jsontypes.MustRegister(&VoteSetBitsMessage{})
  30. }
  31. // NewRoundStepMessage is sent for every step taken in the ConsensusState.
  32. // For every height/round/step transition
  33. type NewRoundStepMessage struct {
  34. Height int64 `json:",string"`
  35. Round int32
  36. Step cstypes.RoundStepType
  37. SecondsSinceStartTime int64 `json:",string"`
  38. LastCommitRound int32
  39. }
  40. func (*NewRoundStepMessage) TypeTag() string { return "tendermint/NewRoundStepMessage" }
  41. // ValidateBasic performs basic validation.
  42. func (m *NewRoundStepMessage) ValidateBasic() error {
  43. if m.Height < 0 {
  44. return errors.New("negative Height")
  45. }
  46. if m.Round < 0 {
  47. return errors.New("negative Round")
  48. }
  49. if !m.Step.IsValid() {
  50. return errors.New("invalid Step")
  51. }
  52. // NOTE: SecondsSinceStartTime may be negative
  53. // LastCommitRound will be -1 for the initial height, but we don't know what height this is
  54. // since it can be specified in genesis. The reactor will have to validate this via
  55. // ValidateHeight().
  56. if m.LastCommitRound < -1 {
  57. return errors.New("invalid LastCommitRound (cannot be < -1)")
  58. }
  59. return nil
  60. }
  61. // ValidateHeight validates the height given the chain's initial height.
  62. func (m *NewRoundStepMessage) ValidateHeight(initialHeight int64) error {
  63. if m.Height < initialHeight {
  64. return fmt.Errorf("invalid Height %v (lower than initial height %v)",
  65. m.Height, initialHeight)
  66. }
  67. if m.Height == initialHeight && m.LastCommitRound != -1 {
  68. return fmt.Errorf("invalid LastCommitRound %v (must be -1 for initial height %v)",
  69. m.LastCommitRound, initialHeight)
  70. }
  71. if m.Height > initialHeight && m.LastCommitRound < 0 {
  72. return fmt.Errorf("LastCommitRound can only be negative for initial height %v",
  73. initialHeight)
  74. }
  75. return nil
  76. }
  77. // String returns a string representation.
  78. func (m *NewRoundStepMessage) String() string {
  79. return fmt.Sprintf("[NewRoundStep H:%v R:%v S:%v LCR:%v]",
  80. m.Height, m.Round, m.Step, m.LastCommitRound)
  81. }
  82. // NewValidBlockMessage is sent when a validator observes a valid block B in some round r,
  83. // i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r.
  84. // In case the block is also committed, then IsCommit flag is set to true.
  85. type NewValidBlockMessage struct {
  86. Height int64 `json:",string"`
  87. Round int32
  88. BlockPartSetHeader types.PartSetHeader
  89. BlockParts *bits.BitArray
  90. IsCommit bool
  91. }
  92. func (*NewValidBlockMessage) TypeTag() string { return "tendermint/NewValidBlockMessage" }
  93. // ValidateBasic performs basic validation.
  94. func (m *NewValidBlockMessage) ValidateBasic() error {
  95. if m.Height < 0 {
  96. return errors.New("negative Height")
  97. }
  98. if m.Round < 0 {
  99. return errors.New("negative Round")
  100. }
  101. if err := m.BlockPartSetHeader.ValidateBasic(); err != nil {
  102. return fmt.Errorf("wrong BlockPartSetHeader: %w", err)
  103. }
  104. if m.BlockParts.Size() == 0 {
  105. return errors.New("empty blockParts")
  106. }
  107. if m.BlockParts.Size() != int(m.BlockPartSetHeader.Total) {
  108. return fmt.Errorf("blockParts bit array size %d not equal to BlockPartSetHeader.Total %d",
  109. m.BlockParts.Size(),
  110. m.BlockPartSetHeader.Total)
  111. }
  112. if m.BlockParts.Size() > int(types.MaxBlockPartsCount) {
  113. return fmt.Errorf("blockParts bit array is too big: %d, max: %d", m.BlockParts.Size(), types.MaxBlockPartsCount)
  114. }
  115. return nil
  116. }
  117. // String returns a string representation.
  118. func (m *NewValidBlockMessage) String() string {
  119. return fmt.Sprintf("[ValidBlockMessage H:%v R:%v BP:%v BA:%v IsCommit:%v]",
  120. m.Height, m.Round, m.BlockPartSetHeader, m.BlockParts, m.IsCommit)
  121. }
  122. // ProposalMessage is sent when a new block is proposed.
  123. type ProposalMessage struct {
  124. Proposal *types.Proposal
  125. }
  126. func (*ProposalMessage) TypeTag() string { return "tendermint/Proposal" }
  127. // ValidateBasic performs basic validation.
  128. func (m *ProposalMessage) ValidateBasic() error {
  129. return m.Proposal.ValidateBasic()
  130. }
  131. // String returns a string representation.
  132. func (m *ProposalMessage) String() string {
  133. return fmt.Sprintf("[Proposal %v]", m.Proposal)
  134. }
  135. // ProposalPOLMessage is sent when a previous proposal is re-proposed.
  136. type ProposalPOLMessage struct {
  137. Height int64 `json:",string"`
  138. ProposalPOLRound int32
  139. ProposalPOL *bits.BitArray
  140. }
  141. func (*ProposalPOLMessage) TypeTag() string { return "tendermint/ProposalPOL" }
  142. // ValidateBasic performs basic validation.
  143. func (m *ProposalPOLMessage) ValidateBasic() error {
  144. if m.Height < 0 {
  145. return errors.New("negative Height")
  146. }
  147. if m.ProposalPOLRound < 0 {
  148. return errors.New("negative ProposalPOLRound")
  149. }
  150. if m.ProposalPOL.Size() == 0 {
  151. return errors.New("empty ProposalPOL bit array")
  152. }
  153. if m.ProposalPOL.Size() > types.MaxVotesCount {
  154. return fmt.Errorf("proposalPOL bit array is too big: %d, max: %d", m.ProposalPOL.Size(), types.MaxVotesCount)
  155. }
  156. return nil
  157. }
  158. // String returns a string representation.
  159. func (m *ProposalPOLMessage) String() string {
  160. return fmt.Sprintf("[ProposalPOL H:%v POLR:%v POL:%v]", m.Height, m.ProposalPOLRound, m.ProposalPOL)
  161. }
  162. // BlockPartMessage is sent when gossipping a piece of the proposed block.
  163. type BlockPartMessage struct {
  164. Height int64 `json:",string"`
  165. Round int32
  166. Part *types.Part
  167. }
  168. func (*BlockPartMessage) TypeTag() string { return "tendermint/BlockPart" }
  169. // ValidateBasic performs basic validation.
  170. func (m *BlockPartMessage) ValidateBasic() error {
  171. if m.Height < 0 {
  172. return errors.New("negative Height")
  173. }
  174. if m.Round < 0 {
  175. return errors.New("negative Round")
  176. }
  177. if err := m.Part.ValidateBasic(); err != nil {
  178. return fmt.Errorf("wrong Part: %w", err)
  179. }
  180. return nil
  181. }
  182. // String returns a string representation.
  183. func (m *BlockPartMessage) String() string {
  184. return fmt.Sprintf("[BlockPart H:%v R:%v P:%v]", m.Height, m.Round, m.Part)
  185. }
  186. // VoteMessage is sent when voting for a proposal (or lack thereof).
  187. type VoteMessage struct {
  188. Vote *types.Vote
  189. }
  190. func (*VoteMessage) TypeTag() string { return "tendermint/Vote" }
  191. // ValidateBasic performs basic validation.
  192. func (m *VoteMessage) ValidateBasic() error {
  193. return m.Vote.ValidateBasic()
  194. }
  195. // String returns a string representation.
  196. func (m *VoteMessage) String() string {
  197. return fmt.Sprintf("[Vote %v]", m.Vote)
  198. }
  199. // HasVoteMessage is sent to indicate that a particular vote has been received.
  200. type HasVoteMessage struct {
  201. Height int64 `json:",string"`
  202. Round int32
  203. Type tmproto.SignedMsgType
  204. Index int32
  205. }
  206. func (*HasVoteMessage) TypeTag() string { return "tendermint/HasVote" }
  207. // ValidateBasic performs basic validation.
  208. func (m *HasVoteMessage) ValidateBasic() error {
  209. if m.Height < 0 {
  210. return errors.New("negative Height")
  211. }
  212. if m.Round < 0 {
  213. return errors.New("negative Round")
  214. }
  215. if !types.IsVoteTypeValid(m.Type) {
  216. return errors.New("invalid Type")
  217. }
  218. if m.Index < 0 {
  219. return errors.New("negative Index")
  220. }
  221. return nil
  222. }
  223. // String returns a string representation.
  224. func (m *HasVoteMessage) String() string {
  225. return fmt.Sprintf("[HasVote VI:%v V:{%v/%02d/%v}]", m.Index, m.Height, m.Round, m.Type)
  226. }
  227. // VoteSetMaj23Message is sent to indicate that a given BlockID has seen +2/3 votes.
  228. type VoteSetMaj23Message struct {
  229. Height int64 `json:",string"`
  230. Round int32
  231. Type tmproto.SignedMsgType
  232. BlockID types.BlockID
  233. }
  234. func (*VoteSetMaj23Message) TypeTag() string { return "tendermint/VoteSetMaj23" }
  235. // ValidateBasic performs basic validation.
  236. func (m *VoteSetMaj23Message) ValidateBasic() error {
  237. if m.Height < 0 {
  238. return errors.New("negative Height")
  239. }
  240. if m.Round < 0 {
  241. return errors.New("negative Round")
  242. }
  243. if !types.IsVoteTypeValid(m.Type) {
  244. return errors.New("invalid Type")
  245. }
  246. if err := m.BlockID.ValidateBasic(); err != nil {
  247. return fmt.Errorf("wrong BlockID: %w", err)
  248. }
  249. return nil
  250. }
  251. // String returns a string representation.
  252. func (m *VoteSetMaj23Message) String() string {
  253. return fmt.Sprintf("[VSM23 %v/%02d/%v %v]", m.Height, m.Round, m.Type, m.BlockID)
  254. }
  255. // VoteSetBitsMessage is sent to communicate the bit-array of votes seen for the
  256. // BlockID.
  257. type VoteSetBitsMessage struct {
  258. Height int64 `json:",string"`
  259. Round int32
  260. Type tmproto.SignedMsgType
  261. BlockID types.BlockID
  262. Votes *bits.BitArray
  263. }
  264. func (*VoteSetBitsMessage) TypeTag() string { return "tendermint/VoteSetBits" }
  265. // ValidateBasic performs basic validation.
  266. func (m *VoteSetBitsMessage) ValidateBasic() error {
  267. if m.Height < 0 {
  268. return errors.New("negative Height")
  269. }
  270. if !types.IsVoteTypeValid(m.Type) {
  271. return errors.New("invalid Type")
  272. }
  273. if err := m.BlockID.ValidateBasic(); err != nil {
  274. return fmt.Errorf("wrong BlockID: %w", err)
  275. }
  276. // NOTE: Votes.Size() can be zero if the node does not have any
  277. if m.Votes.Size() > types.MaxVotesCount {
  278. return fmt.Errorf("votes bit array is too big: %d, max: %d", m.Votes.Size(), types.MaxVotesCount)
  279. }
  280. return nil
  281. }
  282. // String returns a string representation.
  283. func (m *VoteSetBitsMessage) String() string {
  284. return fmt.Sprintf("[VSB %v/%02d/%v %v %v]", m.Height, m.Round, m.Type, m.BlockID, m.Votes)
  285. }
  286. // MsgToProto takes a consensus message type and returns the proto defined
  287. // consensus message.
  288. //
  289. // TODO: This needs to be removed, but WALToProto depends on this.
  290. func MsgToProto(msg Message) (*tmcons.Message, error) {
  291. if msg == nil {
  292. return nil, errors.New("consensus: message is nil")
  293. }
  294. var pb tmcons.Message
  295. switch msg := msg.(type) {
  296. case *NewRoundStepMessage:
  297. pb = tmcons.Message{
  298. Sum: &tmcons.Message_NewRoundStep{
  299. NewRoundStep: &tmcons.NewRoundStep{
  300. Height: msg.Height,
  301. Round: msg.Round,
  302. Step: uint32(msg.Step),
  303. SecondsSinceStartTime: msg.SecondsSinceStartTime,
  304. LastCommitRound: msg.LastCommitRound,
  305. },
  306. },
  307. }
  308. case *NewValidBlockMessage:
  309. pbPartSetHeader := msg.BlockPartSetHeader.ToProto()
  310. pbBits := msg.BlockParts.ToProto()
  311. pb = tmcons.Message{
  312. Sum: &tmcons.Message_NewValidBlock{
  313. NewValidBlock: &tmcons.NewValidBlock{
  314. Height: msg.Height,
  315. Round: msg.Round,
  316. BlockPartSetHeader: pbPartSetHeader,
  317. BlockParts: pbBits,
  318. IsCommit: msg.IsCommit,
  319. },
  320. },
  321. }
  322. case *ProposalMessage:
  323. pbP := msg.Proposal.ToProto()
  324. pb = tmcons.Message{
  325. Sum: &tmcons.Message_Proposal{
  326. Proposal: &tmcons.Proposal{
  327. Proposal: *pbP,
  328. },
  329. },
  330. }
  331. case *ProposalPOLMessage:
  332. pbBits := msg.ProposalPOL.ToProto()
  333. pb = tmcons.Message{
  334. Sum: &tmcons.Message_ProposalPol{
  335. ProposalPol: &tmcons.ProposalPOL{
  336. Height: msg.Height,
  337. ProposalPolRound: msg.ProposalPOLRound,
  338. ProposalPol: *pbBits,
  339. },
  340. },
  341. }
  342. case *BlockPartMessage:
  343. parts, err := msg.Part.ToProto()
  344. if err != nil {
  345. return nil, fmt.Errorf("msg to proto error: %w", err)
  346. }
  347. pb = tmcons.Message{
  348. Sum: &tmcons.Message_BlockPart{
  349. BlockPart: &tmcons.BlockPart{
  350. Height: msg.Height,
  351. Round: msg.Round,
  352. Part: *parts,
  353. },
  354. },
  355. }
  356. case *VoteMessage:
  357. vote := msg.Vote.ToProto()
  358. pb = tmcons.Message{
  359. Sum: &tmcons.Message_Vote{
  360. Vote: &tmcons.Vote{
  361. Vote: vote,
  362. },
  363. },
  364. }
  365. case *HasVoteMessage:
  366. pb = tmcons.Message{
  367. Sum: &tmcons.Message_HasVote{
  368. HasVote: &tmcons.HasVote{
  369. Height: msg.Height,
  370. Round: msg.Round,
  371. Type: msg.Type,
  372. Index: msg.Index,
  373. },
  374. },
  375. }
  376. case *VoteSetMaj23Message:
  377. bi := msg.BlockID.ToProto()
  378. pb = tmcons.Message{
  379. Sum: &tmcons.Message_VoteSetMaj23{
  380. VoteSetMaj23: &tmcons.VoteSetMaj23{
  381. Height: msg.Height,
  382. Round: msg.Round,
  383. Type: msg.Type,
  384. BlockID: bi,
  385. },
  386. },
  387. }
  388. case *VoteSetBitsMessage:
  389. bi := msg.BlockID.ToProto()
  390. bits := msg.Votes.ToProto()
  391. vsb := &tmcons.Message_VoteSetBits{
  392. VoteSetBits: &tmcons.VoteSetBits{
  393. Height: msg.Height,
  394. Round: msg.Round,
  395. Type: msg.Type,
  396. BlockID: bi,
  397. },
  398. }
  399. if bits != nil {
  400. vsb.VoteSetBits.Votes = *bits
  401. }
  402. pb = tmcons.Message{
  403. Sum: vsb,
  404. }
  405. default:
  406. return nil, fmt.Errorf("consensus: message not recognized: %T", msg)
  407. }
  408. return &pb, nil
  409. }
  410. // MsgFromProto takes a consensus proto message and returns the native go type.
  411. func MsgFromProto(msg *tmcons.Message) (Message, error) {
  412. if msg == nil {
  413. return nil, errors.New("consensus: nil message")
  414. }
  415. var pb Message
  416. switch msg := msg.Sum.(type) {
  417. case *tmcons.Message_NewRoundStep:
  418. rs, err := tmmath.SafeConvertUint8(int64(msg.NewRoundStep.Step))
  419. // deny message based on possible overflow
  420. if err != nil {
  421. return nil, fmt.Errorf("denying message due to possible overflow: %w", err)
  422. }
  423. pb = &NewRoundStepMessage{
  424. Height: msg.NewRoundStep.Height,
  425. Round: msg.NewRoundStep.Round,
  426. Step: cstypes.RoundStepType(rs),
  427. SecondsSinceStartTime: msg.NewRoundStep.SecondsSinceStartTime,
  428. LastCommitRound: msg.NewRoundStep.LastCommitRound,
  429. }
  430. case *tmcons.Message_NewValidBlock:
  431. pbPartSetHeader, err := types.PartSetHeaderFromProto(&msg.NewValidBlock.BlockPartSetHeader)
  432. if err != nil {
  433. return nil, fmt.Errorf("parts header to proto error: %w", err)
  434. }
  435. pbBits := new(bits.BitArray)
  436. err = pbBits.FromProto(msg.NewValidBlock.BlockParts)
  437. if err != nil {
  438. return nil, fmt.Errorf("parts to proto error: %w", err)
  439. }
  440. pb = &NewValidBlockMessage{
  441. Height: msg.NewValidBlock.Height,
  442. Round: msg.NewValidBlock.Round,
  443. BlockPartSetHeader: *pbPartSetHeader,
  444. BlockParts: pbBits,
  445. IsCommit: msg.NewValidBlock.IsCommit,
  446. }
  447. case *tmcons.Message_Proposal:
  448. pbP, err := types.ProposalFromProto(&msg.Proposal.Proposal)
  449. if err != nil {
  450. return nil, fmt.Errorf("proposal msg to proto error: %w", err)
  451. }
  452. pb = &ProposalMessage{
  453. Proposal: pbP,
  454. }
  455. case *tmcons.Message_ProposalPol:
  456. pbBits := new(bits.BitArray)
  457. err := pbBits.FromProto(&msg.ProposalPol.ProposalPol)
  458. if err != nil {
  459. return nil, fmt.Errorf("proposal PoL to proto error: %w", err)
  460. }
  461. pb = &ProposalPOLMessage{
  462. Height: msg.ProposalPol.Height,
  463. ProposalPOLRound: msg.ProposalPol.ProposalPolRound,
  464. ProposalPOL: pbBits,
  465. }
  466. case *tmcons.Message_BlockPart:
  467. parts, err := types.PartFromProto(&msg.BlockPart.Part)
  468. if err != nil {
  469. return nil, fmt.Errorf("blockpart msg to proto error: %w", err)
  470. }
  471. pb = &BlockPartMessage{
  472. Height: msg.BlockPart.Height,
  473. Round: msg.BlockPart.Round,
  474. Part: parts,
  475. }
  476. case *tmcons.Message_Vote:
  477. vote, err := types.VoteFromProto(msg.Vote.Vote)
  478. if err != nil {
  479. return nil, fmt.Errorf("vote msg to proto error: %w", err)
  480. }
  481. pb = &VoteMessage{
  482. Vote: vote,
  483. }
  484. case *tmcons.Message_HasVote:
  485. pb = &HasVoteMessage{
  486. Height: msg.HasVote.Height,
  487. Round: msg.HasVote.Round,
  488. Type: msg.HasVote.Type,
  489. Index: msg.HasVote.Index,
  490. }
  491. case *tmcons.Message_VoteSetMaj23:
  492. bi, err := types.BlockIDFromProto(&msg.VoteSetMaj23.BlockID)
  493. if err != nil {
  494. return nil, fmt.Errorf("voteSetMaj23 msg to proto error: %w", err)
  495. }
  496. pb = &VoteSetMaj23Message{
  497. Height: msg.VoteSetMaj23.Height,
  498. Round: msg.VoteSetMaj23.Round,
  499. Type: msg.VoteSetMaj23.Type,
  500. BlockID: *bi,
  501. }
  502. case *tmcons.Message_VoteSetBits:
  503. bi, err := types.BlockIDFromProto(&msg.VoteSetBits.BlockID)
  504. if err != nil {
  505. return nil, fmt.Errorf("block ID to proto error: %w", err)
  506. }
  507. bits := new(bits.BitArray)
  508. err = bits.FromProto(&msg.VoteSetBits.Votes)
  509. if err != nil {
  510. return nil, fmt.Errorf("votes to proto error: %w", err)
  511. }
  512. pb = &VoteSetBitsMessage{
  513. Height: msg.VoteSetBits.Height,
  514. Round: msg.VoteSetBits.Round,
  515. Type: msg.VoteSetBits.Type,
  516. BlockID: *bi,
  517. Votes: bits,
  518. }
  519. default:
  520. return nil, fmt.Errorf("consensus: message not recognized: %T", msg)
  521. }
  522. if err := pb.ValidateBasic(); err != nil {
  523. return nil, err
  524. }
  525. return pb, nil
  526. }
  527. // WALToProto takes a WAL message and return a proto walMessage and error.
  528. func WALToProto(msg WALMessage) (*tmcons.WALMessage, error) {
  529. var pb tmcons.WALMessage
  530. switch msg := msg.(type) {
  531. case types.EventDataRoundState:
  532. pb = tmcons.WALMessage{
  533. Sum: &tmcons.WALMessage_EventDataRoundState{
  534. EventDataRoundState: &tmproto.EventDataRoundState{
  535. Height: msg.Height,
  536. Round: msg.Round,
  537. Step: msg.Step,
  538. },
  539. },
  540. }
  541. case msgInfo:
  542. consMsg, err := MsgToProto(msg.Msg)
  543. if err != nil {
  544. return nil, err
  545. }
  546. pb = tmcons.WALMessage{
  547. Sum: &tmcons.WALMessage_MsgInfo{
  548. MsgInfo: &tmcons.MsgInfo{
  549. Msg: *consMsg,
  550. PeerID: string(msg.PeerID),
  551. },
  552. },
  553. }
  554. case timeoutInfo:
  555. pb = tmcons.WALMessage{
  556. Sum: &tmcons.WALMessage_TimeoutInfo{
  557. TimeoutInfo: &tmcons.TimeoutInfo{
  558. Duration: msg.Duration,
  559. Height: msg.Height,
  560. Round: msg.Round,
  561. Step: uint32(msg.Step),
  562. },
  563. },
  564. }
  565. case EndHeightMessage:
  566. pb = tmcons.WALMessage{
  567. Sum: &tmcons.WALMessage_EndHeight{
  568. EndHeight: &tmcons.EndHeight{
  569. Height: msg.Height,
  570. },
  571. },
  572. }
  573. default:
  574. return nil, fmt.Errorf("to proto: wal message not recognized: %T", msg)
  575. }
  576. return &pb, nil
  577. }
  578. // WALFromProto takes a proto wal message and return a consensus walMessage and
  579. // error.
  580. func WALFromProto(msg *tmcons.WALMessage) (WALMessage, error) {
  581. if msg == nil {
  582. return nil, errors.New("nil WAL message")
  583. }
  584. var pb WALMessage
  585. switch msg := msg.Sum.(type) {
  586. case *tmcons.WALMessage_EventDataRoundState:
  587. pb = types.EventDataRoundState{
  588. Height: msg.EventDataRoundState.Height,
  589. Round: msg.EventDataRoundState.Round,
  590. Step: msg.EventDataRoundState.Step,
  591. }
  592. case *tmcons.WALMessage_MsgInfo:
  593. walMsg, err := MsgFromProto(&msg.MsgInfo.Msg)
  594. if err != nil {
  595. return nil, fmt.Errorf("msgInfo from proto error: %w", err)
  596. }
  597. pb = msgInfo{
  598. Msg: walMsg,
  599. PeerID: types.NodeID(msg.MsgInfo.PeerID),
  600. }
  601. case *tmcons.WALMessage_TimeoutInfo:
  602. tis, err := tmmath.SafeConvertUint8(int64(msg.TimeoutInfo.Step))
  603. // deny message based on possible overflow
  604. if err != nil {
  605. return nil, fmt.Errorf("denying message due to possible overflow: %w", err)
  606. }
  607. pb = timeoutInfo{
  608. Duration: msg.TimeoutInfo.Duration,
  609. Height: msg.TimeoutInfo.Height,
  610. Round: msg.TimeoutInfo.Round,
  611. Step: cstypes.RoundStepType(tis),
  612. }
  613. return pb, nil
  614. case *tmcons.WALMessage_EndHeight:
  615. pb := EndHeightMessage{
  616. Height: msg.EndHeight.Height,
  617. }
  618. return pb, nil
  619. default:
  620. return nil, fmt.Errorf("from proto: wal message not recognized: %T", msg)
  621. }
  622. return pb, nil
  623. }