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.

1120 lines
35 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /*
  2. Consensus State Machine Overview:
  3. * Propose, Prevote, Precommit represent state machine stages. (aka RoundStep, or step).
  4. Each take a predetermined amount of time depending on the round number.
  5. * The Commit step can be entered by two means:
  6. 1. After the Precommit step, +2/3 Precommits were found
  7. 2. At any time, +2/3 Commits were found
  8. * Once in the Commit stage, two conditions must both be satisfied
  9. before proceeding to the next height NewHeight.
  10. * The Propose step of the next height does not begin until
  11. at least Delta duration *after* +2/3 Commits were found.
  12. The step stays at NewHeight until this timeout occurs before
  13. proceeding to Propose.
  14. +-------------------------------------+
  15. | |
  16. v |(Wait til CommitTime + Delta)
  17. +-----------+ +-----+-----+
  18. +----------> | Propose +--------------+ | NewHeight |
  19. | +-----------+ | +-----------+
  20. | | ^
  21. | | |
  22. | | |
  23. |(Else) v |
  24. +-----+-----+ +-----------+ |
  25. | Precommit | <------------------------+ Prevote | |
  26. +-----+-----+ +-----------+ |
  27. |(If +2/3 Precommits found) |
  28. | |
  29. | + (When +2/3 Commits found) |
  30. | | |
  31. v v |
  32. +------------------------------------------------------------------------------+
  33. | Commit | |
  34. | | |
  35. | +----------------+ * Save Block | |
  36. | |Get Block Parts |---> * Stage Block +--+ + |
  37. | +----------------+ * Broadcast Commit | * Setup New Height |
  38. | | * Move Commits set to |
  39. | +--> LastCommits to continue |
  40. | | collecting commits |
  41. | +-----------------+ | * Broadcast New State |
  42. | |Get +2/3 Commits |--> * Set CommitTime +--+ |
  43. | +-----------------+ |
  44. | |
  45. +------------------------------------------------------------------------------+
  46. */
  47. package consensus
  48. import (
  49. "bytes"
  50. "errors"
  51. "fmt"
  52. "math"
  53. "sync"
  54. "sync/atomic"
  55. "time"
  56. . "github.com/tendermint/tendermint/account"
  57. . "github.com/tendermint/tendermint/binary"
  58. . "github.com/tendermint/tendermint/block"
  59. . "github.com/tendermint/tendermint/common"
  60. . "github.com/tendermint/tendermint/config"
  61. . "github.com/tendermint/tendermint/consensus/types"
  62. "github.com/tendermint/tendermint/mempool"
  63. "github.com/tendermint/tendermint/state"
  64. )
  65. const (
  66. roundDuration0 = 60 * time.Second // The first round is 60 seconds long.
  67. roundDurationDelta = 15 * time.Second // Each successive round lasts 15 seconds longer.
  68. roundDeadlinePrevote = float64(1.0 / 3.0) // When the prevote is due.
  69. roundDeadlinePrecommit = float64(2.0 / 3.0) // When the precommit vote is due.
  70. newHeightDelta = roundDuration0 / 3 // The time to wait between commitTime and startTime of next consensus rounds.
  71. )
  72. var (
  73. ErrInvalidProposalSignature = errors.New("Error invalid proposal signature")
  74. )
  75. //-----------------------------------------------------------------------------
  76. // RoundStep enum type
  77. type RoundStep uint8
  78. const (
  79. RoundStepNewHeight = RoundStep(0x00) // Round0 for new height started, wait til CommitTime + Delta
  80. RoundStepNewRound = RoundStep(0x01) // Pseudostep, immediately goes to RoundStepPropose
  81. RoundStepPropose = RoundStep(0x10) // Did propose, gossip proposal
  82. RoundStepPrevote = RoundStep(0x11) // Did prevote, gossip prevotes
  83. RoundStepPrecommit = RoundStep(0x12) // Did precommit, gossip precommits
  84. RoundStepCommit = RoundStep(0x20) // Entered commit state machine
  85. )
  86. func (rs RoundStep) String() string {
  87. switch rs {
  88. case RoundStepNewHeight:
  89. return "RoundStepNewHeight"
  90. case RoundStepNewRound:
  91. return "RoundStepNewRound"
  92. case RoundStepPropose:
  93. return "RoundStepPropose"
  94. case RoundStepPrevote:
  95. return "RoundStepPrevote"
  96. case RoundStepPrecommit:
  97. return "RoundStepPrecommit"
  98. case RoundStepCommit:
  99. return "RoundStepCommit"
  100. default:
  101. panic(Fmt("Unknown RoundStep %X", rs))
  102. }
  103. }
  104. //-----------------------------------------------------------------------------
  105. // RoundAction enum type
  106. type RoundActionType uint8
  107. const (
  108. RoundActionPropose = RoundActionType(0xA0) // Propose and goto RoundStepPropose
  109. RoundActionPrevote = RoundActionType(0xA1) // Prevote and goto RoundStepPrevote
  110. RoundActionPrecommit = RoundActionType(0xA2) // Precommit and goto RoundStepPrecommit
  111. RoundActionTryCommit = RoundActionType(0xC0) // Goto RoundStepCommit, or RoundStepPropose for next round.
  112. RoundActionCommit = RoundActionType(0xC1) // Goto RoundStepCommit upon +2/3 commits
  113. RoundActionTryFinalize = RoundActionType(0xC2) // Maybe goto RoundStepPropose for next round.
  114. )
  115. func (ra RoundActionType) String() string {
  116. switch ra {
  117. case RoundActionPropose:
  118. return "RoundActionPropose"
  119. case RoundActionPrevote:
  120. return "RoundActionPrevote"
  121. case RoundActionPrecommit:
  122. return "RoundActionPrecommit"
  123. case RoundActionTryCommit:
  124. return "RoundActionTryCommit"
  125. case RoundActionCommit:
  126. return "RoundActionCommit"
  127. case RoundActionTryFinalize:
  128. return "RoundActionTryFinalize"
  129. default:
  130. panic(Fmt("Unknown RoundAction %X", ra))
  131. }
  132. }
  133. //-----------------------------------------------------------------------------
  134. type RoundAction struct {
  135. Height uint // The block height for which consensus is reaching for.
  136. Round uint // The round number at given height.
  137. Action RoundActionType // Action to perform.
  138. }
  139. //-----------------------------------------------------------------------------
  140. // Immutable when returned from ConsensusState.GetRoundState()
  141. type RoundState struct {
  142. Height uint // Height we are working on
  143. Round uint
  144. Step RoundStep
  145. StartTime time.Time
  146. CommitTime time.Time // Time when +2/3 commits were found
  147. Validators *state.ValidatorSet
  148. Proposal *Proposal
  149. ProposalBlock *Block
  150. ProposalBlockParts *PartSet
  151. ProposalPOL *POL
  152. ProposalPOLParts *PartSet
  153. LockedBlock *Block
  154. LockedBlockParts *PartSet
  155. LockedPOL *POL // Rarely needed, so no LockedPOLParts.
  156. Prevotes *VoteSet
  157. Precommits *VoteSet
  158. Commits *VoteSet
  159. LastCommits *VoteSet
  160. PrivValidator *state.PrivValidator
  161. }
  162. func (rs *RoundState) String() string {
  163. return rs.StringIndented("")
  164. }
  165. func (rs *RoundState) StringIndented(indent string) string {
  166. return fmt.Sprintf(`RoundState{
  167. %s H:%v R:%v S:%v
  168. %s StartTime: %v
  169. %s CommitTime: %v
  170. %s Validators: %v
  171. %s Proposal: %v
  172. %s ProposalBlock: %v %v
  173. %s ProposalPOL: %v %v
  174. %s LockedBlock: %v %v
  175. %s LockedPOL: %v
  176. %s Prevotes: %v
  177. %s Precommits: %v
  178. %s Commits: %v
  179. %s LastCommits: %v
  180. %s}`,
  181. indent, rs.Height, rs.Round, rs.Step,
  182. indent, rs.StartTime,
  183. indent, rs.CommitTime,
  184. indent, rs.Validators.StringIndented(indent+" "),
  185. indent, rs.Proposal,
  186. indent, rs.ProposalBlockParts.StringShort(), rs.ProposalBlock.StringShort(),
  187. indent, rs.ProposalPOLParts.StringShort(), rs.ProposalPOL.StringShort(),
  188. indent, rs.LockedBlockParts.StringShort(), rs.LockedBlock.StringShort(),
  189. indent, rs.LockedPOL.StringShort(),
  190. indent, rs.Prevotes.StringIndented(indent+" "),
  191. indent, rs.Precommits.StringIndented(indent+" "),
  192. indent, rs.Commits.StringIndented(indent+" "),
  193. indent, rs.LastCommits.StringShort(),
  194. indent)
  195. }
  196. func (rs *RoundState) StringShort() string {
  197. return fmt.Sprintf(`RoundState{H:%v R:%v S:%v ST:%v}`,
  198. rs.Height, rs.Round, rs.Step, rs.StartTime)
  199. }
  200. //-----------------------------------------------------------------------------
  201. // Tracks consensus state across block heights and rounds.
  202. type ConsensusState struct {
  203. started uint32
  204. stopped uint32
  205. quit chan struct{}
  206. blockStore *BlockStore
  207. mempoolReactor *mempool.MempoolReactor
  208. runActionCh chan RoundAction
  209. newStepCh chan *RoundState
  210. mtx sync.Mutex
  211. RoundState
  212. state *state.State // State until height-1.
  213. stagedBlock *Block // Cache last staged block.
  214. stagedState *state.State // Cache result of staged block.
  215. lastCommittedHeight uint // Last called saveCommitVoteBlock() on.
  216. }
  217. func NewConsensusState(state *state.State, blockStore *BlockStore, mempoolReactor *mempool.MempoolReactor) *ConsensusState {
  218. cs := &ConsensusState{
  219. quit: make(chan struct{}),
  220. blockStore: blockStore,
  221. mempoolReactor: mempoolReactor,
  222. runActionCh: make(chan RoundAction, 1),
  223. newStepCh: make(chan *RoundState, 1),
  224. }
  225. cs.updateToState(state)
  226. return cs
  227. }
  228. func (cs *ConsensusState) GetRoundState() *RoundState {
  229. cs.mtx.Lock()
  230. defer cs.mtx.Unlock()
  231. return cs.getRoundState()
  232. }
  233. func (cs *ConsensusState) getRoundState() *RoundState {
  234. rs := cs.RoundState // copy
  235. return &rs
  236. }
  237. func (cs *ConsensusState) NewStepCh() chan *RoundState {
  238. return cs.newStepCh
  239. }
  240. func (cs *ConsensusState) Start() {
  241. if atomic.CompareAndSwapUint32(&cs.started, 0, 1) {
  242. log.Info("Starting ConsensusState")
  243. go cs.stepTransitionRoutine()
  244. }
  245. }
  246. func (cs *ConsensusState) Stop() {
  247. if atomic.CompareAndSwapUint32(&cs.stopped, 0, 1) {
  248. log.Info("Stopping ConsensusState")
  249. close(cs.quit)
  250. }
  251. }
  252. func (cs *ConsensusState) IsStopped() bool {
  253. return atomic.LoadUint32(&cs.stopped) == 1
  254. }
  255. func (cs *ConsensusState) queueAction(ra RoundAction) {
  256. go func() {
  257. cs.runActionCh <- ra
  258. }()
  259. }
  260. // Source of all round state transitions (and votes).
  261. func (cs *ConsensusState) stepTransitionRoutine() {
  262. // For clarity, all state transitions that happen after some timeout are here.
  263. // Schedule the next action by pushing a RoundAction{} to cs.runActionCh.
  264. scheduleNextAction := func() {
  265. go func() {
  266. // NOTE: We can push directly to runActionCh because
  267. // we're running in a separate goroutine, which avoids deadlocks.
  268. rs := cs.getRoundState()
  269. round, roundStartTime, roundDuration, _, elapsedRatio := calcRoundInfo(rs.StartTime)
  270. log.Info("Scheduling next action", "height", rs.Height, "round", round, "step", rs.Step, "roundStartTime", roundStartTime, "elapsedRatio", elapsedRatio)
  271. switch rs.Step {
  272. case RoundStepNewHeight:
  273. // We should run RoundActionPropose when rs.StartTime passes.
  274. if elapsedRatio < 0 {
  275. // startTime is in the future.
  276. time.Sleep(time.Duration((-1.0 * elapsedRatio) * float64(roundDuration)))
  277. }
  278. cs.runActionCh <- RoundAction{rs.Height, rs.Round, RoundActionPropose}
  279. case RoundStepNewRound:
  280. // Pseudostep: Immediately goto propose.
  281. cs.runActionCh <- RoundAction{rs.Height, rs.Round, RoundActionPropose}
  282. case RoundStepPropose:
  283. // Wake up when it's time to vote.
  284. time.Sleep(time.Duration((roundDeadlinePrevote - elapsedRatio) * float64(roundDuration)))
  285. cs.runActionCh <- RoundAction{rs.Height, rs.Round, RoundActionPrevote}
  286. case RoundStepPrevote:
  287. // Wake up when it's time to precommit.
  288. time.Sleep(time.Duration((roundDeadlinePrecommit - elapsedRatio) * float64(roundDuration)))
  289. cs.runActionCh <- RoundAction{rs.Height, rs.Round, RoundActionPrecommit}
  290. case RoundStepPrecommit:
  291. // Wake up when the round is over.
  292. time.Sleep(time.Duration((1.0 - elapsedRatio) * float64(roundDuration)))
  293. cs.runActionCh <- RoundAction{rs.Height, rs.Round, RoundActionTryCommit}
  294. case RoundStepCommit:
  295. // There's nothing to scheudle, we're waiting for
  296. // ProposalBlockParts.IsComplete() &&
  297. // Commits.HasTwoThirdsMajority()
  298. panic("The next action from RoundStepCommit is not scheduled by time")
  299. default:
  300. panic("Should not happen")
  301. }
  302. }()
  303. }
  304. scheduleNextAction()
  305. // NOTE: All ConsensusState.RunAction*() calls come from here.
  306. // Since only one routine calls them, it is safe to assume that
  307. // the RoundState Height/Round/Step won't change concurrently.
  308. // However, other fields like Proposal could change concurrent
  309. // due to gossip routines.
  310. ACTION_LOOP:
  311. for {
  312. var roundAction RoundAction
  313. select {
  314. case roundAction = <-cs.runActionCh:
  315. case <-cs.quit:
  316. return
  317. }
  318. height, round, action := roundAction.Height, roundAction.Round, roundAction.Action
  319. rs := cs.GetRoundState()
  320. log.Info("Running round action", "height", rs.Height, "round", rs.Round, "step", rs.Step, "action", action, "startTime", rs.StartTime)
  321. // Continue if action is not relevant
  322. if height != rs.Height {
  323. continue
  324. }
  325. // If action <= RoundActionPrecommit, the round must match too.
  326. if action <= RoundActionPrecommit && round != rs.Round {
  327. continue
  328. }
  329. // Run action
  330. switch action {
  331. case RoundActionPropose:
  332. if rs.Step != RoundStepNewHeight && rs.Step != RoundStepNewRound {
  333. continue ACTION_LOOP
  334. }
  335. cs.RunActionPropose(rs.Height, rs.Round)
  336. scheduleNextAction()
  337. continue ACTION_LOOP
  338. case RoundActionPrevote:
  339. if rs.Step >= RoundStepPrevote {
  340. continue ACTION_LOOP
  341. }
  342. cs.RunActionPrevote(rs.Height, rs.Round)
  343. scheduleNextAction()
  344. continue ACTION_LOOP
  345. case RoundActionPrecommit:
  346. if rs.Step >= RoundStepPrecommit {
  347. continue ACTION_LOOP
  348. }
  349. cs.RunActionPrecommit(rs.Height, rs.Round)
  350. scheduleNextAction()
  351. continue ACTION_LOOP
  352. case RoundActionTryCommit:
  353. if rs.Step >= RoundStepCommit {
  354. continue ACTION_LOOP
  355. }
  356. if rs.Precommits.HasTwoThirdsMajority() {
  357. // Enter RoundStepCommit and commit.
  358. cs.RunActionCommit(rs.Height)
  359. continue ACTION_LOOP
  360. } else {
  361. // Could not commit, move onto next round.
  362. cs.SetupNewRound(rs.Height, rs.Round+1)
  363. // cs.Step is now at RoundStepNewRound
  364. scheduleNextAction()
  365. continue ACTION_LOOP
  366. }
  367. case RoundActionCommit:
  368. if rs.Step >= RoundStepCommit {
  369. continue ACTION_LOOP
  370. }
  371. // Enter RoundStepCommit and commit.
  372. cs.RunActionCommit(rs.Height)
  373. continue ACTION_LOOP
  374. case RoundActionTryFinalize:
  375. if cs.TryFinalizeCommit(rs.Height) {
  376. // Now at new height
  377. // cs.Step is at RoundStepNewHeight or RoundStepNewRound.
  378. scheduleNextAction()
  379. continue ACTION_LOOP
  380. } else {
  381. // do not schedule next action.
  382. continue ACTION_LOOP
  383. }
  384. default:
  385. panic("Unknown action")
  386. }
  387. // For clarity, ensure that all switch cases call "continue"
  388. panic("Should not happen.")
  389. }
  390. }
  391. // Updates ConsensusState and increments height to match that of state.
  392. // If calculated round is greater than 0 (based on BlockTime or calculated StartTime)
  393. // then also sets up the appropriate round, and cs.Step becomes RoundStepNewRound.
  394. // Otherwise the round is 0 and cs.Step becomes RoundStepNewHeight.
  395. func (cs *ConsensusState) updateToState(state *state.State) {
  396. // Sanity check state.
  397. if cs.Height > 0 && cs.Height != state.LastBlockHeight {
  398. panic(Fmt("updateToState() expected state height of %v but found %v",
  399. cs.Height, state.LastBlockHeight))
  400. }
  401. // Reset fields based on state.
  402. validators := state.BondedValidators
  403. height := state.LastBlockHeight + 1 // next desired block height
  404. cs.Height = height
  405. cs.Round = 0
  406. cs.Step = RoundStepNewHeight
  407. if cs.CommitTime.IsZero() {
  408. cs.StartTime = state.LastBlockTime.Add(newHeightDelta)
  409. } else {
  410. cs.StartTime = cs.CommitTime.Add(newHeightDelta)
  411. }
  412. cs.CommitTime = time.Time{}
  413. cs.Validators = validators
  414. cs.Proposal = nil
  415. cs.ProposalBlock = nil
  416. cs.ProposalBlockParts = nil
  417. cs.ProposalPOL = nil
  418. cs.ProposalPOLParts = nil
  419. cs.LockedBlock = nil
  420. cs.LockedBlockParts = nil
  421. cs.LockedPOL = nil
  422. cs.Prevotes = NewVoteSet(height, 0, VoteTypePrevote, validators)
  423. cs.Precommits = NewVoteSet(height, 0, VoteTypePrecommit, validators)
  424. cs.LastCommits = cs.Commits
  425. cs.Commits = NewVoteSet(height, 0, VoteTypeCommit, validators)
  426. cs.state = state
  427. cs.stagedBlock = nil
  428. cs.stagedState = nil
  429. // Update the round if we need to.
  430. round := calcRound(cs.StartTime)
  431. if round > 0 {
  432. cs.setupNewRound(round)
  433. }
  434. // If we've timed out, then send rebond tx.
  435. if cs.PrivValidator != nil && cs.state.UnbondingValidators.HasAddress(cs.PrivValidator.Address) {
  436. rebondTx := &RebondTx{
  437. Address: cs.PrivValidator.Address,
  438. Height: cs.Height + 1,
  439. }
  440. err := cs.PrivValidator.SignRebondTx(rebondTx)
  441. if err == nil {
  442. log.Info("Signed and broadcast RebondTx", "height", cs.Height, "round", cs.Round, "tx", rebondTx)
  443. cs.mempoolReactor.BroadcastTx(rebondTx)
  444. } else {
  445. log.Warn("Error signing RebondTx", "height", cs.Height, "round", cs.Round, "tx", rebondTx, "error", err)
  446. }
  447. }
  448. }
  449. // After the call cs.Step becomes RoundStepNewRound.
  450. func (cs *ConsensusState) setupNewRound(round uint) {
  451. // Sanity check
  452. if round == 0 {
  453. panic("setupNewRound() should never be called for round 0")
  454. }
  455. // Increment all the way to round.
  456. validators := cs.Validators.Copy()
  457. validators.IncrementAccum(round - cs.Round)
  458. cs.Round = round
  459. cs.Step = RoundStepNewRound
  460. cs.Validators = validators
  461. cs.Proposal = nil
  462. cs.ProposalBlock = nil
  463. cs.ProposalBlockParts = nil
  464. cs.ProposalPOL = nil
  465. cs.ProposalPOLParts = nil
  466. cs.Prevotes = NewVoteSet(cs.Height, round, VoteTypePrevote, validators)
  467. cs.Prevotes.AddFromCommits(cs.Commits)
  468. cs.Precommits = NewVoteSet(cs.Height, round, VoteTypePrecommit, validators)
  469. cs.Precommits.AddFromCommits(cs.Commits)
  470. }
  471. func (cs *ConsensusState) SetPrivValidator(priv *state.PrivValidator) {
  472. cs.mtx.Lock()
  473. defer cs.mtx.Unlock()
  474. cs.PrivValidator = priv
  475. }
  476. //-----------------------------------------------------------------------------
  477. // Set up the round to desired round and set step to RoundStepNewRound
  478. func (cs *ConsensusState) SetupNewRound(height uint, desiredRound uint) bool {
  479. cs.mtx.Lock()
  480. defer cs.mtx.Unlock()
  481. if cs.Height != height {
  482. return false
  483. }
  484. if desiredRound <= cs.Round {
  485. return false
  486. }
  487. cs.setupNewRound(desiredRound)
  488. // c.Step is now RoundStepNewRound
  489. cs.newStepCh <- cs.getRoundState()
  490. return true
  491. }
  492. func (cs *ConsensusState) RunActionPropose(height uint, round uint) {
  493. cs.mtx.Lock()
  494. defer cs.mtx.Unlock()
  495. if cs.Height != height || cs.Round != round {
  496. return
  497. }
  498. defer func() {
  499. cs.Step = RoundStepPropose
  500. cs.newStepCh <- cs.getRoundState()
  501. }()
  502. // Nothing to do if it's not our turn.
  503. if cs.PrivValidator == nil || !bytes.Equal(cs.Validators.Proposer().Address, cs.PrivValidator.Address) {
  504. return
  505. }
  506. var block *Block
  507. var blockParts *PartSet
  508. var pol *POL
  509. var polParts *PartSet
  510. // Decide on block and POL
  511. if cs.LockedBlock != nil {
  512. // If we're locked onto a block, just choose that.
  513. block = cs.LockedBlock
  514. blockParts = cs.LockedBlockParts
  515. pol = cs.LockedPOL
  516. } else {
  517. // Otherwise we should create a new proposal.
  518. var validation *Validation
  519. if cs.Height == 1 {
  520. // We're creating a proposal for the first block.
  521. // The validation is empty.
  522. validation = &Validation{}
  523. } else {
  524. // We need to create a proposal.
  525. // If we don't have enough commits from the last height,
  526. // we can't do anything.
  527. if !cs.LastCommits.HasTwoThirdsMajority() {
  528. return
  529. } else {
  530. validation = cs.LastCommits.MakeValidation()
  531. }
  532. }
  533. txs := cs.mempoolReactor.Mempool.GetProposalTxs()
  534. block = &Block{
  535. Header: &Header{
  536. Network: Config.Network,
  537. Height: cs.Height,
  538. Time: time.Now(),
  539. Fees: 0, // TODO fees
  540. NumTxs: uint(len(txs)),
  541. LastBlockHash: cs.state.LastBlockHash,
  542. LastBlockParts: cs.state.LastBlockParts,
  543. StateHash: nil, // Will set afterwards.
  544. },
  545. Validation: validation,
  546. Data: &Data{
  547. Txs: txs,
  548. },
  549. }
  550. // Set the block.Header.StateHash.
  551. // TODO: we could cache the resulting state to cs.stagedState.
  552. // TODO: This is confusing, not clear that we're mutating block.
  553. cs.state.Copy().AppendBlock(block, PartSetHeader{}, false)
  554. blockParts = NewPartSetFromData(BinaryBytes(block))
  555. pol = cs.LockedPOL // If exists, is a PoUnlock.
  556. }
  557. if pol != nil {
  558. polParts = NewPartSetFromData(BinaryBytes(pol))
  559. }
  560. // Make proposal
  561. proposal := NewProposal(cs.Height, cs.Round, blockParts.Header(), polParts.Header())
  562. err := cs.PrivValidator.SignProposal(proposal)
  563. if err == nil {
  564. log.Info("Signed and set proposal", "height", cs.Height, "round", cs.Round, "proposal", proposal)
  565. // Set fields
  566. cs.Proposal = proposal
  567. cs.ProposalBlock = block
  568. cs.ProposalBlockParts = blockParts
  569. cs.ProposalPOL = pol
  570. cs.ProposalPOLParts = polParts
  571. } else {
  572. log.Warn("Error signing proposal", "height", cs.Height, "round", cs.Round, "error", err)
  573. }
  574. }
  575. // Prevote for LockedBlock if we're locked, or ProposealBlock if valid.
  576. // Otherwise vote nil.
  577. func (cs *ConsensusState) RunActionPrevote(height uint, round uint) {
  578. cs.mtx.Lock()
  579. defer cs.mtx.Unlock()
  580. if cs.Height != height || cs.Round != round {
  581. panic(Fmt("RunActionPrevote(%v/%v), expected %v/%v", height, round, cs.Height, cs.Round))
  582. }
  583. defer func() {
  584. cs.Step = RoundStepPrevote
  585. cs.newStepCh <- cs.getRoundState()
  586. }()
  587. // If a block is locked, prevote that.
  588. if cs.LockedBlock != nil {
  589. cs.signAddVote(VoteTypePrevote, cs.LockedBlock.Hash(), cs.LockedBlockParts.Header())
  590. return
  591. }
  592. // If ProposalBlock is nil, prevote nil.
  593. if cs.ProposalBlock == nil {
  594. log.Warn("ProposalBlock is nil")
  595. cs.signAddVote(VoteTypePrevote, nil, PartSetHeader{})
  596. return
  597. }
  598. // Try staging cs.ProposalBlock
  599. err := cs.stageBlock(cs.ProposalBlock, cs.ProposalBlockParts)
  600. if err != nil {
  601. // ProposalBlock is invalid, prevote nil.
  602. log.Warn("ProposalBlock is invalid", "error", err)
  603. cs.signAddVote(VoteTypePrevote, nil, PartSetHeader{})
  604. return
  605. }
  606. // Prevote cs.ProposalBlock
  607. cs.signAddVote(VoteTypePrevote, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header())
  608. return
  609. }
  610. // Lock & Precommit the ProposalBlock if we have enough prevotes for it,
  611. // or unlock an existing lock if +2/3 of prevotes were nil.
  612. func (cs *ConsensusState) RunActionPrecommit(height uint, round uint) {
  613. cs.mtx.Lock()
  614. defer cs.mtx.Unlock()
  615. if cs.Height != height || cs.Round != round {
  616. panic(Fmt("RunActionPrecommit(%v/%v), expected %v/%v", height, round, cs.Height, cs.Round))
  617. }
  618. defer func() {
  619. cs.Step = RoundStepPrecommit
  620. cs.newStepCh <- cs.getRoundState()
  621. }()
  622. hash, partsHeader, ok := cs.Prevotes.TwoThirdsMajority()
  623. if !ok {
  624. // If we don't have two thirds of prevotes,
  625. // don't do anything at all.
  626. return
  627. }
  628. // Remember this POL. (hash may be nil)
  629. cs.LockedPOL = cs.Prevotes.MakePOL()
  630. // If +2/3 prevoted nil. Just unlock.
  631. if len(hash) == 0 {
  632. cs.LockedBlock = nil
  633. cs.LockedBlockParts = nil
  634. return
  635. }
  636. // If +2/3 prevoted for already locked block, precommit it.
  637. if cs.LockedBlock.HashesTo(hash) {
  638. cs.signAddVote(VoteTypePrecommit, hash, partsHeader)
  639. return
  640. }
  641. // If +2/3 prevoted for cs.ProposalBlock, lock it and precommit it.
  642. if cs.ProposalBlock.HashesTo(hash) {
  643. // Validate the block.
  644. if err := cs.stageBlock(cs.ProposalBlock, cs.ProposalBlockParts); err != nil {
  645. // Prevent zombies.
  646. log.Warn("+2/3 prevoted for an invalid block", "error", err)
  647. return
  648. }
  649. cs.LockedBlock = cs.ProposalBlock
  650. cs.LockedBlockParts = cs.ProposalBlockParts
  651. cs.signAddVote(VoteTypePrecommit, hash, partsHeader)
  652. return
  653. }
  654. // We don't have the block that validators prevoted.
  655. // Unlock if we're locked.
  656. cs.LockedBlock = nil
  657. cs.LockedBlockParts = nil
  658. return
  659. }
  660. // Enter commit step. See the diagram for details.
  661. // There are two ways to enter this step:
  662. // * After the Precommit step with +2/3 precommits, or,
  663. // * Upon +2/3 commits regardless of current step
  664. // Either way this action is run at most once per round.
  665. func (cs *ConsensusState) RunActionCommit(height uint) {
  666. cs.mtx.Lock()
  667. defer cs.mtx.Unlock()
  668. if cs.Height != height {
  669. panic(Fmt("RunActionCommit(%v), expected %v", height, cs.Height))
  670. }
  671. defer func() {
  672. cs.Step = RoundStepCommit
  673. cs.newStepCh <- cs.getRoundState()
  674. }()
  675. // Sanity check.
  676. // There are two ways to enter:
  677. // 1. +2/3 precommits at the end of RoundStepPrecommit
  678. // 2. +2/3 commits at any time
  679. hash, partsHeader, ok := cs.Precommits.TwoThirdsMajority()
  680. if !ok {
  681. hash, partsHeader, ok = cs.Commits.TwoThirdsMajority()
  682. if !ok {
  683. panic("RunActionCommit() expects +2/3 precommits or commits")
  684. }
  685. }
  686. // Clear the Locked* fields and use cs.Proposed*
  687. if cs.LockedBlock.HashesTo(hash) {
  688. cs.ProposalBlock = cs.LockedBlock
  689. cs.ProposalBlockParts = cs.LockedBlockParts
  690. cs.LockedBlock = nil
  691. cs.LockedBlockParts = nil
  692. cs.LockedPOL = nil
  693. }
  694. // If we don't have the block being committed, set up to get it.
  695. if !cs.ProposalBlock.HashesTo(hash) {
  696. if !cs.ProposalBlockParts.HasHeader(partsHeader) {
  697. // We're getting the wrong block.
  698. // Set up ProposalBlockParts and keep waiting.
  699. cs.ProposalBlock = nil
  700. cs.ProposalBlockParts = NewPartSetFromHeader(partsHeader)
  701. } else {
  702. // We just need to keep waiting.
  703. }
  704. } else {
  705. // We have the block, so save/stage/sign-commit-vote.
  706. cs.saveCommitVoteBlock(cs.ProposalBlock, cs.ProposalBlockParts)
  707. }
  708. // If we have the block AND +2/3 commits, queue RoundActionTryFinalize.
  709. // Round will immediately become finalized.
  710. if cs.ProposalBlock.HashesTo(hash) && cs.Commits.HasTwoThirdsMajority() {
  711. cs.queueAction(RoundAction{cs.Height, cs.Round, RoundActionTryFinalize})
  712. }
  713. }
  714. // Returns true if Finalize happened, which increments height && sets
  715. // the step to RoundStepNewHeight (or RoundStepNewRound, but probably not).
  716. func (cs *ConsensusState) TryFinalizeCommit(height uint) bool {
  717. cs.mtx.Lock()
  718. defer cs.mtx.Unlock()
  719. if cs.Height != height {
  720. panic(Fmt("TryFinalizeCommit(%v), expected %v", height, cs.Height))
  721. }
  722. if cs.Step == RoundStepCommit &&
  723. cs.Commits.HasTwoThirdsMajority() &&
  724. cs.ProposalBlockParts.IsComplete() {
  725. // Sanity check
  726. if cs.ProposalBlock == nil {
  727. panic(Fmt("Expected ProposalBlock to exist"))
  728. }
  729. hash, header, _ := cs.Commits.TwoThirdsMajority()
  730. if !cs.ProposalBlock.HashesTo(hash) {
  731. panic(Fmt("Expected ProposalBlock to hash to commit hash"))
  732. }
  733. if !cs.ProposalBlockParts.HasHeader(header) {
  734. panic(Fmt("Expected ProposalBlockParts header to be commit header"))
  735. }
  736. err := cs.stageBlock(cs.ProposalBlock, cs.ProposalBlockParts)
  737. if err == nil {
  738. log.Debug(Fmt("Finalizing commit of block: %v", cs.ProposalBlock))
  739. // We have the block, so save/stage/sign-commit-vote.
  740. cs.saveCommitVoteBlock(cs.ProposalBlock, cs.ProposalBlockParts)
  741. // Increment height.
  742. cs.updateToState(cs.stagedState)
  743. // cs.Step is now RoundStepNewHeight or RoundStepNewRound
  744. cs.newStepCh <- cs.getRoundState()
  745. return true
  746. } else {
  747. // Prevent zombies.
  748. // TODO: Does this ever happen?
  749. panic(Fmt("+2/3 committed an invalid block: %v", err))
  750. }
  751. }
  752. return false
  753. }
  754. //-----------------------------------------------------------------------------
  755. func (cs *ConsensusState) SetProposal(proposal *Proposal) error {
  756. cs.mtx.Lock()
  757. defer cs.mtx.Unlock()
  758. // Already have one
  759. if cs.Proposal != nil {
  760. return nil
  761. }
  762. // Does not apply
  763. if proposal.Height != cs.Height || proposal.Round != cs.Round {
  764. return nil
  765. }
  766. // We don't care about the proposal if we're already in RoundStepCommit.
  767. if cs.Step == RoundStepCommit {
  768. return nil
  769. }
  770. // Verify signature
  771. if !cs.Validators.Proposer().PubKey.VerifyBytes(SignBytes(proposal), proposal.Signature) {
  772. return ErrInvalidProposalSignature
  773. }
  774. cs.Proposal = proposal
  775. cs.ProposalBlockParts = NewPartSetFromHeader(proposal.BlockParts)
  776. cs.ProposalPOLParts = NewPartSetFromHeader(proposal.POLParts)
  777. return nil
  778. }
  779. // NOTE: block is not necessarily valid.
  780. // NOTE: This function may increment the height.
  781. func (cs *ConsensusState) AddProposalBlockPart(height uint, round uint, part *Part) (added bool, err error) {
  782. cs.mtx.Lock()
  783. defer cs.mtx.Unlock()
  784. // Blocks might be reused, so round mismatch is OK
  785. if cs.Height != height {
  786. return false, nil
  787. }
  788. // We're not expecting a block part.
  789. if cs.ProposalBlockParts == nil {
  790. return false, nil // TODO: bad peer? Return error?
  791. }
  792. added, err = cs.ProposalBlockParts.AddPart(part)
  793. if err != nil {
  794. return added, err
  795. }
  796. if added && cs.ProposalBlockParts.IsComplete() {
  797. var n int64
  798. var err error
  799. cs.ProposalBlock = ReadBinary(&Block{}, cs.ProposalBlockParts.GetReader(), &n, &err).(*Block)
  800. // If we're already in the commit step, try to finalize round.
  801. if cs.Step == RoundStepCommit {
  802. cs.queueAction(RoundAction{cs.Height, cs.Round, RoundActionTryFinalize})
  803. }
  804. // XXX If POL is valid, consider unlocking.
  805. return true, err
  806. }
  807. return true, nil
  808. }
  809. // NOTE: POL is not necessarily valid.
  810. func (cs *ConsensusState) AddProposalPOLPart(height uint, round uint, part *Part) (added bool, err error) {
  811. cs.mtx.Lock()
  812. defer cs.mtx.Unlock()
  813. if cs.Height != height || cs.Round != round {
  814. return false, nil
  815. }
  816. // We're not expecting a POL part.
  817. if cs.ProposalPOLParts == nil {
  818. return false, nil // TODO: bad peer? Return error?
  819. }
  820. added, err = cs.ProposalPOLParts.AddPart(part)
  821. if err != nil {
  822. return added, err
  823. }
  824. if added && cs.ProposalPOLParts.IsComplete() {
  825. var n int64
  826. var err error
  827. cs.ProposalPOL = ReadBinary(&POL{}, cs.ProposalPOLParts.GetReader(), &n, &err).(*POL)
  828. return true, err
  829. }
  830. return true, nil
  831. }
  832. func (cs *ConsensusState) AddVote(address []byte, vote *Vote) (added bool, index uint, err error) {
  833. cs.mtx.Lock()
  834. defer cs.mtx.Unlock()
  835. return cs.addVote(address, vote)
  836. }
  837. // TODO: Maybe move this out of here?
  838. func (cs *ConsensusState) LoadHeaderValidation(height uint) (*Header, *Validation) {
  839. meta := cs.blockStore.LoadBlockMeta(height)
  840. if meta == nil {
  841. return nil, nil
  842. }
  843. validation := cs.blockStore.LoadBlockValidation(height)
  844. return meta.Header, validation
  845. }
  846. //-----------------------------------------------------------------------------
  847. func (cs *ConsensusState) addVote(address []byte, vote *Vote) (added bool, index uint, err error) {
  848. switch vote.Type {
  849. case VoteTypePrevote:
  850. // Prevotes checks for height+round match.
  851. return cs.Prevotes.Add(address, vote)
  852. case VoteTypePrecommit:
  853. // Precommits checks for height+round match.
  854. return cs.Precommits.Add(address, vote)
  855. case VoteTypeCommit:
  856. if vote.Height == cs.Height {
  857. // No need to check if vote.Round < cs.Round ...
  858. // Prevotes && Precommits already checks that.
  859. cs.Prevotes.Add(address, vote)
  860. cs.Precommits.Add(address, vote)
  861. added, index, err = cs.Commits.Add(address, vote)
  862. if added && cs.Commits.HasTwoThirdsMajority() && cs.CommitTime.IsZero() {
  863. cs.CommitTime = time.Now()
  864. log.Debug(Fmt("Set CommitTime to %v", cs.CommitTime))
  865. if cs.Step < RoundStepCommit {
  866. cs.queueAction(RoundAction{cs.Height, cs.Round, RoundActionCommit})
  867. } else {
  868. cs.queueAction(RoundAction{cs.Height, cs.Round, RoundActionTryFinalize})
  869. }
  870. }
  871. return added, index, err
  872. }
  873. if vote.Height+1 == cs.Height {
  874. return cs.LastCommits.Add(address, vote)
  875. }
  876. return false, 0, nil
  877. default:
  878. panic("Unknown vote type")
  879. }
  880. }
  881. func (cs *ConsensusState) stageBlock(block *Block, blockParts *PartSet) error {
  882. if block == nil {
  883. panic("Cannot stage nil block")
  884. }
  885. // Already staged?
  886. if cs.stagedBlock == block {
  887. return nil
  888. }
  889. // Create a copy of the state for staging
  890. stateCopy := cs.state.Copy()
  891. // Commit block onto the copied state.
  892. // NOTE: Basic validation is done in state.AppendBlock().
  893. err := stateCopy.AppendBlock(block, blockParts.Header(), true)
  894. if err != nil {
  895. return err
  896. } else {
  897. cs.stagedBlock = block
  898. cs.stagedState = stateCopy
  899. return nil
  900. }
  901. }
  902. func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header PartSetHeader) *Vote {
  903. if cs.PrivValidator == nil || !cs.Validators.HasAddress(cs.PrivValidator.Address) {
  904. return nil
  905. }
  906. vote := &Vote{
  907. Height: cs.Height,
  908. Round: cs.Round,
  909. Type: type_,
  910. BlockHash: hash,
  911. BlockParts: header,
  912. }
  913. err := cs.PrivValidator.SignVote(vote)
  914. if err == nil {
  915. log.Info("Signed and added vote", "height", cs.Height, "round", cs.Round, "vote", vote)
  916. cs.addVote(cs.PrivValidator.Address, vote)
  917. return vote
  918. } else {
  919. log.Warn("Error signing vote", "height", cs.Height, "round", cs.Round, "vote", vote, "error", err)
  920. return nil
  921. }
  922. }
  923. func (cs *ConsensusState) saveCommitVoteBlock(block *Block, blockParts *PartSet) {
  924. // Only run once per height.
  925. if cs.lastCommittedHeight >= block.Height {
  926. return
  927. } else {
  928. cs.lastCommittedHeight = block.Height
  929. }
  930. // The proposal must be valid.
  931. if err := cs.stageBlock(block, blockParts); err != nil {
  932. // Prevent zombies.
  933. log.Warn("+2/3 precommitted an invalid block", "error", err)
  934. return
  935. }
  936. // Save to blockStore
  937. cs.blockStore.SaveBlock(block, blockParts)
  938. // Save the state
  939. cs.stagedState.Save()
  940. // Update mempool.
  941. cs.mempoolReactor.Mempool.ResetForBlockAndState(block, cs.stagedState)
  942. cs.signAddVote(VoteTypeCommit, block.Hash(), blockParts.Header())
  943. }
  944. //-----------------------------------------------------------------------------
  945. // total duration of given round
  946. func calcRoundDuration(round uint) time.Duration {
  947. return roundDuration0 + roundDurationDelta*time.Duration(round)
  948. }
  949. // startTime is when round zero started.
  950. func calcRoundStartTime(round uint, startTime time.Time) time.Time {
  951. return startTime.Add(roundDuration0*time.Duration(round) +
  952. roundDurationDelta*(time.Duration((int64(round)*int64(round)-int64(round))/2)))
  953. }
  954. // calculates the current round given startTime of round zero.
  955. // NOTE: round is zero if startTime is in the future.
  956. func calcRound(startTime time.Time) uint {
  957. now := time.Now()
  958. if now.Before(startTime) {
  959. return 0
  960. }
  961. // Start + D_0 * R + D_delta * (R^2 - R)/2 <= Now; find largest integer R.
  962. // D_delta * R^2 + (2D_0 - D_delta) * R + 2(Start - Now) <= 0.
  963. // AR^2 + BR + C <= 0; A = D_delta, B = (2_D0 - D_delta), C = 2(Start - Now).
  964. // R = Floor((-B + Sqrt(B^2 - 4AC))/2A)
  965. A := float64(roundDurationDelta)
  966. B := 2.0*float64(roundDuration0) - float64(roundDurationDelta)
  967. C := 2.0 * float64(startTime.Sub(now))
  968. R := math.Floor((-B + math.Sqrt(B*B-4.0*A*C)) / (2 * A))
  969. if math.IsNaN(R) {
  970. panic("Could not calc round, should not happen")
  971. }
  972. if R > math.MaxInt32 {
  973. panic(Fmt("Could not calc round, round overflow: %v", R))
  974. }
  975. if R < 0 {
  976. return 0
  977. }
  978. return uint(R)
  979. }
  980. // convenience
  981. // NOTE: elapsedRatio can be negative if startTime is in the future.
  982. func calcRoundInfo(startTime time.Time) (round uint, roundStartTime time.Time, roundDuration time.Duration,
  983. roundElapsed time.Duration, elapsedRatio float64) {
  984. round = calcRound(startTime)
  985. roundStartTime = calcRoundStartTime(round, startTime)
  986. roundDuration = calcRoundDuration(round)
  987. roundElapsed = time.Now().Sub(roundStartTime)
  988. elapsedRatio = float64(roundElapsed) / float64(roundDuration)
  989. return
  990. }