Exploring Pre-Votes and Pre-Commits for the Byzantine Fault Tolerance Consensus (BFT)
By: Nazar Hussain
Tags: Consensus Algorithm, Finality, Byzantine Fault Tolerance, Cryptocurrency, Blockchain

Since their introduction in late 2018, Lisk Improvement Proposals (or LIPs), have helped to improve the ecosystem in close collaboration with the Lisk community. One of the many network features we introduced through this process was the new Byzantine Fault Tolerance (BFT) consensus system. We have already covered the benefits of this consensus algorithm for the Lisk protocol in this blog post. Ahead of its implementation in Lisk SDK 3.0.0, I want to focus one important aspect of the BFT consensus — the process of computing block finality i.e. a guarantee that a particular block is never reverted.

What are the Main Benefits of BFT?

Before we dive deep into this topic, let’s quickly go through basic key features that BFT improves on the blockchain.

1. Safety: If more than ⅔ of the active delegates in the network follow the protocol honestly, two conflicting blocks can never be finalized on the chain.

2. Liveness: Even if ⅓ of the active delegates go offline, new blocks can still be finalized on the network.

3. Accountability: If a delegate violates the protocol, he/she will be held accountable for it.

These are the three high-level values BFT provides to the protocol. As an effect it tries to recover from forks as quickly as possible to grow the network chain with better finality. Each of these features require more extensive understanding. If you want, you can also explore the LIP itself or the research paper. Here we will focus more on the implementation details.

With the BFT consensus, each node does not only maintain the blockchain. It also maintains additional metadata in memory to validate and verify blocks, according to the rules defined by the algorithm. This information will also be partially persisted on the blockchain itself, to make sure that a node can rebuild this in-memory dataset if it crashes. One of the properties we additionally persist to the blockchain for every block is the height at which a delegate has previously forged and maximum pre-voted height at the time of forging that block. Along with this, each node will persist the finalized height, so in the case of chain recovery the already finalized blocks can’t be reverted.

Let’s dive into the topic for the day — voting for the blocks by the delegates.

Vote Democracy for Blocks

Voting is not anything new in the Lisk Ecosystem — it’s the backbone of any Delegated Proof of Stake (DPoS) consensus algorithm. LSK token holders can vote for delegates, then, based on their votes, the system chooses the top delegates which are eligible to forge new blocks for a particular round. Previously, the voting system was used only to vote for delegates. With the introduction of BFT, this concept expands. Now, each delegate will cast a vote for each block, the only difference is these votes will be maintained and kept by individual nodes to themselves. Only few computed attributes will be shared with the network, and not with the whole voting ledger. The mathematical formulas and protocol checks in the system will ensure each node casts the votes appropriately.

Like in any voting system, the basic rule is that you, as a delegate, can cast your vote only once for a block at a particular height. Since two blocks can’t exist at the same height, you can actually cast vote once for each block. This process is called pre-voting. The blocks which will collect more than ⅔ of all votes (majority) are eligible for the next round of voting.

The second round of voting is called pre-committing, and the rule is the same — one delegate can pre-commit one block, only once, for the blocks which are qualified (already got more than ⅔ of all pre-votes). So during the second round, the block which got more than ⅔ of pre-commits will be considered finalized. The highest block finalized will be considered as the finalized height for the chain. All the blocks with height below finalized block will be also considered as final and cannot be reverted, in any case.

There are some other rules as well:

1. A delegate can’t pre-vote and pre-commit the blocks for the round in which they were not active. This happens in order to avoid spam votes. So we need to keep track of the round when the delegate became active.

2. A delegate can’t pre-vote and pre-commit more than two rounds behind, to improve the performance of the whole system.

Example Scenario #1 — Four Delegates, All Forging

To better understand this concept, let’s take one small example. Say we have four active delegates in the network.To finalize any block — at least ⅔ (or three delegates) must agree.