You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
3.7 KiB

/*
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 LogFilter.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "LogFilter.h"
#include <libdevcore/SHA3.h>
#include "State.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
10 years ago
std::ostream& dev::eth::operator<<(std::ostream& _out, LogFilter const& _s)
{
// TODO
_out << "(@" << _s.m_addresses << "#" << _s.m_topics << ">" << _s.m_earliest << "-" << _s.m_latest << "< )";
return _out;
}
void LogFilter::streamRLP(RLPStream& _s) const
{
_s.appendList(4) << m_addresses << m_topics << m_earliest << m_latest;
}
h256 LogFilter::sha3() const
{
RLPStream s;
streamRLP(s);
return dev::sha3(s.out());
}
bool LogFilter::isRangeFilter() const
{
if (m_addresses.size())
return false;
for (auto const& t: m_topics)
if (t.size())
return false;
return true;
}
bool LogFilter::matches(LogBloom _bloom) const
{
if (m_addresses.size())
{
for (auto const& i: m_addresses)
if (_bloom.containsBloom<3>(dev::sha3(i)))
goto OK1;
return false;
}
OK1:
for (auto const& t: m_topics)
if (t.size())
{
for (auto const& i: t)
if (_bloom.containsBloom<3>(dev::sha3(i)))
goto OK2;
return false;
OK2:;
}
return true;
}
bool LogFilter::matches(State const& _s, unsigned _i) const
{
return matches(_s.receipt(_i)).size() > 0;
}
vector<LogBloom> LogFilter::bloomPossibilities() const
{
// return combination of each of the addresses/topics
vector<LogBloom> ret;
// | every address with every topic
for (auto const& i: m_addresses)
{
// 1st case, there are addresses and topics
//
// m_addresses = [a0, a1];
// m_topics = [[t0], [t1a, t1b], [], []];
//
// blooms = [
// a0 | t0, a0 | t1a | t1b,
// a1 | t0, a1 | t1a | t1b
// ]
//
for (auto const& t: m_topics)
if (t.size())
{
LogBloom b = LogBloom().shiftBloom<3>(dev::sha3(i));
for (auto const &j: t)
b = b.shiftBloom<3>(dev::sha3(j));
ret.push_back(b);
}
}
// 2nd case, there are no topics
//
// m_addresses = [a0, a1];
// m_topics = [[t0], [t1a, t1b], [], []];
//
// blooms = [a0, a1];
//
if (!ret.size())
for (auto const& i: m_addresses)
ret.push_back(LogBloom().shiftBloom<3>(dev::sha3(i)));
// 3rd case, there are no addresses, at least create blooms from topics
//
// m_addresses = [];
// m_topics = [[t0], [t1a, t1b], [], []];
//
// blooms = [t0, t1a | t1b];
//
if (!m_addresses.size())
for (auto const& t: m_topics)
if (t.size())
{
LogBloom b;
for (auto const &j: t)
b = b.shiftBloom<3>(dev::sha3(j));
ret.push_back(b);
}
return ret;
}
LogEntries LogFilter::matches(TransactionReceipt const& _m) const
{
// there are no addresses or topics to filter
if (isRangeFilter())
return _m.log();
LogEntries ret;
if (matches(_m.bloom()))
for (LogEntry const& e: _m.log())
{
if (!m_addresses.empty() && !m_addresses.count(e.address))
goto continue2;
for (unsigned i = 0; i < 4; ++i)
if (!m_topics[i].empty() && (e.topics.size() < i || !m_topics[i].count(e.topics[i])))
goto continue2;
ret.push_back(e);
continue2:;
}
return ret;
}