Browse Source

Bloom Filter, first version

cl-refactor
Vlad Gluhovsky 10 years ago
parent
commit
013ba9966a
  1. 7
      libwhisper/BloomFilter.cpp
  2. 5
      libwhisper/BloomFilter.h
  3. 22
      libwhisper/Common.cpp
  4. 15
      libwhisper/Common.h
  5. 4
      libwhisper/WhisperHost.cpp
  6. 4
      libwhisper/WhisperHost.h
  7. 8
      test/libwhisper/bloomFilter.cpp

7
libwhisper/BloomFilter.cpp

@ -27,11 +27,11 @@ using namespace dev::shh;
bool BloomFilter::matches(AbridgedTopic const& _t) const
{
static unsigned const c_PerfectMatch = ~unsigned(0);
static unsigned const c_match = ~unsigned(0);
unsigned topic = AbridgedTopic::Arith(_t).convert_to<unsigned>();
unsigned matchingBits = m_filter & topic;
matchingBits |= ~topic;
return (c_PerfectMatch == matchingBits);
return (c_match == matchingBits);
}
void SharedBloomFilter::add(AbridgedTopic const& _t)
@ -46,7 +46,8 @@ void SharedBloomFilter::add(AbridgedTopic const& _t)
m_refCounter[i]++;
//else: overflow
// in order to encounter overflow, you have to set 65536 filters simultaneously.
// in order to encounter overflow, you have to set at least 65536 filters simultaneously.
// even then, the problem will only arise after at least 65536 filters will be be removed.
// we assume, it will never happen.
}

5
libwhisper/BloomFilter.h

@ -36,7 +36,12 @@ public:
BloomFilter(unsigned _i): m_filter(_i) {}
BloomFilter(AbridgedTopic const& _t): m_filter(AbridgedTopic::Arith(_t).convert_to<unsigned>()) {}
unsigned getUnsigned() const { return m_filter; }
AbridgedTopic getAbridgedTopic() const { return AbridgedTopic(m_filter); }
bool matches(AbridgedTopic const& _t) const;
virtual void add(Topic const& _t) { add(abridge(_t)); }
virtual void add(Topics const& _topics) { for (Topic t : _topics) add(abridge(t)); }
virtual void add(AbridgedTopic const& _t) { m_filter |= AbridgedTopic::Arith(_t).convert_to<unsigned>(); }
virtual void remove(AbridgedTopic const&) {} // not implemented in this class, use derived class instead.

22
libwhisper/Common.cpp

@ -20,9 +20,9 @@
*/
#include "Common.h"
#include <libdevcore/SHA3.h>
#include "Message.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
@ -84,6 +84,26 @@ bool TopicFilter::matches(Envelope const& _e) const
return false;
}
TopicFilter::TopicFilter(RLP const& _r)
{
for (RLP i: _r)
{
m_topicMasks.push_back(TopicMask());
for (RLP j: i)
m_topicMasks.back().push_back(j.toPair<FixedHash<4>, FixedHash<4>>());
}
}
AbridgedTopic TopicFilter::exportBloomFilter() const
{
AbridgedTopic ret;
for (TopicMask const& t: m_topicMasks)
for (auto i: t)
ret |= i.first;
return ret;
}
TopicMask BuildTopicMask::toTopicMask() const
{
TopicMask ret;

15
libwhisper/Common.h

@ -48,7 +48,6 @@ using h256Set = dev::h256Set;
class WhisperHost;
class WhisperPeer;
class Whisper;
class Envelope;
enum WhisperPacket
@ -91,7 +90,7 @@ protected:
h256s m_parts;
};
using TopicMask = std::vector<std::pair<AbridgedTopic, AbridgedTopic>>;
using TopicMask = std::vector<std::pair<AbridgedTopic, AbridgedTopic>>; // where pair::first is the actual abridged topic hash, pair::second is a constant (probably redundunt)
using TopicMasks = std::vector<TopicMask>;
class TopicFilter
@ -101,20 +100,12 @@ public:
TopicFilter(Topics const& _m) { m_topicMasks.push_back(TopicMask()); for (auto const& h: _m) m_topicMasks.back().push_back(std::make_pair(abridge(h), h ? ~AbridgedTopic() : AbridgedTopic())); }
TopicFilter(TopicMask const& _m): m_topicMasks(1, _m) {}
TopicFilter(TopicMasks const& _m): m_topicMasks(_m) {}
TopicFilter(RLP const& _r)//: m_topicMasks(_r.toVector<std::vector<>>())
{
for (RLP i: _r)
{
m_topicMasks.push_back(TopicMask());
for (RLP j: i)
m_topicMasks.back().push_back(j.toPair<FixedHash<4>, FixedHash<4>>());
}
}
TopicFilter(RLP const& _r);
void streamRLP(RLPStream& _s) const { _s << m_topicMasks; }
h256 sha3() const;
bool matches(Envelope const& _m) const;
AbridgedTopic exportBloomFilter() const;
private:
TopicMasks m_topicMasks;

4
libwhisper/WhisperHost.cpp

@ -113,6 +113,7 @@ unsigned WhisperHost::installWatch(shh::Topics const& _t)
if (!m_filters.count(h))
m_filters.insert(make_pair(h, f));
m_bloom.add(f.filter.exportBloomFilter());
return installWatchOnId(h);
}
@ -151,9 +152,12 @@ void WhisperHost::uninstallWatch(unsigned _i)
auto fit = m_filters.find(id);
if (fit != m_filters.end())
{
m_bloom.remove(fit->second.filter.exportBloomFilter());
if (!--fit->second.refCount)
m_filters.erase(fit);
}
}
void WhisperHost::doWork()
{

4
libwhisper/WhisperHost.h

@ -34,6 +34,7 @@
#include "Common.h"
#include "WhisperPeer.h"
#include "Interface.h"
#include "BloomFilter.h"
namespace dev
{
@ -60,7 +61,7 @@ public:
virtual void uninstallWatch(unsigned _watchId) override;
virtual h256s peekWatch(unsigned _watchId) const override { dev::Guard l(m_filterLock); try { return m_watches.at(_watchId).changes; } catch (...) { return h256s(); } }
virtual h256s checkWatch(unsigned _watchId) override { cleanup(); dev::Guard l(m_filterLock); h256s ret; try { ret = m_watches.at(_watchId).changes; m_watches.at(_watchId).changes.clear(); } catch (...) {} return ret; }
virtual h256s watchMessages(unsigned _watchId) override;
virtual h256s watchMessages(unsigned _watchId) override; /// returns IDs of messages, which match specific watch criteria
virtual Envelope envelope(h256 _m) const override { try { dev::ReadGuard l(x_messages); return m_messages.at(_m); } catch (...) { return Envelope(); } }
@ -86,6 +87,7 @@ private:
mutable dev::Mutex m_filterLock;
std::map<h256, InstalledFilter> m_filters;
std::map<unsigned, ClientWatch> m_watches;
SharedBloomFilter m_bloom;
};
}

8
test/libwhisper/bloomFilter.cpp

@ -44,6 +44,14 @@ BOOST_AUTO_TEST_CASE(match)
unsigned b00110110 = 0x36;
unsigned b00110111 = 0x37;
AbridgedTopic x(b00111000);
SharedBloomFilter f1(b00111000);
SharedBloomFilter f2(x);
BOOST_REQUIRE_EQUAL(x, f1.getAbridgedTopic());
BOOST_REQUIRE_EQUAL(x, f2.getAbridgedTopic());
BOOST_REQUIRE_EQUAL(b00111000, f1.getUnsigned());
BOOST_REQUIRE_EQUAL(b00111000, f2.getUnsigned());
BOOST_REQUIRE(!f.matches(AbridgedTopic(b00000001)));
f.add(AbridgedTopic(b00000001));
BOOST_REQUIRE(!f.matches(AbridgedTopic(b00010000)));

Loading…
Cancel
Save