Fabric 诞生于2015年,是Hyperledger 最早期的项目之一,其主要由IBM 开发并开源,并受到来自多国家的科技公司、顾问公司和新创的广泛参与。Fabric 可以说是专为企业应用而生的分散式帐本,其以较好的效能与能支援通用程式语言开发的智能合约著称。然而另一方面,Fabric 的复杂架构、充满大量隐晦技术用语的文件、以及与主流区块链截然不同的设计也让开发者望而生畏,见树不见林。

笔者认为,只要洞悉Fabric独特架构背后的设计哲学,便能理解Fabric整体的运作逻辑以及复杂架构,见树又见林。在本文中,笔者将从《Hyperledger Fabric: A Distributed Operating System for Permissioned Blockchains》这篇由IBM研究员发表的论文出发,来探讨:

主流区块链技术体系的局限 Fabric 的设计哲学 Fabric 的运作流程 Fabric 独具的特性

一般公众所知的区块链技术,多是指起源于比特币/以太坊的区块链技术体系,为了与下文所提及的技术做出区分,笔者暂且把主流区块链技术体系称为「中本区块链」(Nakamoto Blockchain)。

中本区块链在企业协作场景的局限

技术概观

中本区块链最重要的特性就是它是无需许可的(Permissionless),是一个去中心化与去识别化的公共网路。因此,它具有抗女巫机制(Sybil-control Mechanism)和独特的共识模型(Consensus Model)以维持它严格的信任假设(Trust Assumption)及维护公平性与激励性。

然而,造就了中本区块链的共识模型却同时也是它最大的效能瓶颈,它究竟为什么比较低效呢

排序— 执行模型(Order-Execute Model)与主动复制(Active Replication)

中本区块链的共识模型称为「排序—执行」模型(Order-Execute Model),顾名思义,就是先对交易顺序形成共识— —也就是排序,再交由所有节点依序执行。同时,每个参与出块的节点必须在「排序」之前先「执行」每一个即将被自己打包的交易,并将无效的(Invalid)交易舍弃;所有节点收到区块后依序「再执行」每笔交易一遍以验证结果,结果无误后再更新本地的帐本。

这样的状态复制模式又称为「主动复制」(Active Replication),在此模式下,节点仅能透过计算过程的重复执行结果来更新自身状态。读者可以注意到:无论这个交易需要的计算有多耗时,它都必须被每一个节点重复执行,这就是中本区块链缺乏效率的主因。

无需许可制与效能的取舍

问题是:为什么中本区块链要使用缺乏效率的主动复制一切又回到中本区块链的「无需许可制」。无需许可代表所有节点都可能会是出块节点,也就必须进一步假设所有节点都可能是会做恶的拜占庭节点。让节点重复执行交易以对其「验证」,是维持严格信任假设的必要手段。

其他局限

除了效能问题,「排序— 执行」模型还伴随一些其他局限:

序列化的执行(Sequential Execution):由于每个节点都有赖于交易的「依序执行」来更新自身状态,可扩展性也受到局限,也难以使用平行处理等方式改善。 确定性的智能合约(Deterministic Code):除了保证交易顺序之外,还必须确保交易的执行都是确定性的(Deterministic),这也限制了智能合约无法使用现有的通用语言开发,因为通用语言多半包含非确定性的(Non-deterministic)特性与内部实作,为此必须重新开发新语言,例如以太坊的智能合约语言Solidity与其虚拟机EVM。 执行机密性(Confidentiality of Execution):由于交易必须被「所有」节点执行,中本区块链所保存的所有状态都必须是公开的,如此每个节点才能读/写这些状态,这也就不利于交易机密性,因为任何节点都能知道任一智能合约的逻辑与其内部状态。

不利于企业协作

效能瓶颈、缺乏隐私与较高的开发成本都会增加在企业协作场景中使用区块链技术的难度。在公共网路的场景中,为了「无需许可制」而牺牲效能是可以接受的,但在企业协作场景就未必合适。

然而,企业之间的网路环境通常并不像公共网路一般能让任何人都「无需许可」地使用,也就是说:在企业协作场景中,原本为了「无需许可制」而存在的「排序—执行」模型或许还有改进的空间。因此,陆陆续续出现了许多改进中本区块链的方案。而在众多构想当中最知名的一个,就是由IBM研究员提出的改进方案,这个方案后来也成为Fabric架构的核心。

那么这个改进方案究竟是什么

新模式:从全新的观点设计适合企业协作的分散式帐本

如上所述,企业协作的网路环境跟公共网路正好相反:企业协作网路是比较受限的,除了参与者固定、采取实名认证之外,还带有权限控管,天生就是「许可制」的环境。而一个采用「许可制」的网路具有比较宽松的信任模型,也就是说:参与者不作恶的机率是比较大的,这带给了共识模型更大的设计弹性。

由IBM研究员提出的改进思路可以浓缩成一句话:「少数执行,多数验证」。这样的思路其实相当直观:在「许可制」的条件下,可以不需要让所有节点都重复执行交易,只要在足以保证安全性的最低条件下让「一部分」的节点执行即可,其他大多数节点不需重复执行,仅需进行少量验证并更新自身状态即可。那么要如何只用少量节点执行就确保安全性呢这需要透过少量节点之间的「共识」来确保。

执行— 排序— 验证模型(Execute-Order-Validate Model)与「混合复制」(Hybrid Replication)

基于上述思路,IBM研究员设计出「执行—排序—验证」模型(Execute-Order-Validate Model)。首先,交易会交由一部分预先指定的节点各自「执行」,执行结果若一致就可以形成共识,未形成共识的交易会被舍弃;接下来,来自不同节点、已形成共识的交易会经由一个特定服务进行排序并打包至区块中;最后,这个特定服务再将区块传播给所有节点,收到区块的节点仅需对交易进行少量「验证」,若验证结果无误便可以更新自身状态。

这个模型体现了「少数执行,多数验证」的精神,其最直接的好处是让大多数节点省去了重复执行交易的工作,并且能在「许可制」的环境下兼顾安全性与效能;除此之外,它还能带来一些良好特性,这些特性会于下文再进行详述。

相对于「主动复制」,不需重复计算而直接更新状态的作法称为「被动复制」(Passive Replication),而在「执行—排序—验证」模型中的作法既不是「主动复制」、也不是「被动复制」— —因为还是有「排序」跟「验证」工作,而是结合两者的「混合复制」(Hybrid Replication)。其「主动」的部分在于:由少数节点达成之「执行」结果的共识可以代表该交易的有效性,因为仅有达成共识的交易最终会被所有节点执行;「被动」的部分在于:大多数节点不需要真的重复执行交易,仅需少量验证便可更新本身状态。

在理解Fabric 的设计哲学后,接下来我们就进入Fabric 的脉络来看看这个模型的运作。

Fabric 概观

由上述的设计哲学我们可以知道:在Fabric 中,「执行」、「排序」、「验证」皆会交由不同角色的节点完成,他们必须各司其职、互相配合才能使Fabric 运行无阻— —这与中本区块链架构中所有节点都做相同工作的设计俨然不同。

Fabric由客户端(Client)、对等节点(Peer)与排序服务(Ordering Service)这三种主要角色构成,它们会组成一个「通道」(Channel)并共同维护一份帐本,只有该通道的组成节点可以读取该帐本的资料。值得一提的是,Fabric节点之间可以根据不同的协作场景同时建构不同通道,且每个通道都是一个独立的区块链网路,具有各自的帐本。

接下来,我们来看看这些角色的主要功能:

客户端(Client)

客户端就是最顶层的应用程式,是使用者与Fabric 互动的主要介面,透过Fabric 提供的软体开发套件(Software Development Kit, SDK)与Fabric 互动。

对等节点(Peer)

对等节点(Peer)是构成Fabric最主要的角色,它负责交易的「执行」与「验证」,以及区块链资料与本地的帐本状态的维护,是具有状态的。值得一提的是,根据「执行—排序—验证」模型,只有少部分被指定的节点需「执行」交易,其他节点只需要「验证」即可。其中,负责「执行」的节点称为「背书节点」(Endorsing Peer);负责「验证」的节点称为「提交节点」(Committing Peer)。

每个对等节点内部的构造都相同,每项工作都由对应的模组完成,以下我们来看看3 个比较重要的模组:

背书模组(Endorser):实现交易的「执行」,其内部实做了Docker容器(Container),能支援用不同通用语言开发的智能合约(Chaincode),合约与背书政策须事先由客户端部署。 提交模组(Committer):实现交易的「验证」与节点状态的更新,并含有一些底层的设定档与系统智能合约(System Chaincode)。 成员服务提供者(Membership Service Provider, MSP):MSP是实现「许可制」的关键模组:它负责节点的身份(Identity)与权限控管(Permissioning)。Fabric采用业界通用的X.509凭证来做身份识别,能够相容于现有的身份管理体系。其中,MSP只负责管理凭证,并不负责发布凭证— —那么谁可以颁发凭证呢只要是凭证机构(Certificate Authority, CA)都能颁发,不论是商用的CA或者是Fabric原生的Fabric-CA,这使Fabric能够很好地与既存的公钥基础建设(Public-key Infrastructure, PKI)整合。

排序服务(Ordering Service)

排序服务(Ordering Service)是Fabric特有的设计,它可以是单个节点,或是多个节点组成的丛集(Cluster),专门负责交易的「排序」与区块的生产,为通道提供交易顺序的共识。相对于有状态的对等节点,无需「执行」、「验证」交易与维护帐本的排序服务是无状态的,这为Fabric带来一个良好的特性:由于不需要处理状态同步问题,Fabric的排序服务能够很容易地透过横向扩展来提高整个系统的交易量。

细心的读者应该会发现笔者目前已提及了两种共识:背书节点的共识与排序服务的共识,关于这两个共识的差异也会在下文详述。

Fabric 运作流程

一个交易从发起到写入帐本究竟会历经哪些流程根据「执行— 排序— 验证」模型,交易会历经三个阶段:「执行阶段」、「排序阶段」与「验证阶段」,整体流程如上图的循序图(Sequence Diagram)所示。根据上图的标号,执行阶段对应了步骤1 与步骤2;排序阶段对应步骤3 与步骤4;验证阶段对应最下面文字叙述的段落。

我们来看看各个阶段的详细运作流程:

1. 执行(Execute)

首先,由客户端发出交易提案(Transaction Proposal),并将签章后的提案发送给一个或多个背书节点。交易提案内容包括ChaincodeID、呼叫参数等等。智能合约(Chaincode)在部署时需附上相应的背书政策(Endorsing Policy),其内会载明这份合约需由哪些节点背书,以及背书形成共识的条件,例如:5个背书节点当中至少3个具有相同执行结果。 接着,背书节点开始「执行」交易并模拟(Simulate)结果。智能合约已事先安装/部署于节点,会在Docker容器中执行。节点的状态以带有版本的(Versioned)键值对(Key-value Pair)表示。每一次执行前所需读取的状态键值对称为「读集合」(Readset);执行后的产生变化的新状态键值对称为「写集合」(Writeset),同样地,它们也都具有版号。 背书节点将交易执行的结果制成「背书」(Endorsement)并回传给客户端,其内容包含读集合、写集合、一些后设资料如TransactionID、EndorserID、背书节点签章等等。 客户端收集来自不同背书节点的「背书」,直到满足背书政策指定的共识,也就是说:需有一定数量的背书节点具有相同执行结果— — 也就是相同的读集合与写集合。

2. 排序(Order)

若满足背书政策,客户端则接着将执行结果制成交易(Transaction)后送给排序节点;否则便舍弃这次交易。交易内包含资料酬载(Payload)、后设资料、以及来自各背书节点的背书。 排序节点会对在一段时间内收到的所有交易进行「排序」并生产区块以形成共识。 接着,排序节点将带有所有交易的区块发送给所有的提交节点。在这里,作为中心协调者的排序服务具有比流言散布协定(Gossip Protocol)来得更有效率的讯息传播模式,通讯复杂度从O(n²) 降阶成O(n),尽管排序服务的频宽也将会是瓶颈,但排序服务可以再进一步采取其他措施减轻通讯负担(Overhead),例如使用更大的丛集。

3. 验证(Validate)

最后,提交节点将在收到区块后进行简单的验证— —由于整个过程都无需「执行」交易,因此它非常迅速且轻量。验证可以再细分为三个步骤:首先是背书政策的评估(Endorsment Policy Evaluation),检查交易附上的背书是否确实满足背书政策;接下来是读写集合(Read/Write Conflict Check)的比对,检查「读集合」的版本是否一致;如果以上都没问题,就可以根据写集合对帐本进行更新。 值得一提的是,提交节点需注意区块是否含有「无效交易」(Invalid Transaction),若交易为无效则直接舍弃,若判定为恶意的行为则可以采取「许可制」之下的独特对策:直接将交易的背书节点设为阻挡名单(Blocklist)。

让Fabric 更灵活的特性:共识的解耦

虽然「执行—排序—验证」模型最初的目标是解决中本区块链的效能问题,但它独特的架构也带来了一些额外的特性,其中值得一提的就是共识的解耦。Fabric具有两个层次的共识:基于背书政策的应用层共识,以及基于排序服务的协定层共识,这意味着应用层与协定层的共识是解耦的(Decoupled)。

应用层的共识:对开发者来说,他们可以为每个运作于Fabric的智能合约都指定不同的背书政策,例如:需要高度信任的应用就把共识门槛调高;反之,就把共识门槛调低,在设计上具有更多弹性。除此之外,应用层共识也使Fabric得以实现非确定性的交易(Non-deterministic Transaction),因为这个共识仅需于少数的背书节点之间形成即可,不需下沉到协定层。 协定层的共识:对系统维运者来说,他们可以依照实际需求去抽换排序服务的共识协定。例如,在跨组织协作中,可以选择具有拜占庭容错(Byzantine Fault Tolerance, BFT)的共识算法,例如PBFT;在同组织的协作中,则可以选择仅具故障容错(Crash Fault Tolerance, CFT)的共识算法,例如Raft。

总结

综上所述,我们可以看到:Fabric尝试用不同的思路来改进中本区块链,透过全新的共识模型,除了更加高效,还具备了更好的可扩展性、模组化的共识、可用通用程式语言开发智能合约、以及便于整合的身份管理体系。

最后再强调一次:中本区块链与Fabric 有全然不同的设计目的。Fabric 可信赖的「许可制」须仰赖企业之间链下的信任关系,一旦用于非企业协作场景,它的信任假设就会受到动摇,在不具「许可制」保护及缺乏抗女巫机制的情况下,Fabric 安全性将不比中本区块链。

关于Fabric 的开发、部署及管理,笔者所在的BSOS 公司具备丰富实务经验,也有多位技术人员具备Hyperledger 官方认证的CHFA 证书(Certified Hyperledger Fabric Administrator, CHFA),欢迎对企业区块链或Fabric 有兴趣的朋友,多多与我们交流指教。