fabric源于IBM,初衷为了服务于工业生产,IBM将44,000行代码开源,是了不起的贡献,让我们可以有机会如此近的去探究区块链的原理,但毕竟IBM是从自身利益和客户利益出发的,并不是毫无目的的去做这项公益事业,我们在看fabric的同时要有一种审慎的思维:区块链不一定非得这样,它跟比特币最本质的非技术区别在哪里。我们先来大致了解一下fabric的关键术语(因为一些词汇用英文更准确,我就不硬翻译了)。
1. Terminology
  • Transaction  它一条request,用来在ledger上执行一个function,这个function是用chaincode来实现的
  • Transactor  发出transaction的实体,比如它可能是一个客户端应用
  • Ledger  Legder可以理解为一串经过加密的block链条,每一个block包含着transactions和当前world state等信息
  • World State  world state是一组变量的集合,包含着transactions的执行结果
  • Chaincode  这是一段应用层面的代码(又叫smart contract,智能合约),它存储在ledger上,作为transaction的一部分。也就是说chaincode来运行transaction,然后运行结果可能会修改world state
  • Validating Peer  参与者之一,它是一种在网络里负责执行一致性协议、确认交易和维护账本的计算机节点
  • Nonvalidating Peer  它相当于一个代理节点,用来连接transactor和邻近的VP(Validating Peer)节点。一个NVP节点不会去执行transactions但是回去验证它们。同时它也会承担起事件流server和提供REST services的角色
  • Permissioned Ledger  这是一个要求每一个实体和节点都要成为网络成员的blockchain网络,所有匿名节点都不被允许连接
  • Privacy  用来保护和隐蔽chain transactors的身份,当网络成员要检查交易时,如果没有特权的话,是无法追踪到交易的transactor
  • Confidentiality  这个特性使得交易内容不是对所有人可见,只开放给利益相关者
  • Auditability  将blockchain用于商业用途需要遵守规则,方便监管者调查交易记录
2. Architecture
架构核心逻辑有三条:Membership、Blockchain和Chaincode。

2.1 Membership Services
这项服务用来管理节点身份、隐私、confidentiality 和 auditability。在一个 non-permissioned的区块链网络里,参与者不要求授权,所有的节点被视作一样,都可以去submit一个transaction,去把这些交易存到区块(blocks)中。那Membership Service是要将一个 non-permissioned的区块链网络变成一个permissioned的区块链网络,凭借着Public Key Infrastructure (PKI)、去中心和一致性。
2.2 Blockchain Services
Blockchain services使用建立在HTTP/2上的P2P协议来管理分布式账本。提供最有效的哈希算法来维护world state的副本。采取可插拔的方式来根据具体需求来设置共识协议,比如PBFT,Raft,PoW和PoS等等。
2.3 Chaincode Services
Chaincode services 会提供一种安全且轻量级的沙盒运行模式,来在VP节点上执行chaincode逻辑。这里使用Container环境,里面的base镜像都是经过签名验证的安全镜像,包括OS层和开发chaincode的语言、runtime和SDK层,目前支持Go、Jave和Nodejs开发语言。
2.4 Events
在blockchain网络里,VP节点和chaincode会发送events来触发一些监听动作。比如chaincode是用户代码,它可以产生用户事件。
2.5 API 和 CLI
提供REST API,允许注册用户、查询blockchain和发送transactions。一些针对chaincode的API,可以用来执行transactions和查询交易结果。对于开发者,可以通过CLI快速去测试chaincode,或者去查询交易状态。
3. Topology
分布式网络的拓扑结构是非常值得研究的。在这个世界里散布着众多参与者,不同角色,不同利益体,各种各样的情况处理象征着分布式网络里的规则和法律,无规则不成方圆。在区块链网络里,有Membership service,有VP节点,NVP节点,一个或多个应用,它们形成一个chain,然后会有多个chain,每一个chain都有各自的安全要求和操作需求。
3.1 单个VP节点网络
最简单的网络就是只包含一个VP节点,因此就省去了共识部分。

3.2 多个VP节点网络
多个VP和NVP参与的网络才是有价值和实际意义的。NVP节点分担VP节点的工作压力,承担处理API请求和events的工作。

而对于VP节点,VP节点间会组成一个网状网络来传播信息。一个NVP节点如果被允许的话可以与邻近的一个VP节点相连。NVP节点是可以省略的,如果Application可以直接和VP节点通讯。
3.3 Multichain
还会存在一个网络里多条chain的情况,各个chain的意图不一样。
4. Protocol
fabric是用gRPC来做P2P通讯的,是一个双向流消息传递。使用 Protocol Buffer来序列化要传递的数据结构。
4.1 Message
message分四种:Discovery,Transaction,Synchronization 和 Consensus。每一种信息下还会包含更多的子信息,由payload指出。
payload是一个不透明的字节数组,它包含着一些对象,比如 Transaction 或者 Response。例如,如果 type 是 CHAIN_TRANSACTION,那么 payload 就是一个 Transaction的对象。
message Message {
   enum Type {
        UNDEFINED = 0;
        DISC_HELLO = 1;
        DISC_DISCONNECT = 2;
        DISC_GET_PEERS = 3;
        DISC_PEERS = 4;
        DISC_NEWMSG = 5;
        CHAIN_STATUS = 6;
        CHAIN_TRANSACTION = 7;
        CHAIN_GET_TRANSACTIONS = 8;
        CHAIN_QUERY = 9;
        SYNC_GET_BLOCKS = 11;
        SYNC_BLOCKS = 12;
        SYNC_BLOCK_ADDED = 13;
        SYNC_STATE_GET_SNAPSHOT = 14;
        SYNC_STATE_SNAPSHOT = 15;
        SYNC_STATE_GET_DELTAS = 16;
        SYNC_STATE_DELTAS = 17;
        RESPONSE = 20;
        CONSENSUS = 21;
    }
    Type type = 1;
    bytes payload = 2;
    google.protobuf.Timestamp timestamp = 3;
}
4.1.1 Discovery Messages
一个新启动的节点,如果CORE_PEER_DISCOVERY_ROOTNODE(ROOTNODE是指网络中其它任意一个节点的IP)被指定了,它就会开始运行discovery协议。而ROOTNODE就作为最一开始的发现节点,然后通过ROOTNODE节点进而发现全网中所有的节点。discovery协议信息是DISC_HELLO,它的payload是一个HelloMessage对象,同时包含信息发送节点的信息:
message HelloMessage {
  PeerEndpoint peerEndpoint = 1;
  uint64 blockNumber = 2;
}
message PeerEndpoint {
    PeerID ID = 1;
    string address = 2;
    enum Type {
      UNDEFINED = 0;
      VALIDATOR = 1;
      NON_VALIDATOR = 2;
    }
    Type type = 3;
    bytes pkiID = 4;
}
message PeerID {
    string name = 1;
}

如果一个节点接收到DISC_HELLO信息,发现里面的block height高于自己目前的block height,它会立即发送一个同步协议来与全网同步自己的状态(mark:但是在源码层面似乎并没有实现同步这个逻辑)。
在这个刚加入节点完成DISC_HELLO这轮消息传递后,接下来回周期性的发送DISC_GET_PEERS来发现其它加入网络中的节点。为了回复DISC_GET_PEERS,一个节点会发送DISC_PEERS。
4.1.2 Synchronization Messages
Synchronization 协议是接着上面所说的discovery协议开始的,当一个节点发现它的block的状态跟其它节点不一致时,就会触发同步。该节点会广播(broadcast)三种信息:SYNC_GET_BLOCKS , SYNC_STATE_GET_SNAPSHOT 或者 
SYNC_STATE_GET_DELTAS,同时对应接收到三种信息:SYNC_BLOCKS , SYNC_STATE_SNAPSHOT 或者 SYNC_STATE_DELTAS。
目前fabric嵌入的共识算法是pbft。
SYNC_GET_BLOCKS 会请求一系列连续的block,发送的数据结构中payload将是一个SyncBlockRange对象。
message SyncBlockRange {
    uint64 correlationId = 1;
    uint64 start = 2;
    uint64 end = 3;
}
接收的节点会回复SYNC_BLOCKS,它的payload是一个SyncBlocks对象:
message SyncBlocks {
    SyncBlockRange range = 1;
    repeated Block blocks = 2;
}
start和end表示起始和结束的block。例如start=3, end=5,代表了block 3,4,5;start=5, end=3,代表了block 5,4,3。
SYNC_STATE_GET_SNAPSHOT 会请求当前world state的一个snapshot,该信息的payload是一个SyncStateSnapshotRequest对象:
message SyncStateSnapshotRequest {
    uint64 correlationId = 1;
}
correlationId是发出请求的peer用来追踪对应的该信息的回复。收到该消息的peer会回复SYNC_STATE_SNAPSHOT,它的payload是一个SyncStateSnapshot对象:
message SyncStateSnapshot {
    bytes delta = 1;
    uint64 sequence = 2;
    uint64 blockNumber = 3;
    SyncStateSnapshotRequest request = 4;
}
SYNC_STATE_GET_DELTAS 默认Ledger会包含500个transition deltas。delta(j)表示block(i)和block(j)之间的状态转变(i = j -1)。
4.1.3 Consensus Messages
Consensus framework会将接收到的CHAIN_TRANSACTION转变成CONSENSUS,然后广播给所有的VP节点。
4.1.4 Transaction Messages
在fabric中的交易有三种:Deploy, Invoke 和 Query。Deploy将指定的chaincode安装到chain上,Invoke和Query会调用已经部署好的chaincode的函数。
4.2 Ledger
Ledger主要包含两块:blockchain和world state。blockchain就是一系列连在一起的block,用来记录历史交易。world state是一个key-value数据库,当交易执行后,chaincode会将state存在里面。
4.2.1 Blockchain
blockchain是指由一些block连成的list,每一个block都包含上一个block的hash。一个block还会包含一些交易列表以及执行所有这些交易后world state的一个hash。
message Block {
  version = 1;
  google.protobuf.Timestamp timestamp = 2;
  bytes transactionsHash = 3;
  bytes stateHash = 4;
  bytes previousBlockHash = 5;
  bytes consensusMetadata = 6;
  NonHashData nonHashData = 7;
}
message BlockTransactions {
  repeated Transaction transactions = 1;
}
那上一个block的hash是如何计算的呢:
  • 用 protocol buffer 序列化block的信息
  • 用 SHA3 SHAKE256 算法将序列化后的block信息哈希成一个512字节的输出
上面的数据结构中有一个 transactionHash, 它是transaction merkle tree的根节点(用默克尔树来描述这些交易)。
4.2.2 World State
一个peer的world state是所有部署的chaincodes的状态(state)的集合。一个chaincode的状态由键值对(key-value)的集合来描述。我们期望网络里的节点拥有一致的world state,所以会通过计算world state的 crypto-hash 来进行比较,但是将会消耗比较昂贵的算力,为此我们需要设计一个高效率的计算方法。比如引入Bucket-tree来实现world state的组织。
world state中的key的表示为{chaincodeID, ckey},我们可以这样来描述key, key = chaincodeID+nil+cKey。
world state的key-value会存到一个hash表中,这个hash表有预先定义好数量(numBuckets)的buckets组成。一个 hash function 会来定义哪个桶包含哪个key。这些buckets都将作为merkle-tree的叶子节点,编号最小的bucket作为这个merkle-tree最左面的叶子节点。倒数第二层的构建,从左开始每maxGroupingAtEachLevel(预先定义好数量)这么多的叶子节点为一组聚在一起,形成N组,每一组都会插入一个节点作为所包含叶子节点的父节点,这样就形成了倒数第二层。要注意的是,最末层的父节点(就是刚刚描述的插入的节点)可能会有少于maxGroupingAtEachLevel的孩子节点。按照这样的方法不断构建更高一层,直到根节点被构建出来。
举一个例子,{numBuckets=10009 and maxGroupingAtEachLevel=10},它形成的tree的每一次包含的节点数目如下:

4.3 Consensus Framework
consensus framework包含了三个package:consensus、controller和helper。
  • consensus.Communicator用来发送消息给其他的VP节点
  • consensus.Executor用于交易的启动、执行和回滚,还有preview、commit
  • controller指定被VP节点使用的consensus plugin
  • helper用来帮助consensus plugin与stack交互,例如维护message handler
目前有两个consensus plugin:pbft和noops。 
pbft是 微软论文PBFT共识算法的一个实现。 
noops 用于开发和测试,它没有共识机制,但是会处理所有consensus message,所以如果要开发自己的consensus plugin,从它开始吧。
4.3.1 Executor 接口
在源码中我们会经常看 executor 相关的代码,这个借口下的方法可以做到: 
开始批量交易、执行交易、提交与回滚交易
4.3.2 Ledger 接口
type Ledger interface {
    ReadOnlyLedger
    UtilLedger
    WritableLedger
}
ReadOnlyLedger接口用来查询 ledger 的本地备份,不做修改,函数有:
1、GetBlockchainSize() (uint64, error),这个函数在源码里常见,返回了ledger的长度
2、GetBlock(id uint64) (block *pb.Block, err error)
3、GetCurrentStateHash() (stateHash []byte, err error),返回 ledger 当前状态的hash
4.3.3 helper 包
helper包可以帮助VP节点建立与其他peer之间的通信和消息处理,helper.HandleMessage,这个函数会处理四种消息类型,
pb.Message_CONSENSUS 
pb.Message_CHAIN_TRANSACTION 
pb.Message_CHAIN_QUERY 
others
4.4 Chaincode
chaincode是一段应用级的代码,交易逻辑就在里面,fabric是用Docker容器来运行chaincode的。一旦chaincode容器被启动,它就会通过gRPC与启动这个chaincode的VP(Validating Peer)节点连接。
上面4.1提到的四种消息中有一种叫transaction message,包含Deploy, Invoke 和 Query。指的就是与chaincode相关的交易信息。chaincode需要实现三个函数,Init,Invoke 和 Query。Init是构造函数,它只在部署交易时被执行,Query函数用来读取状态。Invoke来进行交易的发生。
chaincode容器被部署时,会向对应的peer进行注册,注册之后,VP节点就会通知chaincode容器调用Init函数。其实peer跟chaincode容器之间是隔着一个shim层的,chaincode容器的shim层会接收来自peer的信息,根据信息调用chaincode相应的函数,如Invoke。
5. What we can do
5.1 Asset Management 资产管理
这是一个在fabric上实现的一个chaincode demo,用来模拟数字资产的管理。chaincode一共有四个函数:init(user), assign(asset, user), transfer(asset, user), query(asset)。
在chaincode被部署时,init(user)就会被自动调用。设想一下, 
1. Alice是这个chaincode的部署者; 
2. Alice想要将管理员这个角色分配给Bob; 
3. 之后Alice会获得Bob的一个TCert,我们叫这个证书BobCert; 
4. Alice构建一条deploy交易,并将交易的元数据设置到BobCert; 
5. Alice将这个交易提交到fabric网络中。
这样Bob就会被赋予管理员角色,这就是init函数要做的。接下来看一下assign:
1、Bob成为了chaincode的管理员
2、Bob想要将资产‘Picasso’分配给Charlie
3、Bob会获得Charlie的一个TCert,我们叫这个证书CharlieCert
4、Bob构建一个invoke交易,来调用assign这个函数,参数是 (‘Picasso’, Base64(DER(CharlieCert)))
5、Bob提交这个交易到fabric网络中
transfer函数: 
1. Charlie成为了资产‘Picasso’的拥有者了 
2. Charlie想要将‘Picasso’的所有权转交给Dave 
3. Charlie获得Dave的一个TCert,我们叫这个证书为DaveCert 
4. Charlie构建一个invoke交易,来调用transfer函数,参数为(‘Picasso’, Base64(DER(DaveCert))) 
5. Charlie提交交易到fabric网络中
query函数用来查询资产的拥有者。
完成整套逻辑,需要我们写的chaincode的代码只有三百行。像在transfer的实现中,我们需要首先判断这个发起人的身份,确保只有资产所有者才能转移自己的资产,然后全网公证资产的转移,任何一方都无法篡改和抵赖。
6. Defect
其实fabric还存在着诸多的缺陷,毕竟目前还是一个襁褓中的婴儿。 
例如memberserice与现有CA系统的集成,数据库部分也欠缺。 
其实这里有一个开放性的命题,大家不妨一起想想,可以在博客下面的评论中留言,或许会碰撞出一些火花:VP(validating peer)节点是网络的实质性参与者,可以提出交易,并就交易达成一致,然后执行交易,但在fabric中有一个节点叫NVP(not-validating peer)节点,它只与某一个VP节点相连,不能参与交易执行和一致性达成,只能为它所连的VP节点分担API处理部分和事件部分的压力,但可以去查询网络产生的ledger,有人说这样的设计可以有助于监管者加入进来,监管者只需查询生成的ledger,而不需参与交易,也有人说NVP节点引入是为了降低VP节点的计算压力,将一些外围的操作让NVP节点来做。
7. Contribution
Implement SYNC_BLOCK_ADDED handler
我的一个同事实现了SYNC_BLOCK_ADDED消息的handler,这样在noops共识模式下,当一个block被加到(mined/added)ledger时,NVP节点就可以处理这条消息了,并将最新加入的block存在它自己的ledger中。
SYNC_BLOCK_ADDED message 对应的callback是beforeBlockAdded(core/peer/handler.go),官方代码如下:
func (d *Handler) beforeBlockAdded(e *fsm.Event) {
    peerLogger.Debugf("Received message: %s", e.Event)
    msg, ok := e.Args[0].(*pb.Message)
    if !ok {
        e.Cancel(fmt.Errorf("Received unexpected message type"))
        return
    }
    // Add the block and any delta state to the ledger
    _ = msg
}
这里并没有去获取和处理block的信息,我们需要加入如下:
if ValidatorEnabled() {
     e.Cancel(fmt.Errorf("VP shouldn't receive SYNC_BLOCK_ADDED"))
     return
 }
    // Add the block and any delta state to the ledger
-   _ = msg
 blockState := &pb.BlockState{}
 err := proto.Unmarshal(msg.Payload, blockState)
 if err != nil {
     e.Cancel(fmt.Errorf("Error unmarshalling BlockState: %s", err))
     return
 }
 coord := d.Coordinator
 blockHeight := coord.GetBlockchainSize()
 if blockHeight <= 0 {
     e.Cancel(fmt.Errorf("No genesis block is made"))
     return
 }
 curBlock, err := coord.GetBlockByNumber(blockHeight -1)
 if err != nil {
     e.Cancel(fmt.Errorf("Error fetching block #%d, %s", blockHeight -1, err))
     return
 }
 hash, err := curBlock.GetHash()
 if err != nil {
     e.Cancel(fmt.Errorf("Error hashing latest block"))
     return
 }
 if bytes.Compare(hash, blockState.Block.PreviousBlockHash) != 0 {
     e.Cancel(fmt.Errorf("PreviousBlockHash of received block doesnot match hash of current block"))
     return
 }
 coord.PutBlock(blockHeight, blockState.Block)
 delta := &statemgmt.StateDelta{}
 if err := delta.Unmarshal(blockState.StateDelta); nil != err {
     e.Cancel(fmt.Errorf("Received a corrupt state delta"))
     return
 }
 coord.ApplyStateDelta(msg, delta)
 if coord.CommitStateDelta(msg) != nil {
     e.Cancel(fmt.Errorf("Played state forward, hashes matched, but failed to commit, invalidated state"))
     return
 }
 peerLogger.Infof("Blockchain height grows into %d", coord.GetBlockchainSize())
Enable statetransfer for HELLO message
我们还发现当一个NVP节点刚加入网络时,它会发送一个DISC_HELLO message,随后从其他节点接收一个包含那个节点的blockchain信息的DISC_HELLO message,不过官方代码并没有给出NVP依据这些返回信息同步自己状态的实现。NVP正在网络中实施自己的状态同步时,一个新的block被mine,NVP却不能把这个新的block加入到自己的chain中。所以目前就出现了一个棘手的情况:当新的NVP节点刚加入网络时,通过HELLO message获取其他节点的blockchain信息开始同步自己的状态,这肯定需要一定的时间来完成,但与此同时,网络里的交易还在继续,新的block会被不断的mined,虽然NVP能接收到SYNC_BLOCK_ADDED,并拥有处理它的handler,但是这时候却不能将新的block信息加入到自己的chain中,因为hash不匹配,毕竟NVP节点并没有完成一开始的同步。

IBM HyperLedger fabric 详解相关推荐

  1. 系统批量运维管理器Fabric详解

    系统批量运维管理器Fabric详解 Fabrici 是基于python现实的SSH命令行工具,简化了SSH的应用程序部署及系统管理任务,它提供了系统基础的操作组件,可以实现本地或远程shell命令,包 ...

  2. Python远程部署利器Fabric详解

    http://www.bjhee.com/fabric.html Fabric是一个Python的库,它提供了丰富的同SSH交互的接口,可以用来在本地或远程机器上自动化.流水化地执行Shell命令.因 ...

  3. GIZA++实现了IBM模型1~5 IBM Model 1详解

    IBM model是统计机器翻译中的经典翻译模型,也是基于词的统计机器翻译系统的基础.IBM翻译模型共有5个复杂度依次递增的统计翻译模型,IBM model1是其中最简单的模型,也是其他模型进行计算的 ...

  4. IBM Storwize V7000详解:IIS西安大会现场观察

    http://stor-age.zdnet.com.cn/stor-age/2010/1026/1922114.shtml 转载于:https://blog.51cto.com/quadro/4750 ...

  5. python镜像下载包_python包详解

    干货大礼包!21天带你轻松学Python(文末领取更多福利) 点击查看课程视频地址 本课程来自于千锋教育在阿里云开发者社区学习中心上线课程<Python入门2020最新大课>,主讲人姜伟. ...

  6. 区块链开源实现hyperledger fabric架构详解

    hyperledger fabric是区块链中联盟链的优秀实现,主要代码由IBM.Intel.各大银行等贡献,目前v1.1版的kafka共识方式可达到1000/s次的吞吐量.本文中我们依次讨论:区块链 ...

  7. Hyperledger Fabric之MSP详解

    HyperledgerFabric之MSP机制,功能及使用场景详解. 更多区块链技术与应用分类: 区块链应用    区块链开发 以太坊 | Fabric | BCOS | 密码技术 | 共识算法 | ...

  8. Hyperledger Fabric的test-network启动过程Bash源码详解

    前言 在基于Debian搭建Hyperledger Fabric 2.4开发环境及运行简单案例中,我们已经完成了Fabric 2.4的环境搭建及fabric-samples/test-network官 ...

  9. Hyperledger Fabric 通道配置文件和容器环境变量详解

    Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https ...

最新文章

  1. Pytorch中的向前计算(autograd)、梯度计算以及实现线性回归操作
  2. Expected a default value of type Tensor on parameter residual:
  3. 用力和应变片计算弹性模量_第4章 力学量传感器.pptx
  4. java set中元素是数组_将HashSet中的元素转换为Java中的数组
  5. CSDN下载频道2014年11月4日本-5日常维护公告
  6. python 解析器的常用options
  7. 全球企业KVM开源贡献榜发布,腾讯云、华为、阿里巴巴等入围
  8. ASP.NET抓取网页内容
  9. C++模板类与Java泛型类
  10. android crash没有日志_App测试之monkey(四)-调试参数及日志
  11. ExtJS 4无限制滚动条的Grid
  12. Android Studio禁止混淆JNI代码
  13. VC++字符串类型转换
  14. Windows下Cmake安装步骤详解(图文)
  15. Mybatis:高级知识1- resultMap实现一对一、一对多、多对多
  16. 告别360全家桶,安利一波电脑必备软件
  17. Product Requirement Document
  18. Pycharm放大缩小,快捷键控制
  19. can口通信的软件测试,CAN网络一致性测试和UDS测试设备
  20. OpenPlanner变道遇到的问题及解决

热门文章

  1. Python学习笔记:高级特性
  2. 现代谱估计:Blackman-Tukey 相关图
  3. Linux服务器安装NodeJs简易方法
  4. 【Python】判断列表中是否存在一个数
  5. 科大星云诗社动态20210911
  6. 我的独白2017-12-20
  7. [MATLAB学习笔记]peaks函数1013(2)
  8. 深度学习 500 问!一份火爆 GitHub 的面试手册
  9. 火爆 GitHub 的 16 张机器学习速查表,值得收藏!
  10. python做项目看板_三、使用python数据仓库实现可视化看板