From 1ea4cb457d284285a30d31291a3b229c2e533081 Mon Sep 17 00:00:00 2001
From: Matt Corallo
Constructs a new Bloom Filter which will provide approximately the given false positive * rate when the given number of elements have been inserted.
@@ -82,8 +99,10 @@ public class BloomFilter extends Message { * *randomNonce is a tweak for the hash function used to prevent some theoretical DoS attacks. * It should be a random value, however secureness of the random value is of no great consequence.
+ * + *updateFlag is used to control filter behavior
*/ - public BloomFilter(int elements, double falsePositiveRate, long randomNonce) { + public BloomFilter(int elements, double falsePositiveRate, long randomNonce, bloomUpdate updateFlag) { // The following formulas were stolen from Wikipedia's page on Bloom Filters (with the addition of min(..., MAX_...)) // Size required for a given number of elements and false-positive rate int size = Math.min((int)(-1 / (Math.pow(Math.log(2), 2)) * elements * Math.log(falsePositiveRate)), @@ -92,6 +111,7 @@ public class BloomFilter extends Message { // Optimal number of hash functions for a given filter size and element count. hashFuncs = Math.min((int)(data.length * 8 / elements * Math.log(2)), MAX_HASH_FUNCS); this.nTweak = randomNonce; + this.nFlags = (byte)(0xff & updateFlag.ordinal()); } /** @@ -117,6 +137,8 @@ public class BloomFilter extends Message { throw new ProtocolException("Bloom filter hash function count out of range"); nTweak = readUint32(); + + nFlags = readBytes(1)[0]; length = cursor - offset; } @@ -129,6 +151,7 @@ public class BloomFilter extends Message { stream.write(data); Utils.uint32ToByteStreamLE(hashFuncs, stream); Utils.uint32ToByteStreamLE(nTweak, stream); + stream.write(nFlags); } @Override diff --git a/core/src/test/java/com/google/bitcoin/core/BloomFilterTest.java b/core/src/test/java/com/google/bitcoin/core/BloomFilterTest.java index f946bf29..a2dedcfa 100644 --- a/core/src/test/java/com/google/bitcoin/core/BloomFilterTest.java +++ b/core/src/test/java/com/google/bitcoin/core/BloomFilterTest.java @@ -9,7 +9,7 @@ import org.spongycastle.util.encoders.Hex; public class BloomFilterTest { @Test public void insertSerializeTest() { - BloomFilter filter = new BloomFilter(3, 0.01, 0); + BloomFilter filter = new BloomFilter(3, 0.01, 0, BloomFilter.bloomUpdate.UPDATE_ALL); filter.insert(Hex.decode("99108ad8ed9bb6274d3980bab5a85c048f0950c8")); assertTrue (filter.contains(Hex.decode("99108ad8ed9bb6274d3980bab5a85c048f0950c8"))); @@ -23,7 +23,7 @@ public class BloomFilterTest { assertTrue(filter.contains(Hex.decode("b9300670b4c5366e95b2699e8b18bc75e5f729c5"))); // Value generated by the reference client - assertTrue(Arrays.equals(Hex.decode("03614e9b0500000000000000"), filter.bitcoinSerialize())); + assertTrue(Arrays.equals(Hex.decode("03614e9b050000000000000001"), filter.bitcoinSerialize())); } @Test @@ -42,7 +42,7 @@ public class BloomFilterTest { assertTrue(filter.contains(Hex.decode("b9300670b4c5366e95b2699e8b18bc75e5f729c5"))); // Value generated by the reference client - assertTrue(Arrays.equals(Hex.decode("03ce42990500000001000080"), filter.bitcoinSerialize())); + assertTrue(Arrays.equals(Hex.decode("03ce4299050000000100008002"), filter.bitcoinSerialize())); } @Test @@ -70,6 +70,6 @@ public class BloomFilterTest { BloomFilter filter = wallet.getBloomFilter(wallet.getBloomFilterElementCount(), 0.001, 0); // Value generated by the reference client - assertTrue(Arrays.equals(Hex.decode("082ae5edc8e51d4a030800000000000000"), filter.bitcoinSerialize())); + assertTrue(Arrays.equals(Hex.decode("082ae5edc8e51d4a03080000000000000002"), filter.bitcoinSerialize())); } } diff --git a/core/src/test/java/com/google/bitcoin/core/FilteredBlockAndPartialMerkelTreeTests.java b/core/src/test/java/com/google/bitcoin/core/FilteredBlockAndPartialMerkelTreeTests.java index 1fecb76e..3e4d8820 100644 --- a/core/src/test/java/com/google/bitcoin/core/FilteredBlockAndPartialMerkelTreeTests.java +++ b/core/src/test/java/com/google/bitcoin/core/FilteredBlockAndPartialMerkelTreeTests.java @@ -87,7 +87,7 @@ public class FilteredBlockAndPartialMerkelTreeTests extends TestWithPeerGroup { BloomFilter filter = wallet.getBloomFilter(wallet.getKeychainSize()*2, 0.001, 0xDEADBEEF); // Compare the serialized bloom filter to a known-good value - assertTrue(Arrays.equals(filter.bitcoinSerialize(), Hex.decode("0e1b091ca195e45a9164889b6bc46a09000000efbeadde"))); + assertTrue(Arrays.equals(filter.bitcoinSerialize(), Hex.decode("0e1b091ca195e45a9164889b6bc46a09000000efbeadde02"))); // Cheat and place the previous block (block 100000) at the head of the block store without supporting blocks blockStore = new MemoryBlockStore(NetworkParameters.unitTests());