4万字《腾讯云技术实践精选集 2021》发布,点击下载 了解详情
写点什么

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

  • 2020 年 2 月 15 日
  • 本文字数:3664 字

    阅读完需:约 12 分钟

基于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 服务。



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


2020 年 2 月 15 日 17:37468

评论

发布
暂无评论
发现更多内容

中国区块链第一村的价值裂变

CECBC

基于Agora Web SDK自定义直播画面

dajyaretakuya

WebRTC 声网 Agora 数字合成

被解救的代码 - 代码即服务时代来了!

阿里巴巴云原生

容器 微服务 开发者 云原生 开发工具

腾讯校招都会问些什么?| 五面腾讯(Java岗)经历分享

Java架构师迁哥

从基础到实战一应俱全,这份全网首发的Kafka技术手册,超详细!

Java架构师迁哥

图说丨一图看懂浪潮云“1231”业务战略

浪潮云

CRM Transaction处理中的权限控制

Jerry Wang

CRM SAP abap

4年Java开发经验,经常被问到高并发、性能调优方面的问题,该怎么办?

Java架构师迁哥

2021金三银四面试经历:阿里七面(已拿offer),面试经历+真题分享

Java 编程 程序员 架构 面试

Python--TKinter

若尘

Python编程 5月日更

Keycloak 13 自定义用户身份认证流程(User Storage SPI)

Zhang

MySQL spi keycloak 13.0.0 user storage spi

用ABAP 生成二维码 QR Code

Jerry Wang

二维码 SAP abap

关于打的 umd 包在使用时,报 require is not defined 错误的问题出处

blueju

业界率先支持 MCP-OVER-XDS 协议,Nacos 2.0.1 + 1.4.2 Release 正式发布

阿里巴巴云原生

容器 微服务 云原生 k8s 中间件

“碳中和”目标下的绿色金融探索

CECBC

金融

爱奇艺世界大会|刘文峰:科技创新如何为用户和艺术家服务?

爱奇艺技术产品团队

爱奇艺世界大会|开幕式速览:智能制作助推影视工业化,匠心构筑行业健康生态

爱奇艺技术产品团队

ElasticSearch架构剖析

五分钟学大数据

大数据 elasticsearch 5月日更

打破思维定式(十一)

Changing Lin

Flink消费Kafka

大数据技术指南

大数据 flink 5月日更

新融合,新跳板:智能云网如何让企业数字化转型,起步即领先?

脑极体

架构实战营模块四总结

竹林七贤

终于来了!这份阿里P9纯手写的Java并发核心手册,把我没学会的高扩展、高性能、高可用全部讲清楚了

Java 程序员 架构 面试

进大厂的iOS程序员,原来是这样“跳槽”的!

iOS猿_员

有无社保缴纳识别接口

ALone

“技术+应用”驱动金融科技创新融合

CECBC

金融

5分钟速读之Rust权威指南(三)

码生笔谈

rust

使用 Shell 脚本实现 Docker

ScratchLab

Docker 容器 namespace Cgroups

数据挖掘从入门到放弃(四):手撕(绘)关联规则挖掘算法

数据社

机器学习 5月日更

五岳核心版上线!这份阿里开发手册核心版又将被多少人疯狂转载?

Java 编程 程序员 架构 面试

2021最热门的20个数据库学习总结,你会用哪几个?

北游学Java

Java MySQL 数据库 后端

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