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()); } }