From 95c063202cd2397aa946fecfb30a2ba98173a7a3 Mon Sep 17 00:00:00 2001
From: Gav Wood <i@gavwood.com>
Date: Sun, 5 Oct 2014 14:02:14 +0200
Subject: [PATCH 1/5] Block hash download fix.

---
 libethereum/EthereumHost.cpp | 13 ++++++++++---
 libwhisper/WhisperPeer.cpp   | 18 ++++++++++--------
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp
index de0e991e6..e7e80c28a 100644
--- a/libethereum/EthereumHost.cpp
+++ b/libethereum/EthereumHost.cpp
@@ -74,12 +74,19 @@ void EthereumHost::noteHavePeerState(EthereumPeer* _who)
 {
 	clog(NetAllDetail) << "Have peer state.";
 
+	// TODO: FIX: BUG: Better state management!
+
 	// if already downloading hash-chain, ignore.
 	if (m_grabbing != Grabbing::Nothing)
 	{
-		clog(NetAllDetail) << "Already downloading chain. Just set to help out.";
-		_who->ensureGettingChain();
-		return;
+		for (auto const& i: peers())
+			if (i->cap<EthereumPeer>()->m_grabbing == m_grabbing || m_grabbing == Grabbing::State)
+			{
+				clog(NetAllDetail) << "Already downloading chain. Just set to help out.";
+				_who->ensureGettingChain();
+				return;
+			}
+		m_grabbing = Grabbing::Nothing;
 	}
 
 	// otherwise check to see if we should be downloading...
diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp
index 4baccdf9c..e92e2cac3 100644
--- a/libwhisper/WhisperPeer.cpp
+++ b/libwhisper/WhisperPeer.cpp
@@ -92,15 +92,17 @@ void WhisperPeer::sendMessages()
 		n++;
 	}
 
-	// pause before sending if no messages to send
-	if (!n)
+	if (n)
+	{
+		RLPStream s;
+		prep(s);
+		s.appendList(n + 1) << MessagesPacket;
+		s.appendRaw(amalg.out(), n);
+		sealAndSend(s);
+	}
+	else
+		// just pause if no messages to send
 		this_thread::sleep_for(chrono::milliseconds(100));
-
-	RLPStream s;
-	prep(s);
-	s.appendList(n + 1) << MessagesPacket;
-	s.appendRaw(amalg.out(), n);
-	sealAndSend(s);
 }
 
 void WhisperPeer::noteNewMessage(h256 _h, Message const& _m)

From 7c818f40035435a34e57644ffbbf10b100f55ee9 Mon Sep 17 00:00:00 2001
From: Gav Wood <i@gavwood.com>
Date: Sun, 5 Oct 2014 14:29:11 +0200
Subject: [PATCH 2/5] More inclusive about.

---
 alethzero/MainWin.cpp | 2 +-
 third/MainWin.cpp     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 2181098a9..67f50da3e 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -462,7 +462,7 @@ QString Main::lookup(QString const& _a) const
 
 void Main::on_about_triggered()
 {
-	QMessageBox::about(this, "About AlethZero PoC-" + QString(dev::Version).section('.', 1, 1), QString("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood, 2014.\nBased on a design by Vitalik Buterin.\n\nThanks to the various contributors including: Alex Leverington, Tim Hughes, caktux, Eric Lombrozo, Marko Simovic.");
+	QMessageBox::about(this, "About AlethZero PoC-" + QString(dev::Version).section('.', 1, 1), QString("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood, 2014.\nThis software wouldn't be where it is today without the many leaders & contributors including:\n\nVitalik Buterin, Tim Hughes, caktux, Nick Savers, Eric Lombrozo, Marko Simovic, the many testers and the Berlin DEV team.");
 }
 
 void Main::on_paranoia_triggered()
diff --git a/third/MainWin.cpp b/third/MainWin.cpp
index 5305abc12..280fe7ba0 100644
--- a/third/MainWin.cpp
+++ b/third/MainWin.cpp
@@ -347,7 +347,7 @@ QString Main::lookup(QString const& _a) const
 
 void Main::on_about_triggered()
 {
-	QMessageBox::about(this, "About Third PoC-" + QString(dev::Version).section('.', 1, 1), QString("Third/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood, 2014.\nBased on a design by Vitalik Buterin.\n\nThanks to the various contributors including: Alex Leverington, Tim Hughes, caktux, Eric Lombrozo, Marko Simovic.");
+	QMessageBox::about(this, "About Third PoC-" + QString(dev::Version).section('.', 1, 1), QString("Third/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood, 2014.\nThis software wouldn't be where it is today without the many leaders & contributors including:\n\nVitalik Buterin, Tim Hughes, caktux, Nick Savers, Eric Lombrozo, Marko Simovic, the many testers and the Berlin DEV team.");
 }
 
 void Main::writeSettings()

From ab6c8f9c8e9637db40f7630522626950fc8b8063 Mon Sep 17 00:00:00 2001
From: Gav Wood <i@gavwood.com>
Date: Sun, 5 Oct 2014 14:40:10 +0200
Subject: [PATCH 3/5] Minor networking improvements.

---
 alethzero/MainWin.cpp     |  2 +-
 libdevcore/RangeMask.h    | 10 ++++++++--
 libethereum/DownloadMan.h |  6 +++---
 third/MainWin.cpp         |  2 +-
 4 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 67f50da3e..0703a44a6 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -462,7 +462,7 @@ QString Main::lookup(QString const& _a) const
 
 void Main::on_about_triggered()
 {
-	QMessageBox::about(this, "About AlethZero PoC-" + QString(dev::Version).section('.', 1, 1), QString("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood, 2014.\nThis software wouldn't be where it is today without the many leaders & contributors including:\n\nVitalik Buterin, Tim Hughes, caktux, Nick Savers, Eric Lombrozo, Marko Simovic, the many testers and the Berlin DEV team.");
+	QMessageBox::about(this, "About AlethZero PoC-" + QString(dev::Version).section('.', 1, 1), QString("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood, 2014.\nThis software wouldn't be where it is today without the many leaders & contributors including:\n\nVitalik Buterin, Tim Hughes, caktux, Nick Savers, Eric Lombrozo, Marko Simovic, the many testers and the Berlin \304\220\316\236V team.");
 }
 
 void Main::on_paranoia_triggered()
diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h
index f1b0043ff..e6a66776c 100644
--- a/libdevcore/RangeMask.h
+++ b/libdevcore/RangeMask.h
@@ -43,7 +43,7 @@ public:
 	using Range = std::pair<T, T>;
 	using Ranges = std::vector<Range>;
 
-	RangeMask() {}
+	RangeMask(): m_all(0, 0) {}
 	RangeMask(T _begin, T _end): m_all(_begin, _end) {}
 	RangeMask(Range const& _c): m_all(_c) {}
 
@@ -150,7 +150,7 @@ public:
 
 	bool full() const
 	{
-		return m_ranges.size() == 1 && m_ranges.begin()->first == m_all.first && m_ranges.begin()->second == m_all.second;
+		return m_all.first == m_all.second || (m_ranges.size() == 1 && m_ranges.begin()->first == m_all.first && m_ranges.begin()->second == m_all.second);
 	}
 
 	void clear()
@@ -158,6 +158,12 @@ public:
 		m_ranges.clear();
 	}
 
+	void reset()
+	{
+		m_ranges.clear();
+		m_all = std::make_pair(0, 0);
+	}
+
 	std::pair<T, T> const& all() const { return m_all; }
 
 	class const_iterator
diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h
index 3b88040fd..bf4a7db7f 100644
--- a/libethereum/DownloadMan.h
+++ b/libethereum/DownloadMan.h
@@ -63,8 +63,8 @@ private:
 		Guard l(m_fetch);
 		m_remaining.clear();
 		m_indices.clear();
-		m_asked.clear();
-		m_attempted.clear();
+		m_asked.reset();
+		m_attempted.reset();
 	}
 
 	DownloadMan* m_man = nullptr;
@@ -109,7 +109,7 @@ public:
 				i->resetFetch();
 		}
 		m_chain.clear();
-		m_blocksGot.clear();
+		m_blocksGot.reset();
 	}
 
 	RangeMask<unsigned> taken(bool _desperate = false) const
diff --git a/third/MainWin.cpp b/third/MainWin.cpp
index 280fe7ba0..10f07ef6a 100644
--- a/third/MainWin.cpp
+++ b/third/MainWin.cpp
@@ -347,7 +347,7 @@ QString Main::lookup(QString const& _a) const
 
 void Main::on_about_triggered()
 {
-	QMessageBox::about(this, "About Third PoC-" + QString(dev::Version).section('.', 1, 1), QString("Third/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood, 2014.\nThis software wouldn't be where it is today without the many leaders & contributors including:\n\nVitalik Buterin, Tim Hughes, caktux, Nick Savers, Eric Lombrozo, Marko Simovic, the many testers and the Berlin DEV team.");
+	QMessageBox::about(this, "About Third PoC-" + QString(dev::Version).section('.', 1, 1), QString("Third/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood, 2014.\nThis software wouldn't be where it is today without the many leaders & contributors including:\n\nVitalik Buterin, Tim Hughes, caktux, Nick Savers, Eric Lombrozo, Marko Simovic, the many testers and the Berlin \304\220\316\236V team.");
 }
 
 void Main::writeSettings()

From 2e8ac064806d3cac06363f0dfa542d2e08cefb39 Mon Sep 17 00:00:00 2001
From: Gav Wood <i@gavwood.com>
Date: Sun, 5 Oct 2014 15:21:59 +0200
Subject: [PATCH 4/5] Guards for View. Improved logging.

---
 alethzero/DownloadView.cpp   | 2 +-
 libethereum/DownloadMan.h    | 9 +++++++--
 libethereum/EthereumPeer.cpp | 2 +-
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp
index 657727a6a..56dd9c3d2 100644
--- a/alethzero/DownloadView.cpp
+++ b/alethzero/DownloadView.cpp
@@ -51,7 +51,7 @@ void DownloadView::paintEvent(QPaintEvent*)
 	QSizeF area(n, n);
 	QPointF pos(0, 0);
 
-	auto const& bg = m_man->blocksGot();
+	auto bg = m_man->blocksGot();
 
 	for (unsigned i = bg.all().first, ei = bg.all().second; i < ei; ++i)
 	{
diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h
index bf4a7db7f..3bd401d8e 100644
--- a/libethereum/DownloadMan.h
+++ b/libethereum/DownloadMan.h
@@ -94,6 +94,7 @@ public:
 			for (auto i: m_subs)
 				i->resetFetch();
 		}
+		WriteGuard l(m_lock);
 		m_chain.clear();
 		m_chain.reserve(_chain.size());
 		for (auto i = _chain.rbegin(); i != _chain.rend(); ++i)
@@ -108,12 +109,14 @@ public:
 			for (auto i: m_subs)
 				i->resetFetch();
 		}
+		WriteGuard l(m_lock);
 		m_chain.clear();
 		m_blocksGot.reset();
 	}
 
 	RangeMask<unsigned> taken(bool _desperate = false) const
 	{
+		ReadGuard l(m_lock);
 		auto ret = m_blocksGot;
 		if (!_desperate)
 		{
@@ -126,15 +129,17 @@ public:
 
 	bool isComplete() const
 	{
+		ReadGuard l(m_lock);
 		return m_blocksGot.full();
 	}
 
-	h256s chain() const { return m_chain; }
+	h256s chain() const { ReadGuard l(m_lock); return m_chain; }
 	void foreachSub(std::function<void(DownloadSub const&)> const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); }
 	unsigned subCount() const { ReadGuard l(x_subs); return m_subs.size(); }
-	RangeMask<unsigned> blocksGot() const { return m_blocksGot; }
+	RangeMask<unsigned> blocksGot() const { ReadGuard l(m_lock); return m_blocksGot; }
 
 private:
+	mutable SharedMutex m_lock;
 	h256s m_chain;
 	RangeMask<unsigned> m_blocksGot;
 
diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp
index d7d69187d..b45abfbff 100644
--- a/libethereum/EthereumPeer.cpp
+++ b/libethereum/EthereumPeer.cpp
@@ -115,7 +115,7 @@ void EthereumPeer::tryGrabbingHashChain()
 
 void EthereumPeer::giveUpOnFetch()
 {
-	clogS(NetNote) << "GIVE UP FETCH";
+	clogS(NetNote) << "Finishing fetch...";
 
 	// a bit overkill given that the other nodes may yet have the needed blocks, but better to be safe than sorry.
 	if (m_grabbing == Grabbing::Chain || m_grabbing == Grabbing::ChainHelper)

From 2ed2d479c67c425a255f8991aa72df3ff4780d48 Mon Sep 17 00:00:00 2001
From: subtly <subtly@users.noreply.github.com>
Date: Sun, 5 Oct 2014 19:48:08 +0200
Subject: [PATCH 5/5] Add mutexed askedContains in placed of .asked.contains().
 Issue #333 (dev::RangeMask<unsigned int>::contains), nextFetch clears m_asked
 concurrent to m_asked.contains() iteration.

---
 alethzero/DownloadView.cpp | 2 +-
 libethereum/DownloadMan.h  | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp
index 56dd9c3d2..a6533023c 100644
--- a/alethzero/DownloadView.cpp
+++ b/alethzero/DownloadView.cpp
@@ -63,7 +63,7 @@ void DownloadView::paintEvent(QPaintEvent*)
 			unsigned h = 0;
 			m_man->foreachSub([&](DownloadSub const& sub)
 			{
-				if (sub.asked().contains(i))
+				if (sub.askedContains(i))
 					s = h;
 				h++;
 			});
diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h
index 3bd401d8e..6f4c4bafb 100644
--- a/libethereum/DownloadMan.h
+++ b/libethereum/DownloadMan.h
@@ -54,6 +54,7 @@ public:
 	/// Nothing doing here.
 	void doneFetch() { resetFetch(); }
 
+	bool askedContains(unsigned _i) const { Guard l(m_fetch); return m_asked.contains(_i); }
 	RangeMask<unsigned> const& asked() const { return m_asked; }
 	RangeMask<unsigned> const& attemped() const { return m_attempted; }
 
@@ -69,7 +70,7 @@ private:
 
 	DownloadMan* m_man = nullptr;
 
-	Mutex m_fetch;
+	mutable Mutex m_fetch;
 	h256Set m_remaining;
 	std::map<h256, unsigned> m_indices;
 	RangeMask<unsigned> m_asked;