From 3d3dd6f721780e924e4202b8916a76ec9f26d5db Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Sun, 7 Feb 2016 16:17:30 +0000 Subject: [PATCH] Split peer event listeners into single method interfaces --- .../src/main/java/org/bitcoinj/core/Peer.java | 99 ++++-- .../java/org/bitcoinj/core/PeerGroup.java | 308 +++++++++++++----- .../bitcoinj/core/TransactionBroadcast.java | 13 +- .../BlocksDownloadedEventListener.java | 43 +++ .../ChainDownloadStartedEventListener.java | 35 ++ .../core/listeners/GetDataEventListener.java | 40 +++ .../core/listeners/NewBestBlockListener.java | 4 +- .../core/listeners/PeerDataEventListener.java | 49 +-- .../PreMessageReceivedEventListener.java | 38 +++ .../core/listeners/ReorganizeListener.java | 3 +- .../java/org/bitcoinj/kits/WalletAppKit.java | 10 +- .../bitcoinj/core/BitcoindComparisonTool.java | 11 +- .../java/org/bitcoinj/core/PeerGroupTest.java | 20 +- .../test/java/org/bitcoinj/core/PeerTest.java | 7 +- .../testing/TestWithNetworkConnections.java | 9 +- .../org/bitcoinj/examples/DoubleSpend.java | 6 +- .../java/org/bitcoinj/tools/WalletTool.java | 12 +- 17 files changed, 510 insertions(+), 197 deletions(-) create mode 100644 core/src/main/java/org/bitcoinj/core/listeners/BlocksDownloadedEventListener.java create mode 100644 core/src/main/java/org/bitcoinj/core/listeners/ChainDownloadStartedEventListener.java create mode 100644 core/src/main/java/org/bitcoinj/core/listeners/GetDataEventListener.java create mode 100644 core/src/main/java/org/bitcoinj/core/listeners/PreMessageReceivedEventListener.java diff --git a/core/src/main/java/org/bitcoinj/core/Peer.java b/core/src/main/java/org/bitcoinj/core/Peer.java index c55785d2..3a55504c 100644 --- a/core/src/main/java/org/bitcoinj/core/Peer.java +++ b/core/src/main/java/org/bitcoinj/core/Peer.java @@ -76,9 +76,18 @@ public class Peer extends PeerSocketHandler { this.callOnDisconnect = callOnDisconnect; } } - private final CopyOnWriteArrayList connectionEventListeners; - private final CopyOnWriteArrayList> dataEventListeners; - private final CopyOnWriteArrayList> onTransactionEventListeners; + private final CopyOnWriteArrayList> blocksDownloadedEventListeners + = new CopyOnWriteArrayList>(); + private final CopyOnWriteArrayList> chainDownloadStartedEventListeners + = new CopyOnWriteArrayList>(); + private final CopyOnWriteArrayList connectionEventListeners + = new CopyOnWriteArrayList(); + private final CopyOnWriteArrayList> getDataEventListeners + = new CopyOnWriteArrayList>(); + private final CopyOnWriteArrayList> preMessageReceivedEventListeners + = new CopyOnWriteArrayList>(); + private final CopyOnWriteArrayList> onTransactionEventListeners + = new CopyOnWriteArrayList>(); // Whether to try and download blocks and transactions from this peer. Set to false by PeerGroup if not the // primary peer. This is to avoid redundant work and concurrency problems with downloading the same chain // in parallel. @@ -220,9 +229,6 @@ public class Peer extends PeerSocketHandler { this.blockChain = chain; // Allowed to be null. this.vDownloadData = chain != null; this.getDataFutures = new CopyOnWriteArrayList(); - this.connectionEventListeners = new CopyOnWriteArrayList(); - this.dataEventListeners = new CopyOnWriteArrayList>(); - this.onTransactionEventListeners = new CopyOnWriteArrayList>(); this.getAddrFutures = new LinkedList>(); this.fastCatchupTimeSecs = params.getGenesisBlock().getTimeSeconds(); this.isAcked = false; @@ -254,23 +260,54 @@ public class Peer extends PeerSocketHandler { /** Deprecated: use the more specific event handler methods instead */ @Deprecated @SuppressWarnings("deprecation") public void addEventListener(AbstractPeerEventListener listener) { - addEventListener(listener, Threading.USER_THREAD); + addBlocksDownloadedEventListener(Threading.USER_THREAD, listener); + addChainDownloadStartedEventListener(Threading.USER_THREAD, listener); + addConnectionEventListener(Threading.USER_THREAD, listener); + addGetDataEventListener(Threading.USER_THREAD, listener); + addOnTransactionBroadcastListener(Threading.USER_THREAD, listener); + addPreMessageReceivedEventListener(Threading.USER_THREAD, listener); } /** Deprecated: use the more specific event handler methods instead */ @Deprecated public void addEventListener(AbstractPeerEventListener listener, Executor executor) { + addBlocksDownloadedEventListener(executor, listener); + addChainDownloadStartedEventListener(executor, listener); addConnectionEventListener(executor, listener); - addDataEventListener(executor, listener); + addGetDataEventListener(executor, listener); addOnTransactionBroadcastListener(executor, listener); + addPreMessageReceivedEventListener(executor, listener); } /** Deprecated: use the more specific event handler methods instead */ @Deprecated public void removeEventListener(AbstractPeerEventListener listener) { + removeBlocksDownloadedEventListener(listener); + removeChainDownloadStartedEventListener(listener); removeConnectionEventListener(listener); - removeDataEventListener(listener); + removeGetDataEventListener(listener); removeOnTransactionBroadcastListener(listener); + removePreMessageReceivedEventListener(listener); + } + + /** Registers a listener that is invoked when new blocks are downloaded. */ + public void addBlocksDownloadedEventListener(BlocksDownloadedEventListener listener) { + addBlocksDownloadedEventListener(Threading.USER_THREAD, listener); + } + + /** Registers a listener that is invoked when new blocks are downloaded. */ + public void addBlocksDownloadedEventListener(Executor executor, BlocksDownloadedEventListener listener) { + blocksDownloadedEventListeners.add(new ListenerRegistration(listener, executor)); + } + + /** Registers a listener that is invoked when a blockchain downloaded starts. */ + public void addChainDownloadStartedEventListener(ChainDownloadStartedEventListener listener) { + addChainDownloadStartedEventListener(Threading.USER_THREAD, listener); + } + + /** Registers a listener that is invoked when a blockchain downloaded starts. */ + public void addChainDownloadStartedEventListener(Executor executor, ChainDownloadStartedEventListener listener) { + chainDownloadStartedEventListeners.add(new ListenerRegistration(listener, executor)); } /** Registers a listener that is invoked when a peer is connected or disconnected. */ @@ -284,13 +321,13 @@ public class Peer extends PeerSocketHandler { } /** Registers a listener that is called when messages are received. */ - public void addDataEventListener(PeerDataEventListener listener) { - addDataEventListener(Threading.USER_THREAD, listener); + public void addGetDataEventListener(GetDataEventListener listener) { + addGetDataEventListener(Threading.USER_THREAD, listener); } /** Registers a listener that is called when messages are received. */ - public void addDataEventListener(Executor executor, PeerDataEventListener listener) { - dataEventListeners.add(new ListenerRegistration(listener, executor)); + public void addGetDataEventListener(Executor executor, GetDataEventListener listener) { + getDataEventListeners.add(new ListenerRegistration(listener, executor)); } /** Registers a listener that is called when a transaction is broadcast across the network */ @@ -303,23 +340,45 @@ public class Peer extends PeerSocketHandler { onTransactionEventListeners.add(new ListenerRegistration(listener, executor)); } + /** Registers a listener that is called immediately before a message is received */ + public void addPreMessageReceivedEventListener(PreMessageReceivedEventListener listener) { + addPreMessageReceivedEventListener(Threading.USER_THREAD, listener); + } + + /** Registers a listener that is called immediately before a message is received */ + public void addPreMessageReceivedEventListener(Executor executor, PreMessageReceivedEventListener listener) { + preMessageReceivedEventListeners.add(new ListenerRegistration(listener, executor)); + } + // Package-local version for PeerGroup void addConnectionEventListenerWithoutOnDisconnect(Executor executor, PeerConnectionEventListener listener) { connectionEventListeners.add(new PeerConnectionListenerRegistration(listener, executor, false)); } + public boolean removeBlocksDownloadedEventListener(BlocksDownloadedEventListener listener) { + return ListenerRegistration.removeFromList(listener, blocksDownloadedEventListeners); + } + + public boolean removeChainDownloadStartedEventListener(ChainDownloadStartedEventListener listener) { + return ListenerRegistration.removeFromList(listener, chainDownloadStartedEventListeners); + } + public boolean removeConnectionEventListener(PeerConnectionEventListener listener) { return ListenerRegistration.removeFromList(listener, connectionEventListeners); } - public boolean removeDataEventListener(PeerDataEventListener listener) { - return ListenerRegistration.removeFromList(listener, dataEventListeners); + public boolean removeGetDataEventListener(GetDataEventListener listener) { + return ListenerRegistration.removeFromList(listener, getDataEventListeners); } public boolean removeOnTransactionBroadcastListener(OnTransactionBroadcastListener listener) { return ListenerRegistration.removeFromList(listener, onTransactionEventListeners); } + public boolean removePreMessageReceivedEventListener(PreMessageReceivedEventListener listener) { + return ListenerRegistration.removeFromList(listener, preMessageReceivedEventListeners); + } + @Override public String toString() { PeerAddress addr = getAddress(); @@ -376,7 +435,7 @@ public class Peer extends PeerSocketHandler { protected void processMessage(Message m) throws Exception { // Allow event listeners to filter the message stream. Listeners are allowed to drop messages by // returning null. - for (ListenerRegistration registration : dataEventListeners) { + for (ListenerRegistration registration : preMessageReceivedEventListeners) { // Skip any listeners that are supposed to run in another thread as we don't want to block waiting // for it, which might cause circular deadlock. if (registration.executor == Threading.SAME_THREAD) { @@ -642,13 +701,13 @@ public class Peer extends PeerSocketHandler { protected void processGetData(GetDataMessage getdata) { log.info("{}: Received getdata message: {}", getAddress(), getdata.toString()); ArrayList items = new ArrayList(); - for (ListenerRegistration registration : dataEventListeners) { + for (ListenerRegistration registration : getDataEventListeners) { if (registration.executor != Threading.SAME_THREAD) continue; List listenerItems = registration.listener.getData(this, getdata); if (listenerItems == null) continue; items.addAll(listenerItems); } - if (items.size() == 0) { + if (items.isEmpty()) { return; } log.info("{}: Sending {} items gathered from listeners to peer", getAddress(), items.size()); @@ -1055,7 +1114,7 @@ public class Peer extends PeerSocketHandler { // 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. final int blocksLeft = Math.max(0, (int) vPeerVersionMessage.bestHeight - checkNotNull(blockChain).getBestChainHeight()); - for (final ListenerRegistration registration : dataEventListeners) { + for (final ListenerRegistration registration : blocksDownloadedEventListeners) { registration.executor.execute(new Runnable() { @Override public void run() { @@ -1388,7 +1447,7 @@ public class Peer extends PeerSocketHandler { // chain even if the chain block count is lower. final int blocksLeft = getPeerBlockHeightDifference(); if (blocksLeft >= 0) { - for (final ListenerRegistration registration : dataEventListeners) { + for (final ListenerRegistration registration : chainDownloadStartedEventListeners) { registration.executor.execute(new Runnable() { @Override public void run() { diff --git a/core/src/main/java/org/bitcoinj/core/PeerGroup.java b/core/src/main/java/org/bitcoinj/core/PeerGroup.java index 706f5557..7e607c2a 100644 --- a/core/src/main/java/org/bitcoinj/core/PeerGroup.java +++ b/core/src/main/java/org/bitcoinj/core/PeerGroup.java @@ -116,11 +116,20 @@ public class PeerGroup implements TransactionBroadcaster { @GuardedBy("lock") private Peer downloadPeer; // Callback for events related to chain download. @Nullable @GuardedBy("lock") private PeerDataEventListener downloadListener; + private final CopyOnWriteArrayList> peersBlocksDownloadedEventListeners + = new CopyOnWriteArrayList>(); + private final CopyOnWriteArrayList> peersChainDownloadStartedEventListeners + = new CopyOnWriteArrayList>(); /** Callbacks for events related to peer connection/disconnection */ - protected final CopyOnWriteArrayList> peerConnectionEventListeners; + protected final CopyOnWriteArrayList> peerConnectionEventListeners + = new CopyOnWriteArrayList>(); /** Callbacks for events related to peer data being received */ - protected final CopyOnWriteArrayList> peerDataEventListeners; - protected final CopyOnWriteArrayList> onTransactionBroadastEventListeners; + private final CopyOnWriteArrayList> peerGetDataEventListeners + = new CopyOnWriteArrayList>(); + private final CopyOnWriteArrayList> peersPreMessageReceivedEventListeners + = new CopyOnWriteArrayList>(); + protected final CopyOnWriteArrayList> peersTransactionBroadastEventListeners + = new CopyOnWriteArrayList>(); // Peer discovery sources, will be polled occasionally if there aren't enough inactives. private final CopyOnWriteArraySet peerDiscoverers; // The version message to use for new connections. @@ -146,25 +155,7 @@ public class PeerGroup implements TransactionBroadcaster { // This event listener is added to every peer. It's here so when we announce transactions via an "inv", every // peer can fetch them. - private final AbstractPeerDataEventListener peerListener = new AbstractPeerDataEventListener() { - @Override - public List getData(Peer peer, GetDataMessage m) { - return handleGetData(m); - } - - @Override - 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; - if (rate > target) { - // TODO: Avoid hitting this path if the remote peer didn't acknowledge applying a new filter yet. - if (log.isDebugEnabled()) - log.debug("Force update Bloom filter due to high false positive rate ({} vs {})", rate, target); - recalculateFastCatchupAndFilter(FilterRecalculateMode.FORCE_SEND_FOR_REFRESH); - } - } - }; + private final PeerListener peerListener = new PeerListener(); private int minBroadcastConnections = 0; private final ScriptsChangeEventListener walletScriptEventListener = new ScriptsChangeEventListener() { @@ -226,6 +217,30 @@ public class PeerGroup implements TransactionBroadcaster { // in broadcastTransaction. private final Set runningBroadcasts; + private class PeerListener implements GetDataEventListener, BlocksDownloadedEventListener { + + public PeerListener() { + } + + @Override + public List getData(Peer peer, GetDataMessage m) { + return handleGetData(m); + } + + @Override + 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; + if (rate > target) { + // TODO: Avoid hitting this path if the remote peer didn't acknowledge applying a new filter yet. + if (log.isDebugEnabled()) + log.debug("Force update Bloom filter due to high false positive rate ({} vs {})", rate, target); + recalculateFastCatchupAndFilter(FilterRecalculateMode.FORCE_SEND_FOR_REFRESH); + } + } + } + private class PeerStartupListener extends AbstractPeerConnectionEventListener { @Override public void onPeerConnected(Peer peer, int peerCount) { @@ -324,7 +339,7 @@ public class PeerGroup implements TransactionBroadcaster { *

The user does not need any additional software for this: it's all pure Java. As of April 2014 this mode * is experimental.

* - * @params doDiscovery if true, DNS or HTTP peer discovery will be performed via Tor: this is almost always what you want. + * @param doDiscovery if true, DNS or HTTP peer discovery will be performed via Tor: this is almost always what you want. * @throws java.util.concurrent.TimeoutException if Tor fails to start within 20 seconds. */ public static PeerGroup newWithTor(Context context, @Nullable AbstractBlockChain chain, TorClient torClient, boolean doDiscovery) throws TimeoutException { @@ -411,9 +426,6 @@ public class PeerGroup implements TransactionBroadcaster { pendingPeers = new CopyOnWriteArrayList(); channels = connectionManager; peerDiscoverers = new CopyOnWriteArraySet(); - peerConnectionEventListeners = new CopyOnWriteArrayList>(); - peerDataEventListeners = new CopyOnWriteArrayList>(); - onTransactionBroadastEventListeners = new CopyOnWriteArrayList>(); runningBroadcasts = Collections.synchronizedSet(new HashSet()); bloomFilterMerger = new FilterMerger(DEFAULT_BLOOM_FILTER_FP_RATE); vMinRequiredProtocolVersion = params.getProtocolVersionNum(NetworkParameters.ProtocolVersion.BLOOM_FILTER); @@ -687,15 +699,74 @@ public class PeerGroup implements TransactionBroadcaster { setUserAgent(name, version, null); } + /** Use the more specific listener methods instead */ + @Deprecated @SuppressWarnings("deprecation") + public void addEventListener(AbstractPeerEventListener listener, Executor executor) { + addBlocksDownloadedEventListener(Threading.USER_THREAD, listener); + addChainDownloadStartedEventListener(Threading.USER_THREAD, listener); + addConnectionEventListener(Threading.USER_THREAD, listener); + addGetDataEventListener(Threading.USER_THREAD, listener); + addOnTransactionBroadcastListener(Threading.USER_THREAD, listener); + addPreMessageReceivedEventListener(Threading.USER_THREAD, listener); + } + + /** Use the more specific listener methods instead */ + @Deprecated @SuppressWarnings("deprecation") + public void addEventListener(AbstractPeerEventListener listener) { + addBlocksDownloadedEventListener(executor, listener); + addChainDownloadStartedEventListener(executor, listener); + addConnectionEventListener(executor, listener); + addGetDataEventListener(executor, listener); + addOnTransactionBroadcastListener(executor, listener); + addPreMessageReceivedEventListener(executor, listener); + } + + /** See {@link Peer#addBlocksDownloadedEventListener(BlocksDownloadedEventListener)} */ + public void addBlocksDownloadedEventListener(BlocksDownloadedEventListener listener) { + addBlocksDownloadedEventListener(Threading.USER_THREAD, listener); + } + + /** + *

Adds a listener that will be notified on the given executor when + * blocks are downloaded by the download peer.

+ * @see Peer#addBlocksDownloadedEventListener(Executor, BlocksDownloadedEventListener) + */ + public void addBlocksDownloadedEventListener(Executor executor, BlocksDownloadedEventListener listener) { + peersBlocksDownloadedEventListeners.add(new ListenerRegistration(checkNotNull(listener), executor)); + for (Peer peer : getConnectedPeers()) + peer.addBlocksDownloadedEventListener(executor, listener); + for (Peer peer : getPendingPeers()) + peer.addBlocksDownloadedEventListener(executor, listener); + } + + /** See {@link Peer#addBlocksDownloadedEventListener(BlocksDownloadedEventListener)} */ + public void addChainDownloadStartedEventListener(ChainDownloadStartedEventListener listener) { + addChainDownloadStartedEventListener(Threading.USER_THREAD, listener); + } + + /** + *

Adds a listener that will be notified on the given executor when + * chain download starts.

+ */ + public void addChainDownloadStartedEventListener(Executor executor, ChainDownloadStartedEventListener listener) { + peersChainDownloadStartedEventListeners.add(new ListenerRegistration(checkNotNull(listener), executor)); + for (Peer peer : getConnectedPeers()) + peer.addChainDownloadStartedEventListener(executor, listener); + for (Peer peer : getPendingPeers()) + peer.addChainDownloadStartedEventListener(executor, listener); + } + + /** See {@link Peer#addConnectionEventListener(PeerConnectionEventListener)} */ + public void addConnectionEventListener(PeerConnectionEventListener listener) { + addConnectionEventListener(Threading.USER_THREAD, listener); + } /** *

Adds a listener that will be notified on the given executor when:

*
    + *
  1. New peers are discovered.
  2. *
  3. New peers are connected to.
  4. *
  5. Peers are disconnected from.
  6. - *
  7. A message is received by the download peer (there is always one peer which is elected as a peer which - * will be used to retrieve data). - *
  8. Blocks are downloaded by the download peer.
  9. * *
*/ @@ -703,22 +774,22 @@ public class PeerGroup implements TransactionBroadcaster { peerConnectionEventListeners.add(new ListenerRegistration(checkNotNull(listener), executor)); for (Peer peer : getConnectedPeers()) peer.addConnectionEventListener(executor, listener); - for (Peer peer: getPendingPeers()) + for (Peer peer : getPendingPeers()) peer.addConnectionEventListener(executor, listener); } - /** See {@link Peer#addDataEventListener(Executor, PeerDataEventListener)} */ - public void addDataEventListener(final Executor executor, final PeerDataEventListener listener) { - peerDataEventListeners.add(new ListenerRegistration(checkNotNull(listener), executor)); - for (Peer peer : getConnectedPeers()) - peer.addDataEventListener(executor, listener); - for (Peer peer: getPendingPeers()) - peer.addDataEventListener(executor, listener); + /** See {@link Peer#addGetDataEventListener(GetDataEventListener)} */ + public void addGetDataEventListener(GetDataEventListener listener) { + addGetDataEventListener(Threading.USER_THREAD, listener); } - /** See {@link Peer#addDataEventListener(PeerDataEventListener)} */ - public void addDataEventListener(PeerDataEventListener listener) { - addDataEventListener(Threading.USER_THREAD, listener); + /** See {@link Peer#addGetDataEventListener(Executor, GetDataEventListener)} */ + public void addGetDataEventListener(final Executor executor, final GetDataEventListener listener) { + peerGetDataEventListeners.add(new ListenerRegistration(checkNotNull(listener), executor)); + for (Peer peer : getConnectedPeers()) + peer.addGetDataEventListener(executor, listener); + for (Peer peer : getPendingPeers()) + peer.addGetDataEventListener(executor, listener); } /** See {@link Peer#addOnTransactionBroadcastListener(OnTransactionBroadcastListener)} */ @@ -728,16 +799,54 @@ public class PeerGroup implements TransactionBroadcaster { /** See {@link Peer#addOnTransactionBroadcastListener(OnTransactionBroadcastListener)} */ public void addOnTransactionBroadcastListener(Executor executor, OnTransactionBroadcastListener listener) { - onTransactionBroadastEventListeners.add(new ListenerRegistration(checkNotNull(listener), executor)); + peersTransactionBroadastEventListeners.add(new ListenerRegistration(checkNotNull(listener), executor)); for (Peer peer : getConnectedPeers()) peer.addOnTransactionBroadcastListener(executor, listener); - for (Peer peer: getPendingPeers()) + for (Peer peer : getPendingPeers()) peer.addOnTransactionBroadcastListener(executor, listener); } - /** See {@link Peer#addConnectionEventListener(PeerConnectionEventListener)} */ - public void addConnectionEventListener(PeerConnectionEventListener listener) { - addConnectionEventListener(Threading.USER_THREAD, listener); + /** See {@link Peer#addPreMessageReceivedEventListener(PreMessageReceivedEventListener)} */ + public void addPreMessageReceivedEventListener(PreMessageReceivedEventListener listener) { + addPreMessageReceivedEventListener(Threading.USER_THREAD, listener); + } + + /** See {@link Peer#addPreMessageReceivedEventListener(Executor, PreMessageReceivedEventListener)} */ + public void addPreMessageReceivedEventListener(Executor executor, PreMessageReceivedEventListener listener) { + peersPreMessageReceivedEventListeners.add(new ListenerRegistration(checkNotNull(listener), executor)); + for (Peer peer : getConnectedPeers()) + peer.addPreMessageReceivedEventListener(executor, listener); + for (Peer peer : getPendingPeers()) + peer.addPreMessageReceivedEventListener(executor, listener); + } + + /** Use the more specific listener methods instead */ + @Deprecated @SuppressWarnings("deprecation") + public void removeEventListener(AbstractPeerEventListener listener) { + removeBlocksDownloadedEventListener(listener); + removeChainDownloadStartedEventListener(listener); + removeConnectionEventListener(listener); + removeGetDataEventListener(listener); + removeOnTransactionBroadcastListener(listener); + removePreMessageReceivedEventListener(listener); + } + + public boolean removeBlocksDownloadedEventListener(BlocksDownloadedEventListener listener) { + boolean result = ListenerRegistration.removeFromList(listener, peersBlocksDownloadedEventListeners); + for (Peer peer : getConnectedPeers()) + peer.removeBlocksDownloadedEventListener(listener); + for (Peer peer : getPendingPeers()) + peer.removeBlocksDownloadedEventListener(listener); + return result; + } + + public boolean removeChainDownloadStartedEventListener(ChainDownloadStartedEventListener listener) { + boolean result = ListenerRegistration.removeFromList(listener, peersChainDownloadStartedEventListeners); + for (Peer peer : getConnectedPeers()) + peer.removeChainDownloadStartedEventListener(listener); + for (Peer peer : getPendingPeers()) + peer.removeChainDownloadStartedEventListener(listener); + return result; } /** The given event listener will no longer be called with events. */ @@ -751,18 +860,18 @@ public class PeerGroup implements TransactionBroadcaster { } /** The given event listener will no longer be called with events. */ - public boolean removeDataEventListener(PeerDataEventListener listener) { - boolean result = ListenerRegistration.removeFromList(listener, peerDataEventListeners); + public boolean removeGetDataEventListener(GetDataEventListener listener) { + boolean result = ListenerRegistration.removeFromList(listener, peerGetDataEventListeners); for (Peer peer : getConnectedPeers()) - peer.removeDataEventListener(listener); + peer.removeGetDataEventListener(listener); for (Peer peer : getPendingPeers()) - peer.removeDataEventListener(listener); + peer.removeGetDataEventListener(listener); return result; } /** The given event listener will no longer be called with events. */ public boolean removeOnTransactionBroadcastListener(OnTransactionBroadcastListener listener) { - boolean result = ListenerRegistration.removeFromList(listener, onTransactionBroadastEventListeners); + boolean result = ListenerRegistration.removeFromList(listener, peersTransactionBroadastEventListeners); for (Peer peer : getConnectedPeers()) peer.removeOnTransactionBroadcastListener(listener); for (Peer peer : getPendingPeers()) @@ -770,26 +879,13 @@ public class PeerGroup implements TransactionBroadcaster { return result; } - /** Use the more specific listener methods instead */ - @Deprecated @SuppressWarnings("deprecation") - public void addEventListener(AbstractPeerEventListener listener, Executor executor) { - addConnectionEventListener(executor, listener); - addDataEventListener(executor, listener); - addOnTransactionBroadcastListener(executor, listener); - } - - /** Use the more specific listener methods instead */ - @Deprecated @SuppressWarnings("deprecation") - public void addEventListener(AbstractPeerEventListener listener) { - addEventListener(listener, Threading.USER_THREAD); - } - - /** Use the more specific listener methods instead */ - @Deprecated @SuppressWarnings("deprecation") - public void removeEventListener(AbstractPeerEventListener listener) { - removeConnectionEventListener(listener); - removeDataEventListener(listener); - removeOnTransactionBroadcastListener(listener); + public boolean removePreMessageReceivedEventListener(PreMessageReceivedEventListener listener) { + boolean result = ListenerRegistration.removeFromList(listener, peersPreMessageReceivedEventListeners); + for (Peer peer : getConnectedPeers()) + peer.removePreMessageReceivedEventListener(listener); + for (Peer peer : getPendingPeers()) + peer.removePreMessageReceivedEventListener(listener); + return result; } /** @@ -1273,7 +1369,7 @@ public class PeerGroup implements TransactionBroadcaster { /** * Returns the number of currently connected peers. To be informed when this count changes, register a - * {@link PeerEventListener} and use the onPeerConnected/onPeerDisconnected methods. + * {@link org.bitcoinj.core.listeners.PeerConnectionEventListener} and use the onPeerConnected/onPeerDisconnected methods. */ public int numConnectedPeers() { return peers.size(); @@ -1383,10 +1479,20 @@ public class PeerGroup implements TransactionBroadcaster { public void startBlockChainDownload(PeerDataEventListener listener) { lock.lock(); try { - if (downloadPeer != null && this.downloadListener != null) - downloadPeer.removeDataEventListener(this.downloadListener); - if (downloadPeer != null && listener != null) - downloadPeer.addDataEventListener(listener); + if (downloadPeer != null) { + if (this.downloadListener != null) { + downloadPeer.removeBlocksDownloadedEventListener(this.downloadListener); + downloadPeer.removeChainDownloadStartedEventListener(this.downloadListener); + downloadPeer.removeGetDataEventListener(this.downloadListener); + downloadPeer.removePreMessageReceivedEventListener(this.downloadListener); + } + if (listener != null) { + downloadPeer.addBlocksDownloadedEventListener(listener); + downloadPeer.addChainDownloadStartedEventListener(listener); + downloadPeer.addGetDataEventListener(listener); + downloadPeer.addPreMessageReceivedEventListener(listener); + } + } this.downloadListener = listener; // TODO: be more nuanced about which peer to download from. We can also try // downloading from multiple peers and handle the case when a new peer comes along @@ -1444,14 +1550,22 @@ public class PeerGroup implements TransactionBroadcaster { } } // Make sure the peer knows how to upload transactions that are requested from us. - peer.addDataEventListener(Threading.SAME_THREAD, peerListener); + peer.addBlocksDownloadedEventListener(Threading.SAME_THREAD, peerListener); + peer.addGetDataEventListener(Threading.SAME_THREAD, peerListener); + // And set up event listeners for clients. This will allow them to find out about new transactions and blocks. + for (ListenerRegistration registration : peersBlocksDownloadedEventListeners) + peer.addBlocksDownloadedEventListener(registration.executor, registration.listener); + for (ListenerRegistration registration : peersChainDownloadStartedEventListeners) + peer.addChainDownloadStartedEventListener(registration.executor, registration.listener); for (ListenerRegistration registration : peerConnectionEventListeners) peer.addConnectionEventListenerWithoutOnDisconnect(registration.executor, registration.listener); - for (ListenerRegistration registration : peerDataEventListeners) - peer.addDataEventListener(registration.executor, registration.listener); - for (ListenerRegistration registration : onTransactionBroadastEventListeners) + for (ListenerRegistration registration : peerGetDataEventListeners) + peer.addGetDataEventListener(registration.executor, registration.listener); + for (ListenerRegistration registration : peersTransactionBroadastEventListeners) peer.addOnTransactionBroadcastListener(registration.executor, registration.listener); + for (ListenerRegistration registration : peersPreMessageReceivedEventListeners) + peer.addPreMessageReceivedEventListener(registration.executor, registration.listener); } finally { lock.unlock(); } @@ -1505,15 +1619,23 @@ public class PeerGroup implements TransactionBroadcaster { return; if (downloadPeer != null) { log.info("Unsetting download peer: {}", downloadPeer); - if (downloadListener != null) - downloadPeer.removeDataEventListener(downloadListener); + if (downloadListener != null) { + downloadPeer.removeBlocksDownloadedEventListener(downloadListener); + downloadPeer.removeChainDownloadStartedEventListener(downloadListener); + downloadPeer.removeGetDataEventListener(downloadListener); + downloadPeer.removePreMessageReceivedEventListener(downloadListener); + } downloadPeer.setDownloadData(false); } downloadPeer = peer; if (downloadPeer != null) { log.info("Setting download peer: {}", downloadPeer); - if (downloadListener != null) - peer.addDataEventListener(Threading.SAME_THREAD, downloadListener); + if (downloadListener != null) { + peer.addBlocksDownloadedEventListener(Threading.SAME_THREAD, downloadListener); + peer.addChainDownloadStartedEventListener(Threading.SAME_THREAD, downloadListener); + peer.addGetDataEventListener(Threading.SAME_THREAD, downloadListener); + peer.addPreMessageReceivedEventListener(Threading.SAME_THREAD, downloadListener); + } downloadPeer.setDownloadData(true); if (chain != null) downloadPeer.setDownloadParameters(fastCatchupTimeSecs, bloomFilterMerger.getLastFilter() != null); @@ -1611,15 +1733,23 @@ public class PeerGroup implements TransactionBroadcaster { lock.unlock(); } - peer.removeDataEventListener(peerListener); + peer.removeBlocksDownloadedEventListener(peerListener); + peer.removeGetDataEventListener(peerListener); for (Wallet wallet : wallets) { peer.removeWallet(wallet); } final int fNumConnectedPeers = numConnectedPeers; - for (ListenerRegistration registration : peerDataEventListeners) - peer.removeDataEventListener(registration.listener); - for (ListenerRegistration registration : onTransactionBroadastEventListeners) + + for (ListenerRegistration registration: peersBlocksDownloadedEventListeners) + peer.removeBlocksDownloadedEventListener(registration.listener); + for (ListenerRegistration registration: peersChainDownloadStartedEventListeners) + peer.removeChainDownloadStartedEventListener(registration.listener); + for (ListenerRegistration registration: peerGetDataEventListeners) + peer.removeGetDataEventListener(registration.listener); + for (ListenerRegistration registration: peersPreMessageReceivedEventListeners) + peer.removePreMessageReceivedEventListener(registration.listener); + for (ListenerRegistration registration : peersTransactionBroadastEventListeners) peer.removeOnTransactionBroadcastListener(registration.listener); for (final ListenerRegistration registration : peerConnectionEventListeners) { registration.executor.execute(new Runnable() { @@ -1656,7 +1786,7 @@ public class PeerGroup implements TransactionBroadcaster { } } - private class ChainDownloadSpeedCalculator extends AbstractPeerDataEventListener implements Runnable { + private class ChainDownloadSpeedCalculator implements BlocksDownloadedEventListener, Runnable { private int blocksInLastSecond, txnsInLastSecond, origTxnsInLastSecond; private long bytesInLastSecond; @@ -1783,7 +1913,7 @@ public class PeerGroup implements TransactionBroadcaster { chainDownloadSpeedCalculator = new ChainDownloadSpeedCalculator(); executor.scheduleAtFixedRate(chainDownloadSpeedCalculator, 1, 1, TimeUnit.SECONDS); } - peer.addDataEventListener(Threading.SAME_THREAD, chainDownloadSpeedCalculator); + peer.addBlocksDownloadedEventListener(Threading.SAME_THREAD, chainDownloadSpeedCalculator); // startBlockChainDownload will setDownloadData(true) on itself automatically. peer.startBlockChainDownload(); diff --git a/core/src/main/java/org/bitcoinj/core/TransactionBroadcast.java b/core/src/main/java/org/bitcoinj/core/TransactionBroadcast.java index 48097421..51c50120 100644 --- a/core/src/main/java/org/bitcoinj/core/TransactionBroadcast.java +++ b/core/src/main/java/org/bitcoinj/core/TransactionBroadcast.java @@ -19,8 +19,6 @@ package org.bitcoinj.core; import com.google.common.annotations.*; import com.google.common.base.*; import com.google.common.util.concurrent.*; -import org.bitcoinj.core.listeners.AbstractPeerDataEventListener; -import org.bitcoinj.core.listeners.PeerDataEventListener; import org.bitcoinj.utils.*; import org.slf4j.*; @@ -29,6 +27,7 @@ import java.util.*; import java.util.concurrent.*; import static com.google.common.base.Preconditions.checkState; +import org.bitcoinj.core.listeners.PreMessageReceivedEventListener; /** * Represents a single transaction broadcast that we are performing. A broadcast occurs after a new transaction is created @@ -88,7 +87,7 @@ public class TransactionBroadcast { this.minConnections = minConnections; } - private PeerDataEventListener rejectionListener = new AbstractPeerDataEventListener() { + private PreMessageReceivedEventListener rejectionListener = new PreMessageReceivedEventListener() { @Override public Message onPreMessageReceived(Peer peer, Message m) { if (m instanceof RejectMessage) { @@ -100,7 +99,7 @@ public class TransactionBroadcast { if (size > threshold) { log.warn("Threshold for considering broadcast rejected has been reached ({}/{})", size, threshold); future.setException(new RejectedTransactionException(tx, rejectMessage)); - peerGroup.removeDataEventListener(this); + peerGroup.removePreMessageReceivedEventListener(this); } } } @@ -109,7 +108,7 @@ public class TransactionBroadcast { }; public ListenableFuture broadcast() { - peerGroup.addDataEventListener(Threading.SAME_THREAD, rejectionListener); + peerGroup.addPreMessageReceivedEventListener(Threading.SAME_THREAD, rejectionListener); log.info("Waiting for {} peers required for broadcast, we have {} ...", minConnections, peerGroup.getConnectedPeers().size()); peerGroup.waitForPeers(minConnections).addListener(new EnoughAvailablePeers(), Threading.SAME_THREAD); return future; @@ -161,7 +160,7 @@ public class TransactionBroadcast { // So we just have to assume we're done, at that point. This happens when we're not given // any peer discovery source and the user just calls connectTo() once. if (minConnections == 1) { - peerGroup.removeDataEventListener(rejectionListener); + peerGroup.removePreMessageReceivedEventListener(rejectionListener); future.set(tx); } } @@ -197,7 +196,7 @@ public class TransactionBroadcast { // We're done! It's important that the PeerGroup lock is not held (by this thread) at this // point to avoid triggering inversions when the Future completes. log.info("broadcastTransaction: {} complete", tx.getHash()); - peerGroup.removeDataEventListener(rejectionListener); + peerGroup.removePreMessageReceivedEventListener(rejectionListener); conf.removeEventListener(this); future.set(tx); // RE-ENTRANCY POINT } diff --git a/core/src/main/java/org/bitcoinj/core/listeners/BlocksDownloadedEventListener.java b/core/src/main/java/org/bitcoinj/core/listeners/BlocksDownloadedEventListener.java new file mode 100644 index 00000000..c4e7f379 --- /dev/null +++ b/core/src/main/java/org/bitcoinj/core/listeners/BlocksDownloadedEventListener.java @@ -0,0 +1,43 @@ +/** + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoinj.core.listeners; + +import org.bitcoinj.core.*; + +import javax.annotation.*; + +/** + *

Implementors can listen to events like blocks being downloaded/transactions being broadcast/connect/disconnects, + * they can pre-filter messages before they are procesesed by a {@link Peer} or {@link PeerGroup}, and they can + * provide transactions to remote peers when they ask for them.

+ */ +public interface BlocksDownloadedEventListener { + + // 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.

+ * + *

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.

+ * + * @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 + */ + void onBlocksDownloaded(Peer peer, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft); +} diff --git a/core/src/main/java/org/bitcoinj/core/listeners/ChainDownloadStartedEventListener.java b/core/src/main/java/org/bitcoinj/core/listeners/ChainDownloadStartedEventListener.java new file mode 100644 index 00000000..56f6ba85 --- /dev/null +++ b/core/src/main/java/org/bitcoinj/core/listeners/ChainDownloadStartedEventListener.java @@ -0,0 +1,35 @@ +/** + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoinj.core.listeners; + +import org.bitcoinj.core.*; + +/** + *

Implementors can listen to events like blocks being downloaded/transactions being broadcast/connect/disconnects, + * they can pre-filter messages before they are procesesed by a {@link Peer} or {@link PeerGroup}, and they can + * provide transactions to remote peers when they ask for them.

+ */ +public interface ChainDownloadStartedEventListener { + + /** + * Called when a download is started with the initial number of blocks to be downloaded. + * + * @param peer the peer receiving the block + * @param blocksLeft the number of blocks left to download + */ + void onChainDownloadStarted(Peer peer, int blocksLeft); +} diff --git a/core/src/main/java/org/bitcoinj/core/listeners/GetDataEventListener.java b/core/src/main/java/org/bitcoinj/core/listeners/GetDataEventListener.java new file mode 100644 index 00000000..4a8041ae --- /dev/null +++ b/core/src/main/java/org/bitcoinj/core/listeners/GetDataEventListener.java @@ -0,0 +1,40 @@ +/** + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoinj.core.listeners; + +import org.bitcoinj.core.*; + +import javax.annotation.*; +import java.util.*; + +/** + *

Implementors can listen to events like blocks being downloaded/transactions being broadcast/connect/disconnects, + * they can pre-filter messages before they are procesesed by a {@link Peer} or {@link PeerGroup}, and they can + * provide transactions to remote peers when they ask for them.

+ */ +public interface GetDataEventListener { + + /** + *

Called when a peer receives a getdata message, usually in response to an "inv" being broadcast. Return as many + * items as possible which appear in the {@link GetDataMessage}, or null if you're not interested in responding.

+ * + *

Note that this will never be called if registered with any executor other than + * {@link org.bitcoinj.utils.Threading#SAME_THREAD}

+ */ + @Nullable + List getData(Peer peer, GetDataMessage m); +} diff --git a/core/src/main/java/org/bitcoinj/core/listeners/NewBestBlockListener.java b/core/src/main/java/org/bitcoinj/core/listeners/NewBestBlockListener.java index 5850faf4..6c40554d 100644 --- a/core/src/main/java/org/bitcoinj/core/listeners/NewBestBlockListener.java +++ b/core/src/main/java/org/bitcoinj/core/listeners/NewBestBlockListener.java @@ -25,8 +25,8 @@ public interface NewBestBlockListener { /** * Called when a new block on the best chain is seen, after relevant * transactions are extracted and sent to us via either - * {@link ReceiveFromBlockListener#receiveFromBlock(Transaction, StoredBlock, org.bitcoinj.core.BlockChain.NewBlockType, int)} - * or {@link TransactionIsInBlockListener#notifyTransactionIsInBlock(Sha256Hash, StoredBlock, org.bitcoinj.core.BlockChain.NewBlockType, int)}. + * {@link TransactionReceivedInBlockListener#receiveFromBlock(org.bitcoinj.core.Transaction, org.bitcoinj.core.StoredBlock, org.bitcoinj.core.BlockChain.NewBlockType, int relativityOffset)} + * or {@link TransactionReceivedInBlockListener#notifyTransactionIsInBlock(org.bitcoinj.core.Sha256Hash, org.bitcoinj.core.StoredBlock, org.bitcoinj.core.BlockChain.NewBlockType, int)}. * If this block is causing a re-organise to a new chain, this method is NOT * called even though the block may be the new best block: your reorganize * implementation is expected to do whatever would normally be done do for a diff --git a/core/src/main/java/org/bitcoinj/core/listeners/PeerDataEventListener.java b/core/src/main/java/org/bitcoinj/core/listeners/PeerDataEventListener.java index 5a6ed02b..9063c221 100644 --- a/core/src/main/java/org/bitcoinj/core/listeners/PeerDataEventListener.java +++ b/core/src/main/java/org/bitcoinj/core/listeners/PeerDataEventListener.java @@ -18,56 +18,11 @@ package org.bitcoinj.core.listeners; import org.bitcoinj.core.*; -import javax.annotation.*; -import java.util.*; - /** *

Implementors can listen to events like blocks being downloaded/transactions being broadcast/connect/disconnects, * they can pre-filter messages before they are processed by a {@link Peer} or {@link PeerGroup}, and they can * provide transactions to remote peers when they ask for them.

*/ -public interface PeerDataEventListener { - - // 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.

- * - *

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.

- * - * @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 - */ - 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. - * - * @param peer the peer receiving the block - * @param blocksLeft the number of blocks left to download - */ - void onChainDownloadStarted(Peer peer, int blocksLeft); - - /** - *

Called when a message is received by a peer, before the message is processed. The returned message is - * processed instead. Returning null will cause the message to be ignored by the Peer returning the same message - * object allows you to see the messages received but not change them. The result from one event listeners - * callback is passed as "m" to the next, forming a chain.

- * - *

Note that this will never be called if registered with any executor other than - * {@link org.bitcoinj.utils.Threading#SAME_THREAD}

- */ - Message onPreMessageReceived(Peer peer, Message m); - - /** - *

Called when a peer receives a getdata message, usually in response to an "inv" being broadcast. Return as many - * items as possible which appear in the {@link GetDataMessage}, or null if you're not interested in responding.

- * - *

Note that this will never be called if registered with any executor other than - * {@link org.bitcoinj.utils.Threading#SAME_THREAD}

- */ - @Nullable - List getData(Peer peer, GetDataMessage m); +public interface PeerDataEventListener extends BlocksDownloadedEventListener, ChainDownloadStartedEventListener, + GetDataEventListener, PreMessageReceivedEventListener { } diff --git a/core/src/main/java/org/bitcoinj/core/listeners/PreMessageReceivedEventListener.java b/core/src/main/java/org/bitcoinj/core/listeners/PreMessageReceivedEventListener.java new file mode 100644 index 00000000..732acb1c --- /dev/null +++ b/core/src/main/java/org/bitcoinj/core/listeners/PreMessageReceivedEventListener.java @@ -0,0 +1,38 @@ +/** + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoinj.core.listeners; + +import org.bitcoinj.core.*; + +/** + *

Implementors can listen to events like blocks being downloaded/transactions being broadcast/connect/disconnects, + * they can pre-filter messages before they are procesesed by a {@link Peer} or {@link PeerGroup}, and they can + * provide transactions to remote peers when they ask for them.

+ */ +public interface PreMessageReceivedEventListener { + + /** + *

Called when a message is received by a peer, before the message is processed. The returned message is + * processed instead. Returning null will cause the message to be ignored by the Peer returning the same message + * object allows you to see the messages received but not change them. The result from one event listeners + * callback is passed as "m" to the next, forming a chain.

+ * + *

Note that this will never be called if registered with any executor other than + * {@link org.bitcoinj.utils.Threading#SAME_THREAD}

+ */ + Message onPreMessageReceived(Peer peer, Message m); +} diff --git a/core/src/main/java/org/bitcoinj/core/listeners/ReorganizeListener.java b/core/src/main/java/org/bitcoinj/core/listeners/ReorganizeListener.java index 221c6633..c977cbc6 100644 --- a/core/src/main/java/org/bitcoinj/core/listeners/ReorganizeListener.java +++ b/core/src/main/java/org/bitcoinj/core/listeners/ReorganizeListener.java @@ -25,7 +25,8 @@ import org.bitcoinj.core.VerificationException; public interface ReorganizeListener { /** - * Called by the {@link BlockChain} when the best chain (representing total work done) has changed. In this case, + * Called by the {@link org.bitcoinj.core.BlockChain} when the best chain + * (representing total work done) has changed. In this case, * we need to go through our transactions and find out if any have become invalid. It's possible for our balance * to go down in this case: money we thought we had can suddenly vanish if the rest of the network agrees it * should be so.

diff --git a/core/src/main/java/org/bitcoinj/kits/WalletAppKit.java b/core/src/main/java/org/bitcoinj/kits/WalletAppKit.java index 62c000cc..b52851fb 100644 --- a/core/src/main/java/org/bitcoinj/kits/WalletAppKit.java +++ b/core/src/main/java/org/bitcoinj/kits/WalletAppKit.java @@ -20,11 +20,9 @@ package org.bitcoinj.kits; import com.google.common.collect.*; import com.google.common.util.concurrent.*; import com.subgraph.orchid.*; -import org.bitcoinj.core.listeners.DownloadProgressTracker; -import org.bitcoinj.core.listeners.PeerDataEventListener; +import org.bitcoinj.core.listeners.*; import org.bitcoinj.core.*; import org.bitcoinj.net.discovery.*; -import org.bitcoinj.params.*; import org.bitcoinj.protocols.channels.*; import org.bitcoinj.store.*; import org.bitcoinj.wallet.*; @@ -76,7 +74,7 @@ public class WalletAppKit extends AbstractIdleService { protected boolean useAutoSave = true; protected PeerAddress[] peerAddresses; - protected PeerDataEventListener downloadListener; + protected DownloadProgressTracker downloadListener; protected boolean autoStop = true; protected InputStream checkpoints; protected boolean blockingStartup = true; @@ -135,7 +133,7 @@ public class WalletAppKit extends AbstractIdleService { * {@link org.bitcoinj.core.DownloadProgressTracker} is a good choice. This has no effect unless setBlockingStartup(false) has been called * too, due to some missing implementation code. */ - public WalletAppKit setDownloadListener(PeerDataEventListener listener) { + public WalletAppKit setDownloadListener(DownloadProgressTracker listener) { this.downloadListener = listener; return this; } @@ -341,7 +339,7 @@ public class WalletAppKit extends AbstractIdleService { @Override public void onSuccess(@Nullable Object result) { completeExtensionInitiations(vPeerGroup); - final PeerDataEventListener l = downloadListener == null ? new DownloadProgressTracker() : downloadListener; + final DownloadProgressTracker l = downloadListener == null ? new DownloadProgressTracker() : downloadListener; vPeerGroup.startBlockChainDownload(l); } diff --git a/core/src/test/java/org/bitcoinj/core/BitcoindComparisonTool.java b/core/src/test/java/org/bitcoinj/core/BitcoindComparisonTool.java index fb2de158..3b3ca65f 100644 --- a/core/src/test/java/org/bitcoinj/core/BitcoindComparisonTool.java +++ b/core/src/test/java/org/bitcoinj/core/BitcoindComparisonTool.java @@ -87,7 +87,7 @@ public class BitcoindComparisonTool { final Set blocksPendingSend = Collections.synchronizedSet(new HashSet()); final AtomicInteger unexpectedInvs = new AtomicInteger(0); final SettableFuture connectedFuture = SettableFuture.create(); - final AbstractPeerEventListener listener = new AbstractPeerEventListener() { + final PeerConnectionEventListener listener = new PeerConnectionEventListener() { @Override public void onPeerConnected(Peer peer, int peerCount) { if (!peer.getPeerVersionMessage().subVer.contains("Satoshi")) { @@ -114,6 +114,13 @@ public class BitcoindComparisonTool { System.exit(1); } + @Override + public void onPeersDiscovered(Set peerAddresses) { + // Ignore + } + }; + + final PreMessageReceivedEventListener preMessageReceivedListener = new PreMessageReceivedEventListener() { @Override public Message onPreMessageReceived(Peer peer, Message m) { if (m instanceof HeadersMessage) { @@ -196,7 +203,7 @@ public class BitcoindComparisonTool { } }; bitcoind.addConnectionEventListener(Threading.SAME_THREAD, listener); - bitcoind.addDataEventListener(Threading.SAME_THREAD, listener); + bitcoind.addPreMessageReceivedEventListener(Threading.SAME_THREAD, preMessageReceivedListener); bitcoindChainHead = params.getGenesisBlock().getHash(); diff --git a/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java b/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java index 3b1730eb..bc07b0ac 100644 --- a/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java +++ b/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java @@ -47,7 +47,8 @@ public class PeerGroupTest extends TestWithPeerGroup { private BlockingQueue connectedPeers; private BlockingQueue disconnectedPeers; - private AbstractPeerEventListener listener; + private PeerConnectionEventListener listener; + private PreMessageReceivedEventListener preMessageReceivedListener; private Map peerToMessageCount; @Parameterized.Parameters @@ -67,7 +68,7 @@ public class PeerGroupTest extends TestWithPeerGroup { peerToMessageCount = new HashMap(); connectedPeers = new LinkedBlockingQueue(); disconnectedPeers = new LinkedBlockingQueue(); - listener = new AbstractPeerEventListener() { + listener = new PeerConnectionEventListener() { @Override public void onPeerConnected(Peer peer, int peerCount) { connectedPeers.add(peer); @@ -78,6 +79,13 @@ public class PeerGroupTest extends TestWithPeerGroup { disconnectedPeers.add(peer); } + @Override + public void onPeersDiscovered(Set peerAddresses) { + // Ignore + } + }; + + preMessageReceivedListener = new PreMessageReceivedEventListener() { @Override public Message onPreMessageReceived(Peer peer, Message m) { AtomicInteger messageCount = peerToMessageCount.get(peer); @@ -102,7 +110,7 @@ public class PeerGroupTest extends TestWithPeerGroup { public void listener() throws Exception { peerGroup.start(); peerGroup.addConnectionEventListener(listener); - peerGroup.addDataEventListener(listener); + peerGroup.addPreMessageReceivedEventListener(preMessageReceivedListener); // Create a couple of peers. InboundMessageQueuer p1 = connectPeer(1); @@ -124,8 +132,8 @@ public class PeerGroupTest extends TestWithPeerGroup { assertTrue(peerGroup.removeConnectionEventListener(listener)); assertFalse(peerGroup.removeConnectionEventListener(listener)); - assertTrue(peerGroup.removeDataEventListener(listener)); - assertFalse(peerGroup.removeDataEventListener(listener)); + assertTrue(peerGroup.removePreMessageReceivedEventListener(preMessageReceivedListener)); + assertFalse(peerGroup.removePreMessageReceivedEventListener(preMessageReceivedListener)); } @Test @@ -532,7 +540,7 @@ public class PeerGroupTest extends TestWithPeerGroup { new InetSocketAddress("localhost", 2002) ); peerGroup.addConnectionEventListener(listener); - peerGroup.addDataEventListener(listener); + peerGroup.addPreMessageReceivedEventListener(preMessageReceivedListener); peerGroup.addPeerDiscovery(new PeerDiscovery() { @Override public InetSocketAddress[] getPeers(long services, long unused, TimeUnit unused2) throws PeerDiscoveryException { diff --git a/core/src/test/java/org/bitcoinj/core/PeerTest.java b/core/src/test/java/org/bitcoinj/core/PeerTest.java index 04d0fe54..d7b51ec8 100644 --- a/core/src/test/java/org/bitcoinj/core/PeerTest.java +++ b/core/src/test/java/org/bitcoinj/core/PeerTest.java @@ -315,7 +315,7 @@ public class PeerTest extends TestWithNetworkConnections { connect(); // Round-trip a ping so that we never see the response verack if we attach too quick pingAndWait(writeTarget); - peer.addDataEventListener(Threading.SAME_THREAD, new AbstractPeerDataEventListener() { + peer.addPreMessageReceivedEventListener(Threading.SAME_THREAD, new PreMessageReceivedEventListener() { @Override public synchronized Message onPreMessageReceived(Peer p, Message m) { if (p != peer) @@ -331,7 +331,8 @@ public class PeerTest extends TestWithNetworkConnections { fail.set(true); return m; } - + }); + peer.addBlocksDownloadedEventListener(Threading.SAME_THREAD, new BlocksDownloadedEventListener() { @Override public synchronized void onBlocksDownloaded(Peer p, Block block, @Nullable FilteredBlock filteredBlock, int blocksLeft) { int newValue = newBlockMessagesReceived.incrementAndGet(); @@ -369,7 +370,7 @@ public class PeerTest extends TestWithNetworkConnections { connect(); fail.set(true); - peer.addDataEventListener(Threading.SAME_THREAD, new AbstractPeerDataEventListener() { + peer.addChainDownloadStartedEventListener(Threading.SAME_THREAD, new ChainDownloadStartedEventListener() { @Override public void onChainDownloadStarted(Peer p, int blocksLeft) { if (p == peer && blocksLeft == 108) diff --git a/core/src/test/java/org/bitcoinj/testing/TestWithNetworkConnections.java b/core/src/test/java/org/bitcoinj/testing/TestWithNetworkConnections.java index 73635ac0..3dfa433e 100644 --- a/core/src/test/java/org/bitcoinj/testing/TestWithNetworkConnections.java +++ b/core/src/test/java/org/bitcoinj/testing/TestWithNetworkConnections.java @@ -18,8 +18,6 @@ package org.bitcoinj.testing; import org.bitcoinj.core.listeners.AbstractPeerConnectionEventListener; -import org.bitcoinj.core.listeners.AbstractPeerDataEventListener; -import org.bitcoinj.core.listeners.PeerDataEventListener; import org.bitcoinj.core.*; import org.bitcoinj.net.*; import org.bitcoinj.params.UnitTestParams; @@ -41,6 +39,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; +import org.bitcoinj.core.listeners.PreMessageReceivedEventListener; /** * Utility class that makes it easy to work with mock NetworkConnections. @@ -208,7 +207,7 @@ public class TestWithNetworkConnections { private void inboundPongAndWait(final InboundMessageQueuer p, final long nonce) throws Exception { // Receive a ping (that the Peer doesn't see) and wait for it to get through the socket final SettableFuture pongReceivedFuture = SettableFuture.create(); - PeerDataEventListener listener = new AbstractPeerDataEventListener() { + PreMessageReceivedEventListener listener = new PreMessageReceivedEventListener() { @Override public Message onPreMessageReceived(Peer p, Message m) { if (m instanceof Pong && ((Pong) m).getNonce() == nonce) { @@ -218,10 +217,10 @@ public class TestWithNetworkConnections { return m; } }; - p.peer.addDataEventListener(Threading.SAME_THREAD, listener); + p.peer.addPreMessageReceivedEventListener(Threading.SAME_THREAD, listener); inbound(p, new Pong(nonce)); pongReceivedFuture.get(); - p.peer.removeDataEventListener(listener); + p.peer.removePreMessageReceivedEventListener(listener); } protected void pingAndWait(final InboundMessageQueuer p) throws Exception { diff --git a/examples/src/main/java/org/bitcoinj/examples/DoubleSpend.java b/examples/src/main/java/org/bitcoinj/examples/DoubleSpend.java index c9264753..d700fad8 100644 --- a/examples/src/main/java/org/bitcoinj/examples/DoubleSpend.java +++ b/examples/src/main/java/org/bitcoinj/examples/DoubleSpend.java @@ -14,7 +14,7 @@ package org.bitcoinj.examples; -import org.bitcoinj.core.listeners.AbstractPeerEventListener; +import org.bitcoinj.core.listeners.PreMessageReceivedEventListener; import org.bitcoinj.core.*; import org.bitcoinj.kits.WalletAppKit; import org.bitcoinj.params.RegTestParams; @@ -46,8 +46,8 @@ public class DoubleSpend { Transaction tx1 = kit.wallet().createSend(Address.fromBase58(params, "muYPFNCv7KQEG2ZLM7Z3y96kJnNyXJ53wm"), CENT); Transaction tx2 = kit.wallet().createSend(Address.fromBase58(params, "muYPFNCv7KQEG2ZLM7Z3y96kJnNyXJ53wm"), CENT.add(SATOSHI.multiply(10))); final Peer peer = kit.peerGroup().getConnectedPeers().get(0); - peer.addDataEventListener(Threading.SAME_THREAD, - new AbstractPeerEventListener() { + peer.addPreMessageReceivedEventListener(Threading.SAME_THREAD, + new PreMessageReceivedEventListener() { @Override public Message onPreMessageReceived(Peer peer, Message m) { System.err.println("Got a message!" + m.getClass().getSimpleName() + ": " + m); diff --git a/tools/src/main/java/org/bitcoinj/tools/WalletTool.java b/tools/src/main/java/org/bitcoinj/tools/WalletTool.java index 4a13947b..5598d7cf 100644 --- a/tools/src/main/java/org/bitcoinj/tools/WalletTool.java +++ b/tools/src/main/java/org/bitcoinj/tools/WalletTool.java @@ -48,8 +48,12 @@ import joptsimple.OptionSet; import joptsimple.OptionSpec; import joptsimple.util.DateConverter; -import org.bitcoinj.core.listeners.AbstractPeerDataEventListener; +import org.bitcoinj.core.listeners.BlocksDownloadedEventListener; import org.bitcoinj.core.listeners.DownloadProgressTracker; +import org.bitcoinj.core.listeners.WalletChangeEventListener; +import org.bitcoinj.core.listeners.WalletCoinsReceivedEventListener; +import org.bitcoinj.core.listeners.WalletCoinsSentEventListener; +import org.bitcoinj.core.listeners.WalletReorganizeEventListener; import org.bitcoinj.wallet.MarriedKeyChain; import org.bitcoinj.wallet.Protos; import org.slf4j.Logger; @@ -77,10 +81,6 @@ import java.util.logging.LogManager; import static org.bitcoinj.core.Coin.parseCoin; import static com.google.common.base.Preconditions.checkNotNull; -import org.bitcoinj.core.listeners.WalletChangeEventListener; -import org.bitcoinj.core.listeners.WalletCoinsReceivedEventListener; -import org.bitcoinj.core.listeners.WalletCoinsSentEventListener; -import org.bitcoinj.core.listeners.WalletReorganizeEventListener; /** * A command line tool for manipulating wallets and working with Bitcoin. @@ -1131,7 +1131,7 @@ public class WalletTool { break; case BLOCK: - peers.addDataEventListener(new AbstractPeerDataEventListener() { + peers.addBlocksDownloadedEventListener(new BlocksDownloadedEventListener() { @Override 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