Browse Source

Merge remote-tracking branch 'upstream/develop' into develop

cl-refactor
Christoph Jentzsch 10 years ago
parent
commit
0a68f6961c
  1. 2
      CMakeLists.txt
  2. 24
      alethzero/MainWin.cpp
  3. 25
      eth/main.cpp
  4. 24
      exp/main.cpp
  5. 2
      libdevcore/Common.cpp
  6. 25
      libdevcore/RangeMask.cpp
  7. 18
      libdevcore/RangeMask.h
  8. 1
      libethereum/CommonNet.h
  9. 75
      libethereum/DownloadMan.cpp
  10. 128
      libethereum/DownloadMan.h
  11. 65
      libethereum/EthereumHost.cpp
  12. 49
      libethereum/EthereumHost.h
  13. 68
      libethereum/EthereumPeer.cpp
  14. 10
      libethereum/EthereumPeer.h
  15. 34
      libp2p/Host.cpp
  16. 1
      libp2p/Host.h
  17. 8
      libp2p/Session.cpp
  18. 1
      neth/CMakeLists.txt
  19. 29
      neth/main.cpp
  20. 1
      third/MainWin.cpp

2
CMakeLists.txt

@ -353,7 +353,7 @@ if (NOT LANGUAGES)
add_subdirectory(exp)
endif ()
if(NOT ("${TARGET_PLATFORM}" STREQUAL "w64"))
#add_subdirectory(neth) // resurect once moved over to WebThree API.
add_subdirectory(neth)
endif ()
if(QTQML)
add_definitions(-DETH_QTQML)

24
alethzero/MainWin.cpp

@ -97,26 +97,10 @@ Main::Main(QWidget *parent) :
// ui->log->addItem(QString::fromStdString(s));
};
#if 0&&ETH_DEBUG
m_servers.append("192.168.0.10:30301");
#else
int pocnumber = QString(dev::Version).section('.', 1, 1).toInt();
if (pocnumber == 5)
m_servers.push_back("54.72.69.180:30303");
else if (pocnumber == 6)
m_servers.push_back("54.76.56.74:30303");
else
{
connect(&m_webCtrl, &QNetworkAccessManager::finished, [&](QNetworkReply* _r)
{
m_servers = QString::fromUtf8(_r->readAll()).split("\n", QString::SkipEmptyParts);
});
QNetworkRequest r(QUrl("http://www.ethereum.org/servers.poc" + QString::number(pocnumber) + ".txt"));
r.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1712.0 Safari/537.36");
m_webCtrl.get(r);
srand(time(0));
}
#if ETH_DEBUG
m_servers.append("localhost:30300");
#endif
m_servers.append(QString::fromStdString(Host::pocHost() + ":30303"));
cerr << "State root: " << BlockChain::genesis().stateRoot << endl;
cerr << "Block Hash: " << sha3(BlockChain::createGenesisBlock()) << endl;
@ -141,7 +125,7 @@ Main::Main(QWidget *parent) :
connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved()));
m_webThree.reset(new WebThreeDirect("AlethZero", getDataDir() + "/AlethZero", false, {"eth", "shh"}));
m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"}));
connect(ui->webView, &QWebView::loadStarted, [this]()
{

25
eth/main.cpp

@ -99,6 +99,7 @@ void help()
<< "Usage eth [OPTIONS] <remote-host>" << endl
<< "Options:" << endl
<< " -a,--address <addr> Set the coinbase (mining payout) address to addr (default: auto)." << endl
<< " -b,--bootstrap Connect to the default Ethereum peerserver." << endl
<< " -c,--client-name <name> Add a name to your client's version string (default: blank)." << endl
<< " -d,--db-path <path> Load database from path (default: ~/.ethereum " << endl
<< " <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl
@ -134,17 +135,8 @@ string credits(bool _interactive = false)
if (_interactive)
{
string vs = toString(dev::Version);
vs = vs.substr(vs.find_first_of('.') + 1)[0];
int pocnumber = stoi(vs);
string m_servers;
if (pocnumber == 4)
m_servers = "54.72.31.55";
else
m_servers = "54.72.69.180";
cout << "Type 'netstart 30303' to start networking" << endl;
cout << "Type 'connect " << m_servers << " 30303' to connect" << endl;
cout << "Type 'connect " << Host::pocHost() << " 30303' to connect" << endl;
cout << "Type 'exit' to quit" << endl << endl;
}
return cout.str();
@ -185,9 +177,10 @@ int main(int argc, char** argv)
unsigned peers = 5;
bool interactive = false;
#if ETH_JSONRPC
int jsonrpc = 8080;
int jsonrpc = -1;
#endif
string publicIP;
bool bootstrap = false;
bool upnp = true;
bool useLocal = false;
bool forceMining = false;
@ -264,13 +257,15 @@ int main(int argc, char** argv)
return -1;
}
}
else if (arg == "-b" || arg == "--bootstrap")
bootstrap = true;
else if (arg == "-f" || arg == "--force-mining")
forceMining = true;
else if (arg == "-i" || arg == "--interactive")
interactive = true;
#if ETH_JSONRPC
else if ((arg == "-j" || arg == "--json-rpc"))
jsonrpc = jsonrpc ? jsonrpc : 8080;
jsonrpc = jsonrpc == -1 ? 8080 : jsonrpc;
else if (arg == "--json-rpc-port" && i + 1 < argc)
jsonrpc = atoi(argv[++i]);
#endif
@ -317,7 +312,11 @@ int main(int argc, char** argv)
cout << "Address: " << endl << toHex(us.address().asArray()) << endl;
web3.startNetwork();
web3.connect(remoteHost, remotePort);
if (bootstrap)
web3.connect(Host::pocHost());
if (remoteHost.size())
web3.connect(remoteHost, remotePort);
#if ETH_JSONRPC
auto_ptr<EthStubServer> jsonrpcServer;

24
exp/main.cpp

@ -19,12 +19,14 @@
* @date 2014
* Ethereum client.
*/
#include <functional>
#include <libdevcore/Log.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/RLP.h>
#include <libp2p/All.h>
#include <libdevcore/RangeMask.h>
#include <libethereum/DownloadMan.h>
#include <libwhisper/WhisperPeer.h>
using namespace std;
using namespace dev;
@ -34,7 +36,25 @@ using namespace dev::shh;
int main()
{
RangeMask<unsigned> m(0, 100);
DownloadMan man;
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)}));
cnote << s0.nextFetch(2);
cnote << s1.nextFetch(2);
cnote << s2.nextFetch(2);
s0.noteBlock(u256(0));
s0.doneFetch();
cnote << s0.nextFetch(2);
s1.noteBlock(u256(2));
s1.noteBlock(u256(3));
s1.doneFetch();
cnote << s1.nextFetch(2);
s0.doneFetch();
cnote << s0.nextFetch(2);
/* RangeMask<unsigned> m(0, 100);
cnote << m;
m += UnsignedRange(3, 10);
cnote << m;
@ -45,7 +65,7 @@ int main()
cnote << ~m;
cnote << (~m).lowest(10);
for (auto i: (~m).lowest(10))
cnote << i;
cnote << i;*/
return 0;
}

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev
{
char const* Version = "0.6.8c";
char const* Version = "0.6.8d";
}

25
libdevcore/RangeMask.cpp

@ -1,5 +1,22 @@
#include "RangeMask.h"
/*
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.
RangeMask::RangeMask()
{
}
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file RangeMask.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "RangeMask.h"

18
libdevcore/RangeMask.h

@ -24,6 +24,7 @@
#include <map>
#include <utility>
#include <vector>
#include <iostream>
namespace dev
{
@ -52,7 +53,7 @@ public:
{
RangeMask ret(m_all);
for (auto i = m_ranges.begin(); i != m_ranges.end() && _items; ++i)
_items -= (ret.m_ranges[i->first] = std::min(i->first + _items, i->second));
_items -= (ret.m_ranges[i->first] = std::min(i->first + _items, i->second)) - i->first;
return ret;
}
@ -140,6 +141,21 @@ public:
return it != m_ranges.end() && it->first <= _i && it->second > _i;
}
bool empty() const
{
return m_ranges.empty();
}
bool full() const
{
return m_ranges.size() == 1 && m_ranges.begin()->first == m_all.first && m_ranges.begin()->second == m_all.second;
}
void clear()
{
m_ranges.clear();
}
class const_iterator
{
friend class RangeMask;

1
libethereum/CommonNet.h

@ -66,6 +66,7 @@ enum class Grabbing
State,
Hashes,
Chain,
ChainHelper,
Nothing
};

75
libethereum/DownloadMan.cpp

@ -0,0 +1,75 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file DownloadMan.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "DownloadMan.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
DownloadSub::DownloadSub(DownloadMan& _man): m_man(&_man)
{
WriteGuard l(m_man->x_subs);
m_man->m_subs.insert(this);
}
DownloadSub::~DownloadSub()
{
if (m_man)
{
WriteGuard l(m_man->x_subs);
m_man->m_subs.erase(this);
}
}
h256Set DownloadSub::nextFetch(unsigned _n)
{
Guard l(m_fetch);
if (m_remaining.size())
return m_remaining;
m_asked.clear();
m_indices.clear();
m_remaining.clear();
if (!m_man)
return h256Set();
m_asked = (~(m_man->taken() + m_attempted)).lowest(_n);
if (m_asked.empty())
m_asked = (~(m_man->taken(true) + m_attempted)).lowest(_n);
m_attempted += m_asked;
for (auto i: m_asked)
{
auto x = m_man->m_chain[i];
m_remaining.insert(x);
m_indices[x] = i;
}
return m_remaining;
}
void DownloadSub::noteBlock(h256 _hash)
{
Guard l(m_fetch);
if (m_man && m_indices.count(_hash))
m_man->m_blocksGot += m_indices[_hash];
m_remaining.erase(_hash);
}

128
libethereum/DownloadMan.h

@ -0,0 +1,128 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file DownloadMan.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <map>
#include <vector>
#include <set>
#include <libdevcore/Guards.h>
#include <libdevcore/Worker.h>
#include <libdevcore/RangeMask.h>
#include <libdevcore/FixedHash.h>
namespace dev
{
namespace eth
{
class DownloadMan;
class DownloadSub
{
friend class DownloadMan;
public:
DownloadSub(DownloadMan& _man);
~DownloadSub();
/// Finished last fetch - grab the next bunch of block hashes to download.
h256Set nextFetch(unsigned _n);
/// Note that we've received a particular block.
void noteBlock(h256 _hash);
/// Nothing doing here.
void doneFetch() { resetFetch(); }
private:
void resetFetch() // Called by DownloadMan when we need to reset the download.
{
Guard l(m_fetch);
m_remaining.clear();
m_indices.clear();
m_asked.clear();
m_attempted.clear();
}
DownloadMan* m_man = nullptr;
Mutex m_fetch;
h256Set m_remaining;
std::map<h256, unsigned> m_indices;
RangeMask<unsigned> m_asked;
RangeMask<unsigned> m_attempted;
};
class DownloadMan
{
friend class DownloadSub;
public:
~DownloadMan()
{
for (auto i: m_subs)
i->m_man = nullptr;
}
void resetToChain(h256s const& _chain)
{
{
ReadGuard l(x_subs);
for (auto i: m_subs)
i->resetFetch();
}
m_chain.clear();
m_chain.reserve(_chain.size());
for (auto i = _chain.rbegin(); i != _chain.rend(); ++i)
m_chain.push_back(*i);
m_blocksGot = RangeMask<unsigned>(0, m_chain.size());
}
RangeMask<unsigned> taken(bool _desperate = false) const
{
auto ret = m_blocksGot;
if (!_desperate)
{
ReadGuard l(x_subs);
for (auto i: m_subs)
ret += i->m_asked;
}
return ret;
}
bool isComplete() const
{
return m_blocksGot.full();
}
private:
h256s m_chain;
RangeMask<unsigned> m_blocksGot;
mutable SharedMutex x_subs;
std::set<DownloadSub*> m_subs;
};
}
}

65
libethereum/EthereumHost.cpp

@ -15,9 +15,7 @@
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file EthereumHost.cpp
* @authors:
* Gav Wood <i@gavwood.com>
* Eric Lombrozo <elombrozo@gmail.com>
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
@ -34,6 +32,7 @@
#include "TransactionQueue.h"
#include "BlockQueue.h"
#include "EthereumPeer.h"
#include "DownloadMan.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
@ -56,30 +55,6 @@ EthereumHost::~EthereumHost()
i->cap<EthereumPeer>()->giveUpOnFetch();
}
h256Set EthereumHost::neededBlocks(h256Set const& _exclude)
{
Guard l(x_blocksNeeded);
h256Set ret;
if (m_blocksNeeded.size())
{
int s = m_blocksNeeded.size() - 1;
for (; ret.size() < c_maxBlocksAsk && s < (int)m_blocksNeeded.size() && s >= 0; --s)
if (!_exclude.count(m_blocksNeeded[s]))
{
auto it = m_blocksNeeded.begin() + s;
ret.insert(*it);
m_blocksOnWay.insert(*it);
m_blocksNeeded.erase(it);
}
}
if (ret.empty())
for (auto i = m_blocksOnWay.begin(); ret.size() < c_maxBlocksAsk && i != m_blocksOnWay.end() && !_exclude.count(*i); ++i)
ret.insert(*i);
if (ret.size())
clog(NetMessageSummary) << "Asking for" << ret.size() << "blocks that we don't yet have." << m_blocksNeeded.size() << "blocks still needed," << m_blocksOnWay.size() << "total blocks on way.";
return ret;
}
bool EthereumHost::ensureInitialised(TransactionQueue& _tq)
{
if (!m_latestBlockSent)
@ -103,7 +78,7 @@ void EthereumHost::noteHavePeerState(EthereumPeer* _who)
if (m_grabbing != Grabbing::Nothing)
{
clog(NetAllDetail) << "Already downloading chain. Just set to help out.";
_who->restartGettingChain();
_who->ensureGettingChain();
return;
}
@ -118,7 +93,7 @@ void EthereumHost::updateGrabbing(Grabbing _g)
readyForSync();
else if (_g == Grabbing::Chain)
for (auto j: peers())
j->cap<EthereumPeer>()->restartGettingChain();
j->cap<EthereumPeer>()->ensureGettingChain();
}
void EthereumHost::noteHaveChain(EthereumPeer* _from)
@ -145,13 +120,9 @@ void EthereumHost::noteHaveChain(EthereumPeer* _from)
clog(NetNote) << "Difficulty of hashchain HIGHER. Replacing fetch queue [latest now" << _from->m_latestHash.abridged() << ", was" << m_latestBlockSent.abridged() << "]";
// Looks like it's the best yet for total difficulty. Set to download.
{
Guard l(x_blocksNeeded);
m_blocksNeeded = _from->m_neededBlocks;
m_blocksOnWay.clear();
m_totalDifficultyOfNeeded = td;
m_latestBlockSent = _from->m_latestHash;
}
m_man.resetToChain(_from->m_neededBlocks);
m_totalDifficultyOfNeeded = td;
m_latestBlockSent = _from->m_latestHash;
_from->m_grabbing = Grabbing::Chain;
updateGrabbing(Grabbing::Chain);
@ -172,23 +143,25 @@ void EthereumHost::readyForSync()
clog(NetNote) << "No more peers to sync with.";
}
void EthereumHost::noteDoneBlocks()
void EthereumHost::noteDoneBlocks(EthereumPeer* _who)
{
if (m_blocksOnWay.empty())
if (m_man.isComplete())
{
// Done our chain-get.
if (m_blocksNeeded.size())
clog(NetNote) << "No more blocks coming. Missing" << m_blocksNeeded.size() << "blocks.";
else
clog(NetNote) << "No more blocks to get.";
clog(NetNote) << "Chain download complete.";
updateGrabbing(Grabbing::Nothing);
}
if (_who->m_grabbing == Grabbing::Chain)
{
// Done our chain-get.
clog(NetNote) << "Chain download failed. Peer with blocks didn't have them all. This peer is bad and should be punished.";
// TODO: note that peer is BADBADBAD!
updateGrabbing(Grabbing::Nothing);
}
}
bool EthereumHost::noteBlock(h256 _hash, bytesConstRef _data)
{
Guard l(x_blocksNeeded);
m_blocksOnWay.erase(_hash);
if (!m_chain.details(_hash))
{
lock_guard<recursive_mutex> l(m_incomingLock);
@ -257,12 +230,12 @@ void EthereumHost::reset()
{
m_grabbing = Grabbing::Nothing;
m_man.resetToChain(h256s());
m_incomingTransactions.clear();
m_incomingBlocks.clear();
m_totalDifficultyOfNeeded = 0;
m_blocksNeeded.clear();
m_blocksOnWay.clear();
m_latestBlockSent = h256();
m_transactionsSent.clear();

49
libethereum/EthereumHost.h

@ -30,10 +30,12 @@
#include <thread>
#include <libdevcore/Guards.h>
#include <libdevcore/Worker.h>
#include <libdevcore/RangeMask.h>
#include <libethcore/CommonEth.h>
#include <libp2p/Common.h>
#include "CommonNet.h"
#include "EthereumPeer.h"
#include "DownloadMan.h"
namespace dev
{
@ -46,44 +48,6 @@ namespace eth
class TransactionQueue;
class BlockQueue;
#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<DownloadSub*, UnsignedRange> m_fetching;
};
#endif
/**
* @brief The EthereumHost class
* @warning None of this is thread-safe. You have been warned.
@ -113,7 +77,7 @@ private:
/// Session has finished getting the chain of hashes.
void noteHaveChain(EthereumPeer* _who);
/// Called when the peer can no longer provide us with any needed blocks.
void noteDoneBlocks();
void noteDoneBlocks(EthereumPeer* _who);
/// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network.
void doWork();
@ -147,16 +111,15 @@ private:
u256 m_networkId;
Grabbing m_grabbing = Grabbing::Nothing;
Grabbing m_grabbing = Grabbing::Nothing; // TODO: needs to be thread-safe & switch to just having a peer id.
mutable std::recursive_mutex m_incomingLock;
std::vector<bytes> m_incomingTransactions;
std::vector<bytes> m_incomingBlocks;
mutable std::mutex x_blocksNeeded;
u256 m_totalDifficultyOfNeeded;
h256s m_blocksNeeded;
h256Set m_blocksOnWay;
DownloadMan m_man;
h256 m_latestBlockSent;
h256Set m_transactionsSent;

68
libethereum/EthereumPeer.cpp

@ -35,7 +35,8 @@ using namespace p2p;
#define clogS(X) dev::LogOutputStream<X, true>(false) << "| " << std::setw(2) << session()->socketId() << "] "
EthereumPeer::EthereumPeer(Session* _s, HostCapabilityFace* _h):
Capability(_s, _h)
Capability(_s, _h),
m_sub(host()->m_man)
{
sendStatus();
}
@ -65,7 +66,7 @@ void EthereumPeer::sendStatus()
void EthereumPeer::startInitialSync()
{
// Grab trsansactions off them.
// Grab transactions off them.
{
RLPStream s;
prep(s).appendList(1);
@ -90,7 +91,7 @@ void EthereumPeer::tryGrabbingHashChain()
u256 td = max(host()->m_chain.details().totalDifficulty, host()->m_totalDifficultyOfNeeded);
clogS(NetAllDetail) << "Attempt chain-grab? Latest:" << c.abridged() << ", number:" << n << ", TD: max(" << host()->m_chain.details().totalDifficulty << "," << host()->m_totalDifficultyOfNeeded << ") versus " << m_totalDifficulty;
if (td > m_totalDifficulty)
if (td >= m_totalDifficulty)
{
clogS(NetAllDetail) << "No. Our chain is better.";
m_grabbing = Grabbing::Nothing;
@ -101,6 +102,7 @@ void EthereumPeer::tryGrabbingHashChain()
{
clogS(NetAllDetail) << "Yes. Their chain is better.";
host()->updateGrabbing(Grabbing::Hashes);
m_grabbing = Grabbing::Hashes;
RLPStream s;
prep(s).appendList(3);
@ -112,29 +114,17 @@ void EthereumPeer::tryGrabbingHashChain()
void EthereumPeer::giveUpOnFetch()
{
clogS(NetNote) << "GIVE UP FETCH; can't get" << toString(m_askedBlocks);
clogS(NetNote) << "GIVE UP 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)
{
host()->noteDoneBlocks(this);
m_grabbing = Grabbing::Nothing;
host()->updateGrabbing(Grabbing::Nothing);
}
m_sub.doneFetch();
// NOTE: need to notify of giving up on chain-hashes, too, altering state as necessary.
if (m_askedBlocks.size())
{
Guard l (host()->x_blocksNeeded);
host()->m_blocksNeeded.reserve(host()->m_blocksNeeded.size() + m_askedBlocks.size());
for (auto i: m_askedBlocks)
{
m_failedBlocks.insert(i);
host()->m_blocksOnWay.erase(i);
host()->m_blocksNeeded.push_back(i);
}
m_askedBlocks.clear();
}
}
bool EthereumPeer::interpret(RLP const& _r)
@ -251,20 +241,20 @@ bool EthereumPeer::interpret(RLP const& _r)
{
clogS(NetMessageSummary) << "Blocks (" << dec << (_r.itemCount() - 1) << "entries)" << (_r.itemCount() - 1 ? "" : ": NoMoreBlocks");
if (_r.itemCount() == 1 && !m_askedBlocksChanged)
if (_r.itemCount() == 1)
{
// Couldn't get any from last batch - probably got to this peer's latest block - just give up.
m_sub.doneFetch();
giveUpOnFetch();
}
m_askedBlocksChanged = false;
unsigned used = 0;
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
auto h = BlockInfo::headerHash(_r[i].data());
m_sub.noteBlock(h);
if (host()->noteBlock(h, _r[i].data()))
used++;
m_askedBlocks.erase(h);
Guard l(x_knownBlocks);
m_knownBlocks.insert(h);
}
@ -281,12 +271,12 @@ bool EthereumPeer::interpret(RLP const& _r)
if (!host()->m_chain.details(bi.parentHash) && !m_knownBlocks.count(bi.parentHash))
{
unknownParents++;
clogS(NetAllDetail) << "Unknown parent" << bi.parentHash << "of block" << h;
clogS(NetAllDetail) << "Unknown parent" << bi.parentHash.abridged() << "of block" << h.abridged();
}
else
{
knownParents++;
clogS(NetAllDetail) << "Known parent" << bi.parentHash << "of block" << h;
clogS(NetAllDetail) << "Known parent" << bi.parentHash.abridged() << "of block" << h.abridged();
}
}
}
@ -300,21 +290,9 @@ bool EthereumPeer::interpret(RLP const& _r)
return true;
}
void EthereumPeer::restartGettingChain()
{
if (m_askedBlocks.size())
{
m_askedBlocksChanged = true; // So that we continue even if the Ask's reply is empty.
m_askedBlocks.clear(); // So that we restart once we get the Ask's reply.
m_failedBlocks.clear();
}
else
ensureGettingChain();
}
void EthereumPeer::ensureGettingChain()
{
if (m_askedBlocks.size())
if (m_grabbing == Grabbing::ChainHelper)
return; // Already asked & waiting for some.
continueGettingChain();
@ -322,22 +300,20 @@ void EthereumPeer::ensureGettingChain()
void EthereumPeer::continueGettingChain()
{
if (!m_askedBlocks.size())
m_askedBlocks = host()->neededBlocks(m_failedBlocks);
if (m_grabbing != Grabbing::Chain)
m_grabbing = Grabbing::ChainHelper;
if (m_askedBlocks.size())
auto blocks = m_sub.nextFetch(c_maxBlocksAsk);
if (blocks.size())
{
RLPStream s;
prep(s);
s.appendList(m_askedBlocks.size() + 1) << GetBlocksPacket;
for (auto i: m_askedBlocks)
s.appendList(blocks.size() + 1) << GetBlocksPacket;
for (auto const& i: blocks)
s << i;
sealAndSend(s);
}
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();
}
giveUpOnFetch();
}

10
libethereum/EthereumPeer.h

@ -28,9 +28,11 @@
#include <utility>
#include <libdevcore/RLP.h>
#include <libdevcore/Guards.h>
#include <libdevcore/RangeMask.h>
#include <libethcore/CommonEth.h>
#include <libp2p/Capability.h>
#include "CommonNet.h"
#include "DownloadMan.h"
namespace dev
{
@ -65,8 +67,6 @@ private:
void ensureGettingChain();
/// Ensure that we are waiting for a bunch of blocks from our peer.
void continueGettingChain();
/// Now getting a different chain so we need to make sure we restart.
void restartGettingChain();
void giveUpOnFetch();
@ -80,10 +80,6 @@ private:
h256 m_latestHash; ///< Peer's latest block's hash.
u256 m_totalDifficulty; ///< Peer's latest block's total difficulty.
h256s m_neededBlocks; ///< The blocks that we should download from this peer.
h256Set m_failedBlocks; ///< Blocks that the peer doesn't seem to have.
h256Set m_askedBlocks; ///< The blocks for which we sent the last GetBlocks for but haven't received a corresponding Blocks.
bool m_askedBlocksChanged = true;
bool m_requireTransactions;
@ -91,6 +87,8 @@ private:
std::set<h256> m_knownBlocks;
std::set<h256> m_knownTransactions;
std::mutex x_knownTransactions;
DownloadSub m_sub;
};
}

34
libp2p/Host.cpp

@ -34,6 +34,7 @@
#include <set>
#include <chrono>
#include <thread>
#include <boost/algorithm/string.hpp>
#include <libdevcore/Common.h>
#include <libethcore/Exceptions.h>
#include "Session.h"
@ -76,7 +77,9 @@ Host::~Host()
void Host::start()
{
stop();
if (isWorking())
stop();
for (unsigned i = 0; i < 2; ++i)
{
bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : m_netPrefs.listenPort);
@ -103,6 +106,10 @@ void Host::start()
determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp);
ensureAccepting();
m_incomingPeers.clear();
m_freePeers.clear();
m_lastPeersRequest = chrono::steady_clock::time_point::min();
clog(NetNote) << "Id:" << m_id.abridged();
@ -311,8 +318,14 @@ std::map<h512, bi::tcp::endpoint> Host::potentialPeers()
if (auto j = i.second.lock())
{
auto ep = j->endpoint();
// cnote << "Checking potential peer" << j->m_listenPort << j->endpoint() << isPrivateAddress(ep.address()) << ep.port() << j->m_id.abridged();
// Skip peers with a listen port of zero or are on a private network
bool peerOnNet = (j->m_listenPort != 0 && (!isPrivateAddress(ep.address()) || m_netPrefs.localNetworking));
if (!peerOnNet && m_incomingPeers.count(j->m_id))
{
ep = m_incomingPeers.at(j->m_id).first;
peerOnNet = (j->m_listenPort != 0 && (!isPrivateAddress(ep.address()) || m_netPrefs.localNetworking));
}
if (peerOnNet && ep.port() && j->m_id)
ret.insert(make_pair(i.first, ep));
}
@ -349,12 +362,20 @@ void Host::ensureAccepting()
}
}
string Host::pocHost()
{
vector<string> strs;
boost::split(strs, dev::Version, boost::is_any_of("."));
return "poc-" + strs[1] + ".ethdev.com";
}
void Host::connect(std::string const& _addr, unsigned short _port) noexcept
{
try
{
// TODO: actual DNS lookup.
connect(bi::tcp::endpoint(bi::address::from_string(_addr), _port));
bi::tcp::resolver r(m_ioService);
connect(r.resolve({_addr, toString(_port)})->endpoint());
// connect(bi::tcp::endpoint(bi::address::from_string(_addr), _port));
}
catch (exception const& e)
{
@ -435,8 +456,11 @@ void Host::growPeers()
auto x = time(0) % m_freePeers.size();
m_incomingPeers[m_freePeers[x]].second++;
connect(m_incomingPeers[m_freePeers[x]].first);
m_freePeers.erase(m_freePeers.begin() + x);
if (!m_peers.count(m_freePeers[x]))
{
connect(m_incomingPeers[m_freePeers[x]].first);
m_freePeers.erase(m_freePeers.begin() + x);
}
}
}

1
libp2p/Host.h

@ -82,6 +82,7 @@ public:
template <class T> std::shared_ptr<T> cap() const { try { return std::static_pointer_cast<T>(m_capabilities.at(T::staticName())); } catch (...) { return nullptr; } }
/// Connect to a peer explicitly.
static std::string pocHost();
void connect(std::string const& _addr, unsigned short _port = 30303) noexcept;
void connect(bi::tcp::endpoint const& _ep);

8
libp2p/Session.cpp

@ -159,13 +159,13 @@ bool Session::interpret(RLP const& _r)
bi::address_v4 peerAddress(_r[i][0].toHash<FixedHash<4>>().asArray());
auto ep = bi::tcp::endpoint(peerAddress, _r[i][1].toInt<short>());
h512 id = _r[i][2].toHash<h512>();
clogS(NetAllDetail) << "Checking: " << ep << "(" << id.abridged() << ")" << isPrivateAddress(peerAddress) << m_id.abridged() << isPrivateAddress(endpoint().address()) << m_server->m_incomingPeers.count(id) << (m_server->m_incomingPeers.count(id) ? isPrivateAddress(m_server->m_incomingPeers.at(id).first.address()) : -1);
if (isPrivateAddress(peerAddress) && !m_server->m_netPrefs.localNetworking)
goto CONTINUE;
clogS(NetAllDetail) << "Checking: " << ep << "(" << id.abridged() << ")";
// check that it's not us or one we already know:
if (id && (m_server->m_id == id || m_server->havePeer(id) || m_server->m_incomingPeers.count(id)))
if (!(m_id == id && isPrivateAddress(endpoint().address()) && (!m_server->m_incomingPeers.count(id) || isPrivateAddress(m_server->m_incomingPeers.at(id).first.address()))) && (!id || m_server->m_id == id || m_server->m_incomingPeers.count(id)))
goto CONTINUE;
// check that we're not already connected to addr:
@ -180,7 +180,7 @@ bool Session::interpret(RLP const& _r)
m_server->m_incomingPeers[id] = make_pair(ep, 0);
m_server->m_freePeers.push_back(id);
m_server->noteNewPeers();
clogS(NetTriviaDetail) << "New peer: " << ep << "(" << id << ")";
clogS(NetTriviaDetail) << "New peer: " << ep << "(" << id .abridged()<< ")";
CONTINUE:;
}
break;

1
neth/CMakeLists.txt

@ -11,6 +11,7 @@ set(EXECUTABLE neth)
add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} secp256k1)
target_link_libraries(${EXECUTABLE} gmp)

29
neth/main.cpp

@ -39,6 +39,7 @@
#include <eth/CommonJS.h>
#include <eth/CommonJS.cpp>
#endif
#include <libwebthree/WebThree.h>
#include "BuildInfo.h"
#undef KEY_EVENT // from windows.h
@ -413,7 +414,9 @@ int main(int argc, char** argv)
if (!clientName.empty())
clientName += "/";
Client c("NEthereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), coinbase, dbPath);
WebThreeDirect web3("NEthereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), dbPath);
// mode doesn't work anymore: see eth for how that should be structured.
Client& c = *web3.ethereum();
c.setForceMining(true);
@ -479,7 +482,12 @@ int main(int argc, char** argv)
wmove(mainwin, 1, 4);
if (!remoteHost.empty())
c.startNetwork(listenPort, remoteHost, remotePort, mode, peers, publicIP, upnp);
{
web3.setIdealPeerCount(peers);
web3.setNetworkPreferences(NetworkPreferences(listenPort, publicIP, upnp));
web3.startNetwork();
web3.connect(remoteHost, remotePort);
}
if (mining)
c.startMining();
@ -487,7 +495,7 @@ int main(int argc, char** argv)
auto_ptr<EthStubServer> jsonrpcServer;
if (jsonrpc > -1)
{
jsonrpcServer = auto_ptr<EthStubServer>(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), c));
jsonrpcServer = auto_ptr<EthStubServer>(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), web3));
jsonrpcServer->setKeys({us});
jsonrpcServer->StartListening();
}
@ -528,18 +536,19 @@ int main(int argc, char** argv)
{
unsigned port;
iss >> port;
c.startNetwork((short)port);
web3.setNetworkPreferences(NetworkPreferences((short)port, publicIP, upnp));
web3.startNetwork();
}
else if (cmd == "connect")
{
string addr;
unsigned port;
iss >> addr >> port;
c.connect(addr, (short)port);
web3.connect(addr, (short)port);
}
else if (cmd == "netstop")
{
c.stopNetwork();
web3.stopNetwork();
}
else if (cmd == "minestart")
{
@ -560,7 +569,7 @@ int main(int argc, char** argv)
{
if (jsonrpc < 0)
jsonrpc = 8080;
jsonrpcServer = auto_ptr<EthStubServer>(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), c));
jsonrpcServer = auto_ptr<EthStubServer>(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), web3));
jsonrpcServer->setKeys({us});
jsonrpcServer->StartListening();
}
@ -589,7 +598,7 @@ int main(int argc, char** argv)
}
else if (cmd == "peers")
{
for (auto it: c.peers())
for (auto it: web3.peers())
cout << it.host << ":" << it.port << ", " << it.clientVersion << ", "
<< std::chrono::duration_cast<std::chrono::milliseconds>(it.lastPing).count() << "ms"
<< endl;
@ -925,7 +934,7 @@ int main(int argc, char** argv)
// Peers
y = 1;
for (PeerInfo const& i: c.peers())
for (PeerInfo const& i: web3.peers())
{
auto s = boost::format("%1% ms - %2%:%3% - %4%") %
toString(chrono::duration_cast<chrono::milliseconds>(i.lastPing).count()) %
@ -971,7 +980,7 @@ int main(int argc, char** argv)
// Peers
mvwprintw(peerswin, 0, x, "Peers: ");
mvwprintw(peerswin, 0, 9, toString(c.peers().size()).c_str());
mvwprintw(peerswin, 0, 9, toString(web3.peers().size()).c_str());
// Mining flag
if (c.isMining())

1
third/MainWin.cpp

@ -100,6 +100,7 @@ Main::Main(QWidget *parent) :
connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved()));
m_web3.reset(new WebThreeDirect("Third", getDataDir() + "/Third", false, {"eth", "shh"}));
m_web3->connect(Host::pocHost());
connect(ui->webView, &QWebView::loadStarted, [this]()
{

Loading…
Cancel
Save