Add case for empty bloom filter (#561)

This commit is contained in:
Chris Stewart 2019-07-02 10:39:22 -05:00 committed by GitHub
parent 2e141b1d25
commit f7753fcaea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 21 deletions

View file

@ -277,4 +277,11 @@ class BloomFilterTest extends BitcoinSUnitTest {
}
}
it must "be able to instantiate a empty bloom filter" in {
val empty = BloomFilter.empty
empty.data must be(ByteVector.empty)
BloomFilter.fromBytes(empty.bytes) must be(empty)
}
}

View file

@ -316,6 +316,12 @@ object BloomFilter extends Factory[BloomFilter] {
/** Max hashFunc size as per [[https://bitcoin.org/en/developer-reference#filterload]] */
val maxHashFuncs = UInt32(50)
val empty: BloomFilter = BloomFilterImpl(CompactSizeUInt.zero,
ByteVector.empty,
UInt32.zero,
UInt32.zero,
BloomUpdateAll)
/**
* Creates a bloom filter based on the number of elements to be inserted into the filter
* and the desired false positive rate.
@ -348,28 +354,34 @@ object BloomFilter extends Factory[BloomFilter] {
falsePositiveRate: Double,
tweak: UInt32,
flags: BloomFlag): BloomFilter = {
import scala.math._
//m = number of bits in the array
//n = number of elements in the array
//from https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki#bloom-filter-format
val optimalFilterSize: Double = (-1 / pow(log(2), 2) * numElements * log(
falsePositiveRate)) / 8
logger.debug("optimalFilterSize " + optimalFilterSize)
//BIP37 places limitations on the filter size, namely it cannot be > 36,000 bytes
val actualFilterSize: Int =
max(1, min(optimalFilterSize, maxSize.toInt * 8)).toInt
logger.debug("actualFilterSize: " + actualFilterSize)
val optimalHashFuncs: Double = (actualFilterSize * 8 / numElements * log(2))
//BIP37 places a limit on the amount of hashFuncs we can use, which is 50
val actualHashFuncs: Int =
max(1, min(optimalHashFuncs, maxHashFuncs.toInt)).toInt
if (numElements == 0) {
BloomFilter.empty
} else {
import scala.math._
//m = number of bits in the array
//n = number of elements in the array
//from https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki#bloom-filter-format
val optimalFilterSize: Double = (-1 / pow(log(2), 2) * numElements * log(
falsePositiveRate)) / 8
logger.debug("optimalFilterSize " + optimalFilterSize)
//BIP37 places limitations on the filter size, namely it cannot be > 36,000 bytes
val actualFilterSize: Int =
max(1, min(optimalFilterSize, maxSize.toInt * 8)).toInt
logger.debug("actualFilterSize: " + actualFilterSize)
val optimalHashFuncs: Double = (actualFilterSize * 8 / numElements * log(
2))
//BIP37 places a limit on the amount of hashFuncs we can use, which is 50
val actualHashFuncs: Int =
max(1, min(optimalHashFuncs, maxHashFuncs.toInt)).toInt
val emptyByteArray = ByteVector(Array.fill(actualFilterSize)(0.toByte))
BloomFilter(filterSize = CompactSizeUInt(UInt64(actualFilterSize)),
data = emptyByteArray,
hashFuncs = UInt32(actualHashFuncs),
tweak = tweak,
flags = flags)
}
val emptyByteArray = ByteVector(Array.fill(actualFilterSize)(0.toByte))
BloomFilter(CompactSizeUInt(UInt64(actualFilterSize)),
emptyByteArray,
UInt32(actualHashFuncs),
tweak,
flags)
}
def apply(

View file

@ -40,6 +40,7 @@ object CompactSizeUInt extends Factory[CompactSizeUInt] {
private case class CompactSizeUIntImpl(num: UInt64, override val size: Long)
extends CompactSizeUInt
val zero: CompactSizeUInt = CompactSizeUInt(UInt64.zero)
override def fromBytes(bytes: ByteVector): CompactSizeUInt = {
parseCompactSizeUInt(bytes)
}