3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-12 02:05:53 +00:00

Automatically set up fast catchup time on a PeerGroup when wallets are added. Resolves issue 183.

This commit is contained in:
Mike Hearn 2012-05-25 16:05:02 +02:00
parent adb46c7dcb
commit 1f96f850e0
5 changed files with 74 additions and 4 deletions

View File

@ -91,9 +91,14 @@ public abstract class AbstractWalletEventListener implements WalletEventListener
onChange();
}
public void onKeyAdded(ECKey key) {
onChange();
}
/**
* Called by the other default method implementations when something (anything) changes in the wallet.
*/
public void onChange() {
}
}

View File

@ -339,18 +339,41 @@ public class PeerGroup {
}
/**
* Link the given wallet to this PeerGroup. This is used for two purposes:
* <p>Link the given wallet to this PeerGroup. This is used for three purposes:</p>
* <ol>
* <li>So the wallet receives broadcast transactions.</li>
* <li>Announcing pending transactions that didn't get into the chain yet to our peers.</li>
* <li>Set the fast catchup time using {@link PeerGroup#setFastCatchupTimeSecs(long)}, to optimize chain
* download.</li>
* </ol>
* <p>Note that this should be done before chain download commences because if you add a wallet with keys earlier
* than the current chain head, the relevant parts of the chain won't be redownloaded for you.</p>
*/
public synchronized void addWallet(Wallet wallet) {
if (wallet == null)
throw new IllegalArgumentException("wallet is null");
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
// if a key is added. Of course, by then we may have downloaded the chain already. Ideally adding keys would
// automatically rewind the block chain and redownload the blocks to find transactions relevant to those keys,
// all transparently and in the background. But we are a long way from that yet.
wallet.addEventListener(new AbstractWalletEventListener() {
@Override
public void onKeyAdded(ECKey key) {
recalculateFastCatchupTime();
}
});
recalculateFastCatchupTime();
}
private synchronized void recalculateFastCatchupTime() {
long earliestKeyTime = Long.MAX_VALUE;
for (Wallet w : wallets) {
earliestKeyTime = Math.min(earliestKeyTime, w.getEarliestKeyCreationTime());
}
setFastCatchupTimeSecs(earliestKeyTime);
}
/**
@ -738,6 +761,16 @@ public class PeerGroup {
}
}
/**
* Returns the current fast catchup time. The contents of blocks before this time won't be downloaded as they
* cannot contain any interesting transactions. If you use {@link PeerGroup#addWallet(Wallet)} this just returns
* the min of the wallets earliest key times.
* @return a time in seconds since the epoch
*/
public synchronized long getFastCatchupTimeSecs() {
return fastCatchupTimeSecs;
}
protected synchronized void handlePeerDeath(final Peer peer) {
if (!isRunning()) {
log.info("Peer death while shutting down");

View File

@ -1194,9 +1194,15 @@ public class Wallet implements Serializable {
/**
* Adds the given ECKey to the wallet. There is currently no way to delete keys (that would result in coin loss).
*/
public synchronized void addKey(ECKey key) {
public synchronized void addKey(final ECKey key) {
checkArgument(!keychain.contains(key), "Key already present");
keychain.add(key);
EventListenerInvoker.invoke(eventListeners, new EventListenerInvoker<WalletEventListener>() {
@Override
public void invoke(WalletEventListener listener) {
listener.onKeyAdded(key);
}
});
}
/**

View File

@ -99,4 +99,10 @@ public interface WalletEventListener {
* @param tx
*/
void onTransactionConfidenceChanged(Wallet wallet, Transaction tx);
/**
* Called by the {@link Wallet#addKey(ECKey)} method on whatever the calling thread was.
* @param key
*/
void onKeyAdded(ECKey key);
}

View File

@ -24,6 +24,7 @@ import org.junit.Test;
import java.io.IOException;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
@ -306,6 +307,25 @@ public class PeerGroupTest extends TestWithNetworkConnections {
assertTrue(n3.outbound() instanceof InventoryMessage);
peerGroup.stop();
}
@Test
public void testWalletCatchupTime() throws Exception {
// Check the fast catchup time was initialized to something around the current runtime. The wallet was
// already added to the peer in setup.
long time = new Date().getTime() / 1000;
assertTrue(peerGroup.getFastCatchupTimeSecs() > time - 10000);
Wallet w2 = new Wallet(params);
ECKey key1 = new ECKey();
key1.setCreationTimeSeconds(time - 86400); // One day ago.
w2.addKey(key1);
peerGroup.addWallet(w2);
assertEquals(peerGroup.getFastCatchupTimeSecs(), time - 86400);
// Adding a key to the wallet should update the fast catchup time.
ECKey key2 = new ECKey();
key2.setCreationTimeSeconds(time - 100000);
w2.addKey(key2);
assertEquals(peerGroup.getFastCatchupTimeSecs(), time - 100000);
}
private void disconnectAndWait(MockNetworkConnection conn) throws IOException, InterruptedException {
conn.disconnect();