教程 - Chaincode for Operators
1. 什么是链码
链码 (chaincode) 是用 Go,node.js 或 Java 编写的程序,可实现规定的接口。 链码在与背书对端节点进程隔离的安全 Docker 容器中运行。 链码通过应用程序提交的交易初始化和管理帐本状态。
链码通常处理网络成员同意的业务逻辑,因此它类似于智能合约。可以调用链码来更新或查询提案交易中的帐本。在获得适当许可的情况下,一个链码可以在同一通道或不同通道中调用另一个链码以访问其状态。请注意,如果被调用链码与调用链码位于不同的通道,则仅允许读取查询。也就是说,在另一个通道上的被调用链码仅仅是一个查询,它不参与后续提交阶段的状态验证检查。
在以下各节中,我们将通过区块链网络操作者 Noah 的视角探索链码。为了 Noah 的兴趣,我们将专注于链码生命周期操作;根据链码在区块链网络中的操作生命周期而对链码进行打包,安装,实例化和升级的过程。
2. 链码生命周期
Hyperledger Fabric API 支持与区块链网络中的各个节点 (对端节点,交易排序器和 MSP) 进行交互,并且还允许在背书的对端节点上打包,安装,实例化和升级链码。尽管 Hyperledger Fabric 语言特定的 SDK 可用于管理链码的生命周期,但它抽象化了 Hyperledger Fabric API 的细节以促进应用程序开发。此外,可以通过 CLI 直接访问 Hyperledger Fabric API,我们将在本文档中使用它。
我们提供了四个命令来管理链码的生命周期:打包 (package
),安装 (install
),实例化 (instantiate
) 和升级 (upgrade
)。在将来的版本中,我们正在考虑添加停止 (stop
) 和启动 (start
) 交易以禁用和重新启用链码,而不必实际将其卸载。成功安装并实例化一个链码后,该链码处于活动状态 (正在运行),并且可以通过调用 (invoke
) 交易处理交易。安装链码后,可以随时对其进行升级。
3. 打包
链码包包括 3 个部分:
- 链码,由
ChaincodeDeploymentSpec
或 CDS 定义。CDS 根据代码和其他属性,例如名称和版本。 - 可选的实例化策略,可以用与背书使用的策略相同的语法进行描述,并在 背书策略 中进行描述,以及
- 拥有链码的实体的一组签名。
签名用于以下目的:
- 建立链码的所有权,
- 允许验证包的内容,以及
- 以便检测包是否被篡改。
针对链码的实例化策略验证通道上链码的实例化交易的创建者。
3.1 创建包
打包链码有两种方法。一种用于你希望拥有一个链码的多个所有者,因此需要让链码包由多个身份签名的情况。此工作流程要求我们首先创建一个已签名的链码包 (一个 SignedCDS),然后将其串行传递给其他每个所有者进行签名。
更简单的工作流程适用于部署 SignedCDS 的情况,该 SignedCDS 仅具有发布安装交易 (install
) 的节点的身份的签名。
我们将首先处理更复杂的情况。但是,如果你现在不必担心多个所有者,则可以跳到下面安装链码部分。
要创建签名的链码包,请使用以下命令:
$ peer chaincode package -n mycc -p github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd -v 0 -s -S -i "AND('OrgA.admin')" ccpack.out
-s
选项创建一个可以由多个所有者签名的程序包,而不是简单地创建原始 CDS。指定 -s
时,如果其他所有者需要签名,则还必须指定 -S
选项。否则,该过程将创建一个 SignedCDS,该 SignedCDS 除包含 CDS 外,还包含实例化策略。
-S
选项指示该过程使用由 core.yaml
中 localMspid
属性的值标识的 MSP 对软件包进行签名。
-S
选项是可选的。但是,如果创建的软件包没有签名,则任何其他所有者都不能使用 signpackage
命令对其进行签名。
可选的 -i
选项允许你为链码指定实例化策略。实例化策略与背书策略具有相同的格式,并指定可以标识链码的身份。在上面的示例中,仅允许 OrgA 的管理员实例化链码。如果未提供任何策略,则使用默认策略,该默认策略仅允许对端节点 MSP 的管理员身份实例化链码。
3.2 包签名
创建时签名的链码包可以移交给其他所有者进行检查和签名。该工作流支持链码包的带外签名。
可以由集体所有者对 ChaincodeDeploymentSpec 进行签名,以创建一个 SignedChaincodeDeploymentSpec (或 SignedCDS)。SignedCDS 包含 3 个元素:
- CDS 包含源代码,名称和链码的版本。
- 链码的实例化策略,表示为背书策略。
- 通过 背书 定义的链码所有者列表。
备注
请注意,在某些通道上实例化链码时,会为带外确定此背书策略以提供适当的 MSP 主体。如果未指定实例化策略,则默认策略是该通道的任何 MSP 管理员。
每个拥有者通过将 ChaincodeDeploymentSpec 与该拥有者的身份 (例如证书) 结合并签名合并后的结果来背书 ChaincodeDeploymentSpec。
链码所有者可以使用以下命令对先前创建的已签名软件包进行签名:
$ peer chaincode signpackage ccpack.out signedccpack.out
其中 ccpack.out 和 signedccpack.out 分别是输入和输出包。 signedccpack.out 包含使用本地 MSP 签名的程序包的其他签名。
3.3 安装链码
安装 (install
) 交易将链码的源代码打包为规定的格式,称为 ChaincodeDeploymentSpec (或 CDS),并将其安装在将运行该链码的对端节点上。
备注
你必须在将运行链码的通道的每个背书对端节点上安装链码。
当只给安装 (install
) API 一个 ChaincodeDeploymentSpec 时,它将默认实例化策略并包括一个空的所有者列表。
备注
链码只能安装在链码所属成员的背书对端节点上,以保护链码逻辑免受网络上其他成员的机密性。那些没有链码的成员不能成为链码交易的背书人;也就是说,他们无法执行链码。但是,他们仍然可以验证交易并将交易提交到帐本。
要安装链码,请将 SignedProposal 发送到 系统链码 部分中描述的生命周期系统链码 (Lifecycle System Chaincode, LSCC)。例如,要使用 CLI 安装 简单资产链码 部分中介绍的 sacc 示例链码,该命令将如下所示:
$ peer chaincode install -n asset_mgmt -v 1.0 -p sacc
CLI 在内部为 sacc 创建 SignedChaincodeDeploymentSpec,并将其发送到本地对端节点,后者在 LSCC 上调用 Install
方法。 -p
选项的参数指定了链码的路径,该链码必须位于用户的 GOPATH
的源码树中,例如 $GOPATH/src/sacc
。注意,如果对 Node 链码或 Java 链码使用 -l node
或 -l java
,则将 -p
与链码位置的绝对路径一起使用。有关命令选项的完整说明,请参见 命令参考。
请注意,要在对等方上安装,SignedProposal的签名必须来自对等方的本地MSP管理员之一。
3.4 实例化
实例化 (instantiate
) 交易调用生命周期系统链码 (lifecycle System Chaincode, LSCC) 来创建和初始化通道上的链码。这是一个链码通道绑定过程:链码可以绑定到任意数量的通道,并且可以分别且独立地在每个通道上运行。换句话说,不管可能安装和实例化链码的其他通道数量是多少,状态都与提交交易的通道保持隔离。
实例化 (instantiate
) 交易的创建者必须满足 SignedCDS 中包含的链码的实例化策略,并且还必须是通道上的编写者 (writer),该通道被配置为通道创建的一部分。这对于通道的安全性至关重要,它可以防止流氓实体部署链码或欺骗成员以在未绑定的通道上执行链码。
例如,回想一下,默认实例化策略是任何通道 MSP 管理员,因此链码实例化交易的创建者必须是通道管理员的成员。交易提案到达背书人时,它会根据实例化策略验证创建者的签名。在将其提交到帐本之前,在交易验证期间再次进行此操作。
实例化交易还为通道上的该链码设置了背书策略。背书策略描述了交易结果要被通道成员接受的证明要求。
例如,使用 CLI 实例化 sacc 链码并使用 john 和 0 初始化状态,该命令将如下所示:
$ peer chaincode instantiate -n sacc -v 1.0 -c '{"Args":["john","0"]}' -C mychannel -P "AND ('Org1.member','Org2.member')"
备注
请注意背书策略 (CLI 使用波兰语表示法),该策略要求 Org1 和 Org2 的成员对所有要进行 sacc 的交易都背书。也就是说,Org1 和 Org2 都必须对在 sacc 上执行 Invoke 的结果进行签名,以使交易有效。
在成功实例化之后,链码进入通道的活动状态,并准备处理任何类型为ENDORSER_TRANSACTION 的交易提案。交易在到达背书对端节点时被同时处理。
3.5 更新
链码可以随时通过更改其版本进行升级,这是 SignedCDS 的一部分。其他部分,例如所有者和实例化策略是可选的。但是,链码名称必须相同。否则,它将被视为完全不同的链码。
升级之前,必须在所需的背书者上安装新版本的链码。升级是类似于实例化交易的事务,该交易将链码的新版本绑定到通道。绑定到链码旧版本的其他通道仍然可以与旧版本一起运行。换句话说,升级 (upgrade
) 交易一次只影响一个通道,即交易提交到的通道。
备注
请注意,由于链码的多个版本可能同时处于活动状态,因此升级过程不会自动删除旧版本,因此用户必须暂时进行管理。
实例化 (instantiate
) 交易有一个微妙的区别:升级 (upgrade
) 交易是根据当前的链码实例化策略而不是新策略 (如果指定) 检查的。这是为了确保只有在当前实例化策略中指定的现有成员才可以升级链码。
备注
请注意,在升级过程中,将调用链码
Init
函数来执行与数据相关的任何更新或将其重新初始化,因此在升级链码时必须注意避免重置状态。
3.6 停止和启动
注意,停止 (stop
) 和启动 (start
) 生命周期交易尚未实现。但是,你可以通过从每个背书人中删除链码容器和 SignedCDS 包来手动停止链码。这是通过删除运行背书对端节点的每个主机或虚拟机上的链码容器,然后从每个背书对端节点中删除 SignedCDS 来完成的:
备注
TODO - 要从对端节点删除 CDS,你需要首先输入对端节点的容器。我们确实需要提供一个可以执行此操作的实用程序脚本。
$ sudo docker rm -f
$ rm /var/hyperledger/production/chaincodes/:
在以受控方式进行升级的工作流程中,停止将很有用,因为在发布升级之前,链码可以在所有对端节点的通道上停止。
4. 系统链码
系统链码具有相同的编程模型,只是它在对端节点进程中运行,而不是像普通链码那样在隔离的容器中运行。因此,系统链码内置于对端节点可执行文件中,并且没有遵循上述相同的生命周期。特别是,安装,实例化和升级不适用于系统链码。
系统链码的目的是缩短对端节点和链码之间的 gRPC 通信成本,并权衡管理的灵活性。例如,系统链码只能与对端节点二进制文件一起升级。它还必须使用 一组内置的固定参数 进行注册,并且不具有背书策略或背书策略功能。
Hyperledger Fabric 中使用系统链码来实现许多系统行为,以便系统集成商可以适当地替换或修改它们。
当前系统链代码列表:
- LSCC 生命周期系统链码 (Lifecycle system chaincode) 处理上述生命周期请求。
- CSCC 配置系统链码 (Configuration system chaincode) 在对端节点处理通道配置。
- QSCC 查询系统链码 (Query system chaincode) 提供帐本查询 API,例如获取区块和交易。
如 可插拔交易背书和验证 文档所述,用于背书和验证的先前系统链码已由可插入背书和验证功能代替。
修改或替换这些系统链码,尤其是 LSCC 时,必须格外小心。
Reference
- Docs » Tutorials » Chaincode for Operators, https://hyperledger-fabric.readthedocs.io/en/release-1.4/chaincode4noah.html
- https://golang.org/
- https://nodejs.org/en/
- https://java.com/en/
- Docs » Operations Guides » Endorsement policies, https://hyperledger-fabric.readthedocs.io/en/release-1.4/endorsement-policies.html
- Docs » Tutorials » Chaincode for Developers, https://hyperledger-fabric.readthedocs.io/en/release-1.4/chaincode4ade.html#simple-asset-chaincode
- Docs » Commands Reference, https://hyperledger-fabric.readthedocs.io/en/release-1.4/command_ref.html
- Docs » Operations Guides » Pluggable transaction endorsement and validation, https://hyperledger-fabric.readthedocs.io/en/release-1.4/pluggable_endorsement_and_validation.html
项目源代码
项目源代码会逐步上传到 Github,地址为 https://github.com/windstamp。
Contributor
- Windstamp, https://github.com/windstamp