基于tendermint实现Hyperledger Fabric的拜占庭容错排序

一、引言

HyperLedger Fabric 作为一个架构灵活的企业级区块链平台,正在被越来越多的企业用于生产环境。之前我分享过一篇文章《HyperLedger Fabric在携程区块链服务平台的应用实战》介绍了一些携程对于 HyperLedger Fabric 的落地经验,并重点分享了 Fabric 框架在代码结构灵活性上的一些认识和在 Fabric 开源框架的基础上做的一些延伸开发。本文将分享我们在 Fabric 排序服务做的一个延伸点。

二、fabric orderer 服务过程分析

我们先以最简单的 solo 为例,看一下 Fabric 的 orderer 节点接收排序请求后的主要处理逻辑。

首先,orderer 的排序服务需要实现 consensus 包的 Consenter(排序引擎)interface,Consenter 接口只需要实现一个 HandleChain 方法,该方法需要返回一个 Chain 对象。

Chain 对象需要实现 Chaininterface,实现 Order(普通交易排序)、Configure(配置交易排序)、Start 等主要方法。那我们现在来看一下当一个 orderer 节点启动后,将会经过怎样的步骤,如何实现对交易的排序。

1、当我们在 fabric 网络定义排序类型为 solo 的情况时,orderer 节点启动会初始化一个 solo consenter 对象(参考代码 orderer/common/server/main.go 中的方法 initializeMultichannelRegistrar)。

2、当 orderer 启动后,orderer 节点会检查本地账本中存在的通道,此时发现只有一个 testchainid 通道(了解 fabric 的话,我们会知道当区块链网络创世时,会有一条默认名为 testchainid 的系统通道),solo consenter 会为系统通道 testchainid 创建一个 chain 对象保存在 orderer 内存中,并启动监听来自 orderer 节点接收到的系统通道配置交易(testchainid 只会接受配置类交易,如创建新的通道请求)。

chain 对象请求监听的原理其实是在 chain 的 start 方法中会启动一个 goroutine 监听一个名为 sendChan 的 go chan。

3、此时我们假设有一个创建名为 mychannel 新通道的交易被 orderer 接收到,只能是 testchainid 系统通道对应的 chain 对象来进行处理,此时 orderer 节点会判断该交易类型为配置类型交易,则调用 chain 对象的 configure 方法,configure 方法将交易写入 chain.sendChan 中。

4、此时,会触发 sendChan 的监听服务,监听服务会检查交易并将交易通过 ch.support.BlockCutter().Ordered 方法放入本地队列中等待出块,出块任务在启动 orderer 节点时时会启动一个 chan timer,每隔固定时间(设置的 batchTimeOut)会从队列中取出一定的交易数量(不超过设置的每个块最大的交易量)出块,并写入 orderer 本地账本,当 mychannel 的创建交易被成功受理出块,即意味着名为 mychannel 的新通道已经被创建。

5、mychannel 通道创建后,solo consenter 会通过 HandleChain 方法为之创建一个新的 chain 对象,mychannel chain 对象会受理 mychannel 通道的交易排序,原理与以上同。

以上只是以 solo 的 order type 为例,fabric 截止到目前的 1.4 版本,官方推荐使用更稳定的 kafka 排序。

kafka 排序与上述例子中 solo 排序的区别是:可以支持多个 orderer 节点,所有的交易可以请求任何一个 orderer 节点,请求的 orderer 节点本地排序出块后会通过 kafka 集群将数据同步给其他的 orderer 节点,意味着排序服务可以实现更高的可用性。

我们在查看 orderer 源码时,发现了官方已经在做 raft 排序。简单测试了一下,过程是能够走通了,大家可以耐心等 release 版本。

三、为什么要做 pbft 排序服务

我们认为目前已经 release 的 kafka 排序是能够满足初级的联盟链需求的。

背景是,现在的联盟链更多是一强多弱型企业联盟,如一个大型公司主导区块链业务与技术,其上下游机构合作参与;如一个集团性企业布道区块链,其分子公司合作参与;如 aws、阿里云等云厂商提供 baas 云服务,企业使用只需要向 baas 申请节点资源。

以上情况中,kafka 集群大都需要部署到大型公司、集团总部或者云厂商,保证高计算能力和高可用,是可以支持比较高并发的上链请求的(官方数据是 TPS 可以达到 3000 以上)。

为什么说是初级呢?我们可以发现以上列举的情况实际是有偏离区块链初衷的,区块链在联盟中更应该作为联盟企业间平等、互信合作的基础设施。当联盟间各个企业不存在一强多弱,真正是几家平等的企业在合作时,在技术设计中就会存在一个比较大的疑惑,kafka 排序服务应该部署在哪里呢?也许部署到公有云上是一个选择,但当云厂商本身是利益的相关方呢?

所以我们认为,无论是官方正在开发的 raft 排序还是我们做的 pbft 排序,最重要的目的就是首先要允许 orderer 节点部署到不同的企业,每个企业都参与到 fabric 的排序服务,而不是像 kafka 排序一样需要将排序服务部署到一个中心化的机构。

四、基于 tendermint 的 abci 实现 fabric 排序服务

Tendermint 提供了一个高性能、一致的、安全的 BFT 共识引擎,严格的分叉问责保证能够控制作恶者的行为。

Tendermint 非常适合用于扩展异构区块链,包括公有链以及注重的性能的许可链/联盟链,像 Ethermint 就是一次对 Ethereum 以太坊 POS 机制的快速实现。使用 Tendermint 在区块链领域中的成功案例包括 Hyperledger Burrow、cosmos 等著名项目 。

tendermint 项目的团队是正在进行著名跨链项目 Cosmos 研发的团队(相信很多同学一定关注过这个明星项目),而 tendermint 也是作为共识协议用于在 Cosmos Hub 上构建第一个分区。

Tendermint 独有的 abci 定义了区块链执行的标准接口,可以允许用户自定义实现接口内容,不需要修改 tendermint 源代码来集成他,并支持跨语言通过上层接口进行调用。这就为许多其他技术栈甚至不同语言的区块链底层的集成提供了思路。关于更多 tendermint 的介绍这里不再赘述。

这里,我们通过 tendermint 的 abci 来实现 fabric 的 orderer 服务。

image

fabric 的排序方式,需要 peer 节点将交易 proposal 发送给任一 orderer 节点,kafka 排序是 orderer 节点借助 kafka 消息队列,而 raft 排序是 orderer 节点借助 etcd 实现区块传递给其他 orderer 节点。而在这里,我们让 orderer 节点借助其内部的 tendermint 节点服务,将消息传递给其他 orderer 节点,并能够兼容其中的拜占庭节点。

下面我们借助 tendermint 的 abci 接口,实现代码不侵入,完成 orderer 的 tendermint pbft 排序。

首先,新建一个全新的 package 实现 fabric consensus 的所有接口方法。这里可以判断,每次 handleChain 方法触发(一个新的 fabric channel 创建)时,尝试调用 tendermint 包的 node.NewNode 方法启动 tendermint 服务,可以多个 channel 只启动一个 tendermint 服务。

然后,每当有新的交易传递到 orderer 时,envelope 类型的交易都会通过 order 方法和 configure 方法传递进来,这里我们只需要在两个方法中,将交易序列化为 tendermint 可以传递的数据类型如 byte 数组,调用 tendermint 节点的 Mempool.checkTx 方法,将交易打包到 tendermint 的内存池中即可。

之后的事情,打包到 tendermint 内存池中的交易,将进行多个 orderer 节点的 pbft 共识,这里会执行 tendermint 的标准 p2p 通信和多轮共识。

完成共识之后,需要我们通过 tendermint 的 abci 的 DeliverTx 和 commit 方法获取到共识后的交易,并调用 fabric 的 CreateNextBlock 方法和 WriteBlock 方法打包生成区块。即完成一个完整的交易共识并记账。

这里,有一个比较容易产生疑问的问题,我们知道 fabric 是多通道的账本结构,而 tendermint 是单通道账本,如何做到兼容两边?

在这里,实际我们是需要写 fabric 和 tendermint 两套账本的,从上述过程我们可以看到,共识交易完成后需要每个 orderer 节点自行调用 fabric 自带的写区块方法在对应的通道中进行写块,而同时我们在 abci 中也创建了一个 tendermint 的基于 leveldb 的账本。即每一笔交易,我们也在 tendermint 的账本中记录了一份,只是没有区分通道,因为本来 fabric 中的 orderer 也是记录的全通道数据。

该账本主要用于 fabric 追块,当某个 orderer 节点的 tendermint 块高度比其他节点小时,会触发 tendermint 的追块功能,从 tendermint 中读取交易后写入自己的 tendermint 账本,同时写入 fabric 对应通道的区块中。

以上整个过程,没有动过 tendermint 的源代码,只需要扩展一个新的实现 fabric 的 consensus 接口的类,在类中同时实现 tendermint 的 abci 接口即可。简单代码请参考https://github.com/hxmhlt/fabric/tree/develop-1.4-tmpbft

代码一些功能还未完成,如动态添加 orderer 节点需要结合 tendermint 动态添加 validator 功能来做、tendermint 配置文件的自动生成、性能也未进一步优化,也或许还有一些其他问题,代码截至撰写本文还未用于生产环境。开源部分的源代码仅供参考,也欢迎各位读者在评论区交流~

本文转载自公众号携程技术(ID:ctriptech)。

原文链接

https://mp.weixin.qq.com/s/4lccUIoXrfWn_Za8xJXH-w

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335