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。
依赖:
<dependency>
<groupId>org.hyperledger.fabricgroupId>
<artifactId>fabric-gateway-javaartifactId>
<version>2.0.0version>
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"}}
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"
}
}
}
这里主要摘取了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-repoid>
<url>https://oss.sonatype.org/content/repositories/snapshotsurl>
<releases>
<enabled>falseenabled>
releases>
<snapshots>
<enabled>trueenabled>
snapshots>
repository>
repositories>
<dependencies>
<dependency>
<groupId>org.hyperledger.fabric-sdk-javagroupId>
<artifactId>fabric-sdk-javaartifactId>
<version>2.0.0-SNAPSHOTversion>
dependency>
dependencies>
HFClient org1Client = HFClient.createNewInstance();
org1Client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
创建了与fabric网络交互的sdk client实例org1Client,设置了加密套件。
SampleOrg org1 = testConfig.getIntegrationTestsSampleOrg("peerOrg1");
Channel org1Channel = constructChannel(CHANNEL_NAME, org1Client, org1, true);
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();
HFClient org2Client = HFClient.createNewInstance();
org2Client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
SampleOrg org2 = testConfig.getIntegrationTestsSampleOrg("peerOrg2");
Channel org2Channel = constructChannel(CHANNEL_NAME, org2Client, org2,
false);
constructChannel方法和上一步一致,不创建新的chanel,取得已经创建的Channel,其他代码一致
client.newChannel(name).addOrderer(anOrderer)
//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();
}
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"
}
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 -of where 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"
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());
}
}
}
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;
}
}
}
}
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;
}
}
}
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);
}
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)
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)
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 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)
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 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());