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.

349 lines
16 KiB

  1. Byzantine Consensus Algorithm
  2. =============================
  3. Terms
  4. -----
  5. - The network is composed of optionally connected *nodes*. Nodes
  6. directly connected to a particular node are called *peers*.
  7. - The consensus process in deciding the next block (at some *height*
  8. ``H``) is composed of one or many *rounds*.
  9. - ``NewHeight``, ``Propose``, ``Prevote``, ``Precommit``, and
  10. ``Commit`` represent state machine states of a round. (aka
  11. ``RoundStep`` or just "step").
  12. - A node is said to be *at* a given height, round, and step, or at
  13. ``(H,R,S)``, or at ``(H,R)`` in short to omit the step.
  14. - To *prevote* or *precommit* something means to broadcast a `prevote
  15. vote <https://godoc.org/github.com/tendermint/tendermint/types#Vote>`__
  16. or `first precommit
  17. vote <https://godoc.org/github.com/tendermint/tendermint/types#FirstPrecommit>`__
  18. for something.
  19. - A vote *at* ``(H,R)`` is a vote signed with the bytes for ``H`` and
  20. ``R`` included in its
  21. `sign-bytes <block-structure.html#vote-sign-bytes>`__.
  22. - *+2/3* is short for "more than 2/3"
  23. - *1/3+* is short for "1/3 or more"
  24. - A set of +2/3 of prevotes for a particular block or ``<nil>`` at
  25. ``(H,R)`` is called a *proof-of-lock-change* or *PoLC* for short.
  26. State Machine Overview
  27. ----------------------
  28. At each height of the blockchain a round-based protocol is run to
  29. determine the next block. Each round is composed of three *steps*
  30. (``Propose``, ``Prevote``, and ``Precommit``), along with two special
  31. steps ``Commit`` and ``NewHeight``.
  32. In the optimal scenario, the order of steps is:
  33. ::
  34. NewHeight -> (Propose -> Prevote -> Precommit)+ -> Commit -> NewHeight ->...
  35. The sequence ``(Propose -> Prevote -> Precommit)`` is called a *round*.
  36. There may be more than one round required to commit a block at a given
  37. height. Examples for why more rounds may be required include:
  38. - The designated proposer was not online.
  39. - The block proposed by the designated proposer was not valid.
  40. - The block proposed by the designated proposer did not propagate in
  41. time.
  42. - The block proposed was valid, but +2/3 of prevotes for the proposed
  43. block were not received in time for enough validator nodes by the
  44. time they reached the ``Precommit`` step. Even though +2/3 of
  45. prevotes are necessary to progress to the next step, at least one
  46. validator may have voted ``<nil>`` or maliciously voted for something
  47. else.
  48. - The block proposed was valid, and +2/3 of prevotes were received for
  49. enough nodes, but +2/3 of precommits for the proposed block were not
  50. received for enough validator nodes.
  51. Some of these problems are resolved by moving onto the next round &
  52. proposer. Others are resolved by increasing certain round timeout
  53. parameters over each successive round.
  54. State Machine Diagram
  55. ---------------------
  56. ::
  57. +-------------------------------------+
  58. v |(Wait til `CommmitTime+timeoutCommit`)
  59. +-----------+ +-----+-----+
  60. +----------> | Propose +--------------+ | NewHeight |
  61. | +-----------+ | +-----------+
  62. | | ^
  63. |(Else, after timeoutPrecommit) v |
  64. +-----+-----+ +-----------+ |
  65. | Precommit | <------------------------+ Prevote | |
  66. +-----+-----+ +-----------+ |
  67. |(When +2/3 Precommits for block found) |
  68. v |
  69. +--------------------------------------------------------------------+
  70. | Commit |
  71. | |
  72. | * Set CommitTime = now; |
  73. | * Wait for block, then stage/save/commit block; |
  74. +--------------------------------------------------------------------+
  75. Background Gossip
  76. -----------------
  77. A node may not have a corresponding validator private key, but it
  78. nevertheless plays an active role in the consensus process by relaying
  79. relevant meta-data, proposals, blocks, and votes to its peers. A node
  80. that has the private keys of an active validator and is engaged in
  81. signing votes is called a *validator-node*. All nodes (not just
  82. validator-nodes) have an associated state (the current height, round,
  83. and step) and work to make progress.
  84. Between two nodes there exists a ``Connection``, and multiplexed on top
  85. of this connection are fairly throttled ``Channel``\ s of information.
  86. An epidemic gossip protocol is implemented among some of these channels
  87. to bring peers up to speed on the most recent state of consensus. For
  88. example,
  89. - Nodes gossip ``PartSet`` parts of the current round's proposer's
  90. proposed block. A LibSwift inspired algorithm is used to quickly
  91. broadcast blocks across the gossip network.
  92. - Nodes gossip prevote/precommit votes. A node NODE\_A that is ahead of
  93. NODE\_B can send NODE\_B prevotes or precommits for NODE\_B's current
  94. (or future) round to enable it to progress forward.
  95. - Nodes gossip prevotes for the proposed PoLC (proof-of-lock-change)
  96. round if one is proposed.
  97. - Nodes gossip to nodes lagging in blockchain height with block
  98. `commits <https://godoc.org/github.com/tendermint/tendermint/types#Commit>`__
  99. for older blocks.
  100. - Nodes opportunistically gossip ``HasVote`` messages to hint peers
  101. what votes it already has.
  102. - Nodes broadcast their current state to all neighboring peers. (but is
  103. not gossiped further)
  104. There's more, but let's not get ahead of ourselves here.
  105. Proposals
  106. ---------
  107. A proposal is signed and published by the designated proposer at each
  108. round. The proposer is chosen by a deterministic and non-choking round
  109. robin selection algorithm that selects proposers in proportion to their
  110. voting power. (see
  111. `implementation <https://github.com/tendermint/tendermint/blob/develop/types/validator_set.go>`__)
  112. A proposal at ``(H,R)`` is composed of a block and an optional latest
  113. ``PoLC-Round < R`` which is included iff the proposer knows of one. This
  114. hints the network to allow nodes to unlock (when safe) to ensure the
  115. liveness property.
  116. State Machine Spec
  117. ------------------
  118. Propose Step (height:H,round:R)
  119. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  120. Upon entering ``Propose``: - The designated proposer proposes a block at
  121. ``(H,R)``.
  122. The ``Propose`` step ends: - After ``timeoutProposeR`` after entering
  123. ``Propose``. --> goto ``Prevote(H,R)`` - After receiving proposal block
  124. and all prevotes at ``PoLC-Round``. --> goto ``Prevote(H,R)`` - After
  125. `common exit conditions <#common-exit-conditions>`__
  126. Prevote Step (height:H,round:R)
  127. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  128. Upon entering ``Prevote``, each validator broadcasts its prevote vote.
  129. - First, if the validator is locked on a block since ``LastLockRound``
  130. but now has a PoLC for something else at round ``PoLC-Round`` where
  131. ``LastLockRound < PoLC-Round < R``, then it unlocks.
  132. - If the validator is still locked on a block, it prevotes that.
  133. - Else, if the proposed block from ``Propose(H,R)`` is good, it
  134. prevotes that.
  135. - Else, if the proposal is invalid or wasn't received on time, it
  136. prevotes ``<nil>``.
  137. The ``Prevote`` step ends: - After +2/3 prevotes for a particular block
  138. or ``<nil>``. --> goto ``Precommit(H,R)`` - After ``timeoutPrevote``
  139. after receiving any +2/3 prevotes. --> goto ``Precommit(H,R)`` - After
  140. `common exit conditions <#common-exit-conditions>`__
  141. Precommit Step (height:H,round:R)
  142. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  143. Upon entering ``Precommit``, each validator broadcasts its precommit
  144. vote. - If the validator has a PoLC at ``(H,R)`` for a particular block
  145. ``B``, it (re)locks (or changes lock to) and precommits ``B`` and sets
  146. ``LastLockRound = R``. - Else, if the validator has a PoLC at ``(H,R)``
  147. for ``<nil>``, it unlocks and precommits ``<nil>``. - Else, it keeps the
  148. lock unchanged and precommits ``<nil>``.
  149. A precommit for ``<nil>`` means "I didn’t see a PoLC for this round, but
  150. I did get +2/3 prevotes and waited a bit".
  151. The Precommit step ends: - After +2/3 precommits for ``<nil>``. --> goto
  152. ``Propose(H,R+1)`` - After ``timeoutPrecommit`` after receiving any +2/3
  153. precommits. --> goto ``Propose(H,R+1)`` - After `common exit
  154. conditions <#common-exit-conditions>`__
  155. common exit conditions
  156. ^^^^^^^^^^^^^^^^^^^^^^
  157. - After +2/3 precommits for a particular block. --> goto ``Commit(H)``
  158. - After any +2/3 prevotes received at ``(H,R+x)``. --> goto
  159. ``Prevote(H,R+x)``
  160. - After any +2/3 precommits received at ``(H,R+x)``. --> goto
  161. ``Precommit(H,R+x)``
  162. Commit Step (height:H)
  163. ~~~~~~~~~~~~~~~~~~~~~~
  164. - Set ``CommitTime = now()``
  165. - Wait until block is received. --> goto ``NewHeight(H+1)``
  166. NewHeight Step (height:H)
  167. ~~~~~~~~~~~~~~~~~~~~~~~~~
  168. - Move ``Precommits`` to ``LastCommit`` and increment height.
  169. - Set ``StartTime = CommitTime+timeoutCommit``
  170. - Wait until ``StartTime`` to receive straggler commits. --> goto
  171. ``Propose(H,0)``
  172. Proofs
  173. ------
  174. Proof of Safety
  175. ~~~~~~~~~~~~~~~
  176. Assume that at most -1/3 of the voting power of validators is byzantine.
  177. If a validator commits block ``B`` at round ``R``, it's because it saw
  178. +2/3 of precommits at round ``R``. This implies that 1/3+ of honest
  179. nodes are still locked at round ``R' > R``. These locked validators will
  180. remain locked until they see a PoLC at ``R' > R``, but this won't happen
  181. because 1/3+ are locked and honest, so at most -2/3 are available to
  182. vote for anything other than ``B``.
  183. Proof of Liveness
  184. ~~~~~~~~~~~~~~~~~
  185. If 1/3+ honest validators are locked on two different blocks from
  186. different rounds, a proposers' ``PoLC-Round`` will eventually cause
  187. nodes locked from the earlier round to unlock. Eventually, the
  188. designated proposer will be one that is aware of a PoLC at the later
  189. round. Also, ``timeoutProposalR`` increments with round ``R``, while the
  190. size of a proposal are capped, so eventually the network is able to
  191. "fully gossip" the whole proposal (e.g. the block & PoLC).
  192. Proof of Fork Accountability
  193. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  194. Define the JSet (justification-vote-set) at height ``H`` of a validator
  195. ``V1`` to be all the votes signed by the validator at ``H`` along with
  196. justification PoLC prevotes for each lock change. For example, if ``V1``
  197. signed the following precommits: ``Precommit(B1 @ round 0)``,
  198. ``Precommit(<nil> @ round 1)``, ``Precommit(B2 @ round 4)`` (note that
  199. no precommits were signed for rounds 2 and 3, and that's ok),
  200. ``Precommit(B1 @ round 0)`` must be justified by a PoLC at round 0, and
  201. ``Precommit(B2 @ round 4)`` must be justified by a PoLC at round 4; but
  202. the precommit for ``<nil>`` at round 1 is not a lock-change by
  203. definition so the JSet for ``V1`` need not include any prevotes at round
  204. 1, 2, or 3 (unless ``V1`` happened to have prevoted for those rounds).
  205. Further, define the JSet at height ``H`` of a set of validators ``VSet``
  206. to be the union of the JSets for each validator in ``VSet``. For a given
  207. commit by honest validators at round ``R`` for block ``B`` we can
  208. construct a JSet to justify the commit for ``B`` at ``R``. We say that a
  209. JSet *justifies* a commit at ``(H,R)`` if all the committers (validators
  210. in the commit-set) are each justified in the JSet with no duplicitous
  211. vote signatures (by the committers).
  212. - **Lemma**: When a fork is detected by the existence of two
  213. conflicting `commits <./validators.html#commiting-a-block>`__,
  214. the union of the JSets for both commits (if they can be compiled)
  215. must include double-signing by at least 1/3+ of the validator set.
  216. **Proof**: The commit cannot be at the same round, because that would
  217. immediately imply double-signing by 1/3+. Take the union of the JSets
  218. of both commits. If there is no double-signing by at least 1/3+ of
  219. the validator set in the union, then no honest validator could have
  220. precommitted any different block after the first commit. Yet, +2/3
  221. did. Reductio ad absurdum.
  222. As a corollary, when there is a fork, an external process can determine
  223. the blame by requiring each validator to justify all of its round votes.
  224. Either we will find 1/3+ who cannot justify at least one of their votes,
  225. and/or, we will find 1/3+ who had double-signed.
  226. Alternative algorithm
  227. ~~~~~~~~~~~~~~~~~~~~~
  228. Alternatively, we can take the JSet of a commit to be the "full commit".
  229. That is, if light clients and validators do not consider a block to be
  230. committed unless the JSet of the commit is also known, then we get the
  231. desirable property that if there ever is a fork (e.g. there are two
  232. conflicting "full commits"), then 1/3+ of the validators are immediately
  233. punishable for double-signing.
  234. There are many ways to ensure that the gossip network efficiently share
  235. the JSet of a commit. One solution is to add a new message type that
  236. tells peers that this node has (or does not have) a +2/3 majority for B
  237. (or ) at (H,R), and a bitarray of which votes contributed towards that
  238. majority. Peers can react by responding with appropriate votes.
  239. We will implement such an algorithm for the next iteration of the
  240. Tendermint consensus protocol.
  241. Other potential improvements include adding more data in votes such as
  242. the last known PoLC round that caused a lock change, and the last voted
  243. round/step (or, we may require that validators not skip any votes). This
  244. may make JSet verification/gossip logic easier to implement.
  245. Censorship Attacks
  246. ~~~~~~~~~~~~~~~~~~
  247. Due to the definition of a block
  248. `commit <validators.html#commiting-a-block>`__, any 1/3+
  249. coalition of validators can halt the blockchain by not broadcasting
  250. their votes. Such a coalition can also censor particular transactions by
  251. rejecting blocks that include these transactions, though this would
  252. result in a significant proportion of block proposals to be rejected,
  253. which would slow down the rate of block commits of the blockchain,
  254. reducing its utility and value. The malicious coalition might also
  255. broadcast votes in a trickle so as to grind blockchain block commits to
  256. a near halt, or engage in any combination of these attacks.
  257. If a global active adversary were also involved, it can partition the
  258. network in such a way that it may appear that the wrong subset of
  259. validators were responsible for the slowdown. This is not just a
  260. limitation of Tendermint, but rather a limitation of all consensus
  261. protocols whose network is potentially controlled by an active
  262. adversary.
  263. Overcoming Forks and Censorship Attacks
  264. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  265. For these types of attacks, a subset of the validators through external
  266. means should coordinate to sign a reorg-proposal that chooses a fork
  267. (and any evidence thereof) and the initial subset of validators with
  268. their signatures. Validators who sign such a reorg-proposal forego its
  269. collateral on all other forks. Clients should verify the signatures on
  270. the reorg-proposal, verify any evidence, and make a judgement or prompt
  271. the end-user for a decision. For example, a phone wallet app may prompt
  272. the user with a security warning, while a refrigerator may accept any
  273. reorg-proposal signed by +1/2 of the original validators.
  274. No non-synchronous Byzantine fault-tolerant algorithm can come to
  275. consensus when 1/3+ of validators are dishonest, yet a fork assumes that
  276. 1/3+ of validators have already been dishonest by double-signing or
  277. lock-changing without justification. So, signing the reorg-proposal is a
  278. coordination problem that cannot be solved by any non-synchronous
  279. protocol (i.e. automatically, and without making assumptions about the
  280. reliability of the underlying network). It must be provided by means
  281. external to the weakly-synchronous Tendermint consensus algorithm. For
  282. now, we leave the problem of reorg-proposal coordination to human
  283. coordination via internet media. Validators must take care to ensure
  284. that there are no significant network partitions, to avoid situations
  285. where two conflicting reorg-proposals are signed.
  286. Assuming that the external coordination medium and protocol is robust,
  287. it follows that forks are less of a concern than `censorship
  288. attacks <#censorship-attacks>`__.