Fabric
Fabric官方文档https://hyperledger-fabric.readthedocs.io/en/latest/blockchain.html
Fabric是一个支持智能合约的分布式账本系统。
Fabric是私有的,只有通过MSP认证的成员才可以进入到系统,参与合约的缔造与执行。
Fabric是插件式设计,账本数据有多种存放方式,共识机制可以切换,支持不同类型的MSP。
Fabric开发了channel功能,一个channel对应一个账本,只有加入channel的成员可见,可以防止竞争对手知晓交易的细节。
账本由两部分组成:全局状态(word state)和交易日志(transaction log)。 全局状态中记录的是当前状态,交易日志中记录了所有的交易记录,全局状态是这些交易记录的执行结果。
智能合约(Smart Contracts)用chaincode
编写,由区块链外部的应用调用执行,chaincode通常是用来更新账本的。
概念
Assets: 交易的资产
ChainCode: 描述交易逻辑的代码
Ledger Features: 账本功能
Privacy through Channels: channel的私密性,可以对全网开发,也可以只对部分成员开放
包含交易逻辑的ChainCode可以只部署在特定用户端,实现部分公开的效果
还可以在ChainCode中对数据进行加密
Security & Membership Services: 参与交易的用户都经过认证的可信用户
Consensus: 交易从发起到被提交到账本的过程中的检验
四种服务节点
背书节点(Endorser)
确认节点(Committer)
排序节点(Orderer)
证书节点(CA)
关于Peers
是整个网络的基础,账本和智能合约的载体。
创建时无账本和链码。
账本与链码
- 智能合约:chaincode,可以访问账本的代码
- peer持有账本和链码的实例(一对多)
- 允许一个账本没有链码:意味着无法访问和更改账本
- 不管用户是否已经安装了自己的链码,每一个peer都有一些系统链码(据我所知,channel的建立以及lead节点的确定就是通过系统链码来完成的)
- 链码数量与账本数量也没有必然关系
- 由于一个Peer可能持有多个账本和多个链码,超级账本中通道(channel)就显得尤为重要了。
Application与Peers
- Application与Peer的交互主要包括账本查询与账本更新,账本查询只需要简单的三次会话;而账本更新需要额外的两次会话。
orderer用来确保所有的Peer持有的账本同步更新。在上图中,查询账本的步骤可以做如下的简单描述:
(上图的前三点)
- application连接到peer。
- application生成提案,并将提案提交给peer。
- peer根据提案调用相应的链码执行。
- 链码根据提案查询对应的超级账本。
- 向application返回提案应答。
至此,账本查询的完成。更新账本还需要接下来完成下面的步骤:
(下面两点)
- application根据查询的返回结果生成一个交易并发送给排序服务模块(Orderer)。
- orderer将交易发给网络内的所有节点(peers) :因为账本更新要与其他peer达成共识。
- peer根据交易调用相关的链码完成账本更新(此处图中可能产生误导,P1不可以直接调用L1,应该先调用S1,再通过S1调用L1)。
- 账本更新完成后产生事件通知application更新完成。
Peers与通道(Channel)
基本上,一个链由1个通道+ 1个账本+ N个成员组成。非链的成员无法访问该链上的交易。链的成员可以由应用程序动态指定。
类似与发布——订阅模式消息传递方式
通道为网络中的所有模块提供了私有的沟通与交易渠道。
这些模块包括peer节点、oderder节点、application。
加入通道后,这些模块可以共享或管理通道内的所有账本。
一个节点可以加入到多个通道中(即,拥有多个账本),
每个通道的账本是隔离的。
通道是一个逻辑结构,它由物理存在的各种节点组成。
peers提供了访问通道或者管理通道的接口(个人觉得,通道就是一个区块链,一个区块链有一个账本,一个账本可能有一个或者多个链码)。
Peers与组织
- 一个区块链网络由多个组织组成,而非单一的组织。
- 组织才是区块链网络所需要资源的拥有者和提供者,是区块链的价值基础。
- 区块链很有可能是跨域(domain)的,很多时候我们需要多个域一起才能构成一个完整的区块链网络。因此,这里的组织可以看成域的概念
- 4个组织提供了8个peers,通道C连接了其中的5个peers(P1、P3、P5、P7、P8)
- 其他的节点(P2、P4、P6)没有连接到当前通道。但加入了至少一个其他的通道(图中未给出)
- 一个application可以连接到自己所在组织的peer,也可以连接到其他组织的账本。这依赖于application与账本的交互方式。比如:对于查询操作,application只需要连接到自己组织的peer即可;但是对于更新操作,需要连接到所有组织的指定peer,因为更新操作需要背书操作。
- 为了与当前的区块链网络交互,每一个组织都需要一个锚定节点(Anchor Peer)。如P1、P3、P5、P7和P8。
Peers与身份
通过特定的认证授权,每个Peer都被赋予了一个指定的数字签名。数字签名像一个身份证,包含了当前peer的各种信息。每个Peer都拥有所在组织管理员签发的数字签名。
当一个Peer加入通道C的时候,它的数字签名表明了它所在的组织。如图所示,P1和P2的数字签名由CA1签发;而P3和P4的数字签名由CA2签发。通过配置,通道C知道CA1来自组织ORG1;而CA2来自ORG2。ORG1.MSP和ORG2.MSP由通道的MSP统一管理。
通过配置(Channel Configuration),通道知道接入的每个Peer的权限。
MSP(Membership Service Provider)模块决定了一个Peer的角色,访问区块链资源的权限。
由于一个Peer只能属于一个组织,因此它只能被关联到一个MSP上面。
实际上,所有的节点在访问区块链网络的时候都需要进行身份认证。包括Peer节点、application、Orderer节点以及管理员等。
需要注意的是,节点的物理位置并不重要。它可以是位于云端,也可以是组织的中心服务器或者本地的计算机。节点的身份认证决定了它是否可以加入指定的区块链网络,以及加入网络后的角色和权限。
Peers与Orderer
Orderer是整个处理的核心
排序服务保证了application和Peers在交互的时候账本的一致性。
在账本更新的时候,我们需要需要与网络中其它节点达成共识。
通常情况,application需要3个步骤来完成账本更新并保障数据的一致性:
- application将更新提案发给指定的背书节点,背书节点对提案背书,但不更新本地账本,然后将背书结果返回给application。在这里,背书节点是所有节点的一个子集,即不要求所有节点参与背书。
- application将收集所有的背书,然后打包到块中。
- TODO
步骤一:提案
第一步提案阶段,主要由application和一些相关的Peer节点完成。提案阶段是application向不同组织的背书节点提交更新请求。如下图所示:
- application产生一个交易提案,并将提案发送给所有相关的背书Peer节点。每个背书节点根据交易提案独立的执行链码,并返回提案回执。需要注意的是,这个阶段背书节点并不更新本地账本,只是对提案签名并返回给application。当application收集到了足够的提案回执,提案阶段就完成了。
- 如图,A1根据交易T1产生提案P,并分发给通道内的所有背书节点P1和P2。P1和P2分别进行背书,P1调用自己的链码S1产生回执R1和背书E1。P2同理。P1和P2背书完成后将回执发回给application。
- 背书节点的确认依赖于背书策略,背书策略由链码确定,它定义了一个交易在被整个网络接受以前需要哪些组织背书。从业务上来说,当产生一个交易的时候需要哪些组织确认才能让交易生效,那么这些组织就需要为交易背书。
- 背书节点(Endorser Peer)在回执中添加数字签名,并且使用私钥对整个payload域(原始报文)加密。因此,背书回执可以看作是该组织对该交易的一个有效证明。
- 需要注意的是,对于相同的提案,不同的背书节点返回的回执结果可能不一样。导致结果不一样的情况可能原因有两种:一是每个背书节点持有的账本状态不一致,导致背书回执是基于不同的账本状态产生的。对于这种情况,我们只需要简单的请求一个最新回执即可;另外一个原因是由于背书节点链码的不确定性导致的。这种情况就会比较严重,因为不确定性是链码和账本的天敌。不确定性出现说明交易提案本身就有问题,而且很明显这种不一致的结果是不能写入到账本的。而且,每个单独的背书节点并不知道他们的回执具有不确定性,因此需要收集所有的回执并加以比较才能知道是否存在不确定性。关于更多的不确定性的讨论参加交易相关的文章。对于application来说,它在发现不一致的时候可以终止交易,实际上回执不一致的交易会在接下来的步骤中被拒绝掉。
步骤二:打包
打包操作由排序节点(Orderer)完成。所有application的交易在提案完成背书后,包含背书结果的回执会被发送到排序节点。因此,排序节点会收到来自所有application的各种背书提案,它会对所有交易进行排序然后打包发给所有的Peers(包括先前参与背书的Peer)。如下图所示:
- 图中,A1发送的交易T1包含了回执R1和背书E1 E2;A2发送的交易T2包含了回执R2和背书E1。这些交易在排序节点中进行排序打包处理,形成一个块B2。
- 排序服务节点会同步收到不同application发送的很多交易,排序节点会对这些交易排序,然后打包成块。实际上,这些块接下来会发给所有Peer,并成为账本中的新块。在第三步中我们会看见这些块是怎么处理的。
- 需要注意的是,排序后的交易顺序并不和他们到达的顺序一致。排序后的交易顺序就是它们在链码上的执行顺序,交易之间应该是有严格的顺序的。
- 在其它的区块链中,同样的交易可能被打包到不同的块中。但是在超级账本的区块链中这是不允许的,因为一旦一个交易被写入到块中,它的位置也就不可篡改,交易历史也不能在未来被修改,以防止账本分叉(即,要保证一个交易的所有记录被写入到同一个块中。如果交易未完全结束,则等待它完全结束后再写入。防止不可预知的交易结果导致账本分叉)。
- 由此可见,Orderer只是对交易进行排序并打包。它本身不对交易进行验证,因此它和Peer节点不一样,它不包含账本和链码。
步骤三:验证
最后,打包后的交易会被分发到所有节点(Peer)。每个Peer节点会对打包的每一个交易进行验证,以确保每个交易都被相关节点背书,且背书回执是一致的。如果发现不一致,交易将会被审查并保留,不会被写入到账本中。如下图所示:
- Peer节点连接到排序服务,以确保有新的区块产生的时候能获得这个区块的拷贝。每个Peer会单独的处理新的区块。实际上它们的处理方式是一样的,这样确保了账本的一致性。需要注意的是,不是所有的Peer都会连接到Orderer节点。Peer节点可以通过GOSSIP将新的区块散布到网络的其它节点。
- 每个Peer都需要验证接收到的每个交易已经被正确的背书。不同的交易有不同的背书策略,需要不同的组织参与背书。Peer需要确保所有需要参与背书的Peer都参与了背书,并产生了同样的背书结果。
- 在验证成功后,Peer还需要确保当前账本的状态与交易产生是的账本状态是一致的。这就确保了更新后的账本与网络内的其它账本是一致的。因为它们都遵循相同的更新规则。
- 需要注意的是,验证阶段并不需要链码的参与,链码仅在第一步背书的时候用到。这使得参与背书的组织可以对它的背书链码保密。与之对应的是查询链码,它可以对通道内的所有Peer开放。
- 最后,每次Peer的账本更新后都会产生一个块事件。块事件包含了整个块的内容,包括块内的所有交易是否有效或者无效等;而块交易事件仅仅包含了一些摘要信息;除此之外,链码也可以在这个时候产生链码事件。application可以通过注册这些事件知道交易流程。
排序服务与共识
整个交易流程可以被称之为共识,因为所有的Peer在排序和交易内容上达成了一致。
共识是通过多个步骤达成的,而application只是在共识完成后得到通知而已。
排序服务本身也是一个很复杂的处理,但是这里我们简单的认为排序只是搜集、分发来自application的交易提案,而Peer负责验证并将交易更新到账本中。