项目作者: hooj0

项目描述 :
:twisted_rightwards_arrows: Hyperledger fabric java sdk assembly of public, core functional methods, providing further calls to other frameworks.
高级语言: Java
项目地址: git://github.com/hooj0/fabric-sdk-java-commons.git
创建时间: 2018-07-21T09:33:30Z
项目社区:https://github.com/hooj0/fabric-sdk-java-commons

开源协议:MIT License

下载


fabric sdk java commons framework

:twisted_rightwards_arrows: Hyperledger fabric java sdk assembly of public, core functional methods, providing further calls to other frameworks.

发布

准备

fabric sdk java commons framework 使用 fabric-sdk-java1.3 版本。

1、基本配置

1.1、添加 Chaincode 必要的配置资源

在项目文件夹中添加目录 /fabric-sdk-commons/src/test/fixture/integration,目录中增加资源配置。必须了解 end-to-end sample 实例的运行方式,这里不增加额外的赘述。

1.2、添加 fabric区块链网络链接配置

根据自己的需要可以适当的修改配置内容,这里的配置依赖上面配置资源/fabric-sdk-commons/src/test/fixture/integration。配置文件位置 fabric-sdk-commons/src/test/resources/fabric-chaincode.properties
内容如下:

  1. #@changelog properties file fabric configuration
  2. #Sat Jul 28 20:10:31 CST 2018
  3. # 区块链网络版本
  4. fabric.network.configtx.version=v1.0
  5. # 用户 & 密码
  6. hyperledger.fabric.sdk.commons.network.ca.admin.name=admin
  7. hyperledger.fabric.sdk.commons.network.ca.admin.passwd=adminpw
  8. hyperledger.fabric.sdk.commons.network.orgs.member.users=user1
  9. hyperledger.fabric.sdk.commons.network.tls.enable=false
  10. # 公共的根目录
  11. hyperledger.fabric.sdk.commons.config.root.path=src/test/fixture/integration
  12. # peer & order 证书配置
  13. hyperledger.fabric.sdk.commons.crypto.channel.config.root.path=/e2e-2Orgs
  14. # channel & block 配置
  15. hyperledger.fabric.sdk.commons.channel.artifacts.root.path=/channel-artifacts
  16. # Chaincode source code 目录
  17. #hyperledger.fabric.sdk.commons.chaincode.source.code.root.path=/gocc/sample_11
  18. hyperledger.fabric.sdk.commons.chaincode.source.code.root.path=/gocc/sample1
  19. # 背书配置
  20. hyperledger.fabric.sdk.commons.endorsement.policy.file.path=chaincode-endorsement-policy.yaml
  21. # 网络配置文件所在目录
  22. hyperledger.fabric.sdk.commons.network.config.root.path=network_configs

1.3、添加 Key Value 持久化存储配置

持久化缓存配置文件 /fabric-sdk-commons/fabric-kv-store.properties,存储通道或用户的缓存信息,方便下次直接使用而不用重复创建用户和通道。

2、扩展配置

fabric sdk java commons框架支持自定义 FabricConfigurationFabricKeyValueStore 的配置。如果需要自定义扩展配置,需要实现这两个特定的接口。然后在使用的时候传入自定义实现的实例即可。

  1. public ChaincodeDeployTemplate(String channelName, String orgName, FabricConfiguration config, FabricKeyValueStore store) {
  2. super(channelName, orgName, config, store, ChaincodeDeployTemplate.class);
  3. this.init();
  4. }

2.1、自定义 config 配置

FabricConfiguration支持两种网络链接配置方式,一种是 properties 配置文件的实现方式,参考代码:FabricPropertiesConfiguration.java,另一种则是 class 内存的配置方式,参考代码:FabricClassConfiguration.java
可以在创建 ChaincodeDeployTemplateChaincodeTransactionTemplate 模板实例的时候,传入自己想要的配置模式。

  • properties config 配置的模板

    以下是 properties config 配置的模板,可以在模板的基础上修改配置定制

  1. #@changelog properties file fabric configuration
  2. #Sat Jul 28 20:10:31 CST 2018
  3. fabric.network.configtx.version=v1.1
  4. hyperledger.fabric.sdk.commons.network.ca.admin.name=admin
  5. hyperledger.fabric.sdk.commons.network.ca.admin.passwd=adminpw
  6. hyperledger.fabric.sdk.commons.network.orgs.member.users=user1
  7. hyperledger.fabric.sdk.commons.invoke.wait.time=10
  8. hyperledger.fabric.sdk.commons.deploy.wait.time=100
  9. hyperledger.fabric.sdk.commons.proposal.wait.time=1000
  10. hyperledger.fabric.sdk.commons.network.tls.enable=false
  11. hyperledger.fabric.sdk.commons.network.domain=example.com
  12. hyperledger.fabric.sdk.commons.configtxlater.url=http\://192.168.8.8\:7059
  13. hyperledger.fabric.sdk.commons.config.root.path=src/test/fixture/integration
  14. hyperledger.fabric.sdk.commons.crypto.channel.config.root.path=/e2e-2Orgs
  15. hyperledger.fabric.sdk.commons.channel.artifacts.root.path=/channel-artifacts
  16. hyperledger.fabric.sdk.commons.chaincode.source.code.root.path=/gocc/sample11
  17. hyperledger.fabric.sdk.commons.endorsement.policy.file.path=chaincode-endorsement-policy.yaml
  18. hyperledger.fabric.sdk.commons.network.config.root.path=network_configs
  19. hyperledger.fabric.sdk.commons.network.org.peerOrg1.mspid=Org1MSP
  20. hyperledger.fabric.sdk.commons.network.org.peerOrg1.caName=ca0
  21. hyperledger.fabric.sdk.commons.network.org.peerOrg1.domname=org1.example.com
  22. hyperledger.fabric.sdk.commons.network.org.peerOrg1.ca_location=http\://192.168.8.8\:7054
  23. hyperledger.fabric.sdk.commons.network.org.peerOrg1.orderer_locations=orderer.example.com@grpc\://192.168.8.8\:7050
  24. hyperledger.fabric.sdk.commons.network.org.peerOrg1.peer_locations=peer0.org1.example.com@grpc\://192.168.8.8\:7051, peer1.org1.example.com@grpc\://192.168.8.8\:7056
  25. hyperledger.fabric.sdk.commons.network.org.peerOrg1.eventhub_locations=peer0.org1.example.com@grpc\://192.168.8.8\:7053, peer1.org1.example.com@grpc\://192.168.8.8\:7058
  26. hyperledger.fabric.sdk.commons.network.org.peerOrg2.mspid=Org2MSP
  27. hyperledger.fabric.sdk.commons.network.org.peerOrg2.domname=org2.example.com
  28. hyperledger.fabric.sdk.commons.network.org.peerOrg2.ca_location=http\://192.168.8.8\:8054
  29. hyperledger.fabric.sdk.commons.network.org.peerOrg2.orderer_locations=orderer.example.com@grpc\://192.168.8.8\:7050
  30. hyperledger.fabric.sdk.commons.network.org.peerOrg2.peer_locations=peer0.org2.example.com@grpc\://192.168.8.8\:8051, peer1.org2.example.com@grpc\://192.168.8.8\:8056
  31. hyperledger.fabric.sdk.commons.network.org.peerOrg2.eventhub_locations=peer0.org2.example.com@grpc\://192.168.8.8\:8053, peer1.org2.example.com@grpc\://192.168.8.8\:8058
  • class config 配置的模板

    以下是 class config 配置的模板,可以调用FabricClassConfiguration.getInstance()修改配置定制

  1. FabricClassConfiguration config = FabricClassConfiguration.getInstance();
  2. String orgName = "peerOrg1";
  3. config.setNetworkDomain("example.com");
  4. config.setMspId(orgName, "Org1MSP");
  5. config.setOrgDomain(orgName, "org1." + config.getNetworkDomain());
  6. config.setCaName(orgName, "ca0");
  7. config.setCaLocation(orgName, "http://" + config.getFabricNetworkHost() + ":7054");
  8. config.setOrdererLocation(orgName, "orderer.example.com@grpc://" + config.getFabricNetworkHost() + ":7050");
  9. config.setPeerLocation(orgName, "peer0.org1.example.com@grpc://" + config.getFabricNetworkHost() + ":7051, peer1.org1.example.com@grpc://" + config.getFabricNetworkHost() + ":7056");
  10. config.setEventHubLocation(orgName, "peer0.org1.example.com@grpc://" + config.getFabricNetworkHost() + ":7053, peer1.org1.example.com@grpc://" + config.getFabricNetworkHost() + ":7058");
  11. orgName = "peerOrg2";
  12. config.setMspId(orgName, "Org2MSP");
  13. config.setOrgDomain(orgName, "org2." + config.getNetworkDomain());
  14. // config.setCaName(orgName, "ca1");
  15. config.setCaLocation(orgName, "http://" + config.getFabricNetworkHost() + ":8054");
  16. config.setOrdererLocation(orgName, "orderer.example.com@grpc://" + config.getFabricNetworkHost() + ":7050");
  17. config.setPeerLocation(orgName, "peer0.org2.example.com@grpc://" + config.getFabricNetworkHost() + ":8051, peer1.org2.example.com@grpc://" + config.getFabricNetworkHost() + ":8056");
  18. config.setEventHubLocation(orgName, "peer0.org2.example.com@grpc://" + config.getFabricNetworkHost() + ":8053, peer1.org2.example.com@grpc://" + config.getFabricNetworkHost() + ":8058");
  19. config.settingPropertyValue(FabricConfigurationPropertyKey.FABRIC_CONFIGTX_VERSION, "v1.1");
  20. config.settingPropertyValue(FabricConfigurationPropertyKey.CONFIG_TXLATER_URL, "http://" + config.getFabricNetworkHost() + ":7059");
  21. config.settingPropertyValue(FabricConfigurationPropertyKey.INVOKE_WAIT_TIME, "10");
  22. config.settingPropertyValue(FabricConfigurationPropertyKey.DEPLOY_WAIT_TIME, "100");
  23. config.settingPropertyValue(FabricConfigurationPropertyKey.PROPOSAL_WAIT_TIME, "1000");
  24. config.settingPropertyValue(FabricConfigurationPropertyKey.NETWORK_TLS_ENABLED, "true");
  25. config.settingPropertyValue(FabricConfigurationPropertyKey.COMMON_CONFIG_ROOT_PATH, "src/test/fixture/integration");
  26. config.settingPropertyValue(FabricConfigurationPropertyKey.CRYPTO_CHANNEL_CONFIG_ROOT_PATH, "/e2e-2Orgs");
  27. config.settingPropertyValue(FabricConfigurationPropertyKey.CHAINCODE_SOURCE_ROOT_PATH, "/gocc/sample11");
  28. config.settingPropertyValue(FabricConfigurationPropertyKey.CHANNEL_ARTIFACTS_ROOT_PATH, "/channel-artifacts");
  29. config.settingPropertyValue(FabricConfigurationPropertyKey.ENDORSEMENT_POLICY_FILE_PATH, "chaincode-endorsement-policy.yaml");
  30. config.settingPropertyValue(FabricConfigurationPropertyKey.NETWORK_CONFIG_ROOT_PATH, "network_configs");
  31. config.settingPropertyValue(FabricConfigurationPropertyKey.NETWORK_CA_ADMIN_NAME, "admin");
  32. config.settingPropertyValue(FabricConfigurationPropertyKey.NETWORK_CA_ADMIN_PASSWD, "adminpw");
  33. config.settingPropertyValue(FabricConfigurationPropertyKey.NETWORK_ORGS_MEMBER_USERS, "user1");

2.2、自定义 store 配置

FabricKeyValueStore是KV持久化缓存配置,KV 也支持两种配置方式,一种是 FileSystemKeyValueStore 文件系统的配置方式,另一种是 MemoryKeyValueStore 内存系统的配置方式。如果有必要可以实现自己的持久化缓存存储,具体可以实现接口 io.github.hooj0.fabric.sdk.commons.store.FabricKeyValueStore,同样可以在创建 ChaincodeDeployTemplateChaincodeTransactionTemplate 模板实例的时候,传入自己想要的配置模式。

3、部署 Chaincode

公共的代码常量,通道和对等节点以及 ChaincodeId

  1. public class BasedTemplateTest {
  2. final static String foo = "mychannel";
  3. final static String bar = "mychannel2";
  4. final static String org1 = "peerOrg1";
  5. final static String org2 = "peerOrg2";
  6. static String CHAIN_CODE_NAME = "example_cc_go";
  7. static String CHAIN_CODE_PATH = "github.com/example_cc";
  8. static String CHAIN_CODE_VERSION = "1";
  9. static String CHAIN_CODE_VERSION_11 = "11";
  10. static Type CHAIN_CODE_LANG = Type.GO_LANG;
  11. ChaincodeID chaincodeID_1 = ChaincodeID.newBuilder().setName(CHAIN_CODE_NAME).setPath(CHAIN_CODE_PATH).setVersion(CHAIN_CODE_VERSION).build();
  12. ChaincodeID chaincodeID_11 = ChaincodeID.newBuilder().setName(CHAIN_CODE_NAME).setPath(CHAIN_CODE_PATH).setVersion(CHAIN_CODE_VERSION_11).build();
  13. ChaincodeID chaincodeID_11_2 = ChaincodeID.newBuilder().setName(CHAIN_CODE_NAME).setPath(CHAIN_CODE_PATH).setVersion("11.2").build();
  14. }

3.1、创建 Chaincode 部署模板类实例

  1. private ChaincodeDeployOperations operations;
  2. @Before
  3. public void setup() {
  4. operations = new ChaincodeDeployTemplate(foo, org1, FabricPropertiesConfiguration.getInstance());
  5. // 自定义 key value store 文件位置
  6. //operations = new ChaincodeDeployTemplate(foo, org1, FabricClassConfiguration.getInstance(), new File("my-kv-store.properties"));
  7. // 使用 内存 key value store 文件位置
  8. //operations = new ChaincodeDeployTemplate(foo, org1, FabricPropertiesConfiguration.getInstance(), new MemoryKeyValueStore());
  9. }

3.2、安装 Chaincode

传入必要的参数 chaincodeIDChaincode 的文件路径,以及 chaincode 的类型

  1. @Test
  2. public void testInstallDeployTemplate() {
  3. InstallOptions options = new InstallOptions();
  4. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  5. String chaincodeSourceFile = operations.getConfig().getChaincodeRootPath();
  6. operations.install(options, chaincodeSourceFile);
  7. }

3.3、实例化 Chaincode

实例化支持多种结果返回形式,以及多种参数签名发送。

  1. @Test
  2. public void testInstantiateDeployTemplate() {
  3. InstantiateOptions options = new InstantiateOptions();
  4. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  5. options.setEndorsementPolicyFile(Paths.get(operations.getConfig().getEndorsementPolicyFilePath()).toFile());
  6. ResultSet rs = operations.instantiate(options, "init", "a", 200, "b", 300);
  7. System.out.println("-------->>>>>>>" + rs);
  8. }
  9. @Test
  10. public void testInstantiate2DeployTemplate() {
  11. InstantiateOptions options = new InstantiateOptions();
  12. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  13. options.setEndorsementPolicyFile(Paths.get(operations.getConfig().getEndorsementPolicyFilePath()).toFile());
  14. LinkedHashMap<String, Object> args = Maps.newLinkedHashMap();
  15. args.put("a", 300);
  16. args.put("b", 500);
  17. ResultSet rs = operations.instantiate(options, "init", args);
  18. System.out.println("-------->>>>>>>" + rs);
  19. }
  20. @Test
  21. public void testInstantiate3DeployTemplate() throws Exception {
  22. InstantiateOptions options = new InstantiateOptions();
  23. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  24. options.setEndorsementPolicyFile(Paths.get(operations.getConfig().getEndorsementPolicyFilePath()).toFile());
  25. LinkedHashMap<String, Object> args = Maps.newLinkedHashMap();
  26. args.put("a", 300);
  27. args.put("b", 500);
  28. CompletableFuture<TransactionEvent> future = operations.instantiateAsync(options, "init", args);
  29. future.thenApply((BlockEvent.TransactionEvent transactionEvent) -> {
  30. // 必须是有效交易事件
  31. checkArgument(transactionEvent.isValid(), "没有签名的交易事件");
  32. // 必须有签名
  33. checkNotNull(transactionEvent.getSignature(), "没有签名的交易事件");
  34. // 必须有交易区块事件发生
  35. BlockEvent blockEvent = checkNotNull(transactionEvent.getBlockEvent(), "交易事件的区块事件对象为空");
  36. try {
  37. System.out.println("成功实例化Chaincode,本次实例化交易ID:" + transactionEvent.getTransactionID());
  38. System.out.println(transactionEvent.getChannelId());
  39. checkArgument(StringUtils.equals(blockEvent.getChannelId(), operations.getChannel().getName()), "事件名称和对应通道名称不一致");
  40. // 检查
  41. if (!operations.checkInstantiatedChaincode(options.getChaincodeId())) {
  42. throw new AssertionError("chaincode 1 没有实例化");
  43. }
  44. } catch (Exception e) {
  45. throw new RuntimeException(e);
  46. }
  47. return "success";
  48. }).exceptionally(e -> {
  49. if (e instanceof CompletionException && e.getCause() != null) {
  50. e = e.getCause();
  51. }
  52. if (e instanceof TransactionEventException) {
  53. BlockEvent.TransactionEvent te = ((TransactionEventException) e).getTransactionEvent();
  54. if (te != null) {
  55. e.printStackTrace(System.err);
  56. fail(format("Transaction with txid %s failed. %s", te.getTransactionID(), e.getMessage()));
  57. }
  58. }
  59. e.printStackTrace(System.err);
  60. fail(format("Test failed with %s exception %s", e.getClass().getName(), e.getMessage()));
  61. return null;
  62. }).get(operations.getConfig().getTransactionWaitTime(), TimeUnit.SECONDS);
  63. }
  64. @Test
  65. public void testInstantiate4DeployTemplate() {
  66. InstantiateOptions options = new InstantiateOptions();
  67. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  68. options.setEndorsementPolicyFile(Paths.get(operations.getConfig().getEndorsementPolicyFilePath()).toFile());
  69. LinkedHashMap<String, Object> args = Maps.newLinkedHashMap();
  70. args.put("a", 300);
  71. args.put("b", 500);
  72. TransactionEvent event = operations.instantiateFor(options, "init", args);
  73. System.out.println("-------------->>>>>>>" + event);
  74. }

3.4、升级 Chaincode

升级后,每笔交易会发生在两个链码上。

  1. @Test
  2. public void testUpgradeDeployTemplate() throws Exception {
  3. if (!operations.checkChaincode(chaincodeID_11, operations.getOrganization())) {
  4. fail(chaincodeID_11 + " not install | instantiate.");
  5. }
  6. if (!operations.checkInstallChaincode(chaincodeID_11_2)) {
  7. InstallOptions options = new InstallOptions();
  8. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  9. options.setChaincodeUpgradeVersion("11.2");
  10. operations.install(options, operations.getConfig().getChaincodeRootPath());
  11. }
  12. if (operations.checkInstallChaincode(chaincodeID_11_2) && !operations.checkInstantiatedChaincode(chaincodeID_11_2)) {
  13. UpgradeOptions upgradeOptions = new UpgradeOptions();
  14. upgradeOptions.setChaincodeId(chaincodeID_11_2).setChaincodeType(CHAIN_CODE_LANG);
  15. upgradeOptions.setEndorsementPolicyFile(Paths.get(operations.getConfig().getEndorsementPolicyFilePath()).toFile());
  16. ResultSet rs = operations.upgrade(upgradeOptions, "init");
  17. System.out.println("-------------->>>>>>>" + rs);
  18. }
  19. }
  20. @Test
  21. public void testUpgrade2DeployTemplate() throws Exception {
  22. UpgradeOptions options = new UpgradeOptions();
  23. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG).setChaincodeVersion("11.2");
  24. options.setEndorsementPolicyFile(Paths.get(operations.getConfig().getEndorsementPolicyFilePath()).toFile());
  25. InstallOptions installOptions = new InstallOptions().setChaincodeUpgradeVersion("11.2");
  26. installOptions.setChaincodeId(options.getChaincodeId()).setChaincodeType(CHAIN_CODE_LANG);
  27. String chaincodeSourceFile = operations.getConfig().getChaincodeRootPath();
  28. if (!operations.checkInstallChaincode(installOptions.getChaincodeId())) {
  29. operations.install(installOptions, chaincodeSourceFile);
  30. }
  31. CompletableFuture<TransactionEvent> future = operations.upgradeAsync(options, "init", "a", "100", "b", "100");
  32. Object result = future.thenApply((TransactionEvent event) -> {
  33. System.out.println(event.isValid());
  34. System.out.println(event.getBlockEvent());
  35. System.out.println(event.getChannelId());
  36. System.out.println(event.getTimestamp());
  37. System.out.println(event.getSignature());
  38. System.out.println(event.getValidationCode());
  39. System.out.println(event.getType());
  40. return event.getTransactionID();
  41. }).exceptionally(e -> {
  42. e.printStackTrace();
  43. return null;
  44. }).get(10000, TimeUnit.MILLISECONDS);
  45. System.out.println("-------------->>>>>>>" + result);
  46. }
  47. @Test
  48. public void testUpgrade3DeployTemplate() throws Exception {
  49. UpgradeOptions options = new UpgradeOptions();
  50. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG).setChaincodeVersion("11.2");
  51. options.setEndorsementPolicyFile(Paths.get(operations.getConfig().getEndorsementPolicyFilePath()).toFile());
  52. InstallOptions installOptions = new InstallOptions().setChaincodeUpgradeVersion("11.2");
  53. installOptions.setChaincodeId(options.getChaincodeId()).setChaincodeType(CHAIN_CODE_LANG);
  54. String chaincodeSourceFile = operations.getConfig().getChaincodeRootPath();
  55. if (!operations.checkInstallChaincode(installOptions.getChaincodeId())) {
  56. operations.install(installOptions, chaincodeSourceFile);
  57. }
  58. TransactionEvent event = operations.upgradeFor(options, "init");
  59. System.out.println("-------------->>>>>>>" + event);
  60. }

4、交易 Chaincode

交易是最常用的业务接口调用方式,一般交易分为查询交易和修改交易请求两种。

4.1、创建交易模板类 ChaincodeTransactionOperations

同样可以支持自定义传入 configstore 的实现

  1. private ChaincodeTransactionOperations operations;
  2. @Before
  3. public void setup() {
  4. operations = new ChaincodeTransactionTemplate(foo, org1, FabricPropertiesConfiguration.getInstance());
  5. //operations = new ChaincodeTransactionTemplate(foo, org1, FabricPropertiesConfiguration.getInstance(), new File("my-kv-store.properties"));
  6. //operations = new ChaincodeTransactionTemplate(foo, org1, FabricPropertiesConfiguration.getInstance(), new MemoryKeyValueStore());
  7. }

4.2、Chaincode invoke

执行交易执行3种不同方式的结果返回形式,普通的结果封装 ResultSet 和 异步线程模型结果 CompletableFuture<TransactionEvent> 以及 TransactionEvent 结果返回,适用于不同的业务场景需求。

  1. @Test
  2. public void testInvokeTransactionTemplate() {
  3. InvokeOptions options = new InvokeOptions();
  4. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  5. options.setClientUserContext(operations.getOrganization().getUser("user1"));
  6. ResultSet rs = operations.invoke(options, "move", "a", "b", 20);
  7. System.out.println(rs);
  8. try {
  9. TransactionEvent event = operations.getChannel().sendTransaction(rs.getResponses()).get();
  10. System.out.println(event.isValid());
  11. System.out.println(event.getBlockEvent());
  12. } catch (InterruptedException | ExecutionException e) {
  13. e.printStackTrace();
  14. }
  15. }
  16. @Test
  17. public void testInvokeTransactionTemplate2() throws InterruptedException, ExecutionException, TimeoutException {
  18. InvokeOptions options = new InvokeOptions();
  19. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  20. options.setClientUserContext(operations.getOrganization().getUser("user1"));
  21. CompletableFuture<TransactionEvent> future = operations.invokeAsync(options, "move", "b", "a", 3);
  22. future.thenApply((BlockEvent.TransactionEvent transactionEvent) -> {
  23. // 必须是有效交易事件
  24. checkArgument(transactionEvent.isValid(), "没有签名的交易事件");
  25. // 必须有签名
  26. checkNotNull(transactionEvent.getSignature(), "没有签名的交易事件");
  27. // 必须有交易区块事件发生
  28. BlockEvent blockEvent = checkNotNull(transactionEvent.getBlockEvent(), "交易事件的区块事件对象为空");
  29. try {
  30. System.out.println("成功实例化Chaincode,本次实例化交易ID:" + transactionEvent.getTransactionID());
  31. System.out.println(transactionEvent.getChannelId());
  32. checkArgument(StringUtils.equals(blockEvent.getChannelId(), operations.getChannel().getName()), "事件名称和对应通道名称不一致");
  33. } catch (Exception e) {
  34. throw new RuntimeException(e);
  35. }
  36. QueryOptions options2 = new QueryOptions();
  37. options2.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  38. options2.setProposalWaitTime(100000);
  39. options2.setSpecificPeers(false);
  40. //operations.instantiate("hoojo3");
  41. options2.setClientUserContext(operations.getOrganization().getUser("hoojo5"));
  42. String a = operations.query(options2, "query", "a");
  43. String b = operations.query(options2, "query", "b");
  44. System.out.println("a mount ---->" + a);
  45. System.out.println("b mount ---->" + b);
  46. return "success";
  47. }).exceptionally(e -> {
  48. if (e instanceof CompletionException && e.getCause() != null) {
  49. e = e.getCause();
  50. }
  51. if (e instanceof TransactionEventException) {
  52. BlockEvent.TransactionEvent te = ((TransactionEventException) e).getTransactionEvent();
  53. if (te != null) {
  54. e.printStackTrace(System.err);
  55. fail(format("Transaction with txid %s failed. %s", te.getTransactionID(), e.getMessage()));
  56. }
  57. }
  58. e.printStackTrace(System.err);
  59. fail(format("Test failed with %s exception %s", e.getClass().getName(), e.getMessage()));
  60. return null;
  61. }).get(operations.getConfig().getTransactionWaitTime(), TimeUnit.SECONDS);
  62. }
  63. @Test
  64. public void testInvokeTransactionTemplate3() {
  65. InvokeOptions options = new InvokeOptions();
  66. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  67. options.setClientUserContext(operations.getOrganization().getUser("user1"));
  68. TransactionEvent event = operations.invokeFor(options, "move", "a", "b", 5);
  69. System.out.println(event.getTransactionID());
  70. System.out.println(event.getCreator().getId());
  71. }

4.3、Chaincode query

查询支持两种结果返回的方式,返回字符串和封装的结果集 ResultSet

  1. @Test
  2. public void testQueryTransactionTemplate() {
  3. QueryOptions options = new QueryOptions();
  4. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  5. options.setProposalWaitTime(100000);
  6. options.setSpecificPeers(false);
  7. operations.instantiate("hoojo3");
  8. options.setClientUserContext(operations.getOrganization().getUser("hoojo3"));
  9. // options.setRequestUser(requestUser);
  10. String rs = operations.query(options, "query", "a");
  11. System.out.println(rs);
  12. rs = operations.query(options, "query", "b");
  13. System.out.println(rs);
  14. }
  15. @Test
  16. public void testQueryTransactionTemplate2() {
  17. QueryOptions options = new QueryOptions();
  18. options.setChaincodeId(chaincodeID_11).setChaincodeType(CHAIN_CODE_LANG);
  19. operations.instantiate("hoojo3");
  20. options.setClientUserContext(operations.getOrganization().getUser("user1"));
  21. options.setRequestUser(operations.getOrganization().getUser("hoojo3"));
  22. ResultSet rs = operations.queryFor(options, "query", "a");
  23. System.out.println(rs);
  24. }

5、问题反馈

如果有任何疑问或交流的想法,欢迎在 issues 发布话题,我会及时跟进。