将智能合约部署到通道
Deploying a smart contract to a channel(将智能合约部署到通道)
最终用户通过调用智能合约与区块链账本进行交互。在Hyperledger Fabric中,智能合约通过称为chaincode的软件包进行部署。一个组织想要验证交易或者查询账本的内容,就需要在其peer节点上部署chaincode。当一个已经安装了chaincode的节点加入channel之后,channel的成员就可以把chaincode部署到channel上,然后使用chaincode上的智能合约来创建和更新chanel账本上的资产。
我们使用一个叫做Fabric链码生命周期的程序来将chaincode部署到channel上;在链码可以被使用于交易之前,Fabric链码生命周期需要多个组织同意链码将如何操作。(个人理解:需要组织同意智能合约的内容,智能合约才能部署到channel上)举个例子,当一个背书策略制定哪些组织需要执行chaincode来验证一个交易时,channel上的成员需要使用Fabric链码生命周期来同意链码的背书策略。有关如何在通道上部署和管理链码的更深入的概述,请参阅Fabric chaincode lifecycle。
你可以使用 peer lifecycle chaincode commands这个教程来学习在Fabric测试网络中如何使用peer lifecycle chaincode commands来部署链码到channel。了解命令后,您可以使用本教程中的步骤将自己的链码部署到测试或生产网络。在这个教程中,你会部署教程Writing your first application tutorial使用的链码程序。
**注意:**当前教程使用v2.0版本中引入的Fabric链码生命周期。
Start the network(启动测试网络)
启动测试网络并创建channel,具体步骤参考Fabric测试网络使用。
你可以根据以下步骤使用节点的CLI来部署 asset-transfer (basic) 链码到channel中:
- [第一步:打包智能合约]
- [第二步:安装链码包]
- [第三步:批准链码定义]
- [第四部:提交链码定义到channel中]
Setup Logspout (optional)(启动日志输出,可选)
此步骤不是必需的,但是对于故障排除链码非常有用。要监视智能合约的日志,管理员可以使用logspout查看一组Docker容器的聚合输出。这个工具收集不同的Docker容器的输出流到一个位置,这样就可以在一个窗口看这些容器都发生了什么。这可以帮助管理员在安装智能合约或者是开发人员调用智能合约时调试问题。因为某些容器的创建纯粹是为了启动智能合约,并且仅存在很短的时间,所以从网络中收集所有日志将很有帮助。
Fabric的商业票据示例中已经包含了用于安装和配置Logspout的脚本monitordocker.sh。在本教程中,我们还将使用相同的脚本。Logspout工具将持续向您的终端流式传输日志,因此您将需要使用新的终端窗口。打开一个新终端,然后导航到test-network目录。
1 | cd fabric-samples/test-network |
你可以在任何目录下运行 monitordocker.sh
脚本,为了方便使用我们把 monitordocker.sh
从commercial-paper
拷贝到你的工作目录(test-network)。
1 | cp ../commercial-paper/organization/digibank/configuration/cli/monitordocker.sh . |
你可以使用下面的命令来启动Logspout:
1 | ./monitordocker.sh net_test |
你会看到类似下面的输出:
1 | Starting monitoring on all containers on the network net_basic |
在我们部署链码之前你不会看到太多的日志。
Package the smart contract(打包智能合约)
We need to package the chaincode before it can be installed on our peers. The steps are different if you want to install a smart contract written in Go, JavaScript, or Typescript.
在把智能合约安装到我们的节点之前需要先将其打包。根据编写智能合约的语言的不同,其步骤也是不一样的。(本次只使用Go,其他语言如Go, JavaScript, or Typescript请参考官方文档)
Go
在我们打包链码之前,我们需要先安装链码的依赖。切换到Go版本的 asset-transfer (basic) 项目目录下:
1 | cd fabric-samples/asset-transfer-basic/chaincode-go |
该示例使用Go模块来安装chaincode依赖项。依赖关系列在asset-transfer-basic / chaincode-go目录的go.mod文件中。您应该花一点时间来检查此文件。
1 | module github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go |
go.mod文件将Fabric合约API导入到智能合约包中。你可以打开asset-transfer-basic/chaincode-go/chaincode/smartcontract.go
来查看在智能合约的最开始是如使用contract API来定义SmartContract
类的。
1 | // SmartContract provides functions for managing an Asset |
然后,将SmartContract类型用于为智能合约中定义的方法创建交易上下文,该方法可将数据读取和写入区块链账本。
1 |
|
你可以通过访问 API documentation 和 smart contract processing topic来学习更多的关于合约API的内容。
为了安装智能合约的依赖,在asset-transfer-basic/chaincode-go
目录下运行下面的命令:
1 | GO111MODULE=on go mod vendor |
如果命令成功,则go软件包将安装vendor文件夹中。
现在我们已经有了依赖的包,我们可以创建chaincode的包了。把当前目录切换到test-network
以便我们可以将链码于其他网络组件打包在一起。
1 | cd ../../test-network |
You can use the peer
CLI to create a chaincode package in the required format. The peer
binaries are located in the bin
folder of the fabric-samples
repository. Use the following command to add those binaries to your CLI Path:
您可以使用peer
CLI创建所需格式的链码包。peer
二进制文件位于fabric-samples存储库的bin文件夹中。可以使用下面的命令添加到你的环境变量中。
1 | export PATH=${PWD}/../bin:$PATH |
您还需要将FABRIC_CFG_PATH设置为指向fabric-samples存储库中的core.yaml文件:
1 | export FABRIC_CFG_PATH=$PWD/../config/ |
使用下面的命令来查看peer的版本,如果输出正常说明你已经可以使用peer
CLI了。
1 | peer version |
You can now create the chaincode package using the peer lifecycle chaincode package command:
现在你可以通过 peer lifecycle chaincode package 命令来创建链码包了:
1 | peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_1.0 |
This command will create a package named basic.tar.gz
in your current directory. The --lang
flag is used to specify the chaincode language and the --path
flag provides the location of your smart contract code. The path must be a fully qualified path or a path relative to your present working directory. The --label
flag is used to specify a chaincode label that will identity your chaincode after it is installed. It is recommended that your label include the chaincode name and version.
这个命令会在你的当前目录下创建一个名为basic.tar.gz
的压缩包。--lang
标志是制定chaincode的语言,而--path
标志用于提供智能合约代码的位置。该路径必须是标准路径或相对于您当前工作目录的路径。--label
标志用于指定一个链码标签,该标签将在安装链码后对其进行标识。建议您的标签包含链码名称和版本。
Now that we created the chaincode package, we can install the chaincode on the peers of the test network.
现在我们已经创建了链码包,我们可以把链码安装到网络上的节点上了。
Install the chaincode package(安装链码包)
After we package the asset-transfer (basic) smart contract, we can install the chaincode on our peers. The chaincode needs to be installed on every peer that will endorse a transaction. Because we are going to set the endorsement policy to require endorsements from both Org1 and Org2, we need to install the chaincode on the peers operated by both organizations:
在我们打包了 asset-transfer (basic) 的智能合约之后,我们就可以将此链码安装到我们的peer节点上了。需要在所有的交易背书节点上安装链码。因为我们将设置背书策略要求来自Org1和Org2的背书,所以我们需要在两个组织运营的对等方上安装链码:
Let’s install the chaincode on the Org1 peer first. Set the following environment variables to operate the peer
CLI as the Org1 admin user. The CORE_PEER_ADDRESS
will be set to point to the Org1 peer, peer0.org1.example.com
.
让我们先把链码安装到Org1的节点上。设置以下环境变量来使用Org1的admin用户的身份运行peer
CLI。将CORE_PEER_ADDRESS设置为指向Org1的节点的peer0.org1.example.com
。
1 | export CORE_PEER_TLS_ENABLED=true |
Issue the peer lifecycle chaincode install command to install the chaincode on the peer:
发出在peer节点上安装链码的命令:
1 | peer lifecycle chaincode install basic.tar.gz |
If the command is successful, the peer will generate and return the package identifier. This package ID will be used to approve the chaincode in the next step. You should see output similar to the following:
如果命令执行成功,则peer将生成并返回安装包的标识符。这个包的ID会在下一步批准这个链码时使用。你会看到类似下面的输出:
1 | 2020-12-21 14:46:18.360 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nJbasic_1.0:2c47b5b060a64aafa3c878b4bcb0ca680bdb2417ca8855b5440fa595562517d2\022\tbasic_1.0" > |
在运行monitordocker.sh
的终端可以看到下面的日志:
1 | peer0.org1.example.com|2020-12-21 06:46:18.363 UTC [lifecycle] InstallChaincode -> INFO 046 Successfully installed chaincode with package ID 'basic_1.0:2c47b5b060a64aafa3c878b4bcb0ca680bdb2417ca8855b5440fa595562517d2' |
We can now install the chaincode on the Org2 peer. Set the following environment variables to operate as the Org2 admin and target target the Org2 peer, peer0.org2.example.com.
现在我们把链码安装到Org2组织的peer节点上。先设置环境变量让我们可以以Org2的管理员身份来操作Org2的节点:
1 | export CORE_PEER_LOCALMSPID="Org2MSP" |
Issue the following command to install the chaincode(发出以下命令来安装链码):
1 | peer lifecycle chaincode install basic.tar.gz |
The chaincode is built by the peer when the chaincode is installed. The install command will return any build errors from the chaincode if there is a problem with the smart contract code.
在安装链码时,由peer节点来构建链码。如果智能合约有问题,安装命令会把所有构建的错误返回。
Approve a chaincode definition(批准链码定义)
After you install the chaincode package, you need to approve a chaincode definition for your organization. The definition includes the important parameters of chaincode governance such as the name, version, and the chaincode endorsement policy.
在安装链码包之后,需要你所在的组织批准链码的定义。这个定义包括链码管理的重要参数,例如名称、版本以及链码的背书策略。
The set of channel members who need to approve a chaincode before it can be deployed is governed by the Application/Channel/lifeycleEndorsement
policy.By default, this policy requires that a majority of channel members need to approve a chaincode before it can used on a channel.Because we have only two organizations on the channel, and a majority of 2 is 2, we need approve a chaincode definition of asset-transfer (basic) as Org1 and Org2.
在channel上的哪些成员需要在其可以部署链码之前批准,是定义在Application/Channel/lifeycleEndorsement
策略中。默认情况下,此策略要求大多数channel的成员需要批准链码后才能在频道上使用。因为在我们的channel上只有两个组织,并且大多数就是2,我们需要以Org1和Org2的身份来批准asset-transfer (basic)的链码定义。
If an organization has installed the chaincode on their peer, they need to include the packageID in the chaincode definition approved by their organization. The package ID is used to associate the chaincode installed on a peer with an approved chaincode definition, and allows an organization to use the chaincode to endorse transactions. You can find the package ID of a chaincode by using the peer lifecycle chaincode queryinstalled command to query your peer.
如果一个组织已经在其peer节点上安装了链码,这个组织需要在其批准的链码定义中包含packageID。packageID是用来把安装在节点上的chaincode和已经批准通过的链码定义关联起来的,并且允许一个组织在背书节点使用这个链码。你可以使用peer lifecycle chaincode queryinstalled 命令在你的peer节点上查询一个链码的packageID。
1 | peer lifecycle chaincode queryinstalled |
The package ID is the combination of the chaincode label and a hash of the chaincode binaries. Every peer will generate the same package ID. You should see output similar to the following:
packageID是链码标签和链码二进制文件的哈希值的组合。每个peer将生成相同的程序包ID。您应该看到类似于以下内容的输出:
1 | Installed chaincodes on peer: |
We are going to use the package ID when we approve the chaincode, so let’s go ahead and save it as an environment variable. Paste the package ID returned by peer lifecycle chaincode queryinstalled
into the command below. Note: The package ID will not be the same for all users, so you need to complete this step using the package ID returned from your command window in the previous step.
在我们批准链码时我们需要使用这个 package ID,所以让我们先把它保存为一个环境变量:
1 | export CC_PACKAGE_ID=basic_1.0:2c47b5b060a64aafa3c878b4bcb0ca680bdb2417ca8855b5440fa595562517d2 |
Because the environment variables have been set to operate the peer
CLI as the Org2 admin, we can approve the chaincode definition of asset-transfer (basic) as Org2. Chaincode is approved at the organization level, so the command only needs to target one peer. The approval is distributed to the other peers within the organization using gossip. Approve the chaincode definition using the peer lifecycle chaincode approveformyorg command:
因为当前的环境变量已经设置为以Org2组织的管理员来操作peer
CLI,我们可以以组织Org2的身份批准这个asset-transfer (basic)的链码定义。链码是在组织的级别进行批准的,所以这个命令只需要针对一个peer节点即可。这个批准的动作会使用gossip来在组织内部传播。使用 peer lifecycle chaincode approveformyorg命令来批准链码定义:
1 | peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem |
The command above uses the --package-id
flag to include the package identifier in the chaincode definition. The --sequence
parameter is an integer that keeps track of the number of times a chaincode has been defined or updated. Because the chaincode is being deployed to the channel for the first time, the sequence number is 1. When the asset-transfer (basic) chaincode is upgraded, the sequence number will be incremented to 2. If you are using the low level APIs provided by the Fabric Chaincode Shim API, you could pass the --init-required
flag to the command above to request the execution of the Init function to initialize the chaincode. The first invoke of the chaincode would need to target the Init function and include the --isInit
flag before you could use the other functions in the chaincode to interact with the ledger.
上面的命令使用--package-id
标志将软件包标识符包含在链码定义中。--sequence
参数是一个整数,用于跟踪定义或更新链码的次数;由于链码是第一次部署到channel,因此序列号为1。当asset-transfer (basic) 的链码在更新时,这个序列号会增加到2。链代码的首次调用需要使用--isInit
来指明调用链码的Init函数,然后才能使用链代码中的其他函数与账本进行交互。
We could have provided a --signature-policy
or --channel-config-policy
argument to the approveformyorg
command to specify a chaincode endorsement policy. The endorsement policy specifies how many peers belonging to different channel members need to validate a transaction against a given chaincode. Because we did not set a policy, the definition of asset-transfer (basic) will use the default endorsement policy, which requires that a transaction be endorsed by a majority of channel members present when the transaction is submitted. This implies that if new organizations are added or removed from the channel, the endorsement policy is updated automatically to require more or fewer endorsements. In this tutorial, the default policy will require a majority of 2 out of 2 and transactions will need to be endorsed by a peer from Org1 and Org2. If you want to specify a custom endorsement policy, you can use the Endorsement Policies operations guide to learn about the policy syntax.
我们可以在approveformyorg
命令中提供--signature-policy
或--channel-config-policy
参数,以指定链码背书策略。背书策略指定需要多少个属于不同渠道成员的peer根据给定的链码验证来交易。因为我们没有指定合格策略,asset-transfer (basic) 的定义会使用默认的背书策略,该政策要求在提交交易时,该交易必须得到channel中大多数成员的认可。这意味着,如果在channel中添加或删除组织,则背书政策会自动更新,以要求更多或更少的认可。在本教程中,默认策略需要2个中的大多数也就是2,并且交易需要由来自Org1和Org2的peer认可。如果要指定自定义认可策略,则可以使用 Endorsement Policies 操作指南来了解策略语法。
You need to approve a chaincode definition with an identity that has an admin role. As a result, the CORE_PEER_MSPCONFIGPATH
variable needs to point to the MSP folder that contains an admin identity. You cannot approve a chaincode definition with a client user. The approval needs to be submitted to the ordering service, which will validate the admin signature and then distribute the approval to your peers.
你需要使用具有管理员角色的身份来批准的链码定义。即CORE_PEER_MSPCONFIGPATH
变量需要指向包含管理员身份的MSP文件夹。你不能使用客户端用户的身份来批准链码。这个审批结果需要提交给排序服务,排序服务会验证管理员的签名,然后分发这个验证结果到你的peer节点。
We still need to approve the chaincode definition as Org1. Set the following environment variables to operate as the Org1 admin:
你还需要在组织Org1上批准这个链码定义,把环境变量修改为以组织Org1的管理员身份来操作:
1 | export CORE_PEER_LOCALMSPID="Org1MSP" |
You can now approve the chaincode definition as Org1.
现在你可以以组织Org1的身份批准链码定义了。
1 | peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem |
We now have the majority we need to deploy the asset-transfer (basic) the chaincode to the channel. While only a majority of organizations need to approve a chaincode definition (with the default policies), all organizations need to approve a chaincode definition to start the chaincode on their peers. If you commit the definition before a channel member has approved the chaincode, the organization will not be able to endorse transactions. As a result, it is recommended that all channel members approve a chaincode before committing the chaincode definition.
现在我们已经有了将asset-transfer (basic) 的链码部署到渠道的大多数的批准。在将链码定义部署到channel上时,我们需要大多数组织的批准(使用默认的策略);但是所有的组织都需批准链码定义才能在其peer启动这个链码。如果你在一个channel成员批准定义之前将链码定义提交到channel,那么这个组织将无法批准交易。结果,建议所有通道成员在提交链码定义之前批准链码。
Committing the chaincode definition to the channel(将链码定义提交到通道)
After a sufficient number of organizations have approved a chaincode definition, one organization can commit the chaincode definition to the channel. If a majority of channel members have approved the definition, the commit transaction will be successful and the parameters agreed to in the chaincode definition will be implemented on the channel.
在有足够数量的组织批准链码定义之后,其中一个组织就可以把链码定义提交到通道中了。如果大多数通道成员已批准该定义,则提交定义的交易将会成功,并且链码定义中同意的参数将在该通道上实现。
You can use the peer lifecycle chaincode checkcommitreadiness command to check whether channel members have approved the same chaincode definition. The flags used for the checkcommitreadiness
command are identical to the flags used to approve a chaincode for your organization. However, you do not need to include the --package-id
flag.
你可以使用 peer lifecycle chaincode checkcommitreadiness命令来检查channel上的成员是否已经批准了相同的链码定义。用于checkcommitreadiness
命令的标志与您的组织批准链码的标志相同;但是不需要包括--package-id
标志。
1 | peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json |
The command will produce a JSON map that displays if a channel member has approved the parameters that were specified in the checkcommitreadiness
command:
这个命令会生成一个JSON来显示通道成员是否已经批准了定义。
1 | { |
Since both organizations that are members of the channel have approved the same parameters, the chaincode definition is ready to be committed to the channel. You can use the peer lifecycle chaincode commit command to commit the chaincode definition to the channel. The commit command also needs to be submitted by an organization admin.
因为channel上的两个成员都已经批准了相同的参数,因此链码定义已准备好提交给channel。你可以使用peer lifecycle chaincode commit 命令将链码定义提交到channel。commit命令依然需要由组织管理员来发起。
1 | peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt |
The transaction above uses the --peerAddresses
flag to target peer0.org1.example.com
from Org1 and peer0.org2.example.com
from Org2. The commit
transaction is submitted to the peers joined to the channel to query the chaincode definition that was approved by the organization that operates the peer. The command needs to target the peers from a sufficient number of organizations to satisfy the policy for deploying a chaincode. Because the approval is distributed within each organization, you can target any peer that belongs to a channel member.
上面的交易使用--peerAddresses
标志来指定Org1中的peer0.org1.example.com
和Org2中的peer0.org2.example.com
。 commit
交易会提交给已经加入通道的peer节点,用于peer节点查询同组织内其他节点批准的链码定义。该命令需要指明来自足够数量的组织中的peer节点,以满足部署链码的策略。因为批准操作已经在每个组织内部进行广播,所以你可以指定属于一个通道成员的任意的peer节点。
The chaincode definition endorsements by channel members are submitted to the ordering service to be added to a block and distributed to the channel. The peers on the channel then validate whether a sufficient number of organizations have approved the chaincode definition. The peer lifecycle chaincode commit
command will wait for the validations from the peer before returning a response.
通道成员对链码定义的认可会提交给排序服务,以添加到区块并分发给渠道。然后通道上的peer节点验证是否有足够数量的组织批准了链码定义。peer lifecycle chaincode commit
命令在返回相应之前会等待peer节点的验证。
You can use the peer lifecycle chaincode querycommitted command to confirm that the chaincode definition has been committed to the channel.
你可以使用 peer lifecycle chaincode querycommitted 命令来确认链码定义已经提交到通道。
1 | peer lifecycle chaincode querycommitted --channelID mychannel --name basic --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem |
If the chaincode was successful committed to the channel, the querycommitted
command will return the sequence and version of the chaincode definition:
如果链码已经成功提交到通道,querycommitted
命令会返回该链码定义的序列号和版本号:
1 | Committed chaincode definition for chaincode 'basic' on channel 'mychannel': |
Invoking the chaincode(调用链码)
After the chaincode definition has been committed to a channel, the chaincode will start on the peers joined to the channel where the chaincode was installed. The asset-transfer (basic) chaincode is now ready to be invoked by client applications. Use the following command create an initial set of assets on the ledger. Note that the invoke command needs target a sufficient number of peers to meet chaincode endorsement policy.
在链码定义提交到通道之后,链码可以由加入了通道并且安装了此链码的peer节点来启动。 asset-transfer (basic) 的链码已经可以由客户端程序进行调用。使用以下命令在账本上创建和初始化资产。请注意,invoke命令需要以足够数量的peer为目标,以满足链码的背书策略。
1 | peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}' |
If the command is successful, you should be able to a response similar to the following:
如果命令执行成功,你会看到类似下面的响应:
1 | 2020-12-21 16:51:11.086 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 |
We can use a query function to read the set of cars that were created by the chaincode:
我们使用查询方法来查看我们通过链码创建的车:
1 | peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}' |
The response to the query should be the following list of assets:
下面的资产列表就是查询的响应结果:
1 | [{"ID":"asset1","color":"blue","size":5,"owner":"Tomoko","appraisedValue":300},{"ID":"asset2","color":"red","size":5,"owner":"Brad","appraisedValue":400},{"ID":"asset3","color":"green","size":10,"owner":"Jin Soo","appraisedValue":500},{"ID":"asset4","color":"yellow","size":10,"owner":"Max","appraisedValue":600},{"ID":"asset5","color":"black","size":15,"owner":"Adriana","appraisedValue":700},{"ID":"asset6","color":"white","size":15,"owner":"Michel","appraisedValue":800}] |
Upgrading a smart contract(更新智能合约)
You can use the same Fabric chaincode lifecycle process to upgrade a chaincode that has already been deployed to a channel. Channel members can upgrade a chaincode by installing a new chaincode package and then approving a chaincode definition with the new package ID, a new chaincode version, and with the sequence number incremented by one. The new chaincode can be used after the chaincode definition is committed to the channel. This process allows channel members to coordinate on when a chaincode is upgraded, and ensure that a sufficient number of channel members are ready to use the new chaincode before it is deployed to the channel.
您可以使用相同的Fabric链码生命周期流程来升级已经部署到通道的链码。通道成员可以通过以下方式升级链码:安装新的链码包,然后批准这个具有新packageID、新链码版本以及序列号加1的链码定义。在链码定义被提交给通道后新的链码就可以被使用。此过程允许通道成员在升级链码时进行协调,并确保在将新链码部署到通道之前,有足够数量的通道成员准备使用新链码。
Channel members can also use the upgrade process to change the chaincode endorsement policy. By approving a chaincode definition with a new endorsement policy and committing the chaincode definition to the channel, channel members can change the endorsement policy governing a chaincode without installing a new chaincode package.
通道成员也可以使用这个更新流程来修改链码的背书策略。通过批准具有新背书策略的链码定义并将其提交给渠道,渠道成员可以更改背书策略而无需安装新的链码包。
To provide a scenario for upgrading the asset-transfer (basic) chaincode that we just deployed,let’s assume that Org1 and Org2 would like to install a version of the chaincode that is written in another language. They will use the Fabric chaincode lifecycle to update the chaincode version and ensure that both organizations have installed the new chaincode before it becomes active on the channel.
为了提供一个我们刚才部署的asset-transfer (basic) 链码升级的情景,让我们假设Org1和Org2想要安装一个通过其他语言编写的链码版本。他们会使用Fabric链码生命周期来更新链码的版本并且在新链码可用于通道之前确保所有的组织已经安装了新的链码。
We are going to assume that Org1 and Org2 initially installed the GO version of the asset-transfer (basic) chaincode, but would be more comfortable working with a chaincode written in JavaScript. The first step is to package the JavaScript version of the asset-transfer (basic) chaincode. If you used the JavaScript instructions to package your chaincode when you went through the tutorial, you can install new chaincode binaries by following the steps for packaging a chaincode written in Go or TypeScript.
我们假设Org1和Org2最初安装了asset-transfer (basic) GO版本的链码,但使用JavaScript编写的链码会更舒适。第一步就是打包JavaScript版本的asset-transfer (basic) 链码。
Issue the following commands from the test-network
directory to install the chaincode dependences.
在test-network
目录下运行下面的命令来安装链码的依赖。
1 | cd ../asset-transfer-basic/chaincode-javascript |
打包
You can then issue the following commands to package the JavaScript chaincode from the test-network
directory. We will set the environment variables needed to use the peer
CLI again in case you closed your terminal.
然后你可以在test-network
目录下运行下面的命令来打包JavaScript版本的链码。在运行命令之前先参考前面的内容来设置可以操作Org1的环境变量。
1 | peer lifecycle chaincode package basic_2.tar.gz --path ../asset-transfer-basic/chaincode-javascript/ --lang node --label basic_2.0 |
安装
We can now use the following command to install the new chaincode package on the Org1 peer.
你可以在Org1组织的peer节点通过下面的命令来安装一个新的链码包。
1 | peer lifecycle chaincode install basic_2.tar.gz |
The new chaincode package will create a new package ID. We can find the new package ID by querying our peer.
新的链码包会创建一个新的package ID,我们通过查询peer来获取新的package ID。
1 | peer lifecycle chaincode queryinstalled |
The queryinstalled
command will return a list of the chaincode that have been installed on your peer similar to this output.
queryinstalled
命令会返回你的peer已经安装的链码,输出类似如下:
1 | Installed chaincodes on peer: |
You can use the package label to find the package ID of the new chaincode and save it as a new environment variable. This output is for example only – your package ID will be different, so DO NOT COPY AND PASTE!
你可以把新的 package ID保存为一个新的环境变量。下面的命令只是一个例子,不要直接copy。
1 | export NEW_CC_PACKAGE_ID=basic_2.0:59cb45985332d79a903ef39d710eeb23a1c63bddaf8cd999481071457d22acbd |
批准链码定义
Org1 can now approve a new chaincode definition(Org1现在可以批准这个新的链码定义):
1 | peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem |
The new chaincode definition uses the package ID of the JavaScript chaincode package and updates the chaincode version. Because the sequence parameter is used by the Fabric chaincode lifecycle to keep track of chaincode upgrades, Org1 also needs to increment the sequence number from 1 to 2. You can use the peer lifecycle chaincode querycommitted command to find the sequence of the chaincode that was last committed to the channel.
新的链码定义使用JavaScript版本的链码包的packageID以及新的链码版本。由于Fabric链码生命周期使用序列号来跟踪链码升级,因此Org1还需要将序列号从1递增到2。你可以使用 peer lifecycle chaincode querycommitted命令来查询链码上次提交到通道的序列号。
We now need to install the chaincode package and approve the chaincode definition as Org2 in order to upgrade the chaincode. Run the following commands to operate the peer
CLI as the Org2 admin:
我们现在需要以Org2组织的身份来安装链码并且批准链码定义来更新链码,运行下面的命令来使用Org2组织的管理员进行操作:
1 | export CORE_PEER_LOCALMSPID="Org2MSP" |
其他组织安装链码
We can now use the following command to install the new chaincode package on the Org2 peer.
我们现在就可以使用下面的命令来安装新的链码包到Org2组织的peer上。
1 | peer lifecycle chaincode install basic_2.tar.gz |
批准链码定义
You can now approve the new chaincode definition for Org2.
我们现在可以为Org2组织批准这个新的链码定义。
1 | peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem |
Use the peer lifecycle chaincode checkcommitreadiness command to check if the chaincode definition with sequence 2 is ready to be committed to the channel:
使用peer lifecycle chaincode checkcommitreadiness 敏玲来检查序列号为2的链码定义是否已经准备好被提交到channel上:
1 | peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 2.0 --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json |
The chaincode is ready to be upgraded if the command returns the following JSON:
如果这个命令返回以下内容,说明已经准备好更新了:
1 | { |
The chaincode will be upgraded on the channel after the new chaincode definition is committed. Until then, the previous chaincode will continue to run on the peers of both organizations. Org2 can use the following command to upgrade the chaincode:
在新的链码定义提交后,通道上的链码将会升级。在此之前,先前的链码将继续在两个组织的peer上运行。Org2组织可以使用下面的命令来更新链码:
1 | peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 2.0 --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt |
A successful commit transaction will start the new chaincode right away. If the chaincode definition changed the endorsement policy, the new policy would be put in effect.
成功的提交的交易将立即启动新的链码。如果链码定义更改了背书策略,则新政策将生效。
You can use the docker ps
command to verify that the new chaincode has started on your peers:
你现在可以使用 docker ps
命令来验证新的链码已经在你的peer节点启动。
1 | docker ps |
If you used the --init-required
flag, you need to invoke the Init function before you can use the upgraded chaincode. Because we did not request the execution of Init, we can test our new JavaScript chaincode by creating a new car:
我们现在可以通过创建一个新的汽车来测试我们新的JavaScript版本的链码:
1 | peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateAsset","Args":["asset8","blue","16","Kelley","750"]}' |
You can query all the cars on the ledger again to see the new car:
你可以查询账本上所有的车来看新创建的car:
1 | peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}' |
You should see the following result from the JavaScript chaincode:
通过JavaScript版本的链码,你会看到下面的结果:
1 | [{"Key":"asset1","Record":{"ID":"asset1","color":"blue","size":5,"owner":"Tomoko","appraisedValue":300}},{"Key":"asset2","Record":{"ID":"asset2","color":"red","size":5,"owner":"Brad","appraisedValue":400}},{"Key":"asset3","Record":{"ID":"asset3","color":"green","size":10,"owner":"Jin Soo","appraisedValue":500}},{"Key":"asset4","Record":{"ID":"asset4","color":"yellow","size":10,"owner":"Max","appraisedValue":600}},{"Key":"asset5","Record":{"ID":"asset5","color":"black","size":15,"owner":"Adriana","appraisedValue":700}},{"Key":"asset6","Record":{"ID":"asset6","color":"white","size":15,"owner":"Michel","appraisedValue":800}},{"Key":"asset8","Record":{"ID":"asset8","Color":"blue","Size":"16","Owner":"Kelley","AppraisedValue":"750"}}] |
Clean up(清理)
When you are finished using the chaincode, you can also use the following commands to remove the Logspout tool.
当你使用链码结束之后,你可以通过下面的命令来移除Logspout tool。
1 | docker stop logspout |
You can then bring down the test network by issuing the following command from the test-network
directory:
你现在可以在test-network
目录下使用下面的命令来关闭测试网络:
1 | ./network.sh down |