]>
Commit | Line | Data |
---|---|---|
f914f1a7 | 1 | // Copyright (c) 2012-2014 The Bitcoin Core developers |
fa94b9d5 | 2 | // Distributed under the MIT software license, see the accompanying |
bd21612c | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
51ed9ec9 | 4 | |
bd21612c MC |
5 | #ifndef BITCOIN_BLOOM_H |
6 | #define BITCOIN_BLOOM_H | |
7 | ||
bd21612c MC |
8 | #include "serialize.h" |
9 | ||
51ed9ec9 BD |
10 | #include <vector> |
11 | ||
bd21612c MC |
12 | class COutPoint; |
13 | class CTransaction; | |
51ed9ec9 | 14 | class uint256; |
bd21612c | 15 | |
fa94b9d5 | 16 | //! 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001% |
bd21612c MC |
17 | static const unsigned int MAX_BLOOM_FILTER_SIZE = 36000; // bytes |
18 | static const unsigned int MAX_HASH_FUNCS = 50; | |
19 | ||
fa94b9d5 MF |
20 | /** |
21 | * First two bits of nFlags control how much IsRelevantAndUpdate actually updates | |
22 | * The remaining bits are reserved | |
23 | */ | |
e1a4f377 MC |
24 | enum bloomflags |
25 | { | |
26 | BLOOM_UPDATE_NONE = 0, | |
27 | BLOOM_UPDATE_ALL = 1, | |
28 | // Only adds outpoints to the filter if the output is a pay-to-pubkey/pay-to-multisig script | |
29 | BLOOM_UPDATE_P2PUBKEY_ONLY = 2, | |
30 | BLOOM_UPDATE_MASK = 3, | |
31 | }; | |
bd21612c MC |
32 | |
33 | /** | |
34 | * BloomFilter is a probabilistic filter which SPV clients provide | |
7e6d23b1 | 35 | * so that we can filter the transactions we send them. |
bd21612c MC |
36 | * |
37 | * This allows for significantly more efficient transaction and block downloads. | |
38 | * | |
7e6d23b1 CD |
39 | * Because bloom filters are probabilistic, a SPV node can increase the false- |
40 | * positive rate, making us send it transactions which aren't actually its, | |
bd21612c | 41 | * allowing clients to trade more bandwidth for more privacy by obfuscating which |
7e6d23b1 | 42 | * keys are controlled by them. |
bd21612c MC |
43 | */ |
44 | class CBloomFilter | |
45 | { | |
46 | private: | |
47 | std::vector<unsigned char> vData; | |
37c6389c GM |
48 | bool isFull; |
49 | bool isEmpty; | |
bd21612c | 50 | unsigned int nHashFuncs; |
b1f99bed | 51 | unsigned int nTweak; |
e1a4f377 | 52 | unsigned char nFlags; |
bd21612c MC |
53 | |
54 | unsigned int Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const; | |
55 | ||
69a5f8be GA |
56 | // Private constructor for CRollingBloomFilter, no restrictions on size |
57 | CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak); | |
58 | friend class CRollingBloomFilter; | |
59 | ||
bd21612c | 60 | public: |
fa94b9d5 MF |
61 | /** |
62 | * Creates a new bloom filter which will provide the given fp rate when filled with the given number of elements | |
63 | * Note that if the given parameters will result in a filter outside the bounds of the protocol limits, | |
64 | * the filter created will be as close to the given parameters as possible within the protocol limits. | |
65 | * This will apply if nFPRate is very low or nElements is unreasonably high. | |
66 | * nTweak is a constant which is added to the seed value passed to the hash function | |
67 | * It should generally always be a random value (and is largely only exposed for unit testing) | |
68 | * nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK) | |
69 | */ | |
e1a4f377 | 70 | CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak, unsigned char nFlagsIn); |
8bdd2877 | 71 | CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {} |
bd21612c | 72 | |
3f6540ad | 73 | ADD_SERIALIZE_METHODS; |
3d796f89 | 74 | |
84881f8c | 75 | template <typename Stream, typename Operation> |
31e9a838 | 76 | inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { |
bd21612c MC |
77 | READWRITE(vData); |
78 | READWRITE(nHashFuncs); | |
b1f99bed | 79 | READWRITE(nTweak); |
e1a4f377 | 80 | READWRITE(nFlags); |
3d796f89 | 81 | } |
bd21612c MC |
82 | |
83 | void insert(const std::vector<unsigned char>& vKey); | |
84 | void insert(const COutPoint& outpoint); | |
85 | void insert(const uint256& hash); | |
86 | ||
87 | bool contains(const std::vector<unsigned char>& vKey) const; | |
88 | bool contains(const COutPoint& outpoint) const; | |
89 | bool contains(const uint256& hash) const; | |
90 | ||
9c347313 | 91 | void clear(); |
83671efe | 92 | void reset(unsigned int nNewTweak); |
9c347313 | 93 | |
fa94b9d5 MF |
94 | //! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS |
95 | //! (catch a filter which was just deserialized which was too big) | |
bd21612c MC |
96 | bool IsWithinSizeConstraints() const; |
97 | ||
fa94b9d5 | 98 | //! Also adds any outputs which match the filter to the filter (to match their spending txes) |
d38da59b | 99 | bool IsRelevantAndUpdate(const CTransaction& tx); |
37c6389c | 100 | |
fa94b9d5 | 101 | //! Checks for empty and full filters to avoid wasting cpu |
37c6389c | 102 | void UpdateEmptyFull(); |
bd21612c MC |
103 | }; |
104 | ||
69a5f8be GA |
105 | /** |
106 | * RollingBloomFilter is a probabilistic "keep track of most recently inserted" set. | |
83671efe PT |
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. | |
69a5f8be GA |
112 | * |
113 | * contains(item) will always return true if item was one of the last N things | |
114 | * insert()'ed ... but may also return true for items that were not inserted. | |
115 | */ | |
116 | class CRollingBloomFilter | |
117 | { | |
118 | public: | |
6eed52e0 PW |
119 | // A random bloom filter calls GetRand() at creation time. |
120 | // Don't create global CRollingBloomFilter objects, as they may be | |
121 | // constructed before the randomizer is properly initialized. | |
122 | CRollingBloomFilter(unsigned int nElements, double nFPRate); | |
69a5f8be GA |
123 | |
124 | void insert(const std::vector<unsigned char>& vKey); | |
2983fe04 | 125 | void insert(const uint256& hash); |
69a5f8be | 126 | bool contains(const std::vector<unsigned char>& vKey) const; |
2983fe04 | 127 | bool contains(const uint256& hash) const; |
69a5f8be | 128 | |
6eed52e0 | 129 | void reset(); |
69a5f8be GA |
130 | |
131 | private: | |
132 | unsigned int nBloomSize; | |
133 | unsigned int nInsertions; | |
134 | CBloomFilter b1, b2; | |
135 | }; | |
136 | ||
137 | ||
093303a8 | 138 | #endif // BITCOIN_BLOOM_H |