fabric-gateway-java 调用虚拟机上的fabric链码,以fabcar为例
作为学习的记录。我是在虚拟机上搭建了fabric网络和通道,并部署了官方示例fabcar链码,现在想在windows上通过fabric-gateway-java 实现对fabric上链码的调用。
fabric的版本是2.4.0,编译器是IDEA,代码基于springboot框架。
fanric环境的搭建、test-network及通道的创建、链码的部署这里不再赘述。
首先导入如下依赖:
-
<dependency>
-
<groupId>org.hyperledger.fabric-sdk-java</groupId>
-
<artifactId>fabric-sdk-java</artifactId>
-
<version>1.4.7</version>
-
</dependency>
-
-
<dependency>
-
<groupId>org.hyperledger.fabric</groupId>
-
<artifactId>fabric-gateway-java</artifactId>
-
<version>2.2.0</version>
-
</dependency>
代码的结构,我的结构是这样的:
首先,我们需要将test-network建立好之后,文件夹test-neteork/organizations下的orderorganizations和peerorganizations文件从虚拟机中复制到代码中,我是放在了resources/crypto-config目录下。
随后写的是链接建立文件,connection.json。
-
{
-
"name": "basic-network",
-
"version": "1.0.0",
-
"dependencies": {
-
},
-
"client": {
-
"organization": "Org1",
-
"connection": {
-
"timeout": {
-
"peer": {
-
"endorser": "300"
-
},
-
"orderer": "300"
-
}
-
}
-
},
-
"channels": {
-
"mychannel": {
-
"orderers": [
-
"orderer.example.com"
-
],
-
"peers": {
-
"peer0.org1.example.com": {
-
"endorsingPeer": true,
-
"chaincodeQuery": true,
-
"ledgerQuery": true,
-
"eventSource": true
-
},
-
"peer0.org2.example.com": {
-
"endorsingPeer": true,
-
"chaincodeQuery": true,
-
"ledgerQuery": true,
-
"eventSource": true
-
}
-
}
-
}
-
},
-
"organizations": {
-
"Org1": {
-
"mspid": "Org1MSP",
-
"peers": [
-
"peer0.org1.example.com"
-
],
-
"certificateAuthorities": [
-
"ca-org1"
-
],
-
"adminPrivateKeyPEM": {
-
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/priv_sk"
-
},
-
"signedCertPEM": {
-
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem"
-
}
-
},
-
"Org2": {
-
"mspid": "Org2MSP",
-
"peers": [
-
"peer0.org2.example.com"
-
],
-
"certificateAuthorities": [
-
"ca-org2"
-
],
-
"adminPrivateKeyPEM": {
-
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/priv_sk"
-
},
-
"signedCertPEM": {
-
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem"
-
}
-
}
-
},
-
"orderers": {
-
"orderer.example.com": {
-
"url": "grpcs://192.168.16.129:7050",
-
"mspid": "OrdererMSP",
-
"grpcOptions": {
-
"ssl-target-name-override": "orderer.example.com",
-
"hostnameOverride": "orderer.example.com"
-
},
-
"tlsCACerts": {
-
"path": "src/main/resources/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt"
-
},
-
"adminPrivateKeyPEM": {
-
"path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/keystore/priv_sk"
-
},
-
"signedCertPEM": {
-
"path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/Admin@example.com-cert.pem"
-
}
-
}
-
},
-
"peers": {
-
"peer0.org1.example.com": {
-
"url": "grpcs://192.168.16.129:7051",
-
"grpcOptions": {
-
"ssl-target-name-override": "peer0.org1.example.com",
-
"hostnameOverride": "peer0.org1.example.com",
-
"request-timeout": 120001
-
},
-
"tlsCACerts": {
-
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
-
}
-
},
-
"peer0.org2.example.com": {
-
"url": "grpcs://192.168.16.129:9051",
-
"grpcOptions": {
-
"ssl-target-name-override": "peer0.org2.example.com",
-
"hostnameOverride": "peer0.org2.example.com",
-
"request-timeout": 120001
-
},
-
"tlsCACerts": {
-
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
-
}
-
}
-
},
-
"certificateAuthorities": {
-
"ca-org1": {
-
"url": "https://192.168.16.129:7054",
-
"grpcOptions": {
-
"verify": true
-
},
-
"tlsCACerts": {
-
"path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"
-
},
-
"registrar": [
-
{
-
"enrollId": "admin",
-
"enrollSecret": "adminpw"
-
}
-
]
-
},
-
"ca-org2": {
-
"url": "https://192.168.16.129:8054",
-
"grpcOptions": {
-
"verify": true
-
},
-
"tlsCACerts": {
-
"path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem"
-
},
-
"registrar": [
-
{
-
"enrollId": "admin",
-
"enrollSecret": "adminpw"
-
}
-
]
-
}
-
}
-
}
-
其中的ip换成自己虚拟机的ip,文件路径根据自己存放的orderorganizations和peerorganizations的目录进行调整。
之后配置properties文件:
-
fabric.networkConnectionConfigPath = src/main/resources/connection.json
-
-
fabric.certificatePath = src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem
-
-
fabric.privateKeyPath = src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/priv_sk
指定了,connection,json文件的位置,和后续链接用到的私钥和证书目录。
之后就可以开始写代码了hh。
首先是配置类的代码,主要功能是从properties文件中读取需要的参数值
-
import lombok.Data;
-
import org.springframework.boot.context.properties.ConfigurationProperties;
-
import org.springframework.context.annotation.Configuration;
-
-
-
-
-
-
public class HyperLedgerFabricProperties {
-
-
-
String networkConnectionConfigPath;
-
String certificatePath;
-
String privateKeyPath;
-
-
-
}
之后还是一个配置类,用来获取gateway.
-
import lombok.AllArgsConstructor;
-
import lombok.extern.slf4j.Slf4j;
-
import org.hyperledger.fabric.gateway.Gateway;
-
import org.hyperledger.fabric.gateway.Identities;
-
import org.hyperledger.fabric.gateway.Wallet;
-
import org.hyperledger.fabric.gateway.Wallets;
-
import org.springframework.context.annotation.Bean;
-
import org.springframework.context.annotation.Configuration;
-
-
import java.io.BufferedReader;
-
import java.nio.charset.StandardCharsets;
-
import java.nio.file.Files;
-
import java.nio.file.Paths;
-
import java.security.PrivateKey;
-
import java.security.cert.X509Certificate;
-
import java.util.concurrent.TimeUnit;
-
-
-
-
-
public class HyperLedgerConfig {
-
-
final HyperLedgerFabricProperties hyperLedgerFabricProperties;
-
-
-
public Gateway gateway() throws Exception {
-
-
-
BufferedReader certificateReader = Files.newBufferedReader(Paths.get(hyperLedgerFabricProperties.getCertificatePath()), StandardCharsets.UTF_8);
-
-
X509Certificate certificate = Identities.readX509Certificate(certificateReader);
-
-
BufferedReader privateKeyReader = Files.newBufferedReader(Paths.get(hyperLedgerFabricProperties.getPrivateKeyPath()), StandardCharsets.UTF_8);
-
-
PrivateKey privateKey = Identities.readPrivateKey(privateKeyReader);
-
-
Wallet wallet = Wallets.newInMemoryWallet();
-
wallet.put("user1" , Identities.newX509Identity("Org1MSP", certificate , privateKey));
-
-
-
Gateway.Builder builder = Gateway.createBuilder()
-
.identity(wallet , "user1")
-
.networkConfig(Paths.get("src/main/resources/connection.json"));
-
-
Gateway gateway = builder.connect();
-
-
-
log.info("=========================================== connected fabric gateway {} " , gateway);
-
-
return gateway;
-
}
-
}
没有问题以后,就是controller的代码,这里就以queryAllCars命令为例。
-
import com.谷歌.common.collect.Maps;
-
import lombok.AllArgsConstructor;
-
import lombok.extern.slf4j.Slf4j;
-
import org.apache.commons.codec.binary.StringUtils;
-
import org.hyperledger.fabric.gateway.*;
-
import org.springframework.context.annotation.Bean;
-
import org.springframework.context.annotation.Configuration;
-
import org.springframework.web.bind.annotation.GetMapping;
-
import org.springframework.web.bind.annotation.PathVariable;
-
import org.springframework.web.bind.annotation.RequestMapping;
-
import org.springframework.web.bind.annotation.RestController;
-
-
import javax.servlet.http.HttpServletRequest;
-
import java.io.BufferedReader;
-
import java.nio.charset.StandardCharsets;
-
import java.nio.file.Files;
-
import java.nio.file.Paths;
-
import java.security.PrivateKey;
-
import java.security.cert.X509Certificate;
-
import java.util.Map;
-
import java.util.concurrent.TimeoutException;
-
-
-
-
-
-
-
public class Fabriccontroller {
-
final Gateway gateway;
-
-
-
-
-
public Map<String, Object> queryall() throws ContractException {
-
-
Map<String, Object> result = Maps.newConcurrentMap();
-
Contract contract = getContract();
-
byte[] car = contract.evaluateTransaction("queryAllCars");
-
-
result.put("result", StringUtils.newStringUtf8(car));
-
-
-
return result;
-
}
-
-
private Network getNetwork(){
-
return gateway.getNetwork("mychannel");
-
}
-
-
private Contract getContract(){
-
return getNetwork().getContract("fabcar");
-
}
-
-
-
}
最后getnetwork()和getcontract()的参数分别是通道的名称和链码的名称,根据自己的情况做调整。
最后,运行主启动类。
-
import org.springframework.boot.SpringApplication;
-
import org.springframework.boot.autoconfigure.SpringBootApplication;
-
import org.springframework.boot.context.properties.EnableConfigurationProperties;
-
-
-
-
public class FabricJdkApplication {
-
-
public static void main(String[] args) {
-
SpringApplication.run(FabricJdkApplication.class, args);
-
}
-
-
}
注意:一定要在linux中先运行起来测试网络并安装好链码后才能够连接成功。
浏览器测试一下,返回查询数据
还有一点注意的是,当我们这一次工作结束,关闭了区块链网络。下一次在重启网络,要更新代码中的 orderorganizations和peerorganizations,替换成新网络的属性文件,否则自然是链接不上的。
学习中参考了B站“老哥没有饿意”的视频。作为初学者,如有问题和错误,欢迎大家的讨论和指正。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfjajai
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01