@Test public void disconnectOldVersions1() throws Exception { // Set up the connection with an old version. final SettableFuture<Void> connectedFuture = SettableFuture.create(); final SettableFuture<Void> disconnectedFuture = SettableFuture.create(); peer.addEventListener( new AbstractPeerEventListener() { @Override public void onPeerConnected(Peer peer, int peerCount) { connectedFuture.set(null); } @Override public void onPeerDisconnected(Peer peer, int peerCount) { disconnectedFuture.set(null); } }); connectWithVersion(500); // We must wait uninterruptibly here because connect[WithVersion] generates a peer that // interrupts the current // thread when it disconnects. Uninterruptibles.getUninterruptibly(connectedFuture); Uninterruptibles.getUninterruptibly(disconnectedFuture); try { peer.writeTarget.writeBytes(new byte[1]); fail(); } catch (IOException e) { assertTrue( (e.getCause() != null && e.getCause() instanceof CancelledKeyException) || (e instanceof SocketException && e.getMessage().equals("Socket is closed"))); } }
// Check that it starts downloading the block chain correctly on request. @Test public void startBlockChainDownload() throws Exception { Block b1 = createFakeBlock(blockStore).block; blockChain.add(b1); Block b2 = makeSolvedTestBlock(b1); blockChain.add(b2); connect(); fail.set(true); peer.addEventListener( new AbstractPeerEventListener() { @Override public void onChainDownloadStarted(Peer p, int blocksLeft) { if (p == peer && blocksLeft == 108) fail.set(false); } }, Threading.SAME_THREAD); peer.startBlockChainDownload(); List<Sha256Hash> expectedLocator = new ArrayList<Sha256Hash>(); expectedLocator.add(b2.getHash()); expectedLocator.add(b1.getHash()); expectedLocator.add(unitTestParams.getGenesisBlock().getHash()); GetBlocksMessage message = (GetBlocksMessage) outbound(writeTarget); assertEquals(message.getLocator(), expectedLocator); assertEquals(Sha256Hash.ZERO_HASH, message.getStopHash()); }
@Test public void testAddEventListener() throws Exception { connect(); PeerEventListener listener = new AbstractPeerEventListener(); peer.addEventListener(listener); assertTrue(peer.removeEventListener(listener)); assertFalse(peer.removeEventListener(listener)); }
// Check that inventory message containing blocks we want is processed correctly. @Test public void newBlock() throws Exception { Block b1 = createFakeBlock(blockStore).block; blockChain.add(b1); final Block b2 = makeSolvedTestBlock(b1); // Receive notification of a new block. final InventoryMessage inv = new InventoryMessage(unitTestParams); InventoryItem item = new InventoryItem(InventoryItem.Type.Block, b2.getHash()); inv.addItem(item); final AtomicInteger newBlockMessagesReceived = new AtomicInteger(0); connect(); // Round-trip a ping so that we never see the response verack if we attach too quick pingAndWait(writeTarget); peer.addEventListener( new AbstractPeerEventListener() { @Override public synchronized Message onPreMessageReceived(Peer p, Message m) { if (p != peer) fail.set(true); if (m instanceof Pong) return m; int newValue = newBlockMessagesReceived.incrementAndGet(); if (newValue == 1 && !inv.equals(m)) fail.set(true); else if (newValue == 2 && !b2.equals(m)) fail.set(true); else if (newValue > 3) fail.set(true); return m; } @Override public synchronized void onBlocksDownloaded(Peer p, Block block, int blocksLeft) { int newValue = newBlockMessagesReceived.incrementAndGet(); if (newValue != 3 || p != peer || !block.equals(b2) || blocksLeft != OTHER_PEER_CHAIN_HEIGHT - 2) fail.set(true); } }, Threading.SAME_THREAD); long height = peer.getBestHeight(); inbound(writeTarget, inv); pingAndWait(writeTarget); assertEquals(height + 1, peer.getBestHeight()); // Response to the getdata message. inbound(writeTarget, b2); pingAndWait(writeTarget); Threading.waitForUserCode(); pingAndWait(writeTarget); assertEquals(3, newBlockMessagesReceived.get()); GetDataMessage getdata = (GetDataMessage) outbound(writeTarget); List<InventoryItem> items = getdata.getItems(); assertEquals(1, items.size()); assertEquals(b2.getHash(), items.get(0).hash); assertEquals(InventoryItem.Type.Block, items.get(0).type); }
public void recursiveDownload(boolean useNotFound) throws Exception { // Using ping or notfound? connectWithVersion(useNotFound ? 70001 : 60001); // Check that we can download all dependencies of an unconfirmed relevant transaction from the // mempool. ECKey to = new ECKey(); final Transaction[] onTx = new Transaction[1]; peer.addEventListener( new AbstractPeerEventListener() { @Override public void onTransaction(Peer peer1, Transaction t) { onTx[0] = t; } }, Threading.SAME_THREAD); // Make the some fake transactions in the following graph: // t1 -> t2 -> [t5] // -> t3 -> t4 -> [t6] // -> [t7] // -> [t8] // The ones in brackets are assumed to be in the chain and are represented only by hashes. Transaction t2 = TestUtils.createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), to); Sha256Hash t5 = t2.getInput(0).getOutpoint().getHash(); Transaction t4 = TestUtils.createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), new ECKey()); Sha256Hash t6 = t4.getInput(0).getOutpoint().getHash(); t4.addOutput(Utils.toNanoCoins(1, 0), new ECKey()); Transaction t3 = new Transaction(unitTestParams); t3.addInput(t4.getOutput(0)); t3.addOutput(Utils.toNanoCoins(1, 0), new ECKey()); Transaction t1 = new Transaction(unitTestParams); t1.addInput(t2.getOutput(0)); t1.addInput(t3.getOutput(0)); Sha256Hash someHash = new Sha256Hash("2b801dd82f01d17bbde881687bf72bc62e2faa8ab8133d36fcb8c3abe7459da6"); t1.addInput( new TransactionInput( unitTestParams, t1, new byte[] {}, new TransactionOutPoint(unitTestParams, 0, someHash))); Sha256Hash anotherHash = new Sha256Hash("3b801dd82f01d17bbde881687bf72bc62e2faa8ab8133d36fcb8c3abe7459da6"); t1.addInput( new TransactionInput( unitTestParams, t1, new byte[] {}, new TransactionOutPoint(unitTestParams, 1, anotherHash))); t1.addOutput(Utils.toNanoCoins(1, 0), to); t1 = TestUtils.roundTripTransaction(unitTestParams, t1); t2 = TestUtils.roundTripTransaction(unitTestParams, t2); t3 = TestUtils.roundTripTransaction(unitTestParams, t3); t4 = TestUtils.roundTripTransaction(unitTestParams, t4); // Announce the first one. Wait for it to be downloaded. InventoryMessage inv = new InventoryMessage(unitTestParams); inv.addTransaction(t1); inbound(writeTarget, inv); GetDataMessage getdata = (GetDataMessage) outbound(writeTarget); Threading.waitForUserCode(); assertEquals(t1.getHash(), getdata.getItems().get(0).hash); inbound(writeTarget, t1); pingAndWait(writeTarget); assertEquals(t1, onTx[0]); // We want its dependencies so ask for them. ListenableFuture<List<Transaction>> futures = peer.downloadDependencies(t1); assertFalse(futures.isDone()); // It will recursively ask for the dependencies of t1: t2, t3, someHash and anotherHash. getdata = (GetDataMessage) outbound(writeTarget); assertEquals(4, getdata.getItems().size()); assertEquals(t2.getHash(), getdata.getItems().get(0).hash); assertEquals(t3.getHash(), getdata.getItems().get(1).hash); assertEquals(someHash, getdata.getItems().get(2).hash); assertEquals(anotherHash, getdata.getItems().get(3).hash); long nonce = -1; if (!useNotFound) nonce = ((Ping) outbound(writeTarget)).getNonce(); // For some random reason, t4 is delivered at this point before it's needed - perhaps it was a // Bloom filter // false positive. We do this to check that the mempool is being checked for seen transactions // before // requesting them. inbound(writeTarget, t4); // Deliver the requested transactions. inbound(writeTarget, t2); inbound(writeTarget, t3); if (useNotFound) { NotFoundMessage notFound = new NotFoundMessage(unitTestParams); notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, someHash)); notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, anotherHash)); inbound(writeTarget, notFound); } else { inbound(writeTarget, new Pong(nonce)); } assertFalse(futures.isDone()); // It will recursively ask for the dependencies of t2: t5 and t4, but not t3 because it already // found t4. getdata = (GetDataMessage) outbound(writeTarget); assertEquals(getdata.getItems().get(0).hash, t2.getInput(0).getOutpoint().getHash()); // t5 isn't found and t4 is. if (useNotFound) { NotFoundMessage notFound = new NotFoundMessage(unitTestParams); notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t5)); inbound(writeTarget, notFound); } else { bouncePing(); } assertFalse(futures.isDone()); // Continue to explore the t4 branch and ask for t6, which is in the chain. getdata = (GetDataMessage) outbound(writeTarget); assertEquals(t6, getdata.getItems().get(0).hash); if (useNotFound) { NotFoundMessage notFound = new NotFoundMessage(unitTestParams); notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t6)); inbound(writeTarget, notFound); } else { bouncePing(); } pingAndWait(writeTarget); // That's it, we explored the entire tree. assertTrue(futures.isDone()); List<Transaction> results = futures.get(); assertTrue(results.contains(t2)); assertTrue(results.contains(t3)); assertTrue(results.contains(t4)); }