3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-07 06:44:16 +00:00

Link Peer and Wallet directly instead of using an event listener.

This paves the way for tighter coupling in future, needed for various features.
This commit is contained in:
Mike Hearn 2013-01-20 20:56:36 +01:00
parent e9babb2772
commit 8b9ddd2caf
3 changed files with 24 additions and 37 deletions

View File

@ -53,6 +53,7 @@ public class Peer {
private final NetworkParameters params;
private final AbstractBlockChain blockChain;
private PeerAddress address;
// TODO: Make the types here explicit and remove synchronization on adders/removers.
private List<PeerEventListener> eventListeners;
private List<PeerLifecycleListener> lifecycleListeners;
// Whether to try and download blocks and transactions from this peer. Set to false by PeerGroup if not the
@ -69,6 +70,8 @@ public class Peer {
// A class that tracks recent transactions that have been broadcast across the network, counts how many
// peers announced them and updates the transaction confidence data. It is passed to each Peer.
private MemoryPool memoryPool;
// Each wallet added to the peer will be notified of downloaded transaction data.
private CopyOnWriteArrayList<Wallet> wallets;
// A time before which we only download block headers, after that point we download block bodies.
private long fastCatchupTimeSecs;
// Whether we are currently downloading headers only or block bodies. Starts at true. If the fast catchup time is
@ -123,6 +126,7 @@ public class Peer {
this.handler = new PeerHandler();
this.pendingPings = new CopyOnWriteArrayList<PendingPing>();
this.lastPingTimes = null;
this.wallets = new CopyOnWriteArrayList<Wallet>();
}
/**
@ -413,9 +417,18 @@ public class Peer {
}
if (maybeHandleRequestedData(tx))
return;
// Tell all listeners (like wallets) about this tx so they can decide whether to keep it or not. If no
// listener keeps a reference around then the memory pool will forget about it after a while too because
// it uses weak references.
// Tell all wallets about this tx so they can check if it's relevant or not.
for (ListIterator<Wallet> it = wallets.listIterator(); it.hasNext();) {
Wallet wallet = it.next();
try {
wallet.receivePending(tx);
} catch (VerificationException e) {
log.error("Wallet failed to verify tx", e);
// Carry on, listeners may still want to know.
}
}
// Tell all listeners about this tx so they can decide whether to keep it or not. If no listener keeps a
// reference around then the memory pool will forget about it after a while too because it uses weak references.
final Transaction ftx = tx;
EventListenerInvoker.invoke(eventListeners, new EventListenerInvoker<PeerEventListener>() {
@Override
@ -863,12 +876,12 @@ public class Peer {
* independently, otherwise the wallet will receive duplicate notifications.
*/
public void addWallet(Wallet wallet) {
addEventListener(wallet.getPeerEventListener());
wallets.add(wallet);
}
/** Unlinks the given wallet from peer. See {@link Peer#addWallet(Wallet)}. */
public void removeWallet(Wallet wallet) {
removeEventListener(wallet.getPeerEventListener());
wallets.remove(wallet);
}
/**

View File

@ -542,7 +542,6 @@ public class PeerGroup extends AbstractIdleService {
public synchronized void addWallet(Wallet wallet) {
Preconditions.checkNotNull(wallet);
wallets.add(wallet);
addEventListener(wallet.getPeerEventListener());
announcePendingWalletTransactions(Collections.singletonList(wallet), peers);
// Don't bother downloading block bodies before the oldest keys in all our wallets. Make sure we recalculate
@ -609,7 +608,6 @@ public class PeerGroup extends AbstractIdleService {
if (wallet == null)
throw new IllegalArgumentException("wallet is null");
wallets.remove(wallet);
removeEventListener(wallet.getPeerEventListener());
}
/**
@ -854,13 +852,17 @@ public class PeerGroup extends AbstractIdleService {
if (downloadPeer != null) {
log.info("Unsetting download peer: {}", downloadPeer);
downloadPeer.setDownloadData(false);
for (Wallet wallet : wallets)
downloadPeer.removeWallet(wallet);
}
downloadPeer = peer;
if (downloadPeer != null) {
log.info("Setting download peer: {}", downloadPeer);
downloadPeer.setDownloadData(true);
if (chain != null)
downloadPeer.setDownloadParameters(fastCatchupTimeSecs, bloomFilter != null);
downloadPeer.setDownloadParameters(fastCatchupTimeSecs, bloomFilter != null);
// TODO: The peer should calculate the fast catchup time from the added wallets here.
for (Wallet wallet : wallets)
downloadPeer.addWallet(wallet);
}
}

View File

@ -2201,34 +2201,6 @@ public class Wallet implements Serializable, BlockChainListener {
}
return earliestTime;
}
// This object is used to receive events from a Peer or PeerGroup. Currently it is only used to receive
// transactions. Note that it does NOT pay attention to block message because they will be received from the
// BlockChain object along with extra data we need for correct handling of re-orgs.
private transient PeerEventListener peerEventListener;
/**
* The returned object can be used to connect the wallet to a {@link Peer} or {@link PeerGroup} in order to
* receive and process blocks and transactions.
*/
synchronized PeerEventListener getPeerEventListener() {
if (peerEventListener == null) {
// Instantiate here to avoid issues with wallets resurrected from serialized copies.
peerEventListener = new AbstractPeerEventListener() {
@Override
public void onTransaction(Peer peer, Transaction t) {
// Runs locked on a peer thread.
try {
receivePending(t);
} catch (VerificationException e) {
log.warn("Received broadcast transaction that does not validate: {}", t);
log.warn("VerificationException caught", e);
}
}
};
}
return peerEventListener;
}
public Sha256Hash getLastBlockSeenHash() {
return lastBlockSeenHash;