From 52f4f289c1bf71f9a6e96529b8c76178f838d004 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Sat, 4 Jul 2015 01:09:31 +0200 Subject: [PATCH] rating initial version complete --- libwhisper/BloomFilter.h | 54 ++++++++++++++++++++++++++---- libwhisper/Common.cpp | 2 +- libwhisper/Message.cpp | 3 +- test/libwhisper/bloomFilter.cpp | 23 +++++++++---- test/libwhisper/whisperMessage.cpp | 2 +- 5 files changed, 68 insertions(+), 16 deletions(-) diff --git a/libwhisper/BloomFilter.h b/libwhisper/BloomFilter.h index 7b5d179c6..32ac15043 100644 --- a/libwhisper/BloomFilter.h +++ b/libwhisper/BloomFilter.h @@ -35,17 +35,20 @@ public: TopicBloomFilterBase() { init(); } TopicBloomFilterBase(FixedHash const& _h): FixedHash(_h) { init(); } - void addBloom(dev::shh::AbridgedTopic const& _h) { addRaw(_h.template bloomPart()); } - void removeBloom(dev::shh::AbridgedTopic const& _h) { removeRaw(_h.template bloomPart()); } - bool containsBloom(dev::shh::AbridgedTopic const& _h) const { return this->contains(_h.template bloomPart()); } + void addBloom(AbridgedTopic const& _h) { addRaw(bloom(_h)); } + void removeBloom(AbridgedTopic const& _h) { removeRaw(bloom(_h)); } + bool containsBloom(AbridgedTopic const& _h) const { return this->contains(bloom(_h)); } void addRaw(FixedHash const& _h); void removeRaw(FixedHash const& _h); bool containsRaw(FixedHash const& _h) const { return this->contains(_h); } + + static FixedHash bloom(AbridgedTopic const& _h); + static void setBit(FixedHash& _h, unsigned index); + static bool isBitSet(FixedHash const& _h, unsigned _index); private: void init() { for (unsigned i = 0; i < CounterSize; ++i) m_refCounter[i] = 0; } - static bool isBitSet(FixedHash const& _h, unsigned _index); static const unsigned CounterSize = N * 8; std::array m_refCounter; @@ -83,12 +86,51 @@ void TopicBloomFilterBase::removeRaw(FixedHash const& _h) template bool TopicBloomFilterBase::isBitSet(FixedHash const& _h, unsigned _index) -{ +{ unsigned iByte = _index / 8; - unsigned iBit = _index % 8; + unsigned iBit = _index & 0x7; return (_h[iByte] & c_powerOfTwoBitMmask[iBit]) != 0; } +template +void TopicBloomFilterBase::setBit(FixedHash& _h, unsigned _index) +{ + unsigned iByte = _index / 8; + unsigned iBit = _index & 0x7; + _h[iByte] |= c_powerOfTwoBitMmask[iBit]; +} + +template +FixedHash TopicBloomFilterBase::bloom(AbridgedTopic const& _h) +{ + // The size of AbridgedTopic is 32 bits, and 27 of them participate in this algorithm. + + // We need to review the algorithm if any of the following constants will be changed. + static_assert(4 == AbridgedTopic::size, "wrong template parameter in TopicBloomFilterBase::bloom()"); + static_assert(3 == BitsPerBloom, "wrong template parameter in TopicBloomFilterBase::bloom()"); + + FixedHash ret; + + if (TopicBloomFilterSize == N) + for (unsigned i = 0; i < BitsPerBloom; ++i) + { + unsigned x = _h[i]; + if (_h[BitsPerBloom] & c_powerOfTwoBitMmask[i]) + x += 256; + + setBit(ret, x); + } + else + for (unsigned i = 0; i < BitsPerBloom; ++i) + { + unsigned x = unsigned(_h[i]) + unsigned(_h[i + 1]); + x %= N * 8; + setBit(ret, x); + } + + return ret; +} + using TopicBloomFilter = TopicBloomFilterBase; } diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index 7c7a9801b..4681a21b3 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -100,7 +100,7 @@ TopicBloomFilterHash TopicFilter::exportBloom() const TopicBloomFilterHash ret; for (TopicMask const& t: m_topicMasks) for (auto const& i: t) - ret |= i.first.template bloomPart(); + ret |= TopicBloomFilter::bloom(i.first); return ret; } diff --git a/libwhisper/Message.cpp b/libwhisper/Message.cpp index 2d15ee315..435811a3b 100644 --- a/libwhisper/Message.cpp +++ b/libwhisper/Message.cpp @@ -20,6 +20,7 @@ */ #include "Message.h" +#include "BloomFilter.h" using namespace std; using namespace dev; @@ -185,7 +186,7 @@ void Envelope::proveWork(unsigned _ms) bool Envelope::matchesBloomFilter(TopicBloomFilterHash const& f) const { for (AbridgedTopic t: m_topic) - if (f.contains(t.template bloomPart())) + if (f.contains(TopicBloomFilter::bloom(t))) return true; return false; diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index 197a7258d..d7d4bd849 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(bloomFilterRaw) BOOST_REQUIRE(!f.contains(b00110111)); } -static const unsigned DistributionTestSize = 8; +static const unsigned DistributionTestSize = TopicBloomFilterSize; static const unsigned TestArrSize = 8 * DistributionTestSize; void updateDistribution(FixedHash const& _h, array& _distribution) @@ -271,10 +271,10 @@ BOOST_AUTO_TEST_CASE(distributionRate) Topic x(0xC0FFEE); // deterministic pseudorandom value - for (unsigned i = 0; i < 22000; ++i) + for (unsigned i = 0; i < 26000; ++i) { x = sha3(x); - FixedHash h = x.template bloomPart(); + FixedHash h = TopicBloomFilter::bloom(abridge(x)); updateDistribution(h, distribution); } @@ -283,16 +283,25 @@ BOOST_AUTO_TEST_CASE(distributionRate) average += distribution[i]; average /= TestArrSize; - unsigned deviation = average / 10; // approx. 10% + unsigned deviation = average / 3; unsigned maxAllowed = average + deviation; unsigned minAllowed = average - deviation; + unsigned maximum = 0; + unsigned minimum = 0xFFFFFFFF; + for (unsigned i = 0; i < TestArrSize; ++i) { - //cnote << i << ":" << distribution[i]; - BOOST_REQUIRE(distribution[i] > minAllowed); - BOOST_REQUIRE(distribution[i] < maxAllowed); + unsigned const& z = distribution[i]; + if (z > maximum) + maximum = z; + else if (z < minimum) + minimum = z; } + + cnote << minimum << average << maximum; + BOOST_REQUIRE(minimum > minAllowed); + BOOST_REQUIRE(maximum < maxAllowed); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libwhisper/whisperMessage.cpp b/test/libwhisper/whisperMessage.cpp index 8d9a29579..f0c0aedc9 100644 --- a/test/libwhisper/whisperMessage.cpp +++ b/test/libwhisper/whisperMessage.cpp @@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(work) Message m(payload); Envelope e = m.seal(zero, topics, 1, 50); unsigned x = e.workProved(); - cnote << x; + //cnote << x; BOOST_REQUIRE(x > 4); } }