如何将智能合约部署到通道——部署Fabric测试网络的实例
使用系统版本:Ubuntu 18.04
提示:任何命令错误都可以试试加sudo提升权限!!!
参考文章:官方文档
一、启动网络
1.1 进入测试网络目录
我们将从部署Fabric测试网络的实例开始。在开始之前,请确保已经完成了准备阶段并安装了示例,二进制文件和Docker映像,如未完成,可以参考超级账本Fabric 2.x 详细安装步骤及可能问题解决方式。
进入fabric-samples/test-network目录
cd ~/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network
1.2 恢复到已知的初始状态
使用以下命令结束所有活动或陈旧的Docker容器并删除以前生成的部件
sudo ./network.sh down
1.3 启动测试网络
sudo ./network.sh up createChannel
该createChannel命令创建一个以mychannel两个通道成员Org1和Org2命名的通道。该命令还将属于每个组织的peer节点加入通道。如果成功创建了网络和通道,则可以在日志中看到以下消息:
============Channel successfully joined================
二、设置Logspout(可选)
此步骤不是必需的,但是对于故障排除链码非常有用。
Fabric示例monitordocker.sh中的commercial-paper示例已包含用于安装和配置Logspout的脚本。
2.1 打开一个新的终端
2.2 进入fabric-samples/test-network目录
cd ~/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network
2.3 将monitordocker.sh脚本从commercial-paper示例复制到fabric-samples/test-network工作目录中
sudo cp ../commercial-paper/organization/digibank/configuration/cli/monitordocker.sh .
2.4 启动Logspout
sudo ./monitordocker.sh net_test
成功后可以看到类似于以下内容的输出:
Starting monitoring on all containers on the network net_test
Unable to find image 'gliderlabs/logspout:latest' locally
latest: Pulling from gliderlabs/logspout
188c0c94c7c5: Already exists
f76076d59b2f: Pull complete
d09edbff691c: Pull complete
Digest: sha256:2b70c1989a00a2775311e66aec8be6e2479deb0e0c0c0be603de1863f49027e8
Status: Downloaded newer image for gliderlabs/logspout:latest
1c6c61c50c02e45282d565c8177d81358945a1ab59065a822491ee88fcac1ad6
三、打包智能合约
注意:以下为由Go语言编写的智能合约打包步骤,JavaScript打包见第八节。
3.1 打开一个新的终端
3.2 安装chaincode依赖项
依赖项go.mod在fabric-samples/chaincode/fabcar/go目录中的文件中列出,该go.mod文件将Fabric合约API导入到智能合约包中。
cd ~/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/chaincode/fabcar/go
sudo GO111MODULE=on go mod vendor
3.3 返回到test-network所在目录
返回到test-network所在目录,以便可以将链码与其他网络部件打包在一起。
cd ../../../test-network
3.4 将bin目录中二进制文件添加到CLI路径
所需格式的链码包可以使用peer CLI创建,使用以下命令将这些二进制文件添加到你的CLI路径。
export PATH=${PWD}/../bin:$PATH
3.5 设置FABRIC_CFG_PATH为指向fabric-samples中的core.yaml文件
export FABRIC_CFG_PATH=$PWD/../config/
3.6 创建链码包
使用peer lifecycle chaincode package命令创建链码包。
sudo peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/ --lang golang --label fabcar_1
命令解释:此命令将在当前目录中创建一个名为basic.tar.gz的软件包。–lang标签用于指定链码语言,–path标签提供智能合约代码的位置,该路径必须是标准路径或相对于当前工作目录的路径,–label标签用于指定一个链码标签,该标签将在安装链码后对其进行标识。建议您的标签包含链码名称和版本。
现在,我们已经创建了链码包,我们可以在测试网络的对等节点上安装链码。
四、安装链码包
打包Fabcar智能合约后,我们可以在peer节点上安装链码。需要在将认可交易的每个peer节点上安装链码。因为我们将设置背书策略以要求来自Org1和Org2的背书,所以我们需要在两个组织的peer节点上安装链码:peer0.org1.example.com和peer0.org2.example.com。
4.1 Org1 peer节点安装链码
先在Org1 peer节点上安装链码。
- 设置以下环境变量,以Org1管理员的身份操作peer CLI。
export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051
- 使用 peer lifecycle chaincode install 命令在peer节点上安装链码。
sudo peer lifecycle chaincode install fabcar.tar.gz
- 如果命令成功,则peer节点将生成并返回包标识符。下一步,此包ID将用于通过链码。你应该看到类似于以下内容的输出:
2020-11-24 20:59:00.766 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nIfabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506\022\010fabcar_1" > 2020-11-24 20:59:00.775 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506
4.2 Org2 peer节点安装链码
- 设置以下环境变量,以Org2管理员的身份操作peer CLI。
export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051
- 使用 peer lifecycle chaincode install 命令在peer节点上安装链码。
sudo peer lifecycle chaincode install fabcar.tar.gz
- 注意:安装链码时,链码由peer节点构建。如果智能合约代码有问题,install命令将从链码中返回所有构建错误。
五、通过链码定义
安装链码包后,需要通过组织的链码定义。该定义包括链码管理的重要参数,例如名称,版本和链码认可策略。
如果组织已在其peer节点上安装了链码,则他们需要在其组织通过的链码定义中包括包ID。包ID用于将peer节点上安装的链码与通过的链码定义相关联,并允许组织使用链码来认可交易。
5.1 查询包ID
可以使用peer lifecycle chaincode queryinstalled命令来查询peer节点,从而找到链码的包ID。
sudo peer lifecycle chaincode queryinstalled
包ID是链码标签和链码二进制文件的哈希值的组合。每个peer节点将生成相同的包ID。你应该看到类似于以下内容的输出:
Installed chaincodes on peer:
Package ID: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506, Label: fabcar_1
通过链码时,我们将使用包ID,因此,将包ID保存为环境变量。将返回的包ID粘贴到下面的命令中。
注意:包ID对于所有用户而言都不相同,因此需要使用上一步中从命令窗口返回的包ID来完成此步骤。而不是直接赋值命令!!!
export CC_PACKAGE_ID=fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506
5.2 Org2通过链码定义
因为已经设置了环境变量为peer CLI作为Orig2管理员进行操作,所以我们可以以Org2组织级别将Fabcar的链码定义通过。使用 peer lifecycle chaincode approveformyorg命令通过链码定义:
sudo peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --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
5.3Org1通过链码定义
设置以下环境变量以Org1管理员身份运行:
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
Org1通过链码定义:
sudo peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --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
六、将链码定义提交给通道
使用peer lifecycle chaincode checkcommitreadiness命令来检查通道成员是否已批准相同的链码定义:
sudo peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --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
该命令将生成一个JSON映射,该映射显示通道成员是否批准了checkcommitreadiness命令中指定的参数:
{
"approvals": {
"Org1MSP": true,
"Org2MSP": true
}
}
由于作为通道成员的两个组织都同意了相同的参数,因此链码定义已准备好提交给通道。你可以使用peer lifecycle chaincode commit命令将链码定义提交到通道。commit命令还需要由组织管理员提交。
sudo peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --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
可以使用peer lifecycle chaincode querycommitted命令来确认链码定义已提交给通道。
sudo peer lifecycle chaincode querycommitted --channelID mychannel --name fabcar --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
如果将链码成功提交给通道,该querycommitted命令将返回链码定义的顺序和版本:
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
七、调用链码
sudo 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 fabcar --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":[]}'
如果命令成功执行,应该能够得到类似于以下的响应:
chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
还可以使用查询功能来读取由链码创建的汽车的集合:
sudo peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'
对查询的响应应为以下汽车列表:
[{
"Key":"CAR0","Record":{
"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},
{
"Key":"CAR1","Record":{
"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}},
{
"Key":"CAR2","Record":{
"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}},
{
"Key":"CAR3","Record":{
"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}},
{
"Key":"CAR4","Record":{
"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}},
{
"Key":"CAR5","Record":{
"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}},
{
"Key":"CAR6","Record":{
"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}},
{
"Key":"CAR7","Record":{
"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}},
{
"Key":"CAR8","Record":{
"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}},
{
"Key":"CAR9","Record":{
"make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]
八、升级智能合约
在第三节中安装的链码包是由Go语言写的,接下来我们升级为由JavaScript编写的链码。
-
从test-network目录发出以下命令以安装chaincode依赖项:
cd ../chaincode/fabcar/javascript # 没有安装npm记得自行安装,另外记得换国内源!!! # 另外国内更适合使用 cnpm # sudo npm install # 这里我使用了cnmp。使用nmp也可。 sudo cnmp install cd ../../../test-network
-
执行以下命令来打包test-network目录中的JavaScript链码:
# 如果你未关闭终端,以下环境变量可以不用设置 # 设置再次使用peer CLI所需的环境变量 export FABRIC_CFG_PATH=$PWD/../config/ export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp # 打包链码 sudo peer lifecycle chaincode package fabcar_2.tar.gz --path ../chaincode/fabcar/javascript/ --lang node --label fabcar_2 # 如果你未关闭终端,以下环境变量可以不用设置 # 运行以下命令,以Org1管理员的身份操作peer CLI export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 # 使用以下命令在Org1peer节点上安装新的链码包 sudo peer lifecycle chaincode install fabcar_2.tar.gz
-
新的链码包将创建一个新的包ID。可以通过查询peer节点来找到新的包ID:
sudo peer lifecycle chaincode queryinstalled
该queryinstalled命令将返回已在peer节点上安装的链码的列表:
Installed chaincodes on peer: Package ID: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506, Label: fabcar_1 Package ID: fabcar_2:760e754e45a8ecf4bcc654945ac4554bbdb793d63255b047b5b9a6199a004ae4, Label: fabcar_2
-
使用包标签找到新链码的包ID,并将其另存为新的环境变量:
export NEW_CC_PACKAGE_ID=fabcar_2:760e754e45a8ecf4bcc654945ac4554bbdb793d63255b047b5b9a6199a004ae4
-
现在,Org1可以通过新的链码定义:
sudo peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --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
-
切换为Org2来通过新的链码定义:
export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051 # 在Org2peer节点上安装新的链码包 sudo peer lifecycle chaincode install fabcar_2.tar.gz # 同意Org2的新链码定义 sudo peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --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
-
使用peer lifecycle chaincode checkcommitreadiness命令检查序列2的链码定义是否准备好提交给通道:
sudo peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --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
如果命令返回以下JSON,则表示链代码已准备好升级:
{ "Approvals": { "Org1MSP": true, "Org2MSP": true } }
-
提交新的链码定义后,链码将在通道上升级。在此之前,先前的链码将继续在两个组织的peer节点上运行。Org2可以使用以下命令来升级链码:
sudo peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --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
成功的提交事务将立即启动新的链码。如果链码定义更改了背书政策,则新政策将生效。
你可以使用以下命令来验证新链码已在你的peer节点上启动:docker pdocker ps
-
创建新车来测试新的JavaScript链代码
```bash sudo 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 fabcar --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":"createCar","Args":["CAR11","Honda","Accord","Black","Tom"]}' ```
-
你可以再次查询分类帐上的所有汽车以查看新汽车:
sudo peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'
-
你应该从JavaScript链代码中看到以下结果:
[{ "Key":"CAR0","Record":{ "make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}}, { "Key":"CAR1","Record":{ "make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}}, { "Key":"CAR11","Record":{ "color":"Black","docType":"car","make":"Honda","model":"Accord","owner":"Tom"}}, { "Key":"CAR2","Record":{ "make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}}, { "Key":"CAR3","Record":{ "make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}}, { "Key":"CAR4","Record":{ "make":"Tesla","model":"S","colour":"black","owner":"Adriana"}}, { "Key":"CAR5","Record":{ "make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}}, { "Key":"CAR6","Record":{ "make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}}, { "Key":"CAR7","Record":{ "make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}}, { "Key":"CAR8","Record":{ "make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}}, { "Key":"CAR9","Record":{ "make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]
-
九、清理
使用完链码后,你可以使用以下命令删除Logspout工具:
docker stop logspout
docker rm logspout
然后,你可以通过从test-network目录发出以下命令来关闭测试网络:
sudo ./network.sh down
来源:oschina
链接:https://my.oschina.net/u/4400107/blog/4749199