Fabric━━部署智能合约

根据官网教程v2.3.3版本,实践在通道中部署智能合约

启动测试网络

根据之前的操作,重新启动测试网络,这里使用-ca选项来生成证书

./network.sh up createChannel -ca

设置 Logspout

使用该logspout 工具查看来自一组 Docker 容器的聚合输出,用于在安装智能合约或调用智能合约时调试问题。

直接安装和配置(脚本位于fabric-samples):

cp ~/fabric-samples/commercial-paper/organization/digibank/configuration/cli/monitordocker.sh .
./monitordocker.sh fabric_test # 网络名称改为实际名称

部署链码到通道

Fabcar 链代码部署到通道

打包智能合约

Go

打包链码之前,需要安装链码依赖。注意GO111MODULE=on下安装依赖:

go mod vendor # 在链码目录chaincode/fabcar/go

配置环境变量

export PATH=${PWD}/../bin:$PATH # 在test-network目录
export FABRIC_CFG_PATH=$PWD/../config/ # for core.yaml

创建链码包

回到test_network目录,生成链码包:

peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/ --lang golang --label fabcar_1
  • 在当前目录创建一个压缩包fabcar.tar.gz
  • --label指定链码标签,唯一识别,使用链码名称_版本号

Java

先进入链码目录:

cd fabric-samples/chaincode/fabcar/java

如果使用Gradle, build.gradle中列举了使用的依赖包,安装:

./gradlew installDist

构建的智能合约位于 build 目录,回到test_network目录,生成链码包:

peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/java/build/install/fabcar --lang java --label fabcar_1

安装链码包

链码需要安装在需要为交易背书的所有节点上(实际执行的节点),也是有背书策略决定的。这里使用的背书策略是Org1 and Org2,需要在两个组织的节点上安装:

  • peer0.org1.example.com
  • peer0.org2.example.com

设置环境变量

以 Org1 admin操作:

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

安装链码

设置完环境变量后,直接在peer0.org1.example.com上安装链码:

peer lifecycle chaincode install fabcar.tar.gz

输出,返回链码的标志符:

2021-11-21 18:04:24.760 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nIfabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276\022\010fabcar_1" >
2021-11-21 18:04:24.765 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276

同样步骤在peer0.org2.example.com上安装链码:

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 # peer0.org2.example.com
----------------------------------------------
peer lifecycle chaincode install fabcar.tar.gz

链码是在安装链码时由节点构建的,如果智能合约代码有问题,安装命令将返回任何构建错误。

批准链码定义

安装链码包后,需要组织批准链码的定义,包括:链码名称、版本以及背书策略。链码包 ID 用于将安装在同级上的链码与已批准的链码定义相关联,并允许组织使用链码来背书交易。

链码部署前必须由即configtx.yaml中的Application/Channel/lifeycleEndorsement :指定策略,其默认策略是通道上大多数成员批准,才能在通道中使用该链码/部署链码。

查询安装的链码包ID

包 ID 是链码标签和链码二进制文件的哈希值的组合,每个peer将生成相同的包 ID:

peer lifecycle chaincode queryinstalled # peer0.org2.example.com
# output
Installed chaincodes on peer:
Package ID: fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276, Label: fabcar_1

使用环境变量保存:

export CC_PACKAGE_ID=fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276

批准定义是在组织级别,必须是admin管理员角色批准定义

批准定义

接着上述过程,是在peer0.org2.example.com上操作

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
  • --package-id 指定链码的ID
  • --sequence 记录链码定义或更新的次数
  • 可以提供--signature-policy指定背书策略

改变环境变量(以 Org1 admin操作),组织1批准:

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

说明:批准链码的定义是由组织的管理员角色完成的,然后批准会提交到排序服务,验证管理员的签名后分发到组织中的其他节点。尽管链码定义只是需要通道上的大多数(默认策略)成员批准即可,但是组织必须批准链码的定义后才能启动其节点上的链码—即不能执行链码/不能为交易进行背书(需要模拟执行)(对于安装的节点)。所有推荐通道成员在提交定义前都批准链码的定义。

提交链码定义到通道

只有足够的组织批准了链码的定义,一个组织才能将链码的定义提交到通道。

查询对链码定义的批准:只需要提供名称等,不需要--package-id

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

output:

{
	"approvals": {
		"Org1MSP": true,
		"Org2MSP": true
	}
}

提交链码

以组织管理员角色提交链码到通道:

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
  • 使用--peerAddresses来指定commit tx分发的节点

通过指定节点,以此查询对应链码的定义,由于组织的批准已经分发到组织中的各个节点,这里只需要随意指定组织中的peer节点,有足够多的组织批准定义后,交易就会提交到通道。

查看提交的链码定义

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

返回对应链码定义的序号和版本:

Committed chaincode definition for chaincode 'fabcar' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]

调用链码

将链码定义提交到通道后,链代码现在已准备好由客户端应用程序调用。注意:invoke 命令需要针对足够数量的对等节点来满足链码背书策略。

初始化

调用initLedger函数

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":[]}'

查询

使用query命令:得到链码函数执行后的背书结果,不会产生一次交易

peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'

升级智能合约

使用相同的 Fabric 链码生命周期流程来升级已部署到通道的链码,通道成员可以通过安装新的链码包,然后使用新的包 ID、新的链码版本和序列号加 1 来批准链码定义来升级链码。还可以使用升级过程来更改链码背书策略。

例如安装Java版本的链码包,先根据上面说明下载依赖

打包

../chaincode/fabcar/java/build/install/fabcar打包为fabcar_2.tar.gz:

export PATH=${PWD}/../bin:$PATHexport FABRIC_CFG_PATH=$PWD/../config/export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp peer lifecycle chaincode package fabcar_2.tar.gz --path ../chaincode/fabcar/javascript/ --lang java --label fabcar_2

安装链码包

peer0.org1.example.com节点安装,配置环境变量:

export CORE_PEER_TLS_ENABLED=trueexport CORE_PEER_LOCALMSPID="Org1MSP"export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crtexport CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport CORE_PEER_ADDRESS=localhost:7051

安装新的链码包:

peer lifecycle chaincode install fabcar_2.tar.gz

安装后会产生新的Package ID,同样使用queryinstalled查询节点上安装的所有链码:

peer lifecycle chaincode queryinstalled--------------------------------------------# outputInstalled chaincodes on peer:Package ID: fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276, Label: fabcar_1Package ID: fabcar_2:a268f4cf1971bebbf41204aad5375fdc2a8542f4cb5edb139803b33555901b7a, Label: fabcar_2

保存Package ID:

export NEW_CC_PACKAGE_ID=fabcar_2:a268f4cf1971bebbf41204aad5375fdc2a8542f4cb5edb139803b33555901b7a

批准定义

组织org1批准新链码的定义,注意版本号和序号增加:

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

在组织2中同样操作:

设置环境变量,安装链码,批准链码

export CORE_PEER_LOCALMSPID="Org2MSP"export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crtexport CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crtexport CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=localhost:9051----------------------------------------------------peer lifecycle chaincode install fabcar_2.tar.gz # 安装链码----------------------------------------------------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的链码定义是否可以准备提交到通道(是否得到大多数组织批准):

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

提交定义

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

新链码的定义一提交,通道上的链码就会升级,可以从docker ps运行的链码容器看到结果。

调用

如果使用 --init-required flag,在你使用链码前必须调用初始化函数。

调用createCar:

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"]}'

查询:

peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'

说明:升级后数据仍然存在,Go和Java中定义Car的字段名(colour/color)有的不一样,导致查询可能是null

链接

  1. https://hyperledger-fabric.readthedocs.io/zh_CN/latest/deploy_chaincode.html
posted @ 2021-11-24 14:02  qxxiao  阅读(316)  评论(0)    收藏  举报