概述
fabric官方提供的java sdk包含两个项目fabric-sdk-java和fabric-gateway-java,前者用于与fabric网络交互的低级API(比如创建channel、加入channel、安装chaincode等),fabric-sdk-java还包含了fabric-ca client的实现,后者为高级API(主要针对chaincode的调用),fabric-gateway-java使用了fabric-sdk-java的api。

一、fabric-gateway-java的基本用法
依赖:

<dependency>
<groupId>org.hyperledger.fabric</groupId>
<artifactId>fabric-gateway-java</artifactId>
<version>2.0.0</version>
</dependency> 
官方示例:

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.TimeoutException;

import org.hyperledger.fabric.gateway.Contract;
import org.hyperledger.fabric.gateway.ContractException;
import org.hyperledger.fabric.gateway.Gateway;
import org.hyperledger.fabric.gateway.Network;
import org.hyperledger.fabric.gateway.Wallet;
import org.hyperledger.fabric.gateway.Wallets;

class Sample {
public static void main(String[] args) throws IOException {

// 载入一个存在的持有用户身份的钱包,用于访问fabric网络
Path walletDirectory = Paths.get(“wallet”);
Wallet wallet = Wallets.newFileSystemWallet(walletDirectory);

//Path为fabric网络配置文件的路径
Path networkConfigFile = Paths.get(“connection.json”);

// 配置gateway连接用于访问fabric网络(用户和网络配置文件)
Gateway.Builder builder = Gateway.createBuilder()
.identity(wallet, “user1”)
.networkConfig(networkConfigFile);

// 创建一个gateway连接
try (Gateway gateway = builder.connect()) {

//根据gateway获取指定的通道网络
Network network = gateway.getNetwork(“mychannel”);
//根据chaincode名称从通道网络中获取智能合约
Contract contract = network.getContract(“fabcar”);

// 提交事务 存储到账本
byte[] createCarResult = contract.createTransaction(“createCar”)
.submit(“CAR10”, “VW”, “Polo”, “Grey”, “Mary”);
System.out.println(new String(createCarResult, StandardCharsets.UTF_8));

// 从账本中查询状态
byte[] queryAllCarsResult = contract.evaluateTransaction(“queryAllCars”);
System.out.println(new String(queryAllCarsResult, StandardCharsets.UTF_8));

} catch (ContractException | TimeoutException | InterruptedException e) {
e.printStackTrace();
}
}

这里抽象出了钱包、网关的概念,网关即API调用的入口,每个钱包可以存放多个用户身份,构造网关的时候指定钱包其中一个用户。
怎么构建一个钱包,可以参考fabric-gateway-java/src/test/java/org/hyperledger/fabric/gateway/TestUtils.java
钱包就是一个目录,里面存放了一个一个的身份,每个身份包含了mspId,证书类型、证书和私钥,参考fabric-gateway-java/src/test/fixtures/test-wallet/x509-v1.id,下面一个身份文件示例:

{“version”:1,”mspId”:”mspId”,”type”:”X.509″,”credentials”:{“certificate”:”—–BEGIN CERTIFICATE—–\nMIIBWjCB3qADAgECAgYBbvXSw4QwDQYJKoZIhvcNAQELBQAwEzERMA8GA1UEAwwI\nSm9obiBEb2UwHhcNMTkxMjEwMTYzNzQwWhcNMTkxMTI2MDA1NTUxWjATMREwDwYD\nVQQDDAhKb2huIERvZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABBIV2OGF/VkRcQTf\n5NjLpQMIW+kc6VmBdpd7+YJ4CrpxtCISiMcDf4LxQ2QdVhkM0FSiYCFLxnDOg8u6\nTm+uKVzlH0HEKkPycoDk784dcvyXiUuWuo6ZHXaCQJfEHNldPzANBgkqhkiG9w0B\nAQsFAANoADBlAjEAoNys0S+/R9/w3bUMwohRN7NuIh2JYmxy3oEafunF4LaNaRd8\ndG9gLBn/7LQZGUu7AjBLQQMV0GPZCNl6JN4TZyxcARxDCmpiuIAzwZuFRYpaAVTO\npJgR6ICTZ0Ko3rz4cT4=\n—–END CERTIFICATE—–\n”,”privateKey”:”—–BEGIN PRIVATE KEY—–\nMIG/AgEAMBAGByqGSM49AgEGBSuBBAAiBIGnMIGkAgEBBDAAL3tEAlZDEPZiOxZp\njjGncTzZtLBbtO30tqT+WdTbRqwF9OpGLBAgsbzzo9nhqBagBwYFK4EEACKhZANi\nAAQSFdjhhf1ZEXEE3+TYy6UDCFvpHOlZgXaXe/mCeAq6cbQiEojHA3+C8UNkHVYZ\nDNBUomAhS8ZwzoPLuk5vrilc5R9BxCpD8nKA5O/OHXL8l4lLlrqOmR12gkCXxBzZ\nXT8=\n—–END PRIVATE KEY—–\n”}}
1
fabric网络配置文件示例:

{
“name”: “basic-network”,
“version”: “1.0.0”,
“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
}
}
}
},
“organizations”: {
“Org1”: {
“mspid”: “Org1MSP”,
“peers”: [
“peer0.org1.example.com”
],
“certificateAuthorities”: [
“ca.example.com”
]
}
},
“orderers”: {
“orderer.example.com”: {
“url”: “grpc://localhost:7050”
}
},
“peers”: {
“peer0.org1.example.com”: {
“url”: “grpc://localhost:7051”
}
},
“certificateAuthorities”: {
“ca.example.com”: {
“url”: “http://localhost:7054”,
“caName”: “ca.example.com”
}
}

二、fabric-sdk-java的基本用法
这里主要摘取了End2endLifecycleIT.java的代码进行分析,根据这个demo学习sdk如何使用,最后总结主要用到的类和方法。

chaincode详见:
https://github.com/hyperledger/fabric-sdk-java/blob/v2.0.0/src/test/fixture/sdkintegration/gocc/sample_11/src/github.com/example_cc/example_cc.go

场景:有两个组织peerOrg1,peerOrg2。首先创建两个sdk client,根据client创建channel,将peer加入通道,打包、审批、提交chaincode,最后调用chaincode。

依赖:

<repositories>
<repository>
<id>snapshots-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

<dependencies>
<!– 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>2.0.0-SNAPSHOT</version>
</dependency>
</dependencies> 
1. 创建 client实例org1Client
HFClient org1Client = HFClient.createNewInstance();
org1Client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
1
2
创建了与fabric网络交互的sdk client实例org1Client,设置了加密套件。

2. 创建org1Channel,Orderer和Org1的peer加入Channel
SampleOrg org1 = testConfig.getIntegrationTestsSampleOrg(“peerOrg1”);
Channel org1Channel = constructChannel(CHANNEL_NAME, org1Client, org1, true);
1
2
testConfig从properties文件读取key/value配置,根据key/value组装SampleOrg、SampleUser对象。
从testConfig获取peerOrg1的配置,并调用constructChannel创建channel。

constructChannel方法:

SampleUser peerAdmin = myOrg.getPeerAdmin();
client.setUserContext(peerAdmin);

Collection<Orderer> orderers = new LinkedList<>();

for (String orderName : myOrg.getOrdererNames()) {

Properties ordererProperties = testConfig.getOrdererProperties(orderName);
orderers.add(client.newOrderer(orderName, myOrg.getOrdererLocation(orderName),
ordererProperties));
}

//Just pick the first orderer in the list to create the channel.
Orderer anOrderer = orderers.iterator().next();
orderers.remove(anOrderer);

String path = TEST_FIXTURES_PATH + “/sdkintegration/e2e-2Orgs/” + testConfig.getFabricConfigGenVers() + “/” + name + “.tx”;

ChannelConfiguration channelConfiguration = new ChannelConfiguration(new File(path));

Channel newChannel = client.newChannel(name, anOrderer, channelConfiguration, client.getChannelConfigurationSignature(channelConfiguration, peerAdmin));

out(“Created channel %s”, name);

for (String peerName : myOrg.getPeerNames()) {
String peerLocation = myOrg.getPeerLocation(peerName);

Properties peerProperties = testConfig.getPeerProperties(peerName); //test properties for peer.. if any.
if (peerProperties == null) {
peerProperties = new Properties();
}
Peer peer = client.newPeer(peerName, peerLocation, peerProperties);
newChannel.joinPeer(peer, createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.ENDORSING_PEER, PeerRole.LEDGER_QUERY, PeerRole.CHAINCODE_QUERY, PeerRole.EVENT_SOURCE)));

out(“Peer %s joined channel %s”, peerName, name);
}
for (Orderer orderer : orderers) { //add remaining orderers if any.
newChannel.addOrderer(orderer);
}

newChannel.initialize(); 
设置身份上下文setUserContext
遍历orderer配置列表,生成orderer对象,取出第一个orderer用于创建通道
根据通道配置文件(tx)构建ChannelConfiguration对象
根据orderer、ChannelConfiguration、通道配置签名创建通道newChannel
遍历peer配置列表生成peer对象,加入到通道newChannel,并设置peer的默认角色
将剩余的orderer加入通道
调用initialize方法初始化通道
3. 创建client实例org2Client
HFClient org2Client = HFClient.createNewInstance();
org2Client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite()); 
4. 创建org2Channel,Org2的peer加入Channel
SampleOrg org2 = testConfig.getIntegrationTestsSampleOrg(“peerOrg2”);
Channel org2Channel = constructChannel(CHANNEL_NAME, org2Client, org2,
false); 
constructChannel方法和上一步一致,不创建新的chanel,取得已经创建的Channel,其他代码一致

client.newChannel(name).addOrderer(anOrderer)
 
5. Org1、Org2的Peer交叉加入Channel
//Add to the channel peers from other org.
Collection<Peer> org2OtherPeers = addOtherOrgPeers(org2Client, org2Channel, org1);
//Since org2’s peers has joined channel can now add them to org1 too
Collection<Peer> org1OtherPeers = addOtherOrgPeers(org1Client, org1Channel, org2);
 
addOtherOrgPeers方法:

for (String peerName : otherOrg.getPeerNames()) {
String peerLocation = otherOrg.getPeerLocation(peerName);
Properties peerProperties = testConfig.getPeerProperties(peerName); //test properties for peer.. if any.
if (peerProperties == null) {
peerProperties = new Properties();
}
Peer peer = myClient.newPeer(peerName, peerLocation, peerProperties);
myChannel.addPeer(peer, createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.ENDORSING_PEER, PeerRole.LEDGER_QUERY, PeerRole.CHAINCODE_QUERY, PeerRole.EVENT_SOURCE)));

添加peer的时候设置了默认角色
其中createPeerOptions为Channel类的静态方法,PeerOptions为Channel的静态内部类

public static PeerOptions createPeerOptions() {
return new PeerOptions();

6. chaincode package
chaincode路径在文章开头已经提到过了

LifecycleChaincodePackage lifecycleChaincodePackage = createLifecycleChaincodePackage(
“lc_example_cc_go_1”, // some label
Type.GO_LANG,
IntegrationSuite.getGoChaincodePath(“sample1”).toString(),
CHAIN_CODE_PATH,
“src/test/fixture/meta-infs/end2endit”); 
private LifecycleChaincodePackage createLifecycleChaincodePackage(String chaincodeLabel, Type chaincodeType, String chaincodeSourceLocation, String chaincodePath, String metadadataSource) throws IOException, InvalidArgumentException {
out(“creating install package %s.”, chaincodeLabel);
Path metadataSourcePath = null;
if (metadadataSource != null) {
metadataSourcePath = Paths.get(metadadataSource);
}
LifecycleChaincodePackage lifecycleChaincodePackage = LifecycleChaincodePackage.fromSource(chaincodeLabel, Paths.get(chaincodeSourceLocation),
chaincodeType,
chaincodePath, metadataSourcePath);
return lifecycleChaincodePackage;

meta目录结构

src/test/fixture/meta-infs/end2endit
└── META-INF
└── statedb
└── couchdb
└── indexes
└── IndexA.json 
IndexA.json

{
“ddoc”: “indexADDoc”,
“index”: {
“fields”: [
“a”
]
},
“name”: “indexA”,
“type”: “json”

7. 生成背书策略对象(opt)
LifecycleChaincodeEndorsementPolicy chaincodeEndorsementPolicy = LifecycleChaincodeEndorsementPolicy.fromSignaturePolicyYamlFile(Paths.get(TEST_FIXTURES_PATH +
“/sdkintegration/chaincodeendorsementpolicy.yaml”)); 
chaincodeendorsementpolicy.yaml

# A Shotgun policy xx
identities: # list roles to be used in the policy
user1: {“role”: {“name”: “member”, “mspId”: “Org1MSP”}} # role member in org with mspid Org1MSP
user2: {“role”: {“name”: “member”, “mspId”: “Org2MSP”}}
admin1: {“role”: {“name”: “admin”, “mspId”: “Org1MSP”}} # admin role.
admin2: {“role”: {“name”: “admin”, “mspId”: “Org2MSP”}}

policy: # the policy .. could have been flat but show grouping.
1-of: # signed by one of these groups can be <n>-of where <n> is any digit 2-of, 3-of etc..
– 1-of:
– signed-by: “user1” # a reference to one of the identities defined above.
– signed-by: “admin1”
– 1-of:
– signed-by: “user2”
– signed-by: “admin2” 
8. chaincode install
final String goChaincodeName = “lc_example_cc_go”;
runChannel(org1Client, org1Channel, org1, org1MyPeers, org1OtherPeers,
org2Client, org2Channel, org2, org2MyPeers, org2OtherPeers,
lifecycleChaincodePackage, goChaincodeName,
“1”, //Version – bump up next time.
chaincodeEndorsementPolicy,
null, // ChaincodeCollectionConfiguration
true, // initRequired
expectedMap); 
runChannel

org1Client.setUserContext(org1.getPeerAdmin());

final String chaincodeLabel = lifecycleChaincodePackage.getLabel();
final Type chaincodeType = lifecycleChaincodePackage.getType();

//Org1 installs the chaincode on its peers.
out(“Org1 installs the chaincode on its peers.”);
String org1ChaincodePackageID = lifecycleInstallChaincode(org1Client, org1MyPeers, lifecycleChaincodePackage);
 
lifecycleInstallChaincode

LifecycleInstallChaincodeRequest installProposalRequest = client.newLifecycleInstallChaincodeRequest();
installProposalRequest.setLifecycleChaincodePackage(lifecycleChaincodePackage);
installProposalRequest.setProposalWaitTime(DEPLOYWAITTIME);

Collection<LifecycleInstallChaincodeProposalResponse> responses = client.sendLifecycleInstallChaincodeRequest(installProposalRequest, peers);

String packageID = null;
for (LifecycleInstallChaincodeProposalResponse response : responses) {
if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
out(“Successful install proposal response Txid: %s from peer %s”, response.getTransactionID(), response.getPeer().getName());
if (packageID == null) {
packageID = response.getPackageId();
assertNotNull(format(“Hashcode came back as null from peer: %s “, response.getPeer()), packageID);
} else {
assertEquals(“Miss match on what the peers returned back as the packageID”, packageID, response.getPackageId());
}
}

使用步骤6中的lifecycleChaincodePackaged对象构造LifecycleInstallChaincodeRequest对象
调用client.sendLifecycleInstallChaincodeRequest执行安装,返回LifecycleInstallChaincodeProposalResponse,再从response获取packageId
9. chaincode queryinstalled
Collection<LifecycleQueryInstalledChaincodesProposalResponse> results = client.sendLifecycleQueryInstalledChaincodes(client.newLifecycleQueryInstalledChaincodesRequest(), peers);
for (LifecycleQueryInstalledChaincodesProposalResponse peerResults : results) {
if(peerResults.getStatus()==ChaincodeResponse.Status.SUCCESS){
for (LifecycleQueryInstalledChaincodesResult lifecycleQueryInstalledChaincodesResult : peerResults.getLifecycleQueryInstalledChaincodesResult()) {
if (excpectedPackageId.equals(lifecycleQueryInstalledChaincodesResult.getPackageId())) {
found = true;
break;
}
}
}

10. chaincode query chaincode definition(opt)
sequence第一次调用一定是1

long sequence = -1L;
final QueryLifecycleQueryChaincodeDefinitionRequest queryLifecycleQueryChaincodeDefinitionRequest = org1Client.newQueryLifecycleQueryChaincodeDefinitionRequest();
queryLifecycleQueryChaincodeDefinitionRequest.setChaincodeName(chaincodeName);

Collection<LifecycleQueryChaincodeDefinitionProposalResponse> firstQueryDefininitions = org1Channel.lifecycleQueryChaincodeDefinition(queryLifecycleQueryChaincodeDefinitionRequest, org1MyPeers);

for (LifecycleQueryChaincodeDefinitionProposalResponse firstDefinition : firstQueryDefininitions) {
if (firstDefinition.getStatus() == ProposalResponse.Status.SUCCESS) {
sequence = firstDefinition.getSequence() + 1L; //Need to bump it up to the next.
break;
} else { //Failed but why?
if (404 == firstDefinition.getChaincodeActionResponseStatus()) {
// not found .. done set sequence to 1;
sequence = 1;
break;
}
}

根据chaincode名称构造QueryLifecycleQueryChaincodeDefinitionRequest对象
查询lifecycleQueryChaincodeDefinition
11. chaincode approveformyorg
TransactionEvent transactionEvent = lifecycleApproveChaincodeDefinitionForMyOrg(org1Client, org1Channel,
Collections.singleton(anOrg1Peer),
sequence, chaincodeName, chaincodeVersion,
lifecycleChaincodeEndorsementPolicy,
chaincodeCollectionConfiguration,
initRequired, org1ChaincodePackageID)
.get(testConfig.getTransactionWaitTime(),
TimeUnit.SECONDS);
assertTrue(transactionEvent.isValid()); 
如果transactionEvent.isValid()的值为true,则审批通过。

CompletableFuture<TransactionEvent> lifecycleApproveChaincodeDefinitionForMyOrg(HFClient client, Channel channel,Collection<Peer> peers, long sequence,String chaincodeName, String chaincodeVersion, LifecycleChaincodeEndorsementPolicy chaincodeEndorsementPolicy, ChaincodeCollectionConfiguration chaincodeCollectionConfiguration, boolean initRequired, String org1ChaincodePackageID) {
LifecycleApproveChaincodeDefinitionForMyOrgRequest lifecycleApproveChaincodeDefinitionForMyOrgRequest = client.newLifecycleApproveChaincodeDefinitionForMyOrgRequest();
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setSequence(sequence);
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeName(chaincodeName);
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeVersion(chaincodeVersion);
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setInitRequired(initRequired);

if (null != chaincodeCollectionConfiguration) {
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeCollectionConfiguration(chaincodeCollectionConfiguration);
}

if (null != chaincodeEndorsementPolicy) {
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeEndorsementPolicy(chaincodeEndorsementPolicy);
}

lifecycleApproveChaincodeDefinitionForMyOrgRequest.setPackageId(org1ChaincodePackageID);

Collection<LifecycleApproveChaincodeDefinitionForMyOrgProposalResponse> lifecycleApproveChaincodeDefinitionForMyOrgProposalResponse = channel.sendLifecycleApproveChaincodeDefinitionForMyOrgProposal(lifecycleApproveChaincodeDefinitionForMyOrgRequest,
peers);

for (LifecycleApproveChaincodeDefinitionForMyOrgProposalResponse response : lifecycleApproveChaincodeDefinitionForMyOrgProposalResponse) {
final Peer peer = response.getPeer();
assertEquals(format(“failure on %s message is: %s”, peer, response.getMessage()), ChaincodeResponse.Status.SUCCESS, response.getStatus());
assertFalse(peer + ” ” + response.getMessage(), response.isInvalid());
assertTrue(format(“failure on %s”, peer), response.isVerified());
}
return channel.sendTransaction(lifecycleApproveChaincodeDefinitionForMyOrgProposalResponse);

构造LifecycleApproveChaincodeDefinitionForMyOrgRequest对象(sequence、chaincodeName、chaincodeVersion、initRequired、packageId)
chaincodeCollectionConfiguration和chaincodeEndorsementPolicy可为空,这里chaincodeEndorsementPolicy使用了第7步构造的对象
12. chaincode checkcommitreadiness
out(“Checking on org2’s network for approvals”);
verifyByCheckCommitReadinessStatus(org2Client, org2Channel, sequence, chaincodeName, chaincodeVersion, lifecycleChaincodeEndorsementPolicy, chaincodeCollectionConfiguration, initRequired, org2MyPeers,
new HashSet<>(Arrays.asList(ORG_1_MSP, ORG_2_MSP)), // Approved
Collections.emptySet()); // Un approved.

out(“Checking on org1’s network for approvals”);
verifyByCheckCommitReadinessStatus(org1Client, org1Channel, sequence, chaincodeName, chaincodeVersion, lifecycleChaincodeEndorsementPolicy, chaincodeCollectionConfiguration, initRequired, org1MyPeers,
new HashSet<>(Arrays.asList(ORG_1_MSP, ORG_2_MSP)), // Approved
Collections.emptySet()); // unapproved. 
private void verifyByCheckCommitReadinessStatus(HFClient client, Channel channel, long definitionSequence, String chaincodeName,
String chaincodeVersion, LifecycleChaincodeEndorsementPolicy chaincodeEndorsementPolicy,
ChaincodeCollectionConfiguration chaincodeCollectionConfiguration, boolean initRequired, Collection<Peer> org1MyPeers,
Set<String> expectedApproved, Set<String> expectedUnApproved) throws InvalidArgumentException, ProposalException {
LifecycleCheckCommitReadinessRequest lifecycleCheckCommitReadinessRequest = client.newLifecycleSimulateCommitChaincodeDefinitionRequest();
lifecycleCheckCommitReadinessRequest.setSequence(definitionSequence);
lifecycleCheckCommitReadinessRequest.setChaincodeName(chaincodeName);
lifecycleCheckCommitReadinessRequest.setChaincodeVersion(chaincodeVersion);
if (null != chaincodeEndorsementPolicy) {
lifecycleCheckCommitReadinessRequest.setChaincodeEndorsementPolicy(chaincodeEndorsementPolicy);
}
if (null != chaincodeCollectionConfiguration) {
lifecycleCheckCommitReadinessRequest.setChaincodeCollectionConfiguration(chaincodeCollectionConfiguration);
}
lifecycleCheckCommitReadinessRequest.setInitRequired(initRequired);

Collection<LifecycleCheckCommitReadinessProposalResponse> lifecycleSimulateCommitChaincodeDefinitionProposalResponse = channel.sendLifecycleCheckCommitReadinessRequest(lifecycleCheckCommitReadinessRequest, org1MyPeers);
for (LifecycleCheckCommitReadinessProposalResponse resp : lifecycleSimulateCommitChaincodeDefinitionProposalResponse) {
final Peer peer = resp.getPeer();
assertEquals(ChaincodeResponse.Status.SUCCESS, resp.getStatus());
assertEquals(format(“Approved orgs failed on %s”, peer), expectedApproved, resp.getApprovedOrgs());
assertEquals(format(“UnApproved orgs failed on %s”, peer), expectedUnApproved, resp.getUnApprovedOrgs());
}

主要构造LifecycleCheckCommitReadinessRequest对象(sequence、chaincodeName、chaincodeVersion、initRequired)

13. chaincode commit
out(“Org2 doing commit chaincode definition”);
Collection<Peer> org2EndorsingPeers = Arrays.asList(org2MyPeers.iterator().next(), org2OtherPeers.iterator().next());
transactionEvent = commitChaincodeDefinitionRequest(org2Client, org2Channel, sequence, chaincodeName, chaincodeVersion, org2ChaincodeEndorsementPolicy, chaincodeCollectionConfiguration, initRequired, org2EndorsingPeers)
.get(testConfig.getTransactionWaitTime(), TimeUnit.SECONDS);
assertTrue(transactionEvent.isValid());

out(“Org2 done with commit. block #%d!”, transactionEvent.getBlockEvent().getBlockNumber());
 
private CompletableFuture<TransactionEvent> commitChaincodeDefinitionRequest(HFClient client, Channel channel, long definitionSequence, String chaincodeName, String chaincodeVersion,
LifecycleChaincodeEndorsementPolicy chaincodeEndorsementPolicy,
ChaincodeCollectionConfiguration chaincodeCollectionConfiguration,
boolean initRequired, Collection<Peer> endorsingPeers) throws ProposalException, InvalidArgumentException, InterruptedException, ExecutionException, TimeoutException {
LifecycleCommitChaincodeDefinitionRequest lifecycleCommitChaincodeDefinitionRequest = client.newLifecycleCommitChaincodeDefinitionRequest();
lifecycleCommitChaincodeDefinitionRequest.setSequence(definitionSequence);
lifecycleCommitChaincodeDefinitionRequest.setChaincodeName(chaincodeName);
lifecycleCommitChaincodeDefinitionRequest.setChaincodeVersion(chaincodeVersion);
if (null != chaincodeEndorsementPolicy) {
lifecycleCommitChaincodeDefinitionRequest.setChaincodeEndorsementPolicy(chaincodeEndorsementPolicy);
}
if (null != chaincodeCollectionConfiguration) {
lifecycleCommitChaincodeDefinitionRequest.setChaincodeCollectionConfiguration(chaincodeCollectionConfiguration);
}
lifecycleCommitChaincodeDefinitionRequest.setInitRequired(initRequired);

Collection<LifecycleCommitChaincodeDefinitionProposalResponse> lifecycleCommitChaincodeDefinitionProposalResponses = channel.sendLifecycleCommitChaincodeDefinitionProposal(lifecycleCommitChaincodeDefinitionRequest,
endorsingPeers);

for (LifecycleCommitChaincodeDefinitionProposalResponse resp : lifecycleCommitChaincodeDefinitionProposalResponses) {

final Peer peer = resp.getPeer();
assertEquals(format(“%s had unexpected status.”, peer.toString()), ChaincodeResponse.Status.SUCCESS, resp.getStatus());
assertTrue(format(“%s not verified.”, peer.toString()), resp.isVerified());
}
return channel.sendTransaction(lifecycleCommitChaincodeDefinitionProposalResponses);

主要构造LifecycleCommitChaincodeDefinitionRequest对象(sequence、chaincodeName、chaincodeVersion、initRequired)

14. chaincode init、 chaincode invoke
out(“Org1 doing init”);
transactionEvent = executeChaincode(org1Client, org1.getPeerAdmin(), org1Channel, “init”,
initRequired ? true : null, // doInit don’t even specify it has it should default to false
chaincodeName, chaincodeType, “a,”, “100”, “b”, “300”).get(testConfig.getTransactionWaitTime(), TimeUnit.SECONDS);
assertTrue(transactionEvent.isValid());

transactionEvent = executeChaincode(org2Client, org2.getPeerAdmin(), org2Channel, “move”,
false, // doInit
chaincodeName, chaincodeType, “a,”, “b”, “10”).get(testConfig.getTransactionWaitTime(), TimeUnit.SECONDS);
assertTrue(transactionEvent.isValid()); 
CompletableFuture<TransactionEvent> executeChaincode(HFClient client, User userContext, Channel channel, String fcn, Boolean doInit, String chaincodeName, Type chaincodeType, String… args) throws InvalidArgumentException, ProposalException {

final ExecutionException[] executionExceptions = new ExecutionException[1];

Collection<ProposalResponse> successful = new LinkedList<>();
Collection<ProposalResponse> failed = new LinkedList<>();

TransactionProposalRequest transactionProposalRequest = client.newTransactionProposalRequest();
transactionProposalRequest.setChaincodeName(chaincodeName);
transactionProposalRequest.setChaincodeLanguage(chaincodeType);
transactionProposalRequest.setUserContext(userContext);

transactionProposalRequest.setFcn(fcn);
transactionProposalRequest.setProposalWaitTime(testConfig.getProposalWaitTime());
transactionProposalRequest.setArgs(args);
if (null != doInit) {
transactionProposalRequest.setInit(doInit);
}

// Collection<ProposalResponse> transactionPropResp = channel.sendTransactionProposalToEndorsers(transactionProposalRequest);
Collection<ProposalResponse> transactionPropResp = channel.sendTransactionProposal(transactionProposalRequest, channel.getPeers());
for (ProposalResponse response : transactionPropResp) {
if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
out(“Successful transaction proposal response Txid: %s from peer %s”, response.getTransactionID(), response.getPeer().getName());
successful.add(response);
} else {
failed.add(response);
}
}

out(“Received %d transaction proposal responses. Successful+verified: %d . Failed: %d”,
transactionPropResp.size(), successful.size(), failed.size());
if (failed.size() > 0) {
ProposalResponse firstTransactionProposalResponse = failed.iterator().next();
fail(“Not enough endorsers for executeChaincode(move a,b,100):” + failed.size() + ” endorser error: ” +
firstTransactionProposalResponse.getMessage() +
“. Was verified: ” + firstTransactionProposalResponse.isVerified());
}
out(“Successfully received transaction proposal responses.”);

// System.exit(10);

// Send Transaction Transaction to orderer
out(“Sending chaincode transaction(move a,b,100) to orderer.”);
return channel.sendTransaction(successful);


构造TransactionProposalRequest对象,最后多了一步将结果发送给orderer:channel.sendTransaction(successful)

15. chaincode query
executeVerifyByQuery(org1Client, org1Channel, chaincodeName, (String) expected.get(“queryBvalue”));
executeVerifyByQuery(org2Client, org2Channel, chaincodeName, (String) expected.get(“queryBvalue”));
 
void executeVerifyByQuery(HFClient client, Channel channel, String chaincodeName, String expect) throws ProposalException, InvalidArgumentException {
out(“Now query chaincode for the value of b.”);
QueryByChaincodeRequest queryByChaincodeRequest = client.newQueryProposalRequest();
queryByChaincodeRequest.setArgs(“b”);
queryByChaincodeRequest.setFcn(“query”);
queryByChaincodeRequest.setChaincodeName(chaincodeName);

Collection<ProposalResponse> queryProposals = channel.queryByChaincode(queryByChaincodeRequest, channel.getPeers());
for (ProposalResponse proposalResponse : queryProposals) {
if (!proposalResponse.isVerified() || proposalResponse.getStatus() != ProposalResponse.Status.SUCCESS) {
fail(“Failed query proposal from peer ” + proposalResponse.getPeer().getName() + ” status: ” + proposalResponse.getStatus() +
“. Messages: ” + proposalResponse.getMessage()
+ “. Was verified : ” + proposalResponse.isVerified());
} else {
String payload = proposalResponse.getProposalResponse().getResponse().getPayload().toStringUtf8();
out(“Query payload of b from peer %s returned %s”, proposalResponse.getPeer().getName(), payload);
assertEquals(expect, payload);
}
}


主要构造QueryByChaincodeRequest对象(chaincodeName、Fcn、Args)

总结一下
创建sdk实例,并设置当前用户身份

HFClient client = HFClient.createNewInstance();
client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
client.setUserContext(peerAdmin);
 
创建channel

ChannelConfiguration channelConfiguration = new ChannelConfiguration(new File(path));
Channel newChannel = client.newChannel(name, anOrderer, channelConfiguration, client.getChannelConfigurationSignature(channelConfiguration, peerAdmin));
 
创建peer并加入channel

Peer peer = client.newPeer(peerName, peerLocation, peerProperties);
newChannel.joinPeer(peer, createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.ENDORSING_PEER, PeerRole.LEDGER_QUERY, PeerRole.CHAINCODE_QUERY, PeerRole.EVENT_SOURCE)));
 
orderer加入channel

newChannel.addOrderer(orderer);
 
初始化channel

newChannel.initialize();
 
打包chaincode

LifecycleChaincodePackage lifecycleChaincodePackage = LifecycleChaincodePackage.fromSource(chaincodeLabel, Paths.get(chaincodeSourceLocation),
chaincodeType,
chaincodePath, metadataSourcePath);
 
安装chaincode

LifecycleInstallChaincodeRequest installProposalRequest = client.newLifecycleInstallChaincodeRequest();
installProposalRequest.setLifecycleChaincodePackage(lifecycleChaincodePackage);
Collection<LifecycleInstallChaincodeProposalResponse> responses = client.sendLifecycleInstallChaincodeRequest(installProposalRequest, peers);
 
查询已安装chaincode

//sendLifecycleQueryInstalledChaincode
final LifecycleQueryInstalledChaincodeRequest lifecycleQueryInstalledChaincodeRequest = client.newLifecycleQueryInstalledChaincodeRequest();
lifecycleQueryInstalledChaincodeRequest.setPackageID(packageId);
Collection<LifecycleQueryInstalledChaincodeProposalResponse> responses = client.sendLifecycleQueryInstalledChaincode(lifecycleQueryInstalledChaincodeRequest, peers);

//sendLifecycleQueryInstalledChaincodes
Collection<LifecycleQueryInstalledChaincodesProposalResponse> results = client.sendLifecycleQueryInstalledChaincodes(client.newLifecycleQueryInstalledChaincodesRequest(), peers);
 
审批chaincode

LifecycleApproveChaincodeDefinitionForMyOrgRequest lifecycleApproveChaincodeDefinitionForMyOrgRequest = client.newLifecycleApproveChaincodeDefinitionForMyOrgRequest();
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setSequence(sequence);
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeName(chaincodeName);
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setChaincodeVersion(chaincodeVersion);
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setInitRequired(initRequired);
lifecycleApproveChaincodeDefinitionForMyOrgRequest.setPackageId(org1ChaincodePackageID);
Collection<LifecycleApproveChaincodeDefinitionForMyOrgProposalResponse> lifecycleApproveChaincodeDefinitionForMyOrgProposalResponse = channel.sendLifecycleApproveChaincodeDefinitionForMyOrgProposal(lifecycleApproveChaincodeDefinitionForMyOrgRequest,peers);
 
查询审批chaincode

LifecycleCheckCommitReadinessRequest lifecycleCheckCommitReadinessRequest = client.newLifecycleSimulateCommitChaincodeDefinitionRequest();
lifecycleCheckCommitReadinessRequest.setSequence(definitionSequence);
lifecycleCheckCommitReadinessRequest.setChaincodeName(chaincodeName);
lifecycleCheckCommitReadinessRequest.setChaincodeVersion(chaincodeVersion);
lifecycleCheckCommitReadinessRequest.setInitRequired(initRequired);
Collection<LifecycleCheckCommitReadinessProposalResponse> lifecycleSimulateCommitChaincodeDefinitionProposalResponse = channel.sendLifecycleCheckCommitReadinessRequest(lifecycleCheckCommitReadinessRequest, org1MyPeers);
 
提交chaincode

LifecycleCommitChaincodeDefinitionRequest lifecycleCommitChaincodeDefinitionRequest = client.newLifecycleCommitChaincodeDefinitionRequest();
lifecycleCommitChaincodeDefinitionRequest.setSequence(definitionSequence);
lifecycleCommitChaincodeDefinitionRequest.setChaincodeName(chaincodeName);
lifecycleCommitChaincodeDefinitionRequest.setChaincodeVersion(chaincodeVersion);
lifecycleCommitChaincodeDefinitionRequest.setInitRequired(initRequired);
Collection<LifecycleCommitChaincodeDefinitionProposalResponse> lifecycleCommitChaincodeDefinitionProposalResponses = channel.sendLifecycleCommitChaincodeDefinitionProposal(lifecycleCommitChaincodeDefinitionRequest,endorsingPeers);
 
调用chaincode

TransactionProposalRequest transactionProposalRequest = client.newTransactionProposalRequest();
transactionProposalRequest.setChaincodeName(chaincodeName);
transactionProposalRequest.setChaincodeLanguage(chaincodeType);
transactionProposalRequest.setUserContext(userContext);
transactionProposalRequest.setFcn(fcn);
transactionProposalRequest.setArgs(args);
transactionProposalRequest.setInit(doInit);
// Collection<ProposalResponse> transactionPropResp = channel.sendTransactionProposalToEndorsers(transactionProposalRequest);
Collection<ProposalResponse> transactionPropResp = channel.sendTransactionProposal(transactionProposalRequest, channel.getPeers());
 
查询chaincode状态值

QueryByChaincodeRequest queryByChaincodeRequest = client.newQueryProposalRequest();
queryByChaincodeRequest.setArgs(“b”);
queryByChaincodeRequest.setFcn(“query”);
queryByChaincodeRequest.setChaincodeName(chaincodeName);
Collection<ProposalResponse> queryProposals = channel.queryByChaincode(queryByChaincodeRequest, channel.getPeers());
————————————————
版权声明:本文为CSDN博主「kk3909」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kk3909/article/details/105217162