Skip to content

Commit d2d7ee0

Browse files
petertoddsipa
authored andcommitted
Make CRollingBloomFilter set nTweak for you
While CBloomFilter is usually used with an explicitly set nTweak, CRollingBloomFilter is only used internally. Requiring every caller to set nTweak is error-prone and redundant; better to have the class handle that for you with a high-quality randomness source. Additionally when clearing the filter it makes sense to change nTweak as well to recover from a bad setting, e.g. due to insufficient randomness at initialization, so the clear() method is replaced by a reset() method that sets a new, random, nTweak value.
1 parent a3d65fe commit d2d7ee0

File tree

5 files changed

+29
-12
lines changed

5 files changed

+29
-12
lines changed

src/bloom.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "hash.h"
99
#include "script/script.h"
1010
#include "script/standard.h"
11+
#include "random.h"
1112
#include "streams.h"
1213

1314
#include <math.h>
@@ -121,6 +122,12 @@ void CBloomFilter::clear()
121122
isEmpty = true;
122123
}
123124

125+
void CBloomFilter::reset(unsigned int nNewTweak)
126+
{
127+
clear();
128+
nTweak = nNewTweak;
129+
}
130+
124131
bool CBloomFilter::IsWithinSizeConstraints() const
125132
{
126133
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
@@ -217,7 +224,8 @@ CRollingBloomFilter::CRollingBloomFilter(unsigned int nElements, double fpRate,
217224
// inserted, so at least one always contains the last nElements
218225
// inserted.
219226
nBloomSize = nElements * 2;
220-
nInsertions = 0;
227+
228+
reset(nTweak);
221229
}
222230

223231
void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
@@ -254,9 +262,12 @@ bool CRollingBloomFilter::contains(const uint256& hash) const
254262
return contains(data);
255263
}
256264

257-
void CRollingBloomFilter::clear()
265+
void CRollingBloomFilter::reset(unsigned int nNewTweak)
258266
{
259-
b1.clear();
260-
b2.clear();
267+
if (!nNewTweak)
268+
nNewTweak = GetRand(std::numeric_limits<unsigned int>::max());
269+
270+
b1.reset(nNewTweak);
271+
b2.reset(nNewTweak);
261272
nInsertions = 0;
262273
}

src/bloom.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class CBloomFilter
8989
bool contains(const uint256& hash) const;
9090

9191
void clear();
92+
void reset(unsigned int nNewTweak);
9293

9394
//! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS
9495
//! (catch a filter which was just deserialized which was too big)
@@ -103,22 +104,27 @@ class CBloomFilter
103104

104105
/**
105106
* RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
106-
* Construct it with the number of items to keep track of, and a false-positive rate.
107+
* Construct it with the number of items to keep track of, and a false-positive
108+
* rate. Unlike CBloomFilter, by default nTweak is set to a cryptographically
109+
* secure random value for you. Similarly rather than clear() the method
110+
* reset() is provided, which also changes nTweak to decrease the impact of
111+
* false-positives.
107112
*
108113
* contains(item) will always return true if item was one of the last N things
109114
* insert()'ed ... but may also return true for items that were not inserted.
110115
*/
111116
class CRollingBloomFilter
112117
{
113118
public:
114-
CRollingBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak);
119+
CRollingBloomFilter(unsigned int nElements, double nFPRate,
120+
unsigned int nTweak = 0);
115121

116122
void insert(const std::vector<unsigned char>& vKey);
117123
void insert(const uint256& hash);
118124
bool contains(const std::vector<unsigned char>& vKey) const;
119125
bool contains(const uint256& hash) const;
120126

121-
void clear();
127+
void reset(unsigned int nNewTweak = 0);
122128

123129
private:
124130
unsigned int nBloomSize;

src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4812,7 +4812,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
48124812
{
48134813
// Periodically clear addrKnown to allow refresh broadcasts
48144814
if (nLastRebroadcast)
4815-
pnode->addrKnown.clear();
4815+
pnode->addrKnown.reset();
48164816

48174817
// Rebroadcast our address
48184818
AdvertizeLocal(pnode);

src/net.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2060,7 +2060,7 @@ unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
20602060

20612061
CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) :
20622062
ssSend(SER_NETWORK, INIT_PROTO_VERSION),
2063-
addrKnown(5000, 0.001, insecure_rand()),
2063+
addrKnown(5000, 0.001),
20642064
setInventoryKnown(SendBufferSize() / 1000)
20652065
{
20662066
nServices = 0;

src/test/bloom_tests.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ static std::vector<unsigned char> RandomData()
469469
BOOST_AUTO_TEST_CASE(rolling_bloom)
470470
{
471471
// last-100-entry, 1% false positive:
472-
CRollingBloomFilter rb1(100, 0.01, 0);
472+
CRollingBloomFilter rb1(100, 0.01, 1);
473473

474474
// Overfill:
475475
static const int DATASIZE=399;
@@ -500,7 +500,7 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
500500
BOOST_CHECK(nHits < 175);
501501

502502
BOOST_CHECK(rb1.contains(data[DATASIZE-1]));
503-
rb1.clear();
503+
rb1.reset(1);
504504
BOOST_CHECK(!rb1.contains(data[DATASIZE-1]));
505505

506506
// Now roll through data, make sure last 100 entries
@@ -527,7 +527,7 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
527527
BOOST_CHECK(nHits < 100);
528528

529529
// last-1000-entry, 0.01% false positive:
530-
CRollingBloomFilter rb2(1000, 0.001, 0);
530+
CRollingBloomFilter rb2(1000, 0.001, 1);
531531
for (int i = 0; i < DATASIZE; i++) {
532532
rb2.insert(data[i]);
533533
}

0 commit comments

Comments
 (0)