运行测试Demo——End2endIT.java
运行结果分析
1. 先构建通道foo,把org1加入该通道,运行该通道
run-channel.png
2. 初始化a为100,b为200,并把此交易送至orderer中
set-a-b.png
3. a转账100给b,背书后,把交易送至orderer
a-100to-b.png
4. 查询b的值
query-b.png
5. 后面就是创建调用另一个通道bar,进行相同的 *** 作,这里也不详细罗列了
End2endIT源码分析(注释都在代码中)1. 先执行checkConfig()方法检查配置项
@Before public void checkConfig() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, MalformedURLException, org.hyperledger.fabric_ca.sdk.exception.InvalidArgumentException { out("nnnRUNNING: %s.n", testName); resetConfig();//先重置配置文件org.hyperledger.fabric.sdk.helper.Config,config主要是fabric需要的配置项 configHelper.customizeConfig();//调用命令行输入的指定变量,覆盖掉上面的Config配置 testSampleOrgs = testConfig.getIntegrationTestsSampleOrgs();//获取testConfig配置的组织,TestConfig在End2endIT已经被new出来,里面也有大量的测试配置项 for (SampleOrg sampleOrg : testSampleOrgs) {//设置颁发证书的CA证书机构 String caName = sampleOrg.getCAName(); if (caName != null && !caName.isEmpty()) { sampleOrg.setCAClient(HFCAClient.createNewInstance(caName, sampleOrg.getCALocation(), sampleOrg.getCAProperties())); } else { sampleOrg.setCAClient(HFCAClient.createNewInstance(sampleOrg.getCALocation(), sampleOrg.getCAProperties())); } } }
2. 执行setup()方法
@Test public void setup() throws Exception { if (sampleStoreFile.exists()) { sampleStoreFile.delete();//模拟数据库存储使用了HFCSampletest.properties } sampleStore = new SampleStore(sampleStoreFile);//初始化存储 enrollUsersSetup(sampleStore);// 利用ca做初始化 runFabricTest(sampleStore);//核心方法 }
3. 分析enrollUsersSetup()方法
for (SampleOrg sampleOrg : testSampleOrgs) { HFCAClient ca = sampleOrg.getCAClient();//获得ca客户端 final String orgName = sampleOrg.getName();//组织名称 final String mspid = sampleOrg.getMSPID();//组织证书ID ca.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());//设置CA客户端证书套件 if (testConfig.isRunningFabricTLS()) { //从CA客户端获取TLS证书 final EnrollmentRequest enrollmentRequestTLS = new EnrollmentRequest(); enrollmentRequestTLS.addHost("localhost"); enrollmentRequestTLS.setProfile("tls"); final Enrollment enroll = ca.enroll("admin", "adminpw", enrollmentRequestTLS); final String tlsCertPEM = enroll.getCert(); final String tlsKeyPEM = getPEMStringFromPrivateKey(enroll.getKey()); final Properties tlsProperties = new Properties(); tlsProperties.put("clientKeyBytes", tlsKeyPEM.getBytes(UTF_8)); tlsProperties.put("clientCertBytes", tlsCertPEM.getBytes(UTF_8)); clientTLSProperties.put(sampleOrg.getName(), tlsProperties); sampleStore.storeClientPEMTLCertificate(sampleOrg, tlsCertPEM); sampleStore.storeClientPEMTLSKey(sampleOrg, tlsKeyPEM); } //检查是否连接成功 HFCAInfo info = ca.info(); assertNotNull(info); String infoname = info.getCAName(); if (infoname != null && !infoName.isEmpty()) { assertEquals(ca.getCAName(), infoName); } //获取组织管理员(admin) SampleUser admin = sampleStore.getMember(TEST_ADMIN_NAME, orgName); if (!admin.isEnrolled()) { //管理员只需在CA客户端进行登记 admin.setEnrollment(ca.enroll(admin.getName(), "adminpw")); admin.setMspId(mspid); } //获取普通用户 SampleUser user = sampleStore.getMember(testUser1, sampleOrg.getName()); if (!user.isRegistered()) { //如果未注册则生成注册请求 RegistrationRequest rr = new RegistrationRequest(user.getName(), "org1.department1"); //设置密码(注册请求发出去后,CA会返回一个密码) user.setEnrollmentSecret(ca.register(rr, admin)); } if (!user.isEnrolled()) { //如果未登记则登记 user.setEnrollment(ca.enroll(user.getName(), user.getEnrollmentSecret())); user.setMspId(mspid); } final String sampleOrgName = sampleOrg.getName(); final String sampleOrgDomainName = sampleOrg.getDomainName();//获取组织的命名域 //使用证书文件生成用户信息 SampleUser peerOrgAdmin = sampleStore.getMember(sampleOrgName + "Admin", sampleOrgName, sampleOrg.getMSPID(), Util.findFileSk(Paths.get(testConfig.getTestChannelPath(), "crypto-config/peerOrganizations/", sampleOrgDomainName, format("/users/Admin@%s/msp/keystore", sampleOrgDomainName)).toFile()), Paths.get(testConfig.getTestChannelPath(), "crypto-config/peerOrganizations/", sampleOrgDomainName, format("/users/Admin@%s/msp/signcerts/Admin@%s-cert.pem", sampleOrgDomainName, sampleOrgDomainName)).toFile()); sampleOrg.setPeerAdmin(peerOrgAdmin);//设置节点管理员(一个特殊的用户,可以创建通道,加入节点以及安装链码) sampleOrg.addUser(user);//组织内添加用户 sampleOrg.setAdmin(admin); //设置管理员身份 }
4. 分析 runFabricTest()方法
// Setup client //Create instance of client. HFClient client = HFClient.createNewInstance();//初始化一个客户端,类似cli client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());//设置加密算法 //Construct and run the channels // 获取peerOrg1组织1 SampleOrg sampleOrg = testConfig.getIntegrationTestsSampleOrg("peerOrg1"); // 构建一个channel通道,Org1加入到该通道中 Channel fooChannel = constructChannel(FOO_CHANNEL_NAME, client, sampleOrg); // 保存通道名称到数据库中(这里是存储到上面方法文件) sampleStore.saveChannel(fooChannel); // 安装链码、实例化链码、执行一个查询测试 runChannel(client, fooChannel, true, sampleOrg, 0); assertFalse(fooChannel.isShutdown()); fooChannel.shutdown(true); // Force foo channel to shutdown clean up resources. assertTrue(fooChannel.isShutdown()); assertNull(client.getChannel(FOO_CHANNEL_NAME)); out("n"); // 下面是组织2的过程,跟组织1是类似的 sampleOrg = testConfig.getIntegrationTestsSampleOrg("peerOrg2"); Channel barChannel = constructChannel(BAR_CHANNEL_NAME, client, sampleOrg); assertTrue(barChannel.isInitialized()); sampleStore.saveChannel(barChannel); assertFalse(barChannel.isShutdown()); runChannel(client, barChannel, true, sampleOrg, 100); //run a newly constructed bar channel with different b value! //let bar channel just shutdown so we have both scenarios. out("nTraverse the blocks for chain %s ", barChannel.getName()); // 对区块进行各种查询,包括区块读写集、区块数量高度等 blockWalker(client, barChannel); assertFalse(barChannel.isShutdown()); assertTrue(barChannel.isInitialized()); out("That's all folks!");
5. 分析constructChannel()方法(重点1)
a. 获取peer的admin用户,实际上是crytogen根据crypto-config.yaml配置的默认admin账户
SampleUser peerAdmin = sampleOrg.getPeerAdmin(); client.setUserContext(peerAdmin);
b. 接着是初始化orderer排序节点对象
Collectionorderers = new linkedList<>(); for (String orderName : sampleOrg.getOrdererNames()) { Properties ordererProperties = testConfig.getOrdererProperties(orderName); //example of setting keepAlive to avoid timeouts on inactive http2 connections. // Under 5 minutes would require changes to server side to accept faster ping rates. ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveTime", new Object[] {5L, TimeUnit.MINUTES}); ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveTimeout", new Object[] {8L, TimeUnit.SECONDS}); ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveWithoutCalls", new Object[] {true}); orderers.add(client.newOrderer(orderName, sampleOrg.getOrdererLocation(orderName), ordererProperties)); }
c. 创建一个channel,这里使用的是Configtxgen 生成的“通道配置”文件
//Just pick the first orderer in the list to create the channel. Orderer anOrderer = orderers.iterator().next();//选择第一个排序节点进行创建通道 orderers.remove(anOrderer); //从排序节点集合中移除已经在使用的节点 //通过读取channel.tx文件,生成信道配置对象 ChannelConfiguration channelConfiguration = new ChannelConfiguration(new File(TEST_FIXTURES_PATH + "/sdkintegration/e2e-2Orgs/channel/" + name + ".tx")); //创建信道对象,只有一个签名,就是组织节点管理员。如果创建信道策略需要更多的签名,那么他们必须添加 Channel newChannel = client.newChannel(name, anOrderer, channelConfiguration, client.getChannelConfigurationSignature(channelConfiguration, sampleOrg.getPeerAdmin())); out("Created channel %s", name);
d. client.newPeer创建peer节点,然后joinPeer加入通道channel中
boolean everyother = true; //test with both cases when doing peer eventing. for (String peerName : sampleOrg.getPeerNames()) { String peerLocation = sampleOrg.getPeerLocation(peerName);//获取节点位置 Properties peerProperties = testConfig.getPeerProperties(peerName); //获取节点属性 if (peerProperties == null) { peerProperties = new Properties(); } //Example of setting specific options on grpc's NettyChannelBuilder peerProperties.put("grpc.NettyChannelBuilderOption.maxInboundMessageSize", 9000000); Peer peer = client.newPeer(peerName, peerLocation, peerProperties);//通过客户端生成节点对象 if (testConfig.isFabricVersionAtOrAfter("1.3")) { //加入生成的节点 newChannel.joinPeer(peer, createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.ENDORSING_PEER, PeerRole.LEDGER_QUERY, PeerRole.CHAINCODE_QUERY, PeerRole.EVENT_SOURCE))); //Default is all roles. } else { if (doPeerEventing && everyother) { newChannel.joinPeer(peer, createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.ENDORSING_PEER, PeerRole.LEDGER_QUERY, PeerRole.CHAINCODE_QUERY, PeerRole.EVENT_SOURCE))); //Default is all roles. } else { // Set peer to not be all roles but eventing. newChannel.joinPeer(peer, createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.ENDORSING_PEER, PeerRole.LEDGER_QUERY, PeerRole.CHAINCODE_QUERY))); } } out("Peer %s joined channel %s", peerName, name); everyother = !everyother; }
e. 给channel设置监听事件的grpc接口,最后进行初始化
//获取组织内事件记录节点集合 for (String eventHubName : sampleOrg.getEventHubNames()) { //获取事件记录属性 final Properties eventHubProperties = testConfig.getEventHubProperties(eventHubName); eventHubProperties.put("grpc.NettyChannelBuilderOption.keepAliveTime", new Object[] {5L, TimeUnit.MINUTES}); eventHubProperties.put("grpc.NettyChannelBuilderOption.keepAliveTimeout", new Object[] {8L, TimeUnit.SECONDS}); EventHub eventHub = client.newEventHub(eventHubName, sampleOrg.getEventHubLocation(eventHubName), eventHubProperties); newChannel.addEventHub(eventHub); } //信道实例化 newChannel.initialize(); out("Finished initialization channel %s", name);
6.分析runChannel()方法(重点2)
a. 安装链码
if (installChaincode) { //一大段设置安装的链码信息 // ....... //发送安装链码的交易提案 responses = client.sendInstallProposal(installProposalRequest, peers); //检查返回的结果,并输出相应的信息 //.......
b. 实例化链码,设置背书策略
//实例化链码 InstantiateProposalRequest instantiateProposalRequest = client.newInstantiationProposalRequest(); instantiateProposalRequest.setProposalWaitTime(DEPLOYWAITTIME); instantiateProposalRequest.setChaincodeID(chaincodeID); instantiateProposalRequest.setChaincodeLanguage(CHAIN_CODE_LANG); instantiateProposalRequest.setFcn("init"); instantiateProposalRequest.setArgs(new String[] {"a", "500", "b", "" + (200 + delta)}); Maptm = new HashMap<>(); tm.put("HyperLedgerFabric", "InstantiateProposalRequest:JavaSDK".getBytes(UTF_8)); tm.put("method", "InstantiateProposalRequest".getBytes(UTF_8)); instantiateProposalRequest.setTransientMap(tm); //设置背书策略 ChaincodeEndorsementPolicy chaincodeEndorsementPolicy = new ChaincodeEndorsementPolicy(); chaincodeEndorsementPolicy.fromYamlFile(new File(TEST_FIXTURES_PATH + "/sdkintegration/chaincodeendorsementpolicy.yaml")); instantiateProposalRequest.setChaincodeEndorsementPolicy(chaincodeEndorsementPolicy); out("Sending instantiateProposalRequest to all peers with arguments: a and b set to 100 and %s respectively", "" + (200 + delta)); successful.clear(); failed.clear(); //检查结果,并输出相应信息
c. 转账,查询,异常处理
channel.sendTransaction(successful, createTransactionOptions() .userContext(client.getUserContext()) .shuffleOrders(false) .orderers(channel.getOrderers()) .nOfEvents(nOfEvents) ).thenApply(transactionEvent -> { //....... // 调用example_cc.go里面的move方法,a给b转账 }.thenApply(transactionEvent -> { //........ // query查询b的余额 try { }).exceptionally(e -> { //........ // 异常处理 }
d. 查询区块高度,信息之类的
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)