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.

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