Browse Source

Merge branch 'develop' into basenet

cl-refactor
Gav Wood 11 years ago
parent
commit
1c0aa7a0fc
  1. 12
      exp/main.cpp
  2. 38
      iethxi/EthereumMacOSXBundleInfo.plist.in
  3. 9
      iethxi/Simple.qml
  4. 7
      libethcore/BlockInfo.cpp
  5. 2
      libethcore/CommonEth.cpp
  6. 2
      libethential/Common.cpp
  7. 32
      libethereum/BlockChain.cpp
  8. 20
      libethereum/BlockQueue.cpp
  9. 51
      libethereum/EthereumHost.cpp
  10. 4
      libethereum/EthereumHost.h
  11. 54
      libethereum/EthereumSession.cpp
  12. 6
      libethereum/EthereumSession.h
  13. 2
      libethereum/Transaction.cpp
  14. 1
      libethereumx/CMakeLists.txt
  15. 30
      libethereumx/Ethereum.cpp
  16. 52
      libethnet/Common.h
  17. 33
      libethnet/PeerHost.cpp
  18. 20
      libethnet/PeerHost.h
  19. 31
      libethnet/PeerSession.cpp
  20. 13
      libethnet/PeerSession.h
  21. BIN
      third/alethzero.icns
  22. 14
      windows/LibEthereum.vcxproj

12
exp/main.cpp

@ -25,19 +25,24 @@
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/support_utree.hpp>
#endif
#include <libethential/Log.h>
#include <libethential/Common.h>
#include <libethential/CommonData.h>
#include <libethential/RLP.h>
#if 0
#include <libevm/VM.h>
#include "BuildInfo.h"
#endif
using namespace std;
using namespace eth;
#if 0
#if 0
namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;
namespace sp = boost::spirit;
#if 0
class ASTSymbol: public string
{
public:
@ -291,5 +296,8 @@ int main(int, char**)
killBigints(out);
cout << endl;
#endif
cnote << RLP(fromHex("f837c0c0b4600160003556601359506301000000600035040f6018590060005660805460016080530160005760003560805760203560003557"));
cnote << toHex(RLPStream(1).append(bytes(54, 0)).out());
return 0;
}

38
iethxi/EthereumMacOSXBundleInfo.plist.in

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

9
iethxi/Simple.qml

@ -0,0 +1,9 @@
import QtQuick.Controls 1.1
ApplicationWindow {
title: "My App"
Button {
text: "Push Me"
anchors.centerIn: parent
}
}

7
libethcore/BlockInfo.cpp

@ -71,6 +71,8 @@ h256 BlockInfo::headerHash(bytesConstRef _block)
void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
{
hash = eth::sha3(_header.data());
int field = 0;
try
{
@ -106,10 +108,9 @@ void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
void BlockInfo::populate(bytesConstRef _block, bool _checkNonce)
{
hash = eth::sha3(_block);
RLP root(_block);
RLP header = root[0];
if (!header.isList())
throw InvalidBlockFormat(0, header.data());
populateFromHeader(header, _checkNonce);
@ -171,7 +172,7 @@ u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const
if (!parentHash)
return c_genesisDifficulty;
else
return timestamp >= _parent.timestamp + 9 ? _parent.difficulty - (_parent.difficulty >> 10) : (_parent.difficulty + (_parent.difficulty >> 10));
return timestamp >= _parent.timestamp + 5 ? _parent.difficulty - (_parent.difficulty >> 10) : (_parent.difficulty + (_parent.difficulty >> 10));
}
void BlockInfo::verifyParent(BlockInfo const& _parent) const

2
libethcore/CommonEth.cpp

@ -29,7 +29,7 @@ using namespace eth;
//#define ETH_ADDRESS_DEBUG 1
const unsigned eth::c_protocolVersion = 28;
const unsigned eth::c_protocolVersion = 30;
const unsigned eth::c_databaseVersion = 1;
static const vector<pair<u256, string>> g_units =

2
libethential/Common.cpp

@ -27,6 +27,6 @@ using namespace eth;
namespace eth
{
char const* EthVersion = "0.6.6";
char const* EthVersion = "0.6.8";
}

32
libethereum/BlockChain.cpp

@ -165,6 +165,16 @@ bool contains(T const& _t, V const& _v)
return false;
}
inline string toString(h256s const& _bs)
{
ostringstream out;
out << "[ ";
for (auto i: _bs)
out << i.abridged() << ", ";
out << "]";
return out.str();
}
h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max)
{
vector<bytes> blocks;
@ -183,7 +193,7 @@ h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max
}
catch (UnknownParent)
{
cwarn << "Unknown parent of block!!!" << eth::sha3(block).abridged();
cwarn << "Unknown parent of block!!!" << BlockInfo::headerHash(block).abridged();
_bq.import(&block, *this);
}
catch (...){}
@ -223,7 +233,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
throw;
}
#endif
auto newHash = eth::sha3(_block);
auto newHash = BlockInfo::headerHash(_block);
// Check block doesn't already exist first!
if (details(newHash))
@ -320,20 +330,18 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
m_lastBlockHash = newHash;
}
m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32));
clog(BlockChainNote) << " Imported and best. Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:";
for (auto r: ret)
clog(BlockChainNote) << r.abridged();
clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret);
}
else
{
clog(BlockChainNote) << " Imported but not best (oTD:" << details(last).totalDifficulty << ", TD:" << td << ")";
clog(BlockChainNote) << " Imported but not best (oTD:" << details(last).totalDifficulty << " > TD:" << td << ")";
}
return ret;
}
h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, bool _post) const
{
cdebug << "treeRoute" << _from.abridged() << "..." << _to.abridged();
// cdebug << "treeRoute" << _from.abridged() << "..." << _to.abridged();
if (!_from || !_to)
{
return h256s();
@ -342,14 +350,14 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
h256s back;
unsigned fn = details(_from).number;
unsigned tn = details(_to).number;
cdebug << "treeRoute" << fn << "..." << tn;
// cdebug << "treeRoute" << fn << "..." << tn;
while (fn > tn)
{
if (_pre)
ret.push_back(_from);
_from = details(_from).parent;
fn--;
cdebug << "from:" << fn << _from.abridged();
// cdebug << "from:" << fn << _from.abridged();
}
while (fn < tn)
{
@ -357,7 +365,7 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
back.push_back(_to);
_to = details(_to).parent;
tn--;
cdebug << "to:" << tn << _to.abridged();
// cdebug << "to:" << tn << _to.abridged();
}
while (_from != _to)
{
@ -371,7 +379,7 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
back.push_back(_to);
fn--;
tn--;
cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged();
// cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged();
}
if (o_common)
*o_common = _from;
@ -408,7 +416,7 @@ h256Set BlockChain::allUnclesFrom(h256 _parent) const
h256 p = _parent;
for (unsigned i = 0; i < 6 && p != m_genesisHash; ++i, p = details(p).parent)
{
ret.insert(sha3(RLP(block(p))[0].data()));
ret.insert(p); // TODO: check: should this be details(p).parent?
for (auto i: RLP(block(p))[2])
ret.insert(sha3(i.data()));
}

20
libethereum/BlockQueue.cpp

@ -31,13 +31,18 @@ using namespace eth;
bool BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
{
// Check if we already know this block.
h256 h = sha3(_block);
h256 h = BlockInfo::headerHash(_block);
cnote << "Queuing block" << h.abridged() << "for import...";
UpgradableGuard l(m_lock);
if (m_readySet.count(h) || m_drainingSet.count(h) || m_futureSet.count(h))
{
// Already know about this one.
cnote << "Already known.";
return false;
}
// VERIFY: populates from the block and checks the block is internally coherent.
BlockInfo bi;
@ -56,15 +61,20 @@ bool BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
return false;
}
#endif
auto newHash = eth::sha3(_block);
// Check block doesn't already exist first!
if (_bc.details(newHash))
if (_bc.details(h))
{
cnote << "Already known in chain.";
return false;
}
// Check it's not crazy
if (bi.timestamp > (u256)time(0))
if (bi.timestamp > (u256)time(0) + 10)
{
cnote << "Invalid timestamp.";
return false;
}
{
UpgradeGuard ul(l);
@ -73,12 +83,14 @@ bool BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.details(bi.parentHash))
{
// We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on.
// cnote << "OK - queued for future.";
m_future.insert(make_pair(bi.parentHash, make_pair(h, _block.toBytes())));
m_futureSet.insert(h);
}
else
{
// If valid, append to blocks.
// cnote << "OK - ready for chain insertion.";
m_ready.push_back(_block.toBytes());
m_readySet.insert(h);

51
libethereum/EthereumHost.cpp

@ -367,22 +367,27 @@ void EthereumHost::connect(bi::tcp::endpoint const& _ep)
});
}
h256Set EthereumHost::neededBlocks()
h256Set EthereumHost::neededBlocks(h256Set const& _exclude)
{
Guard l(x_blocksNeeded);
h256Set ret;
if (m_blocksNeeded.size())
{
while (ret.size() < c_maxBlocksAsk && m_blocksNeeded.size())
{
ret.insert(m_blocksNeeded.back());
m_blocksOnWay.insert(m_blocksNeeded.back());
m_blocksNeeded.pop_back();
}
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);
}
}
else
for (auto i = m_blocksOnWay.begin(); ret.size() < c_maxBlocksAsk && i != m_blocksOnWay.end(); ++i)
if (!ret.size())
for (auto i = m_blocksOnWay.begin(); ret.size() < c_maxBlocksAsk && i != m_blocksOnWay.end() && !_exclude.count(*i); ++i)
ret.insert(*i);
clog(NetMessageSummary) << "Asking for" << ret.size() << "blocks that we don't yet have." << m_blocksNeeded.size() << "blocks still needed," << m_blocksOnWay.size() << "blocks on way.";
return ret;
}
@ -416,6 +421,17 @@ bool EthereumHost::ensureInitialised(TransactionQueue& _tq)
return false;
}
void EthereumHost::noteDoneBlocks()
{
clog(NetNote) << "Peer given up on blocks fetch.";
if (m_blocksOnWay.empty())
{
// Done our chain-get.
clog(NetNote) << "No more blocks coming. Missing" << m_blocksNeeded.size() << "blocks.";
m_latestBlockSent = m_chain->currentHash();
}
}
bool EthereumHost::noteBlock(h256 _hash, bytesConstRef _data)
{
Guard l(x_blocksNeeded);
@ -504,8 +520,14 @@ void EthereumHost::maintainBlocks(BlockQueue& _bq, h256 _currentHash)
m_incomingBlocks.clear();
}
// Send any new blocks.
if (_currentHash != m_latestBlockSent)
// If we've finished our initial sync...
{
Guard l(x_blocksNeeded);
if (m_blocksOnWay.size())
return;
}
// ...send any new blocks.
if (m_latestBlockSent != _currentHash)
{
RLPStream ts;
EthereumSession::prep(ts);
@ -516,6 +538,7 @@ void EthereumHost::maintainBlocks(BlockQueue& _bq, h256 _currentHash)
bs += m_chain->block(h);
++c;
}
clog(NetNote) << "Sending" << c << "new blocks (current is" << _currentHash << ", was" << m_latestBlockSent << ")";
ts.appendList(1 + c).append(BlocksPacket).appendRaw(bs, c);
bytes b;
ts.swapOut(b);
@ -529,8 +552,8 @@ void EthereumHost::maintainBlocks(BlockQueue& _bq, h256 _currentHash)
p->send(&b);
p->m_knownBlocks.clear();
}
m_latestBlockSent = _currentHash;
}
m_latestBlockSent = _currentHash;
}
void EthereumHost::growPeers()
@ -574,7 +597,7 @@ void EthereumHost::noteHaveChain(std::shared_ptr<EthereumSession> const& _from)
if (_from->m_neededBlocks.empty())
return;
clog(NetNote) << "Hash-chain COMPLETE:" << log2((double)_from->m_totalDifficulty) << "vs" << log2((double)m_chain->details().totalDifficulty) << "," << log2((double)m_totalDifficultyOfNeeded) << ";" << _from->m_neededBlocks.size() << " blocks, ends" << _from->m_neededBlocks.back().abridged();
clog(NetNote) << "Hash-chain COMPLETE:" << _from->m_totalDifficulty << "vs" << m_chain->details().totalDifficulty << "," << m_totalDifficultyOfNeeded << ";" << _from->m_neededBlocks.size() << " blocks, ends" << _from->m_neededBlocks.back().abridged();
if ((m_totalDifficultyOfNeeded && td < m_totalDifficultyOfNeeded) || td < m_chain->details().totalDifficulty)
{
@ -596,7 +619,7 @@ void EthereumHost::noteHaveChain(std::shared_ptr<EthereumSession> const& _from)
Guard l(x_peers);
for (auto const& i: m_peers)
if (shared_ptr<EthereumSession> p = i.second.lock())
p->ensureGettingChain();
p->restartGettingChain();
}
}

4
libethereum/EthereumHost.h

@ -113,6 +113,8 @@ private:
bool noteBlock(h256 _hash, bytesConstRef _data);
/// Session has finished getting the chain of hashes.
void noteHaveChain(std::shared_ptr<EthereumSession> const& _who);
/// Called when the peer can no longer provide us with any needed blocks.
void noteDoneBlocks();
/// Called when the session has provided us with a new peer we can connect to.
void noteNewPeers() {}
@ -129,7 +131,7 @@ private:
/// Get a bunch of needed blocks.
/// Removes them from our list of needed blocks.
/// @returns empty if there's no more blocks left to fetch, otherwise the blocks to fetch.
h256Set neededBlocks();
h256Set neededBlocks(h256Set const& _exclude);
/// Check to see if the network peer-state initialisation has happened.
virtual bool isInitialised() const { return m_latestBlockSent; }

54
libethereum/EthereumSession.cpp

@ -56,7 +56,7 @@ EthereumSession::~EthereumSession()
catch (...){}
}
string toString(h256s const& _bs)
inline string toString(h256s const& _bs)
{
ostringstream out;
out << "[ ";
@ -75,6 +75,7 @@ void EthereumSession::giveUpOnFetch()
m_server->m_blocksNeeded.reserve(m_server->m_blocksNeeded.size() + m_askedBlocks.size());
for (auto i: m_askedBlocks)
{
m_failedBlocks.insert(i);
m_server->m_blocksOnWay.erase(i);
m_server->m_blocksNeeded.push_back(i);
}
@ -109,8 +110,9 @@ bool EthereumSession::interpret(RLP const& _r)
m_id = _r[6].toHash<h512>();
m_totalDifficulty = _r[7].toInt<u256>();
m_latestHash = _r[8].toHash<h256>();
auto genesisHash = _r[9].toHash<h256>();
clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "/" << m_networkId << "]" << m_id.abridged() << showbase << hex << m_caps << dec << m_listenPort;
clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "/" << m_networkId << "/" << genesisHash.abridged() << "]" << m_id.abridged() << showbase << hex << m_caps << dec << m_listenPort;
if (m_server->havePeer(m_id))
{
@ -120,6 +122,12 @@ bool EthereumSession::interpret(RLP const& _r)
return false;
}
if (genesisHash != m_server->m_chain->genesisHash())
{
disconnect(WrongGenesis);
return false;
}
if (m_protocolVersion != EthereumHost::protocolVersion() || m_networkId != m_server->networkId() || !m_id)
{
disconnect(IncompatibleProtocol);
@ -301,17 +309,17 @@ bool EthereumSession::interpret(RLP const& _r)
break;
clogS(NetMessageSummary) << "Blocks (" << dec << (_r.itemCount() - 1) << " entries)";
if (_r.itemCount() == 1)
if (_r.itemCount() == 1 && !m_askedBlocksChanged)
{
// Couldn't get any from last batch - probably got to this peer's latest block - just give up.
giveUpOnFetch();
break;
}
m_askedBlocksChanged = false;
unsigned used = 0;
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
auto h = sha3(_r[i].data());
auto h = BlockInfo::headerHash(_r[i].data());
if (m_server->noteBlock(h, _r[i].data()))
used++;
m_askedBlocks.erase(h);
@ -324,7 +332,7 @@ bool EthereumSession::interpret(RLP const& _r)
{
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
auto h = sha3(_r[i].data());
auto h = BlockInfo::headerHash(_r[i].data());
BlockInfo bi(_r[i].data());
if (!m_server->m_chain->details(bi.parentHash) && !m_knownBlocks.count(bi.parentHash))
{
@ -339,7 +347,7 @@ bool EthereumSession::interpret(RLP const& _r)
}
}
clogS(NetMessageSummary) << dec << knownParents << " known parents, " << unknownParents << "unknown, " << used << "used.";
ensureGettingChain();
continueGettingChain();
break;
}
case GetTransactionsPacket:
@ -355,10 +363,30 @@ bool EthereumSession::interpret(RLP const& _r)
return true;
}
void EthereumSession::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 EthereumSession::ensureGettingChain()
{
if (m_askedBlocks.size())
return; // Already asked & waiting for some.
continueGettingChain();
}
void EthereumSession::continueGettingChain()
{
if (!m_askedBlocks.size())
m_askedBlocks = m_server->neededBlocks();
m_askedBlocks = m_server->neededBlocks(m_failedBlocks);
if (m_askedBlocks.size())
{
@ -370,7 +398,10 @@ void EthereumSession::ensureGettingChain()
sealAndSend(s);
}
else
clogS(NetMessageSummary) << "No blocks left to get.";
{
clogS(NetMessageSummary) << "No blocks left to get. Peer doesn't seem to have " << m_failedBlocks.size() << "of our needed blocks.";
m_server->noteDoneBlocks();
}
}
void EthereumSession::ping()
@ -513,7 +544,7 @@ void EthereumSession::start()
{
RLPStream s;
prep(s);
s.appendList(9) << HelloPacket
s.appendList(10) << HelloPacket
<< (uint)EthereumHost::protocolVersion()
<< m_server->networkId()
<< m_server->m_clientVersion
@ -521,7 +552,8 @@ void EthereumSession::start()
<< m_server->m_public.port()
<< m_server->m_key.pub()
<< m_server->m_chain->details().totalDifficulty
<< m_server->m_chain->currentHash();
<< m_server->m_chain->currentHash()
<< m_server->m_chain->genesisHash();
sealAndSend(s);
ping();
getPeers();

6
libethereum/EthereumSession.h

@ -60,6 +60,10 @@ private:
/// Ensure that we are waiting for a bunch of blocks from our peer.
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();
@ -97,8 +101,10 @@ 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;
std::chrono::steady_clock::time_point m_ping;
std::chrono::steady_clock::time_point m_connect;

2
libethereum/Transaction.cpp

@ -27,7 +27,7 @@
using namespace std;
using namespace eth;
#define ETH_ADDRESS_DEBUG 1
#define ETH_ADDRESS_DEBUG 0
Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender)
{

1
libethereumx/CMakeLists.txt

@ -17,6 +17,7 @@ file(GLOB HEADERS "*.h")
include_directories(..)
target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} ethcore)

30
libethereumx/Ethereum.cpp

@ -63,63 +63,67 @@ void Ethereum::startServer()
{
}
void Client::flushTransactions()
void Ethereum::flushTransactions()
{
}
std::vector<PeerInfo> Client::peers()
std::vector<PeerInfo> Ethereum::peers()
{
return std::vector<PeerInfo>();
}
size_t Client::peerCount() const
size_t Ethereum::peerCount() const
{
return 0;
}
void Client::connect(std::string const& _seedHost, unsigned short _port)
void Ethereum::connect(std::string const& _seedHost, unsigned short _port)
{
}
void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
void Ethereum::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
{
}
bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
bytes Ethereum::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
{
return bytes();
}
Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice)
Address Ethereum::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice)
{
return Address();
}
void Client::inject(bytesConstRef _rlp)
void Ethereum::inject(bytesConstRef _rlp)
{
}
u256 Client::balanceAt(Address _a, int _block) const
u256 Ethereum::balanceAt(Address _a, int _block) const
{
return u256();
}
std::map<u256, u256> Client::storageAt(Address _a, int _block) const
PastMessages Ethereum::messages(MessageFilter const& _filter) const
{
}
std::map<u256, u256> Ethereum::storageAt(Address _a, int _block) const
{
return std::map<u256, u256>();
}
u256 Client::countAt(Address _a, int _block) const
u256 Ethereum::countAt(Address _a, int _block) const
{
return u256();
}
u256 Client::stateAt(Address _a, u256 _l, int _block) const
u256 Ethereum::stateAt(Address _a, u256 _l, int _block) const
{
return u256();
}
bytes Client::codeAt(Address _a, int _block) const
bytes Ethereum::codeAt(Address _a, int _block) const
{
return bytes();
}

52
libethnet/Common.h

@ -37,6 +37,7 @@ namespace eth
bool isPrivateAddress(bi::address _addressToCheck);
class RLP;
class PeerHost;
class PeerSession;
@ -88,4 +89,55 @@ struct PeerInfo
class UPnP;
class PeerCapability;
class HostCapabilityFace
{
public:
HostCapabilityFace(PeerHost*) {}
virtual ~HostCapabilityFace() {}
virtual std::string name() const = 0;
virtual PeerCapability* newPeerCapability(PeerSession* _s) = 0;
};
template<class PeerCap>
class HostCapability: public HostCapabilityFace
{
public:
HostCapability(PeerHost* _h): m_host(_h) {}
virtual ~HostCapability() {}
static std::string staticName() { return PeerCap::name(); }
PeerHost* host() const { return m_host; }
protected:
virtual std::string name() const { return PeerCap::name(); }
virtual PeerCapability* newPeerCapability(PeerSession* _s) { return new PeerCap(_s); }
private:
PeerHost* m_host;
};
class PeerCapability
{
friend class PeerSession;
public:
PeerCapability(PeerSession* _s): m_session(_s) {}
virtual ~PeerCapability() {}
/// Must return the capability name.
static std::string name() { return ""; }
PeerSession* session() const { return m_session; }
protected:
virtual bool interpret(RLP const&) = 0;
private:
PeerSession* m_session;
};
}

33
libethnet/PeerHost.cpp

@ -52,13 +52,12 @@ static const set<bi::address> c_rejectAddresses = {
{bi::address_v6::from_string("::")}
};
PeerHost::PeerHost(std::string const& _clientVersion, u256 _networkId, unsigned short _port, string const& _publicAddress, bool _upnp):
PeerHost::PeerHost(std::string const& _clientVersion, unsigned short _port, string const& _publicAddress, bool _upnp):
m_clientVersion(_clientVersion),
m_listenPort(_port),
m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), _port)),
m_socket(m_ioService),
m_key(KeyPair::create()),
m_networkId(_networkId)
m_key(KeyPair::create())
{
populateAddresses();
determinePublic(_publicAddress, _upnp);
@ -66,13 +65,12 @@ PeerHost::PeerHost(std::string const& _clientVersion, u256 _networkId, unsigned
clog(NetNote) << "Id:" << toHex(m_key.address().ref().cropped(0, 4));
}
PeerHost::PeerHost(std::string const& _clientVersion, u256 _networkId, string const& _publicAddress, bool _upnp):
PeerHost::PeerHost(std::string const& _clientVersion, string const& _publicAddress, bool _upnp):
m_clientVersion(_clientVersion),
m_listenPort(0),
m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), 0)),
m_socket(m_ioService),
m_key(KeyPair::create()),
m_networkId(_networkId)
m_key(KeyPair::create())
{
m_listenPort = m_acceptor.local_endpoint().port();
@ -83,13 +81,12 @@ PeerHost::PeerHost(std::string const& _clientVersion, u256 _networkId, string co
clog(NetNote) << "Id:" << toHex(m_key.address().ref().cropped(0, 4));
}
PeerHost::PeerHost(std::string const& _clientVersion, u256 _networkId):
PeerHost::PeerHost(std::string const& _clientVersion):
m_clientVersion(_clientVersion),
m_listenPort(0),
m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), 0)),
m_socket(m_ioService),
m_key(KeyPair::create()),
m_networkId(_networkId)
m_key(KeyPair::create())
{
// populate addresses.
populateAddresses();
@ -101,10 +98,20 @@ PeerHost::~PeerHost()
disconnectPeers();
}
unsigned PeerHost::protocolVersion() const
{
return 0;
}
void PeerHost::registerPeer(std::shared_ptr<PeerSession> _s)
{
Guard l(x_peers);
m_peers[_s->m_id] = _s;
{
Guard l(x_peers);
m_peers[_s->m_id] = _s;
}
for (auto const& i: _s->m_caps)
if (haveCapability(i))
_s->m_capabilities.push_back(shared_ptr<PeerCapability>(m_capabilities[i]->newPeerCapability(_s.get())));
}
void PeerHost::disconnectPeers()
@ -293,7 +300,7 @@ void PeerHost::ensureAccepting()
} catch (...){}
bi::address remoteAddress = m_socket.remote_endpoint().address();
// Port defaults to 0 - we let the hello tell us which port the peer listens to
auto p = std::make_shared<PeerSession>(this, std::move(m_socket), m_networkId, remoteAddress);
auto p = std::make_shared<PeerSession>(this, std::move(m_socket), remoteAddress);
p->start();
}
catch (std::exception const& _e)
@ -341,7 +348,7 @@ void PeerHost::connect(bi::tcp::endpoint const& _ep)
}
else
{
auto p = make_shared<PeerSession>(this, std::move(*s), m_networkId, _ep.address(), _ep.port());
auto p = make_shared<PeerSession>(this, std::move(*s), _ep.address(), _ep.port());
clog(NetConnect) << "Connected to " << _ep;
p->start();
}

20
libethnet/PeerHost.h

@ -47,11 +47,11 @@ class PeerHost
public:
/// Start server, listening for connections on the given port.
PeerHost(std::string const& _clientVersion, u256 _networkId, unsigned short _port, std::string const& _publicAddress = std::string(), bool _upnp = true);
PeerHost(std::string const& _clientVersion, unsigned short _port, std::string const& _publicAddress = std::string(), bool _upnp = true);
/// Start server, listening for connections on a system-assigned port.
PeerHost(std::string const& _clientVersion, u256 _networkId, std::string const& _publicAddress = std::string(), bool _upnp = true);
PeerHost(std::string const& _clientVersion, std::string const& _publicAddress = std::string(), bool _upnp = true);
/// Start server, but don't listen.
PeerHost(std::string const& _clientVersion, u256 _networkId);
PeerHost(std::string const& _clientVersion);
/// Will block on network process events.
virtual ~PeerHost();
@ -59,8 +59,11 @@ public:
/// Closes all peers.
void disconnectPeers();
virtual u256 networkId() { return m_networkId; }
virtual unsigned protocolVersion() { return 0; }
/// Basic peer network protocol version.
unsigned protocolVersion() const;
/// Register a peer-capability; all new peer connections will have this capability.
template <class T> void registerCapability() { m_capabilities[T::name()] = std::shared_ptr<HostCapabilityFace>(new T(this)); }
/// Connect to a peer explicitly.
void connect(std::string const& _addr, unsigned short _port = 30303) noexcept;
@ -97,6 +100,9 @@ public:
void registerPeer(std::shared_ptr<PeerSession> _s);
bool haveCapability(std::string const& _name) const { return m_capabilities.count(_name); }
std::vector<std::string> caps() const { std::vector<std::string> ret; for (auto const& i: m_capabilities) ret.push_back(i.first); return ret; }
protected:
/// Called when the session has provided us with a new peer we can connect to.
void noteNewPeers() {}
@ -124,8 +130,6 @@ protected:
bi::tcp::endpoint m_public;
KeyPair m_key;
u256 m_networkId;
mutable std::mutex x_peers;
mutable std::map<Public, std::weak_ptr<PeerSession>> m_peers; // mutable because we flush zombie entries (null-weakptrs) as regular maintenance from a const method.
@ -139,6 +143,8 @@ protected:
std::vector<bi::address_v4> m_addresses;
std::vector<bi::address_v4> m_peerAddresses;
std::map<std::string, std::shared_ptr<HostCapabilityFace>> m_capabilities;
bool m_accepting = false;
};

31
libethnet/PeerSession.cpp

@ -30,10 +30,9 @@ using namespace eth;
#define clogS(X) eth::LogOutputStream<X, true>(false) << "| " << std::setw(2) << m_socket.native_handle() << "] "
PeerSession::PeerSession(PeerHost* _s, bi::tcp::socket _socket, u256 _rNId, bi::address _peerAddress, unsigned short _peerPort):
PeerSession::PeerSession(PeerHost* _s, bi::tcp::socket _socket, bi::address _peerAddress, unsigned short _peerPort):
m_server(_s),
m_socket(std::move(_socket)),
m_reqNetworkId(_rNId),
m_listenPort(_peerPort),
m_rating(0)
{
@ -45,6 +44,9 @@ PeerSession::PeerSession(PeerHost* _s, bi::tcp::socket _socket, u256 _rNId, bi::
PeerSession::~PeerSession()
{
// Read-chain finished for one reason or another.
for (auto& i: m_capabilities)
i.reset();
try
{
if (m_socket.is_open())
@ -65,7 +67,7 @@ bi::tcp::endpoint PeerSession::endpoint() const
return bi::tcp::endpoint();
}
bool PeerSession::preInterpret(RLP const& _r)
bool PeerSession::interpret(RLP const& _r)
{
clogS(NetRight) << _r;
switch (_r[0].toInt<unsigned>())
@ -73,13 +75,12 @@ bool PeerSession::preInterpret(RLP const& _r)
case HelloPacket:
{
m_protocolVersion = _r[1].toInt<uint>();
m_networkId = _r[2].toInt<u256>();
auto clientVersion = _r[3].toString();
m_caps = _r[4].toInt<uint>();
m_listenPort = _r[5].toInt<unsigned short>();
m_id = _r[6].toHash<h512>();
auto clientVersion = _r[2].toString();
m_caps = _r[3].toVector<string>();
m_listenPort = _r[4].toInt<unsigned short>();
m_id = _r[5].toHash<h512>();
clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "/" << m_networkId << "]" << m_id.abridged() << showbase << hex << m_caps << dec << m_listenPort;
clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "]" << m_id.abridged() << showbase << hex << m_caps << dec << m_listenPort;
if (m_server->havePeer(m_id))
{
@ -89,7 +90,7 @@ bool PeerSession::preInterpret(RLP const& _r)
return false;
}
if (m_protocolVersion != m_server->protocolVersion() || m_networkId != m_server->networkId() || !m_id)
if (m_protocolVersion != m_server->protocolVersion() || !m_id)
{
disconnect(IncompatibleProtocol);
return false;
@ -103,7 +104,6 @@ bool PeerSession::preInterpret(RLP const& _r)
}
m_server->registerPeer(shared_from_this());
onNewPeer();
break;
}
case DisconnectPacket:
@ -179,7 +179,10 @@ bool PeerSession::preInterpret(RLP const& _r)
}
break;
default:
return interpret(_r);
for (auto const& i: m_capabilities)
if (i->interpret(_r))
return true;
return false;
}
return true;
}
@ -326,8 +329,8 @@ void PeerSession::start()
prep(s);
s.appendList(9) << HelloPacket
<< m_server->protocolVersion()
<< m_server->networkId()
<< m_server->m_clientVersion
<< m_server->caps()
<< m_server->m_public.port()
<< m_server->m_key.pub();
sealAndSend(s);
@ -390,7 +393,7 @@ void PeerSession::doRead()
else
{
RLP r(data.cropped(8));
if (!preInterpret(r))
if (!interpret(r))
{
// error
dropped();

13
libethnet/PeerSession.h

@ -42,7 +42,7 @@ class PeerSession: public std::enable_shared_from_this<PeerSession>
friend class PeerHost;
public:
PeerSession(PeerHost* _server, bi::tcp::socket _socket, u256 _rNId, bi::address _peerAddress, unsigned short _peerPort = 0);
PeerSession(PeerHost* _server, bi::tcp::socket _socket, bi::address _peerAddress, unsigned short _peerPort = 0);
virtual ~PeerSession();
void start();
@ -55,9 +55,6 @@ public:
bi::tcp::endpoint endpoint() const; ///< for other peers to connect to.
protected:
virtual bool interpret(RLP const& _r);
virtual void onNewPeer();
static RLPStream& prep(RLPStream& _s);
void sealAndSend(RLPStream& _s);
void sendDestroy(bytes& _msg);
@ -71,7 +68,7 @@ private:
void write();
void getPeers();
bool preInterpret(RLP const& _r);
bool interpret(RLP const& _r);
/// @returns true iff the _msg forms a valid message for sending or receiving on the network.
static bool checkPacket(bytesConstRef _msg);
@ -88,10 +85,8 @@ private:
bytes m_incoming;
uint m_protocolVersion;
u256 m_networkId;
u256 m_reqNetworkId;
unsigned short m_listenPort; ///< Port that the remote client is listening on for connections. Useful for giving to peers.
uint m_caps;
std::vector<std::string> m_caps;
std::chrono::steady_clock::time_point m_ping;
std::chrono::steady_clock::time_point m_connect;
@ -99,6 +94,8 @@ private:
uint m_rating;
std::vector<std::shared_ptr<PeerCapability>> m_capabilities;
bool m_willBeDeleted = false; ///< True if we already posted a deleter on the strand.
};

BIN
third/alethzero.icns

Binary file not shown.

14
windows/LibEthereum.vcxproj

@ -41,15 +41,16 @@
<ClCompile Include="..\libethereum\BlockDetails.cpp" />
<ClCompile Include="..\libethereum\BlockQueue.cpp" />
<ClCompile Include="..\libethereum\Client.cpp" />
<ClCompile Include="..\libethereum\CommonNet.cpp" />
<ClCompile Include="..\libethereum\Defaults.cpp" />
<ClCompile Include="..\libethereum\EthereumHost.cpp" />
<ClCompile Include="..\libethereum\EthereumSession.cpp" />
<ClCompile Include="..\libethereum\Executive.cpp" />
<ClCompile Include="..\libethereum\ExtVM.cpp" />
<ClCompile Include="..\libethereum\Manifest.cpp" />
<ClCompile Include="..\libethereum\MessageFilter.cpp" />
<ClCompile Include="..\libethereum\Miner.cpp" />
<ClCompile Include="..\libethereum\PeerNetwork.cpp" />
<ClCompile Include="..\libethereum\PeerServer.cpp" />
<ClCompile Include="..\libethereum\PeerSession.cpp" />
<ClCompile Include="..\libethereum\PastMessage.cpp" />
<ClCompile Include="..\libethereum\State.cpp" />
<ClCompile Include="..\libethereum\Transaction.cpp" />
<ClCompile Include="..\libethereum\TransactionQueue.cpp" />
@ -100,15 +101,16 @@
<ClInclude Include="..\libethereum\BlockDetails.h" />
<ClInclude Include="..\libethereum\BlockQueue.h" />
<ClInclude Include="..\libethereum\Client.h" />
<ClInclude Include="..\libethereum\CommonNet.h" />
<ClInclude Include="..\libethereum\Defaults.h" />
<ClInclude Include="..\libethereum\EthereumHost.h" />
<ClInclude Include="..\libethereum\EthereumSession.h" />
<ClInclude Include="..\libethereum\Executive.h" />
<ClInclude Include="..\libethereum\ExtVM.h" />
<ClInclude Include="..\libethereum\Manifest.h" />
<ClInclude Include="..\libethereum\MessageFilter.h" />
<ClInclude Include="..\libethereum\Miner.h" />
<ClInclude Include="..\libethereum\PeerNetwork.h" />
<ClInclude Include="..\libethereum\PeerServer.h" />
<ClInclude Include="..\libethereum\PeerSession.h" />
<ClInclude Include="..\libethereum\PastMessage.h" />
<ClInclude Include="..\libethereum\State.h" />
<ClInclude Include="..\libethereum\Transaction.h" />
<ClInclude Include="..\libethereum\TransactionQueue.h" />

Loading…
Cancel
Save