Gav Wood
11 years ago
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