hyperledger/fabric的java客户端
以1.4版本举例
准备connection_profile
各个orderers节点的tlsca证书其实是一样的,peers节点也是一样的情况
---
#
# Copyright Fujitsu Australia Software Technology, IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
#
name: Network-Config
version: "1.0.0"
client:
# 客户端使用Org1的Admin用户的认证信息
organization: Org1
connection:
timeout:
peer:
endorser: 300
orderer: 300
organizations:
Org1:
mspid: Org1MSP
peers:
- peer1.org1.example.com
- peer2.org1.example.com
- peer3.org1.example.com
adminPrivateKey:
# Org1的Admin用户私钥来源:
# crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/xxxxxxxxxxxxxxxxxxxxxxxxx_sk
pem: |
-----BEGIN PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-----END PRIVATE KEY-----
signedCert:
# Org1的Admin用户公钥证书来源:
# crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem
pem: |
-----BEGIN CERTIFICATE-----
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
-----END CERTIFICATE-----
# 列出可用channel
channels:
mychannel1:
orderers:
- orderer1.example.com
- orderer2.example.com
- orderer3.example.com
peers:
peer1.org1.example.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer2.org1.example.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer3.org1.example.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
mychannel2:
orderers:
- orderer1.example.com
- orderer2.example.com
- orderer3.example.com
peers:
peer1.org1.example.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer2.org1.example.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer3.org1.example.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
orderers:
orderer1.example.com:
url: grpcs://10.10.0.1:7050
grpcOptions:
ssl-target-name-override: orderer1.example.com
hostnameOverride: orderer1.example.com
grpc.keepalive_time_ms: 300000
grpc.keepalive_timeout_ms: 20000
tlsCACerts:
# orderer1的https认证CA来源:
# crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
pem: |
-----BEGIN CERTIFICATE-----
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
-----END CERTIFICATE-----
orderer2.example.com:
url: grpcs://10.10.0.2:7050
grpcOptions:
ssl-target-name-override: orderer2.example.com
hostnameOverride: orderer2.example.com
grpc.keepalive_time_ms: 300000
grpc.keepalive_timeout_ms: 20000
tlsCACerts:
pem: |
-----BEGIN CERTIFICATE-----
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
-----END CERTIFICATE-----
orderer3.example.com:
url: grpcs://10.10.0.3:7050
grpcOptions:
ssl-target-name-override: orderer3.example.com
hostnameOverride: orderer3.example.com
grpc.keepalive_time_ms: 300000
grpc.keepalive_timeout_ms: 20000
tlsCACerts:
pem: |
-----BEGIN CERTIFICATE-----
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
-----END CERTIFICATE-----
peers:
peer1.org1.example.com:
url: grpcs://10.10.1.1:7051
grpcOptions:
ssl-target-name-override: peer1.org1.example.com
hostnameOverride: peer1.org1.example.com
grpc.http2.keepalive_time: 60
tlsCACerts:
# Org1的peer1的https认证CA来源:
# crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp/tlscacerts/tlsca.org1.example.com-cert.pem
pem: |
-----BEGIN CERTIFICATE-----
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
-----END CERTIFICATE-----
peer2.org1.example.com:
url: grpcs://10.10.1.2:7051
grpcOptions:
ssl-target-name-override: peer2.org1.example.com
hostnameOverride: peer2.org1.example.com
grpc.http2.keepalive_time: 60
tlsCACerts:
pem: |
-----BEGIN CERTIFICATE-----
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
-----END CERTIFICATE-----
peer3.org1.example.com:
url: grpcs://10.10.1.3:7051
grpcOptions:
ssl-target-name-override: peer3.org1.example.com
hostnameOverride: peer3.org1.example.com
grpc.http2.keepalive_time: 60
tlsCACerts:
pem: |
-----BEGIN CERTIFICATE-----
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
-----END CERTIFICATE-----
fabric-sdk-java使用demo
初始化客户端
private HFClient client;
private NetworkConfig netConfig;
@PostConstruct
public void initClient() {
netConfig = NetworkConfig.fromYamlFile(Paths.get(pemDir, CONNECTION_PROFILE).toFile());
// 创建HFClient实例
client = HFClient.createNewInstance();
client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
client.setUserContext(netConfig.getClientOrganization().getPeerAdmin());
}
连接到channel
private synchronized Channel getChannel(String name) {
Channel channel = client.getChannel(name);
if (channel != null) {
return channel;
}
// 创建通道实例
// 实例已缓存入client的内部map
channel = client.loadChannelFromConfig(name, netConfig);
channel.initialize();
return channel;
}
query链码
为使用protobuf为出入参进行序列化,需配置protobuf-maven-plugin来自动把proto定义编译为java对象
public void testChainCodeQuery() {
Channel channel = getChannel("mychannel1");
ChaincodeID cid = ChaincodeID.newBuilder().setName("chaincode1").build();
// query链码
QueryByChaincodeRequest query = client.newQueryProposalRequest();
query.setChaincodeID(cid);
query.setFcn("queryFunction1");
// 假设查询参数是简单的单据号
query.setArgs("xxxxxxx");
Collection<ProposalResponse> rsp = channel.queryByChaincode(query);
ProposalResponse pr = rsp.iterator().next();
if (pr.getStatus().equals(Status.SUCCESS)) {
// QueryResult是protobuf定义的对象,如果智能合约里是用protobuf进行的序列化,则这里就要用protobuf进行反序列化
QueryResult result = QueryResult.parseFrom(pr.getProposalResponse().getResponse().getPayload());
log.info(result.toString());
return;
}
}
invoke链码
public void testChainCodeInvoke() {
Channel channel = getChannel("mychannel1");
ChaincodeID cid = ChaincodeID.newBuilder().setName("chaincode1").build();
// InvokeParam是protobuf定义的对象,复杂的提交参数需要protobuf进行序列化
InvokeParam.Builder builder = InvokeParam.newBuilder();
builder.setXXX(XXX);
builder.setYYY(YYY);
builder.setZZZ(XXX);
builder.setLoanNo(LOAN);
TransactionProposalRequest invoke = client.newTransactionProposalRequest();
invoke.setChaincodeID(cid);
invoke.setFcn("invokeFunction1");
invoke.setArgs(builder.build().toByteArray());
// 让endorsing peer验证请求,并返回新的区块信息
Collection<ProposalResponse> rsp = channel.sendTransactionProposal(invoke);
ProposalResponse pr = rsp.iterator().next();
if (!pr.getStatus().equals(Status.SUCCESS)) {
log.info("invokeFunction1 failed: {}", pr.getProposalResponse().getResponse().getMessage());
return;
}
// 正式提交新区块给orderer
TransactionEvent event = channel.sendTransaction(rsp).get();
log.info("Transaction ID: {}", event.getTransactionID());
}