Fabric 2.0 新的链码生命周期

作者 tinywell 日期 2019-12-04
Fabric 2.0 新的链码生命周期

Fabric 2.0 版本老早就发布了 Alpha 版本,但一直都没有发布正式版本。我对于新事物通常保有好奇,但是却鲜有率先尝试,对于 “Alpha” 自然敬而远之,一直没有细看(也许只是因为懒)。

Alpha中介绍了 2.0 两块主要的变化:FabToken 和新的链码生命周期管理 (chaincode lifecycle)。前不久 FabToken 据说是因为觉得设计的不够好,代码整个回滚掉,结束了这个短暂的尝试,说是要回去重新好好设计后再来。而对于链码生命周期管理的功能,在这周的工作组例会上传来消息,说是 Alpha 版上相关功能已经基本稳定,正式版发布这一块也基本不会有太大变化。正好得空,于是细细看了看期许已久的新版链码生命周期管理。

功能介绍

2.0 Alpha 中对链码的安装和使用采了用一套新的流程,相比于现有流程变得更加去中心化。新的流程中,一个链码使用之前,是需要相关的多个组织能够在这个链码的相关参数上达成一致才行,比如背书策略等等。

相比于 1.x 版本的链码管理,新版本的功能改进的方面很多:

  • 链码的相关参数需要多个组织达成一致: 在 1.x 版本中,一个组织就能决定链码的参数(比如背书策略),通道内其他组织毫无参与感。新的链码生命周期会更加灵活,它既支持原有的这种中心化的信任模型,同时还支持去中心化的方式:在链码生效前需要通道内一定数量的组织对链码参数达成共识。
  • 更安全的链码升级过程: 在原有链码生命周期中,一个组织就能完成链码的升级交易,不管其他组织是否有安装升级的链码是否想升级。在新的模型下,链码升级需要得到足够数量的组织同意之后才能升级。
  • 更简单的背书策略升级: 原有版本要想升级背书策略,只能进行一次完整的链码升级过程,这意味着要重新打包链码、安装链码、升级链码。新的链码生命周期中可以避免这些冗余的步骤,只对背书策略进行升级,甚至还可以使用一个默认的”大多数“背书策略,这个策略还能随着组织的增减自动更新。
  • 便于检查的链码包: 新的链码生命周期可以将链码打包成更易阅读的 tar 包。这样查看链码信息或者组织间协调安装事宜会更方便。
  • 使用一个链码包在通道内启动多个链码实例: 在原来的版本中,标识一个通道内的链码实例所用的名称和版本号两个要素是在安装链码时指定的。而在新版本中,你可以利用一个安装好的包使用不同的名字在一个通道或多个通道内多次部署。

看完这些,我只想说:”哇!哦哦哦!awsome!“

基本每个都是痛点。尤其背书策略的升级,这是目前链码管理最为人诟病的地方。背书策略在链码实例化时指定,一旦通道成员发生变化就必须更新背书策略,而更新背书策略又需要所有成员进行链码升级。现在一个默认的背书策略就可以解决所有问题,有特殊背书需求,也可以仅升级背书策略就行。而去中心化的链码部署/升级过程也更加的”区块链“了,不再是一言堂。

如何使用

在新的链码生命周期中,安装和定义一个链码需要四个步骤:

  1. 打包链码: 可以一个组织打包,也可以多个组织各自打包;
  2. 安装链码: 在需要参与背书或查询账本的组织的 peer 节点上安装这个链码;
  3. 审批链码定义: 需要使用这个链码的组织需要对这个链码的定义进行审批,只有链码定义得到足够数量的组织审批同意后才能被启用,满足策略由 LifecycleEndorsement 定义,默认为”大多数“( majority) ;
  4. 提交链码定义: 链码定义被足够数量的组织审批同意后,由一个组织将这个链码定义提交到通道上:先从同意的组织哪里收集满足策略的背书,然后提交交易以确认这个链码定义。

打包链码

通过 peer 可执行文件或者 sdk 或者其他工具将链码源码打包成一个 tar 包,满足以下要求:

  • 文件扩展名为 .tar.gz

  • tar 包中包含两部分:一个名为 “Chaincode-Package-Metadata.json” 元数据文件以及另一个包含链码源码的 tar 包

  • “Chaincode-Package-Metadata.json” 文件中包含链码语言类型(Type)、链码路径(Path)以及标识链码的标签(Label)三个要素,示例如下:

    "Path":"github.com/chaincode/fabcar/go","Type":"golang","Label":"fabcarv1"}

peer cli 的命令如下:

1
2
3
4
5
Usage:
peer lifecycle chaincode package [outputfile] [flags]

# 将链码打包成 "mycc.tar.gz",指定路径、语言和标签名称
peer lifecycle chaincode package mycc.tar.gz --path github.com/hyperledger/fabric-samples/chaincode/abstore/go/ --lang golang --label myccv1

安装链码

使用 Admin 用户为组织内需要为这个链码背书或账本查询的每一个 peer 节点安装打包好的链码。安装成功后会返回一个链码识别号,标识号由链码标签和 hash 值组成。这个识别号后续也可以通过查询已安装链码的方式得到。

peer cli 命令如下:

1
2
3
4
5
6
7
8
Usage:
peer lifecycle chaincode install [flags]

# 将链码包 "mycc.tar.gz" 安装到目标节点 "peer0.org1.example.com:7051"
peer lifecycle chaincode install mycc.tar.gz --peerAddresses peer0.org1.example.com:7051

2019-03-13 13:48:53.691 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nEmycc:ebd89878c2bbccf62f68c36072626359376aa83c36435a058d453e8dbfd894cc" >
2019-03-13 13:48:53.691 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: mycc:a7ca45a7cc85f1d89c905b775920361ed089a364e12a9b6d55ba75c965ddd6a9

审批链码定义

链码受链码定义约束,审批链码定义就是对这些定义的要素进行确认,链码定义包含以下要素:

  • Name: 调用链码时使用的名称;
  • Version: 链码版本号,链码有变化则更新版本号;
  • Sequence: 序号,一个链码每被定义一次序号增加一;
  • Endorsement Policy: 背书策略;
  • Collection Configuration: 私有数据集的配置文件路径;
  • Initialization: 是否启动执行链码初始化函数;
  • ESCC/VSCC Plugins: 背书及验证系统链码插件;

除此之外,链码定义还包括一个链码识别号(既上一步安装链码得到的),但是这个不是必须的。如果一个组织还没有安装链码,它可以不带链码识别号对这个链码定义进行审批,另外不同许这个链码识别号不一样,这也就是说,不同组织可以安装不一样的链码,但是可以作为对等的链码来使用,只要保证他们的读写集一致。

每一个需要用到这个链码的组织都需要进行链码定义的审批,审批动作由 Admin 身份执行,同组织内只需要执行一次,其他所有 peer 节点都可以使用。如果两个组织发送的链码定义不一致,则这个链码定义不会生效。

peer cli 命令如下:

1
2
3
4
5
6
7
8
9
Usage:
peer lifecycle chaincode approveformyorg [flags]

export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --tls --cafile $ORDERER_CA --channelID mychannel --name mycc --version 1.0 --init-required --package-id myccv1:a7ca45a7cc85f1d89c905b775920361ed089a364e12a9b6d55ba75c965ddd6a9 --sequence 1 --signature-policy "AND ('Org1MSP.peer','Org2MSP.peer')"

2019-03-18 16:04:09.046 UTC [cli.lifecycle.chaincode] InitCmdFactory -> INFO 001 Retrieved channel (mychannel) orderer endpoint: orderer.example.com:7050
2019-03-18 16:04:11.253 UTC [chaincodeCmd] ClientWait -> INFO 002 txid [efba188ca77889cc1c328fc98e0bb12d3ad0abcda3f84da3714471c7c1e6c13c] committed with status (VALID) at peer0.org1.example.com:7051

提交链码定义

当一个链码定义收集到足够数量的组织的审批同意,则可以由其中任一组织发起提交交易,使得链码定义生效。提交过程由两步构成,第一步到相关组织的背书节点上执行背书收集背书签名(这个过程应该是通过系统链码帮助完成的),第二步将链码定义和背书发到排序服务,提交到通道上,使其生效。

一个链码定义是否已有足够数量的同意,可以通过checkcommitreadiness 命令查询。

peer cli 命令如下:

1
2
3
4
5
6
7
Usage:
peer lifecycle chaincode commit [flags]

peer lifecycle chaincode commit -o orderer.example.com:7050 --channelID mychannel --name mycc --version 1.0 --sequence 1 --init-required --tls --cafile $ORDERER_CA --peerAddresses peer0.org1.example.com:7051 --peerAddresses peer0.org2.example.com:9051

2019-03-18 16:14:27.258 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [b6f657a14689b27d69a50f39590b3949906b5a426f9d7f0dcee557f775e17882] committed with status (VALID) at peer0.org2.example.com:9051
2019-03-18 16:14:27.321 UTC [chaincodeCmd] ClientWait -> INFO 002 txid [b6f657a14689b27d69a50f39590b3949906b5a426f9d7f0dcee557f775e17882] committed with status (VALID) at peer0.org1.example.com:7051

当链码定义提交生效后,第一次调用链码时,会自动启动链码容器。这时候终于可以愉快的使用你的链码啦。

Reference