### Question:
PeerGroup extends AbstractExecutionThreadService implements TransactionBroadcaster { public void startBlockChainDownload(PeerEventListener listener) { lock.lock(); try { if (downloadPeer != null && this.downloadListener != null) downloadPeer.removeEventListener(this.downloadListener); this.downloadListener = listener; if (!peers.isEmpty()) { startBlockChainDownloadFromPeer(peers.iterator().next()); } } finally { lock.unlock(); } } PeerGroup(NetworkParameters params);  PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain);  PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain, ClientConnectionManager connectionManager); void setMaxConnections(int maxConnections); int getMaxConnections(); void setVersionMessage(VersionMessage ver); VersionMessage getVersionMessage(); void setUserAgent(String name, String version, @Nullable String comments); void setUserAgent(String name, String version); void addEventListener(PeerEventListener listener, Executor executor); void addEventListener(PeerEventListener listener); boolean removeEventListener(PeerEventListener listener); void clearEventListeners(); List<Peer> getConnectedPeers(); List<Peer> getPendingPeers(); void addAddress(PeerAddress peerAddress); void addAddress(InetAddress address); void addPeerDiscovery(PeerDiscovery peerDiscovery); void addWallet(Wallet wallet); void addPeerFilterProvider(PeerFilterProvider provider); void removeWallet(Wallet wallet); void recalculateFastCatchupAndFilter(FilterRecalculateMode mode); void setBloomFilterFalsePositiveRate(double bloomFilterFPRate); int numConnectedPeers(); @Nullable Peer connectTo(InetSocketAddress address); void setConnectTimeoutMillis(int connectTimeoutMillis); void startBlockChainDownload(PeerEventListener listener); void downloadBlockChain(); MemoryPool getMemoryPool(); void setFastCatchupTimeSecs(long secondsSinceEpoch); long getFastCatchupTimeSecs(); ListenableFuture<PeerGroup> waitForPeers(final int numPeers); int getMinBroadcastConnections(); void setMinBroadcastConnections(int value); ListenableFuture<Transaction> broadcastTransaction(final Transaction tx); ListenableFuture<Transaction> broadcastTransaction(final Transaction tx, final int minConnections); long getPingIntervalMsec(); void setPingIntervalMsec(long pingIntervalMsec); void setMinRequiredProtocolVersion(int minRequiredProtocolVersion); int getMinRequiredProtocolVersion(); int getMostCommonChainHeight(); static int getMostCommonChainHeight(final List<Peer> peers); Peer getDownloadPeer(); static final long DEFAULT_PING_INTERVAL_MSEC; static final double DEFAULT_BLOOM_FILTER_FP_RATE; static final double MAX_FP_RATE_INCREASE; static final int DEFAULT_CONNECT_TIMEOUT_MILLIS; }### Answer:
@Test public void singleDownloadPeer2() throws Exception { peerGroup.startAsync(); peerGroup.awaitRunning(); InboundMessageQueuer p1 = connectPeer(1); Block b1 = TestUtils.createFakeBlock(blockStore).block; Block b2 = TestUtils.makeSolvedTestBlock(b1); Block b3 = TestUtils.makeSolvedTestBlock(b2); peerGroup.startBlockChainDownload(new AbstractPeerEventListener() { }); GetBlocksMessage getblocks = (GetBlocksMessage) outbound(p1); assertEquals(Sha256Hash.ZERO_HASH, getblocks.getStopHash()); InventoryMessage inv = new InventoryMessage(params); inv.addBlock(b1); inv.addBlock(b2); inv.addBlock(b3); inbound(p1, inv); assertTrue(outbound(p1) instanceof GetDataMessage); inbound(p1, b1); InboundMessageQueuer p2 = connectPeer(2); Message message = (Message)outbound(p2); assertNull(message == null ? "" : message.toString(), message); peerGroup.stopAsync(); }