Tendermint

Table of Contents

1. Tendermint 简介

Tendermint 是一个区块链开发平台,它包括 core 和 ABCI(Application Blockchain Interface)两个部分: core 为核心模块,由共识引擎和网络模块组成,ABCI 为应用程序接口。

Tendermint 大大简化了区块链的开发工作,CosmosBinance ChainTerra 等区块链项目都使用了 Tendermint 。

2. Tendermint 共识引擎

假设已经选择了 Proposer(节 2.1 会介绍如何选择一个 Proposer),图 1(摘自:https://docs.tendermint.com/v0.35/introduction/what-is-tendermint.html#consensus-overview )介绍了 Tendermint 通过多轮投票来产生新的区块的过程。

tendermint_consensus_logic.png

Figure 1: Tendermint Consensus Logic

简单的说,Tendermint 通过多轮投票来产生新的块,每一个工作循环包括了三个步骤:

  1. Propose(提议)
  2. Prevote(预投票)
  3. Precommit(预提交)

正常情况下的流程如下: 节点收到 Propose 后,通过验证后,对其它节点广播 Prevote 消息;如果节点收到了超过 2/3 节点发来的 Prevote 消息,则会广播 Precommit 消息;如果节点收到了超过 2/3 节点发来的 Precommit 消息,则写入这个区块到本地。

2.1. Proposer 的选择

Tendermint 使用 PoS(Proof of Stake),要想成为 Proposer,必须抵押资产。Proposer 的选择采用 Weighted Round Robin 算法,详情参考:https://github.com/tendermint/tendermint/blob/master/spec/consensus/proposer-selection.md

2.2. 不分叉

在 Ethereum 中,短暂分叉(Chain Reorganizations)是很常见的。

在 Tendermint 中,只要恶意节点不超过 1/3,就不会分叉。这是利用“锁机制”来实现的,详情可参考:https://zhuanlan.zhihu.com/p/111770050

2.3. Tendermint 和 PBFT 的比较

Tendermint 和 PBFT 很像,比如都最多容忍不超过 1/3 的恶意节点;比如都是三阶段提交,Tendermint 中使用术语 propose/prevote/precommit,这和 PBFT 的三个阶段 pre-prepare/prepare/commit 一一对应。

Tendermint 和 PBFT 的不同如表 1(摘自:https://zhuanlan.zhihu.com/p/111770050 )所示。

Table 1: Tendermint 和 PBFT 的不同
比较点 PBFT Tendermint BFT
节点权力 一致 根据资产权重有投票权区分
打包节点的选取 顺序轮换 POS 算法选取,根据资产轮换
超时处理 pbft 在执行超时会触发 view-change 机制,进行 view 的轮换 发现 proposer 超时时产生空快,但是不计入区块链,依靠正常流程轮换主节点
共识数据处理 pbft 为节省硬盘空间会在一定时候清理共识消息,并引入 checkpoint 的概念,完成共识后再清除 数据全部放入区块中

总结:可以认为 Tendermint 是 PBFT 的简化版本。

3. ABCI

上层应用可以通过 ABCI 和底层进行交互,下面是 ABCI 所支持的函数:

// From: https://github.com/tendermint/tendermint/blob/master/abci/types/application.go

// Application is an interface that enables any finite, deterministic state machine
// to be driven by a blockchain-based replication engine via the ABCI.
// All methods take a RequestXxx argument and return a ResponseXxx argument,
// except CheckTx/DeliverTx, which take `tx []byte`, and `Commit`, which takes nothing.
type Application interface {
	// Info/Query Connection
	Info(RequestInfo) ResponseInfo    // Return application info
	Query(RequestQuery) ResponseQuery // Query for state

	// Mempool Connection
	CheckTx(RequestCheckTx) ResponseCheckTx // Validate a tx for the mempool

	// Consensus Connection
	InitChain(RequestInitChain) ResponseInitChain // Initialize blockchain w validators/other info from TendermintCore
	PrepareProposal(RequestPrepareProposal) ResponsePrepareProposal
	ProcessProposal(RequestProcessProposal) ResponseProcessProposal
	// Commit the state and return the application Merkle root hash
	Commit() ResponseCommit
	// Create application specific vote extension
	ExtendVote(RequestExtendVote) ResponseExtendVote
	// Verify application's vote extension data
	VerifyVoteExtension(RequestVerifyVoteExtension) ResponseVerifyVoteExtension
	// Deliver the decided block with its txs to the Application
	FinalizeBlock(RequestFinalizeBlock) ResponseFinalizeBlock

	// State Sync Connection
	ListSnapshots(RequestListSnapshots) ResponseListSnapshots                // List available snapshots
	OfferSnapshot(RequestOfferSnapshot) ResponseOfferSnapshot                // Offer a snapshot to the application
	LoadSnapshotChunk(RequestLoadSnapshotChunk) ResponseLoadSnapshotChunk    // Load a snapshot chunk
	ApplySnapshotChunk(RequestApplySnapshotChunk) ResponseApplySnapshotChunk // Apply a snapshot chunk
}

4. 参考

Tendermint 论文:The latest gossip on BFT consensus
Tendermint Core documentation: https://docs.tendermint.com/
Tendermint Specifications: https://github.com/tendermint/tendermint/tree/master/spec

Author: cig01

Created: <2020-11-30 Mon>

Last updated: <2022-04-01 Fri>

Creator: Emacs 27.1 (Org mode 9.4)