Browse Source

NewBlockHashes packet, basic implementation.

cl-refactor
Gav Wood 10 years ago
parent
commit
82ca50d234
  1. 74
      alethzero/Main.ui
  2. 1
      alethzero/MainWin.cpp
  3. 4
      eth/main.cpp
  4. 51
      libethereum/EthereumHost.cpp
  5. 4
      libethereum/EthereumHost.h
  6. 34
      libethereum/EthereumPeer.cpp
  7. 2
      libethereum/EthereumPeer.h
  8. 3
      libp2p/Host.cpp
  9. 2
      libp2p/Host.h
  10. 5
      libwebthree/WebThree.cpp
  11. 5
      libwebthree/WebThree.h
  12. 6
      mix/Web3Server.cpp

74
alethzero/Main.ui

@ -256,6 +256,19 @@
</widget> </widget>
<widget class="QWidget" name="layoutWidget"> <widget class="QWidget" name="layoutWidget">
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="1">
<widget class="QLineEdit" name="listenIP">
<property name="inputMask">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>Automatic</string>
</property>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@ -266,16 +279,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1" colspan="2">
<widget class="QSpinBox" name="idealPeers">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item row="3" column="2"> <item row="3" column="2">
<widget class="QSpinBox" name="port"> <widget class="QSpinBox" name="port">
<property name="minimum"> <property name="minimum">
@ -289,20 +292,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="3">
<widget class="QLineEdit" name="listenIP"> <widget class="QLabel" name="label_2">
<property name="inputMask">
<string/>
</property>
<property name="text"> <property name="text">
<string/> <string>Public IP</string>
</property> </property>
</widget>
</item>
<item row="3" column="4">
<widget class="QLineEdit" name="forcePublicIP">
<property name="placeholderText"> <property name="placeholderText">
<string>Automatic</string> <string>Automatic</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="0" column="3">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Ideal &amp;Peers</string> <string>Ideal &amp;Peers</string>
@ -312,21 +316,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="0" column="0">
<widget class="QLineEdit" name="forcePublicIP">
<property name="placeholderText">
<string>Automatic</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Public IP</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>&amp;Client Name</string> <string>&amp;Client Name</string>
@ -336,13 +326,30 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="0" column="4">
<widget class="QSpinBox" name="idealPeers">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="clientName"> <widget class="QLineEdit" name="clientName">
<property name="placeholderText"> <property name="placeholderText">
<string>Anonymous</string> <string>Anonymous</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="5">
<widget class="QLineEdit" name="enode">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>
@ -1751,7 +1758,6 @@ font-size: 14pt</string>
<tabstop>verbosity</tabstop> <tabstop>verbosity</tabstop>
<tabstop>tabWidget</tabstop> <tabstop>tabWidget</tabstop>
<tabstop>urlEdit</tabstop> <tabstop>urlEdit</tabstop>
<tabstop>idealPeers</tabstop>
<tabstop>listenIP</tabstop> <tabstop>listenIP</tabstop>
<tabstop>port</tabstop> <tabstop>port</tabstop>
<tabstop>transactionQueue</tabstop> <tabstop>transactionQueue</tabstop>

1
alethzero/MainWin.cpp

@ -1774,6 +1774,7 @@ void Main::on_net_triggered()
ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : h256()); ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : h256());
web3()->startNetwork(); web3()->startNetwork();
ui->downloadView->setDownloadMan(ethereum()->downloadMan()); ui->downloadView->setDownloadMan(ethereum()->downloadMan());
ui->enode->setText(QString::fromStdString(web3()->enode()));
} }
else else
{ {

4
eth/main.cpp

@ -407,6 +407,7 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
#if 0
cout << "\x1b[30mEthBlack\x1b[0m" << endl; cout << "\x1b[30mEthBlack\x1b[0m" << endl;
cout << "\x1b[90mEthCoal\x1b[0m" << endl; cout << "\x1b[90mEthCoal\x1b[0m" << endl;
cout << "\x1b[37mEthGray\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;35mEthPurpleU\x1b[0m" << endl;
cout << "\x1b[4;36mEthCyanU\x1b[0m" << endl; cout << "\x1b[4;36mEthCyanU\x1b[0m" << endl;
cout << "\x1b[4;37mEthWhiteU\x1b[0m" << endl; cout << "\x1b[4;37mEthWhiteU\x1b[0m" << endl;
#endif
// Init defaults // Init defaults
Defaults::get(); Defaults::get();
@ -1051,6 +1052,7 @@ int main(int argc, char** argv)
cout << "Transaction Signer: " << sigKey.address() << endl; cout << "Transaction Signer: " << sigKey.address() << endl;
cout << "Mining Benefactor: " << coinbase << endl; cout << "Mining Benefactor: " << coinbase << endl;
web3.startNetwork(); web3.startNetwork();
cout << "Node ID: " << web3.enode() << endl;
if (bootstrap) if (bootstrap)
web3.addNode(p2p::NodeId(), Host::pocHost()); web3.addNode(p2p::NodeId(), Host::pocHost());

51
libethereum/EthereumHost.cpp

@ -189,7 +189,7 @@ void EthereumHost::maintainTransactions()
for (auto const& i: ts) for (auto const& i: ts)
{ {
bool unsent = !m_transactionsSent.count(i.first); 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); peerTransactions[p].push_back(i.first);
} }
for (auto const& t: ts) for (auto const& t: ts)
@ -218,28 +218,28 @@ void EthereumHost::maintainTransactions()
} }
} }
std::vector<std::shared_ptr<EthereumPeer>> EthereumHost::randomSelection(unsigned _percent, std::function<bool(EthereumPeer*)> const& _allow) pair<vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<EthereumPeer>>> EthereumHost::randomSelection(unsigned _percent, std::function<bool(EthereumPeer*)> const& _allow)
{ {
std::vector<std::shared_ptr<EthereumPeer>> candidates; pair<vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<EthereumPeer>>> ret;
candidates.reserve(peerSessions().size()); ret.second.reserve(peerSessions().size());
for (auto const& j: peerSessions()) for (auto const& j: peerSessions())
{ {
auto pp = j.first->cap<EthereumPeer>(); auto pp = j.first->cap<EthereumPeer>();
if (_allow(pp.get())) if (_allow(pp.get()))
candidates.push_back(pp); ret.second.push_back(pp);
} }
std::vector<std::shared_ptr<EthereumPeer>> ret; ret.second.reserve((peerSessions().size() * _percent + 99) / 100);
for (unsigned i = (peerSessions().size() * _percent + 99) / 100; i-- && candidates.size();) for (unsigned i = (peerSessions().size() * _percent + 99) / 100; i-- && ret.second.size();)
{ {
unsigned n = rand() % candidates.size(); unsigned n = rand() % ret.second.size();
ret.push_back(std::move(candidates[n])); ret.first.push_back(std::move(ret.second[n]));
candidates.erase(candidates.begin() + n); ret.second.erase(ret.second.begin() + n);
} }
return ret; return ret;
} }
void EthereumHost::maintainBlocks(h256 _currentHash) void EthereumHost::maintainBlocks(h256 const& _currentHash)
{ {
// Send any new blocks. // Send any new blocks.
auto detailsFrom = m_chain.details(m_latestBlockSent); 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)); 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<EthereumPeer> const& p: s.first)
for (auto const& b: blocks) for (auto const& b: blocks)
if (!p->m_knownBlocks.count(b)) {
{ RLPStream ts;
RLPStream ts; p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(b), 1).append(m_chain.details(b).totalDifficulty);
p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(b), 1).append(m_chain.details(b).totalDifficulty);
Guard l(p->x_knownBlocks); Guard l(p->x_knownBlocks);
p->sealAndSend(ts); p->sealAndSend(ts);
p->m_knownBlocks.clear(); p->m_knownBlocks.clear();
} }
for (shared_ptr<EthereumPeer> 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; m_latestBlockSent = _currentHash;
} }

4
libethereum/EthereumHost.h

@ -80,7 +80,7 @@ public:
void noteNewBlocks() { m_newBlocks = true; } void noteNewBlocks() { m_newBlocks = true; }
private: private:
std::vector<std::shared_ptr<EthereumPeer>> randomSelection(unsigned _percent = 25, std::function<bool(EthereumPeer*)> const& _allow = [](EthereumPeer const*){ return true; }); std::pair<std::vector<std::shared_ptr<EthereumPeer>>, std::vector<std::shared_ptr<EthereumPeer>>> randomSelection(unsigned _percent = 25, std::function<bool(EthereumPeer*)> const& _allow = [](EthereumPeer const*){ return true; });
/// Session is tell us that we may need (re-)syncing with the peer. /// Session is tell us that we may need (re-)syncing with the peer.
void noteNeedsSyncing(EthereumPeer* _who); void noteNeedsSyncing(EthereumPeer* _who);
@ -92,7 +92,7 @@ private:
void doWork(); void doWork();
void maintainTransactions(); void maintainTransactions();
void maintainBlocks(h256 _currentBlock); void maintainBlocks(h256 const& _currentBlock);
/// Get a bunch of needed blocks. /// Get a bunch of needed blocks.
/// Removes them from our list of needed blocks. /// Removes them from our list of needed blocks.

34
libethereum/EthereumPeer.cpp

@ -559,37 +559,33 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
default:; default:;
} }
Guard l(x_knownBlocks); ETH_GUARDED(x_knownBlocks)
m_knownBlocks.insert(h); m_knownBlocks.insert(h);
} }
break; break;
} }
/* case NewBlockHashesPacket: case NewBlockHashesPacket:
{ {
clog(NetMessageSummary) << "NewBlock: " << h; clog(NetMessageSummary) << "NewBlockHashes";
if (_r.itemCount() == 1) if (host()->isSyncing())
disable("NewBlock without any data fields.");
else if (host()->isSyncing())
clog(NetMessageSummary) << "Ignoring since we're already downloading."; clog(NetMessageSummary) << "Ignoring since we're already downloading.";
else else
{ {
unsigned knowns = 0; unsigned knowns = 0;
unsigned unknowns = 0; unsigned unknowns = 0;
unsigned itemCount = _r.itemCount();
for (unsigned i = 0; i < itemCount; ++i) for (unsigned i = 0; i < itemCount; ++i)
{ {
addRating(1); addRating(1);
auto h = _r[i].toHash<h256>(); auto h = _r[i].toHash<h256>();
ETH_GUARDED(x_knownBlocks)
m_knownBlocks.insert(h);
auto status = host()->m_bq.blockStatus(h); auto status = host()->m_bq.blockStatus(h);
if (status == QueueStatus::Importing || status == QueueStatus::Ready || host()->m_chain.isKnown(h)) if (status == QueueStatus::Importing || status == QueueStatus::Ready || host()->m_chain.isKnown(h))
{ knowns++;
clog(NetMessageSummary) << "block hash ready:" << h << ". Start blocks download...";
transition(Asking::Blocks);
return true;
}
else if (status == QueueStatus::Bad) else if (status == QueueStatus::Bad)
{ {
cwarn << "block hash bad!" << h << ". Bailing..."; cwarn << "block hash bad!" << h << ". Bailing...";
transition(Asking::Nothing);
return true; return true;
} }
else if (status == QueueStatus::Unknown) else if (status == QueueStatus::Unknown)
@ -599,14 +595,18 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
} }
else else
knowns++; knowns++;
m_syncingLastReceivedHash = h;
} }
clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns; now at" << m_syncingLastReceivedHash; clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns";
transition(Asking::Blocks); if (unknowns > 0)
{
host()->m_man.resetToChain(m_syncingNeededBlocks);
host()->changeSyncer(this);
transition(Asking::Blocks);
}
return true; return true;
} }
break; break;
}*/ }
default: default:
return false; return false;
} }

2
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 /// 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. /// 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. 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. 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. u256 m_syncingTotalDifficulty; ///< Peer's latest block's total difficulty, as of the current sync.

3
libp2p/Host.cpp

@ -413,7 +413,6 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
// create or update m_peers entry // create or update m_peers entry
shared_ptr<Peer> p; shared_ptr<Peer> p;
ETH_RECURSIVE_GUARDED(x_sessions) ETH_RECURSIVE_GUARDED(x_sessions)
{
if (m_peers.count(_n)) if (m_peers.count(_n))
{ {
p = m_peers[_n]; p = m_peers[_n];
@ -425,7 +424,6 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
p.reset(new Peer(node)); p.reset(new Peer(node));
m_peers[_n] = p; m_peers[_n] = p;
} }
}
connect(p); connect(p);
} }
else if (m_nodeTable) 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) t->async_wait([this, _n](boost::system::error_code const& _ec)
{ {
if (!_ec && m_nodeTable) if (!_ec && m_nodeTable)
// FIXME RACE CONDITION (use weak_ptr or mutex).
if (auto n = m_nodeTable->node(_n)) if (auto n = m_nodeTable->node(_n))
requirePeer(n.id, n.endpoint); requirePeer(n.id, n.endpoint);
}); });

2
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. // 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; } 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(); } 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 /// Start network. @threadsafe

5
libwebthree/WebThree.cpp

@ -72,6 +72,11 @@ WebThreeDirect::~WebThreeDirect()
m_ethereum.reset(); m_ethereum.reset();
} }
p2p::NetworkPreferences const& WebThreeDirect::networkPreferences() const
{
return m_net.networkPreferences();
}
void WebThreeDirect::setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) void WebThreeDirect::setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers)
{ {
auto had = isNetworkStarted(); auto had = isNetworkStarted();

5
libwebthree/WebThree.h

@ -73,6 +73,7 @@ public:
virtual bool haveNetwork() const = 0; virtual bool haveNetwork() const = 0;
virtual p2p::NetworkPreferences const& networkPreferences() const = 0;
virtual void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) = 0; virtual void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) = 0;
virtual p2p::NodeId id() const = 0; virtual p2p::NodeId id() const = 0;
@ -88,6 +89,8 @@ public:
/// Is network working? there may not be any peers yet. /// Is network working? there may not be any peers yet.
virtual bool isNetworkStarted() const = 0; 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(); } bool haveNetwork() const override { return m_net.haveNetwork(); }
p2p::NetworkPreferences const& networkPreferences() const override;
void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers = false) override; void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers = false) override;
p2p::NodeId id() const override { return m_net.id(); } p2p::NodeId id() const override { return m_net.id(); }

6
mix/Web3Server.cpp

@ -70,6 +70,12 @@ class EmptyNetwork : public dev::WebThreeNetworkFace
return false; 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 setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) override
{ {
(void)_n; (void)_n;

Loading…
Cancel
Save