Tendermint

什么是Tendermint

Tenermint 是一个软件,用于在多台机器之间实现安全一致地复制一个应用。
所谓安全,指的是即使有多达 1/3 的机器出现任意故障的情况下, Tendermint 仍然能够正常工作。
所谓一致,指的是每一个正常工作的机器都会有着同样的交易日志,计算相同的状态。
安全一致的复制是分布式系统中一个至关重要的问题:从货币到选举,再到基础设施规划,它在广泛应用的容错中承担了一个极其重要的角色。

 Tendermint 的设计原则是易使用,易理解,高性能,对于各种分布式应用都十分有用。 
 Tendermint 说明文档:https://tendermint.readthedocs.io/en/master/ 
 Tendermint 地址:https://github.com/tendermint/tendermint
    Tendermint官方网站:https://tendermint.com/
Tendermint_第1张图片

Tendermint 与其他技术的比较

Tendermint 大体上与两类软件很类似。
第一类包含了分布式的键值存储,比如 Zookeeper,etcd 和 consul,它们都使用了非拜占庭容错共识。
第二类就是 “区块链技术”,它既包括了像比特币和以太坊这样的加密货币,也包括了像 Hyperledger Burrow 这样的分布式账本设计。

Zookeeper, etcd, consul

Zookeeper,etcd 和 consul 都是在一个经典的非拜占庭容错共识算法上实现了一个键值存储。Zookeeper 使用了一个叫做 Zookeeper Atomic Broadcast 的 Paxos 版本,而 etcd 和 consul 使用了更年轻,也更简单的 Raft 共识算法。一个典型的集群由 3-5 台机器构成,虽然可以经受住 1/2 的机器发生问题,但是只要发生一次拜占庭故障就可以摧毁整个系统。它们每一个都提供了一个稍微有别于键值存储的实现,但是都将关注点放在提供分布式系统的基础服务,比如动态配置,服务发现,锁,选取领导人等等。

Tendermint 是一个本质上类似的软件,但是有两点关键不同:它是拜占庭容错的,这意味着它可以经受 1/3 机器发生任意形式的故障 – 包括黑客和恶意攻击。

它并不像键值存储一样针对某一指定类型的应用。相反,它关注与任意的状态机复制,因此开发者可以量身打造适合自己的应用逻辑,从键值存储到加密货币到电子投票平台,甚至更多的应用都可适用。

以上内容取自于 consul.io 和 Hashicorp sites.

Bitcoin, Ethereum, etc.

在比特币和以太坊这样的传统加密货币下出现了 Tendermint,它的目的在于提供一个比比特币的工作量证明更加有效和安全的共识算法。在早期,Tendermint 内置了简单的货币来参与共识,用户必须向一个安全账户中“绑定”一定数量的货币,如果他们表现不端,这些钱就会被收回 – 这一点使得 Tendermint 成为一个 POS 算法。

自那时起,Tendermint 已经进化为一个能够承载任意应用状态的通用区块链共识引擎。这意味着它可以成为其他区块链软件共识引擎的一个即插即用的替代品。所以基于当前的以太坊代码库,无论是以 Rust,Go,Haskell,任何人都可以使用 Tendermint 共识运行一个 ABCI 应用。实际上,我们已经完成了这一点(https://github.com/tendermint/ethermint)。此外,我们也计划为 Bitcoin,ZCash,和其他确定性的应用完成同样的工作。另一个基于 Tendermint 构建的加密货币应用是 Cosmos。

Fabric, Burrow

Fabric 采用了与 Tendermint 类似的方法,但是更关注于如何管理状态,并且要求所有的应用行为能够在多个 docker 容器,它们叫做 “chaincode” 的模块中运行。它使用了来自 IBM (augmented to handle potentially non-deterministic chaincode) 的 PBFT 实现。通过扩展 Tendermint 来处理未来工作存在的不确定性,在 Tendermint 中以一个 ABCI 应用实现这个基于 docker 的行为是完全有可能的。Burrow 是一个以太坊虚拟机和以太坊交易机制的实现,同时附带有名字注册,许可权和天然合约,可替代区块链 API等额外特性。它使用 Tendermint 作为它的共识引擎,提供了一个特殊的应用状态。

什么是 ABCI (应用区块链接口)

区块链应用接口(Application BlockChain Interface,ABCI)允许应用的拜占庭容错复制可以由任意一种编程语言编写。

Motivation

至今为止,所有的区块链“栈”(比如,比特币)都有着大一统的设计。这就是说,每个区块链栈都是一个单一的程序,这个程序处理了去中心化账本的所有事务。它还包括了 P2P 连接,交易的“内存池”广播,在最新块上的共识,账户余额,图灵完备的合约,用户级别的许可权等。

在计算机科学中,使用大一统的架构,是一个典型的错误实践。这会使得代码重用变得困难,而且如果真的去这么做时,会导致代码库分支的维护变得十分复杂。尤其当代码设计并非模块化时,会产生难以维护的“意大利面条式代码”。

大一统设计的另一个问题是,它限制了区块链栈的语言。比如在以太坊中,它支持一个图灵完备的字节码虚拟机,它限制你必须使用可以编译为那种类型字节码的语言。目前,它所支持的语言是 Serpent 和 Solidity。

相反,我们的方式是从特定区块链应用的应用状态细节中,将共识引擎和 P2P 层分离开来。我们通过将应用细节抽象为一个借口来实现这一点,这个接口被实现为一个 socket 协议。

所以,我们就有了一个接口,应用区块链接口(ABCI),和它的主要实现,Tendermint Socket Protocol (TSP, 或 Teaspoon)。

区块链应用接口(Application BlockChain Interface,ABCI)允许应用的拜占庭容错复制可以由任意一种编程语言编写。 

Intro to ABCI

Tendermint Core (“共识引擎”)通过一个满足 ABCI 标准的 socket 协议与应用进行交流。 
举个大家比较熟悉的例子,比特币。比特币是一个加密货币区块链,其中的每个节点维护了一个完全经过审计的 UTXO 数据库。如果有人想要在 ABCI 之上创建一个类似比特币的系统,Tendermint Core 将会负责:

  • 在节点间共享区块和交易
  • 建立交易(区块链)的标准/不可变顺序

而应用将会负责:

  • 维护 UTXO 数据库
  • 验证交易的加密签名
  • 阻止花费尚未存在的交易
  • 允许客户端查询 UTXO 数据库

ABCI 包含了 3 个主要的消息类型,它们由 core 发送至应用,应用会对消息产生相应的回复: 
  DeliverTx 消息是应用的主要部分。链中的每笔交易都通过这个消息进行传送。应用需要基于当前状态,应用协议,和交易的加密证书上,去验证接收到 DeliverTx 消息的每笔交易,。一个经过验证的交易然后需要去更新应用状态 – 比如通过将绑定一个值到键值存储,或者通过更新 UTXO 数据库。 
  CheckTx 消息类似于 DeliverTx,但是它仅用于验证交易。Tendermint Core 的内存池首先通过 CheckTx 检验一笔交易的有效性,并且只将有效交易中继到其他节点。比如,一个应用可能会检查在交易中不断增长的序列号,如果序列号过时,CheckTx 就会返回一个错误。又或者,他们可能使用一个基于容量的系统,该系统需要对每笔交易重新更新容量。 
  Commit 消息用于计算当前应用状态的一个加密保证(cryptographic commitment),这个加密保证会被放到下一个区块头。这有一些比较方便的属性。现在,更新状态时的不一致性会被认为是区块链的分支,分支会捕获所有的编程错误。这同样也简化了保障轻节点客户端安全的开发,因为 Merkel-hash 证明可以通过在区块哈希上的检查得到验证,区块链哈希由一个 quorum 签署。 
  一个应用可能有多个 ABCI socket 连接。Tendermint Core 给应用创建了三个 ABCI 连接:一个用于内存池广播时的交易验证,一个用于运行提交区块时的共识引擎,还有一个用于查询应用状态。 
  很显然,在创建区块链时,应用的设计者需要非常小心地设计他们的消息处理,这个架构提供一个范例。下图阐释了通过 ABCI 的消息流: 

Tendermint_第2张图片

A Note on Determinism

区块链交易处理的逻辑必须是确定性的。如果应用逻辑不确定,就无法在 Tendermint Core 复制节点间达成共识。

在以太坊上的 Solidity 是用于区块链应用一个非常好的语言选择,除了一些其他因素,它还是一个完全确定性的编程语言。但是,通过使用现有的一些语言,比如 Java,C++,Python 和 Go 也是可以创建确定性应用的。对通过避免非确定性来源创建确定性程序,游戏程序员和区块链开发者都已经很熟悉了,比如:

  • 随机数生成器(没有确定性的种子)
  • 线程上的竞争条件(或者避免多线程)
  • 系统时钟
  • 未初始化的内存(在像 C 或者 C++ 这样的不安全语言)
  • 浮点数算法
  • 随机的语言特性(比如 Go 语言的 map 迭代)

尽管程序员可以通过加倍小心来避免非确定性,但是给每个语言创建一个特殊的语法检查器或静态分析器,用它们来检查确定性也是有可能的。在未来,我们可能会与合作者一起创造出这样的工具。

Tendermint共识概述

Tendermint 是一个易于理解,大部分操作为异步的 BFT 共识协议。下图是一个简单的状态机,它展示了协议遵循的规则:

Tendermint_第3张图片

协议中的参与者叫着 “验证人”(validator)。他们轮流对交易区块进行提议,并对这些区块进行投票。区块会被提交到链上,每一个块占据一个“高度”(height)。提交块可能会失败,如果失败,协议就会开始下一轮的提交,并且一个新的验证人会继续提交那个高度的区块。要想成功提交一个块,需要有两个阶段的投票:“预投票”(pre-vote)和“预提交”(pre-commit)。在同一轮提交中,只有超过 2/3 的验证人对同一个块进行了预提交,这个块才能被提交到链上。

上图右下角有一对夫妇在跳波卡舞,因为验证人做的事情就像是在跳波卡舞。当超过 2/3 的验证人对同一个块进行了预投票,我们就把它叫做一个“波卡”(polka)。每一个预提交都必须被同一轮中的一个波卡所证明。

由于一些原因,验证人可能在提交一个块时失败:当前提议者可能离线了,或者网络非常慢。Tendermint 允许他们证实一个验证人应该被跳过。在进行下一轮的投票前,验证人会等待一小段时间从提议者那里接收一个完整的提议块。这种对于超时的依赖,使得 Tendermint 成为了一个弱同步协议,而非一个异步协议。但是,协议的剩余部分都是异步的,只有在接收到超过 2/3 的验证人集合时,验证人才会采取下一步操作。Tendermint 能够简化的一个原因就是它使用了同样的机制来提交一个块和跳过直接进入下一轮。

基于不到 1/3 的验证人是拜占庭节点的前提,Tendermint 保证了永远都不会违背其安全性 – 也就是说,验证人永远不会在同一高度提交冲突块。为了达到这一点,它引入了一些 “锁定”(locking)的规则,这些规则对流程图中的路径进行了模块化。一旦一个验证人预提交了一个块,它就被“锁定”在了那个块上。然后,

  1. 它必须为被锁定的那个块进行预投票
  2. 只有在之后的轮中,有了那个块的一个波卡,它才能够解锁,并为一个新块进行预提交。

Stake

在许多系统中,并非所有的验证人都在共识协议有着同样的“高度”(height)。因此,我们对 1/3 还是 2/3 的验证人并不十分感兴趣,而是关心在所有投票力量所占的比例,在个体验证人中,这些比例可能并不是均匀分布的。

由于 Tendermint 可以复制任意的应用程序,定义一种货币,并用该货币来计算投票权力是完全有可能的。当使用货币决定投票权时,这个系统通常叫做权益证明(Proof-of-Stake)系统。通过应用逻辑,可以将验证人的货币持有强制绑定到一个押金账户中。如果他们被发现在共识协议中表现不端,这些钱就会被销毁。这就给协议的安全性增加了一个经济因素,能够让人们量化违反共识假设的成本,这个假设就是只有不到 1/3 的投票权来自拜占庭节点。

Cosmos Network 的设计目的,是在 实现为 ABCI 应用的加密货币中使用这个权益证明机制。

区块链结构

Tendermint使用如下的区块链结构保存区块链信息。区块包括三部分:Header(区块头),Data(区块中的交易信息)以及LastCommit(上一个区块的Commit信息)。

Tendermint_第4张图片

区块头中包括:

a)区块高度
b)上个区块ID(LastBlockID),也就是上一个区块Header的hash
c)Data Hash,所有区块交易信息hash
d)App State Hash,应用程序当前状态的hash,这个hash是通过ABCI接口的Commit的返回值。
e)Validator Hash,生成区块时所有validator信息的hash
f)LastCommit hash,上一个区块的Commit的hash。

RPC服务

Tendermint Core提供RPC服务,以供其他模块通过RPC访问区块以及应用的相关信息。

Tendermint的工作原理剖析

当一个Tx进来时, Tmcore的mempool(MP)会通过mempool connection(一个socket连接,由abci-server提供,端口号为46658)调用Application Logic(AL:也就是abci-app,我们自己用任何语言编写的APP逻辑)里的checkTx方法,AL向MP返回验证结果。MP根据验证结果放行或者拒绝该Tx。

Tendermint(TM)把tx暂存在内存池(mempool)里,并把这条tx通过P2P网络复制给其它TM节点。TM发起了对这条 tx 的拜占庭共识投票,所有4个 Tendermint 节点都参与了。投票过程分三轮,第一轮预投票(PreVote),超过 2/3 认可后进入第二轮预提交(PreCommit),超过 2/3 认可后进入最后一轮正式提交(Commit)
 

TM提交Tx时依次通过Consensus Connection(一个socket连接,由abci-server提供,端口号为46658)向ABCI-APP发送指令BeginBlock-->多次DeliverTx-->EndBlock--> Commit,提交成功后会将StateRoot(application Merkle root hash)返回给TM,TM New出一个区块。

Tendermint_第5张图片

参考:Baidu、Google、Tendermint、GitHub

你可能感兴趣的:(————Tendermint,【区块链】)