Gav Wood
10 years ago
8 changed files with 344 additions and 27 deletions
@ -0,0 +1,64 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file BloomFilter.cpp
|
|||
* @author Vladislav Gluhovsky <vlad@ethdev.com> |
|||
* @date June 2015 |
|||
*/ |
|||
|
|||
#include "BloomFilter.h" |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::shh; |
|||
|
|||
static unsigned const c_mask[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; |
|||
|
|||
void TopicBloomFilter::addRaw(AbridgedTopic const& _h) |
|||
{ |
|||
*this |= _h; |
|||
for (unsigned i = 0; i < CounterSize; ++i) |
|||
if (isBitSet(_h, i)) |
|||
{ |
|||
if (m_refCounter[i] != numeric_limits<uint16_t>::max()) |
|||
m_refCounter[i]++; |
|||
else |
|||
BOOST_THROW_EXCEPTION(Overflow()); |
|||
} |
|||
} |
|||
|
|||
void TopicBloomFilter::removeRaw(AbridgedTopic const& _h) |
|||
{ |
|||
for (unsigned i = 0; i < CounterSize; ++i) |
|||
if (isBitSet(_h, i)) |
|||
{ |
|||
if (m_refCounter[i]) |
|||
m_refCounter[i]--; |
|||
|
|||
if (!m_refCounter[i]) |
|||
(*this)[i / 8] &= ~c_mask[i % 8]; |
|||
} |
|||
} |
|||
|
|||
bool TopicBloomFilter::isBitSet(AbridgedTopic const& _h, unsigned _index) |
|||
{ |
|||
unsigned iByte = _index / 8; |
|||
unsigned iBit = _index % 8; |
|||
return (_h[iByte] & c_mask[iBit]) != 0; |
|||
} |
|||
|
|||
|
|||
|
@ -0,0 +1,62 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file BloomFilter.h
|
|||
* @author Vladislav Gluhovsky <vlad@ethdev.com> |
|||
* @date June 2015 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "Common.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace shh |
|||
{ |
|||
|
|||
class TopicBloomFilter: public AbridgedTopic |
|||
{ |
|||
public: |
|||
TopicBloomFilter() { init(); } |
|||
TopicBloomFilter(AbridgedTopic const& _h): AbridgedTopic(_h) { init(); } |
|||
|
|||
void addBloom(AbridgedTopic const& _h) { addRaw(_h.template bloomPart<BitsPerBloom, 4>()); } |
|||
void removeBloom(AbridgedTopic const& _h) { removeRaw(_h.template bloomPart<BitsPerBloom, 4>()); } |
|||
bool containsBloom(AbridgedTopic const& _h) const { return contains(_h.template bloomPart<BitsPerBloom, 4>()); } |
|||
|
|||
void addRaw(AbridgedTopic const& _h); |
|||
void removeRaw(AbridgedTopic const& _h); |
|||
bool containsRaw(AbridgedTopic const& _h) const { return contains(_h); } |
|||
|
|||
enum { BitsPerBloom = 3 }; |
|||
|
|||
private: |
|||
void init() { for (unsigned i = 0; i < CounterSize; ++i) m_refCounter[i] = 0; } |
|||
static bool isBitSet(AbridgedTopic const& _h, unsigned _index); |
|||
|
|||
enum { CounterSize = 8 * TopicBloomFilter::size }; |
|||
std::array<uint16_t, CounterSize> m_refCounter; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,182 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file whisperMessage.cpp
|
|||
* @author Vladislav Gluhovsky <vlad@ethdev.com> |
|||
* @date June 2015 |
|||
*/ |
|||
|
|||
#include <boost/test/unit_test.hpp> |
|||
#include <libdevcore/SHA3.h> |
|||
#include <libwhisper/BloomFilter.h> |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::shh; |
|||
|
|||
void testAddNonExisting(TopicBloomFilter& _f, AbridgedTopic const& _h) |
|||
{ |
|||
BOOST_REQUIRE(!_f.containsRaw(_h)); |
|||
_f.addRaw(_h); |
|||
BOOST_REQUIRE(_f.containsRaw(_h)); |
|||
} |
|||
|
|||
void testRemoveExisting(TopicBloomFilter& _f, AbridgedTopic const& _h) |
|||
{ |
|||
BOOST_REQUIRE(_f.containsRaw(_h)); |
|||
_f.removeRaw(_h); |
|||
BOOST_REQUIRE(!_f.containsRaw(_h)); |
|||
} |
|||
|
|||
void testAddNonExistingBloom(TopicBloomFilter& _f, AbridgedTopic const& _h) |
|||
{ |
|||
BOOST_REQUIRE(!_f.containsBloom(_h)); |
|||
_f.addBloom(_h); |
|||
BOOST_REQUIRE(_f.containsBloom(_h)); |
|||
} |
|||
|
|||
void testRemoveExistingBloom(TopicBloomFilter& _f, AbridgedTopic const& _h) |
|||
{ |
|||
BOOST_REQUIRE(_f.containsBloom(_h)); |
|||
_f.removeBloom(_h); |
|||
BOOST_REQUIRE(!_f.containsBloom(_h)); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE(bloomFilter) |
|||
|
|||
BOOST_AUTO_TEST_CASE(bloomFilterRandom) |
|||
{ |
|||
VerbosityHolder setTemporaryLevel(10); |
|||
cnote << "Testing Bloom Filter matching..."; |
|||
|
|||
TopicBloomFilter f; |
|||
vector<AbridgedTopic> vec; |
|||
Topic x(0xDEADBEEF); |
|||
int const c_rounds = 4; |
|||
|
|||
for (int i = 0; i < c_rounds; ++i, x = sha3(x)) |
|||
vec.push_back(abridge(x)); |
|||
|
|||
for (int i = 0; i < c_rounds; ++i) |
|||
testAddNonExisting(f, vec[i]); |
|||
|
|||
for (int i = 0; i < c_rounds; ++i) |
|||
testRemoveExisting(f, vec[i]); |
|||
|
|||
for (int i = 0; i < c_rounds; ++i) |
|||
testAddNonExistingBloom(f, vec[i]); |
|||
|
|||
for (int i = 0; i < c_rounds; ++i) |
|||
testRemoveExistingBloom(f, vec[i]); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE(bloomFilterRaw) |
|||
{ |
|||
VerbosityHolder setTemporaryLevel(10); |
|||
cnote << "Testing Raw Bloom matching..."; |
|||
|
|||
TopicBloomFilter f; |
|||
|
|||
AbridgedTopic b00000001(0x01); |
|||
AbridgedTopic b00010000(0x10); |
|||
AbridgedTopic b00011000(0x18); |
|||
AbridgedTopic b00110000(0x30); |
|||
AbridgedTopic b00110010(0x32); |
|||
AbridgedTopic b00111000(0x38); |
|||
AbridgedTopic b00000110(0x06); |
|||
AbridgedTopic b00110110(0x36); |
|||
AbridgedTopic b00110111(0x37); |
|||
|
|||
testAddNonExisting(f, b00000001); |
|||
testAddNonExisting(f, b00010000); |
|||
testAddNonExisting(f, b00011000); |
|||
testAddNonExisting(f, b00110000); |
|||
BOOST_REQUIRE(f.contains(b00111000)); |
|||
testAddNonExisting(f, b00110010); |
|||
testAddNonExisting(f, b00000110); |
|||
BOOST_REQUIRE(f.contains(b00110110)); |
|||
BOOST_REQUIRE(f.contains(b00110111)); |
|||
|
|||
f.removeRaw(b00000001); |
|||
f.removeRaw(b00000001); |
|||
f.removeRaw(b00000001); |
|||
BOOST_REQUIRE(!f.contains(b00000001)); |
|||
BOOST_REQUIRE(f.contains(b00010000)); |
|||
BOOST_REQUIRE(f.contains(b00011000)); |
|||
BOOST_REQUIRE(f.contains(b00110000)); |
|||
BOOST_REQUIRE(f.contains(b00110010)); |
|||
BOOST_REQUIRE(f.contains(b00111000)); |
|||
BOOST_REQUIRE(f.contains(b00000110)); |
|||
BOOST_REQUIRE(f.contains(b00110110)); |
|||
BOOST_REQUIRE(!f.contains(b00110111)); |
|||
|
|||
f.removeRaw(b00010000); |
|||
BOOST_REQUIRE(!f.contains(b00000001)); |
|||
BOOST_REQUIRE(f.contains(b00010000)); |
|||
BOOST_REQUIRE(f.contains(b00011000)); |
|||
BOOST_REQUIRE(f.contains(b00110000)); |
|||
BOOST_REQUIRE(f.contains(b00110010)); |
|||
BOOST_REQUIRE(f.contains(b00111000)); |
|||
BOOST_REQUIRE(f.contains(b00000110)); |
|||
BOOST_REQUIRE(f.contains(b00110110)); |
|||
BOOST_REQUIRE(!f.contains(b00110111)); |
|||
|
|||
f.removeRaw(b00111000); |
|||
BOOST_REQUIRE(!f.contains(b00000001)); |
|||
BOOST_REQUIRE(f.contains(b00010000)); |
|||
BOOST_REQUIRE(!f.contains(b00011000)); |
|||
BOOST_REQUIRE(f.contains(b00110000)); |
|||
BOOST_REQUIRE(f.contains(b00110010)); |
|||
BOOST_REQUIRE(!f.contains(b00111000)); |
|||
BOOST_REQUIRE(f.contains(b00000110)); |
|||
BOOST_REQUIRE(f.contains(b00110110)); |
|||
BOOST_REQUIRE(!f.contains(b00110111)); |
|||
|
|||
f.addRaw(b00000001); |
|||
BOOST_REQUIRE(f.contains(b00000001)); |
|||
BOOST_REQUIRE(f.contains(b00010000)); |
|||
BOOST_REQUIRE(!f.contains(b00011000)); |
|||
BOOST_REQUIRE(f.contains(b00110000)); |
|||
BOOST_REQUIRE(f.contains(b00110010)); |
|||
BOOST_REQUIRE(!f.contains(b00111000)); |
|||
BOOST_REQUIRE(f.contains(b00000110)); |
|||
BOOST_REQUIRE(f.contains(b00110110)); |
|||
BOOST_REQUIRE(f.contains(b00110111)); |
|||
|
|||
f.removeRaw(b00110111); |
|||
BOOST_REQUIRE(!f.contains(b00000001)); |
|||
BOOST_REQUIRE(f.contains(b00010000)); |
|||
BOOST_REQUIRE(!f.contains(b00011000)); |
|||
BOOST_REQUIRE(!f.contains(b00110000)); |
|||
BOOST_REQUIRE(!f.contains(b00110010)); |
|||
BOOST_REQUIRE(!f.contains(b00111000)); |
|||
BOOST_REQUIRE(!f.contains(b00000110)); |
|||
BOOST_REQUIRE(!f.contains(b00110110)); |
|||
BOOST_REQUIRE(!f.contains(b00110111)); |
|||
|
|||
f.removeRaw(b00110111); |
|||
BOOST_REQUIRE(!f.contains(b00000001)); |
|||
BOOST_REQUIRE(!f.contains(b00010000)); |
|||
BOOST_REQUIRE(!f.contains(b00011000)); |
|||
BOOST_REQUIRE(!f.contains(b00110000)); |
|||
BOOST_REQUIRE(!f.contains(b00110010)); |
|||
BOOST_REQUIRE(!f.contains(b00111000)); |
|||
BOOST_REQUIRE(!f.contains(b00000110)); |
|||
BOOST_REQUIRE(!f.contains(b00110110)); |
|||
BOOST_REQUIRE(!f.contains(b00110111)); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE_END() |
Loading…
Reference in new issue