概述

fabric官方提供的java sdk包含两个项目fabric-sdk-javafabric-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"}}

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

创建了与fabric网络交互的sdk client实例org1Client,设置了加密套件。

2. 创建org1Channel,Orderer和Org1的peer加入Channel
 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();
  
  • 设置身份上下文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的时候设置了默认角色
其中createPeerOptionsChannel类的静态方法,PeerOptionsChannel的静态内部类

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

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐