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.

155 lines
3.9 KiB

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