首页 > 编程语言 >java版本的智能合约部署到fabric区块链测试网络

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

时间:2023-11-20 16:22:06浏览次数:40  
标签:java fabric -- PWD computer 链码 区块 com example

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

在之前的文章中我们可以成功启动测试网络并进行了相关测试,现在我们需要进行智能合约的编写操作,并将其部署到测试网络中进行相关测试。本节智能合约代码采取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/[email protected]/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/[email protected]/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/[email protected]/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

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

标签:java,fabric,--,PWD,computer,链码,区块,com,example
From: https://www.cnblogs.com/nichols1205/p/17844247.html

相关文章

  • 1688 商品详情 APIERP 选品专用 API 接口 Python Java
    1688商品详情API接口是一种程序化的接口,它允许商家或开发者使用自己的编程技能,对1688平台上的商品信息进行查询、获取和更新。通过这个API接口,商家可以根据自己的需求,获取商品的详细信息,如价格、库存、描述、图片等,从而更好地进行营销和客户服务。使用1688商品详情API接......
  • 秦疆的Java课程笔记:33 流程控制 Scanner
    之前学习的基本语法中并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,可以获取用户的输入。java.util.Scanner是Java5的新特性,可以通过Scanner类来获取用户的输入。基本语法:Scanners=newScanner(System.in);通过Scanner类的nexr()与nextLine()方法获取输入的......
  • Java 删除PDF页面 (免费工具分享)
    对PDF页面的增删通常需要借助专门的工具,而这些工具一般需要付费才能使用。那么我们可以通过Java代码免费实现这一功能吗?答案是肯定的。这篇文章就教大家如何使用一个免费的国产Java库来删除PDF中的指定页面或者删除PDF中的空白页。 使用Java快速删除PDF中的指定页面1.首先,我......
  • PHP调用java的jar包方法
    制作创建测试的jar包打开idea,文件->新建项目->java模块->选择SDK->项目名称为calcutil在src中新建名为Calc.java,内容如下publicclassCalc{publicstaticintadd(inta,intb){returna+b;}}配置工件:文件->项目结构->工件->添加->jar......
  • c# AES 解密 快手店铺 java的AES加密方法
    JAVA版本的解密:/***参数说明:*message:带解密的密文*privateKey:加密密钥**/StringdecodeMessage=PlatformEventSecurityUtil.decode(message,privateKey);/***方法详情**/privatestaticfinalStringCIPHER_ALGORITHM="AES/CBC/PKCS5Padding"......
  • 这才是java对象正解
    这才是Java对象正解 在深入讨论对象之前,让我们先明确对对象和实例的理解。什么是对象?对象(Object)是内存中分配的实际数据结构,它包含了数据和方法。在Java中,对象是类的一个实例,可以是具体类(例如Child)的实例,也可以是抽象类或接口的实现类的实例。对象是具体的实体,它具有特......
  • 什么是Java中的process_reaper线程?
     随着时间的推移,我在应用程序中获得了成百上千个这样的process_reaper线程。有人知道这些可能是什么吗?它们似乎是在我的Runtime.exec()中使用的,但是我在finally语句中销毁了我的进程,但它们仍然会出现屏幕截图:http://www.dropmocks.com/mBxM5Processproc=null;Str......
  • 掌握Java面向对象OOP篇(一)
    掌握面向对象OOP篇(一)边学边记--OOP(ObjectOrientatedPrograming)1.为什么要引入面向对象?原因:封装、继承、多态举个例子理解面向对象代码的好处:比如:我们有一个实际问题,假设现在一个宠物店有两只小狗,第一只叫做小白,年龄2岁,白色;第二只叫做小红,年龄3岁,红色;现在我们的宠物......
  • JAVA分批处理数据简单示例
    功能描述在处理业务时,经常遇到需要分批次处理数据的场景,例如有105条数据,每次推送20条,分批次推送最后不足20条数据时,一次性推送全部剩余数据DEMO示例packageshiguang.test;importjava.util.ArrayList;importjava.util.List;publicclassBatchProcessingExample{......
  • Java 学生管理系统
    需求:​ 采取控制台的方式去书写学生管理系统。分析:初始菜单:"-------------欢迎来到学生管理系统----------------""1:添加学生""2:删除学生""3:修改学生""4:查询学生""5:退出""请输入您的选择:"学生类:​ 属性:id、姓名、年龄、家庭住址添加功能:​ 键盘录入每一个学生信......