diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp
new file mode 100644
index 000000000..0fe5e1414
--- /dev/null
+++ b/alethzero/DownloadView.cpp
@@ -0,0 +1,40 @@
+/*
+ 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 .
+*/
+/** @file DownloadView.cpp
+ * @author Gav Wood
+ * @date 2014
+ */
+
+#include "DownloadView.h"
+
+#include
+#include
+#include
+#include "Grapher.h"
+
+using namespace std;
+using namespace dev;
+using namespace dev::eth;
+
+DownloadView::DownloadView(QWidget* _p): QWidget(_p)
+{
+}
+
+void DownloadView::paintEvent(QPaintEvent*)
+{
+ QPainter p(this);
+}
diff --git a/alethzero/DownloadView.h b/alethzero/DownloadView.h
new file mode 100644
index 000000000..ea3e05b8f
--- /dev/null
+++ b/alethzero/DownloadView.h
@@ -0,0 +1,49 @@
+/*
+ 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 .
+*/
+/** @file DownloadView.h
+ * @author Gav Wood
+ * @date 2014
+ */
+
+#pragma once
+
+#ifdef Q_MOC_RUN
+#define BOOST_MPL_IF_HPP_INCLUDED
+#endif
+
+#include
+#include
+#ifndef Q_MOC_RUN
+#include
+#endif
+
+namespace dev { namespace eth {
+struct MineInfo;
+}}
+
+class DownloadView: public QWidget
+{
+ Q_OBJECT
+
+public:
+ DownloadView(QWidget* _p = nullptr);
+
+protected:
+ virtual void paintEvent(QPaintEvent*);
+
+private:
+};
diff --git a/alethzero/Main.ui b/alethzero/Main.ui
index aa8a43f1c..7ae434ff5 100644
--- a/alethzero/Main.ui
+++ b/alethzero/Main.ui
@@ -1432,6 +1432,39 @@ font-size: 14pt
+
+
+ QDockWidget::DockWidgetFeatureMask
+
+
+ Blockchain Download
+
+
+ 2
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+
+
&Quit
@@ -1712,6 +1745,12 @@ font-size: 14pt
1
+
+ DownloadView
+ QWidget
+
+ 1
+
destination
diff --git a/eth/main.cpp b/eth/main.cpp
index 69a555904..cebec34e9 100644
--- a/eth/main.cpp
+++ b/eth/main.cpp
@@ -747,7 +747,7 @@ int main(int argc, char** argv)
c.startMining();
while (true)
{
- if (c.blockChain().details().number - n == mining)
+ if (c.isMining() && c.blockChain().details().number - n == mining)
c.stopMining();
this_thread::sleep_for(chrono::milliseconds(100));
}
diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp
index 2b88fc768..03435ad4f 100644
--- a/libethereum/EthereumHost.cpp
+++ b/libethereum/EthereumHost.cpp
@@ -97,7 +97,6 @@ bool EthereumHost::ensureInitialised(TransactionQueue& _tq)
void EthereumHost::noteDoneBlocks()
{
- clog(NetNote) << "Peer given up on blocks fetch.";
if (m_blocksOnWay.empty())
{
// Done our chain-get.
@@ -135,13 +134,15 @@ void EthereumHost::doWork()
void EthereumHost::maintainTransactions(TransactionQueue& _tq, h256 _currentHash)
{
bool resendAll = (_currentHash != m_latestBlockSent);
-
- for (auto it = m_incomingTransactions.begin(); it != m_incomingTransactions.end(); ++it)
- if (_tq.import(&*it))
- {}//ret = true; // just putting a transaction in the queue isn't enough to change the state - it might have an invalid nonce...
- else
- m_transactionsSent.insert(sha3(*it)); // if we already had the transaction, then don't bother sending it on.
- m_incomingTransactions.clear();
+ {
+ lock_guard l(m_incomingLock);
+ for (auto it = m_incomingTransactions.begin(); it != m_incomingTransactions.end(); ++it)
+ if (_tq.import(&*it))
+ {}//ret = true; // just putting a transaction in the queue isn't enough to change the state - it might have an invalid nonce...
+ else
+ m_transactionsSent.insert(sha3(*it)); // if we already had the transaction, then don't bother sending it on.
+ m_incomingTransactions.clear();
+ }
// Send any new transactions.
for (auto const& p: peers())
diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h
index 7c6b4b865..7e2f38230 100644
--- a/libethereum/EthereumHost.h
+++ b/libethereum/EthereumHost.h
@@ -46,6 +46,126 @@ namespace eth
class TransactionQueue;
class BlockQueue;
+using UnsignedRange = std::pair;
+using UnsignedRanges = std::vector;
+
+class RangeMask
+{
+public:
+ RangeMask() {}
+ RangeMask(unsigned _begin, unsigned _end): m_ranges({{_begin, _end}}) {}
+
+ RangeMask& operator+=(RangeMask const& _m)
+ {
+ for (auto const& i: _m.m_ranges)
+ operator+=(i);
+ return *this;
+ }
+ RangeMask& operator+=(UnsignedRange const& _m)
+ {
+ for (auto i = _m.first; i < _m.second;)
+ {
+ // for each number, we find the element equal or next lower. this must contain the value.
+ auto it = m_ranges.lower_bound(i);
+ auto uit = m_ranges.upper_bound(i + 1);
+ if (it == m_ranges.end() || it->second < i)
+ // lower range is too low to merge.
+ // if the next higher range is too high.
+ if (uit == m_ranges.end() || uit->first > _m.second)
+ {
+ // just create a new range
+ m_ranges[i] = _m.second;
+ break;
+ }
+ else
+ {
+ if (uit->first == i)
+ // move i to end of range
+ i = uit->second;
+ else
+ {
+ // merge with the next higher range
+ // move i to end of range
+ i = m_ranges[i] = uit->second;
+ i = uit->second;
+ m_ranges.erase(uit);
+ }
+ }
+ else if (it->second == i)
+ {
+ // if the next higher range is too high.
+ if (uit == m_ranges.end() || uit->first > _m.second)
+ {
+ // merge with the next lower range
+ m_ranges[it->first] = _m.second;
+ break;
+ }
+ else
+ {
+ // merge with both next lower & next higher.
+ i = m_ranges[it->first] = uit->second;
+ m_ranges.erase(uit);
+ }
+ }
+ else
+ i = it->second;
+ }
+ return *this;
+ }
+
+ RangeMask& operator+=(unsigned _i)
+ {
+ return operator+=(UnsignedRange(_i, _i + 1));
+ }
+
+ bool contains(unsigned _i) const
+ {
+ auto it = m_ranges.lower_bound(_i);
+ return it != m_ranges.end() && it->first <= _i && it->second > _i;
+ }
+
+private:
+ std::map m_ranges;
+};
+
+#if 0
+class DownloadSub
+{
+ friend class DownloadMan;
+
+public:
+ h256s nextFetch();
+ void noteBlock(h256 _hash, bytesConstRef _data);
+
+private:
+ void resetFetch(); // Called by DownloadMan when we need to reset the download.
+
+ DownloadMan* m_man;
+
+ Mutex m_fetch;
+ h256s m_fetching;
+ h256s m_activeGet;
+ bool m_killFetch;
+ RangeMask m_attempted;
+};
+
+class DownloadMan
+{
+ friend class DownloadSub;
+
+public:
+ void resetToChain(h256s const& _chain);
+
+private:
+ void cancelFetch(DownloadSub* );
+ void noteBlock(h256 _hash, bytesConstRef _data);
+
+ h256s m_chain;
+ RangeMask m_complete;
+ std::map m_fetching;
+};
+#endif
+
/**
* @brief The EthereumHost class
* @warning None of this is thread-safe. You have been warned.
diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp
index 238bc3d8d..6990e4f59 100644
--- a/libethereum/EthereumPeer.cpp
+++ b/libethereum/EthereumPeer.cpp
@@ -148,14 +148,17 @@ bool EthereumPeer::interpret(RLP const& _r)
break;
}
case TransactionsPacket:
+ {
clogS(NetMessageSummary) << "Transactions (" << dec << (_r.itemCount() - 1) << "entries)";
addRating(_r.itemCount() - 1);
+ lock_guard l(host()->m_incomingLock);
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
host()->m_incomingTransactions.push_back(_r[i].data().toBytes());
m_knownTransactions.insert(sha3(_r[i].data()));
}
break;
+ }
case GetBlockHashesPacket:
{
h256 later = _r[1].toHash();
@@ -306,6 +309,7 @@ void EthereumPeer::continueGettingChain()
}
else
{
+ if (m_failedBlocks.size())
clogS(NetMessageSummary) << "No blocks left to get. Peer doesn't seem to have" << m_failedBlocks.size() << "of our needed blocks.";
host()->noteDoneBlocks();
}
diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp
index e8c1fd1cb..a6b57a05c 100644
--- a/libethereum/Executive.cpp
+++ b/libethereum/Executive.cpp
@@ -187,6 +187,7 @@ bool Executive::go(OnOpFunc const& _onOp)
catch (VMException const& _e)
{
clog(StateChat) << "VM Exception: " << _e.description();
+ m_endGas = m_vm->gas();
}
catch (Exception const& _e)
{
diff --git a/libevm/VM.h b/libevm/VM.h
index e7d218ec6..801779e50 100644
--- a/libevm/VM.h
+++ b/libevm/VM.h
@@ -41,7 +41,6 @@ class BreakPointHit: public VMException {};
class BadInstruction: public VMException {};
class OutOfGas: public VMException {};
class StackTooSmall: public VMException { public: StackTooSmall(u256 _req, u256 _got): req(_req), got(_got) {} u256 req; u256 got; };
-class OperandOutOfRange: public VMException { public: OperandOutOfRange(u256 _min, u256 _max, u256 _got): mn(_min), mx(_max), got(_got) {} u256 mn; u256 mx; u256 got; };
// Convert from a 256-bit integer stack/memory entry into a 160-bit Address hash.
// Currently we just pull out the right (low-order in BE) 160-bits.