Refactor the code that sets filters a bit, and send a mempool query after wallet contents change in case of a key import.

This commit is contained in:
Mike Hearn 2013-02-19 16:10:21 +01:00
parent 3c606516be
commit 5a3515bef0
3 changed files with 39 additions and 15 deletions

View file

@ -1241,4 +1241,35 @@ public class Peer {
return null; return null;
} }
} }
/**
* <p>Sets a Bloom filter on this connection. This will cause the given {@link BloomFilter} object to be sent to the
* remote peer and if either a memory pool has been set using {@link Peer#setMemoryPool(MemoryPool)} or the
* downloadData property is true, a {@link MemoryPoolMessage} is sent as well to trigger downloading of any
* pending transactions that may be relevant.</p>
*
* <p>The Peer does not keep a reference to the BloomFilter. Also, it will not automatically request filters
* from any wallets added using {@link Peer#addWallet(Wallet)}. This is to allow callers to avoid redundantly
* recalculating the same filter repeatedly when using multiple peers together.</p>
*
* <p>Therefore, you should not use this method if your app uses a {@link PeerGroup}. It is called for you.</p>
*
* <p>If the remote peer doesn't support Bloom filtering, then this call is ignored.</p>
*/
public void setBloomFilter(BloomFilter filter) throws IOException {
if (!getPeerVersionMessage().isBloomFilteringSupported())
return;
boolean shouldQueryMemPool;
synchronized (this) {
shouldQueryMemPool = memoryPool != null || downloadData.get();
}
log.info("{}: Sending Bloom filter{}", this, shouldQueryMemPool ? " and querying mempool" : "");
ChannelFuture future = sendMessage(filter);
if (shouldQueryMemPool)
future.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
sendMessage(new MemoryPoolMessage());
}
});
}
} }

View file

@ -580,16 +580,12 @@ public class PeerGroup extends AbstractIdleService {
for (Wallet w : wallets) for (Wallet w : wallets)
filter.merge(w.getBloomFilter(lastBloomFilterElementCount, bloomFilterFPRate, bloomFilterTweak)); filter.merge(w.getBloomFilter(lastBloomFilterElementCount, bloomFilterFPRate, bloomFilterTweak));
bloomFilter = filter; bloomFilter = filter;
for (Peer peer : peers) { for (Peer peer : peers)
if (peer.getPeerVersionMessage().isBloomFilteringSupported()) { try {
try { peer.setBloomFilter(filter);
log.info("{}: Sending peer an updated Bloom Filter.", peer); } catch (IOException e) {
peer.sendMessage(filter); throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
}
} }
// Do this last so that bloomFilter is already set when it gets called. // Do this last so that bloomFilter is already set when it gets called.
setFastCatchupTimeSecs(earliestKeyTime); setFastCatchupTimeSecs(earliestKeyTime);
@ -719,11 +715,7 @@ public class PeerGroup extends AbstractIdleService {
// aren't relevant to our wallet. We may still receive some false positives, which is // aren't relevant to our wallet. We may still receive some false positives, which is
// OK because it helps improve wallet privacy. Old nodes will just ignore the message. // OK because it helps improve wallet privacy. Old nodes will just ignore the message.
try { try {
if (bloomFilter != null && peer.getPeerVersionMessage().isBloomFilteringSupported()) { if (bloomFilter != null) peer.setBloomFilter(bloomFilter);
log.info("{}: Sending Bloom filter and querying memory pool", peer);
peer.sendMessage(bloomFilter);
peer.sendMessage(new MemoryPoolMessage());
}
} catch (IOException e) { } // That was quick...already disconnected } catch (IOException e) { } // That was quick...already disconnected
// Link the peer to the memory pool so broadcast transactions have their confidence levels updated. // Link the peer to the memory pool so broadcast transactions have their confidence levels updated.
peer.setMemoryPool(memoryPool); peer.setMemoryPool(memoryPool);

View file

@ -311,12 +311,13 @@ public class PeerGroupTest extends TestWithPeerGroup {
peerGroup.addWallet(wallet); peerGroup.addWallet(wallet);
// Transaction announced to the first peer. // Transaction announced to the first peer.
InventoryMessage inv1 = (InventoryMessage) outbound(p1); InventoryMessage inv1 = (InventoryMessage) outbound(p1);
assertTrue(outbound(p1) instanceof BloomFilter); // Filter is recalculated.
assertTrue(outbound(p1) instanceof MemoryPoolMessage);
assertEquals(t3.getHash(), inv1.getItems().get(0).hash); assertEquals(t3.getHash(), inv1.getItems().get(0).hash);
// Peer asks for the transaction, and get it. // Peer asks for the transaction, and get it.
GetDataMessage getdata = new GetDataMessage(params); GetDataMessage getdata = new GetDataMessage(params);
getdata.addItem(inv1.getItems().get(0)); getdata.addItem(inv1.getItems().get(0));
inbound(p1, getdata); inbound(p1, getdata);
assertTrue(outbound(p1) instanceof BloomFilter); // Filter is recalculated.
Transaction t4 = (Transaction) outbound(p1); Transaction t4 = (Transaction) outbound(p1);
assertEquals(t3, t4); assertEquals(t3, t4);