diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp
index 210649edb..046b8973a 100644
--- a/alethzero/DownloadView.cpp
+++ b/alethzero/DownloadView.cpp
@@ -30,29 +30,118 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
-DownloadView::DownloadView(QWidget* _p): QWidget(_p)
+SyncView::SyncView(QWidget* _p): QWidget(_p)
{
}
-void DownloadView::paintEvent(QPaintEvent*)
+void SyncView::paintEvent(QPaintEvent*)
{
QPainter p(this);
-
p.fillRect(rect(), Qt::white);
- if (!m_man || m_man->chainEmpty() || !m_man->subCount())
+
+ if (!m_client)
+ return;
+
+ DownloadMan const* man = m_client->downloadMan();
+ BlockQueueStatus bqs = m_client->blockQueueStatus();
+ SyncStatus sync = m_client->syncStatus();
+
+ unsigned syncFrom = m_client->numberFromHash(PendingBlockHash);
+ unsigned syncImported = syncFrom;
+ unsigned syncImporting = syncImported + bqs.importing;
+ unsigned syncVerified = syncImporting + bqs.verified;
+ unsigned syncVerifying = syncVerified + bqs.verifying;
+ unsigned syncUnverified = syncVerifying + bqs.unverified;
+ unsigned syncCount = syncUnverified + bqs.unknown - syncFrom;
+
+ // best effort guess. assumes there's no forks.
+ unsigned downloadFrom = m_client->numberFromHash(m_client->isKnown(man->firstBlock()) ? man->firstBlock() : PendingBlockHash);
+ unsigned downloadCount = sync.blocksTotal;
+ DownloadMan::Overview overview = man->overview();
+ unsigned downloadDone = downloadFrom + overview.total;
+ unsigned downloadFlank = downloadFrom + overview.firstIncomplete;
+ unsigned downloadPoint = downloadFrom + overview.lastComplete;
+
+ unsigned hashFrom = sync.state == SyncState::Hashes ? m_client->numberFromHash(PendingBlockHash) : downloadFrom;
+ unsigned hashCount = sync.state == SyncState::Hashes ? sync.hashesTotal : downloadCount;
+ unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount);
+
+ m_lastFrom = min(syncFrom, m_lastFrom);
+ m_lastTo = max(max(syncFrom + syncCount, hashFrom + hashCount), m_lastTo);
+ unsigned from = min(min(hashFrom, downloadFrom), min(syncFrom, m_lastFrom));
+ unsigned count = max(max(hashFrom + hashCount, downloadFrom + downloadCount), max(syncFrom + syncCount, m_lastTo)) - from;
+ m_lastFrom = (m_lastFrom * 99 + syncFrom * 1) / 100;
+ m_lastTo = (m_lastTo * 99 + max(syncFrom + syncCount, hashFrom + hashCount) * 1) / 100;
+
+ if (!count)
+ {
+ m_lastFrom = m_lastTo = (unsigned)-1;
return;
+ }
+
+ cnote << "Range " << from << "-" << (from + count) << "(" << hashFrom << "+" << hashCount << "," << downloadFrom << "+" << downloadCount << "," << syncFrom << "+" << syncCount << ")";
+ auto r = [&](unsigned u) {
+ return toString((u - from) * 100 / count) + "%";
+ };
+
+ if (count)
+ {
+ cnote << "Hashes:" << r(hashDone) << " Blocks:" << r(downloadFlank) << r(downloadDone) << r(downloadPoint);
+ cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified);
+ }
+
+ float squareSize = min(rect().width(), rect().height());
+ QPen pen;
+ pen.setCapStyle(Qt::FlatCap);
+ pen.setWidthF(squareSize / 20);
+ auto middle = [&](float x) {
+ return QRectF(squareSize / 2 - squareSize / 2 * x, 0 + squareSize / 2 - squareSize / 2 * x, squareSize * x, squareSize * x);
+ };
+
+ auto arcLen = [&](unsigned x) {
+ return x * -5760.f / count;
+ };
+ auto arcPos = [&](unsigned x) {
+ return int(90 * 16.f + arcLen(x - from)) % 5760;
+ };
+
+ p.setPen(Qt::NoPen);
+ p.setBrush(QColor::fromHsv(0, 0, 210));
+ pen.setWidthF(0.f);
+ p.drawPie(middle(0.4f), arcPos(from), arcLen(hashDone - from));
+
+ auto progress = [&](unsigned h, unsigned s, unsigned v, float size, float thickness, unsigned nfrom, unsigned ncount) {
+ p.setBrush(Qt::NoBrush);
+ pen.setColor(QColor::fromHsv(h, s, v));
+ pen.setWidthF(squareSize * thickness);
+ p.setPen(pen);
+ p.drawArc(middle(size), arcPos(nfrom), arcLen(ncount));
+ };
+
+ progress(0, 50, 170, 0.4f, 0.12f, downloadFlank, downloadPoint - downloadFlank);
+ progress(0, 0, 150, 0.4f, 0.10f, from, downloadDone - from);
+
+ progress(0, 0, 230, 0.7f, 0.090f, from, syncUnverified - from);
+ progress(60, 25, 210, 0.7f, 0.08f, from, syncVerifying - from);
+ progress(120, 25, 190, 0.7f, 0.07f, from, syncVerified - from);
+
+ progress(0, 0, 220, 0.9f, 0.02f, from, count);
+ progress(0, 0, 100, 0.9f, 0.04f, from, syncFrom - from);
+ progress(0, 50, 100, 0.9f, 0.08f, syncFrom, syncImporting - syncFrom);
+
+ return;
double ratio = (double)rect().width() / rect().height();
if (ratio < 1)
ratio = 1 / ratio;
- double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(m_man->chainSize() / ratio)));
+ double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(man->chainSize() / ratio)));
// QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n));
QSizeF area(n, n);
QPointF pos(0, 0);
- auto bg = m_man->blocksGot();
- unsigned subCount = m_man->subCount();
+ auto bg = man->blocksGot();
+ unsigned subCount = man->subCount();
if (subCount == 0)
return;
unsigned dh = 360 / subCount;
@@ -64,7 +153,7 @@ void DownloadView::paintEvent(QPaintEvent*)
else
{
unsigned h = 0;
- m_man->foreachSub([&](DownloadSub const& sub)
+ man->foreachSub([&](DownloadSub const& sub)
{
if (sub.askedContains(i))
s = h;
diff --git a/alethzero/DownloadView.h b/alethzero/DownloadView.h
index d0fc445f8..71fc41f3f 100644
--- a/alethzero/DownloadView.h
+++ b/alethzero/DownloadView.h
@@ -32,21 +32,24 @@
#endif
namespace dev { namespace eth {
-class DownloadMan;
+class Client;
}}
-class DownloadView: public QWidget
+class SyncView: public QWidget
{
Q_OBJECT
public:
- DownloadView(QWidget* _p = nullptr);
+ SyncView(QWidget* _p = nullptr);
- void setDownloadMan(dev::eth::DownloadMan const* _man) { m_man = _man; }
+ void setEthereum(dev::eth::Client const* _c) { m_client = _c; }
protected:
virtual void paintEvent(QPaintEvent*);
private:
- dev::eth::DownloadMan const* m_man = nullptr;
+ dev::eth::Client const* m_client = nullptr;
+
+ unsigned m_lastFrom = (unsigned)-1;
+ unsigned m_lastTo = (unsigned)-1;
};
diff --git a/alethzero/Main.ui b/alethzero/Main.ui
index b2e3a9a29..97853e174 100644
--- a/alethzero/Main.ui
+++ b/alethzero/Main.ui
@@ -199,6 +199,7 @@
+
@@ -1804,6 +1805,11 @@ font-size: 14pt
&Sentinel...
+
+
+ &Rewind Chain...
+
+
@@ -1814,7 +1820,7 @@ font-size: 14pt
1
- DownloadView
+ SyncView
QWidget
1
diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index bc569c5cf..60c07fd8d 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -1044,6 +1044,17 @@ void Main::on_vmInterpreter_triggered() { VMFactory::setKind(VMKind::Interpreter
void Main::on_vmJIT_triggered() { VMFactory::setKind(VMKind::JIT); }
void Main::on_vmSmart_triggered() { VMFactory::setKind(VMKind::Smart); }
+void Main::on_rewindChain_triggered()
+{
+ bool ok;
+ int n = QInputDialog::getInt(this, "Rewind Chain", "Enter the number of the new chain head.", ethereum()->number() * 9 / 10, 1, ethereum()->number(), 1, &ok);
+ if (ok)
+ {
+ ethereum()->rewind(n);
+ refreshAll();
+ }
+}
+
void Main::on_urlEdit_returnPressed()
{
QString s = ui->urlEdit->text();
@@ -1993,12 +2004,12 @@ void Main::on_net_triggered()
web3()->setNetworkPreferences(netPrefs(), ui->dropPeers->isChecked());
ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : h256());
web3()->startNetwork();
- ui->downloadView->setDownloadMan(ethereum()->downloadMan());
+ ui->downloadView->setEthereum(ethereum());
ui->enode->setText(QString::fromStdString(web3()->enode()));
}
else
{
- ui->downloadView->setDownloadMan(nullptr);
+ ui->downloadView->setEthereum(nullptr);
writeSettings();
web3()->stopNetwork();
}
diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h
index b1939534b..0e944b042 100644
--- a/alethzero/MainWin.h
+++ b/alethzero/MainWin.h
@@ -187,6 +187,7 @@ private slots:
void on_vmInterpreter_triggered();
void on_vmJIT_triggered();
void on_vmSmart_triggered();
+ void on_rewindChain_triggered();
// Debugger
void on_debugCurrent_triggered();
diff --git a/exp/main.cpp b/exp/main.cpp
index 1db9b4267..88608f8cf 100644
--- a/exp/main.cpp
+++ b/exp/main.cpp
@@ -135,7 +135,7 @@ int main()
DownloadSub s0(man);
DownloadSub s1(man);
DownloadSub s2(man);
- man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)}));
+ man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)}), 0);
assert((s0.nextFetch(2) == h256Set{(u256)7, (u256)8}));
assert((s1.nextFetch(2) == h256Set{(u256)5, (u256)6}));
assert((s2.nextFetch(2) == h256Set{(u256)3, (u256)4}));
diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h
index 09bc3393b..a9922063a 100644
--- a/libdevcore/FixedHash.h
+++ b/libdevcore/FixedHash.h
@@ -24,6 +24,7 @@
#pragma once
#include
+#include
#include
#include
#include "CommonData.h"
@@ -151,7 +152,7 @@ public:
{
FixedHash ret;
for (auto& i: ret.m_data)
- i = std::uniform_int_distribution(0, 255)(_eng);
+ i = (uint8_t)std::uniform_int_distribution(0, 255)(_eng);
return ret;
}
diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h
index eccc8305d..6c32517f5 100644
--- a/libdevcore/RangeMask.h
+++ b/libdevcore/RangeMask.h
@@ -200,6 +200,20 @@ public:
return c;
}
+ size_t firstOut() const
+ {
+ if (m_ranges.empty() || !m_ranges.count(m_all.first))
+ return m_all.first;
+ return m_ranges.at(m_all.first);
+ }
+
+ size_t lastIn() const
+ {
+ if (m_ranges.empty())
+ return m_all.first;
+ return m_ranges.rbegin()->second - 1;
+ }
+
private:
/// The ground range.
UnsignedRange m_all;
diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp
index 8bf95d02f..186c6ce06 100644
--- a/libdevcrypto/Common.cpp
+++ b/libdevcrypto/Common.cpp
@@ -22,6 +22,7 @@
#include "Common.h"
#include
+#include
#include
#include
#include
@@ -262,16 +263,9 @@ bytes dev::scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uin
KeyPair KeyPair::create()
{
- static boost::thread_specific_ptr s_eng;
- static unsigned s_id = 0;
- if (!s_eng.get())
- s_eng.reset(new mt19937_64(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count() + ++s_id));
-
- uniform_int_distribution d(0, 255);
-
for (int i = 0; i < 100; ++i)
{
- KeyPair ret(FixedHash<32>::random(*s_eng.get()));
+ KeyPair ret(FixedHash<32>::random());
if (ret.address())
return ret;
}
@@ -353,7 +347,7 @@ void Nonce::initialiseIfNeeded()
std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count());
std::uniform_int_distribution d(0, 255);
for (unsigned i = 0; i < 32; ++i)
- m_value[i] = byte(d(s_eng));
+ m_value[i] = (uint8_t)d(s_eng);
}
if (!m_value)
BOOST_THROW_EXCEPTION(InvalidState());
diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp
index bf4eaf4d0..719ec016e 100644
--- a/libethereum/BlockChain.cpp
+++ b/libethereum/BlockChain.cpp
@@ -799,6 +799,25 @@ void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end)
}
}
+void BlockChain::rewind(unsigned _newHead)
+{
+ DEV_WRITE_GUARDED(x_lastBlockHash)
+ {
+ if (_newHead >= m_lastBlockNumber)
+ return;
+ m_lastBlockHash = numberHash(_newHead);
+ m_lastBlockNumber = _newHead;
+ auto o = m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&m_lastBlockHash, 32));
+ if (!o.ok())
+ {
+ cwarn << "Error writing to extras database: " << o.ToString();
+ cout << "Put" << toHex(bytesConstRef(ldb::Slice("best"))) << "=>" << toHex(bytesConstRef(ldb::Slice((char const*)&m_lastBlockHash, 32)));
+ cwarn << "Fail writing to extras database. Bombing out.";
+ exit(-1);
+ }
+ }
+}
+
tuple BlockChain::treeRoute(h256 const& _from, h256 const& _to, bool _common, bool _pre, bool _post) const
{
// cdebug << "treeRoute" << _from << "..." << _to;
@@ -1070,7 +1089,8 @@ bool BlockChain::isKnown(h256 const& _hash) const
if (d.empty())
return false;
}
- return true;
+// return true;
+ return details(_hash).number <= m_lastBlockNumber; // to allow rewind functionality.
}
bytes BlockChain::block(h256 const& _hash) const
diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h
index 4cffca2df..1d88430b0 100644
--- a/libethereum/BlockChain.h
+++ b/libethereum/BlockChain.h
@@ -215,6 +215,9 @@ public:
/// Will call _progress with the progress in this operation first param done, second total.
void rebuild(std::string const& _path, ProgressCallback const& _progress = std::function(), bool _prepPoW = false);
+ /// Alter the head of the chain to some prior block along it.
+ void rewind(unsigned _newHead);
+
/** @returns a tuple of:
* - an vector of hashes of all blocks between @a _from and @a _to, all blocks are ordered first by a number of
* blocks that are parent-to-child, then two sibling blocks, then a number of blocks that are child-to-parent;
diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp
index e22f10880..5dd1a97cb 100644
--- a/libethereum/BlockChainSync.cpp
+++ b/libethereum/BlockChainSync.cpp
@@ -80,7 +80,7 @@ DownloadMan& BlockChainSync::downloadMan()
void BlockChainSync::abortSync()
{
- downloadMan().resetToChain(h256s());
+ downloadMan().reset();
}
void BlockChainSync::onPeerStatus(std::shared_ptr _peer)
diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp
index 5e0a523d8..f95a3880e 100644
--- a/libethereum/BlockQueue.cpp
+++ b/libethereum/BlockQueue.cpp
@@ -215,8 +215,10 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
return ImportResult::Malformed;
}
+ clog(BlockQueueTraceChannel) << "Block" << h << "is" << bi.number << "parent is" << bi.parentHash;
+
// Check block doesn't already exist first!
- if (_bc.details(h))
+ if (_bc.isKnown(h))
{
cblockq << "Already known in chain.";
return ImportResult::AlreadyInChain;
diff --git a/libethereum/Client.h b/libethereum/Client.h
index 829ec77c1..fac54b010 100644
--- a/libethereum/Client.h
+++ b/libethereum/Client.h
@@ -217,6 +217,8 @@ public:
std::string const& sentinel() const { return m_sentinel; }
/// Set the extra data that goes into mined blocks.
void setExtraData(bytes const& _extraData) { m_extraData = _extraData; }
+ /// Rewind to a prior head.
+ void rewind(unsigned _n) { m_bc.rewind(_n); }
protected:
/// InterfaceStub methods
diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp
index 2cef62680..f463b0195 100644
--- a/libethereum/ClientBase.cpp
+++ b/libethereum/ClientBase.cpp
@@ -45,7 +45,7 @@ State ClientBase::asOf(BlockNumber _h) const
return asOf(bc().numberHash(_h));
}
-h256 ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& _secret)
+pair ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& _secret)
{
prepareForTransaction();
@@ -59,7 +59,7 @@ h256 ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const&
StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged());
cnote << "New transaction " << t;
- return t.sha3();
+ return make_pair(t.sha3(), toAddress(ts.from, ts.nonce));
}
// TODO: remove try/catch, allow exceptions
diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h
index 05766b3a1..82f03def0 100644
--- a/libethereum/ClientBase.h
+++ b/libethereum/ClientBase.h
@@ -77,7 +77,7 @@ public:
/// Submits the given transaction.
/// @returns the new transaction's hash.
- virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override;
+ virtual std::pair submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override;
using Interface::submitTransaction;
/// Makes the given call. Nothing is recorded into the state.
diff --git a/libethereum/DownloadMan.cpp b/libethereum/DownloadMan.cpp
index 5e68e3c49..a9d353292 100644
--- a/libethereum/DownloadMan.cpp
+++ b/libethereum/DownloadMan.cpp
@@ -24,6 +24,16 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
+DownloadMan::Overview DownloadMan::overview() const
+{
+ ReadGuard l(m_lock);
+ Overview ret;
+ ret.firstIncomplete = m_blocksGot.firstOut();
+ ret.lastComplete = ret.lastStarted = m_blocksGot.lastIn();// TODO: lastStarted properly
+ ret.total = m_blocksGot.size();
+ return ret;
+}
+
DownloadSub::DownloadSub(DownloadMan& _man): m_man(&_man)
{
WriteGuard l(m_man->x_subs);
diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h
index ac99e1d36..b697d87ae 100644
--- a/libethereum/DownloadMan.h
+++ b/libethereum/DownloadMan.h
@@ -82,6 +82,14 @@ class DownloadMan
friend class DownloadSub;
public:
+ struct Overview
+ {
+ size_t total;
+ size_t firstIncomplete;
+ size_t lastComplete;
+ size_t lastStarted;
+ };
+
~DownloadMan()
{
for (auto i: m_subs)
@@ -97,11 +105,9 @@ public:
void resetToChain(h256s const& _chain)
{
- {
- ReadGuard l(x_subs);
+ DEV_READ_GUARDED(x_subs)
for (auto i: m_subs)
i->resetFetch();
- }
WriteGuard l(m_lock);
m_chain.clear();
m_chain.reserve(_chain.size());
@@ -112,11 +118,9 @@ public:
void reset()
{
- {
- ReadGuard l(x_subs);
+ DEV_READ_GUARDED(x_subs)
for (auto i: m_subs)
i->resetFetch();
- }
WriteGuard l(m_lock);
m_chain.clear();
m_blocksGot.reset();
@@ -127,11 +131,9 @@ public:
ReadGuard l(m_lock);
auto ret = m_blocksGot;
if (!_desperate)
- {
- ReadGuard l(x_subs);
- for (auto i: m_subs)
- ret += i->m_asked;
- }
+ DEV_READ_GUARDED(x_subs)
+ for (auto i: m_subs)
+ ret += i->m_asked;
return ret;
}
@@ -144,12 +146,15 @@ public:
h256s remaining() const
{
h256s ret;
- ReadGuard l(m_lock);
- for (auto i: m_blocksGot.inverted())
- ret.push_back(m_chain[i]);
+ DEV_READ_GUARDED(m_lock)
+ for (auto i: m_blocksGot.inverted())
+ ret.push_back(m_chain[i]);
return ret;
}
+ h256 firstBlock() const { return m_chain.empty() ? h256() : m_chain[0]; }
+ Overview overview() const;
+
size_t chainSize() const { ReadGuard l(m_lock); return m_chain.size(); }
size_t chainEmpty() const { ReadGuard l(m_lock); return m_chain.empty(); }
void foreachSub(std::function const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); }
diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp
index 186eb6fa8..f00ec7dc7 100644
--- a/libethereum/EthereumHost.cpp
+++ b/libethereum/EthereumHost.cpp
@@ -45,6 +45,12 @@ static unsigned const c_maxSendTransactions = 256;
char const* const EthereumHost::s_stateNames[static_cast(SyncState::Size)] = {"Idle", "Waiting", "Hashes", "Blocks", "NewBlocks" };
+#ifdef _WIN32
+const char* EthereumHostTrace::name() { return EthPurple "^" EthGray " "; }
+#else
+const char* EthereumHostTrace::name() { return EthPurple "⧫" EthGray " "; }
+#endif
+
EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId):
HostCapability(),
Worker ("ethsync"),
@@ -67,7 +73,7 @@ bool EthereumHost::ensureInitialised()
{
// First time - just initialise.
m_latestBlockSent = m_chain.currentHash();
- clog(NetNote) << "Initialising: latest=" << m_latestBlockSent;
+ clog(EthereumHostTrace) << "Initialising: latest=" << m_latestBlockSent;
Guard l(x_transactions);
m_transactionsSent = m_tq.knownTransactions();
@@ -150,7 +156,7 @@ void EthereumHost::maintainTransactions()
RLPStream ts;
_p->prep(ts, TransactionsPacket, n).appendRaw(b, n);
_p->sealAndSend(ts);
- cnote << "Sent" << n << "transactions to " << _p->session()->info().clientVersion;
+ clog(EthereumHostTrace) << "Sent" << n << "transactions to " << _p->session()->info().clientVersion;
}
_p->m_requireTransactions = false;
return true;
@@ -206,11 +212,15 @@ void EthereumHost::maintainBlocks(h256 const& _currentHash)
if (diff(detailsFrom.number, detailsTo.number) < 20)
{
// don't be sending more than 20 "new" blocks. if there are any more we were probably waaaay behind.
- clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")";
+ clog(EthereumHostTrace) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")";
h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true));
- auto s = randomSelection(25, [&](EthereumPeer* p){ DEV_GUARDED(p->x_knownBlocks) return !p->m_knownBlocks.count(_currentHash); return false; });
+ auto s = randomSelection(25, [&](EthereumPeer* p){
+ DEV_GUARDED(p->x_knownBlocks)
+ return !p->m_knownBlocks.count(_currentHash);
+ return false;
+ });
for (shared_ptr const& p: get<0>(s))
for (auto const& b: blocks)
{
@@ -292,11 +302,11 @@ void EthereumHost::onPeerTransactions(std::shared_ptr _peer, RLP c
{
if (_peer->isCriticalSyncing())
{
- clog(NetAllDetail) << "Ignoring transaction from peer we are syncing with";
+ clog(EthereumHostTrace) << "Ignoring transaction from peer we are syncing with";
return;
}
unsigned itemCount = _r.itemCount();
- clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)";
+ clog(EthereumHostTrace) << "Transactions (" << dec << itemCount << "entries)";
m_tq.enqueue(_r, _peer->session()->id());
}
@@ -351,10 +361,8 @@ void EthereumHost::onTransactionImported(ImportResult _ir, h256 const& _h, h512
break;
case ImportResult::AlreadyKnown:
// if we already had the transaction, then don't bother sending it on.
- {
- Guard l(x_transactions);
+ DEV_GUARDED(x_transactions)
m_transactionsSent.insert(_h);
- }
peer->addRating(0);
break;
case ImportResult::Success:
diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h
index b65ddb5d0..6cb82ebb4 100644
--- a/libethereum/EthereumHost.h
+++ b/libethereum/EthereumHost.h
@@ -49,6 +49,8 @@ class TransactionQueue;
class BlockQueue;
class BlockChainSync;
+struct EthereumHostTrace: public LogChannel { static const char* name(); static const int verbosity = 6; };
+
/**
* @brief The EthereumHost class
* @warning None of this is thread-safe. You have been warned.
diff --git a/libethereum/Interface.cpp b/libethereum/Interface.cpp
index efa304bd5..e95e03a45 100644
--- a/libethereum/Interface.cpp
+++ b/libethereum/Interface.cpp
@@ -46,6 +46,5 @@ Address Interface::submitTransaction(Secret const& _secret, u256 const& _endowme
ts.gas = _gas;
ts.gasPrice = _gasPrice;
ts.nonce = _nonce;
- submitTransaction(ts, _secret);
- return toAddress(toAddress(_secret), _nonce);
+ return submitTransaction(ts, _secret).second;
}
diff --git a/libethereum/Interface.h b/libethereum/Interface.h
index c65670a30..973433af9 100644
--- a/libethereum/Interface.h
+++ b/libethereum/Interface.h
@@ -67,7 +67,7 @@ public:
/// Submits a new transaction.
/// @returns the transaction's hash.
- virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0;
+ virtual std::pair submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0;
/// Submits the given message-call transaction.
void submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data = bytes(), u256 const& _gas = 10000, u256 const& _gasPrice = 10 * szabo, u256 const& _nonce = UndefinedU256);
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 8ba3b438a..bc87be4ab 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -1212,7 +1212,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per
uncommitToMine();
// OK - transaction looks valid - execute.
- u256 startGasUsed = gasUsed();
+ u256 startGasUsed = e.gasUsed();
#if ETH_PARANOIA
ctrace << "Executing" << e.t() << "on" << h;
ctrace << toHex(e.t().rlp());
@@ -1262,7 +1262,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per
// Add to the user-originated transactions that we've executed.
m_transactions.push_back(e.t());
- m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + (m_currentBlock.number >= 830000 ? e.gasUsedNoRefunds() : e.gasUsed()), e.logs()));
+ m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsed(), e.logs()));
m_transactionSet.insert(e.t().sha3());
}
diff --git a/libweb3jsonrpc/AccountHolder.cpp b/libweb3jsonrpc/AccountHolder.cpp
index f4b3a9f9f..43a7073d2 100644
--- a/libweb3jsonrpc/AccountHolder.cpp
+++ b/libweb3jsonrpc/AccountHolder.cpp
@@ -109,7 +109,7 @@ AddressHash SimpleAccountHolder::realAccounts() const
h256 SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t)
{
if (isRealAccount(_t.from))
- return m_client()->submitTransaction(_t, m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); }));
+ return m_client()->submitTransaction(_t, m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); })).first;
else if (isProxyAccount(_t.from))
queueTransaction(_t);
return h256();
@@ -118,7 +118,7 @@ h256 SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t)
h256 FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t)
{
if (isRealAccount(_t.from))
- return m_client()->submitTransaction(_t, m_accounts[_t.from]);
+ return m_client()->submitTransaction(_t, m_accounts[_t.from]).first;
else if (isProxyAccount(_t.from))
queueTransaction(_t);
return h256();
diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp
index 23f68996c..90ff19feb 100644
--- a/mix/ClientModel.cpp
+++ b/mix/ClientModel.cpp
@@ -674,8 +674,7 @@ void ClientModel::debugRecord(unsigned _index)
Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction)
{
- m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto);
- return m_client->lastCreatedContractAddr();
+ return m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto);
}
void ClientModel::callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr)
diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp
index c41661046..c73763076 100644
--- a/mix/MixClient.cpp
+++ b/mix/MixClient.cpp
@@ -303,20 +303,14 @@ State MixClient::asOf(h256 const& _block) const
return ret;
}
-h256 MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto)
+pair MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto)
{
WriteGuard l(x_state);
TransactionSkeleton ts = _ts;
ts.nonce = m_state.transactionsFrom(toAddress(_secret));
eth::Transaction t(ts, _secret);
executeTransaction(t, m_state, false, _gasAuto, _secret);
- return t.sha3();
-}
-
-Address MixClient::lastCreatedContractAddr() const
-{
- Transaction tr = m_state.pending().back();
- return tr.isCreation() ? right160(sha3(rlpList(tr.sender(), tr.nonce()))) : Address();
+ return make_pair(t.sha3(), toAddress(ts.from, ts.nonce));
}
dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff)
diff --git a/mix/MixClient.h b/mix/MixClient.h
index 5b1b155a1..f9574e90a 100644
--- a/mix/MixClient.h
+++ b/mix/MixClient.h
@@ -58,8 +58,8 @@ public:
dev::eth::ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override;
using ClientBase::submitTransaction;
- virtual h256 submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret) override { return submitTransaction(_ts, _secret, false); }
- h256 submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto);
+ virtual std::pair submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret) override { return submitTransaction(_ts, _secret, false); }
+ std::pair submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto);
dev::eth::ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict);
void setAddress(Address _us) override;
diff --git a/neth/main.cpp b/neth/main.cpp
index d5cb4bb4b..5ec253440 100644
--- a/neth/main.cpp
+++ b/neth/main.cpp
@@ -1057,9 +1057,7 @@ int main(int argc, char** argv)
else if (gas < minGas)
cwarn << "Minimum gas amount is" << minGas;
else
- {
c->submitTransaction(us.secret(), endowment, init, gas);
- }
}
}
else if (c && cmd == "inspect")