diff --git a/alethzero/Main.ui b/alethzero/Main.ui
index f28f5b5fc..736af8684 100644
--- a/alethzero/Main.ui
+++ b/alethzero/Main.ui
@@ -256,6 +256,19 @@
+ -
+
+
+
+
+
+
+
+
+ Automatic
+
+
+
-
@@ -266,16 +279,6 @@
- -
-
-
- 1
-
-
- 5
-
-
-
-
@@ -289,20 +292,21 @@
- -
-
-
-
-
+
-
+
-
+ Public IP
+
+
+ -
+
Automatic
- -
+
-
Ideal &Peers
@@ -312,21 +316,7 @@
- -
-
-
- Automatic
-
-
-
- -
-
-
- Public IP
-
-
-
- -
+
-
&Client Name
@@ -336,13 +326,30 @@
- -
+
-
+
+
+ 1
+
+
+ 5
+
+
+
+ -
Anonymous
+ -
+
+
+ true
+
+
+
@@ -1751,7 +1758,6 @@ font-size: 14pt
verbosity
tabWidget
urlEdit
- idealPeers
listenIP
port
transactionQueue
diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 42951279b..62515f171 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -1774,6 +1774,7 @@ void Main::on_net_triggered()
ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : h256());
web3()->startNetwork();
ui->downloadView->setDownloadMan(ethereum()->downloadMan());
+ ui->enode->setText(QString::fromStdString(web3()->enode()));
}
else
{
diff --git a/eth/main.cpp b/eth/main.cpp
index 985e74e59..801ee1a0f 100644
--- a/eth/main.cpp
+++ b/eth/main.cpp
@@ -407,6 +407,7 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
int main(int argc, char** argv)
{
+#if 0
cout << "\x1b[30mEthBlack\x1b[0m" << endl;
cout << "\x1b[90mEthCoal\x1b[0m" << endl;
cout << "\x1b[37mEthGray\x1b[0m" << endl;
@@ -472,7 +473,7 @@ int main(int argc, char** argv)
cout << "\x1b[4;35mEthPurpleU\x1b[0m" << endl;
cout << "\x1b[4;36mEthCyanU\x1b[0m" << endl;
cout << "\x1b[4;37mEthWhiteU\x1b[0m" << endl;
-
+#endif
// Init defaults
Defaults::get();
@@ -1051,6 +1052,7 @@ int main(int argc, char** argv)
cout << "Transaction Signer: " << sigKey.address() << endl;
cout << "Mining Benefactor: " << coinbase << endl;
web3.startNetwork();
+ cout << "Node ID: " << web3.enode() << endl;
if (bootstrap)
web3.addNode(p2p::NodeId(), Host::pocHost());
diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp
index 340ae417f..5744f75fa 100644
--- a/libethereum/EthereumHost.cpp
+++ b/libethereum/EthereumHost.cpp
@@ -189,7 +189,7 @@ void EthereumHost::maintainTransactions()
for (auto const& i: ts)
{
bool unsent = !m_transactionsSent.count(i.first);
- for (auto const& p: randomSelection(100, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(i.first)); }))
+ for (auto const& p: randomSelection(0, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(i.first)); }).second)
peerTransactions[p].push_back(i.first);
}
for (auto const& t: ts)
@@ -218,28 +218,28 @@ void EthereumHost::maintainTransactions()
}
}
-std::vector> EthereumHost::randomSelection(unsigned _percent, std::function const& _allow)
+pair>, vector>> EthereumHost::randomSelection(unsigned _percent, std::function const& _allow)
{
- std::vector> candidates;
- candidates.reserve(peerSessions().size());
+ pair>, vector>> ret;
+ ret.second.reserve(peerSessions().size());
for (auto const& j: peerSessions())
{
auto pp = j.first->cap();
if (_allow(pp.get()))
- candidates.push_back(pp);
+ ret.second.push_back(pp);
}
- std::vector> ret;
- for (unsigned i = (peerSessions().size() * _percent + 99) / 100; i-- && candidates.size();)
+ ret.second.reserve((peerSessions().size() * _percent + 99) / 100);
+ for (unsigned i = (peerSessions().size() * _percent + 99) / 100; i-- && ret.second.size();)
{
- unsigned n = rand() % candidates.size();
- ret.push_back(std::move(candidates[n]));
- candidates.erase(candidates.begin() + n);
+ unsigned n = rand() % ret.second.size();
+ ret.first.push_back(std::move(ret.second[n]));
+ ret.second.erase(ret.second.begin() + n);
}
return ret;
}
-void EthereumHost::maintainBlocks(h256 _currentHash)
+void EthereumHost::maintainBlocks(h256 const& _currentHash)
{
// Send any new blocks.
auto detailsFrom = m_chain.details(m_latestBlockSent);
@@ -253,17 +253,28 @@ void EthereumHost::maintainBlocks(h256 _currentHash)
h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true));
- for (auto const& p: randomSelection(100, [&](EthereumPeer* p){return !p->m_knownBlocks.count(_currentHash); }))
+ auto s = randomSelection(0, [&](EthereumPeer* p){ ETH_GUARDED(p->x_knownBlocks) return !p->m_knownBlocks.count(_currentHash); return false; });
+ for (shared_ptr const& p: s.first)
for (auto const& b: blocks)
- if (!p->m_knownBlocks.count(b))
- {
- RLPStream ts;
- p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(b), 1).append(m_chain.details(b).totalDifficulty);
+ {
+ RLPStream ts;
+ p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(b), 1).append(m_chain.details(b).totalDifficulty);
- Guard l(p->x_knownBlocks);
- p->sealAndSend(ts);
- p->m_knownBlocks.clear();
- }
+ Guard l(p->x_knownBlocks);
+ p->sealAndSend(ts);
+ p->m_knownBlocks.clear();
+ }
+ for (shared_ptr const& p: s.second)
+ {
+ RLPStream ts;
+ p->prep(ts, NewBlockHashesPacket, blocks.size());
+ for (auto const& b: blocks)
+ ts.append(b);
+
+ Guard l(p->x_knownBlocks);
+ p->sealAndSend(ts);
+ p->m_knownBlocks.clear();
+ }
}
m_latestBlockSent = _currentHash;
}
diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h
index c2fffcd82..baa850b5c 100644
--- a/libethereum/EthereumHost.h
+++ b/libethereum/EthereumHost.h
@@ -80,7 +80,7 @@ public:
void noteNewBlocks() { m_newBlocks = true; }
private:
- std::vector> randomSelection(unsigned _percent = 25, std::function const& _allow = [](EthereumPeer const*){ return true; });
+ std::pair>, std::vector>> randomSelection(unsigned _percent = 25, std::function const& _allow = [](EthereumPeer const*){ return true; });
/// Session is tell us that we may need (re-)syncing with the peer.
void noteNeedsSyncing(EthereumPeer* _who);
@@ -92,7 +92,7 @@ private:
void doWork();
void maintainTransactions();
- void maintainBlocks(h256 _currentBlock);
+ void maintainBlocks(h256 const& _currentBlock);
/// Get a bunch of needed blocks.
/// Removes them from our list of needed blocks.
diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp
index a3327bbf8..c550bd4f7 100644
--- a/libethereum/EthereumPeer.cpp
+++ b/libethereum/EthereumPeer.cpp
@@ -559,37 +559,33 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
default:;
}
- Guard l(x_knownBlocks);
- m_knownBlocks.insert(h);
+ ETH_GUARDED(x_knownBlocks)
+ m_knownBlocks.insert(h);
}
break;
}
-/* case NewBlockHashesPacket:
+ case NewBlockHashesPacket:
{
- clog(NetMessageSummary) << "NewBlock: " << h;
- if (_r.itemCount() == 1)
- disable("NewBlock without any data fields.");
- else if (host()->isSyncing())
+ clog(NetMessageSummary) << "NewBlockHashes";
+ if (host()->isSyncing())
clog(NetMessageSummary) << "Ignoring since we're already downloading.";
else
{
unsigned knowns = 0;
unsigned unknowns = 0;
+ unsigned itemCount = _r.itemCount();
for (unsigned i = 0; i < itemCount; ++i)
{
addRating(1);
auto h = _r[i].toHash();
+ ETH_GUARDED(x_knownBlocks)
+ m_knownBlocks.insert(h);
auto status = host()->m_bq.blockStatus(h);
if (status == QueueStatus::Importing || status == QueueStatus::Ready || host()->m_chain.isKnown(h))
- {
- clog(NetMessageSummary) << "block hash ready:" << h << ". Start blocks download...";
- transition(Asking::Blocks);
- return true;
- }
+ knowns++;
else if (status == QueueStatus::Bad)
{
cwarn << "block hash bad!" << h << ". Bailing...";
- transition(Asking::Nothing);
return true;
}
else if (status == QueueStatus::Unknown)
@@ -599,14 +595,18 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
}
else
knowns++;
- m_syncingLastReceivedHash = h;
}
- clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns; now at" << m_syncingLastReceivedHash;
- transition(Asking::Blocks);
+ clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns";
+ if (unknowns > 0)
+ {
+ host()->m_man.resetToChain(m_syncingNeededBlocks);
+ host()->changeSyncer(this);
+ transition(Asking::Blocks);
+ }
return true;
}
break;
- }*/
+ }
default:
return false;
}
diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h
index a80d5dadd..75ebab02f 100644
--- a/libethereum/EthereumPeer.h
+++ b/libethereum/EthereumPeer.h
@@ -129,7 +129,7 @@ private:
/// This is built as we ask for hashes. Once no more hashes are given, we present this to the
/// host who initialises the DownloadMan and m_sub becomes active for us to begin asking for blocks.
h256s m_syncingNeededBlocks; ///< The blocks that we should download from this peer.
- h256 m_syncingLastReceivedHash; ///< Hash more recently received from peer.
+ h256 m_syncingLastReceivedHash; ///< Hash most recently received from peer.
h256 m_syncingLatestHash; ///< Peer's latest block's hash, as of the current sync.
u256 m_syncingTotalDifficulty; ///< Peer's latest block's total difficulty, as of the current sync.
diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp
index 78c1102c1..d47f1764e 100644
--- a/libp2p/Host.cpp
+++ b/libp2p/Host.cpp
@@ -413,7 +413,6 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
// create or update m_peers entry
shared_ptr p;
ETH_RECURSIVE_GUARDED(x_sessions)
- {
if (m_peers.count(_n))
{
p = m_peers[_n];
@@ -425,7 +424,6 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
p.reset(new Peer(node));
m_peers[_n] = p;
}
- }
connect(p);
}
else if (m_nodeTable)
@@ -438,6 +436,7 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
t->async_wait([this, _n](boost::system::error_code const& _ec)
{
if (!_ec && m_nodeTable)
+ // FIXME RACE CONDITION (use weak_ptr or mutex).
if (auto n = m_nodeTable->node(_n))
requirePeer(n.id, n.endpoint);
});
diff --git a/libp2p/Host.h b/libp2p/Host.h
index 375481c38..ea47b58b4 100644
--- a/libp2p/Host.h
+++ b/libp2p/Host.h
@@ -135,6 +135,8 @@ public:
// TODO: P2P this should be combined with peers into a HostStat object of some kind; coalesce data, as it's only used for status information.
Peers getPeers() const { RecursiveGuard l(x_sessions); Peers ret; for (auto const& i: m_peers) ret.push_back(*i.second); return ret; }
+ NetworkPreferences const& networkPreferences() const { return m_netPrefs; }
+
void setNetworkPreferences(NetworkPreferences const& _p, bool _dropPeers = false) { m_dropPeers = _dropPeers; auto had = isStarted(); if (had) stop(); m_netPrefs = _p; if (had) start(); }
/// Start network. @threadsafe
diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp
index a520190ee..606126e43 100644
--- a/libwebthree/WebThree.cpp
+++ b/libwebthree/WebThree.cpp
@@ -72,6 +72,11 @@ WebThreeDirect::~WebThreeDirect()
m_ethereum.reset();
}
+p2p::NetworkPreferences const& WebThreeDirect::networkPreferences() const
+{
+ return m_net.networkPreferences();
+}
+
void WebThreeDirect::setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers)
{
auto had = isNetworkStarted();
diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h
index 90a4aa3c2..ece83abb8 100644
--- a/libwebthree/WebThree.h
+++ b/libwebthree/WebThree.h
@@ -73,6 +73,7 @@ public:
virtual bool haveNetwork() const = 0;
+ virtual p2p::NetworkPreferences const& networkPreferences() const = 0;
virtual void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) = 0;
virtual p2p::NodeId id() const = 0;
@@ -88,6 +89,8 @@ public:
/// Is network working? there may not be any peers yet.
virtual bool isNetworkStarted() const = 0;
+
+ std::string enode() const { return "enode://" + toHex(id().ref()) + "@" + (networkPreferences().publicIPAddress.empty() ? "127.0.0.1" : networkPreferences().publicIPAddress) + ":" + toString(networkPreferences().listenPort); }
};
@@ -164,6 +167,8 @@ public:
bool haveNetwork() const override { return m_net.haveNetwork(); }
+ p2p::NetworkPreferences const& networkPreferences() const override;
+
void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers = false) override;
p2p::NodeId id() const override { return m_net.id(); }
diff --git a/mix/Web3Server.cpp b/mix/Web3Server.cpp
index 4acb262df..7edc73060 100644
--- a/mix/Web3Server.cpp
+++ b/mix/Web3Server.cpp
@@ -70,6 +70,12 @@ class EmptyNetwork : public dev::WebThreeNetworkFace
return false;
}
+ p2p::NetworkPreferences const& networkPreferences() const override
+ {
+ static const p2p::NetworkPreferences c_ret;
+ return c_ret;
+ }
+
void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) override
{
(void)_n;