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.

161 lines
4.0 KiB

  1. # Tendermint v1 Markdown pseudocode
  2. This adds hooks for the existing ABCI to the prior pseudocode
  3. ### Initialization
  4. ```go
  5. h_p ← 0
  6. round_p ← 0
  7. step_p is one of {propose, prevote, precommit}
  8. decision_p ← Vector()
  9. lockedValue_p ← nil
  10. validValue_p ← nil
  11. validRound_p ← -1
  12. ```
  13. ### StartRound(round)
  14. ```go
  15. function startRound(round) {
  16. round_p ← round
  17. step_p ← propose
  18. if proposer(h_p, round_p) = p {
  19. if validValue_p != nil {
  20. proposal ← validValue_p
  21. } else {
  22. txdata ← mempool.GetBlock()
  23. // getBlockProposal fills in header
  24. proposal ← getBlockProposal(txdata)
  25. }
  26. broadcast ⟨PROPOSAL, h_p, round_p, proposal, validRound_p⟩
  27. } else {
  28. schedule OnTimeoutPropose(h_p,round_p) to be executed after timeoutPropose(round_p)
  29. }
  30. }
  31. ```
  32. ### ReceiveProposal
  33. In the case where the local node is not locked on any round, the following is ran:
  34. ```go
  35. upon ⟨PROPOSAL, h_p, round_p, v, −1) from proposer(h_p, round_p) while step_p = propose do {
  36. if valid(v) ∧ (lockedRound_p = −1 ∨ lockedValue_p = v) {
  37. broadcast ⟨PREVOTE, h_p, round_p, id(v)⟩
  38. } else {
  39. broadcast ⟨PREVOTE, h_p, round_p, nil⟩
  40. }
  41. step_p ← prevote
  42. }
  43. ```
  44. In the case where the node is locked on a round, the following is ran:
  45. ```go
  46. upon ⟨PROPOSAL, h_p, round_p, v, vr⟩
  47. from proposer(h_p, round_p)
  48. AND 2f + 1 ⟨PREVOTE, h_p, vr, id(v)⟩
  49. while step_p = propose ∧ (vr ≥ 0 ∧ vr < round_p) do {
  50. if valid(v) ∧ (lockedRound_p ≤ vr ∨ lockedValue_p = v) {
  51. broadcast ⟨PREVOTE, h_p, round_p, id(v)⟩
  52. } else {
  53. broadcast ⟨PREVOTE, h_p, round_p, nil⟩
  54. }
  55. step_p ← prevote
  56. }
  57. ```
  58. ### Prevote timeout
  59. Upon receiving 2f + 1 prevotes, setup a timeout.
  60. ```go
  61. upon 2f + 1 ⟨PREVOTE, h_p, vr, -1⟩
  62. with step_p = prevote for the first time, do {
  63. schedule OnTimeoutPrevote(h_p, round_p) to be executed after timeoutPrevote(round_p)
  64. }
  65. ```
  66. with OnTimeoutPrevote defined as:
  67. ```go
  68. function OnTimeoutPrevote(height, round) {
  69. if (height = h_p && round = round_p && step_p = prevote) {
  70. broadcast ⟨PRECOMMIT, h_p, round_p, nil⟩
  71. step_p ← precommit
  72. }
  73. }
  74. ```
  75. ### Receiving enough prevotes to precommit
  76. The following code is ran upon receiving 2f + 1 prevotes for the same block
  77. ```go
  78. upon ⟨PROPOSAL, h_p, round_p, v, *⟩
  79. from proposer(h_p, round_p)
  80. AND 2f + 1 ⟨PREVOTE, h_p, vr, id(v)⟩
  81. while valid(v) ∧ step_p >= prevote for the first time do {
  82. if (step_p = prevote) {
  83. lockedValue_p ← v
  84. lockedRound_p ← round_p
  85. broadcast ⟨PRECOMMIT, h_p, round_p, id(v)⟩
  86. step_p ← precommit
  87. }
  88. validValue_p ← v
  89. validRound_p ← round_p
  90. }
  91. ```
  92. And upon receiving 2f + 1 prevotes for nil:
  93. ```go
  94. upon 2f + 1 ⟨PREVOTE, h_p, round_p, nil⟩
  95. while step_p = prevote do {
  96. broadcast ⟨PRECOMMIT, h_p, round_p, nil⟩
  97. step_p ← precommit
  98. }
  99. ```
  100. ### Precommit timeout
  101. Upon receiving 2f + 1 precommits, setup a timeout.
  102. ```go
  103. upon 2f + 1 ⟨PRECOMMIT, h_p, vr, *⟩ for the first time, do {
  104. schedule OnTimeoutPrecommit(h_p, round_p) to be executed after timeoutPrecommit(round_p)
  105. }
  106. ```
  107. with OnTimeoutPrecommit defined as:
  108. ```go
  109. function OnTimeoutPrecommit(height, round) {
  110. if (height = h_p && round = round_p) {
  111. StartRound(round_p + 1)
  112. }
  113. }
  114. ```
  115. ### Upon Receiving 2f + 1 precommits
  116. The following code is ran upon receiving 2f + 1 precommits for the same block
  117. ```go
  118. upon ⟨PROPOSAL, h_p, r, v, *⟩
  119. from proposer(h_p, r)
  120. AND 2f + 1 ⟨ PRECOMMIT, h_p, r, id(v)⟩
  121. while decision_p[h_p] = nil do {
  122. if (valid(v)) {
  123. decision_p[h_p] ← v
  124. h_p ← h_p + 1
  125. reset lockedRound_p, lockedValue_p,validRound_p and validValue_p to initial values
  126. ABCI.BeginBlock(v.header)
  127. ABCI.DeliverTxs(v.data)
  128. ABCI.EndBlock()
  129. StartRound(0)
  130. }
  131. }
  132. ```
  133. If we don't see 2f + 1 precommits for the same block, we wait until we get 2f + 1 precommits, and the timeout occurs.