@Test public void invDownloadTxMultiPeer() throws Exception { // Check co-ordination of which peer to download via the memory pool. VersionMessage ver = new VersionMessage(unitTestParams, 100); InetSocketAddress address = new InetSocketAddress("127.0.0.1", 4242); Peer peer2 = new Peer(unitTestParams, ver, new PeerAddress(address), blockChain, memoryPool); peer2.addWallet(wallet); VersionMessage peerVersion = new VersionMessage(unitTestParams, OTHER_PEER_CHAIN_HEIGHT); peerVersion.clientVersion = 70001; peerVersion.localServices = VersionMessage.NODE_NETWORK; connect(); InboundMessageQueuer writeTarget2 = connect(peer2, peerVersion); // Make a tx and advertise it to one of the peers. BigInteger value = Utils.toNanoCoins(1, 0); Transaction tx = createFakeTx(unitTestParams, value, this.address); InventoryMessage inv = new InventoryMessage(unitTestParams); InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash()); inv.addItem(item); inbound(writeTarget, inv); // We got a getdata message. GetDataMessage message = (GetDataMessage) outbound(writeTarget); assertEquals(1, message.getItems().size()); assertEquals(tx.getHash(), message.getItems().get(0).hash); assertTrue(memoryPool.maybeWasSeen(tx.getHash())); // Advertising to peer2 results in no getdata message. inbound(writeTarget2, inv); pingAndWait(writeTarget2); assertNull(outbound(writeTarget2)); }
// 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); }
@Test public void fastCatchup() throws Exception { connect(); // Check that blocks before the fast catchup point are retrieved using getheaders, and after // using getblocks. // This test is INCOMPLETE because it does not check we handle >2000 blocks correctly. Block b1 = createFakeBlock(blockStore).block; blockChain.add(b1); Utils.rollMockClock(60 * 10); // 10 minutes later. Block b2 = makeSolvedTestBlock(b1); Utils.rollMockClock(60 * 10); // 10 minutes later. Block b3 = makeSolvedTestBlock(b2); Utils.rollMockClock(60 * 10); Block b4 = makeSolvedTestBlock(b3); // Request headers until the last 2 blocks. peer.setDownloadParameters((Utils.now().getTime() / 1000) - (600 * 2) + 1, false); peer.startBlockChainDownload(); GetHeadersMessage getheaders = (GetHeadersMessage) outbound(writeTarget); List<Sha256Hash> expectedLocator = new ArrayList<Sha256Hash>(); expectedLocator.add(b1.getHash()); expectedLocator.add(unitTestParams.getGenesisBlock().getHash()); assertEquals(getheaders.getLocator(), expectedLocator); assertEquals(getheaders.getStopHash(), Sha256Hash.ZERO_HASH); // Now send all the headers. HeadersMessage headers = new HeadersMessage( unitTestParams, b2.cloneAsHeader(), b3.cloneAsHeader(), b4.cloneAsHeader()); // We expect to be asked for b3 and b4 again, but this time, with a body. expectedLocator.clear(); expectedLocator.add(b2.getHash()); expectedLocator.add(b1.getHash()); expectedLocator.add(unitTestParams.getGenesisBlock().getHash()); inbound(writeTarget, headers); GetBlocksMessage getblocks = (GetBlocksMessage) outbound(writeTarget); assertEquals(expectedLocator, getblocks.getLocator()); assertEquals(Sha256Hash.ZERO_HASH, getblocks.getStopHash()); // We're supposed to get an inv here. InventoryMessage inv = new InventoryMessage(unitTestParams); inv.addItem(new InventoryItem(InventoryItem.Type.Block, b3.getHash())); inbound(writeTarget, inv); GetDataMessage getdata = (GetDataMessage) outbound(writeTarget); assertEquals(b3.getHash(), getdata.getItems().get(0).hash); // All done. inbound(writeTarget, b3); pingAndWait(writeTarget); closePeer(peer); }
// Check that an inv to a peer that is not set to download missing blocks does nothing. @Test public void invNoDownload() throws Exception { // Don't download missing blocks. peer.setDownloadData(false); connect(); // Make a missing block that we receive. Block b1 = createFakeBlock(blockStore).block; blockChain.add(b1); Block b2 = makeSolvedTestBlock(b1); // Receive an inv. InventoryMessage inv = new InventoryMessage(unitTestParams); InventoryItem item = new InventoryItem(InventoryItem.Type.Block, b2.getHash()); inv.addItem(item); inbound(writeTarget, inv); // Peer does nothing with it. assertNull(outbound(writeTarget)); }
@Test public void invDownloadTx() throws Exception { connect(); peer.setDownloadData(true); // Make a transaction and tell the peer we have it. BigInteger value = Utils.toNanoCoins(1, 0); Transaction tx = createFakeTx(unitTestParams, value, address); InventoryMessage inv = new InventoryMessage(unitTestParams); InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash()); inv.addItem(item); inbound(writeTarget, inv); // Peer hasn't seen it before, so will ask for it. GetDataMessage getdata = (GetDataMessage) outbound(writeTarget); assertEquals(1, getdata.getItems().size()); assertEquals(tx.getHash(), getdata.getItems().get(0).hash); inbound(writeTarget, tx); // Ask for the dependency, it's not in the mempool (in chain). getdata = (GetDataMessage) outbound(writeTarget); inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems())); pingAndWait(writeTarget); assertEquals(value, wallet.getBalance(Wallet.BalanceType.ESTIMATED)); }
// Check that an inventory tickle is processed correctly when downloading missing blocks is // active. @Test public void invTickle() throws Exception { connect(); Block b1 = createFakeBlock(blockStore).block; blockChain.add(b1); // Make a missing block. Block b2 = makeSolvedTestBlock(b1); Block b3 = makeSolvedTestBlock(b2); inbound(writeTarget, b3); InventoryMessage inv = new InventoryMessage(unitTestParams); InventoryItem item = new InventoryItem(InventoryItem.Type.Block, b3.getHash()); inv.addItem(item); inbound(writeTarget, inv); GetBlocksMessage getblocks = (GetBlocksMessage) outbound(writeTarget); List<Sha256Hash> expectedLocator = new ArrayList<Sha256Hash>(); expectedLocator.add(b1.getHash()); expectedLocator.add(unitTestParams.getGenesisBlock().getHash()); assertEquals(getblocks.getLocator(), expectedLocator); assertEquals(getblocks.getStopHash(), b3.getHash()); assertNull(outbound(writeTarget)); }