ABCI v2 (colloquially known as ABCI++) is the flagship feature of CometBFT. This was released as part of v0.38 in September 2023. In this post we describe the power of ABCI v2 and compare it with its predecessor.
ABCI is the separation layer — or interface — between the consensus engine (namely CometBFT) and the application layer of a blockchain system. It is an essential interface that defines the expectations that CometBFT and application have from each other.
Ignoring some of the subtleties of ABCI, we can imagine that the primary information that circulates through this interface is blocks. Intuitively, CometBFT produces a sequence of blocks, where each block is tagged with a height. As soon as CometBFT finishes the production of a block for a new height, it hands off control over that block to the application. In turn, the application can then execute the transactions in the block. This is an oversimplification, but conveys the main idea.
Figure 1. Intuition of block lifecycle under ABCI v0 interface
The diagram above in Figure 1 sketches this flow. Once CometBFT decides on a block, it hands over control over that block to the application. This happens through a sequence of calls: BeginBlock -> [DeliverTx] -> EndBlock
.
The diagram in Figure 1 depicts a subsets of the methods of ABCI v0 as they are implemented in CometBFT release v0.34. For a complete descriptions of the methods comprised in ABCI v0, we refer the interested reader to the specification published at docs.cometbft.com.
The important part is that, under ABCI v0, the application has no control over the contents of the block. Nor can the application get access to anything related to a block before CometBFT decided that block -- only after.
Note that the block lifecycle has a few identifiable phases in the Tendermint consensus algorithm as implemented in CometBFT. (For a refresher on Tendermint consensus algorithm, see https://docs.cometbft.com/v0.38/introduction/#consensus-overview.)
Assuming a failure-free scenario:
[Phase 1] A block proposer is preparing the block and proposing it to the other nodes in the network.
[Phase 2] The block is undergoing a voting phase. This phase in fact includes two sub-phases, namely Prevote and Precommit. For the purpose of this introductory post, we can simply assume there that the Precommit phase is the more relevant one.
[Phase 3] The validators finished deciding on the block. Sometimes this phase is called finalization.
To bring the discussion back to the topic of ABCI v0, it is at phase 3 that the application gets access to the block for every height.
Now let’s discuss ABCI v2, aka ABCI++. We skip over ABCI v1 because v2 supersedes v1 and is the focus of this post.
In contrast to v0, in ABCI v2 the application is granted access to the block at multiple of the key moment during the block production lifecycle:
a. As part of phase 1: before the block is proposed, the application can manipulate the contents of the block. The application is thus able to control the transactions that go into each block and their relative order. See point d. for a refinement on this.
b. As part of phase 2: the application can append arbitrary data to a block. In CometBFT terminology, we call the arbitrary data "vote extension." Specifically, each validator in a CometBFT network may piggyback vote extensions to each block. The vote extensions are specific per-validator, i.e., each validators appends a different extension.
c. Similar to ABCI v0, as part of phase 3: the application gets access to the block once this is decided.
d: refinement on point a. As part of phase 1 of the block for the subsequent height: before the block for this subsequent height is proposed, the application can manipulate the contents of the block and also gains access to vote extensions appended to the prior block.
As we shall see, the ability of an application to build a block while having data from validators from the prior height is a very powerful feature. We will delve into this in a future post.
The diagram below in Figure 2 gives a graphical intuition of the dance between CometBFT and the application under the ABCI v2 model. We ignore some of the methods in the ABCI interface; for a detailed description please refer to the specification on docs.cometbft.com.
Figure 2. Graphical intuition of ABCI v2 block lifecycle
We highlight some nuances and details to help understand Figure 2.
PrepareProposal
for block at height H. This method executes at the block proposer. It grants the proposer full control over what will go in the block. Importantly, the proposer can also consult the vote extensions that validators in the network appended to the block of the prior height H-1. More specifically, this is a set of at least 2f+1 vote extensions that the block proposer observed locally as part of committing the block of height H-1.
ProcessProposal
for block at height H. Each node in the network executes this method to validate the block proposed for height H. As described in this post, this method allows for the implementation of optimistic execution. This method opens up also another possibility for application builders, as follows: In the process of voting for the block at height H — what we denoted Phase 2 earlier — a validator may choose to censor this proposed block by voting nil on it. This is dangerous because it can lead to degenerate scenarios where block production is no longer guaranteed, i.e., the network may lose liveness.
ExtendVote
and VerifyVoteExtension
. The former method allows a validator node to append arbitrary data — a vote extension — that will be made available to the proposer of the block in the subsequent height H+1. The method ExtendVote
is called during the voting phase for block height H, specifically before each validator sends their Precommit vote; the extension is attached to the Precommit vote. The latter method, called VerifyVoteExtension
, allows each validator to accept or reject every extension in the vote that the other validators cast. Accepting an extension means that the validator will deem the Precommit vote for that extension as valid and will count towards forming a quorum to decide on the block height H.
FinalizeBlock
. This method is a consolidation of the three methods we highlighted earlier in Figure 1, namely BeginBlock -> [DeliverTx] -> EndBlock
. It marks the delivery of a block.
The high-level benefit of the new methods in ABCI v2 is that the application can exercise more control over the contents of each block that CometBFT produces.
We already mentioned one practical benefit that ABCI v2 unlocks: The application can implement an optimization called optimistic execution. The Cosmos SDK team describe their experience in this post with implementing this optimization.
Beside optimistic execution, other practical benefits include:
The ability to implement decentralized oracles, as demonstrated in Skip's Slinky.
The ability to do threshold decryption for mempool privacy.
Bonus: RFC 013: ABCI++ is the first RFC that proposed ABCI++ and has a very good table describing improvements that ABCI v2 unlocks for application builders.
We may cover some of these benefits of ABCI v2 in future posts in more detail.
We hope this introductory post raises awareness and provides insights to help understanding of the new ABCI v2 interface. To reiterate, the full specification of ABCI v2 can be found on docs.cometbft.com.
To join the CometBFT builders community or follow along with the development, please find all the details at linktr.ee/cometbft.