Search in sources :

Example 1 with BlockEvent

use of org.hyperledger.fabric.sdk.BlockEvent in project fabric-sdk-java by hyperledger.

the class End2endIT method runChannel.

// CHECKSTYLE.OFF: Method length is 320 lines (max allowed is 150).
void runChannel(HFClient client, Channel channel, boolean installChaincode, SampleOrg sampleOrg, int delta) {
    class ChaincodeEventCapture {

        final String handle;

        final BlockEvent blockEvent;

        final ChaincodeEvent chaincodeEvent;

        ChaincodeEventCapture(String handle, BlockEvent blockEvent, ChaincodeEvent chaincodeEvent) {
            this.handle = handle;
            this.blockEvent = blockEvent;
            this.chaincodeEvent = chaincodeEvent;
        }
    }
    // Test list to capture chaincode events.
    Vector<ChaincodeEventCapture> chaincodeEvents = new Vector<>();
    try {
        final String channelName = channel.getName();
        boolean isFooChain = FOO_CHANNEL_NAME.equals(channelName);
        out("Running channel %s", channelName);
        Collection<Orderer> orderers = channel.getOrderers();
        final ChaincodeID chaincodeID;
        Collection<ProposalResponse> responses;
        Collection<ProposalResponse> successful = new LinkedList<>();
        Collection<ProposalResponse> failed = new LinkedList<>();
        // Register a chaincode event listener that will trigger for any chaincode id and only for EXPECTED_EVENT_NAME event.
        String chaincodeEventListenerHandle = channel.registerChaincodeEventListener(Pattern.compile(".*"), Pattern.compile(Pattern.quote(EXPECTED_EVENT_NAME)), (handle, blockEvent, chaincodeEvent) -> {
            chaincodeEvents.add(new ChaincodeEventCapture(handle, blockEvent, chaincodeEvent));
            String es = blockEvent.getPeer() != null ? blockEvent.getPeer().getName() : blockEvent.getEventHub().getName();
            out("RECEIVED Chaincode event with handle: %s, chaincode Id: %s, chaincode event name: %s, " + "transaction id: %s, event payload: \"%s\", from eventhub: %s", handle, chaincodeEvent.getChaincodeId(), chaincodeEvent.getEventName(), chaincodeEvent.getTxId(), new String(chaincodeEvent.getPayload()), es);
        });
        // For non foo channel unregister event listener to test events are not called.
        if (!isFooChain) {
            channel.unregisterChaincodeEventListener(chaincodeEventListenerHandle);
            chaincodeEventListenerHandle = null;
        }
        ChaincodeID.Builder chaincodeIDBuilder = ChaincodeID.newBuilder().setName(CHAIN_CODE_NAME).setVersion(CHAIN_CODE_VERSION);
        if (null != CHAIN_CODE_PATH) {
            chaincodeIDBuilder.setPath(CHAIN_CODE_PATH);
        }
        chaincodeID = chaincodeIDBuilder.build();
        if (installChaincode) {
            // //////////////////////////
            // Install Proposal Request
            // 
            client.setUserContext(sampleOrg.getPeerAdmin());
            out("Creating install proposal");
            InstallProposalRequest installProposalRequest = client.newInstallProposalRequest();
            installProposalRequest.setChaincodeID(chaincodeID);
            if (isFooChain) {
                // on foo chain install from directory.
                // //For GO language and serving just a single user, chaincodeSource is mostly likely the users GOPATH
                installProposalRequest.setChaincodeSourceLocation(Paths.get(TEST_FIXTURES_PATH, CHAIN_CODE_FILEPATH).toFile());
            } else {
                if (CHAIN_CODE_LANG.equals(Type.GO_LANG)) {
                    installProposalRequest.setChaincodeInputStream(Util.generateTarGzInputStream((Paths.get(TEST_FIXTURES_PATH, CHAIN_CODE_FILEPATH, "src", CHAIN_CODE_PATH).toFile()), Paths.get("src", CHAIN_CODE_PATH).toString()));
                } else {
                    installProposalRequest.setChaincodeInputStream(Util.generateTarGzInputStream((Paths.get(TEST_FIXTURES_PATH, CHAIN_CODE_FILEPATH).toFile()), "src"));
                }
            }
            installProposalRequest.setChaincodeVersion(CHAIN_CODE_VERSION);
            installProposalRequest.setChaincodeLanguage(CHAIN_CODE_LANG);
            out("Sending install proposal");
            // //////////////////////////
            // only a client from the same org as the peer can issue an install request
            int numInstallProposal = 0;
            // Set<String> orgs = orgPeers.keySet();
            // for (SampleOrg org : testSampleOrgs) {
            Collection<Peer> peers = channel.getPeers();
            numInstallProposal = numInstallProposal + peers.size();
            responses = client.sendInstallProposal(installProposalRequest, peers);
            for (ProposalResponse response : responses) {
                if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
                    out("Successful install proposal response Txid: %s from peer %s", response.getTransactionID(), response.getPeer().getName());
                    successful.add(response);
                } else {
                    failed.add(response);
                }
            }
            // }
            out("Received %d install proposal responses. Successful+verified: %d . Failed: %d", numInstallProposal, successful.size(), failed.size());
            if (failed.size() > 0) {
                ProposalResponse first = failed.iterator().next();
                fail("Not enough endorsers for install :" + successful.size() + ".  " + first.getMessage());
            }
        }
        // client.setUserContext(sampleOrg.getUser(TEST_ADMIN_NAME));
        // final ChaincodeID chaincodeID = firstInstallProposalResponse.getChaincodeID();
        // Note installing chaincode does not require transaction no need to
        // send to Orderers
        // /////////////
        // // Instantiate chaincode.
        InstantiateProposalRequest instantiateProposalRequest = client.newInstantiationProposalRequest();
        instantiateProposalRequest.setProposalWaitTime(testConfig.getProposalWaitTime());
        instantiateProposalRequest.setChaincodeID(chaincodeID);
        instantiateProposalRequest.setChaincodeLanguage(CHAIN_CODE_LANG);
        instantiateProposalRequest.setFcn("init");
        instantiateProposalRequest.setArgs(new String[] { "a", "500", "b", "" + (200 + delta) });
        Map<String, byte[]> tm = new HashMap<>();
        tm.put("HyperLedgerFabric", "InstantiateProposalRequest:JavaSDK".getBytes(UTF_8));
        tm.put("method", "InstantiateProposalRequest".getBytes(UTF_8));
        instantiateProposalRequest.setTransientMap(tm);
        /*
              policy OR(Org1MSP.member, Org2MSP.member) meaning 1 signature from someone in either Org1 or Org2
              See README.md Chaincode endorsement policies section for more details.
            */
        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();
        if (isFooChain) {
            // Send responses both ways with specifying peers and by using those on the channel.
            responses = channel.sendInstantiationProposal(instantiateProposalRequest, channel.getPeers());
        } else {
            responses = channel.sendInstantiationProposal(instantiateProposalRequest);
        }
        for (ProposalResponse response : responses) {
            if (response.isVerified() && response.getStatus() == ProposalResponse.Status.SUCCESS) {
                successful.add(response);
                out("Succesful instantiate proposal response Txid: %s from peer %s", response.getTransactionID(), response.getPeer().getName());
            } else {
                failed.add(response);
            }
        }
        out("Received %d instantiate proposal responses. Successful+verified: %d . Failed: %d", responses.size(), successful.size(), failed.size());
        if (failed.size() > 0) {
            for (ProposalResponse fail : failed) {
                out("Not enough endorsers for instantiate :" + successful.size() + "endorser failed with " + fail.getMessage() + ", on peer" + fail.getPeer());
            }
            ProposalResponse first = failed.iterator().next();
            fail("Not enough endorsers for instantiate :" + successful.size() + "endorser failed with " + first.getMessage() + ". Was verified:" + first.isVerified());
        }
        // /////////////
        // / Send instantiate transaction to orderer
        out("Sending instantiateTransaction to orderer with a and b set to 100 and %s respectively", "" + (200 + delta));
        // Specify what events should complete the interest in this transaction. This is the default
        // for all to complete. It's possible to specify many different combinations like
        // any from a group, all from one group and just one from another or even None(NOfEvents.createNoEvents).
        // See. Channel.NOfEvents
        Channel.NOfEvents nOfEvents = createNofEvents();
        if (!channel.getPeers(EnumSet.of(PeerRole.EVENT_SOURCE)).isEmpty()) {
            nOfEvents.addPeers(channel.getPeers(EnumSet.of(PeerRole.EVENT_SOURCE)));
        }
        if (!channel.getEventHubs().isEmpty()) {
            nOfEvents.addEventHubs(channel.getEventHubs());
        }
        channel.sendTransaction(successful, // Basically the default options but shows it's usage.
        createTransactionOptions().userContext(// could be a different user context. this is the default.
        client.getUserContext()).shuffleOrders(// don't shuffle any orderers the default is true.
        false).orderers(// specify the orderers we want to try this transaction. Fails once all Orderers are tried.
        channel.getOrderers()).nOfEvents(// The events to signal the completion of the interest in the transaction
        nOfEvents)).thenApply(transactionEvent -> {
            waitOnFabric(0);
            // must be valid to be here.
            assertTrue(transactionEvent.isValid());
            // musth have a signature.
            assertNotNull(transactionEvent.getSignature());
            // This is the blockevent that has this transaction.
            BlockEvent blockEvent = transactionEvent.getBlockEvent();
            // Make sure the RAW Fabric block is returned.
            assertNotNull(blockEvent.getBlock());
            out("Finished instantiate transaction with transaction id %s", transactionEvent.getTransactionID());
            try {
                assertEquals(blockEvent.getChannelId(), channel.getName());
                successful.clear();
                failed.clear();
                client.setUserContext(sampleOrg.getUser(TESTUSER_1_NAME));
                // /////////////
                // / Send transaction proposal to all peers
                TransactionProposalRequest transactionProposalRequest = client.newTransactionProposalRequest();
                transactionProposalRequest.setChaincodeID(chaincodeID);
                transactionProposalRequest.setChaincodeLanguage(CHAIN_CODE_LANG);
                // transactionProposalRequest.setFcn("invoke");
                transactionProposalRequest.setFcn("move");
                transactionProposalRequest.setProposalWaitTime(testConfig.getProposalWaitTime());
                transactionProposalRequest.setArgs("a", "b", "100");
                Map<String, byte[]> tm2 = new HashMap<>();
                // Just some extra junk in transient map
                tm2.put("HyperLedgerFabric", "TransactionProposalRequest:JavaSDK".getBytes(UTF_8));
                // ditto
                tm2.put("method", "TransactionProposalRequest".getBytes(UTF_8));
                // This should be returned see chaincode why.
                tm2.put("result", ":)".getBytes(UTF_8));
                // This should trigger an event see chaincode why.
                tm2.put(EXPECTED_EVENT_NAME, EXPECTED_EVENT_DATA);
                transactionProposalRequest.setTransientMap(tm2);
                out("sending transactionProposal to all peers with arguments: move(a,b,100)");
                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);
                    }
                }
                // Check that all the proposals are consistent with each other. We should have only one set
                // where all the proposals above are consistent. Note the when sending to Orderer this is done automatically.
                // Shown here as an example that applications can invoke and select.
                // See org.hyperledger.fabric.sdk.proposal.consistency_validation config property.
                Collection<Set<ProposalResponse>> proposalConsistencySets = SDKUtils.getProposalConsistencySets(transactionPropResp);
                if (proposalConsistencySets.size() != 1) {
                    fail(format("Expected only one set of consistent proposal responses but got %d", proposalConsistencySets.size()));
                }
                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 invoke(move a,b,100):" + failed.size() + " endorser error: " + firstTransactionProposalResponse.getMessage() + ". Was verified: " + firstTransactionProposalResponse.isVerified());
                }
                out("Successfully received transaction proposal responses.");
                ProposalResponse resp = successful.iterator().next();
                // This is the data returned by the chaincode.
                byte[] x = resp.getChaincodeActionResponsePayload();
                String resultAsString = null;
                if (x != null) {
                    resultAsString = new String(x, "UTF-8");
                }
                assertEquals(":)", resultAsString);
                // Chaincode's status.
                assertEquals(200, resp.getChaincodeActionResponseStatus());
                TxReadWriteSetInfo readWriteSetInfo = resp.getChaincodeActionResponseReadWriteSetInfo();
                // See blockwalker below how to transverse this
                assertNotNull(readWriteSetInfo);
                assertTrue(readWriteSetInfo.getNsRwsetCount() > 0);
                ChaincodeID cid = resp.getChaincodeID();
                assertNotNull(cid);
                final String path = cid.getPath();
                if (null == CHAIN_CODE_PATH) {
                    assertTrue(path == null || "".equals(path));
                } else {
                    assertEquals(CHAIN_CODE_PATH, path);
                }
                assertEquals(CHAIN_CODE_NAME, cid.getName());
                assertEquals(CHAIN_CODE_VERSION, cid.getVersion());
                // //////////////////////////
                // Send Transaction Transaction to orderer
                out("Sending chaincode transaction(move a,b,100) to orderer.");
                return channel.sendTransaction(successful).get(testConfig.getTransactionWaitTime(), TimeUnit.SECONDS);
            } catch (Exception e) {
                out("Caught an exception while invoking chaincode");
                e.printStackTrace();
                fail("Failed invoking chaincode with error : " + e.getMessage());
            }
            return null;
        }).thenApply(transactionEvent -> {
            try {
                waitOnFabric(0);
                // must be valid to be here.
                assertTrue(transactionEvent.isValid());
                out("Finished transaction with transaction id %s", transactionEvent.getTransactionID());
                // used in the channel queries later
                testTxID = transactionEvent.getTransactionID();
                // //////////////////////////
                // Send Query Proposal to all peers
                // 
                String expect = "" + (300 + delta);
                out("Now query chaincode for the value of b.");
                QueryByChaincodeRequest queryByChaincodeRequest = client.newQueryProposalRequest();
                queryByChaincodeRequest.setArgs(new String[] { "b" });
                queryByChaincodeRequest.setFcn("query");
                queryByChaincodeRequest.setChaincodeID(chaincodeID);
                Map<String, byte[]> tm2 = new HashMap<>();
                tm2.put("HyperLedgerFabric", "QueryByChaincodeRequest:JavaSDK".getBytes(UTF_8));
                tm2.put("method", "QueryByChaincodeRequest".getBytes(UTF_8));
                queryByChaincodeRequest.setTransientMap(tm2);
                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(payload, expect);
                    }
                }
                return null;
            } catch (Exception e) {
                out("Caught exception while running query");
                e.printStackTrace();
                fail("Failed during chaincode query with error : " + e.getMessage());
            }
            return null;
        }).exceptionally(e -> {
            if (e instanceof TransactionEventException) {
                BlockEvent.TransactionEvent te = ((TransactionEventException) e).getTransactionEvent();
                if (te != null) {
                    throw new AssertionError(format("Transaction with txid %s failed. %s", te.getTransactionID(), e.getMessage()), e);
                }
            }
            throw new AssertionError(format("Test failed with %s exception %s", e.getClass().getName(), e.getMessage()), e);
        }).get(testConfig.getTransactionWaitTime(), TimeUnit.SECONDS);
        // Channel queries
        // We can only send channel queries to peers that are in the same org as the SDK user context
        // Get the peers from the current org being used and pick one randomly to send the queries to.
        // Set<Peer> peerSet = sampleOrg.getPeers();
        // Peer queryPeer = peerSet.iterator().next();
        // out("Using peer %s for channel queries", queryPeer.getName());
        BlockchainInfo channelInfo = channel.queryBlockchainInfo();
        out("Channel info for : " + channelName);
        out("Channel height: " + channelInfo.getHeight());
        String chainCurrentHash = Hex.encodeHexString(channelInfo.getCurrentBlockHash());
        String chainPreviousHash = Hex.encodeHexString(channelInfo.getPreviousBlockHash());
        out("Chain current block hash: " + chainCurrentHash);
        out("Chainl previous block hash: " + chainPreviousHash);
        // Query by block number. Should return latest block, i.e. block number 2
        BlockInfo returnedBlock = channel.queryBlockByNumber(channelInfo.getHeight() - 1);
        String previousHash = Hex.encodeHexString(returnedBlock.getPreviousHash());
        out("queryBlockByNumber returned correct block with blockNumber " + returnedBlock.getBlockNumber() + " \n previous_hash " + previousHash);
        assertEquals(channelInfo.getHeight() - 1, returnedBlock.getBlockNumber());
        assertEquals(chainPreviousHash, previousHash);
        // Query by block hash. Using latest block's previous hash so should return block number 1
        byte[] hashQuery = returnedBlock.getPreviousHash();
        returnedBlock = channel.queryBlockByHash(hashQuery);
        out("queryBlockByHash returned block with blockNumber " + returnedBlock.getBlockNumber());
        assertEquals(channelInfo.getHeight() - 2, returnedBlock.getBlockNumber());
        // Query block by TxID. Since it's the last TxID, should be block 2
        returnedBlock = channel.queryBlockByTransactionID(testTxID);
        out("queryBlockByTxID returned block with blockNumber " + returnedBlock.getBlockNumber());
        assertEquals(channelInfo.getHeight() - 1, returnedBlock.getBlockNumber());
        // query transaction by ID
        TransactionInfo txInfo = channel.queryTransactionByID(testTxID);
        out("QueryTransactionByID returned TransactionInfo: txID " + txInfo.getTransactionID() + "\n     validation code " + txInfo.getValidationCode().getNumber());
        if (chaincodeEventListenerHandle != null) {
            channel.unregisterChaincodeEventListener(chaincodeEventListenerHandle);
            // Should be two. One event in chaincode and two notification for each of the two event hubs
            final int numberEventsExpected = channel.getEventHubs().size() + channel.getPeers(EnumSet.of(PeerRole.EVENT_SOURCE)).size();
            // just make sure we get the notifications.
            for (int i = 15; i > 0; --i) {
                if (chaincodeEvents.size() == numberEventsExpected) {
                    break;
                } else {
                    // wait for the events.
                    Thread.sleep(90);
                }
            }
            assertEquals(numberEventsExpected, chaincodeEvents.size());
            for (ChaincodeEventCapture chaincodeEventCapture : chaincodeEvents) {
                assertEquals(chaincodeEventListenerHandle, chaincodeEventCapture.handle);
                assertEquals(testTxID, chaincodeEventCapture.chaincodeEvent.getTxId());
                assertEquals(EXPECTED_EVENT_NAME, chaincodeEventCapture.chaincodeEvent.getEventName());
                assertTrue(Arrays.equals(EXPECTED_EVENT_DATA, chaincodeEventCapture.chaincodeEvent.getPayload()));
                assertEquals(CHAIN_CODE_NAME, chaincodeEventCapture.chaincodeEvent.getChaincodeId());
                BlockEvent blockEvent = chaincodeEventCapture.blockEvent;
                assertEquals(channelName, blockEvent.getChannelId());
            // assertTrue(channel.getEventHubs().contains(blockEvent.getEventHub()));
            }
        } else {
            assertTrue(chaincodeEvents.isEmpty());
        }
        out("Running for Channel %s done", channelName);
    } catch (Exception e) {
        out("Caught an exception running channel %s", channel.getName());
        e.printStackTrace();
        fail("Test failed with error : " + e.getMessage());
    }
}
Also used : Arrays(java.util.Arrays) InvalidProtocolBufferRuntimeException(org.hyperledger.fabric.sdk.exception.InvalidProtocolBufferRuntimeException) InstantiateProposalRequest(org.hyperledger.fabric.sdk.InstantiateProposalRequest) TxReadWriteSetInfo(org.hyperledger.fabric.sdk.TxReadWriteSetInfo) Vector(java.util.Vector) BlockInfo(org.hyperledger.fabric.sdk.BlockInfo) Type(org.hyperledger.fabric.sdk.TransactionRequest.Type) Map(java.util.Map) TestConfigHelper(org.hyperledger.fabric.sdk.TestConfigHelper) Assert.fail(org.junit.Assert.fail) EnumSet(java.util.EnumSet) ChannelConfiguration(org.hyperledger.fabric.sdk.ChannelConfiguration) Orderer(org.hyperledger.fabric.sdk.Orderer) InvalidArgumentException(org.hyperledger.fabric.sdk.exception.InvalidArgumentException) TestConfig(org.hyperledger.fabric.sdk.testutils.TestConfig) Collection(java.util.Collection) ProposalException(org.hyperledger.fabric.sdk.exception.ProposalException) Channel(org.hyperledger.fabric.sdk.Channel) Set(java.util.Set) String.format(java.lang.String.format) EnrollmentRequest(org.hyperledger.fabric_ca.sdk.EnrollmentRequest) PrivateKey(java.security.PrivateKey) Enrollment(org.hyperledger.fabric.sdk.Enrollment) Peer(org.hyperledger.fabric.sdk.Peer) Assert.assertFalse(org.junit.Assert.assertFalse) Pattern(java.util.regex.Pattern) ChaincodeEvent(org.hyperledger.fabric.sdk.ChaincodeEvent) ChaincodeID(org.hyperledger.fabric.sdk.ChaincodeID) EventHub(org.hyperledger.fabric.sdk.EventHub) HFClient(org.hyperledger.fabric.sdk.HFClient) PeerRole(org.hyperledger.fabric.sdk.Peer.PeerRole) NOfEvents.createNofEvents(org.hyperledger.fabric.sdk.Channel.NOfEvents.createNofEvents) HashMap(java.util.HashMap) Hex(org.apache.commons.codec.binary.Hex) QueryByChaincodeRequest(org.hyperledger.fabric.sdk.QueryByChaincodeRequest) TransactionOptions.createTransactionOptions(org.hyperledger.fabric.sdk.Channel.TransactionOptions.createTransactionOptions) TransactionEventException(org.hyperledger.fabric.sdk.exception.TransactionEventException) BlockchainInfo(org.hyperledger.fabric.sdk.BlockchainInfo) BlockEvent(org.hyperledger.fabric.sdk.BlockEvent) LinkedList(java.util.LinkedList) SDKUtils(org.hyperledger.fabric.sdk.SDKUtils) HFCAClient(org.hyperledger.fabric_ca.sdk.HFCAClient) Before(org.junit.Before) InstallProposalRequest(org.hyperledger.fabric.sdk.InstallProposalRequest) HFCAInfo(org.hyperledger.fabric_ca.sdk.HFCAInfo) Properties(java.util.Properties) ChaincodeEndorsementPolicy(org.hyperledger.fabric.sdk.ChaincodeEndorsementPolicy) ProposalResponse(org.hyperledger.fabric.sdk.ProposalResponse) MalformedURLException(java.net.MalformedURLException) UTF_8(java.nio.charset.StandardCharsets.UTF_8) Assert.assertNotNull(org.junit.Assert.assertNotNull) StringWriter(java.io.StringWriter) TransactionInfo(org.hyperledger.fabric.sdk.TransactionInfo) RegistrationRequest(org.hyperledger.fabric_ca.sdk.RegistrationRequest) Assert.assertTrue(org.junit.Assert.assertTrue) IOException(java.io.IOException) Test(org.junit.Test) PeerOptions.createPeerOptions(org.hyperledger.fabric.sdk.Channel.PeerOptions.createPeerOptions) File(java.io.File) KvRwset(org.hyperledger.fabric.protos.ledger.rwset.kvrwset.KvRwset) TimeUnit(java.util.concurrent.TimeUnit) CryptoSuite(org.hyperledger.fabric.sdk.security.CryptoSuite) Assert.assertNull(org.junit.Assert.assertNull) PEMWriter(org.bouncycastle.openssl.PEMWriter) Paths(java.nio.file.Paths) TestUtils.resetConfig(org.hyperledger.fabric.sdk.testutils.TestUtils.resetConfig) TRANSACTION_ENVELOPE(org.hyperledger.fabric.sdk.BlockInfo.EnvelopeType.TRANSACTION_ENVELOPE) Assert.assertEquals(org.junit.Assert.assertEquals) TransactionProposalRequest(org.hyperledger.fabric.sdk.TransactionProposalRequest) HashMap(java.util.HashMap) ChaincodeID(org.hyperledger.fabric.sdk.ChaincodeID) InstantiateProposalRequest(org.hyperledger.fabric.sdk.InstantiateProposalRequest) BlockInfo(org.hyperledger.fabric.sdk.BlockInfo) TransactionInfo(org.hyperledger.fabric.sdk.TransactionInfo) Vector(java.util.Vector) Orderer(org.hyperledger.fabric.sdk.Orderer) ChaincodeEndorsementPolicy(org.hyperledger.fabric.sdk.ChaincodeEndorsementPolicy) TransactionEventException(org.hyperledger.fabric.sdk.exception.TransactionEventException) Peer(org.hyperledger.fabric.sdk.Peer) Channel(org.hyperledger.fabric.sdk.Channel) BlockchainInfo(org.hyperledger.fabric.sdk.BlockchainInfo) LinkedList(java.util.LinkedList) InvalidProtocolBufferRuntimeException(org.hyperledger.fabric.sdk.exception.InvalidProtocolBufferRuntimeException) InvalidArgumentException(org.hyperledger.fabric.sdk.exception.InvalidArgumentException) ProposalException(org.hyperledger.fabric.sdk.exception.ProposalException) TransactionEventException(org.hyperledger.fabric.sdk.exception.TransactionEventException) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) TransactionProposalRequest(org.hyperledger.fabric.sdk.TransactionProposalRequest) InstallProposalRequest(org.hyperledger.fabric.sdk.InstallProposalRequest) QueryByChaincodeRequest(org.hyperledger.fabric.sdk.QueryByChaincodeRequest) TxReadWriteSetInfo(org.hyperledger.fabric.sdk.TxReadWriteSetInfo) Collection(java.util.Collection) ChaincodeEvent(org.hyperledger.fabric.sdk.ChaincodeEvent) ProposalResponse(org.hyperledger.fabric.sdk.ProposalResponse) File(java.io.File) Map(java.util.Map) HashMap(java.util.HashMap) BlockEvent(org.hyperledger.fabric.sdk.BlockEvent)

Example 2 with BlockEvent

use of org.hyperledger.fabric.sdk.BlockEvent in project fabric-sdk-java by hyperledger.

the class End2endAndBackAgainIT method testPeerServiceEventingReplay.

/**
 * This code test the replay feature of the new peer event services.
 * Instead of the default of starting the eventing peer to retrieve the newest block it sets it
 * retrieve starting from the start parameter. Also checks with block and filterblock replays.
 * Depends on end2end and end2endAndBackagain of have fully run to have the blocks need to work with.
 *
 * @param client
 * @param replayTestChannel
 * @param start
 * @param stop
 * @param useFilteredBlocks
 * @throws InvalidArgumentException
 */
private void testPeerServiceEventingReplay(HFClient client, Channel replayTestChannel, final long start, final long stop, final boolean useFilteredBlocks) throws InvalidArgumentException {
    if (testConfig.isRunningAgainstFabric10()) {
        // not supported for v1.0
        return;
    }
    // not yet initialized
    assertFalse(replayTestChannel.isInitialized());
    // not yet shutdown.
    assertFalse(replayTestChannel.isShutdown());
    // Remove all peers just have one ledger peer and one eventing peer.
    List<Peer> savedPeers = new ArrayList<>(replayTestChannel.getPeers());
    for (Peer peer : savedPeers) {
        replayTestChannel.removePeer(peer);
    }
    // need at least two
    assertTrue(savedPeers.size() > 1);
    final Peer eventingPeer = savedPeers.remove(0);
    Peer ledgerPeer = savedPeers.remove(0);
    // no more peers.
    assertTrue(replayTestChannel.getPeers().isEmpty());
    // just checking :)
    assertTrue(replayTestChannel.getPeers(EnumSet.of(PeerRole.CHAINCODE_QUERY, PeerRole.ENDORSING_PEER)).isEmpty());
    // just checking
    assertTrue(replayTestChannel.getPeers(EnumSet.of(PeerRole.LEDGER_QUERY)).isEmpty());
    // should be known by client.
    assertNotNull(client.getChannel(replayTestChannel.getName()));
    final PeerOptions eventingPeerOptions = createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.EVENT_SOURCE));
    if (useFilteredBlocks) {
        eventingPeerOptions.registerEventsForFilteredBlocks();
    }
    if (-1L == stop) {
        // the height of the blockchain
        // Eventing peer start getting blocks from block 0
        replayTestChannel.addPeer(eventingPeer, eventingPeerOptions.startEvents(start));
    } else {
        replayTestChannel.addPeer(eventingPeer, eventingPeerOptions.startEvents(start).stopEvents(// Eventing peer start getting blocks from block 0
        stop));
    }
    // add a ledger peer
    replayTestChannel.addPeer(ledgerPeer, createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.LEDGER_QUERY)));
    // future to set when done.
    CompletableFuture<Long> done = new CompletableFuture<>();
    // some variable used by the block listener being set up.
    final AtomicLong bcount = new AtomicLong(0);
    final AtomicLong stopValue = new AtomicLong(stop == -1L ? Long.MAX_VALUE : stop);
    final Channel finalChannel = replayTestChannel;
    final Map<Long, BlockEvent> blockEvents = Collections.synchronizedMap(new HashMap<>(100));
    final String blockListenerHandle = replayTestChannel.registerBlockListener(blockEvent -> {
        try {
            final long blockNumber = blockEvent.getBlockNumber();
            BlockEvent seen = blockEvents.put(blockNumber, blockEvent);
            assertNull(format("Block number %d seen twice", blockNumber), seen);
            assertTrue(format("Wrong type of block seen block number %d. expected filtered block %b but got %b", blockNumber, useFilteredBlocks, blockEvent.isFiltered()), useFilteredBlocks ? blockEvent.isFiltered() : !blockEvent.isFiltered());
            // count starts with 0 not 1 !
            final long count = bcount.getAndIncrement();
            if (count == 0 && stop == -1L) {
                final BlockchainInfo blockchainInfo = finalChannel.queryBlockchainInfo();
                long lh = blockchainInfo.getHeight();
                // blocks 0L 9L are on chain height 10 .. stop on 9
                stopValue.set(lh - 1L);
                // out("height: %d", lh);
                if (bcount.get() + start > stopValue.longValue()) {
                    // test with latest count.
                    // report back latest count.
                    done.complete(bcount.get());
                }
            } else {
                if (bcount.longValue() + start > stopValue.longValue()) {
                    done.complete(count);
                }
            }
        } catch (AssertionError | Exception e) {
            e.printStackTrace();
            done.completeExceptionally(e);
        }
    });
    try {
        // start it all up.
        replayTestChannel.initialize();
        // give a timeout here.
        done.get(30, TimeUnit.SECONDS);
        // sleep a little to see if more blocks trickle in .. they should not
        Thread.sleep(1000);
        replayTestChannel.unregisterBlockListener(blockListenerHandle);
        // Start 2 and stop is 3  expect 2
        final long expectNumber = stopValue.longValue() - start + 1L;
        assertEquals(format("Didn't get number we expected %d but got %d block events. Start: %d, end: %d, height: %d", expectNumber, blockEvents.size(), start, stop, stopValue.longValue()), expectNumber, blockEvents.size());
        for (long i = stopValue.longValue(); i >= start; i--) {
            // make sure all are there.
            final BlockEvent blockEvent = blockEvents.get(i);
            assertNotNull(format("Missing block event for block number %d. Start= %d", i, start), blockEvent);
        }
        // light weight test just see if we get reasonable values for traversing the block. Test just whats common between
        // Block and FilteredBlock.
        int transactionEventCounts = 0;
        int chaincodeEventsCounts = 0;
        for (long i = stopValue.longValue(); i >= start; i--) {
            final BlockEvent blockEvent = blockEvents.get(i);
            // out("blockwalker %b, start: %d, stop: %d, i: %d, block %d", useFilteredBlocks, start, stopValue.longValue(), i, blockEvent.getBlockNumber());
            // check again
            assertEquals(useFilteredBlocks, blockEvent.isFiltered());
            if (useFilteredBlocks) {
                // should not have raw block event.
                assertNull(blockEvent.getBlock());
                // should have raw filtered block.
                assertNotNull(blockEvent.getFilteredBlock());
            } else {
                // should not have raw block event.
                assertNotNull(blockEvent.getBlock());
                // should have raw filtered block.
                assertNull(blockEvent.getFilteredBlock());
            }
            assertEquals(replayTestChannel.getName(), blockEvent.getChannelId());
            for (BlockInfo.EnvelopeInfo envelopeInfo : blockEvent.getEnvelopeInfos()) {
                if (envelopeInfo.getType() == TRANSACTION_ENVELOPE) {
                    BlockInfo.TransactionEnvelopeInfo transactionEnvelopeInfo = (BlockInfo.TransactionEnvelopeInfo) envelopeInfo;
                    // only have valid blocks.
                    assertTrue(envelopeInfo.isValid());
                    assertEquals(envelopeInfo.getValidationCode(), 0);
                    ++transactionEventCounts;
                    for (BlockInfo.TransactionEnvelopeInfo.TransactionActionInfo ta : transactionEnvelopeInfo.getTransactionActionInfos()) {
                        // out("\nTA:", ta + "\n\n");
                        ChaincodeEvent event = ta.getEvent();
                        if (event != null) {
                            assertNotNull(event.getChaincodeId());
                            assertNotNull(event.getEventName());
                            chaincodeEventsCounts++;
                        }
                    }
                } else {
                    assertEquals("Only non transaction block should be block 0.", blockEvent.getBlockNumber(), 0);
                }
            }
        }
        assertTrue(transactionEventCounts > 0);
        if (expectNumber > 4) {
            // this should be enough blocks with CC events.
            assertTrue(chaincodeEventsCounts > 0);
        }
        // all done.
        replayTestChannel.shutdown(true);
    } catch (Exception e) {
        e.printStackTrace();
        fail(e.getMessage());
    }
}
Also used : ArrayList(java.util.ArrayList) PeerOptions(org.hyperledger.fabric.sdk.Channel.PeerOptions) PeerOptions.createPeerOptions(org.hyperledger.fabric.sdk.Channel.PeerOptions.createPeerOptions) CompletableFuture(java.util.concurrent.CompletableFuture) BlockInfo(org.hyperledger.fabric.sdk.BlockInfo) Peer(org.hyperledger.fabric.sdk.Peer) Channel(org.hyperledger.fabric.sdk.Channel) BlockchainInfo(org.hyperledger.fabric.sdk.BlockchainInfo) InvalidArgumentException(org.hyperledger.fabric.sdk.exception.InvalidArgumentException) ProposalException(org.hyperledger.fabric.sdk.exception.ProposalException) CompletionException(java.util.concurrent.CompletionException) TransactionEventException(org.hyperledger.fabric.sdk.exception.TransactionEventException) MalformedURLException(java.net.MalformedURLException) AtomicLong(java.util.concurrent.atomic.AtomicLong) AtomicLong(java.util.concurrent.atomic.AtomicLong) ChaincodeEvent(org.hyperledger.fabric.sdk.ChaincodeEvent) BlockEvent(org.hyperledger.fabric.sdk.BlockEvent)

Aggregations

MalformedURLException (java.net.MalformedURLException)2 BlockEvent (org.hyperledger.fabric.sdk.BlockEvent)2 BlockInfo (org.hyperledger.fabric.sdk.BlockInfo)2 BlockchainInfo (org.hyperledger.fabric.sdk.BlockchainInfo)2 ChaincodeEvent (org.hyperledger.fabric.sdk.ChaincodeEvent)2 Channel (org.hyperledger.fabric.sdk.Channel)2 PeerOptions.createPeerOptions (org.hyperledger.fabric.sdk.Channel.PeerOptions.createPeerOptions)2 File (java.io.File)1 IOException (java.io.IOException)1 StringWriter (java.io.StringWriter)1 String.format (java.lang.String.format)1 UTF_8 (java.nio.charset.StandardCharsets.UTF_8)1 Paths (java.nio.file.Paths)1 PrivateKey (java.security.PrivateKey)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1 EnumSet (java.util.EnumSet)1 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1