Skip to content

Commit 829c441

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#23115: bloom: use Span instead of std::vector for insert and contains
a11da75 bloom: cleanup includes (fanquake) f1ed1d3 bloom: use constexpr where appropriate (fanquake) 2ba4ddf bloom: use Span instead of std::vector for `insert` and `contains` (William Casarin) Pull request description: This is #18985 rebased, with the most recent comments addressed. > We can avoid many unnecessary std::vector allocations by changing CBloomFilter to take Spans instead of std::vector's for the `insert` and `contains` operations. > CBloomFilter currently converts types such as CDataStream and uint256 to std::vector on `insert` and `contains`. This is unnecessary because CDataStreams and uint256 are already std::vectors internally. We just need a way to point to the right data within those types. Span gives us this ability. ACKs for top commit: sipa: Code review ACK a11da75 laanwj: Code review ACK a11da75 Tree-SHA512: ee9ba02c9588daa1ff51782d1953fd060839dd15aa85861b2633b6ff2398320188ddd00f01d0c99442224485364ede9f8322366de4239fc7831ebfa06bd34659
2 parents d648bbb + a11da75 commit 829c441

File tree

4 files changed

+28
-54
lines changed

4 files changed

+28
-54
lines changed

src/bloom.cpp

Lines changed: 18 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,22 @@
44

55
#include <bloom.h>
66

7-
#include <primitives/transaction.h>
87
#include <hash.h>
8+
#include <primitives/transaction.h>
9+
#include <random.h>
910
#include <script/script.h>
1011
#include <script/standard.h>
11-
#include <random.h>
12+
#include <span.h>
1213
#include <streams.h>
1314

14-
#include <math.h>
15-
#include <stdlib.h>
16-
1715
#include <algorithm>
16+
#include <cmath>
17+
#include <cstdlib>
18+
#include <limits>
19+
#include <vector>
1820

19-
#define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455
20-
#define LN2 0.6931471805599453094172321214581765680755001343602552
21+
static constexpr double LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455;
22+
static constexpr double LN2 = 0.6931471805599453094172321214581765680755001343602552;
2123

2224
CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweakIn, unsigned char nFlagsIn) :
2325
/**
@@ -37,13 +39,13 @@ CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, c
3739
{
3840
}
3941

40-
inline unsigned int CBloomFilter::Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const
42+
inline unsigned int CBloomFilter::Hash(unsigned int nHashNum, Span<const unsigned char> vDataToHash) const
4143
{
4244
// 0xFBA4C795 chosen as it guarantees a reasonable bit difference between nHashNum values.
4345
return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash) % (vData.size() * 8);
4446
}
4547

46-
void CBloomFilter::insert(const std::vector<unsigned char>& vKey)
48+
void CBloomFilter::insert(Span<const unsigned char> vKey)
4749
{
4850
if (vData.empty()) // Avoid divide-by-zero (CVE-2013-5700)
4951
return;
@@ -59,17 +61,10 @@ void CBloomFilter::insert(const COutPoint& outpoint)
5961
{
6062
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
6163
stream << outpoint;
62-
std::vector<unsigned char> data(stream.begin(), stream.end());
63-
insert(data);
64+
insert(stream);
6465
}
6566

66-
void CBloomFilter::insert(const uint256& hash)
67-
{
68-
std::vector<unsigned char> data(hash.begin(), hash.end());
69-
insert(data);
70-
}
71-
72-
bool CBloomFilter::contains(const std::vector<unsigned char>& vKey) const
67+
bool CBloomFilter::contains(Span<const unsigned char> vKey) const
7368
{
7469
if (vData.empty()) // Avoid divide-by-zero (CVE-2013-5700)
7570
return true;
@@ -87,14 +82,7 @@ bool CBloomFilter::contains(const COutPoint& outpoint) const
8782
{
8883
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
8984
stream << outpoint;
90-
std::vector<unsigned char> data(stream.begin(), stream.end());
91-
return contains(data);
92-
}
93-
94-
bool CBloomFilter::contains(const uint256& hash) const
95-
{
96-
std::vector<unsigned char> data(hash.begin(), hash.end());
97-
return contains(data);
85+
return contains(MakeUCharSpan(stream));
9886
}
9987

10088
bool CBloomFilter::IsWithinSizeConstraints() const
@@ -198,7 +186,8 @@ CRollingBloomFilter::CRollingBloomFilter(const unsigned int nElements, const dou
198186
}
199187

200188
/* Similar to CBloomFilter::Hash */
201-
static inline uint32_t RollingBloomHash(unsigned int nHashNum, uint32_t nTweak, const std::vector<unsigned char>& vDataToHash) {
189+
static inline uint32_t RollingBloomHash(unsigned int nHashNum, uint32_t nTweak, Span<const unsigned char> vDataToHash)
190+
{
202191
return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash);
203192
}
204193

@@ -210,7 +199,7 @@ static inline uint32_t FastMod(uint32_t x, size_t n) {
210199
return ((uint64_t)x * (uint64_t)n) >> 32;
211200
}
212201

213-
void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
202+
void CRollingBloomFilter::insert(Span<const unsigned char> vKey)
214203
{
215204
if (nEntriesThisGeneration == nEntriesPerGeneration) {
216205
nEntriesThisGeneration = 0;
@@ -241,13 +230,7 @@ void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
241230
}
242231
}
243232

244-
void CRollingBloomFilter::insert(const uint256& hash)
245-
{
246-
std::vector<unsigned char> vData(hash.begin(), hash.end());
247-
insert(vData);
248-
}
249-
250-
bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
233+
bool CRollingBloomFilter::contains(Span<const unsigned char> vKey) const
251234
{
252235
for (int n = 0; n < nHashFuncs; n++) {
253236
uint32_t h = RollingBloomHash(n, nTweak, vKey);
@@ -261,12 +244,6 @@ bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
261244
return true;
262245
}
263246

264-
bool CRollingBloomFilter::contains(const uint256& hash) const
265-
{
266-
std::vector<unsigned char> vData(hash.begin(), hash.end());
267-
return contains(vData);
268-
}
269-
270247
void CRollingBloomFilter::reset()
271248
{
272249
nTweak = GetRand(std::numeric_limits<unsigned int>::max());

src/bloom.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
#define BITCOIN_BLOOM_H
77

88
#include <serialize.h>
9+
#include <span.h>
910

1011
#include <vector>
1112

1213
class COutPoint;
1314
class CTransaction;
14-
class uint256;
1515

1616
//! 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001%
17-
static const unsigned int MAX_BLOOM_FILTER_SIZE = 36000; // bytes
18-
static const unsigned int MAX_HASH_FUNCS = 50;
17+
static constexpr unsigned int MAX_BLOOM_FILTER_SIZE = 36000; // bytes
18+
static constexpr unsigned int MAX_HASH_FUNCS = 50;
1919

2020
/**
2121
* First two bits of nFlags control how much IsRelevantAndUpdate actually updates
@@ -49,7 +49,7 @@ class CBloomFilter
4949
unsigned int nTweak;
5050
unsigned char nFlags;
5151

52-
unsigned int Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const;
52+
unsigned int Hash(unsigned int nHashNum, Span<const unsigned char> vDataToHash) const;
5353

5454
public:
5555
/**
@@ -66,13 +66,11 @@ class CBloomFilter
6666

6767
SERIALIZE_METHODS(CBloomFilter, obj) { READWRITE(obj.vData, obj.nHashFuncs, obj.nTweak, obj.nFlags); }
6868

69-
void insert(const std::vector<unsigned char>& vKey);
69+
void insert(Span<const unsigned char> vKey);
7070
void insert(const COutPoint& outpoint);
71-
void insert(const uint256& hash);
7271

73-
bool contains(const std::vector<unsigned char>& vKey) const;
72+
bool contains(Span<const unsigned char> vKey) const;
7473
bool contains(const COutPoint& outpoint) const;
75-
bool contains(const uint256& hash) const;
7674

7775
//! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS
7876
//! (catch a filter which was just deserialized which was too big)
@@ -112,10 +110,8 @@ class CRollingBloomFilter
112110
public:
113111
CRollingBloomFilter(const unsigned int nElements, const double nFPRate);
114112

115-
void insert(const std::vector<unsigned char>& vKey);
116-
void insert(const uint256& hash);
117-
bool contains(const std::vector<unsigned char>& vKey) const;
118-
bool contains(const uint256& hash) const;
113+
void insert(Span<const unsigned char> vKey);
114+
bool contains(Span<const unsigned char> vKey) const;
119115

120116
void reset();
121117

src/hash.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <hash.h>
6+
#include <span.h>
67
#include <crypto/common.h>
78
#include <crypto/hmac_sha512.h>
89

src/test/bloom_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
8383
CBloomFilter filter(2, 0.001, 0, BLOOM_UPDATE_ALL);
8484
filter.insert(vchPubKey);
8585
uint160 hash = pubkey.GetID();
86-
filter.insert(std::vector<unsigned char>(hash.begin(), hash.end()));
86+
filter.insert(hash);
8787

8888
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
8989
stream << filter;

0 commit comments

Comments
 (0)