fabric Java SDK是Fabric区块链官方提供的用于Java应用开发的SDK,其链接如下:https://github.com/hyperledger/fabric-sdk-java
fabric-geteway 也是Java SDK的一种,提供了更加便捷的API,官网地址为:https://github.com/hyperledger/fabric-gateway-java
fabric-gateway的使用:
1、导入maven
<dependency>
<groupId>org.hyperledger.fabric</groupId>
<artifactId>fabric-gateway-java</artifactId>
<version>2.0.0</version>
</dependency>
2、将链上的crypto-config文件复制到resource
3、编写 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/383afd7e044f36903e4149d28398cc38e489739998ece0fc36b19de0dc986523_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/3d30d033c6084a9478478e4e355ba49b51fdc2f55cc0c04e6792a017f274227a_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.10.128: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/11c4ce44268e8f217e077f87cd1fc58c94e1f664bdfd6297f1455d2ec1fb0646_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.10.128: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.10.128: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.10.128: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.10.128: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"
}
]
}
}
}
3、fabric.config.properties ,其中的通道名称,链码名称以及私钥路径根据实际情况
# 网络配置文件路径 networkConfigPath = src/main/resources/connection.json # 用户证书路径 certificatePath = src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem # 用户私钥路径 privateKeyPath = src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/59157e7b19fe2eacad4baca256296e93022c51e5bc0102eec4e0b23f54db85f8_sk # 通道名字 channelName = mychannel # 链码名字 contractName = mylocks
资源下的文件结构如下:


4、sdk的调用,代码编写:
package com.example.fabric.demo.test;
import org.hyperledger.fabric.gateway.*;
import org.hyperledger.fabric.sdk.Peer;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.EnumSet;
import java.util.Properties;
/**
* @Description:
* @author: caib
* @Date: 2021/07/15/11:27
*/
public class SdkDemo {
public static void main(String[] args) {
try {
//获取相应参数
Properties properties = new Properties();
InputStream inputStream = SdkDemo.class.getResourceAsStream("/fabric.config.properties");
properties.load(inputStream);
String networkConfigPath = properties.getProperty("networkConfigPath");
String channelName = properties.getProperty("channelName");
String contractName = properties.getProperty("contractName");
//使用org1中的user1初始化一个网关wallet账户用于连接网络
String certificatePath = properties.getProperty("certificatePath");
X509Certificate certificate = readX509Certificate(Paths.get(certificatePath));
String privateKeyPath = properties.getProperty("privateKeyPath");
PrivateKey privateKey = getPrivateKey(Paths.get(privateKeyPath));
Wallet wallet = Wallets.newInMemoryWallet();
wallet.put("user1", Identities.newX509Identity("Org1MSP",certificate,privateKey));
//根据connection.json 获取Fabric网络连接对象
Gateway.Builder builder = Gateway.createBuilder()
.identity(wallet, "user1")
.networkConfig(Paths.get(networkConfigPath));
//连接网关
Gateway gateway = builder.connect();
//获取通道
Network network = gateway.getNetwork(channelName);
//获取合约对象
Contract contract = network.getContract(contractName);
//查询现有资产
//注意更换调用链码的具体函数
byte[] queryAllAssets = contract.evaluateTransaction("queryAllLocks");
System.out.println("所有资产:"+new String(queryAllAssets, StandardCharsets.UTF_8));
// 增加新的资产
byte[] invokeResult = contract.createTransaction("initLock")
.setEndorsingPeers(network.getChannel().getPeers(EnumSet.of(Peer.PeerRole.ENDORSING_PEER)))
.submit("L00A", "TEST001", "");
System.out.println(new String(invokeResult, StandardCharsets.UTF_8));
//查询更新后的资产
byte[] queryAllAssetsAfter = contract.evaluateTransaction("queryAllLocks");
System.out.println("更新资产:"+new String(queryAllAssetsAfter, StandardCharsets.UTF_8));
} catch (Exception e) {
e.printStackTrace();
}
}
private static X509Certificate readX509Certificate(final Path certificatePath) throws IOException, CertificateException {
try (Reader certificateReader = Files.newBufferedReader(certificatePath, StandardCharsets.UTF_8)) {
return Identities.readX509Certificate(certificateReader);
}
}
private static PrivateKey getPrivateKey(final Path privateKeyPath) throws IOException, InvalidKeyException, IOException {
try (Reader privateKeyReader = Files.newBufferedReader(privateKeyPath, StandardCharsets.UTF_8)) {
return Identities.readPrivateKey(privateKeyReader);
}
}
}
Fabric-sdk-java
以下需用到crypto-config的资源
1、引入依赖,如果以及引入了gateway的依赖,此步骤可省略
<dependency> <groupId>org.hyperledger.fabric-sdk-java</groupId> <artifactId>fabric-sdk-java</artifactId> <version>1.4.7</version> </dependency>
2、编写LocalUser,实现User接口
/**
* @Description:
* @author: caib
* @Date: 2021/07/15/14:11
*/
public class LocalUser implements User { //实现User接口
private String name;
private String mspId;
private Enrollment enrollment;
LocalUser(String name, String mspId ,String keyFile, String certFile ) throws Exception {
this.name = name;
this.mspId = mspId;
this.enrollment = loadFromPemFile(keyFile,certFile);
}
private Enrollment loadFromPemFile(String keyFile, String certFile) throws Exception {
//载入私钥PEM文本
byte[] keyPem = Files.readAllBytes(Paths.get(keyFile));
//载入证书PEM文本
byte[] certPem = Files.readAllBytes(Paths.get(certFile));
//载入密码学套件
CryptoPrimitives suite = new CryptoPrimitives();
//将PEM文本转换为私钥对象
PrivateKey privateKey = suite.bytesToPrivateKey(keyPem);
//创建并返回X509Enrollment对象
return new X509Enrollment(privateKey,new String(certPem));
}
@Override
public String getName() {
return name;
}
@Override
public Set<String> getRoles() {
return null;
}
@Override
public String getMspId() {
return mspId;
}
@Override
public Enrollment getEnrollment() {
return enrollment;
}
@Override
public String getAccount() {
return null;
}
@Override
public String getAffiliation() {
return null;
}
}
3、sdk调用
/**
* @Description:
* @author: caib
* @Date: 2021/07/15/15:51
*/
public class Chaincode {
private static final String Crypto_Config_Path = "D:\\ideaProjects\\fabric-sdk-demo\\src\\main\\resources\\crypto-config\\";
private static final String CA_Pemfile = Crypto_Config_Path+"peerOrganizations\\org1.example.com\\ca\\ca.org1.example.com-cert.pem";
private String adminKeyFile = Crypto_Config_Path+"peerOrganizations\\" +
"org1.example.com\\users\\Admin@org1.example.com\\msp\\keystore\\383afd7e044f36903e4149d28398cc38e489739998ece0fc36b19de0dc986523_sk";
private String adminCertFile = Crypto_Config_Path+"peerOrganizations\\org1.example.com\\users\\Admin@org1.example.com\\" +
"msp\\signcerts\\Admin@org1.example.com-cert.pem";
private HFClient client;
private Channel channel;
HFClient InitClient() throws Exception{
this.client = HFClient.createNewInstance();
client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
client.setUserContext(new LocalUser("admin", "Org1MSP", adminKeyFile, adminCertFile));
return client;
}
void CreateChannelIns(String channelName) throws Exception{
this.channel = client.newChannel(channelName);
Properties proper;
proper = loadTLSFile("peerOrganizations\\org1.example.com\\peers\\peer0.org1.example.com\\msp\\tlscacerts\\tlsca.org1.example.com-cert.pem", "peer0.org1.example.com");
Peer peer = client.newPeer("peer0.org1.example.com","grpcs://192.168.10.128:7051", proper);
channel.addPeer(peer);
proper = loadTLSFile("ordererOrganizations\\example.com\\orderers\\orderer.example.com\\msp\\tlscacerts\\tlsca.example.com-cert.pem", "orderer.example.com");
Orderer orderer = client.newOrderer("orderer1.example.com","grpcs://192.168.10.128:7050", proper);
channel.addOrderer(orderer);
channel.initialize();
}
/**
* 为Fabric网络中节点配置TLS根证书
*
* @param rootTLSCert 根证书路径
* @param hostName 节点域名
* @return
* @throws IOException
*/
private static Properties loadTLSFile(String rootTLSCert, String hostName) throws IOException {
Properties properties = new Properties();
properties.put("pemBytes", Files.readAllBytes(Paths.get( Crypto_Config_Path + rootTLSCert)));
properties.setProperty("sslProvider", "openSSL");
properties.setProperty("negotiationType", "TLS");
properties.setProperty("trustServerCertificate", "true");
properties.setProperty("hostnameOverride", hostName);
return properties;
}
void Query() throws Exception{
QueryByChaincodeRequest req = this.client.newQueryProposalRequest();
ChaincodeID cid = ChaincodeID.newBuilder().setName("mylocks").build();
req.setChaincodeID(cid);
req.setFcn("queryAllUsers");
req.setArgs("a");
ProposalResponse[] rsp = this.channel.queryByChaincode(req).toArray(new ProposalResponse[0]);
System.out.format("rsp message => %s\n",rsp[0].getProposalResponse().getResponse().getPayload().toStringUtf8());
}
void Query(String chainCodeName, String funcName , String... args) throws Exception{
QueryByChaincodeRequest req = this.client.newQueryProposalRequest();
ChaincodeID cid = ChaincodeID.newBuilder().setName(chainCodeName).build();
req.setChaincodeID(cid);
req.setFcn(funcName);
req.setArgs(args);
// req.setChaincodeEndorsementPolicy();
ProposalResponse[] rsp = this.channel.queryByChaincode(req).toArray(new ProposalResponse[0]);
System.out.format("rsp message => %s\n",rsp[0].getProposalResponse().getResponse().getPayload().toStringUtf8());
}
void Invode () throws Exception {
QueryByChaincodeRequest req = this.client.newQueryProposalRequest();
ChaincodeID cid = ChaincodeID.newBuilder().setName("mylocks").build();
//提交链码交易
TransactionProposalRequest req2 = client.newTransactionProposalRequest();
req2.setChaincodeID(cid);
req2.setFcn("inc");
req2.setArgs("10");
Collection<ProposalResponse> rsp2 = channel.sendTransactionProposal(req2);
BlockEvent.TransactionEvent event = channel.sendTransaction(rsp2).get();
System.out.format("txid: %s\n", event.getTransactionID());
System.out.format("valid: %b\n", event.isValid());
}
}
