3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-14 19:25:51 +00:00

Add switch to disable download of pending transaction dependencies. This becomes necessary because the current recursive download strategy is often triggering a stack overflow on Android devices.

This commit is contained in:
Andreas Schildbach 2014-04-18 12:48:33 +02:00 committed by Mike Hearn
parent b0fa5435a2
commit 53147fab16
2 changed files with 58 additions and 20 deletions

View File

@ -81,6 +81,8 @@ public class Peer extends PeerSocketHandler {
// The version data to announce to the other side of the connections we make: useful for setting our "user agent"
// equivalent and other things.
private final VersionMessage versionMessage;
// Switch for enabling download of pending transaction dependencies.
private final boolean downloadTxDependencies;
// How many block messages the peer has announced to us. Peers only announce blocks that attach to their best chain
// so we can use this to calculate the height of the peers chain, by adding it to the initial height in the version
// message. This method can go wrong if the peer re-orgs onto a shorter (but harder) chain, however, this is rare.
@ -173,10 +175,30 @@ public class Peer extends PeerSocketHandler {
* used to keep track of which peers relayed transactions and offer more descriptive logging.</p>
*/
public Peer(NetworkParameters params, VersionMessage ver, PeerAddress remoteAddress,
@Nullable AbstractBlockChain chain, @Nullable MemoryPool mempool) {
@Nullable AbstractBlockChain chain, @Nullable MemoryPool mempool) {
this(params, ver, remoteAddress, chain, mempool, true);
}
/**
* <p>Construct a peer that reads/writes from the given block chain and memory pool. Transactions stored in a memory
* pool will have their confidence levels updated when a peer announces it, to reflect the greater likelyhood that
* the transaction is valid.</p>
*
* <p>Note that this does <b>NOT</b> make a connection to the given remoteAddress, it only creates a handler for a
* connection. If you want to create a one-off connection, create a Peer and pass it to
* {@link com.google.bitcoin.net.NioClientManager#openConnection(java.net.SocketAddress, com.google.bitcoin.net.StreamParser)}
* or
* {@link com.google.bitcoin.net.NioClient#NioClient(java.net.SocketAddress, com.google.bitcoin.net.StreamParser, int)}.</p>
*
* <p>The remoteAddress provided should match the remote address of the peer which is being connected to, and is
* used to keep track of which peers relayed transactions and offer more descriptive logging.</p>
*/
public Peer(NetworkParameters params, VersionMessage ver, PeerAddress remoteAddress,
@Nullable AbstractBlockChain chain, @Nullable MemoryPool mempool, boolean downloadTxDependencies) {
super(params, remoteAddress);
this.params = Preconditions.checkNotNull(params);
this.versionMessage = Preconditions.checkNotNull(ver);
this.downloadTxDependencies = downloadTxDependencies;
this.blockChain = chain; // Allowed to be null.
this.vDownloadData = chain != null;
this.getDataFutures = new CopyOnWriteArrayList<GetDataRequest>();
@ -577,26 +599,27 @@ public class Peer extends PeerSocketHandler {
// the chain, in case the sender goes away and the network starts to forget.
// TODO: Not all the above things are implemented.
Futures.addCallback(downloadDependencies(fTx), new FutureCallback<List<Transaction>>() {
public void onSuccess(List<Transaction> dependencies) {
try {
log.info("{}: Dependency download complete!", getAddress());
wallet.receivePending(fTx, dependencies);
} catch (VerificationException e) {
log.error("{}: Wallet failed to process pending transaction {}",
getAddress(), fTx.getHashAsString());
log.error("Error was: ", e);
if (downloadTxDependencies) {
Futures.addCallback(downloadDependencies(fTx), new FutureCallback<List<Transaction>>() {
public void onSuccess(List<Transaction> dependencies) {
try {
log.info("{}: Dependency download complete!", getAddress());
wallet.receivePending(fTx, dependencies);
} catch (VerificationException e) {
log.error("{}: Wallet failed to process pending transaction {}", getAddress(),
fTx.getHashAsString());
log.error("Error was: ", e);
// Not much more we can do at this point.
}
}
public void onFailure(Throwable throwable) {
log.error("Could not download dependencies of tx {}", fTx.getHashAsString());
log.error("Error was: ", throwable);
// Not much more we can do at this point.
}
}
public void onFailure(Throwable throwable) {
log.error("Could not download dependencies of tx {}", fTx.getHashAsString());
log.error("Error was: ", throwable);
// Not much more we can do at this point.
}
});
});
}
}
} catch (VerificationException e) {
log.error("Wallet failed to verify tx", e);

View File

@ -94,6 +94,8 @@ public class PeerGroup extends AbstractExecutionThreadService implements Transac
private final CopyOnWriteArraySet<PeerDiscovery> peerDiscoverers;
// The version message to use for new connections.
@GuardedBy("lock") private VersionMessage versionMessage;
// Switch for enabling download of pending transaction dependencies.
@GuardedBy("lock") private boolean downloadTxDependencies;
// 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 final MemoryPool memoryPool;
@ -290,6 +292,7 @@ public class PeerGroup extends AbstractExecutionThreadService implements Transac
int height = chain == null ? 0 : chain.getBestChainHeight();
// We never request that the remote node wait for a bloom filter yet, as we have no wallets
this.versionMessage = new VersionMessage(params, height, true);
this.downloadTxDependencies = true;
memoryPool = new MemoryPool();
@ -335,6 +338,18 @@ public class PeerGroup extends AbstractExecutionThreadService implements Transac
channels.closeConnections(-adjustment);
}
/**
* Switch for enabling download of pending transaction dependencies. A change of value only takes effect for newly
* connected peers.
*/
public void setDownloadTxDependencies(boolean downloadTxDependencies) {
lock.lock();
try {
this.downloadTxDependencies = downloadTxDependencies;
} finally {
lock.unlock();
}
}
private Runnable triggerConnectionsJob = new Runnable() {
@Override
@ -895,7 +910,7 @@ public class PeerGroup extends AbstractExecutionThreadService implements Transac
ver.bestHeight = chain == null ? 0 : chain.getBestChainHeight();
ver.time = Utils.currentTimeSeconds();
Peer peer = new Peer(params, ver, address, chain, memoryPool);
Peer peer = new Peer(params, ver, address, chain, memoryPool, downloadTxDependencies);
peer.addEventListener(startupListener, Threading.SAME_THREAD);
peer.setMinProtocolVersion(vMinRequiredProtocolVersion);
pendingPeers.add(peer);