Gav Wood
10 years ago
9 changed files with 652 additions and 825 deletions
@ -0,0 +1,393 @@ |
|||||
|
/*
|
||||
|
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 ClientBase.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @author Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#include <libdevcore/StructuredLogger.h> |
||||
|
#include "ClientBase.h" |
||||
|
#include "BlockChain.h" |
||||
|
#include "Executive.h" |
||||
|
|
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
|
||||
|
void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) |
||||
|
{ |
||||
|
prepareForTransaction(); |
||||
|
|
||||
|
u256 n = postMine().transactionsFrom(toAddress(_secret)); |
||||
|
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); |
||||
|
m_tq.attemptImport(t.rlp()); |
||||
|
|
||||
|
StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); |
||||
|
cnote << "New transaction " << t; |
||||
|
} |
||||
|
|
||||
|
Address ClientBase::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) |
||||
|
{ |
||||
|
prepareForTransaction(); |
||||
|
|
||||
|
u256 n = postMine().transactionsFrom(toAddress(_secret)); |
||||
|
Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret); |
||||
|
m_tq.attemptImport(t.rlp()); |
||||
|
|
||||
|
StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); |
||||
|
cnote << "New transaction " << t; |
||||
|
|
||||
|
return right160(sha3(rlpList(t.sender(), t.nonce()))); |
||||
|
} |
||||
|
|
||||
|
// TODO: remove try/catch, allow exceptions
|
||||
|
ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) |
||||
|
{ |
||||
|
ExecutionResult ret; |
||||
|
try |
||||
|
{ |
||||
|
State temp = asOf(_blockNumber); |
||||
|
u256 n = temp.transactionsFrom(toAddress(_secret)); |
||||
|
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); |
||||
|
ret = temp.execute(bc(), t.rlp(), Permanence::Reverted); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
// TODO: Some sort of notification of failure.
|
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) |
||||
|
{ |
||||
|
ExecutionResult ret; |
||||
|
try |
||||
|
{ |
||||
|
State temp = asOf(_blockNumber); |
||||
|
u256 n = temp.transactionsFrom(toAddress(_secret)); |
||||
|
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
|
||||
|
|
||||
|
Transaction t(_value, _gasPrice, _gas, _data, n, _secret); |
||||
|
ret = temp.execute(bc(), t.rlp(), Permanence::Reverted); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
// TODO: Some sort of notification of failure.
|
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
u256 ClientBase::balanceAt(Address _a, BlockNumber _block) const |
||||
|
{ |
||||
|
return asOf(_block).balance(_a); |
||||
|
} |
||||
|
|
||||
|
u256 ClientBase::countAt(Address _a, BlockNumber _block) const |
||||
|
{ |
||||
|
return asOf(_block).transactionsFrom(_a); |
||||
|
} |
||||
|
|
||||
|
u256 ClientBase::stateAt(Address _a, u256 _l, BlockNumber _block) const |
||||
|
{ |
||||
|
return asOf(_block).storage(_a, _l); |
||||
|
} |
||||
|
|
||||
|
bytes ClientBase::codeAt(Address _a, BlockNumber _block) const |
||||
|
{ |
||||
|
return asOf(_block).code(_a); |
||||
|
} |
||||
|
|
||||
|
map<u256, u256> ClientBase::storageAt(Address _a, BlockNumber _block) const |
||||
|
{ |
||||
|
return asOf(_block).storage(_a); |
||||
|
} |
||||
|
|
||||
|
// TODO: remove try/catch, allow exceptions
|
||||
|
LocalisedLogEntries ClientBase::logs(unsigned _watchId) const |
||||
|
{ |
||||
|
LogFilter f; |
||||
|
try |
||||
|
{ |
||||
|
Guard l(m_filterLock); |
||||
|
f = m_filters.at(m_watches.at(_watchId).id).filter; |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
return LocalisedLogEntries(); |
||||
|
} |
||||
|
return logs(f); |
||||
|
} |
||||
|
|
||||
|
LocalisedLogEntries ClientBase::logs(LogFilter const& _f) const |
||||
|
{ |
||||
|
LocalisedLogEntries ret; |
||||
|
unsigned begin = min<unsigned>(bc().number() + 1, (unsigned)_f.latest()); |
||||
|
unsigned end = min(bc().number(), min(begin, (unsigned)_f.earliest())); |
||||
|
|
||||
|
// Handle pending transactions differently as they're not on the block chain.
|
||||
|
if (begin > bc().number()) |
||||
|
{ |
||||
|
State temp = postMine(); |
||||
|
for (unsigned i = 0; i < temp.pending().size(); ++i) |
||||
|
{ |
||||
|
// Might have a transaction that contains a matching log.
|
||||
|
TransactionReceipt const& tr = temp.receipt(i); |
||||
|
auto th = temp.pending()[i].sha3(); |
||||
|
LogEntries le = _f.matches(tr); |
||||
|
if (le.size()) |
||||
|
for (unsigned j = 0; j < le.size(); ++j) |
||||
|
ret.insert(ret.begin(), LocalisedLogEntry(le[j], begin, th)); |
||||
|
} |
||||
|
begin = bc().number(); |
||||
|
} |
||||
|
|
||||
|
set<unsigned> matchingBlocks; |
||||
|
for (auto const& i: _f.bloomPossibilities()) |
||||
|
for (auto u: bc().withBlockBloom(i, end, begin)) |
||||
|
matchingBlocks.insert(u); |
||||
|
|
||||
|
unsigned falsePos = 0; |
||||
|
for (auto n: matchingBlocks) |
||||
|
{ |
||||
|
int total = 0; |
||||
|
auto h = bc().numberHash(n); |
||||
|
auto receipts = bc().receipts(h).receipts; |
||||
|
for (size_t i = 0; i < receipts.size(); i++) |
||||
|
{ |
||||
|
TransactionReceipt receipt = receipts[i]; |
||||
|
if (_f.matches(receipt.bloom())) |
||||
|
{ |
||||
|
auto info = bc().info(h); |
||||
|
auto th = transaction(info.hash, i).sha3(); |
||||
|
LogEntries le = _f.matches(receipt); |
||||
|
if (le.size()) |
||||
|
{ |
||||
|
total += le.size(); |
||||
|
for (unsigned j = 0; j < le.size(); ++j) |
||||
|
ret.insert(ret.begin(), LocalisedLogEntry(le[j], n, th)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!total) |
||||
|
falsePos++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
cdebug << matchingBlocks.size() << "searched from" << (end - begin) << "skipped; " << falsePos << "false +ves"; |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
unsigned ClientBase::installWatch(LogFilter const& _f, Reaping _r) |
||||
|
{ |
||||
|
h256 h = _f.sha3(); |
||||
|
{ |
||||
|
Guard l(m_filterLock); |
||||
|
if (!m_filters.count(h)) |
||||
|
{ |
||||
|
cwatch << "FFF" << _f << h.abridged(); |
||||
|
m_filters.insert(make_pair(h, _f)); |
||||
|
} |
||||
|
} |
||||
|
return installWatch(h, _r); |
||||
|
} |
||||
|
|
||||
|
unsigned ClientBase::installWatch(h256 _h, Reaping _r) |
||||
|
{ |
||||
|
unsigned ret; |
||||
|
{ |
||||
|
Guard l(m_filterLock); |
||||
|
ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0; |
||||
|
m_watches[ret] = ClientWatch(_h, _r); |
||||
|
cwatch << "+++" << ret << _h.abridged(); |
||||
|
} |
||||
|
auto ch = logs(ret); |
||||
|
if (ch.empty()) |
||||
|
ch.push_back(InitialChange); |
||||
|
{ |
||||
|
Guard l(m_filterLock); |
||||
|
swap(m_watches[ret].changes, ch); |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
bool ClientBase::uninstallWatch(unsigned _i) |
||||
|
{ |
||||
|
cwatch << "XXX" << _i; |
||||
|
|
||||
|
Guard l(m_filterLock); |
||||
|
|
||||
|
auto it = m_watches.find(_i); |
||||
|
if (it == m_watches.end()) |
||||
|
return false; |
||||
|
auto id = it->second.id; |
||||
|
m_watches.erase(it); |
||||
|
|
||||
|
auto fit = m_filters.find(id); |
||||
|
if (fit != m_filters.end()) |
||||
|
if (!--fit->second.refCount) |
||||
|
{ |
||||
|
cwatch << "*X*" << fit->first << ":" << fit->second.filter; |
||||
|
m_filters.erase(fit); |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
LocalisedLogEntries ClientBase::peekWatch(unsigned _watchId) const |
||||
|
{ |
||||
|
Guard l(m_filterLock); |
||||
|
|
||||
|
cwatch << "peekWatch" << _watchId; |
||||
|
auto& w = m_watches.at(_watchId); |
||||
|
cwatch << "lastPoll updated to " << chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); |
||||
|
w.lastPoll = chrono::system_clock::now(); |
||||
|
return w.changes; |
||||
|
} |
||||
|
|
||||
|
LocalisedLogEntries ClientBase::checkWatch(unsigned _watchId) |
||||
|
{ |
||||
|
Guard l(m_filterLock); |
||||
|
LocalisedLogEntries ret; |
||||
|
|
||||
|
cwatch << "checkWatch" << _watchId; |
||||
|
auto& w = m_watches.at(_watchId); |
||||
|
cwatch << "lastPoll updated to " << chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); |
||||
|
std::swap(ret, w.changes); |
||||
|
w.lastPoll = chrono::system_clock::now(); |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
h256 ClientBase::hashFromNumber(unsigned _number) const |
||||
|
{ |
||||
|
return bc().numberHash(_number); |
||||
|
} |
||||
|
|
||||
|
BlockInfo ClientBase::blockInfo(h256 _hash) const |
||||
|
{ |
||||
|
return BlockInfo(bc().block(_hash)); |
||||
|
} |
||||
|
|
||||
|
BlockDetails ClientBase::blockDetails(h256 _hash) const |
||||
|
{ |
||||
|
return bc().details(_hash); |
||||
|
} |
||||
|
|
||||
|
Transaction ClientBase::transaction(h256 _transactionHash) const |
||||
|
{ |
||||
|
return Transaction(bc().transaction(_transactionHash), CheckSignature::Range); |
||||
|
} |
||||
|
|
||||
|
Transaction ClientBase::transaction(h256 _blockHash, unsigned _i) const |
||||
|
{ |
||||
|
auto bl = bc().block(_blockHash); |
||||
|
RLP b(bl); |
||||
|
if (_i < b[1].itemCount()) |
||||
|
return Transaction(b[1][_i].data(), CheckSignature::Range); |
||||
|
else |
||||
|
return Transaction(); |
||||
|
} |
||||
|
|
||||
|
Transactions ClientBase::transactions(h256 _blockHash) const |
||||
|
{ |
||||
|
auto bl = bc().block(_blockHash); |
||||
|
RLP b(bl); |
||||
|
Transactions res; |
||||
|
for (unsigned i = 0; i < b[1].itemCount(); i++) |
||||
|
res.emplace_back(b[1][i].data(), CheckSignature::Range); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
TransactionHashes ClientBase::transactionHashes(h256 _blockHash) const |
||||
|
{ |
||||
|
return bc().transactionHashes(_blockHash); |
||||
|
} |
||||
|
|
||||
|
BlockInfo ClientBase::uncle(h256 _blockHash, unsigned _i) const |
||||
|
{ |
||||
|
auto bl = bc().block(_blockHash); |
||||
|
RLP b(bl); |
||||
|
if (_i < b[2].itemCount()) |
||||
|
return BlockInfo::fromHeader(b[2][_i].data()); |
||||
|
else |
||||
|
return BlockInfo(); |
||||
|
} |
||||
|
|
||||
|
UncleHashes ClientBase::uncleHashes(h256 _blockHash) const |
||||
|
{ |
||||
|
return bc().uncleHashes(_blockHash); |
||||
|
} |
||||
|
|
||||
|
unsigned ClientBase::transactionCount(h256 _blockHash) const |
||||
|
{ |
||||
|
auto bl = bc().block(_blockHash); |
||||
|
RLP b(bl); |
||||
|
return b[1].itemCount(); |
||||
|
} |
||||
|
|
||||
|
unsigned ClientBase::uncleCount(h256 _blockHash) const |
||||
|
{ |
||||
|
auto bl = bc().block(_blockHash); |
||||
|
RLP b(bl); |
||||
|
return b[2].itemCount(); |
||||
|
} |
||||
|
|
||||
|
unsigned ClientBase::number() const |
||||
|
{ |
||||
|
return bc().number(); |
||||
|
} |
||||
|
|
||||
|
Transactions ClientBase::pending() const |
||||
|
{ |
||||
|
return postMine().pending(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
StateDiff ClientBase::diff(unsigned _txi, h256 _block) const |
||||
|
{ |
||||
|
State st = asOf(_block); |
||||
|
return st.fromPending(_txi).diff(st.fromPending(_txi + 1)); |
||||
|
} |
||||
|
|
||||
|
StateDiff ClientBase::diff(unsigned _txi, BlockNumber _block) const |
||||
|
{ |
||||
|
State st = asOf(_block); |
||||
|
return st.fromPending(_txi).diff(st.fromPending(_txi + 1)); |
||||
|
} |
||||
|
|
||||
|
Addresses ClientBase::addresses(BlockNumber _block) const |
||||
|
{ |
||||
|
Addresses ret; |
||||
|
for (auto const& i: asOf(_block).addresses()) |
||||
|
ret.push_back(i.first); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
u256 ClientBase::gasLimitRemaining() const |
||||
|
{ |
||||
|
return postMine().gasLimitRemaining(); |
||||
|
} |
||||
|
|
||||
|
void ClientBase::setAddress(Address _us) |
||||
|
{ |
||||
|
preMine().setAddress(_us); |
||||
|
} |
||||
|
|
||||
|
Address ClientBase::address() const |
||||
|
{ |
||||
|
return preMine().address(); |
||||
|
} |
@ -0,0 +1,164 @@ |
|||||
|
/*
|
||||
|
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 ClientBase.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @author Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <chrono> |
||||
|
#include "Interface.h" |
||||
|
#include "LogFilter.h" |
||||
|
|
||||
|
namespace dev { |
||||
|
|
||||
|
namespace eth { |
||||
|
|
||||
|
struct InstalledFilter |
||||
|
{ |
||||
|
InstalledFilter(LogFilter const& _f): filter(_f) {} |
||||
|
|
||||
|
LogFilter filter; |
||||
|
unsigned refCount = 1; |
||||
|
LocalisedLogEntries changes; |
||||
|
}; |
||||
|
|
||||
|
static const h256 PendingChangedFilter = u256(0); |
||||
|
static const h256 ChainChangedFilter = u256(1); |
||||
|
|
||||
|
static const LogEntry SpecialLogEntry = LogEntry(Address(), h256s(), bytes()); |
||||
|
static const LocalisedLogEntry InitialChange(SpecialLogEntry, 0); |
||||
|
|
||||
|
struct ClientWatch |
||||
|
{ |
||||
|
ClientWatch(): lastPoll(std::chrono::system_clock::now()) {} |
||||
|
explicit ClientWatch(h256 _id, Reaping _r): id(_id), lastPoll(_r == Reaping::Automatic ? std::chrono::system_clock::now() : std::chrono::system_clock::time_point::max()) {} |
||||
|
|
||||
|
h256 id; |
||||
|
LocalisedLogEntries changes = LocalisedLogEntries{ InitialChange }; |
||||
|
mutable std::chrono::system_clock::time_point lastPoll = std::chrono::system_clock::now(); |
||||
|
}; |
||||
|
|
||||
|
struct WatchChannel: public LogChannel { static const char* name() { return "(o)"; } static const int verbosity = 7; }; |
||||
|
#define cwatch dev::LogOutputStream<dev::eth::WatchChannel, true>() |
||||
|
struct WorkInChannel: public LogChannel { static const char* name() { return ">W>"; } static const int verbosity = 16; }; |
||||
|
struct WorkOutChannel: public LogChannel { static const char* name() { return "<W<"; } static const int verbosity = 16; }; |
||||
|
struct WorkChannel: public LogChannel { static const char* name() { return "-W-"; } static const int verbosity = 16; }; |
||||
|
#define cwork dev::LogOutputStream<dev::eth::WorkChannel, true>() |
||||
|
#define cworkin dev::LogOutputStream<dev::eth::WorkInChannel, true>() |
||||
|
#define cworkout dev::LogOutputStream<dev::eth::WorkOutChannel, true>() |
||||
|
|
||||
|
class ClientBase: public dev::eth::Interface |
||||
|
{ |
||||
|
public: |
||||
|
ClientBase() {} |
||||
|
virtual ~ClientBase() {} |
||||
|
|
||||
|
/// Submits the given message-call transaction.
|
||||
|
virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; |
||||
|
|
||||
|
/// Submits a new contract-creation transaction.
|
||||
|
/// @returns the new contract's address (assuming it all goes through).
|
||||
|
virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; |
||||
|
|
||||
|
/// Makes the given call. Nothing is recorded into the state.
|
||||
|
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override; |
||||
|
|
||||
|
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override; |
||||
|
|
||||
|
using Interface::balanceAt; |
||||
|
using Interface::countAt; |
||||
|
using Interface::stateAt; |
||||
|
using Interface::codeAt; |
||||
|
using Interface::storageAt; |
||||
|
|
||||
|
virtual u256 balanceAt(Address _a, BlockNumber _block) const override; |
||||
|
virtual u256 countAt(Address _a, BlockNumber _block) const override; |
||||
|
virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const override; |
||||
|
virtual bytes codeAt(Address _a, BlockNumber _block) const override; |
||||
|
virtual std::map<u256, u256> storageAt(Address _a, BlockNumber _block) const override; |
||||
|
|
||||
|
virtual LocalisedLogEntries logs(unsigned _watchId) const override; |
||||
|
virtual LocalisedLogEntries logs(LogFilter const& _filter) const override; |
||||
|
|
||||
|
/// Install, uninstall and query watches.
|
||||
|
virtual unsigned installWatch(LogFilter const& _filter, Reaping _r = Reaping::Automatic) override; |
||||
|
virtual unsigned installWatch(h256 _filterId, Reaping _r = Reaping::Automatic) override; |
||||
|
virtual bool uninstallWatch(unsigned _watchId) override; |
||||
|
virtual LocalisedLogEntries peekWatch(unsigned _watchId) const override; |
||||
|
virtual LocalisedLogEntries checkWatch(unsigned _watchId) override; |
||||
|
|
||||
|
virtual h256 hashFromNumber(unsigned _number) const override; |
||||
|
virtual eth::BlockInfo blockInfo(h256 _hash) const override; |
||||
|
virtual eth::BlockDetails blockDetails(h256 _hash) const override; |
||||
|
virtual eth::Transaction transaction(h256 _transactionHash) const override; |
||||
|
virtual eth::Transaction transaction(h256 _blockHash, unsigned _i) const override; |
||||
|
virtual eth::Transactions transactions(h256 _blockHash) const override; |
||||
|
virtual eth::TransactionHashes transactionHashes(h256 _blockHash) const override; |
||||
|
virtual eth::BlockInfo uncle(h256 _blockHash, unsigned _i) const override; |
||||
|
virtual eth::UncleHashes uncleHashes(h256 _blockHash) const override; |
||||
|
virtual unsigned transactionCount(h256 _blockHash) const override; |
||||
|
virtual unsigned uncleCount(h256 _blockHash) const override; |
||||
|
virtual unsigned number() const override; |
||||
|
virtual eth::Transactions pending() const override; |
||||
|
|
||||
|
using Interface::diff; |
||||
|
virtual StateDiff diff(unsigned _txi, h256 _block) const override; |
||||
|
virtual StateDiff diff(unsigned _txi, BlockNumber _block) const override; |
||||
|
|
||||
|
using Interface::addresses; |
||||
|
virtual Addresses addresses(BlockNumber _block) const override; |
||||
|
virtual u256 gasLimitRemaining() const override; |
||||
|
|
||||
|
// Set the coinbase address
|
||||
|
virtual void setAddress(Address _us) override; |
||||
|
|
||||
|
/// Get the coinbase address
|
||||
|
virtual Address address() const override; |
||||
|
|
||||
|
/// TODO: consider moving it to a separate interface
|
||||
|
|
||||
|
virtual void setMiningThreads(unsigned _threads) override { (void)_threads; BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::setMiningThreads")); } |
||||
|
virtual unsigned miningThreads() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::miningThreads")); } |
||||
|
virtual void startMining() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::startMining")); } |
||||
|
virtual void stopMining() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::stopMining")); } |
||||
|
virtual bool isMining() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::isMining")); } |
||||
|
virtual eth::MineProgress miningProgress() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::miningProgress")); } |
||||
|
virtual std::pair<h256, u256> getWork() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::getWork")); } |
||||
|
virtual bool submitWork(eth::ProofOfWork::Proof const&) override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::ClientBase::submitWork")); } |
||||
|
|
||||
|
protected: |
||||
|
|
||||
|
virtual BlockChain const& bc() const = 0; |
||||
|
virtual State asOf(BlockNumber _h) const = 0; |
||||
|
virtual State asOf(h256 _h) const = 0; |
||||
|
virtual State preMine() const = 0; |
||||
|
virtual State postMine() const = 0; |
||||
|
virtual void prepareForTransaction() = 0; |
||||
|
|
||||
|
TransactionQueue m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain.
|
||||
|
|
||||
|
// filters
|
||||
|
mutable Mutex m_filterLock; |
||||
|
std::map<h256, InstalledFilter> m_filters; |
||||
|
std::map<unsigned, ClientWatch> m_watches; |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
}} |
Loading…
Reference in new issue