fabric-simple(0)序中说明了fabric-gateway-java基于fabric-sdk-java`做的二次开发。这里只介绍基于fabric-gateway-java项目进行开发。
以fabric-samples/asset-transfer-basic/application-gateway-java为例进行修改说明。
github:
https://github.com/hyperledger/fabric-gateway-java
开发环境:java 1.8
编辑器:idea
第1步:resources目录新建文件夹crypto-config,从fabric测试环境中fabric-samples/test-network/下的organizations整个目录拷贝到``crypto-config`下。
第2步:POM文件中引入fabric-gateway-javay的依赖:
第3步:resources目录新建文件connection.json,用于fabric网络的配置,具体内容:
{
"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.example.com"
]
},
"Org2": {
"mspid": "Org2MSP",
"peers": [
"peer0.org2.example.com"
],
"certificateAuthorities": [
"ca.org1.example.com"
]
}
},
"orderers": {
"orderer.example.com": {
"url": "grpcs://127.0.0.1:7050",
"mspid": "OrdererMSP",
"grpcOptions": {
"ssl-target-name-override": "orderer.example.com",
"hostnameOverride": "orderer.example.com"
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt"
}
}
},
"peers": {
"peer0.org1.example.com": {
"url": "grpcs://127.0.0.1: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/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
}
},
"peer0.org2.example.com": {
"url": "grpcs://127.0.0.1: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/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
}
}
},
"certificateAuthorities": {
"ca.org1.example.com": {
"url": "https://127.0.0.1:7054",
"grpcOptions": {
"verify": true
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/organizations/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"
},
"registrar": [
{
"enrollId": "admin",
"enrollSecret": "adminpw"
}
]
},
"ca.org1.example.com": {
"url": "https://127.0.0.1:8054",
"grpcOptions": {
"verify": true
},
"tlsCACerts": {
"path": "src/main/resources/crypto-config/organizations/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem"
},
"registrar": [
{
"enrollId": "admin",
"enrollSecret": "adminpw"
}
]
}
}
}
注意:其中127.0.0.1中的IP地址为远程测试环境的IP。这样才能与远程链码建立网络连接。
第4步:设置各种参数:
// 网络配置文件的路径
private static final Path NETWORK_CONFIG_PATH = Paths.get("src", "main", "resources", "connection.json");
// 证书和私钥的路径
private static final Path cryptoPath = Paths.get("src", "main", "resources", "crypto-config", "organizations",
"peerOrganizations", "org1.example.com");
private static final Path certPath = cryptoPath.resolve(Paths.get("users", "[email protected]", "msp", "signcerts", "[email protected]"));
private static final Path keyDirPath = cryptoPath.resolve(Paths.get("users", "[email protected]", "msp", "keystore", "priv_sk"));
private static final Path tlsCertPath = cryptoPath.resolve(Paths.get("peers", "peer0.org1.example.com", "tls", "ca.crt"));
第5步:具体编码:
1)读取证书:
private static X509Certificate readX509Certificate(final Path certificatePath) {
X509Certificate x509Certificate=null;
try (Reader certificateReader = Files.newBufferedReader(certificatePath, StandardCharsets.UTF_8)) {
x509Certificate = Identities.readX509Certificate(certificateReader);
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} finally {
return x509Certificate;
}
}
2)读取私钥:
private static PrivateKey getPrivateKey(final Path privateKeyPath) {
PrivateKey privateKey = null;
try (Reader privateKeyReader = Files.newBufferedReader(privateKeyPath, StandardCharsets.UTF_8)) {
privateKey = Identities.readPrivateKey(privateKeyReader);
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} finally {
return privateKey;
}
}
3)根据证书私钥来获取身份,配置钱包:
wallet.put("user", Identities.newX509Identity("Org1MSP", certificate, privateKey));
4)配置连接网关:
GatewayImpl.Builder builder = (GatewayImpl.Builder) Gateway.createBuilder()
.identity(wallet, "user")
.networkConfig(NETWORK_CONFIG_PATH);
gateway = builder.connect();
5)获取mychannel通道的网络:
Network network = gateway.getNetwork("mychannel");
6)获取链码lbasic:
Contract contract = network.getContract("basic");
7)可以调用链码的各种借口:
初始化账本的代码:
private static void initLedger(Contract contract) {
try {
contract.submitTransaction("InitLedger");
System.out.println("initLedger successfully");
} catch (ContractException e) {
e.printStackTrace();
} catch (TimeoutException e){
e.printStackTrace();
}catch (InterruptedException e){
e.printStackTrace();
}
}
private static void getAllAssets(Contract contract) {
try {
byte[] queryAllAssets = contract.evaluateTransaction("GetAllAssets");
System.out.println("所有资产:" + prettyJson(queryAllAssets));
} catch (ContractException e) {
e.printStackTrace();
}
}
private static void readAssetById(Contract contract,String assetId) {
try {
byte[] evaluateResult = contract.evaluateTransaction("ReadAsset", assetId);
System.out.println("ID:"+ assetId +"\n资产的信息:" + prettyJson(evaluateResult));
}catch (ContractException e){
e.printStackTrace();
}
}
调用结果:
代码详见:
https://gitee.com/linghufeixia/fabric-simple
application-gateway-java