区块链时代的拜占庭容错:Tendermint(四)

原文题目:《Tendermint: Byzantine Fault Tolerance in the Age of Blockchains》

原文作者:Ethan Buchman

翻译:潘振东

校对:杜满想

本文为节选

构建应用

Tendermint被设计成为可复制的最终确定性状态机的通用的算法。它使用Tendermint套接字协议(TMSP)标准化共识引擎和状态机之间的沟通,使得应用开发者可以用任何语言去构建他们的状态机,并通过这种方式自动复制了基于Tendermit的BFT算法。

背景

互联网上的应用程序通常可以表征为包含两个基本要素:

  • 引擎:处理核心安全性,网络,复制。这通常像一个网络服务器,如Apache或Nginx,可以构建Web应用程序,或者构建分布式应用程序的一致性算法。

  • 状态机:处理交易的实际应用程序逻辑,从引擎接收并更新内部状态。

这种引擎和状态机结构的分离使应用程序开发人员可以用任何编程语言编写想要的应用程序的状态机,在引擎之上可能专门定义其性能,安全性,可用性,支持性和其他考虑因素。与Web服务器及其应用程序不同,后者通常采用的形式是进程通过公共网关接口(CGI)协议使用套接字进行通信。而共识算法一般来说要以更少的可用性或者更少的通用性接口来构建应用程序。像zookeeper,etcd,consul和其他分布式键值对存储应用一样,提供HTTP接口到简单键值对应用程序的特定实例,还有一些更有趣的功能,如原子比较和交换操作并推送通知。但他们没有给应用程序开发人员控制状态机代码本身。

比特币的成功以及源源不断对区块链技术的兴趣产生了要对状态机运行进行高级别的超越共识引擎的控制需求。通过构建更多高级应用直接进入共识,用户,开发商,监管机构等等,可以在任意状态机上实现更大的安全保障,远远超出键值对存储,如货币,交易所,供应链管理 - 治理等等。它之所以引起了这么多人的注意,是因为这个系统巨大的潜力是允许集体执行前执行代码。它实际上是对许多方面的重新发明法律制度,使用分布式共识算法和确定性可执行合同,而不是警察,律师,法官,陪审团和个人喜好。这对人类社会发展的影响是爆炸性的,就像引入民主法治一样。Tendermint旨在提供基本的接口和共识引擎可以构建此类应用程序。

Tendermint 套接字协议

Tendermint套接字协议(TMSP)定义了共识引擎和应用程序状态机之间通讯的核心接口。这个接口定义包括一系列的消息类型,使用Google’s Protocol Buffers (一个长度作为前缀通过套接字传输的协议),一系列的消息类型,他们的参数,返回值和用途都在图5.1中,整体的结构和消息流程也在图5.2中。

图5.1

Golang定义的TMSP Application interface,TMSP消息被定义为使用Google’s Protocal Buffers,序列化格式是通过TMSP套接字传输之前将长度作为前缀,返回值包括一个代码,和HTTP的状态码类似,代表了任意的错误信息,0表示没有错误,消息在客户端缓存直到一个flush消息被发出,在这个点所有的缓存消息都会被发出。服务端设计的是异步化的,消息返回必须是和请求相匹配的正确的顺序。

图5.2

共识逻辑与应用程序逻辑进行通信是通过TMSP(套接字协议)。维护两个sockets(套接字),一个用于mempool检查新交易的有效性,另一个用于执行共识的新提交的块。

TMSP协议被实现为一个有序的异步的服务,消息类型请求和返回是成对的,当一个特殊的消息类型出现的时候,清空并通过连接推送缓存的所有消息然后等待消息。

在TMSP协议有两种消息是核心,AppendTx 和Commit,一旦块由共识产生,引擎就会在块上调用AppendTx处理每个块中的交易,将其传递给应用程序状态机处理。如果交易有效,则会导致应用程序中的状态转换。

一旦所有AppendTx调用返回,共识引擎调用Commit,使得应用程序提交到最新状态,并将其永久存储到磁盘。

分离协议和执行

使用TMSP可以使我们明确区分共识,或者关于交易顺序的协议,以及它们在状态机中的实际执行情况。特别是,我们首先就顺序达成共识,并且然后按顺序执行交易。这种分离实际上有所提升系统的容错,但是仍然需要总数3f + 1个节点去容忍f个拜占庭式节点的失败,只需要2f + 1个节点执行。也就是说,虽然我们仍需要三分之二的多数来排序,我们只需要一半的多数来执行。

另一方面,事实上交易的执行放在排序之后会导致可能是无效的交易,这可能会浪费系统资源。这种情况使用额外的TMSP消息CheckTx解决的,由mempool调用,允许它检查交易是否会对最新的状态有效。但请注意,事实上块中的一次性提交会引起CheckTx处理消息的复杂性。特别是,应用程序希望维护第二个状态机只执行主状态机相关的交易有效性的规则。第二个状态机由CheckTx消息更新状态并在每次提交后重置为最新的已提交状态。在本质上,第二个状态机描述了交易池的过滤规则。 

在某种程度上,CheckTx可以用作`乐观的执行`返回并将结果发送给交易发送者,但结果可能是错误的,比如一个带有冲突交易的块在利息交易之前提交。这种`乐观的执行`是扩展BFT系统的方法的关注焦点,可以很好地适用于交易之间冲突很少的应用程序。与此同时,它增加了客户端的额外复杂性,因为可能需要处理无效的结果。

微服务架构

采用分离关注点作为应用程序设计的策略是从普遍上来看是明智的做法。特别是,许多当今的大规模应用部署采用微服务架构。其中每个功能组件实现为独立的网络服务,通常封装在Linux容器中(例如使用Docker)以提高部署效率,可伸缩性和可升级性。

在Tendermint共识之上运行的应用程序通常会被分解成微服务,例如,许多应用程序将使用一个键值对存储用于存储状态。为了利用数据存储的优势和某些特有功能,将键值存储作为独立运行的服务很常见,如高性能数据类型或默克而树。
应用程序的另一个重要的微服务是治理模块,它管理某个TMSP消息子集,启用该应用程序控制验证器集更改。这样的模块可以在BFT中变成强大系统治理范式。 

某些应用程序可能为用户使用本机货币或帐户结构,因此,提供支持基本元素的模块是有用的,例如,处理数字签名和管理账户动态。用微服务构成复杂TMSP应用程序例子还有很多。实际上,人们甚至可以构建一个可以启动的,包含了使用交易中发送的数据的子应用程序的应用程序。例如,在交易中包含了一个存储docker镜像的哈希,以便从一些文件存储后端pull下来运行并作为未来的子应用程序运行共识中的交易以导致其运行。这是以太坊使用的方法,允许开发人员将一些代码部署到网络中可以通过上面的方式触发在以太坊虚拟机中运行交易(智能合约),以及IBM最近的OpenBlockChain(OBC)项目,它允许开发人员在交易中发送完整的docker上下文,定义运行任意代码以响应发往他们地址的交易的容器。

确定性

关于使用TMSP构建应用程序的最为严格的忠告是他们必须是确定性的,也就是说,对于复制状态机而言不保证安全。每个节点在执行时针对同一状态的同一交易必须获得相同的结果。这不是Tendermint的独特要求。比特币,raft,以太坊,任何其他分布式共识算法,以及锁步等多人游戏必须严格具有确定性,以免达成共识失败。编程语言中有许多非确定性的来源,最明显的是通过随机数和时间,但也可以通过使用浮点精度,并通过哈希表迭代(一些诸如Go之类的语言强制对哈希表进行随机迭代程序员明确何时需要有序数据结构)。对确定性机制的严格限制,以及确定性在每种主流编程语言中的缺失,促使以太坊开发自己的,图灵完备的,完全确定的虚拟机,它构成了应用程序开发人员在以太坊区块链之上构建应用程序的平台。虽然确定性,它有许多特别之处,例如32字节堆栈字,存储键和存储值,不支持字节位移操作,一切都是大数算术。确定性编程在实时世界中得到充分研究,例如锁步,多方游戏。这类游戏构成了另一个复制状态机的例子。并且在许多方面与共识算法非常相似。鼓励使用TMSP构建的应用程序开发人员进行学习使用他们的方法,并在实现应用程序时要小心。使用函数式编程语言和证明方法可以启用正确程序的构建。在另一方面,编译器也在构建以将可能的非确定性程序转换为规范化确定性的。

终止性

如果说确定性是为了保证安全很严格,那么交易执行的终止性就是为了严格的保证存活。然而,它不是一般的可以确定给定程序是否因单个输入而停止,更不用说所有这些问题,这个问题被称为停机问题。

以太坊的虚拟机通过计量解决问题,具体来说,在执行中的每个操作收费。这样,交易就保证在发起者资金不足时终止。这样的计量在更一般的情况下,可以通过编译程序的编译器实现计量他们自己的版本。

没有显着的开销就很难解决这个问题。在本质上,验证器无法判断执行是处于无限循环中还是只是缓慢,但几乎完成。可以使用Tendermint共识协议决定交易超时,超过三分之二的验证人必须同意交易超时,因此被视为无效(即对状态没有影响)。但是,我们没有在这里进一步实践这个想法,留待未来的工作。同时,预计应用程序将在进行全面测试之前部署在任何共识系统中,监控和治理机制在达成共识的情况下,将用来恢复系统失败。

举个例子

在本节中,将介绍和讨论越来越复杂的TMSP应用程序,特别是CheckTx和管理mempool。

Merkleeyes

TMSP应用程序的一个简单示例是基于Merkle树的键值存储。Tendermint提供Merkleeyes,这是一个包装的TMSP应用程序,一个自平衡的Merkle二元搜索树。交易的第一个字节确定交易是get,set还是delete操作。对于get,delete操作,剩余的字节是键(key)。对于set操作,其余字节是包含键和值的序列化列表。Merkleeyes可能使用CheckTx的简单实现对交易进行解码,以确保其格式正确。也可以实现更高级的CheckTx,get和delete操作对未知key无效。调用Commit后,将添加最新更新进入Merkle树,重新计算所有哈希值,树的最新状态也在磁盘上提交存储。

请注意,Merkleeyes被设计为其他TMSP应用使用的基于Merkle树的键值存储的模块。而不是单独的TMSP应用程序,虽然TMSP接口的简单性使它适用于两者。

货币应用

一个更重要的完整实例是一个简单的货币,用的账户结构由以太坊创立,每个用户都有一个公钥和一个基于该公钥的带有余额的账户,该帐户还包含一个序列号,等于帐户发送的交易数量。交易可以从账户发送资金,如果它们包括正确的序列号,并由正确的私钥签名。没有序列号,系统容易受到重放攻击,可以重播从帐户中扣除帐户的已签名交易,从而导致借记多次发生。此外,防止重放攻击在多链环境中,交易签名应包括网络或区块链标识符。

一个支持货币职能的应用程序自然具有比键值存储更多的逻辑。特别是,某些交易明显无效,例如签名无效,序列号不正确或发送超过发起人帐户余额的金额。这些情况都可以通过CheckTx检查。

此外,必须在CheckTx中维护补充应用程序状态是为了在更新时更新序列号和帐户余额当同时在mempool中有多个涉及相同帐户的交易时。调用commit时,将重置补充应用程序状态到最新的提交状态。任何仍在mempool中的交易都可以通过CheckTx重播最新状态。

以太坊

以太坊使用已经描述的机制来过滤掉mempool中的交易,但它也在虚拟机中运行一些交易,它会更新状态并返回结果。虚拟机执行没有在CheckTx中完成,因为它们包含在块中,它更昂贵且严重依赖交易的最终顺序。

总结

TMSP提供了一种简单而灵活的方法来构建任意应用程序,可以用任何编程语言,继承复制自Tendermint一致性算法的BFT状态机。它扮演的角色大致类似于共识引擎和一个应用程序。例如,CGI扮演为Apache和Wordpress。但是,应用程序开发人员必须特别注意确保他们的应用程序是确定性的,并确保交易执行终止。

相关阅读:

区块链时代的拜占庭容错:Tendermint(一)

区块链时代的拜占庭容错:Tendermint(二)

区块链时代的拜占庭容错:Tendermint(三)

原创文章 29 获赞 2 访问量 8027

猜你喜欢

转载自blog.csdn.net/WXblockchain1/article/details/84873966