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.

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