(API CHANGE) Pass the FilteredBlock into PeerEventListener.onBlocksDownloaded when present.

Keep track of downloaded vs server-side filtered transactions per second.
Add a keyboard shortcut to wallet-template to force disconnection from the current peer.
This commit is contained in:
Mike Hearn
2015-02-17 15:19:02 +01:00
parent fcd4b8b68a
commit 1efa1442c8
9 changed files with 39 additions and 22 deletions

View File

@@ -16,6 +16,7 @@
package org.bitcoinj.core; package org.bitcoinj.core;
import javax.annotation.*;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -28,7 +29,7 @@ public class AbstractPeerEventListener implements PeerEventListener {
} }
@Override @Override
public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) { public void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft) {
} }
@Override @Override

View File

@@ -22,6 +22,7 @@ import com.google.common.util.concurrent.SettableFuture;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.*;
import java.util.Date; import java.util.Date;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@@ -54,7 +55,7 @@ public class DownloadProgressTracker extends AbstractPeerEventListener {
} }
@Override @Override
public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) { public void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft) {
if (caughtUp) if (caughtUp)
return; return;

View File

@@ -539,7 +539,7 @@ public class Peer extends PeerSocketHandler {
} }
if (blockChain.add(header)) { if (blockChain.add(header)) {
// The block was successfully linked into the chain. Notify the user of our progress. // The block was successfully linked into the chain. Notify the user of our progress.
invokeOnBlocksDownloaded(header); invokeOnBlocksDownloaded(header, null);
} else { } else {
// This block is unconnected - we don't know how to get from it back to the genesis block yet. // This block is unconnected - we don't know how to get from it back to the genesis block yet.
// That must mean that the peer is buggy or malicious because we specifically requested for // That must mean that the peer is buggy or malicious because we specifically requested for
@@ -846,7 +846,7 @@ public class Peer extends PeerSocketHandler {
// Otherwise it's a block sent to us because the peer thought we needed it, so add it to the block chain. // Otherwise it's a block sent to us because the peer thought we needed it, so add it to the block chain.
if (blockChain.add(m)) { if (blockChain.add(m)) {
// The block was successfully linked into the chain. Notify the user of our progress. // The block was successfully linked into the chain. Notify the user of our progress.
invokeOnBlocksDownloaded(m); invokeOnBlocksDownloaded(m, null);
} else { } else {
// This block is an orphan - we don't know how to get from it back to the genesis block yet. That // This block is an orphan - we don't know how to get from it back to the genesis block yet. That
// must mean that there are blocks we are missing, so do another getblocks with a new block locator // must mean that there are blocks we are missing, so do another getblocks with a new block locator
@@ -950,7 +950,7 @@ public class Peer extends PeerSocketHandler {
if (blockChain.add(m)) { if (blockChain.add(m)) {
// The block was successfully linked into the chain. Notify the user of our progress. // The block was successfully linked into the chain. Notify the user of our progress.
invokeOnBlocksDownloaded(m.getBlockHeader()); invokeOnBlocksDownloaded(m.getBlockHeader(), m);
} else { } else {
// This block is an orphan - we don't know how to get from it back to the genesis block yet. That // This block is an orphan - we don't know how to get from it back to the genesis block yet. That
// must mean that there are blocks we are missing, so do another getblocks with a new block locator // must mean that there are blocks we are missing, so do another getblocks with a new block locator
@@ -1008,7 +1008,7 @@ public class Peer extends PeerSocketHandler {
return found; return found;
} }
private void invokeOnBlocksDownloaded(final Block m) { private void invokeOnBlocksDownloaded(final Block block, @Nullable final FilteredBlock fb) {
// It is possible for the peer block height difference to be negative when blocks have been solved and broadcast // It is possible for the peer block height difference to be negative when blocks have been solved and broadcast
// since the time we first connected to the peer. However, it's weird and unexpected to receive a callback // since the time we first connected to the peer. However, it's weird and unexpected to receive a callback
// with negative "blocks left" in this case, so we clamp to zero so the API user doesn't have to think about it. // with negative "blocks left" in this case, so we clamp to zero so the API user doesn't have to think about it.
@@ -1017,7 +1017,7 @@ public class Peer extends PeerSocketHandler {
registration.executor.execute(new Runnable() { registration.executor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
registration.listener.onBlocksDownloaded(Peer.this, m, blocksLeft); registration.listener.onBlocksDownloaded(Peer.this, block, fb, blocksLeft);
} }
}); });
} }

View File

@@ -16,9 +16,8 @@
package org.bitcoinj.core; package org.bitcoinj.core;
import javax.annotation.Nullable; import javax.annotation.*;
import java.util.List; import java.util.*;
import java.util.Set;
/** /**
* <p>Implementors can listen to events like blocks being downloaded/transactions being broadcast/connect/disconnects, * <p>Implementors can listen to events like blocks being downloaded/transactions being broadcast/connect/disconnects,
@@ -34,16 +33,19 @@ public interface PeerEventListener {
*/ */
public void onPeersDiscovered(Set<PeerAddress> peerAddresses); public void onPeersDiscovered(Set<PeerAddress> peerAddresses);
// TODO: Fix the Block/FilteredBlock type hierarchy so we can avoid the stupid typeless API here.
/** /**
* Called on a Peer thread when a block is received.<p> * <p>Called on a Peer thread when a block is received.</p>
* *
* The block may have transactions or may be a header only once getheaders is implemented. * <p>The block may be a Block object that contains transactions, a Block object that is only a header when
* fast catchup is being used. If set, filteredBlock can be used to retrieve the list of associated transactions.</p>
* *
* @param peer the peer receiving the block * @param peer the peer receiving the block
* @param block the downloaded block * @param block the downloaded block
* @param filteredBlock if non-null, the object that wraps the block header passed as the block param.
* @param blocksLeft the number of blocks left to download * @param blocksLeft the number of blocks left to download
*/ */
public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft); public void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft);
/** /**
* Called when a download is started with the initial number of blocks to be downloaded. * Called when a download is started with the initial number of blocks to be downloaded.

View File

@@ -141,7 +141,7 @@ public class PeerGroup implements TransactionBroadcaster {
} }
@Override @Override
public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) { public void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft) {
if (chain == null) return; if (chain == null) return;
final double rate = chain.getFalsePositiveRate(); final double rate = chain.getFalsePositiveRate();
final double target = bloomFilterMerger.getBloomFilterFPRate() * MAX_FP_RATE_INCREASE; final double target = bloomFilterMerger.getBloomFilterFPRate() * MAX_FP_RATE_INCREASE;
@@ -1462,17 +1462,24 @@ public class PeerGroup implements TransactionBroadcaster {
} }
private class ChainDownloadSpeedCalculator extends AbstractPeerEventListener implements Runnable { private class ChainDownloadSpeedCalculator extends AbstractPeerEventListener implements Runnable {
private int blocksInLastSecond, stallWarning; private int blocksInLastSecond, txnsInLastSecond, origTxnsInLastSecond, stallWarning;
@Override @Override
public synchronized void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) { public synchronized void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft) {
blocksInLastSecond++; blocksInLastSecond++;
// This whole area of the type hierarchy is a mess.
List<Transaction> blockTransactions = block.getTransactions();
int txCount = (blockTransactions != null ? blockTransactions.size() : 0) +
(filteredBlock != null ? filteredBlock.getAssociatedTransactions().size() : 0);
txnsInLastSecond = txnsInLastSecond + txCount;
if (filteredBlock != null)
origTxnsInLastSecond += filteredBlock.getTransactionCount();
} }
@Override @Override
public synchronized void run() { public synchronized void run() {
if (blocksInLastSecond > 1) { if (blocksInLastSecond > 1) {
log.info("{} blocks per second", blocksInLastSecond); log.info("{} blocks/sec, {} tx/sec, {} pre-filtered tx/sec", blocksInLastSecond, txnsInLastSecond, origTxnsInLastSecond);
stallWarning = 0; stallWarning = 0;
} }
if (chain != null && chain.getBestChainHeight() < getMostCommonChainHeight() && blocksInLastSecond == 0 && stallWarning > -1) { if (chain != null && chain.getBestChainHeight() < getMostCommonChainHeight() && blocksInLastSecond == 0 && stallWarning > -1) {
@@ -1485,6 +1492,8 @@ public class PeerGroup implements TransactionBroadcaster {
} }
} }
blocksInLastSecond = 0; blocksInLastSecond = 0;
txnsInLastSecond = 0;
origTxnsInLastSecond = 0;
} }
} }
@Nullable private ChainDownloadSpeedCalculator chainDownloadSpeedCalculator; @Nullable private ChainDownloadSpeedCalculator chainDownloadSpeedCalculator;
@@ -1498,8 +1507,8 @@ public class PeerGroup implements TransactionBroadcaster {
// Every second, run the calculator which will log how fast we are downloading the chain. // Every second, run the calculator which will log how fast we are downloading the chain.
chainDownloadSpeedCalculator = new ChainDownloadSpeedCalculator(); chainDownloadSpeedCalculator = new ChainDownloadSpeedCalculator();
executor.scheduleAtFixedRate(chainDownloadSpeedCalculator, 1, 1, TimeUnit.SECONDS); executor.scheduleAtFixedRate(chainDownloadSpeedCalculator, 1, 1, TimeUnit.SECONDS);
peer.addEventListener(chainDownloadSpeedCalculator, Threading.SAME_THREAD);
} }
peer.addEventListener(chainDownloadSpeedCalculator, Threading.SAME_THREAD);
// startBlockChainDownload will setDownloadData(true) on itself automatically. // startBlockChainDownload will setDownloadData(true) on itself automatically.
peer.startBlockChainDownload(); peer.startBlockChainDownload();

View File

@@ -18,6 +18,7 @@ package org.bitcoinj.jni;
import org.bitcoinj.core.*; import org.bitcoinj.core.*;
import javax.annotation.*;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -33,7 +34,7 @@ public class NativePeerEventListener implements PeerEventListener {
public native void onPeersDiscovered(Set<PeerAddress> peerAddresses); public native void onPeersDiscovered(Set<PeerAddress> peerAddresses);
@Override @Override
public native void onBlocksDownloaded(Peer peer, Block block, int blocksLeft); public native void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft);
@Override @Override
public native void onChainDownloadStarted(Peer peer, int blocksLeft); public native void onChainDownloadStarted(Peer peer, int blocksLeft);

View File

@@ -31,6 +31,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import javax.annotation.*;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@@ -333,7 +334,7 @@ public class PeerTest extends TestWithNetworkConnections {
} }
@Override @Override
public synchronized void onBlocksDownloaded(Peer p, Block block, int blocksLeft) { public synchronized void onBlocksDownloaded(Peer p, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft) {
int newValue = newBlockMessagesReceived.incrementAndGet(); int newValue = newBlockMessagesReceived.incrementAndGet();
if (newValue != 3 || p != peer || !block.equals(b2) || blocksLeft != OTHER_PEER_CHAIN_HEIGHT - 2) if (newValue != 3 || p != peer || !block.equals(b2) || blocksLeft != OTHER_PEER_CHAIN_HEIGHT - 2)
fail.set(true); fail.set(true);

View File

@@ -762,8 +762,7 @@ public class WalletTool {
case BLOCK: case BLOCK:
peers.addEventListener(new AbstractPeerEventListener() { peers.addEventListener(new AbstractPeerEventListener() {
@Override @Override
public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) { public void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft) {
super.onBlocksDownloaded(peer, block, blocksLeft);
// Check if we already ran. This can happen if a block being received triggers download of more // Check if we already ran. This can happen if a block being received triggers download of more
// blocks, or if we receive another block whilst the peer group is shutting down. // blocks, or if we receive another block whilst the peer group is shutting down.
if (latch.getCount() == 0) return; if (latch.getCount() == 0) return;

View File

@@ -1,6 +1,7 @@
package wallettemplate; package wallettemplate;
import com.google.common.util.concurrent.*; import com.google.common.util.concurrent.*;
import javafx.scene.input.*;
import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.kits.WalletAppKit; import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.params.*; import org.bitcoinj.params.*;
@@ -102,6 +103,8 @@ public class Main extends Application {
} }
}, Platform::runLater); }, Platform::runLater);
bitcoin.startAsync(); bitcoin.startAsync();
scene.getAccelerators().put(KeyCombination.valueOf("Shortcut+F"), () -> bitcoin.peerGroup().getDownloadPeer().close());
} }
public void setupWalletKit(@Nullable DeterministicSeed seed) { public void setupWalletKit(@Nullable DeterministicSeed seed) {