一、手动升级链码
1.1. 准备工作
Fabric链码生命周期也可以用于升级已部署到通道的链码。通道成员可以通过安装新的链码包来升级链码,然后使用新的包ID、新的链码版本和递增1的序列号批准链码定义。新的链码可以在链码定义提交到通道之后使用。
注:通过使用新的背书策略批准链码定义并将链码定义提交给通道,通道成员也可以使用升级过程来更改链码背书策略,而无需安装新的链码包。
本节使用peer lifecycle chaincode命令升级已部署到Fabric测试网络的通道中的Go版本的asset-transfer-basic链码。升级链码之前先启动网络、创建通道并部署链码:
cd ~/hyfa/fabric-samples/test-network
./network.sh down
./network.sh up createChannel
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
将二进制文件和配置文件的路径加入环境变量:
export PATH=$PATH:${PWD}/../bin
export FABRIC_CFG_PATH=${PWD}/../config/
1.2. 流程
这里假设JS版本的basic链码更好,因此下面使用手动部署JS版本的basic链码来代表整个升级链码的过程,这样避免了对链码项目源代码的改动。更真实的场景是部署了Go版本的basic链码后,对该链码项目的源代码做了修改(譬如增加了一个新功能),然后再使用修改后的同一项目进行升级。
首先转到JS版本的asset-transfer-basic链码文件夹:
pushd ../asset-transfer-basic/chaincode-javascript
在当前目录中运行以下命令:
npm install
回到test-network文件夹中的工作目录:
popd
使用peer lifecycle chaincode package命令创建新的链码包:
peer lifecycle chaincode package basic_2.tar.gz --path ../asset-transfer-basic/chaincode-javascript/ --lang node --label basic_2.0.1
使用setOrgEnv.sh脚本设置环境变量作为Org1操作peer CLI:
export $(./setOrgEnv.sh Org1 | xargs)
使用命令peer lifecycle chaincode install在Org1的peer节点上安装链码:
peer lifecycle chaincode install basic_2.tar.gz
peer lifecycle chaincode queryinstalled
将新的包ID和测试网络的排序服务的TLS CA证书的路径设置为环境变量:
export NEW_CC_PACKAGE_ID=$(peer lifecycle chaincode calculatepackageid basic_2.0.tar.gz) && echo $NEW_CC_PACKAGE_ID
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
使用peer lifecycle chaincode approveformyorg命令为Org1批准链码定义:
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 2.0.1 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile $ORDERER_CA
使用setOrgEnv.sh脚本设置环境变量作为Org2操作peer CLI:
export $(./setOrgEnv.sh Org2 | xargs)
使用命令peer lifecycle chaincode install在Org2的peer节点上安装链码:
peer lifecycle chaincode install basic_2.tar.gz
peer lifecycle chaincode queryinstalled
使用peer lifecycle chaincode approveformyorg命令为Org2批准链码定义:
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 2.0.1 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile $ORDERER_CA
使用peer lifecycle chaincode checkcommitreadiness命令来检查通道成员是否已经批准了相同的链码定义:
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 2.0.1 --sequence 2 --tls --cafile $ORDERER_CA --output json
使用peer lifecycle chaincode commit命令由组织管理员向通道提交链码定义:
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 2.0.1 --sequence 2 --tls --cafile $ORDERER_CA --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 CLI与测试网络进行交互,验证智能合约的功能是否可用,以及在升级链码之前提交到账本中的数据在升级后是否一致。
修改账本:
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile $ORDERER_CA -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"]}'
查询账本:
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
1.3. 补充说明
从Go版本的basic链码升级为Java版本不会出错,但是在升级后使用智能合约的功能时会有一些问题,表现为升级之前提交到账本中的信息在升级后无法成功查询:
这是因为两个版本的链码在Asset的JSON格式中使用不同的Key值。
Go版本的basic链码的Key值都是大写字母开头:
而Java版本的basic链码的Key值都是小写字母开头:
当链码的各个版本创建的资产的键不兼容时,就会返回一个空值的资产。