java版本的智能合约部署到fabric区块链测试网络

发布时间 2023-11-20 16:19:01作者: Nichols1205

开发智能合约并进行部署和更新操作

在之前的文章中我们可以成功启动测试网络并进行了相关测试,现在我们需要进行智能合约的编写操作,并将其部署到测试网络中进行相关测试。本节智能合约代码采取Java语言进行编写,代码及相关部署参考(https://www.bilibili.com/video/BV1DR4y1M74B/?spm_id_from=333.999.0.0&vd_source=6a98bdea1567b90c8bfe074c52c68444)。

注:本节主要关注于部署和更新操作,完整代码获取方式末尾会介绍。

首先编写Java版本的链码,参考链接(fabric-samples/asset-transfer-basic/chaincode-java at main · hyperledger/fabric-samples · GitHub

本文以电脑类为例,代码结构如下:

需要注意的是,Computer类前面需要接@DataType注解,ComputerContract类需要接@Contract和@Default注解,引用ContractInterface接口,如下:

在合约代码中我们设计了初始化数据、创建数据、更新数据、查询数据、删除数据和查询所有数据等方法,编写完成后打包成jar包:

打包后在target文件夹中会出现jar包:

打包完成后我们还是不能安装链码的,安装java版本的链码需要hyperledger/fabric-javaenv镜像,之前我们拉取的镜像没有这个,因此我们需要先拉取该镜像:

docker pull hyperledger/fabric-javaenv

在fabric-samples下面创建一个chaincode文件夹,并在该文件夹中创建一个自定义名称的文件夹表明合约(这里使用computer-contract),将jar包放到该文件夹中:

mkdir chaincode
cd chaincode
mkdir computer-contract
# 操作完成后回到test-network目录
cd ../../test-network
# 启动测试网络并创建频道
./network.sh up createChannel

打包智能合约

首先将bin目录中二进制文件添加到CLI路径

export PATH=${PWD}/../bin:$PATH

设置FABRIC_CFG_PATH为指向fabric-samples中的core.yaml文件

export FABRIC_CFG_PATH=$PWD/../config/

创建链码包

peer lifecycle chaincode package computer-contract.tar.gz --path ../chaincode/computer-contract/ --lang java --label computer-contract_v1

分析一下命令:

该命令创建了一个tar.gz包,--path指向链码所在文件夹路径,--lang指定语言为Java语言,--label指定链码标签进行标识,建议包含链码名称和版本。

安装链码

Org1 peer节点安装链码

# 设置环境变量
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节点上安装链码。
peer lifecycle chaincode install computer-contract.tar.gz 

成功信息:

Org2 peer节点安装链码

# 设置环境变量
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

# 使用 peer lifecycle chaincode install 命令在peer节点上安装链码。
peer lifecycle chaincode install basic.tar.gz

成功结果同上。

通过链码定义

查询包ID

peer lifecycle chaincode queryinstalled

# 结果:Installed chaincodes on peer:
# Package ID: computer-contract_v1:165fd7b10262e3d88bcdeebd227d1266f8b0eee3b46549b6e0b94540b2ee323b, Label: computer-contract_v1

包ID是链码标签和链码二进制文件的哈希值的组合。每个peer节点将生成相同的包ID。这里需要保存好包ID,后续命令会使用,每个人的不同。将包ID设为环境变量:

# 替换为自己的
export CC_PACKAGE_ID=computer-contract_v1:165fd7b10262e3d88bcdeebd227d1266f8b0eee3b46549b6e0b94540b2ee323b

因为刚设置了org2的环境变量,因此先让org2批准链码:

peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name computer-contract --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

成功信息:

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

# 批准链码
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name computer-contract --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命令来检查通道成员是否已批准相同的链码定义:

peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name computer-contract --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

结果如下:

由于作为通道成员的两个组织都同意了相同的参数,因此链码定义已准备好提交给通道。你可以使用peer lifecycle chaincode commit命令将链码定义提交到通道。commit命令还需要由组织管理员提交。

peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name computer-contract --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命令来确认链码定义已提交给通道。

peer lifecycle chaincode querycommitted --channelID mychannel --name computer-contract --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

结果如下,包含版本等信息:

调用链码

# 调用初始化方法
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 computer-contract --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":[]}'

# 调用查询所有方法
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 computer-contract --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":"getAllComputer","Args":[]}'

查询结果:

有所有的初始化后的信息,最后调用一个修改方法,其他方法自行测试。

先看一下初始化方法:

@Transaction
    public void initLedger(final Context context) {
        ChaincodeStub stub = context.getStub();
        createComputer(context,"computer-0","macOS","apple","A17","19999");
        createComputer(context,"computer-1","huawei","huawei","8090","29999");
        createComputer(context,"computer-2","lenovo","lianxiang","7090","999");
        createComputer(context,"computer-3","tianxuan","huashuo","7091","10000");
        createComputer(context,"computer-4","rog","huashuo","8070","19999");
        createComputer(context,"computer-5","waixingren","daier","8080","20000");
    }

可以看到电脑名为“waixingren”的电脑的key为“computer-5”

# 修改电脑名为waixingren的价格为21000
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 computer-contract --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":"updateComputer","Args":["computer-5","waixingren","daier","8080","21000"]}'

显示修改成功,查询一下所有的看看。

也是成功修改了。至于更新链码跟上述基本一致,在此强调一下需要修改的部分,首先是标识label进行修改,改为v2或其他能表示新版本的符号,随后version改为2.0,--sequence后面改为2(递增),包ID的环境变量设为NEW_CC_PACKAGE_ID或其他能表示的符号,后需用到该变量的地方对应进行改变,反正不难,就酱。可能有遗漏的需要修改的地方,大家可以参照官方文档或大佬的文档(官方:https://hyperledger-fabric.readthedocs.io/en/latest/deploy_chaincode.html 大佬:https://gitee.com/kernelHP/hyperledger-fabric-contract-java-demo/blob/master/doc)。

文中java代码获取方式:关注“李让行人软件开发分享”,回复“测试网部署智能合约Java代码”获取,点个关注不迷路!
本文参考链接:

fabric官网:将智能合约部署到通道 — hyperledger-fabricdocs 主要文档

b站up:https://www.bilibili.com/video/BV1DR4y1M74B/?spm_id_from=333.999.0.0&vd_source=6a98bdea1567b90c8bfe074c52c68444;

https://gitee.com/kernelHP/hyperledger-fabric-contract-java-demo/tree/master/doc

原文:“李让行人软件开发分享”公众号博文