Hyperledger Fabric 管理链码 peer lifecycle chaincode 指令使用
链上代码(Chaincode)简称链码,包括系统链码和用户链码。系统链码(System Chaincode)指的是Fabric Peer中负责系统配置、查询、背书、验证等平台功能的代码逻辑,运行在Peer进程内,将在第14章介绍。用户链码指的是用户编写的用来实现智能合约的应用代码。如无特殊说明,链码一般指的就是用户链码。
链码被部署在Peer节点上,运行在独立的沙盒(目前为Docker容器)中,并通过gRPC协议与相应的Peer节点进行交互。用户可以通过命令行或SDK调用链码方法,链码被调用时,会按照链码内预定逻辑来计算账本状态的更新集合(读写集合)。
链码操作命令
Operate a chaincode: install|instantiate|invoke|package|query|signpackage|upgrade|list.
Usage:
peer chaincode [command]
Available Commands:
install Install a chaincode.
instantiate Deploy the specified chaincode to the network.
invoke Invoke the specified chaincode.
list Get the instantiated chaincodes on a channel or installed chaincodes on a peer.
package Package a chaincode
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
--certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint
--clientauth Use mutual TLS when communicating with the orderer endpoint
--connTimeout duration Timeout for client to connect (default 3s)
-h, --help help for chaincode
--keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint
-o, --orderer string Ordering service endpoint
--ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer
--tls Use TLS when communicating with the orderer endpoint
--tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint
--transient string Transient map of arguments in JSON encoding
Use "peer chaincode [command] --help" for more information about a command.
最简单的操作链码的方式是使用命令行。Fabric自2.0版本开始正式启用新的生命周期系统链码(位于core/chaincode/lifecycle)来管理链码(需开启应用能力V2_0),客户端通过新的peer lifecycle chaincode
子命令(位于internal/peer/lifecycle)对链码进行打包、安装、批注和提交等生命周期管理,取代1.x中的peer chaincode
命令。
相对1.x版本中的模式,新的链码管理从单个组织升级为通道范畴。例如,链码的背书策略可由通道内多个组织来商定,部署和升级也作为通道层面的操作,这些都提高了链码生命周期的安全性。如果要对链码进行调用或查询,仍可以使用原有的peer chaincode invoke
和peer chaincode query
命令。
如果要使用1.x版本中的链码生命周期管理(peer chaincodeinstall/instantaite/upgrade/list等命令),需要将通道的应用能力版本设置为兼容的低版本,如V1_4_2。当通道启用了应用能力V2_0后,将无法再部署或升级原有模式下的链码。
链码生命周期:
链码操作支持全局命令选项:
全局选项 | 类型 | 含义 |
---|---|---|
--cafile | string | 信任的排序服务的 TLS CA 的证书(PEM编码格式)路径 |
--certfile | string | 与排序服务进行双向 TLS 认证时使用的本地证书文件路径 |
--clientauth | bool | 与排序服务通信时是否启用双向 TLS 认证 |
--connTimeout | duration | 客户端连接超时,默认为 3 秒 |
--keyfile | string | 与排序服务双向 TLS 认证时使用的本地私钥文件路径 |
-o,--orderer | string | Orderer 服务地址 |
--ordererTLSHostnameOverride | string | 验证 Orderer TLS 时覆盖所校验的主机名 |
--tls | bool | 连接到 Orderer 服务时是否启用 TLS |
--transient | string | 调用链码时传递的临时信息,其他 peer 将无法获取该信息 |
打包链码
package
子命令可以封装链码相关的数据,将其打包为.tar.gz安装包,供安装使用。
Package a chaincode and write the package to a file.
Usage:
peer chaincode package [outputfile] [flags]
Flags:
-s, --cc-package create CC deployment spec for owner endorsements instead of raw CC deployment spec
-c, --ctor string Constructor message for the chaincode in JSON format (default "{}")
-h, --help help for package
-i, --instantiate-policy string instantiation policy for the chaincode
-l, --lang string Language the chaincode is written in (default "golang")
-n, --name string Name of the chaincode
-p, --path string Path to chaincode
-S, --sign if creating CC deployment spec package for owner endorsements, also sign it with local MSP
-v, --version string Version of the chaincode specified in install/instantiate/upgrade commands
Global Flags:
--cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint
--certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint
--clientauth Use mutual TLS when communicating with the orderer endpoint
--connTimeout duration Timeout for client to connect (default 3s)
--keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint
-o, --orderer string Ordering service endpoint
--ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer
--tls Use TLS when communicating with the orderer endpoint
--tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint
--transient string Transient map of arguments in JSON encoding
其中,生成的打包文件中包括Chaincode-Package-Metadata.json、Code-Package.tar.gz两个文件。Chaincode-Package-Metadata.json内容包括链码路径、类型、标签等信息.Code-Package.tar.gz内容包括链码的源码包结构,如src/examples/chaincode/go/testcc/路径以及内容,但不能包括对目录以外路径的引用。
注意:自2.0版本起,编译链码的ccenv镜像不再包括shim层。链码需要自行包括/hyperledger/fabric-chaincode-go/shim和其他所需要的依赖包。
安装链码
打包后的链码安装包文件,可以使用install命令安装到运行链码的各个Peer。
Install a chaincode on a peer. This installs a chaincode deployment spec package (if provided) or packages the specified chaincode before subsequently installing it.
Usage:
peer chaincode install [flags]
Flags:
--connectionProfile string Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information
-c, --ctor string Constructor message for the chaincode in JSON format (default "{}")
-h, --help help for install
-l, --lang string Language the chaincode is written in (default "golang")
-n, --name string Name of the chaincode
-p, --path string Path to chaincode
--peerAddresses stringArray The addresses of the peers to connect to
--tlsRootCertFiles stringArray If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag
-v, --version string Version of the chaincode specified in install/instantiate/upgrade commands
Global Flags:
--cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint
--certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint
--clientauth Use mutual TLS when communicating with the orderer endpoint
--connTimeout duration Timeout for client to connect (default 3s)
--keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint
-o, --orderer string Ordering service endpoint
--ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer
--tls Use TLS when communicating with the orderer endpoint
--tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint
--transient string Transient map of arguments in JSON encoding
参数 | 类型 | 含义 |
---|---|---|
-- connectionProfile | string | 网络访问信息文件路径,目前仅支持 peer 连接信息 |
-- peerAddresses | stringArray | 请求所发往的 peer 地址列表 |
--tlsRootCertFiles | stringArray | 所连接的 peer 的信任 TLS 根证书 |
Peer会尝试编译链码,如果编译成功,则将安装包以二进制的形式储存到指定路径的chaincodes子目录下,并利用元数据标签和安装包生成的SHA256值作为文件名。
Peer会尝试编译链码,如果编译成功,则将安装包以二进制的形式储存到指定路径的chaincodes子目录下,并利用元数据标签和安装包生成的SHA256值作为文件名。
注意,安装操作需要是Peer认可的组织管理员身份(证书在Peer的admincerts目录下存在)。
查询和批准链码
通道内组织在部署链码前需要足够多的组织管理员对链码定义进行投票批准。链码定义包括链码名称、版本、序列号、背书和验证参数、是否需要初始化、链码包Id,以及可能带有的私密数据集合配置等。操作涉及queryinstalled、getinstalled-package、approveformyorg、checkcommitrea-diness四个链码生命周期子命令。
queryinstalled子命令可以查询目标Peer上已经安装的链码信息。支持的参数包括:
●--connectionProf ile string,网络访问信息文件路径,目前仅支持Peer连接信息。
●-O,--output string,结果输出的格式,目前支持格式化为json格式。
●--peerAddresses stringArray,请求所发往的Peer地址列表。
●--tlsRootCertFiles stringArray,所连接的Peer的信任的TLS根证书。getinstalledpackage子命令可以获取指定的链码安装包(与发送给Peer的安装包内容相同)。支持参数包括:
●--connectionProf ile string,网络访问信息文件路径,目前仅支持Peer连接信息。
●--output-directory string,将获取到的链码安装包保存到指定路径,默认为当前路径。
●--package-id string,所要获取的链码安装包的ID。
●--peerAddresses stringArray,请求所发往的Peer地址列表。
●--tlsRootCertFiles stringArray,所连接的Peer的信任的TLS根证书。
approveformyorg子命令允许用户将链码的定义发送给Peer进行背书,通过后发给Orderer进行排序和确认。所有需要执行链码的组织都需要完成此步骤。默认情况下,只有通道内大多数组织(通道内的Channel/Application/LifecycleEndorsement策略指定,默认为通道内大多数成员)都批准了链码定义,对应链码才能在通道内部署运行。支持的参数包括:
●--channel-config-policy string,指定链码的背书策略名称,该策略名称需要提前存储在通道策略配置中,默认为Channel/Application/Endorsement策略(默认为通道内大多数成员组织背书)。
●-C,--channelID string,执行命令面向的通道名称。
●--collections-conf ig string,启用私密数据功能时,指定集合文件的路径。
●--connectionProf ile string,网络访问信息文件路径,目前仅支持Peer连接信息。
●-E,--endorsement-plugin string,链码所使用的背书插件的名称。
●--init-required,是否需要调用Init方法对链码进行初始化。
●-n,--name string,链码名称。
●--package-id string,链码安装包的名称。
●--peerAddresses stringArray,所连接的Peer节点列表。
●--sequence int,通道内对链码进行定义的序列号(默认为1),每次更新链码定义则需要递增。
●--signature-policy string,指定链码的(基于签名的)背书策略,默认采用Channel/Application/Endorsement指定的策略(默认为通道内大多数成员组织背书),不能与--channel-conf ig-policy同时使用。
●--tlsRootCertFiles stringArray,连接Peer启用TLS时,所信任的TLS根证书列表(注意与Peer地址顺序匹配)。
●-V,--validation-plugin string,链码所使用的校验系统插件名称。
●--waitForEvent,是否等待事件以确认交易在各个Peer提交(默认开启)。
●--waitForEventTimeout duration,等待事件的时间(默认为30s)。
checkcommitreadiness子命令可以获取指定的链码安装包当前的批准状态,调用_lifecycle链码CheckCommitReadiness方法(位于core/chaincode/lifecycle/scc.go)。支持参数与approveformyorg子命令类似。
提交链码并查询状态
通道内链码得到足够多的组织批准后,将成为可以合法运行的链码。此时,任意通道内组织可以使用commit子命令发起提交操作。链码定义被成功提交到通道后,通道内成员可以使用链码(如进行调用)。支持的参数包括:
●--channel-config-policy string,指定链码的背书策略名称,该策略名称需要提前存储在通道策略配置中,默认为Channel/Application/Endorsement策略(默认为通道内大多数成员组织背书)。
●-C,--channelID string,执行命令面向的通道名称。
●--collections-conf ig string,启用私密数据功能时,指定集合文件的路径。
●--connectionProf ile string,网络访问信息文件路径,目前仅支持Peer连接信息。
●-E,--endorsement-plugin string,链码所使用的背书插件的名称。
●--init-required,是否需要调用Init方法对链码进行初始化。
●-n,--name string,链码名称。
●--package-id string,链码安装包的名称。
●--peerAddresses stringArray,所连接的Peer节点列表。
●--sequence int,通道内对链码进行定义的序列号(默认为1),每次更新链码定义则需要递增。
●--signature-policy string,指定链码的(基于签名的)背书策略,默认采用Channel/Application/Endorsement指定的策略(默认为通道内大多数成员组织背书),不能与--channel-conf ig-policy同时使用。
●--tlsRootCertFiles stringArray,连接Peer启用TLS时,所信任的TLS根证书列表(注意与Peer地址顺序匹配)。
●-V,--validation-plugin string,链码所使用的校验系统插件名称。
●--waitForEvent,是否等待事件以确认交易在各个Peer提交(默认开启)。
●--waitForEventTimeout duration,等待事件的时间(默认为30s)。
●-C,--channelID string,执行命令的通道名称。
●--connectionProf ile string,网络访问信息文件路径,目前仅支持Peer连接信息。
●-n,--name string,链码名称。
●-O,--output string,结果输出的格式,目前支持json格式。
●--peerAddresses stringArray,所连接的Peer地址列表。
●--tlsRootCertFiles stringArray,连接Peer启用TLS时,所信任的TLS根证书列表(注意与Peer地址顺序匹配)。
首先使用commit子命令提交已经得到批准的链码定义,然后使用querycommitted子命令查询提交状态
使用私有数据
在批准和提交链码定义时,可以通过--collections-conf ig collection.json来指定与私密数据相关的集合配置(Fabric v1.1.0开始支持),可以实现在同一通道内私密数据的调用只有部分成员共享。如果不指定该参数则默认不启用该特性,意味着通道内所有成员都可以看到链码调用结果。
collections_config.json
配置文件示例 :
[
{
"name": "collection1", // 集合名称
"policy": "OR('Org1MSP.member')", // 集合成员
"requiredPeerCount": 0, // 背书之前至少扩散私有数据到的节点数
"maxPeerCount": 3, // 背书之前尝试扩散最多节点个数, 不能小于 requiredPeerCount
"blockToLive": 1000000, // 私有数据保存时长 0 意味着永不过期
"memberOnlyRead": true, // 是否只允许集合成员来读取私有数据
"memberOnlyWrite": true ,// 是否只允许集合成员来发起对私有数据的写交易
"endorsementPolicy": "OR('Org1MSP.member')" ,// 指定对私有数据写操作时的背书策略
"signaturePolicy": "OR('Org1MSP.member')" // 指定使用签名策略
},
{
"name": "collection2",
"policy": "OR('Org2MSP.member')",
"requiredPeerCount": 0,
"maxPeerCount": 3,
"blockToLive": 1,
"memberOnlyRead": true
}
]
其中,collection.json中定义了collection1和collection2两个集合,其成员分别为Org1、Org2两个组织。当在链码逻辑中指定某个键值属于特定集合时,只有集合内成员能看到明文的读写集合,非集合成员即使在同一通道内也无法获取私密数据。对应policy只支持OR语法,指定哪些组织可以看到私密数据集合。
requiredPeerCount和maxPeerCount指定了在执行背书过程中尝试扩散数据到其他合法节点的个数,避免因背书节点的突然故障而导致私密数据丢失。背书阶段未获取私密数据的合法节点,在提交阶段会尝试从其他节点来拉取私密数据。
调用链码
通过 peer chaincode invoke
命令(实现位于internal/peer/chaincode)可以调用运行中链码定义的方法,所指定的函数名和参数会被传到链码的Invoke()方法进行处理。调用链码操作需要同时与Peer和Orderer打交道。
Invoke the specified chaincode. It will try to commit the endorsed transaction to the network.
Usage:
peer chaincode invoke [flags]
Flags:
-C, --channelID string The channel on which this command should be executed
--connectionProfile string Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information
-c, --ctor string Constructor message for the chaincode in JSON format (default "{}")
-h, --help help for invoke
-I, --isInit Is this invocation for init (useful for supporting legacy chaincodes in the new lifecycle)
-n, --name string Name of the chaincode
--peerAddresses stringArray The addresses of the peers to connect to
--tlsRootCertFiles stringArray If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag
--waitForEvent Whether to wait for the event from each peer's deliver filtered service signifying that the 'invoke' transaction has been committed successfully
--waitForEventTimeout duration Time to wait for the event from each peer's deliver filtered service signifying that the 'invoke' transaction has been committed successfully (default 30s)
Global Flags:
--cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint
--certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint
--clientauth Use mutual TLS when communicating with the orderer endpoint
--connTimeout duration Timeout for client to connect (default 3s)
--keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint
-o, --orderer string Ordering service endpoint
--ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer
--tls Use TLS when communicating with the orderer endpoint
--tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint
--transient string Transient map of arguments in JSON encoding
注意,invoke是异步操作,invoke成功只能保证交易已经进入Orderer进行排序,但无法保证最终写到账本中(例如交易未通过Committer验证而被拒绝)。需要通过事件监听或主动查询等方式来进行确认交易是否最终写到账本上。
查询链码
查询链码可以通过 peer chaincode query
子命令。
该子命令实际上是invoke操作与Peer打交道的部分,即将签名后的Proposal发给指定的Peer节点的ProcessProposal()gRPC接口。最终将-c指定的命令参数发送给了链码中的Invoke()方法执行。
query操作与invoke操作的区别在于,query操作用来查询Peer上账本状态(需要链码支持查询逻辑),不生成交易,也不需要与Orderer打交道。同时,query命令默认只返回第一个Peer的查询结果。
Get endorsed result of chaincode function call and print it. It won't generate transaction.
Usage:
peer chaincode query [flags]
Flags:
-C, --channelID string The channel on which this command should be executed
--connectionProfile string Connection profile that provides the necessary connection information for the network. Note: currently only supported for providing peer connection information
-c, --ctor string Constructor message for the chaincode in JSON format (default "{}")
-h, --help help for query
-x, --hex If true, output the query value byte array in hexadecimal. Incompatible with --raw
-n, --name string Name of the chaincode
--peerAddresses stringArray The addresses of the peers to connect to
-r, --raw If true, output the query value as raw bytes, otherwise format as a printable string
--tlsRootCertFiles stringArray If TLS is enabled, the paths to the TLS root cert files of the peers to connect to. The order and number of certs specified should match the --peerAddresses flag
Global Flags:
--cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint
--certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint
--clientauth Use mutual TLS when communicating with the orderer endpoint
--connTimeout duration Timeout for client to connect (default 3s)
--keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint
-o, --orderer string Ordering service endpoint
--ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer
--tls Use TLS when communicating with the orderer endpoint
--tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint
--transient string Transient map of arguments in JSON encoding
升级链码
链码升级过程需要重复peer lifecycle chaincode相关命令,来执行完整的生命周期,具体步骤如下:
1)更新旧版本链码的源代码,并重新打包链码包。
2)将新的链码包再次安装到Peer,获取新的包Id。注意,相对旧版本要递增版本号。
3)按照策略,通道内足够多组织都要重新对新版本的链码定义进行批准。注意,序列号要递增。
4)通道内足够多组织批准定义后,可以提交新版本链码定义到通道。
5)再次调用链码,确保链码已经自动更新为新的版本。