Fabric是一个模块化和可扩展的开源系统,用于部署和操作许可的区块链,也是Linux基金会(www.hyperledger.org)主持的Hyperledger项目之一。
Hyperledger Fabric是一个较为典型的联盟链结构。
区块链核心概念是分布式帐本(Distributed ledger)。分布式账本是一种在网络成员之间共享、复制和同步的数据库。分布式账本记录网络参与者之间的交易,并降低了因调解不同账本所产生的时间和开支成本。
状态复制机(SMR)与分布式数据库的对比如上图所示,其优点是数据很难造假,即使造假也可以通过追溯来追究责任。缺点是极大的浪费。
区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式数据结构。区块链记账方式与传统的方式相比,一个是帐本不能过大,不能超过区块链网络中最小节点的存储及处理能力。另一方面,区块链环境具有拜占庭缺点:
区块链的发展过程中,一般1.0时代就是数字货币时代,代表是比特币。而2.0时代就是智能合约,代表是以太坊。现在是3.0时代,各种联盟链即为代表。
在fabric中,智能合约叫做chaincode,它有6个状态,如下所示:(与以太坊上的智能合约方式类似)
Install → Instantiate → invocable → Upgrade → Deinstantiate → Uninstall.
智能合约代码上传到区块链上,这一步的状态就叫Install。
Instantiate: 初始化操作。比如,现在的数据是存放在mysql中的,那么上线时需要用Instantiate把数据迁移至链上,这也算初始化。
初始化后,chaincode就进入invocable可调用状态了。
联盟链由于跨多家企业、多个地区甚至国家,很难使得合约保持一致的版本,因此,每个合约都有版本号。而版本升级时,就是Upgrade状态。
最后两个状态对应着合约下链。即合约销毁阶段。
区块链处理一致性方法较多,如PBFT、POW、POS等等。(不再列举)Hyperledger Fabric则采用PBFT(Byzantine-fault tolerant)是第一个引入可插拔共识的区块链系统。网络中的Orders(即Consenter)作为共识插件,也可以理解为提供共识服务的网络节点,其负责接受交易信息并进行排序,以及对交易进行切割并打包,打包后返回批量交易。
Hyperledger Fabric中采用的非对称加密技术实现身份验证和数据加密。也就是常说的SSL技术。
涉及:
可以简单的理解为:私钥签名,公钥验证。具体细节可以寻找过寻找更多资料
PKI(Public Key Infrastructure),它是一种遵循标准的利用公钥加密技术为电子商务的开展提供一套安全基础平台的技术和规范。有一个CA(Certificate Authority)权威机构负责向用户(包括服务提供者与使用者)提供数字证书,包括公钥与私钥,同时CA机构还需要提供一个CRL(Certificate Revocation List)证书吊销列表,如下图。
数字证书是指在互联网通讯中标志通讯各方身份信息的一个数字认证,人们可以在网上用它来识别对方的身份。因此数字证书又称为数字标识。数字证书对网络用户在计算机网络交流中的信息和数据等以加密或解密的形式保证了信息和数据的完整性和安全性。
比如Mary Morris符合X.509规范的数字证书里,其Subject属性里就含有她的信息,包括国家C=US、所属的州或者省份ST=Michigan、所在城市L=Detroit、所属单位O=Mitchesll Cars、其他信息OU=Manufacturing、公用信息CN=Mary Morris/UID=123456等,也含有其他信息,如下面的图所示。
CA颁发了两个证书:公钥与私钥,其中,私钥仅服务提供者保存,而公钥则可被所有人(服务使用者)保存。
所谓非对称加密,就是公钥加密的消息仅私钥可以解密;同理,私钥加密的消息,仅公钥可以解密。对应于前者,可以实现客户端访问服务器时加密消息,例如访问安全级别高的页面时提交的表单信息都需要用公钥加密,确保只有服务器才能解密网络报文。对应于后者,则可实现签名功能,如下面的图所示。
Fabric的体系结构遵循一种新颖的执行顺序验证范式,用于在不可信环境中分布式执行不可信代码。它将事务流程分为三个步骤,可以在系统中的不同实体上运行:
Fabric使用分布式数据库中常见的被动或主备份复制,但使用基于中间件的非对称更新处理,并移植到具有拜占庭式故障的不可信环境中。在Fabric中,每个事务仅由对等体的子集执行(认可),这允许并行执行,并利用“执行-验证”BFT复制解决了潜在的不确定性。灵活的背书策略指定了哪些对等方或多少对等方需要保证给定智能合同的正确执行。第二,Fabric结合了主动复制,即事务对分类帐状态的影响仅在它们之间就总订单达成一致后,在由每个对等方单独执行的确定性验证步骤中写入。这允许Fabric根据交易背书尊重特定于应用程序的信任假设。此外,状态更新的排序被委托给用于一致性的模块化组件(即,原子广播),该组件是无状态的,并且在逻辑上与执行事务和维护分类帐的对等体分离。由于共识是模块化的,它的实现可以根据特定部署的信任假设进行定制。尽管也可以很容易地使用区块链同行来实现共识,但这两种角色的分离增加了灵活性,使人们可以依赖成熟的工具包来进行CFT(故障容错)或BFT订购。
总之,Hyperledger Fabric在拜占庭模型中混合了被动和主动复制,以execute - order - validate为主要体系。
另外涉及概念:
chaincode:Fabric中智能合约的叫法,上文已提到。每个chaincode可提供多个不同的调用命令。
transaction:交易,每条指令都是一次交易。
world state:对同一个key的多次交易形成的最终value,就是世界状态。
endorse:背书。金融上的意义为:指持票人为将票据权利转让给他人或者将一定的票据权利授予他人行使,而在票据背面或者粘单上记载有关事项并签章的行为。通常我们引申为对某个事情负责。在我们的共识机制的投票环节里,背书意味着参与投票。
endorsement policy:背书策略。由智能合约chaincode选择哪些peer节点参与到背书环节来。
peer:存放区块链数据的结点,同时还有endorse和commit功能。
channel:私有的子网络,事实上是为了隔离不同的应用,一个channel可含有一批chaincode。通道是由共识服务提供的一种通讯机制,将peer和orderer连接。
PKI:Public Key Infrastructure,一种遵循标准的利用公钥加密技术为电子商务的开展提供一套安全基础平台的技术和规范。
org:orginazation,管理一系列合作企业的组织。
**peer gossip:**用于八卦的通信层基于gRPC,并利用TLS进行相互身份验证,使每一方都能将TLS凭据绑定远端peer的身份。gossip使用两个阶段进行信息传播:(1)push阶段:每个peer从成员视图中随机选择一组活跃的邻居,并将消息转发给他们;(2)pull阶段:每个peer定期探测一组随机选择的peer,并请求丢失的消息。可以优化利用可用带宽和确保所有对等体以高概率接受所有消息是至关重要的。
**peer transaction manager(PTM)**在版本化的键值存储中维护最新状态。存储一个元组形式(key, val, ver)为每个唯一的输入键存储任何chaincode,包含最近存储的值val和最新版本ver。版本号由块序列号和块中事务序列号组成。这使得版本唯一且单调递增。
生产实现由订购服务节点 (osn),这些节点实现这里描述的操作,并在系统通道进行通信。
OSN直接将新接收到的事务注入到原子广播(例如,Kafka broker)。osn批处理从原子广播和表单块接收的事务。只要满足以下三种条件之一,一个区块就会被切割:(1)该区块包含指定的最大事务数;(2)块已经达到最大大小(以字节为单位);或者(3)从接收到第一个新块的交易已经过去了一段时间,如下所述。
**ordering service:**订购服务管理多个通道。提供以下服务:(1)原子广播建立事务顺序,实现广播和传递调用。(2)重新配置通道,当他的成员通过广播一个配置更新事务来修改通道。(3)访问控制,这些配置中,订购服务作为一个受信任的实体,限制广播的事务和接收块到指定的客户端对等。
fabric联盟链的开发人员主要分为三类:底层是系统运维,负责系统的部署与维护;其次是组织管理人员,负责证书、MSP权限管理、共识机制等;最后是业务开发人员,他们负责编写chaincode、创建维护channel、执行transaction交易等,如下面的图所示。
fabric大致分为底层的网络层、权限管理模块、区块链应用模块,通过SDK和CLI对应用开发者提供服务,如下面的图所示。
开发流程主要包括写智能合约,以及通过SDK调用智能合约,及订阅各类事件,如图。
2.2 MSP
MSP可以简单理解为管理员,其为所有参与网络的节点提供一个身份。
网络中节点有三种身份:
(1)Clients: 提交事务建议以执行,帮助编排执行阶段,最后广播事务以进行排序。
(2)Peers: 执行事务提议并验证事务。所有对等节点都维护分类账。这是一个仅附加的数据结构,以散列链的形式记录所有交易,状态。
(3)ordering service nodes(OSN, 也叫ordorsers): 共同构成订购服务的节点。订购服务建立网络中所有事物的总顺序,其中每个事务都包含在执行阶段的状态更新和依赖关系,以及背书对等体的加密签名。
每个管理协作企业的ORG组织都可以拥有自己的MSP。如下图所示,组织ORG1拥有的MSP叫ORG1.MSP,而组织ORG2业务复杂,所以维护了3个MSP。
MSP出现在两个地方:在channel上有一个全局的MSP,而每个peer、orderer、client等角色上都维护有本地的局部MSP,如图所示。
本地MSP只保存有Global MSP上的子集,内容保存在本地文件系统上,而全局MSP可在逻辑上认为是配置在系统上的,它实际也在每个参与者上保存一份拷贝,但会维持一致性。
MSP也分级,如下图所示,底层的network MSP负责网络层的准入,其MSP由ORG1拥有,而上面的某个channel的MSP则由ORG1和ORG2共同管理。
一个MSP下含有以下结构,如图所示。
可见,MSP结构包括:
peer结点上保存有账本ledger以及智能合约,如下图所示,每个节点都存储有智能合约和公共帐本:
channel是一个逻辑概念,可以通过MSP隔离全网不同组织的参与者,如下图所示:
当有多方参与者时,例如4个org组织、8个peer结点时,其中channel连接了P1、P3、P5、P7、P8这五个节点,其他3个节点加入了其他channel,其部署图如下所示:
加入MSP来管理身份时,如P1和P2由ORG1.MSP管理,而P3和P4的证书则由ORG2.MSP管理,他们共同使用一个channel,则如下图所示:
3.2 交易的执行流程
在执行阶段,客户签署并将事务提议(或简单地说,提议)发送给一个或多个背书人以执行。回想一下,每个链代码都通过背书策略隐式地指定了一组背书人。建议包含提交客户的身份(MSP),事务负载的形式执行一个操作,参数,和chaincode的标识符,现时标志只使用一次,每个客户端(比如一个计数器或一个随机值),和一个事务标识符来自客户端标识符和现时标志。
执行阶段:
(1)执行阶段,客户签署并将事务提议,发送给一个或多个背书人以执行。每个链代码都通过背书策略隐式的指定了一组背书人。包含提交客户的身份(MSP),事务负载的形式,执行一个操作。
(2)背书人通过安装在区块链上的指定的chaincode执行操作来模拟提议。chaincode运行在docker容器中,与主endorser进程隔离。
(3)背书人不将模拟结果持续到分类账状态。区块链的状态是由对等事务管理器(PTM)以版本化的键值存储形式来维护的,对一个键的连续更新的版本号单调递增。一个链代码创建的状态只适用于该链代码,不能被另一个链代码直接访问。注意,chaincode不应在程序代码中维护本地状态,只应该在区块链状态中,维护通过GetState、PutState和DelState操作访问的状态。
(4)每个writeset背书人产生价值,包括状态更新所产生的模拟,以及读取组,代表建议的版本依赖模拟。模拟后,背书者以加密方式签名一条名为背书的消息,该消息readset和writeset(事务ID,背书者ID,背书者签名等元数据),并在提议响应后发送回客户机。
去中心化的设计,必然需要通过投票(多数大于少数)来维持数据一致性,而任何投票都必须经历以下三个过程:
有一方先提出议案proposal,该议案有对应的一批投票者需要对该结果背书,这些投票者依据各自的习惯投票,并将结果反馈;
统计投票结果,若获得多数同意,才能进行下一步;
将获得多数同意的议案记录下来,且公之于众。
由client上的CLI或者SDK进行proposal议案的提出。client会依据智能合约chaincode根据背书策略endorse policy决定把proposal发往哪些背书的peer节点,而peer节点进行投票,client汇总各背书节点的结果;
client将获得多数同意的议案连同各peer的背书(包括其投票结果以及背书签名)交给orderring service,而orderer会汇总各client递交过来的trasaction交易,排序、打包。
orderer将交易打包成区块block,然后通知所有commit peer,各peer各自验证结果,最后将区块block记录到自己的ledger账本中。
我们看一个具体的例子,若channel上有三个peer背书者,client提交流程如下图所示:
详细解释下上图的流程:
首先,client发起一个transaction交易,含有
这三个peer节点模拟执行智能合约,并将结果及其各自的CA证书签名发还client。client收集到足够数量的结果后再进行下一步。
client将含背书结果的tx交易发向ordering service。
ordering service将打包好的block交给committing peer CP1以及EP1、EP2、EP3这三个背书者,背书者此时会校验结果并写入世界状态以及账本中。同时,client由于订阅了消息,也会收到通知。
如果我们从编程的角度来看,则流程会更清楚:
参见上图,A是我们的应用程序,其步骤如下:
A首先连接到peer。
A调用chaincode发起proposal;与此同时,P1收到后先模拟执行,再产生结果返回给A。
A收到各peer返回的结果。
A向O1发起交易;与此同时,O1产生区块后会通知peer,而peer会更新其账本。
最后通过订阅事件A收到了结果。
最后再细看下这三个阶段。
可以看到,A1发出的
O1在一个channel上会收到许多T交易,它会将T排序,在达到block的最大大小(一般应配1M以下,否则性能下降严重,kafka擅长处理小点的消息)或者达到超时时间后,打成区块P2。
O1将含有多条交易T打成区块的B2发往各peer节点,而P1和P2将B2加入各自的L账本中。
本文主要参考了https://blog.csdn.net/shebao3333/article/details/103406037和Hyperledger Fabric的白皮书。