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.

164 lines
6.0 KiB

7 years ago
  1. package types
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "time"
  6. "github.com/tendermint/tendermint/types"
  7. cmn "github.com/tendermint/tmlibs/common"
  8. )
  9. //-----------------------------------------------------------------------------
  10. // RoundStepType enum type
  11. // RoundStepType enumerates the state of the consensus state machine
  12. type RoundStepType uint8 // These must be numeric, ordered.
  13. // RoundStepType
  14. const (
  15. RoundStepNewHeight = RoundStepType(0x01) // Wait til CommitTime + timeoutCommit
  16. RoundStepNewRound = RoundStepType(0x02) // Setup new round and go to RoundStepPropose
  17. RoundStepPropose = RoundStepType(0x03) // Did propose, gossip proposal
  18. RoundStepPrevote = RoundStepType(0x04) // Did prevote, gossip prevotes
  19. RoundStepPrevoteWait = RoundStepType(0x05) // Did receive any +2/3 prevotes, start timeout
  20. RoundStepPrecommit = RoundStepType(0x06) // Did precommit, gossip precommits
  21. RoundStepPrecommitWait = RoundStepType(0x07) // Did receive any +2/3 precommits, start timeout
  22. RoundStepCommit = RoundStepType(0x08) // Entered commit state machine
  23. // NOTE: RoundStepNewHeight acts as RoundStepCommitWait.
  24. )
  25. // String returns a string
  26. func (rs RoundStepType) String() string {
  27. switch rs {
  28. case RoundStepNewHeight:
  29. return "RoundStepNewHeight"
  30. case RoundStepNewRound:
  31. return "RoundStepNewRound"
  32. case RoundStepPropose:
  33. return "RoundStepPropose"
  34. case RoundStepPrevote:
  35. return "RoundStepPrevote"
  36. case RoundStepPrevoteWait:
  37. return "RoundStepPrevoteWait"
  38. case RoundStepPrecommit:
  39. return "RoundStepPrecommit"
  40. case RoundStepPrecommitWait:
  41. return "RoundStepPrecommitWait"
  42. case RoundStepCommit:
  43. return "RoundStepCommit"
  44. default:
  45. return "RoundStepUnknown" // Cannot panic.
  46. }
  47. }
  48. //-----------------------------------------------------------------------------
  49. // RoundState defines the internal consensus state.
  50. // NOTE: Not thread safe. Should only be manipulated by functions downstream
  51. // of the cs.receiveRoutine
  52. type RoundState struct {
  53. Height int64 `json:"height"` // Height we are working on
  54. Round int `json:"round"`
  55. Step RoundStepType `json:"step"`
  56. StartTime time.Time `json:"start_time"`
  57. CommitTime time.Time `json:"commit_time"` // Subjective time when +2/3 precommits for Block at Round were found
  58. Validators *types.ValidatorSet `json:"validators"`
  59. Proposal *types.Proposal `json:"proposal"`
  60. ProposalBlock *types.Block `json:"proposal_block"`
  61. ProposalBlockParts *types.PartSet `json:"proposal_block_parts"`
  62. LockedRound int `json:"locked_round"`
  63. LockedBlock *types.Block `json:"locked_block"`
  64. LockedBlockParts *types.PartSet `json:"locked_block_parts"`
  65. ValidRound int `json:"valid_round"` // Last known round with POL for non-nil valid block.
  66. ValidBlock *types.Block `json:"valid_block"` // Last known block of POL mentioned above.
  67. ValidBlockParts *types.PartSet `json:"valid_block_parts"` // Last known block parts of POL metnioned above.
  68. Votes *HeightVoteSet `json:"votes"`
  69. CommitRound int `json:"commit_round"` //
  70. LastCommit *types.VoteSet `json:"last_commit"` // Last precommits at Height-1
  71. LastValidators *types.ValidatorSet `json:"last_validators"`
  72. }
  73. // Compressed version of the RoundState for use in RPC
  74. type RoundStateSimple struct {
  75. HeightRoundStep string `json:"height/round/step"`
  76. StartTime time.Time `json:"start_time"`
  77. ProposalBlockHash cmn.HexBytes `json:"proposal_block_hash"`
  78. LockedBlockHash cmn.HexBytes `json:"locked_block_hash"`
  79. ValidBlockHash cmn.HexBytes `json:"valid_block_hash"`
  80. Votes json.RawMessage `json:"height_vote_set"`
  81. }
  82. // Compress the RoundState to RoundStateSimple
  83. func (rs *RoundState) RoundStateSimple() RoundStateSimple {
  84. votesJSON, err := rs.Votes.MarshalJSON()
  85. if err != nil {
  86. panic(err)
  87. }
  88. return RoundStateSimple{
  89. HeightRoundStep: fmt.Sprintf("%d/%d/%d", rs.Height, rs.Round, rs.Step),
  90. StartTime: rs.StartTime,
  91. ProposalBlockHash: rs.ProposalBlock.Hash(),
  92. LockedBlockHash: rs.LockedBlock.Hash(),
  93. ValidBlockHash: rs.ValidBlock.Hash(),
  94. Votes: votesJSON,
  95. }
  96. }
  97. // RoundStateEvent returns the H/R/S of the RoundState as an event.
  98. func (rs *RoundState) RoundStateEvent() types.EventDataRoundState {
  99. // XXX: copy the RoundState
  100. // if we want to avoid this, we may need synchronous events after all
  101. rsCopy := *rs
  102. edrs := types.EventDataRoundState{
  103. Height: rs.Height,
  104. Round: rs.Round,
  105. Step: rs.Step.String(),
  106. RoundState: &rsCopy,
  107. }
  108. return edrs
  109. }
  110. // String returns a string
  111. func (rs *RoundState) String() string {
  112. return rs.StringIndented("")
  113. }
  114. // StringIndented returns a string
  115. func (rs *RoundState) StringIndented(indent string) string {
  116. return fmt.Sprintf(`RoundState{
  117. %s H:%v R:%v S:%v
  118. %s StartTime: %v
  119. %s CommitTime: %v
  120. %s Validators: %v
  121. %s Proposal: %v
  122. %s ProposalBlock: %v %v
  123. %s LockedRound: %v
  124. %s LockedBlock: %v %v
  125. %s ValidRound: %v
  126. %s ValidBlock: %v %v
  127. %s Votes: %v
  128. %s LastCommit: %v
  129. %s LastValidators:%v
  130. %s}`,
  131. indent, rs.Height, rs.Round, rs.Step,
  132. indent, rs.StartTime,
  133. indent, rs.CommitTime,
  134. indent, rs.Validators.StringIndented(indent+" "),
  135. indent, rs.Proposal,
  136. indent, rs.ProposalBlockParts.StringShort(), rs.ProposalBlock.StringShort(),
  137. indent, rs.LockedRound,
  138. indent, rs.LockedBlockParts.StringShort(), rs.LockedBlock.StringShort(),
  139. indent, rs.ValidRound,
  140. indent, rs.ValidBlockParts.StringShort(), rs.ValidBlock.StringShort(),
  141. indent, rs.Votes.StringIndented(indent+" "),
  142. indent, rs.LastCommit.StringShort(),
  143. indent, rs.LastValidators.StringIndented(indent+" "),
  144. indent)
  145. }
  146. // StringShort returns a string
  147. func (rs *RoundState) StringShort() string {
  148. return fmt.Sprintf(`RoundState{H:%v R:%v S:%v ST:%v}`,
  149. rs.Height, rs.Round, rs.Step, rs.StartTime)
  150. }