6 changed files with 304 additions and 183 deletions
@ -0,0 +1,150 @@ |
|||||
|
/*
|
||||
|
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 MessageFilter.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include "MessageFilter.h" |
||||
|
|
||||
|
#include <libethcore/SHA3.h> |
||||
|
#include "State.h" |
||||
|
using namespace std; |
||||
|
using namespace eth; |
||||
|
|
||||
|
void MessageFilter::fillStream(RLPStream& _s) const |
||||
|
{ |
||||
|
_s.appendList(8) << m_from << m_to << m_stateAltered << m_altered << m_earliest << m_latest << m_max << m_skip; |
||||
|
} |
||||
|
|
||||
|
h256 MessageFilter::sha3() const |
||||
|
{ |
||||
|
RLPStream s; |
||||
|
fillStream(s); |
||||
|
return eth::sha3(s.out()); |
||||
|
} |
||||
|
|
||||
|
bool MessageFilter::matches(h256 _bloom) const |
||||
|
{ |
||||
|
auto have = [=](Address const& a) { return _bloom.contains(a.bloom()); }; |
||||
|
if (m_from.size()) |
||||
|
{ |
||||
|
for (auto i: m_from) |
||||
|
if (have(i)) |
||||
|
goto OK1; |
||||
|
return false; |
||||
|
} |
||||
|
OK1: |
||||
|
if (m_to.size()) |
||||
|
{ |
||||
|
for (auto i: m_to) |
||||
|
if (have(i)) |
||||
|
goto OK2; |
||||
|
return false; |
||||
|
} |
||||
|
OK2: |
||||
|
if (m_stateAltered.size() || m_altered.size()) |
||||
|
{ |
||||
|
for (auto i: m_altered) |
||||
|
if (have(i)) |
||||
|
goto OK3; |
||||
|
for (auto i: m_stateAltered) |
||||
|
if (have(i.first) && _bloom.contains(h256(i.second).bloom())) |
||||
|
goto OK3; |
||||
|
return false; |
||||
|
} |
||||
|
OK3: |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool MessageFilter::matches(State const& _s, unsigned _i) const |
||||
|
{ |
||||
|
h256 b = _s.changesFromPending(_i).bloom(); |
||||
|
if (!matches(b)) |
||||
|
return false; |
||||
|
|
||||
|
Transaction t = _s.pending()[_i]; |
||||
|
if (!m_to.empty() && !m_to.count(t.receiveAddress)) |
||||
|
return false; |
||||
|
if (!m_from.empty() && !m_from.count(t.sender())) |
||||
|
return false; |
||||
|
if (m_stateAltered.empty() && m_altered.empty()) |
||||
|
return true; |
||||
|
StateDiff d = _s.pendingDiff(_i); |
||||
|
if (!m_altered.empty()) |
||||
|
{ |
||||
|
for (auto const& s: m_altered) |
||||
|
if (d.accounts.count(s)) |
||||
|
return true; |
||||
|
return false; |
||||
|
} |
||||
|
if (!m_stateAltered.empty()) |
||||
|
{ |
||||
|
for (auto const& s: m_stateAltered) |
||||
|
if (d.accounts.count(s.first) && d.accounts.at(s.first).storage.count(s.second)) |
||||
|
return true; |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
PastMessages MessageFilter::matches(Manifest const& _m, unsigned _i) const |
||||
|
{ |
||||
|
PastMessages ret; |
||||
|
matches(_m, vector<unsigned>(1, _i), _m.from, PastMessages(), ret); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
bool MessageFilter::matches(Manifest const& _m, vector<unsigned> _p, Address _o, PastMessages _limbo, PastMessages& o_ret) const |
||||
|
{ |
||||
|
bool ret; |
||||
|
|
||||
|
if ((m_from.empty() || m_from.count(_m.from)) && (m_to.empty() || m_to.count(_m.to))) |
||||
|
_limbo.push_back(PastMessage(_m, _p, _o)); |
||||
|
|
||||
|
// Handle limbos, by checking against all addresses in alteration.
|
||||
|
bool alters = m_altered.empty() && m_stateAltered.empty(); |
||||
|
alters = alters || m_altered.count(_m.from) || m_altered.count(_m.to); |
||||
|
|
||||
|
if (!alters) |
||||
|
for (auto const& i: _m.altered) |
||||
|
if (m_altered.count(_m.to) || m_stateAltered.count(make_pair(_m.to, i))) |
||||
|
{ |
||||
|
alters = true; |
||||
|
break; |
||||
|
} |
||||
|
// If we do alter stuff,
|
||||
|
if (alters) |
||||
|
{ |
||||
|
o_ret += _limbo; |
||||
|
_limbo.clear(); |
||||
|
ret = true; |
||||
|
} |
||||
|
|
||||
|
_p.push_back(0); |
||||
|
for (auto const& m: _m.internal) |
||||
|
{ |
||||
|
if (matches(m, _p, _o, _limbo, o_ret)) |
||||
|
{ |
||||
|
_limbo.clear(); |
||||
|
ret = true; |
||||
|
} |
||||
|
_p.back()++; |
||||
|
} |
||||
|
|
||||
|
return ret; |
||||
|
} |
@ -0,0 +1,73 @@ |
|||||
|
/*
|
||||
|
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 MessageFilter.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <libethential/Common.h> |
||||
|
#include <libethential/RLP.h> |
||||
|
#include <libethcore/CommonEth.h> |
||||
|
#include "PastMessage.h" |
||||
|
|
||||
|
namespace eth |
||||
|
{ |
||||
|
|
||||
|
class Manifest; |
||||
|
class State; |
||||
|
|
||||
|
class MessageFilter |
||||
|
{ |
||||
|
public: |
||||
|
MessageFilter(int _earliest = 0, int _latest = -1, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {} |
||||
|
|
||||
|
void fillStream(RLPStream& _s) const; |
||||
|
h256 sha3() const; |
||||
|
|
||||
|
int earliest() const { return m_earliest; } |
||||
|
int latest() const { return m_latest; } |
||||
|
unsigned max() const { return m_max; } |
||||
|
unsigned skip() const { return m_skip; } |
||||
|
bool matches(h256 _bloom) const; |
||||
|
bool matches(State const& _s, unsigned _i) const; |
||||
|
PastMessages matches(Manifest const& _m, unsigned _i) const; |
||||
|
|
||||
|
MessageFilter from(Address _a) { m_from.insert(_a); return *this; } |
||||
|
MessageFilter to(Address _a) { m_to.insert(_a); return *this; } |
||||
|
MessageFilter altered(Address _a, u256 _l) { m_stateAltered.insert(std::make_pair(_a, _l)); return *this; } |
||||
|
MessageFilter altered(Address _a) { m_altered.insert(_a); return *this; } |
||||
|
MessageFilter withMax(unsigned _m) { m_max = _m; return *this; } |
||||
|
MessageFilter withSkip(unsigned _m) { m_skip = _m; return *this; } |
||||
|
MessageFilter withEarliest(int _e) { m_earliest = _e; return *this; } |
||||
|
MessageFilter withLatest(int _e) { m_latest = _e; return *this; } |
||||
|
|
||||
|
private: |
||||
|
bool matches(Manifest const& _m, std::vector<unsigned> _p, Address _o, PastMessages _limbo, PastMessages& o_ret) const; |
||||
|
|
||||
|
std::set<Address> m_from; |
||||
|
std::set<Address> m_to; |
||||
|
std::set<std::pair<Address, u256>> m_stateAltered; |
||||
|
std::set<Address> m_altered; |
||||
|
int m_earliest = 0; |
||||
|
int m_latest = -1; |
||||
|
unsigned m_max; |
||||
|
unsigned m_skip; |
||||
|
}; |
||||
|
|
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
/*
|
||||
|
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 PastMessage.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include "PastMessage.h" |
||||
|
using namespace std; |
||||
|
using namespace eth; |
@ -0,0 +1,53 @@ |
|||||
|
/*
|
||||
|
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 PastMessage.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <libethential/Common.h> |
||||
|
#include <libethcore/CommonEth.h> |
||||
|
#include "Manifest.h" |
||||
|
|
||||
|
namespace eth |
||||
|
{ |
||||
|
|
||||
|
struct PastMessage |
||||
|
{ |
||||
|
PastMessage(Manifest const& _m, std::vector<unsigned> _path, Address _o): to(_m.to), from(_m.from), value(_m.value), input(_m.input), output(_m.output), path(_path), origin(_o) {} |
||||
|
|
||||
|
PastMessage& polish(h256 _b, u256 _ts, unsigned _n, Address _coinbase) { block = _b; timestamp = _ts; number = _n; coinbase = _coinbase; return *this; } |
||||
|
|
||||
|
Address to; ///< The receiving address of the transaction. Address() in the case of a creation.
|
||||
|
Address from; ///< The receiving address of the transaction. Address() in the case of a creation.
|
||||
|
u256 value; ///< The value associated with the call.
|
||||
|
bytes input; ///< The data associated with the message, or the initialiser if it's a creation transaction.
|
||||
|
bytes output; ///< The data returned by the message, or the body code if it's a creation transaction.
|
||||
|
|
||||
|
std::vector<unsigned> path; ///< Call path into the block transaction. size() is always > 0. First item is the transaction index in the block.
|
||||
|
Address origin; ///< Originating sender of the transaction.
|
||||
|
Address coinbase; ///< Block coinbase.
|
||||
|
h256 block; ///< Block hash.
|
||||
|
u256 timestamp; ///< Block timestamp.
|
||||
|
unsigned number; ///< Block number.
|
||||
|
}; |
||||
|
|
||||
|
typedef std::vector<PastMessage> PastMessages; |
||||
|
|
||||
|
} |
Loading…
Reference in new issue