Hyperledger Fabric链码之三

在《Hyperledger Fabric链码之一》和《Hyperledger Fabric链码之二》中我们介绍了链码的定义,并通过dev网络测试了测试了自己编写的链码程序。
本文中我们站在区块链网络管理员的角度来阐述链码,我们集中在链码的声明周期管理,如链码的打包,安装,初始话以及升级。

链码声明周期


超级帐本Fabric提供的接口使得多种类型的节点能够进行交互 — 节点,排序节点以及成员管理服务 — 同时使得在背书节点上可以进行打包、安装、初始化和升级链码。
Hyperledger Fabric的SDKs对API接口进行了抽象以便于应用开发,用来管理链码的生命周期。此外Hyperledger Fabric的API可以通过CLI的方式直接访问,本文中我们使用了这种方式。
我们为链码的生命周期管理提供了4个命令 package, install, instantiate, 以及 upgrade。 以后版本中,我们计划添加stopstart交易来关闭和启动链码而不需要真正的卸载它。链码被成功安装和初始化后,链码会处于激活状态(running)并通过invoke来处理交易。之后链码也可以被升级。

打包


链码的打包包含3个部分:

  • 链码,被定义为ChaincodeDeploymentSpec或者CDS。 CDS根据代码以及名字和版本来定义链码包。
  • 一个可选的初始化策略,语法构成上与背书endorsement-policies相同
  • 一组签名,来自拥有该链码的实体
    签名具有下面的目的:
  • 建立链码归属权
  • 验证链码包的内容
  • 防止链码包篡改
    在一个channel中链码初始化交易的创建者会经过链码的初始化策略的验证。

创建链码包


有两种方式来打包链码。一种方式是:当一个链码有多个拥有者,因此需要链码包被多个身份进行签名。首先需要创建一个签名的链码包SignedCDS,然后顺序传送给其他拥有者进行签名。
更简单的方式是: 当部署一个仅仅由一个节点签名的SignedCDS时执行install交易
我们首先解决最复杂的情况。但是,如果你不需要担心多个拥有者的情况,你可以直接跳到:ref:安装章节。
使用下面的命令创建链码包

peer chaincode package -n mycc -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -v 0 -s -S -i "AND('OrgA.admin')" ccpack.out

其中, -s选项创建了一个可以被多个拥有者签名的链码包,而不是简单的一个CDS。 当指定了-s, 如果需要其他拥有者签名的话也必须指定-S选项。否则,除了CDS以外,上述命令会创建一个仅包含初始化策略的SignedCDS
-S选项用来指导链码包的签名过程,使用core.yaml文件中localMspid指定的MSP的值。 该选项是可选的。然而如果链码包创建没有使用签名,也就不能被别的拥有者使用signpackage命令来进行签名。
选项-i允许指定链码的初始化策略。初始化策略与背书策略具有相同的格式,用来指定什么身份可以来初始化链码。 在上面的例子中,仅仅OrgA的管理员能够初始化该链码。如果未提供初始化策略,会使用默认值,仅允许节点MSP的管理员身份来初始化链码。

链码包签名


被签名的链码包被创建后可以交给其他拥有者进行检查和签名。 工作流支持线下的链码包签名。
ChaincodeDeploymentSpec 被一组拥有者进行签名得到 SignedChaincodeDeploymentSpec或者SignedCDS. SignedCDS包含3个元素:

  1. CDS包含源码,名字以及链码的版本。
  2. 链码的初始化策略,描述为背书策略
  3. 链码拥有者列表,通过Endorsement来定义。

注意::背书策略是线下确定的,用来提供合适的MSP规则当链码在一些通道初始话的时候。如果未指定初始化策略,那么缺省策略是通道的任何MSP管理员。
每个拥有者背书ChaincodeDeploymentSpec, 然后结合自己的身份(比如证书)后进行签名。
链码拥有者可以使用如下的命令对之前签名的链码包进行签名

 peer chaincode signpackage ccpack.out signedccpack.out

其中, ccpack.out和`signedccpack.out``分别是命令的输入和输出。 后者包含一个额外的本地MSP签名。

安装


install交易将链码源码打包为一个指定的格式ChaincodeDeploymentSpec (或者CDS),并安装到运行链码的节点上。
注意:链码必须安装在同一个通道的所有背书节点上。
install API输入参数仅是ChaincodeDeploymentSpec时,会使用默认的初始化策略并包含一个空的拥有者列表。
注意: 链码应该仅安装在拥有者的背书节点上以保护链码逻辑的机密性,防止网络中其他成员的访问。那些没有链码的成员,不能作为链码交易的背书人;也就是说,他们不能执行链码。然而,他们仍然可以验证和提交交易。

为了安装链码,需要向lifecycle system chaincode (LSCC), 在System Chaincode章节描述,发送一个SignedProposal。例如,安装sacc链码。
使用CLI的方式,安装命令如下:

 peer chaincode install -n asset_mgmt -v 1.0 -p sacc

CLI内部会为sacc创建SignedChaincodeDeploymentSpec 并且发送给本地的peer,节点调用LSCC的install方法。-p参数指定了链码的路径,必须在用户GOPATH下,例如$GOPATH/src/sacc。 CLI命令的完整描述参考CLI章节。

值得注意的是为了在节点上安装链码,SignedProposal的签名必须来自peer本地MSP管理员。

初始化


instantiate交易调用lifecycle System Chaincode (LSCC)`创建并初始化通道中的链码。这是一个链码-通道绑定的过程:链码可以绑定到多个通道中,并独立运行在每一个通道中。也就是说,不管链码被安装并初始化到多少个通道中,通道状态都是隔离的。

instantiate交易的创建者必须在SignedCDS中指定初始化策略,同时必须在通道中具有可写权限,在通道创建时配置。这些对于防止恶意实体部署链码并欺骗成员执行链码具有重要作用。
例如, 默认的初始化策略是通道MSP的任意管理员,因此链码初始化交易的创建者必须是一个通道管理员。当交易提议发送到背书节点,会使用背书策略验证创建者的签名。在交易提交到账本前的验证阶段会再一次进行验证。
初始化交易也会为通道中链码设置背书策略。背书策略描述的是需要多少个对交易结果的背书,交易才能被通道成员承认。
比如,使用CLI的方式来初始化sacc链码,并用状态john0来进行初始化,命令描述如下:

 peer chaincode instantiate -n sacc -v 1.0 -c '{"Args":["john","0"]}' -P "OR ('Org1.member','Org2.member')"

注意:上面命令中背书策略(使用波兰表示法)表示需要Org1或者Org2中的任意成员对所有sacc的所有交易进行背书。即,Org1或Org2必须对执行Invoke的结果进行签名,交易才是有效交易。

交易成功初始化后,链码进入了激活状态,准备处理接收到的类型为ENDORSER_TRANSACTION的交易提议。 交易在背书节点上进行并行处理。

升级


链码可以通过改变版本号的方式来进行升级,版本号是SignedCDS的一部分。其他组成有拥有者、背书策略是可选的。然而,链码名必须是相同的,否则会被认为是完全不同的链码。
升级前,新版本的链码必须首先安装到背书节点上。升级交易与初始化交易类似,会将新版本的交易绑定到通道中。其他绑定旧版本的通道仍然运行旧版本。也就是说upgrade交易一次只影响一个通道,即交易提交到的通道。

注意:既然链码多个版本可以同时运行,那么升级过程不会自动移除旧版本,因此用户需要自己进行处理。

instantiate细微的不同是:upgrade交易会用当前链码的初始化策略进行检查,而不是新的策略。这样用来保证只有当前初始化策略指定的成员能够来升级链码。
注意:在升级阶段,链码Init函数会被调用来升级数据或者重新初始化,因此当升级链码的时候需要格外小心防止重新设置状态。

停止和启动


stopstart交易现在还没有实现。然而,你可以通过手动删除每个背书节点上的链码容器和SignedCDS包来停止一个链码。注:你需要登入peer节点容器来删除CDS。我们提供一个工具脚本来执行这个操作。

 docker rm -f <container id>
rm /var/hyperledger/production/chaincodes/<ccname>:<ccversion>

链码的停止将有助于在可控方式下进行升级,在链码升级前,将通道中所有节点上的链码进行停止。

CLI


注:我们需要平台相关的二进制可执行程序peer. 现在,你可以简单的在运行的docker容器中使用此命令。
fabric-peer Docker容器中执行命令,如下

 docker run -it hyperledger/fabric-peer bash
 # peer chaincode --help

执行上面的命令会显示:

Usage:
    peer chaincode [command]

  Available Commands:
    install     Package the specified chaincode into a deployment spec and save it on the peer's path.
    instantiate Deploy the specified chaincode to the network.
    invoke      Invoke the specified chaincode.
    package     Package the specified chaincode into a deployment spec.
    query       Query using the specified chaincode.
    signpackage Sign the specified chaincode package
    upgrade     Upgrade chaincode.

  Flags:
        --cafile string     Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint
    -C, --chainID string    The chain on which this command should be executed (default "testchainid")
    -c, --ctor string       Constructor message for the chaincode in JSON format (default "{}")
    -E, --escc string       The name of the endorsement system chaincode to be used for this chaincode
    -l, --lang string       Language the chaincode is written in (default "golang")
    -n, --name string       Name of the chaincode
    -o, --orderer string    Ordering service endpoint
    -p, --path string       Path to chaincode
    -P, --policy string     The endorsement policy associated to this chaincode
    -t, --tid string        Name of a custom ID generation algorithm (hashing and decoding) e.g. sha256base64
        --tls               Use TLS when communicating with the orderer endpoint
    -u, --username string   Username for chaincode operations when security is enabled
    -v, --version string    Version of the chaincode specified in install/instantiate/upgrade commands
    -V, --vscc string       The name of the verification system chaincode to be used for this chaincode

  Global Flags:
        --logging-level string       Default logging level and overrides, see core.yaml for full syntax
        --test.coverprofile string   Done (default "coverage.cov")

  Use "peer chaincode [command] --help" for more information about a command.

在脚本中运行,peer命令在执行失败的时候会返回一个非零的错误码。
链码命令使用示例:

    peer chaincode install -n mycc -v 0 -p path/to/my/chaincode/v0
    peer chaincode instantiate -n mycc -v 0 -c '{"Args":["a", "b", "c"]} -C mychannel
    peer chaincode install -n mycc -v 1 -p path/to/my/chaincode/v1
    peer chaincode upgrade -n mycc -v 1 -c '{"Args":["d", "e", "f"]} -C mychannel
    peer chaincode query -C mychannel -n mycc -c '{"Args":["query","e"]}'
    peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'

系统链码


系统链码与链码具有相同的编程模型,不同的是,系统链码运行在peer进程中,而不是隔离的docker容器中。因此,系统链码被编译进了peer可执行程序中,生命周期与前面的不同。比如,系统链码没有install,instantiateupgrade

系统链码的作用是降低节点和链码之间的gRPC通信开销,折中了管理的灵活性。例如,系统链码只能使用peer二进制程序来升级。也必须使用固定的参数来注册,不具有背书策略或者背书策略函数。

系统链码在Fabric中用来实现一些系统行为,可以进行合理的替换和修改。
当前提供的系统链码列表:

  1. LSCC生命周期系统链码用来处理声明周期请求
  2. CSCC配置系统链码在节点端用来处理通道配置
  3. QSCC请求系统链码 提供了账本请求的APIs,例如获取区块和交易。
  4. ESCC背书系统链码通过对交易提议响应进行签名来处理背书
  5. VSCC验证系统链码处理交易验证,包括检查背书策略和多版本并发控制。

在对系统链码进行修改和替换时需要格外的小心,尤其是LSCC,ESCC和VSCC,因为他们管理了整个交易的执行。值得注意的是在将交易提交到账本前VSCC来验证一个区块的有效性,通道中所有节点执行相同的验证以防止账本分叉(不确定)是至关重要的。因此需要格外关注VSCC的修改和替换。

------------------------------------------------------------------------------------完美的终结线--------------------------------------------------------------------------------------

原文地址:https://www.cnblogs.com/informatics/p/8073919.html