(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;
import javax.annotation.*;
import java.util.List;
import java.util.Set;
@@ -28,7 +29,7 @@ public class AbstractPeerEventListener implements PeerEventListener {
}
@Override
public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) {
public void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft) {
}
@Override

View File

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

View File

@@ -539,7 +539,7 @@ public class Peer extends PeerSocketHandler {
}
if (blockChain.add(header)) {
// The block was successfully linked into the chain. Notify the user of our progress.
invokeOnBlocksDownloaded(header);
invokeOnBlocksDownloaded(header, null);
} else {
// 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
@@ -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.
if (blockChain.add(m)) {
// The block was successfully linked into the chain. Notify the user of our progress.
invokeOnBlocksDownloaded(m);
invokeOnBlocksDownloaded(m, null);
} else {
// 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
@@ -950,7 +950,7 @@ public class Peer extends PeerSocketHandler {
if (blockChain.add(m)) {
// The block was successfully linked into the chain. Notify the user of our progress.
invokeOnBlocksDownloaded(m.getBlockHeader());
invokeOnBlocksDownloaded(m.getBlockHeader(), m);
} else {
// 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
@@ -1008,7 +1008,7 @@ public class Peer extends PeerSocketHandler {
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
// 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.
@@ -1017,7 +1017,7 @@ public class Peer extends PeerSocketHandler {
registration.executor.execute(new Runnable() {
@Override
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;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Set;
import javax.annotation.*;
import java.util.*;
/**
* <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);
// 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 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
*/
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.

View File

@@ -141,7 +141,7 @@ public class PeerGroup implements TransactionBroadcaster {
}
@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;
final double rate = chain.getFalsePositiveRate();
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 int blocksInLastSecond, stallWarning;
private int blocksInLastSecond, txnsInLastSecond, origTxnsInLastSecond, stallWarning;
@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++;
// 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
public synchronized void run() {
if (blocksInLastSecond > 1) {
log.info("{} blocks per second", blocksInLastSecond);
log.info("{} blocks/sec, {} tx/sec, {} pre-filtered tx/sec", blocksInLastSecond, txnsInLastSecond, origTxnsInLastSecond);
stallWarning = 0;
}
if (chain != null && chain.getBestChainHeight() < getMostCommonChainHeight() && blocksInLastSecond == 0 && stallWarning > -1) {
@@ -1485,6 +1492,8 @@ public class PeerGroup implements TransactionBroadcaster {
}
}
blocksInLastSecond = 0;
txnsInLastSecond = 0;
origTxnsInLastSecond = 0;
}
}
@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.
chainDownloadSpeedCalculator = new ChainDownloadSpeedCalculator();
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.
peer.startBlockChainDownload();

View File

@@ -18,6 +18,7 @@ package org.bitcoinj.jni;
import org.bitcoinj.core.*;
import javax.annotation.*;
import java.util.List;
import java.util.Set;
@@ -33,7 +34,7 @@ public class NativePeerEventListener implements PeerEventListener {
public native void onPeersDiscovered(Set<PeerAddress> peerAddresses);
@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
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.runners.Parameterized;
import javax.annotation.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -333,7 +334,7 @@ public class PeerTest extends TestWithNetworkConnections {
}
@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();
if (newValue != 3 || p != peer || !block.equals(b2) || blocksLeft != OTHER_PEER_CHAIN_HEIGHT - 2)
fail.set(true);

View File

@@ -762,8 +762,7 @@ public class WalletTool {
case BLOCK:
peers.addEventListener(new AbstractPeerEventListener() {
@Override
public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) {
super.onBlocksDownloaded(peer, block, blocksLeft);
public void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft) {
// 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.
if (latch.getCount() == 0) return;

View File

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