1 // Copyright (c) 2012-2014 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 #include "primitives/transaction.h"
9 #include "script/script.h"
10 #include "script/standard.h"
17 #include <boost/foreach.hpp>
19 #define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455
20 #define LN2 0.6931471805599453094172321214581765680755001343602552
24 CBloomFilter::CBloomFilter(unsigned int nElements
, double nFPRate
, unsigned int nTweakIn
, unsigned char nFlagsIn
) :
26 * The ideal size for a bloom filter with a given number of elements and false positive rate is:
27 * - nElements * log(fp rate) / ln(2)^2
28 * We ignore filter parameters which will create a bloom filter larger than the protocol limits
30 vData(min((unsigned int)(-1 / LN2SQUARED
* nElements
* log(nFPRate
)), MAX_BLOOM_FILTER_SIZE
* 8) / 8),
32 * The ideal number of hash functions is filter size * ln(2) / number of elements
33 * Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
34 * See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
38 nHashFuncs(min((unsigned int)(vData
.size() * 8 / nElements
* LN2
), MAX_HASH_FUNCS
)),
44 // Private constructor used by CRollingBloomFilter
45 CBloomFilter::CBloomFilter(unsigned int nElements
, double nFPRate
, unsigned int nTweakIn
) :
46 vData((unsigned int)(-1 / LN2SQUARED
* nElements
* log(nFPRate
)) / 8),
49 nHashFuncs((unsigned int)(vData
.size() * 8 / nElements
* LN2
)),
51 nFlags(BLOOM_UPDATE_NONE
)
55 inline unsigned int CBloomFilter::Hash(unsigned int nHashNum
, const std::vector
<unsigned char>& vDataToHash
) const
57 // 0xFBA4C795 chosen as it guarantees a reasonable bit difference between nHashNum values.
58 return MurmurHash3(nHashNum
* 0xFBA4C795 + nTweak
, vDataToHash
) % (vData
.size() * 8);
61 void CBloomFilter::insert(const vector
<unsigned char>& vKey
)
65 for (unsigned int i
= 0; i
< nHashFuncs
; i
++)
67 unsigned int nIndex
= Hash(i
, vKey
);
68 // Sets bit nIndex of vData
69 vData
[nIndex
>> 3] |= (1 << (7 & nIndex
));
74 void CBloomFilter::insert(const COutPoint
& outpoint
)
76 CDataStream
stream(SER_NETWORK
, PROTOCOL_VERSION
);
78 vector
<unsigned char> data(stream
.begin(), stream
.end());
82 void CBloomFilter::insert(const uint256
& hash
)
84 vector
<unsigned char> data(hash
.begin(), hash
.end());
88 bool CBloomFilter::contains(const vector
<unsigned char>& vKey
) const
94 for (unsigned int i
= 0; i
< nHashFuncs
; i
++)
96 unsigned int nIndex
= Hash(i
, vKey
);
97 // Checks bit nIndex of vData
98 if (!(vData
[nIndex
>> 3] & (1 << (7 & nIndex
))))
104 bool CBloomFilter::contains(const COutPoint
& outpoint
) const
106 CDataStream
stream(SER_NETWORK
, PROTOCOL_VERSION
);
108 vector
<unsigned char> data(stream
.begin(), stream
.end());
109 return contains(data
);
112 bool CBloomFilter::contains(const uint256
& hash
) const
114 vector
<unsigned char> data(hash
.begin(), hash
.end());
115 return contains(data
);
118 void CBloomFilter::clear()
120 vData
.assign(vData
.size(),0);
125 void CBloomFilter::reset(unsigned int nNewTweak
)
131 bool CBloomFilter::IsWithinSizeConstraints() const
133 return vData
.size() <= MAX_BLOOM_FILTER_SIZE
&& nHashFuncs
<= MAX_HASH_FUNCS
;
136 bool CBloomFilter::IsRelevantAndUpdate(const CTransaction
& tx
)
139 // Match if the filter contains the hash of tx
140 // for finding tx when they appear in a block
145 const uint256
& hash
= tx
.GetHash();
149 for (unsigned int i
= 0; i
< tx
.vout
.size(); i
++)
151 const CTxOut
& txout
= tx
.vout
[i
];
152 // Match if the filter contains any arbitrary script data element in any scriptPubKey in tx
153 // If this matches, also add the specific output that was matched.
154 // This means clients don't have to update the filter themselves when a new relevant tx
155 // is discovered in order to find spending transactions, which avoids round-tripping and race conditions.
156 CScript::const_iterator pc
= txout
.scriptPubKey
.begin();
157 vector
<unsigned char> data
;
158 while (pc
< txout
.scriptPubKey
.end())
161 if (!txout
.scriptPubKey
.GetOp(pc
, opcode
, data
))
163 if (data
.size() != 0 && contains(data
))
166 if ((nFlags
& BLOOM_UPDATE_MASK
) == BLOOM_UPDATE_ALL
)
167 insert(COutPoint(hash
, i
));
168 else if ((nFlags
& BLOOM_UPDATE_MASK
) == BLOOM_UPDATE_P2PUBKEY_ONLY
)
171 vector
<vector
<unsigned char> > vSolutions
;
172 if (Solver(txout
.scriptPubKey
, type
, vSolutions
) &&
173 (type
== TX_PUBKEY
|| type
== TX_MULTISIG
))
174 insert(COutPoint(hash
, i
));
184 BOOST_FOREACH(const CTxIn
& txin
, tx
.vin
)
186 // Match if the filter contains an outpoint tx spends
187 if (contains(txin
.prevout
))
190 // Match if the filter contains any arbitrary script data element in any scriptSig in tx
191 CScript::const_iterator pc
= txin
.scriptSig
.begin();
192 vector
<unsigned char> data
;
193 while (pc
< txin
.scriptSig
.end())
196 if (!txin
.scriptSig
.GetOp(pc
, opcode
, data
))
198 if (data
.size() != 0 && contains(data
))
206 void CBloomFilter::UpdateEmptyFull()
210 for (unsigned int i
= 0; i
< vData
.size(); i
++)
212 full
&= vData
[i
] == 0xff;
213 empty
&= vData
[i
] == 0;
219 CRollingBloomFilter::CRollingBloomFilter(unsigned int nElements
, double fpRate
) :
220 b1(nElements
* 2, fpRate
, 0), b2(nElements
* 2, fpRate
, 0)
222 // Implemented using two bloom filters of 2 * nElements each.
223 // We fill them up, and clear them, staggered, every nElements
224 // inserted, so at least one always contains the last nElements
227 nBloomSize
= nElements
* 2;
232 void CRollingBloomFilter::insert(const std::vector
<unsigned char>& vKey
)
234 if (nInsertions
== 0) {
236 } else if (nInsertions
== nBloomSize
/ 2) {
241 if (++nInsertions
== nBloomSize
) {
246 void CRollingBloomFilter::insert(const uint256
& hash
)
248 vector
<unsigned char> data(hash
.begin(), hash
.end());
252 bool CRollingBloomFilter::contains(const std::vector
<unsigned char>& vKey
) const
254 if (nInsertions
< nBloomSize
/ 2) {
255 return b2
.contains(vKey
);
257 return b1
.contains(vKey
);
260 bool CRollingBloomFilter::contains(const uint256
& hash
) const
262 vector
<unsigned char> data(hash
.begin(), hash
.end());
263 return contains(data
);
266 void CRollingBloomFilter::reset()
268 unsigned int nNewTweak
= GetRand(std::numeric_limits
<unsigned int>::max());