fabric-sdk-java demo(TLS-enabled)
Posted adderhuang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了fabric-sdk-java demo(TLS-enabled)相关的知识,希望对你有一定的参考价值。
fabric-sdk-java demo(TLS-enabled)
使用fabric-sdk-java,实现向fabric区块链上存入数据摘要并查询最新的数据记录。
本实例使用单机fabric1.4.1网络,采用raft共识;拥有五个orderer节点,四个peer节点;使用docker部署;开启TLS;chaincode采用Java编写;fabric状态数据库为couchdb,使用了数据库索引;fabric-sdk-java依赖版本为1.4.1。
采用的fabric网络实例地址://download.csdn.net/download/weixin_43562234/12118778
采用https://blog.csdn.net/weixin_43562234/article/details/104053966这篇博文中的solo单机单节点网络,开启TLS也可以。
建议有一定fabric基础的同学食用。
借鉴IBM的相关说明:
https://developer.ibm.com/tutorials/hyperledger-fabric-java-sdk-for-tls-enabled-fabric-network/
如果使用过程中出现问题,可以在评论区留言。
注意事项
1.依赖
除需要添加必要的fabric-sdk-java的依赖之外,还需要添加以下依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative</artifactId>
<version>1.1.33.Fork15</version>
<classifier>${os.detected.classifier}</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
properties属性中添加:
<os.detected.classifier>windows-x86_64</os.detected.classifier>
我的pom.xml文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<java.version>1.8</java.version>
<grpc.version>1.11.0</grpc.version>
<httpclient.version>4.5.5</httpclient.version>
<os.detected.classifier>windows-x86_64</os.detected.classifier>
</properties>
<groupId>com.richfit</groupId>
<artifactId>fabric-sdk-java</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<name>fabric-sdk-java</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hyperledger.fabric-sdk-java/fabric-sdk-java -->
<dependency>
<groupId>org.hyperledger.fabric-sdk-java</groupId>
<artifactId>fabric-sdk-java</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--<!– https://mvnrepository.com/artifact/io.netty/netty-tcnative –>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative</artifactId>
<version>2.0.25.Final</version>
</dependency>-->
<!-- https://mvnrepository.com/artifact/io.netty/netty-tcnative -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative</artifactId>
<version>1.1.33.Fork15</version>
<classifier>${os.detected.classifier}</classifier>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>
2.域名
windows中需要修改hosts文件,不能直接使用虚拟机ip
hosts位置:
我添加了以下内容
192.168.43.66 peer0.org1.richfit.com
192.168.43.66 peer1.org1.richfit.com
192.168.43.66 peer0.org2.richfit.com
192.168.43.66 peer1.org2.richfit.com
192.168.43.66 orderer.richfit.com
192.168.43.66 orderer0.richfit.com
192.168.43.66 orderer1.richfit.com
192.168.43.66 orderer2.richfit.com
192.168.43.66 orderer3.richfit.com
192.168.43.66 orderer4.richfit.com
## 代码部分
代码结构
代码正文
1.App.class
package com.richfit.fabric.tls;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.richfit.fabric.tls.Business;
import org.hyperledger.fabric.sdk.BlockEvent.TransactionEvent;
import org.hyperledger.fabric.sdk.*;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.exception.ProposalException;
import org.hyperledger.fabric.sdk.security.CryptoSuite;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
/**
* @author adder
* @date 2020/1/20 15:43
*/
public class App {
private static SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws Exception {
Configurations configurations = new Configurations();
HFClient client = HFClient.createNewInstance();
//load parameters
String keyDir = configurations.loadConfigurations().getJsonObject("options").getString("privateKeyFolder");
String keyFile = getKeyFilesInDir(new File(keyDir)).toString();
String certFile = configurations.loadConfigurations().getJsonObject("options").getString("signedCert");
String userName = configurations.loadConfigurations().getJsonObject("options").getString("user_id");
String mspId = configurations.loadConfigurations().getJsonObject("options").getString("msp_id");
String channelName = configurations.loadConfigurations().getJsonObject("options").getString("channel_id");
String peerName = configurations.loadConfigurations().getJsonObject("options").getString("peer_server_hostname");
String peerURL = configurations.loadConfigurations().getJsonObject("options").getString("peer_url");
String ordererName = configurations.loadConfigurations().getJsonObject("options").getString("orderer_server_hostname");
String ordererURL = configurations.loadConfigurations().getJsonObject("options").getString("orderer_url");
//create user object
FabricUser user = new FabricUser(userName, mspId, keyFile, certFile);
//encryption suite
client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
client.setUserContext(user);
//create channel object
Channel channel = client.newChannel(channelName);
//create peer
String peerTLSCert = configurations.loadConfigurations().getJsonObject("options").getString("peer_tls_cacerts");
Properties peer_properties = new Properties();
peer_properties.put("pemBytes", Files.readAllBytes(Paths.get(peerTLSCert)));
peer_properties.setProperty("sslProvider", "openSSL");
peer_properties.setProperty("negotiationType", "TLS");
Peer peer = client.newPeer(peerName, peerURL,peer_properties);
channel.addPeer(peer);
/*//create EvenHub
String event_url = "grpcs://peer0.org1.richfit.com:7051"; // ensure that port is of event hub
EventHub eventHub = client.newEventHub(peerName, event_url, peer_properties);
channel.addEventHub(eventHub);*/
//orderer
String ordererTLSCert = configurations.loadConfigurations().getJsonObject("options").getString("orderer_tls_cacerts");
Properties orderer_properties = new Properties();
orderer_properties.put("pemBytes", Files.readAllBytes(Paths.get(ordererTLSCert)));
orderer_properties.setProperty("sslProvider", "openSSL");
orderer_properties.setProperty("negotiationType", "TLS");
Orderer orderer = client.newOrderer(ordererName, ordererURL,orderer_properties);
channel.addOrderer(orderer);
//init channel
channel.initialize();
//query
queryByChaincode(client,configurations,channel);
//insert
/*for (int i = 0; i <1; i++) {
Business business = new Business();
business.setBizUUID("test");
business.setBizType("test");
business.setFillPerson("test");
business.setSubmissionTim("test");
business.setReviewer("test");
business.setReviewOpinion("test");
business.setReviewPass("test");
business.setToGzwTime("test");
business.setRequestTime(time.format(new Date()));
business.setCount(i);
business.setRequestID("test");
String json = JSON.toJSONString(business);
insertBlockChain(client,configurations,channel,json);
}*/
}
/**
* @description query
* @params [client, configurations, channel]
* @return void
* @author adder
* @date 2020/1/20 14:23
*
*/
public static void queryByChaincode(HFClient client,Configurations configurations,Channel channel) throws FileNotFoundException, ProposalException, InvalidArgumentException, UnsupportedEncodingException {
String chaincodeName = configurations.loadConfigurations().getJsonObject("options").getString("chaincode_id");
ChaincodeID chaincodeID = ChaincodeID.newBuilder().setName(chaincodeName).build();
//build args
ArrayList<String> argsList = new ArrayList<>();
argsList.add("test");
argsList.add("test");
//build query request
QueryByChaincodeRequest request = client.newQueryProposalRequest();
request.setChaincodeID(chaincodeID);
request.setFcn("query");
request.setArgs(argsList);
Collection<ProposalResponse> responses = channel.queryByChaincode(request);
ProposalResponse response = (ProposalResponse) responses.toArray()[0];
//analyse response
if (response.getStatus().toString().equals("SUCCESS")){
System.out.println(response.getChaincodeActionResponseStatus());
String result = new String(response.getChaincodeActionResponsePayload(), StandardCharsets.UTF_8);
System.out.println(result);
JSONObject json = JSONObject.parseObject(result);
String returnCode = (String) json.get("returnCode");
System.out.println(returnCode);
}
}
/**
* @description
* @params [client, configurations, channel, message]
* @return void
* @author adder
* @date 2020/1/21 15:42
*
*/
public static void insertBlockChain(HFClient client,Configurations configurations,Channel channel,String message) throws FileNotFoundException, InvalidArgumentException, ProposalException, ExecutionException, InterruptedException {
String chaincodeName = configurations.loadConfigurations().getJsonObject("options").getString("chaincode_id");
ChaincodeID chaincodeID = ChaincodeID.newBuilder().setName(chaincodeName).build();
JSONObject msgJson = JSONObject.parseObject(message);
msgJson.put("blockTimeTamp",System.currentTimeMillis());
//build args
ArrayList<String> argsList = new ArrayList<>();
argsList.add(msgJson.toJSONString());
//build insert request
TransactionProposalRequest request = client.newTransactionProposalRequest();
request.setChaincodeLanguage(TransactionRequest.Type.JAVA);
request.setChaincodeID(chaincodeID);
request.setArgs(argsList);
request.setFcn("insert");
request.setProposalWaitTime(3000);
Collection<ProposalResponse> responses = channel.sendTransactionProposal(request);
for (ProposalResponse response : responses) {
if (response.getChaincodeActionResponseStatus()==200){
System.out.println("Successfully sent Proposal and received ProposalResponse: status:"+response.getChaincodeActionResponseStatus()+",TransactionInformation: "+response.getProposalResponse().getResponse().getPayload().toStringUtf8());
}
}
CompletableFuture<TransactionEvent> transactionEvent = channel.sendTransaction(responses);
TransactionEvent event = transactionEvent.get();
System.out.println("TransationID: "+event.getTransactionID());
if (event.isValid()){
System.out.println("Successfully committed the change to the ledger by the peer "+event.getPeer());
}
}
/**
* @description get private key from key dir
* @params [filePath]
* @return java.io.File
* @author adder
* @date 2020/1/20 11:02
*
*/
private static File getKeyFilesInDir(File filePath) {
File keyFile = null;
File[] listFiles = filePath.listFiles();
if(listFiles != null) {
for(File file:listFiles) {
if(file.isFile()) {
if(file.getName().endsWith("_sk")) {
keyFile = file;
break;
}
}
}
}
return keyFile;
}
}
2.Business.class
package com.richfit.fabric.tls;
import lombok.Data;
/**
* @author adder
* @date 2020/1/20 15:43
*/
@Data
public class Business {
public String getRequestID() {
return requestID;
}
public void setRequestID(String requestID) {
this.requestID = requestID;
}
private String requestID;
private String bizUUID;
private String bizType;
private String fillPerson;
private String submissionTim;
private String reviewer;
private String reviewOpinion;
private String reviewPass;
private String toGzwTime;
private int count;
private String requestTime;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getBizUUID() {
return bizUUID;
}
public void setBizUUID(String bizUUID) {
this.bizUUID = bizUUID;
}
public String getBizType() {
return bizType;
}
public void setBizType(String bizType) {
this.bizType = bizType;
}
public String getFillPerson() {
return fillPerson;
}
public void setFillPerson(String fillPerson) {
this.fillPerson = fillPerson;
}
public String getSubmissionTim() {
return submissionTim;
}
public void setSubmissionTim(String submissionTim) {
this.submissionTim = submissionTim;
}
public String getReviewer() {
return reviewer;
}
public void setReviewer(String reviewer) {
this.reviewer = reviewer;
}
public String getReviewOpinion() {
return reviewOpinion;
}
public void setReviewOpinion(String reviewOpinion) {
this.reviewOpinion = reviewOpinion;
}
public String getReviewPass() {
return reviewPass;
}
public void setReviewPass(String reviewPass) {
this.reviewPass = reviewPass;
}
public String getToGzwTime() {
return toGzwTime;
}
public void setToGzwTime(String toGzwTime) {
this.toGzwTime = toGzwTime;
}
public String getRequestTime() {
return requestTime;
}
public void setRequestTime(String requestTime) {
this.requestTime = requestTime;
}
}
3.Configurations.class
package com.richfit.fabric.tls;
import org.yaml.snakeyaml.Yaml;
import javax.json.Json;
import javax.json.JsonObject;
import java.io.*;
import java.util.Map;
/**
* @author adder
* @date 2020/1/20 15:43
*/
public class Configurations {
/**
* @description
* @params []
* @return javax.json.JsonObject
* @author adder
* @date 2020/1/24 13:03
*
*/
public JsonObject loadConfigurations() throws FileNotFoundException {
String configPath = "src/main/java/com/richfit/fabric/tls/configure/configure.yml";
InputStream stream = new FileInputStream(new File(configPath));
Yaml yaml = new Yaml();
Map<String,Object> configYaml = yaml.load(stream);
JsonObject configJSON = Json.createObjectBuilder(configYaml).build();
return configJSON;
}
}
4.FabricUser.class
package com.richfit.fabric.tls;
import org.hyperledger.fabric.sdk.Enrollment;
import org.hyperledger.fabric.sdk.User;
import org.hyperledger.fabric.sdk.identity.X509Enrollment;
import org.hyperledger.fabric.sdk.security.CryptoPrimitives;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PrivateKey;
import java.util.Set;
/**
* @author adder
* @date 2020/1/20 15:43
*/
public class FabricUser implements User {
private String name;
private String mspId;
private Enrollment enrollment;
private String keyFile;
private String certFile;
FabricUser(String name, String mspId, String keyFile, String certFile) {
this.name = name;
this.mspId = mspId;
this.keyFile=keyFile;
this.certFile=certFile;
try{
enrollment=loadFromPemFile(keyFile, certFile);
}catch(Exception ex){
ex.printStackTrace();
}
}
private Enrollment loadFromPemFile(String keyFile,String certFile) throws Exception{
byte[] keyPem = Files.readAllBytes(Paths.get(keyFile)); //load private key text
byte[] certPem = Files.readAllBytes(Paths.get(certFile)); //load certificate text
CryptoPrimitives suite = new CryptoPrimitives(); //load the cryptography suite
PrivateKey privateKey = suite.bytesToPrivateKey(keyPem); //convert private key text to object
return new X509Enrollment(privateKey,new String(certPem)); //create X509Enrollment object
}
@Override
public String getName() {
return name;
}
@Override
public String getMspId() {
return mspId;
}
@Override
public Enrollment getEnrollment() {
return enrollment;
}
@Override
public String getAccount() {
return null;
}
@Override
public String getAffiliation() {
return null;
}
@Override
public Set<String> getRoles() {
return null;
}
public String getKeyFile() {
return keyFile;
}
public void setKeyFile(String keyFile) {
this.keyFile = keyFile;
}
public String getCertFile() {
return certFile;
}
public void setCertFile(String certFile) {
this.certFile = certFile;
}
}
6.configure.yml
options:
user_id: "Admin@org1.richfit.com"
msp_id: "Org1MSP"
channel_id: "mychannel"
chaincode_id: "mycc"
peer_url: "grpcs://peer0.org1.richfit.com:7051"
orderer_url: "grpcs://orderer0.richfit.com:8050"
privateKeyFolder: "src/main/java/com/richfit/fabric/tls/configure/crypto-config/peerOrganizations/org1.richfit.com/users/Admin@org1.richfit.com/msp/keystore"
signedCert: "src/main/java/com/richfit/fabric/tls/configure/crypto-config/peerOrganizations/org1.richfit.com/users/Admin@org1.richfit.com/msp/signcerts/Admin@org1.richfit.com-cert.pem"
peer_tls_cacerts: "src/main/java/com/richfit/fabric/tls/configure/crypto-config/peerOrganizations/org1.richfit.com/peers/peer0.org1.richfit.com/tls/ca.crt"
orderer_tls_cacerts: "src/main/java/com/richfit/fabric/tls/configure/crypto-config/ordererOrganizations/richfit.com/orderers/orderer0.richfit.com/tls/ca.crt"
peer_server_hostname: "peer0.org1.richfit.com"
orderer_server_hostname: "orderer0.richfit.com"
以上是关于fabric-sdk-java demo(TLS-enabled)的主要内容,如果未能解决你的问题,请参考以下文章