Fabcoin Core  0.16.2
P2P Digital Currency
bloomFilter.cpp
Go to the documentation of this file.
1 /*
2 This file is part of cpp-ethereum.
3 
4 cpp-ethereum is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8 
9 cpp-ethereum is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #include <boost/test/unit_test.hpp>
23 #include <libdevcore/SHA3.h>
24 #include <libwhisper/BloomFilter.h>
26 
27 using namespace std;
28 using namespace dev;
29 using namespace dev::test;
30 using namespace dev::shh;
31 
34 
36 {
37  BOOST_REQUIRE(!_f.containsRaw(_h));
38  _f.addRaw(_h);
39  BOOST_REQUIRE(_f.containsRaw(_h));
40 }
41 
43 {
44  BOOST_REQUIRE(_f.containsRaw(_h));
45  _f.removeRaw(_h);
46  BOOST_REQUIRE(!_f.containsRaw(_h));
47 }
48 
50 {
51  BOOST_REQUIRE(!_f.containsBloom(_h));
52  _f.addBloom(_h);
53  BOOST_REQUIRE(_f.containsBloom(_h));
54 }
55 
57 {
58  BOOST_REQUIRE(_f.containsBloom(_h));
59  _f.removeBloom(_h);
60  BOOST_REQUIRE(!_f.containsBloom(_h));
61 }
62 
64 {
65  int const m = f.size * 8; // number of bits in the bloom
66  int const k = BitsPerBloom; // number of hash functions (e.g. bits set to 1 in every bloom)
67 
68  double singleBitSet = 1.0 / m; // probability of any bit being set after inserting a single bit
69  double singleBitNotSet = (1.0 - singleBitSet);
70 
71  double singleNot = 1; // single bit not set after inserting N elements in the bloom filter
72  for (int i = 0; i < k * n; ++i)
73  singleNot *= singleBitNotSet;
74 
75  double single = 1.0 - singleNot; // probability of a single bit being set after inserting N elements in the bloom filter
76 
77  double kBitsSet = 1; // probability of K bits being set after inserting N elements in the bloom filter
78  for (int i = 0; i < k; ++i)
79  kBitsSet *= single;
80 
81  return kBitsSet;
82 }
83 
84 double testFalsePositiveRate(TopicBloomFilterTest const& f, int inserted, Topic& x)
85 {
86  int const c_sampleSize = 1000;
87  int falsePositive = 0;
88 
89  for (int i = 0; i < c_sampleSize; ++i)
90  {
91  x = sha3(x);
92  AbridgedTopic a(x);
93  if (f.containsBloom(a))
94  ++falsePositive;
95  }
96 
97  double res = double(falsePositive) / double(c_sampleSize);
98 
99  double expected = calculateExpected(f, inserted);
100  double allowed = expected * 1.2 + 0.05; // allow deviations ~25%
101 
102  //cnote << "Inserted: " << inserted << ", False Positive Rate: " << res << ", Expected: " << expected;
103  BOOST_REQUIRE(res <= allowed);
104  return expected;
105 }
106 
108 
109 //
110 // Disabled tests as they are unstable and tend to stall the test suite.
111 //
112 
114 {
115  // Added this test such that the test executable has at least one test
116 }
117 
118 //BOOST_AUTO_TEST_CASE(falsePositiveRate)
119 //{
120 // VerbosityHolder setTemporaryLevel(10);
121 // cnote << "Testing Bloom Filter False Positive Rate...";
122 
123 // TopicBloomFilterTest f;
124 // Topic x(0xC0DEFEED); // deterministic pseudorandom value
125 
126 // double expectedRate = 0;
127 
128 // for (int i = 1; i < 50 && isless(expectedRate, 0.5); ++i)
129 // {
130 // x = sha3(x);
131 // f.addBloom(AbridgedTopic(x));
132 // expectedRate = testFalsePositiveRate(f, i, x);
133 // }
134 //}
135 
136 //BOOST_AUTO_TEST_CASE(bloomFilterRandom)
137 //{
138 // VerbosityHolder setTemporaryLevel(10);
139 // cnote << "Testing Bloom Filter matching...";
140 
141 // TopicBloomFilterShort f;
142 // vector<AbridgedTopic> vec;
143 // Topic x(0xDEADBEEF);
144 // int const c_rounds = 4;
145 
146 // for (int i = 0; i < c_rounds; ++i, x = sha3(x))
147 // vec.push_back(abridge(x));
148 
149 // for (int i = 0; i < c_rounds; ++i)
150 // testAddNonExisting(f, vec[i]);
151 
152 // for (int i = 0; i < c_rounds; ++i)
153 // testRemoveExisting(f, vec[i]);
154 
155 // for (int i = 0; i < c_rounds; ++i)
156 // testAddNonExistingBloom(f, vec[i]);
157 
158 // for (int i = 0; i < c_rounds; ++i)
159 // testRemoveExistingBloom(f, vec[i]);
160 //}
161 
162 //BOOST_AUTO_TEST_CASE(bloomFilterRaw)
163 //{
164 // VerbosityHolder setTemporaryLevel(10);
165 // cnote << "Testing Raw Bloom matching...";
166 
167 // TopicBloomFilterShort f;
168 
169 // AbridgedTopic b00000001(0x01);
170 // AbridgedTopic b00010000(0x10);
171 // AbridgedTopic b00011000(0x18);
172 // AbridgedTopic b00110000(0x30);
173 // AbridgedTopic b00110010(0x32);
174 // AbridgedTopic b00111000(0x38);
175 // AbridgedTopic b00000110(0x06);
176 // AbridgedTopic b00110110(0x36);
177 // AbridgedTopic b00110111(0x37);
178 
179 // testAddNonExisting(f, b00000001);
180 // testAddNonExisting(f, b00010000);
181 // testAddNonExisting(f, b00011000);
182 // testAddNonExisting(f, b00110000);
183 // BOOST_REQUIRE(f.contains(b00111000));
184 // testAddNonExisting(f, b00110010);
185 // testAddNonExisting(f, b00000110);
186 // BOOST_REQUIRE(f.contains(b00110110));
187 // BOOST_REQUIRE(f.contains(b00110111));
188 
189 // f.removeRaw(b00000001);
190 // f.removeRaw(b00000001);
191 // f.removeRaw(b00000001);
192 // BOOST_REQUIRE(!f.contains(b00000001));
193 // BOOST_REQUIRE(f.contains(b00010000));
194 // BOOST_REQUIRE(f.contains(b00011000));
195 // BOOST_REQUIRE(f.contains(b00110000));
196 // BOOST_REQUIRE(f.contains(b00110010));
197 // BOOST_REQUIRE(f.contains(b00111000));
198 // BOOST_REQUIRE(f.contains(b00000110));
199 // BOOST_REQUIRE(f.contains(b00110110));
200 // BOOST_REQUIRE(!f.contains(b00110111));
201 
202 // f.removeRaw(b00010000);
203 // BOOST_REQUIRE(!f.contains(b00000001));
204 // BOOST_REQUIRE(f.contains(b00010000));
205 // BOOST_REQUIRE(f.contains(b00011000));
206 // BOOST_REQUIRE(f.contains(b00110000));
207 // BOOST_REQUIRE(f.contains(b00110010));
208 // BOOST_REQUIRE(f.contains(b00111000));
209 // BOOST_REQUIRE(f.contains(b00000110));
210 // BOOST_REQUIRE(f.contains(b00110110));
211 // BOOST_REQUIRE(!f.contains(b00110111));
212 
213 // f.removeRaw(b00111000);
214 // BOOST_REQUIRE(!f.contains(b00000001));
215 // BOOST_REQUIRE(f.contains(b00010000));
216 // BOOST_REQUIRE(!f.contains(b00011000));
217 // BOOST_REQUIRE(f.contains(b00110000));
218 // BOOST_REQUIRE(f.contains(b00110010));
219 // BOOST_REQUIRE(!f.contains(b00111000));
220 // BOOST_REQUIRE(f.contains(b00000110));
221 // BOOST_REQUIRE(f.contains(b00110110));
222 // BOOST_REQUIRE(!f.contains(b00110111));
223 
224 // f.addRaw(b00000001);
225 // BOOST_REQUIRE(f.contains(b00000001));
226 // BOOST_REQUIRE(f.contains(b00010000));
227 // BOOST_REQUIRE(!f.contains(b00011000));
228 // BOOST_REQUIRE(f.contains(b00110000));
229 // BOOST_REQUIRE(f.contains(b00110010));
230 // BOOST_REQUIRE(!f.contains(b00111000));
231 // BOOST_REQUIRE(f.contains(b00000110));
232 // BOOST_REQUIRE(f.contains(b00110110));
233 // BOOST_REQUIRE(f.contains(b00110111));
234 
235 // f.removeRaw(b00110111);
236 // BOOST_REQUIRE(!f.contains(b00000001));
237 // BOOST_REQUIRE(f.contains(b00010000));
238 // BOOST_REQUIRE(!f.contains(b00011000));
239 // BOOST_REQUIRE(!f.contains(b00110000));
240 // BOOST_REQUIRE(!f.contains(b00110010));
241 // BOOST_REQUIRE(!f.contains(b00111000));
242 // BOOST_REQUIRE(!f.contains(b00000110));
243 // BOOST_REQUIRE(!f.contains(b00110110));
244 // BOOST_REQUIRE(!f.contains(b00110111));
245 
246 // f.removeRaw(b00110111);
247 // BOOST_REQUIRE(!f.contains(b00000001));
248 // BOOST_REQUIRE(!f.contains(b00010000));
249 // BOOST_REQUIRE(!f.contains(b00011000));
250 // BOOST_REQUIRE(!f.contains(b00110000));
251 // BOOST_REQUIRE(!f.contains(b00110010));
252 // BOOST_REQUIRE(!f.contains(b00111000));
253 // BOOST_REQUIRE(!f.contains(b00000110));
254 // BOOST_REQUIRE(!f.contains(b00110110));
255 // BOOST_REQUIRE(!f.contains(b00110111));
256 //}
257 
258 //static const unsigned DistributionTestSize = TopicBloomFilterSize;
259 //static const unsigned TestArrSize = 8 * DistributionTestSize;
260 
261 //void updateDistribution(FixedHash<DistributionTestSize> const& _h, array<unsigned, TestArrSize>& _distribution)
262 //{
263 // unsigned bits = 0;
264 // for (unsigned i = 0; i < DistributionTestSize; ++i)
265 // if (_h[i])
266 // for (unsigned j = 0; j < 8; ++j)
267 // if (_h[i] & c_powerOfTwoBitMmask[j])
268 // {
269 // _distribution[i * 8 + j]++;
270 // if (++bits >= BitsPerBloom)
271 // return;
272 // }
273 //}
274 
275 //BOOST_AUTO_TEST_CASE(distributionRate)
276 //{
277 // cnote << "Testing Bloom Filter Distribution Rate...";
278 
279 // array<unsigned, TestArrSize> distribution;
280 // for (unsigned i = 0; i < TestArrSize; ++i)
281 // distribution[i] = 0;
282 
283 // Topic x(0xC0FFEE); // deterministic pseudorandom value
284 
285 // for (unsigned i = 0; i < 26000; ++i)
286 // {
287 // x = sha3(x);
288 // FixedHash<DistributionTestSize> h = TopicBloomFilter::bloom(abridge(x));
289 // updateDistribution(h, distribution);
290 // }
291 
292 // unsigned average = 0;
293 // for (unsigned i = 0; i < TestArrSize; ++i)
294 // average += distribution[i];
295 
296 // average /= TestArrSize;
297 // unsigned deviation = average / 3;
298 // unsigned maxAllowed = average + deviation;
299 // unsigned minAllowed = average - deviation;
300 
301 // unsigned maximum = 0;
302 // unsigned minimum = 0xFFFFFFFF;
303 
304 // for (unsigned i = 0; i < TestArrSize; ++i)
305 // {
306 // unsigned const& z = distribution[i];
307 // if (z > maximum)
308 // maximum = z;
309 // else if (z < minimum)
310 // minimum = z;
311 // }
312 
313 // cnote << minimum << average << maximum;
314 // BOOST_REQUIRE(minimum > minAllowed);
315 // BOOST_REQUIRE(maximum < maxAllowed);
316 //}
317 
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
void removeRaw(FixedHash< N > const &_h)
Definition: BloomFilter.h:74
void testAddNonExisting(TopicBloomFilterShort &_f, AbridgedTopic const &_h)
Definition: bloomFilter.cpp:35
std::hash for asio::adress
Definition: Common.h:323
Definition: Eth.h:45
BOOST_AUTO_TEST_CASE(dummyTest)
bool containsRaw(FixedHash< N > const &_h) const
Definition: BloomFilter.h:44
#define a(i)
#define x(i)
void testRemoveExistingBloom(TopicBloomFilterShort &_f, AbridgedTopic const &_h)
Definition: bloomFilter.cpp:56
double testFalsePositiveRate(TopicBloomFilterTest const &f, int inserted, Topic &x)
Definition: bloomFilter.cpp:84
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
Definition: FixedHash.h:47
void removeBloom(AbridgedTopic const &_h)
Definition: BloomFilter.h:39
double calculateExpected(TopicBloomFilterTest const &f, int n)
Definition: bloomFilter.cpp:63
void addBloom(AbridgedTopic const &_h)
Definition: BloomFilter.h:38
#define f(x)
Definition: gost.cpp:57
void addRaw(FixedHash< N > const &_h)
Definition: BloomFilter.h:60
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
Definition: SHA3.cpp:214
#define BOOST_AUTO_TEST_SUITE_END()
Definition: object.cpp:16
bool containsBloom(AbridgedTopic const &_h) const
Definition: BloomFilter.h:40
void testRemoveExisting(TopicBloomFilterShort &_f, AbridgedTopic const &_h)
Definition: bloomFilter.cpp:42
void testAddNonExistingBloom(TopicBloomFilterShort &_f, AbridgedTopic const &_h)
Definition: bloomFilter.cpp:49
Helper functions to work with json::spirit and test files.