Browse Source

Merge remote-tracking branch 'up/develop' into event_watcher

cl-refactor
yann300 10 years ago
parent
commit
11826b62ec
  1. 24
      eth/main.cpp
  2. 1
      libdevcore/Common.h
  3. 2
      libethereum/BlockChain.cpp
  4. 6
      libethereum/BlockQueue.cpp
  5. 2
      libethereum/State.cpp
  6. 24
      libethereum/VerifiedBlock.h
  7. 11
      libp2p/Common.h
  8. 14
      libp2p/Host.cpp
  9. 12
      libp2p/RLPXFrameCoder.cpp
  10. 14
      libp2p/RLPXFrameCoder.h
  11. 286
      libp2p/Session.cpp
  12. 10
      libp2p/Session.h
  13. 36
      libsolidity/AST.cpp
  14. 2
      libwhisper/BloomFilter.h
  15. 6
      libwhisper/Common.cpp
  16. 8
      libwhisper/Common.h
  17. 12
      libwhisper/WhisperHost.cpp
  18. 4
      libwhisper/WhisperHost.h
  19. 7
      libwhisper/WhisperPeer.cpp
  20. 10
      libwhisper/WhisperPeer.h
  21. 10
      test/libp2p/net.cpp
  22. 17
      test/libsolidity/SolidityNameAndTypeResolution.cpp
  23. 4
      test/libwhisper/bloomFilter.cpp
  24. 18
      test/libwhisper/whisperTopic.cpp

24
eth/main.cpp

@ -703,12 +703,24 @@ int main(int argc, char** argv)
string logbuf; string logbuf;
std::string additional; std::string additional;
g_logPost = [&](std::string const& a, char const*){ if (interactive)
if (g_silence) g_logPost = [&](std::string const& a, char const*){
logbuf += a + "\n"; static SpinLock s_lock;
else SpinGuard l(s_lock);
cout << "\r \r" << a << endl << additional << flush;
}; if (g_silence)
logbuf += a + "\n";
else
cout << "\r \r" << a << endl << additional << flush;
// helpful to use OutputDebugString on windows
#ifdef _WIN32
{
OutputDebugStringA(a.data());
OutputDebugStringA("\n");
}
#endif
};
auto getPassword = [&](string const& prompt){ auto getPassword = [&](string const& prompt){
auto s = g_silence; auto s = g_silence;

1
libdevcore/Common.h

@ -45,7 +45,6 @@
#pragma warning(push) #pragma warning(push)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-fpermissive"
#include <boost/version.hpp> #include <boost/version.hpp>
#if (BOOST_VERSION == 105800) #if (BOOST_VERSION == 105800)
#include "boost_multiprecision_number_compare_bug_workaround.hpp" #include "boost_multiprecision_number_compare_bug_workaround.hpp"

2
libethereum/BlockChain.cpp

@ -541,7 +541,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
#endif #endif
} }
#if ETH_CATCH #if ETH_CATCH
catch (BadRoot& ex) catch (BadRoot&)
{ {
cwarn << "BadRoot error. Retrying import later."; cwarn << "BadRoot error. Retrying import later.";
BOOST_THROW_EXCEPTION(FutureTime()); BOOST_THROW_EXCEPTION(FutureTime());

6
libethereum/BlockQueue.cpp

@ -102,7 +102,7 @@ void BlockQueue::verifierBody()
BlockInfo bi; BlockInfo bi;
bi.mixHash = work.hash; bi.mixHash = work.hash;
bi.parentHash = work.parentHash; bi.parentHash = work.parentHash;
m_verifying.push_back(VerifiedBlock { VerifiedBlockRef { bytesConstRef(), move(bi), Transactions() }, bytes() }); m_verifying.emplace_back(move(bi));
} }
VerifiedBlock res; VerifiedBlock res;
@ -148,7 +148,7 @@ void BlockQueue::verifierBody()
m_knownBad.insert(res.verified.info.hash()); m_knownBad.insert(res.verified.info.hash());
} }
else else
m_verified.push_back(move(res)); m_verified.emplace_back(move(res));
while (m_verifying.size() && !m_verifying.front().blockData.empty()) while (m_verifying.size() && !m_verifying.front().blockData.empty())
{ {
if (m_knownBad.count(m_verifying.front().verified.info.parentHash)) if (m_knownBad.count(m_verifying.front().verified.info.parentHash))
@ -157,7 +157,7 @@ void BlockQueue::verifierBody()
m_knownBad.insert(res.verified.info.hash()); m_knownBad.insert(res.verified.info.hash());
} }
else else
m_verified.push_back(move(m_verifying.front())); m_verified.emplace_back(move(m_verifying.front()));
m_verifying.pop_front(); m_verifying.pop_front();
} }
ready = true; ready = true;

2
libethereum/State.cpp

@ -116,7 +116,7 @@ State::State(OverlayDB const& _db, BaseState _bs, Address _coinbaseAddress):
PopulationStatistics State::populateFromChain(BlockChain const& _bc, h256 const& _h, ImportRequirements::value _ir) PopulationStatistics State::populateFromChain(BlockChain const& _bc, h256 const& _h, ImportRequirements::value _ir)
{ {
PopulationStatistics ret; PopulationStatistics ret { 0.0, 0.0 };
if (!_bc.isKnown(_h)) if (!_bc.isKnown(_h))
{ {

24
libethereum/VerifiedBlock.h

@ -43,8 +43,32 @@ struct VerifiedBlockRef
/// @brief Verified block info, combines block data and verified info/transactions /// @brief Verified block info, combines block data and verified info/transactions
struct VerifiedBlock struct VerifiedBlock
{ {
VerifiedBlock() {};
VerifiedBlock(BlockInfo&& _bi)
{
verified.info = _bi;
}
VerifiedBlock(VerifiedBlock&& _other):
verified(std::move(_other.verified)),
blockData(std::move(_other.blockData))
{
}
VerifiedBlock& operator=(VerifiedBlock&& _other)
{
verified = (std::move(_other.verified));
blockData = (std::move(_other.blockData));
return *this;
}
VerifiedBlockRef verified; ///< Verified block structures VerifiedBlockRef verified; ///< Verified block structures
bytes blockData; ///< Block data bytes blockData; ///< Block data
private:
VerifiedBlock(VerifiedBlock const&) = delete;
VerifiedBlock operator=(VerifiedBlock const&) = delete;
}; };
using VerifiedBlocks = std::vector<VerifiedBlock>; using VerifiedBlocks = std::vector<VerifiedBlock>;

11
libp2p/Common.h

@ -149,14 +149,15 @@ using CapDescs = std::vector<CapDesc>;
*/ */
struct PeerSessionInfo struct PeerSessionInfo
{ {
NodeId id; NodeId const id;
std::string clientVersion; std::string const clientVersion;
std::string host; std::string const host;
unsigned short port; unsigned short const port;
std::chrono::steady_clock::duration lastPing; std::chrono::steady_clock::duration lastPing;
std::set<CapDesc> caps; std::set<CapDesc> const caps;
unsigned socketId; unsigned socketId;
std::map<std::string, std::string> notes; std::map<std::string, std::string> notes;
unsigned const protocolVersion;
}; };
using PeerSessionInfos = std::vector<PeerSessionInfo>; using PeerSessionInfos = std::vector<PeerSessionInfo>;

14
libp2p/Host.cpp

@ -254,7 +254,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameCoder*
clog(NetMessageSummary) << "Hello: " << clientVersion << "V[" << protocolVersion << "]" << _id << showbase << capslog.str() << dec << listenPort; clog(NetMessageSummary) << "Hello: " << clientVersion << "V[" << protocolVersion << "]" << _id << showbase << capslog.str() << dec << listenPort;
// create session so disconnects are managed // create session so disconnects are managed
auto ps = make_shared<Session>(this, _io, _s, p, PeerSessionInfo({_id, clientVersion, p->endpoint.address.to_string(), listenPort, chrono::steady_clock::duration(), _rlp[2].toSet<CapDesc>(), 0, map<string, string>()})); auto ps = make_shared<Session>(this, _io, _s, p, PeerSessionInfo({_id, clientVersion, p->endpoint.address.to_string(), listenPort, chrono::steady_clock::duration(), _rlp[2].toSet<CapDesc>(), 0, map<string, string>(), protocolVersion}));
if (protocolVersion < dev::p2p::c_protocolVersion - 1) if (protocolVersion < dev::p2p::c_protocolVersion - 1)
{ {
ps->disconnect(IncompatibleProtocol); ps->disconnect(IncompatibleProtocol);
@ -725,8 +725,16 @@ void Host::startedWorking()
void Host::doWork() void Host::doWork()
{ {
if (m_run) try
m_ioService.run(); {
if (m_run)
m_ioService.run();
}
catch (std::exception const& _e)
{
clog(NetP2PWarn) << "Exception in Network Thread:" << _e.what();
clog(NetP2PWarn) << "Network Restart is Recommended.";
}
} }
void Host::keepAlivePeers() void Host::keepAlivePeers()

12
libp2p/RLPXFrameCoder.cpp

@ -29,6 +29,18 @@ using namespace dev;
using namespace dev::p2p; using namespace dev::p2p;
using namespace CryptoPP; using namespace CryptoPP;
RLPXFrameInfo::RLPXFrameInfo(bytesConstRef _header)
{
length = (_header[0] * 256 + _header[1]) * 256 + _header[2];
padding = ((16 - (length % 16)) % 16);
RLP header(_header.cropped(3), RLP::ThrowOnFail | RLP::FailIfTooSmall);
auto itemCount = header.itemCount();
protocolId = header[0].toInt<uint16_t>();
hasSequence = itemCount > 1;
sequenceId = hasSequence ? header[1].toInt<uint16_t>() : 0;
totalLength = itemCount == 3 ? header[2].toInt<uint32_t>() : 0;
}
RLPXFrameCoder::RLPXFrameCoder(RLPXHandshake const& _init) RLPXFrameCoder::RLPXFrameCoder(RLPXHandshake const& _init)
{ {
// we need: // we need:

14
libp2p/RLPXFrameCoder.h

@ -32,7 +32,21 @@ namespace dev
{ {
namespace p2p namespace p2p
{ {
struct RLPXFrameInfo
{
RLPXFrameInfo() = default;
/// Constructor. frame-size || protocol-type, [sequence-id[, total-packet-size]]
RLPXFrameInfo(bytesConstRef _frameHeader);
uint32_t length = 0; ///< Max: 2**24
uint8_t padding = 0;
uint16_t protocolId = 0;
bool hasSequence = false;
uint16_t sequenceId = 0;
uint32_t totalLength = 0;
};
class RLPXHandshake; class RLPXHandshake;
/** /**

286
libp2p/Session.cpp

@ -27,7 +27,6 @@
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/StructuredLogger.h> #include <libdevcore/StructuredLogger.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include "RLPxHandshake.h"
#include "Host.h" #include "Host.h"
#include "Capability.h" #include "Capability.h"
using namespace std; using namespace std;
@ -157,114 +156,25 @@ void Session::serviceNodesRequest()
addNote("peers", "done"); addNote("peers", "done");
} }
bool Session::interpret(PacketType _t, RLP const& _r) bool Session::readPacket(uint16_t _capId, PacketType _t, RLP const& _r)
{ {
m_lastReceived = chrono::steady_clock::now(); m_lastReceived = chrono::steady_clock::now();
clog(NetRight) << _t << _r; clog(NetRight) << _t << _r;
try // Generic try-catch block designed to capture RLP format errors - TODO: give decent diagnostics, make a bit more specific over what is caught. try // Generic try-catch block designed to capture RLP format errors - TODO: give decent diagnostics, make a bit more specific over what is caught.
{ {
switch (_t) // v4 frame headers are useless, offset packet type used
{ // v5 protocol type is in header, packet type not offset
case DisconnectPacket: if (_capId == 0 && _t < UserPacket)
{ return interpret(_t, _r);
string reason = "Unspecified"; if (m_info.protocolVersion >= 5)
auto r = (DisconnectReason)_r[0].toInt<int>(); for (auto const& i: m_capabilities)
if (!_r[0].isInt()) if (_capId == (uint16_t)i.first.second)
drop(BadProtocol); return i.second->m_enabled ? i.second->interpret(_t, _r) : true;
else if (m_info.protocolVersion <= 4)
{
reason = reasonOf(r);
clog(NetMessageSummary) << "Disconnect (reason: " << reason << ")";
drop(DisconnectRequested);
}
break;
}
case PingPacket:
{
clog(NetTriviaSummary) << "Ping";
RLPStream s;
sealAndSend(prep(s, PongPacket));
break;
}
case PongPacket:
{
DEV_GUARDED(x_info)
m_info.lastPing = std::chrono::steady_clock::now() - m_ping;
clog(NetTriviaSummary) << "Latency: " << chrono::duration_cast<chrono::milliseconds>(m_info.lastPing).count() << " ms";
break;
}
case GetPeersPacket:
// Disabled for interop testing.
// GetPeers/PeersPacket will be modified to only exchange new nodes which it's peers are interested in.
break;
clog(NetTriviaSummary) << "GetPeers";
m_theyRequestedNodes = true;
serviceNodesRequest();
break;
case PeersPacket:
// Disabled for interop testing.
// GetPeers/PeersPacket will be modified to only exchange new nodes which it's peers are interested in.
break;
clog(NetTriviaSummary) << "Peers (" << dec << (_r.itemCount() - 1) << " entries)";
m_weRequestedNodes = false;
for (unsigned i = 0; i < _r.itemCount(); ++i)
{
bi::address peerAddress;
if (_r[i][0].size() == 16)
peerAddress = bi::address_v6(_r[i][0].toHash<FixedHash<16>>().asArray());
else if (_r[i][0].size() == 4)
peerAddress = bi::address_v4(_r[i][0].toHash<FixedHash<4>>().asArray());
else
{
cwarn << "Received bad peer packet:" << _r;
disconnect(BadProtocol);
return true;
}
auto ep = bi::tcp::endpoint(peerAddress, _r[i][1].toInt<short>());
NodeId id = _r[i][2].toHash<NodeId>();
clog(NetAllDetail) << "Checking: " << ep << "(" << id << ")";
if (!isPublicAddress(peerAddress))
goto CONTINUE; // Private address. Ignore.
if (!id)
goto LAMEPEER; // Null identity. Ignore.
if (m_server->id() == id)
goto LAMEPEER; // Just our info - we already have that.
if (id == this->id())
goto LAMEPEER; // Just their info - we already have that.
if (!ep.port())
goto LAMEPEER; // Zero port? Don't think so.
if (ep.port() >= /*49152*/32768)
goto LAMEPEER; // Private port according to IANA.
// OK passed all our checks. Assume it's good.
addRating(1000);
m_server->addNode(id, NodeIPEndpoint(ep.address(), ep.port(), ep.port()));
clog(NetTriviaDetail) << "New peer: " << ep << "(" << id << ")";
CONTINUE:;
LAMEPEER:;
}
break;
default:
for (auto const& i: m_capabilities) for (auto const& i: m_capabilities)
if (_t >= (int)i.second->m_idOffset && _t - i.second->m_idOffset < i.second->hostCapability()->messageCount()) if (_t >= (int)i.second->m_idOffset && _t - i.second->m_idOffset < i.second->hostCapability()->messageCount())
{ return i.second->m_enabled ? i.second->interpret(_t - i.second->m_idOffset, _r) : true;
if (i.second->m_enabled) return false;
return i.second->interpret(_t - i.second->m_idOffset, _r);
else
return true;
}
return false;
}
} }
catch (std::exception const& _e) catch (std::exception const& _e)
{ {
@ -275,6 +185,47 @@ bool Session::interpret(PacketType _t, RLP const& _r)
return true; return true;
} }
bool Session::interpret(PacketType _t, RLP const& _r)
{
switch (_t)
{
case DisconnectPacket:
{
string reason = "Unspecified";
auto r = (DisconnectReason)_r[0].toInt<int>();
if (!_r[0].isInt())
drop(BadProtocol);
else
{
reason = reasonOf(r);
clog(NetMessageSummary) << "Disconnect (reason: " << reason << ")";
drop(DisconnectRequested);
}
break;
}
case PingPacket:
{
clog(NetTriviaSummary) << "Ping";
RLPStream s;
sealAndSend(prep(s, PongPacket));
break;
}
case PongPacket:
DEV_GUARDED(x_info)
{
m_info.lastPing = std::chrono::steady_clock::now() - m_ping;
clog(NetTriviaSummary) << "Latency: " << chrono::duration_cast<chrono::milliseconds>(m_info.lastPing).count() << " ms";
}
break;
case GetPeersPacket:
case PeersPacket:
break;
default:
return false;
}
return true;
}
void Session::ping() void Session::ping()
{ {
RLPStream s; RLPStream s;
@ -296,12 +247,9 @@ void Session::sealAndSend(RLPStream& _s)
bool Session::checkPacket(bytesConstRef _msg) bool Session::checkPacket(bytesConstRef _msg)
{ {
if (_msg.size() < 2) if (_msg[0] > 0x7f || _msg.size() < 2)
return false; return false;
if (_msg[0] > 0x7f) if (RLP(_msg.cropped(1)).actualSize() + 1 != _msg.size())
return false;
RLP r(_msg.cropped(1));
if (r.actualSize() + 1 != _msg.size())
return false; return false;
return true; return true;
} }
@ -418,82 +366,78 @@ void Session::doRead()
{ {
ThreadContext tc(info().id.abridged()); ThreadContext tc(info().id.abridged());
ThreadContext tc2(info().clientVersion); ThreadContext tc2(info().clientVersion);
if (ec && ec.category() != boost::asio::error::get_misc_category() && ec.value() != boost::asio::error::eof) if (!checkRead(h256::size, ec, length))
return;
else if (!m_io->authAndDecryptHeader(bytesRef(m_data.data(), length)))
{ {
clog(NetWarn) << "Error reading: " << ec.message(); clog(NetWarn) << "header decrypt failed";
drop(TCPError); drop(BadProtocol); // todo: better error
return;
}
RLPXFrameInfo header;
try
{
header = RLPXFrameInfo(bytesConstRef(m_data.data(), length));
} }
else if (ec && length == 0) catch (std::exception const& _e)
{
clog(NetWarn) << "Exception decoding frame header RLP:" << bytesConstRef(m_data.data(), h128::size).cropped(3);
drop(BadProtocol);
return; return;
else }
/// read padded frame and mac
auto tlen = header.length + header.padding + h128::size;
ba::async_read(m_socket->ref(), boost::asio::buffer(m_data, tlen), [this, self, header, tlen](boost::system::error_code ec, std::size_t length)
{ {
/// authenticate and decrypt header ThreadContext tc(info().id.abridged());
bytesRef header(m_data.data(), h256::size); ThreadContext tc2(info().clientVersion);
if (!m_io->authAndDecryptHeader(header)) if (!checkRead(tlen, ec, length))
return;
else if (!m_io->authAndDecryptFrame(bytesRef(m_data.data(), tlen)))
{ {
clog(NetWarn) << "header decrypt failed"; clog(NetWarn) << "frame decrypt failed";
drop(BadProtocol); // todo: better error drop(BadProtocol); // todo: better error
return; return;
} }
/// check frame size bytesConstRef frame(m_data.data(), header.length);
uint32_t frameSize = (m_data[0] * 256 + m_data[1]) * 256 + m_data[2]; if (!checkPacket(frame))
if (frameSize >= (uint32_t)1 << 24)
{ {
clog(NetWarn) << "frame size too large"; cerr << "Received " << frame.size() << ": " << toHex(frame) << endl;
drop(BadProtocol); clog(NetWarn) << "INVALID MESSAGE RECEIVED";
disconnect(BadProtocol);
return; return;
} }
else
/// rlp of header has protocol-type, sequence-id[, total-packet-size]
bytes headerRLP(13);
bytesConstRef(m_data.data(), h128::size).cropped(3).copyTo(&headerRLP);
/// read padded frame and mac
auto tlen = frameSize + ((16 - (frameSize % 16)) % 16) + h128::size;
ba::async_read(m_socket->ref(), boost::asio::buffer(m_data, tlen), [this, self, headerRLP, frameSize, tlen](boost::system::error_code ec, std::size_t length)
{ {
ThreadContext tc(info().id.abridged()); auto packetType = (PacketType)RLP(frame.cropped(0, 1)).toInt<unsigned>();
ThreadContext tc2(info().clientVersion); RLP r(frame.cropped(1));
if (ec && ec.category() != boost::asio::error::get_misc_category() && ec.value() != boost::asio::error::eof) if (!readPacket(header.protocolId, packetType, r))
{ clog(NetWarn) << "Couldn't interpret packet." << RLP(r);
clog(NetWarn) << "Error reading: " << ec.message(); }
drop(TCPError); doRead();
} });
else if (ec && length < tlen)
{
clog(NetWarn) << "Error reading - Abrupt peer disconnect: " << ec.message();
repMan().noteRude(*this);
drop(TCPError);
return;
}
else
{
if (!m_io->authAndDecryptFrame(bytesRef(m_data.data(), tlen)))
{
clog(NetWarn) << "frame decrypt failed";
drop(BadProtocol); // todo: better error
return;
}
bytesConstRef frame(m_data.data(), frameSize);
if (!checkPacket(frame))
{
cerr << "Received " << frame.size() << ": " << toHex(frame) << endl;
clog(NetWarn) << "INVALID MESSAGE RECEIVED";
disconnect(BadProtocol);
return;
}
else
{
auto packetType = (PacketType)RLP(frame.cropped(0, 1)).toInt<unsigned>();
RLP r(frame.cropped(1));
if (!interpret(packetType, r))
clog(NetWarn) << "Couldn't interpret packet." << RLP(r);
}
doRead();
}
});
}
}); });
} }
bool Session::checkRead(std::size_t _expected, boost::system::error_code _ec, std::size_t _length)
{
if (_ec && _ec.category() != boost::asio::error::get_misc_category() && _ec.value() != boost::asio::error::eof)
{
clog(NetConnect) << "Error reading: " << _ec.message();
drop(TCPError);
return false;
}
else if (_ec && _length < _expected)
{
clog(NetWarn) << "Error reading - Abrupt peer disconnect: " << _ec.message();
repMan().noteRude(*this);
drop(TCPError);
return false;
}
// If this fails then there's an unhandled asio error
assert(_expected == _length);
return true;
}

10
libp2p/Session.h

@ -96,13 +96,19 @@ private:
/// Perform a read on the socket. /// Perform a read on the socket.
void doRead(); void doRead();
/// Check error code after reading and drop peer if error code.
bool checkRead(std::size_t _expected, boost::system::error_code _ec, std::size_t _length);
/// Perform a single round of the write operation. This could end up calling itself asynchronously. /// Perform a single round of the write operation. This could end up calling itself asynchronously.
void write(); void write();
/// Interpret an incoming message. /// Deliver RLPX packet to Session or Capability for interpretation.
bool interpret(PacketType _t, RLP const& _r); bool readPacket(uint16_t _capId, PacketType _t, RLP const& _r);
/// Interpret an incoming Session packet.
bool interpret(PacketType _t, RLP const& _r);
/// @returns true iff the _msg forms a valid message for sending or receiving on the network. /// @returns true iff the _msg forms a valid message for sending or receiving on the network.
static bool checkPacket(bytesConstRef _msg); static bool checkPacket(bytesConstRef _msg);

36
libsolidity/AST.cpp

@ -175,24 +175,40 @@ void ContractDefinition::checkDuplicateFunctions() const
void ContractDefinition::checkAbstractFunctions() void ContractDefinition::checkAbstractFunctions()
{ {
map<string, bool> functions; // Mapping from name to function definition (exactly one per argument type equality class) and
// flag to indicate whether it is fully implemented.
using FunTypeAndFlag = std::pair<FunctionTypePointer, bool>;
map<string, vector<FunTypeAndFlag>> functions;
// Search from base to derived // Search from base to derived
for (ContractDefinition const* contract: boost::adaptors::reverse(getLinearizedBaseContracts())) for (ContractDefinition const* contract: boost::adaptors::reverse(getLinearizedBaseContracts()))
for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions()) for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions())
{ {
string const& name = function->getName(); auto& overloads = functions[function->getName()];
if (!function->isFullyImplemented() && functions.count(name) && functions[name]) FunctionTypePointer funType = make_shared<FunctionType>(*function);
BOOST_THROW_EXCEPTION(function->createTypeError("Redeclaring an already implemented function as abstract")); auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag)
functions[name] = function->isFullyImplemented(); {
return funType->hasEqualArgumentTypes(*_funAndFlag.first);
});
if (it == overloads.end())
overloads.push_back(make_pair(funType, function->isFullyImplemented()));
else if (it->second)
{
if (!function->isFullyImplemented())
BOOST_THROW_EXCEPTION(function->createTypeError("Redeclaring an already implemented function as abstract"));
}
else if (function->isFullyImplemented())
it->second = true;
} }
// Set to not fully implemented if at least one flag is false.
for (auto const& it: functions) for (auto const& it: functions)
if (!it.second) for (auto const& funAndFlag: it.second)
{ if (!funAndFlag.second)
setFullyImplemented(false); {
break; setFullyImplemented(false);
} return;
}
} }
void ContractDefinition::checkAbstractConstructors() void ContractDefinition::checkAbstractConstructors()

2
libwhisper/BloomFilter.h

@ -91,7 +91,7 @@ bool TopicBloomFilterBase<N>::isBitSet(FixedHash<N> const& _h, unsigned _index)
return (_h[iByte] & c_powerOfTwoBitMmask[iBit]) != 0; return (_h[iByte] & c_powerOfTwoBitMmask[iBit]) != 0;
} }
using TopicBloomFilter = TopicBloomFilterBase<TopicBloomFilterSize>; using TopicBloomFilter = TopicBloomFilterBase<c_topicBloomFilterSize>;
} }
} }

6
libwhisper/Common.cpp

@ -95,12 +95,12 @@ TopicFilter::TopicFilter(RLP const& _r)
} }
} }
FixedHash<TopicBloomFilterSize> TopicFilter::exportBloom() const TopicBloomFilterHash TopicFilter::exportBloom() const
{ {
FixedHash<TopicBloomFilterSize> ret; TopicBloomFilterHash ret;
for (TopicMask const& t: m_topicMasks) for (TopicMask const& t: m_topicMasks)
for (auto const& i: t) for (auto const& i: t)
ret |= i.first.template bloomPart<TopicBloomFilter::BitsPerBloom, TopicBloomFilterSize>(); ret |= i.first.template bloomPart<TopicBloomFilter::BitsPerBloom, c_topicBloomFilterSize>();
return ret; return ret;
} }

8
libwhisper/Common.h

@ -58,8 +58,8 @@ enum WhisperPacket
PacketCount PacketCount
}; };
enum { TopicBloomFilterSize = 64 }; static const int c_topicBloomFilterSize = 64;
enum { WhisperProtocolVersion = 3 }; static const int c_whisperProtocolVersion = 3;
using AbridgedTopic = FixedHash<4>; using AbridgedTopic = FixedHash<4>;
using Topic = h256; using Topic = h256;
@ -67,6 +67,8 @@ using Topic = h256;
using AbridgedTopics = std::vector<AbridgedTopic>; using AbridgedTopics = std::vector<AbridgedTopic>;
using Topics = h256s; using Topics = h256s;
using TopicBloomFilterHash = FixedHash<c_topicBloomFilterSize>;
AbridgedTopic abridge(Topic const& _topic); AbridgedTopic abridge(Topic const& _topic);
AbridgedTopics abridge(Topics const& _topics); AbridgedTopics abridge(Topics const& _topics);
@ -107,7 +109,7 @@ public:
void streamRLP(RLPStream& _s) const { _s << m_topicMasks; } void streamRLP(RLPStream& _s) const { _s << m_topicMasks; }
h256 sha3() const; h256 sha3() const;
bool matches(Envelope const& _m) const; bool matches(Envelope const& _m) const;
FixedHash<TopicBloomFilterSize> exportBloom() const; TopicBloomFilterHash exportBloom() const;
private: private:
TopicMasks m_topicMasks; TopicMasks m_topicMasks;

12
libwhisper/WhisperHost.cpp

@ -94,14 +94,16 @@ unsigned WhisperHost::installWatch(shh::Topics const& _t)
DEV_GUARDED(m_filterLock) DEV_GUARDED(m_filterLock)
{ {
if (!m_filters.count(h)) auto it = m_filters.find(h);
if (m_filters.end() == it)
m_filters.insert(make_pair(h, f)); m_filters.insert(make_pair(h, f));
else
it->second.refCount++;
m_bloom.addRaw(f.filter.exportBloom());
ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0; ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0;
m_watches[ret] = ClientWatch(h); m_watches[ret] = ClientWatch(h);
cwatshh << "+++" << ret << h; cwatshh << "+++" << ret << h;
m_bloom.addRaw(f.filter.exportBloom());
} }
noteAdvertiseTopicsOfInterest(); noteAdvertiseTopicsOfInterest();
@ -138,16 +140,16 @@ void WhisperHost::uninstallWatch(unsigned _i)
auto it = m_watches.find(_i); auto it = m_watches.find(_i);
if (it == m_watches.end()) if (it == m_watches.end())
return; return;
auto id = it->second.id; auto id = it->second.id;
m_watches.erase(it); m_watches.erase(it);
auto fit = m_filters.find(id); auto fit = m_filters.find(id);
if (fit != m_filters.end()) if (fit != m_filters.end())
{ {
m_bloom.removeRaw(fit->second.filter.exportBloom());
if (!--fit->second.refCount) if (!--fit->second.refCount)
m_filters.erase(fit); m_filters.erase(fit);
m_bloom.removeRaw(fit->second.filter.exportBloom());
} }
} }

4
libwhisper/WhisperHost.h

@ -50,11 +50,11 @@ class WhisperHost: public HostCapability<WhisperPeer>, public Interface, public
public: public:
WhisperHost(); WhisperHost();
virtual ~WhisperHost(); virtual ~WhisperHost();
unsigned protocolVersion() const { return WhisperProtocolVersion; } unsigned protocolVersion() const { return c_whisperProtocolVersion; }
/// remove old messages /// remove old messages
void cleanup(); void cleanup();
std::map<h256, Envelope> all() const { dev::ReadGuard l(x_messages); return m_messages; } std::map<h256, Envelope> all() const { dev::ReadGuard l(x_messages); return m_messages; }
FixedHash<TopicBloomFilterSize> bloom() const { dev::Guard l(m_filterLock); return m_bloom; } TopicBloomFilterHash bloom() const { dev::Guard l(m_filterLock); return m_bloom; }
virtual void inject(Envelope const& _e, WhisperPeer* _from = nullptr) override; virtual void inject(Envelope const& _e, WhisperPeer* _from = nullptr) override;
virtual Topics const& fullTopics(unsigned _id) const override { try { return m_filters.at(m_watches.at(_id).id).full; } catch (...) { return EmptyTopics; } } virtual Topics const& fullTopics(unsigned _id) const override { try { return m_filters.at(m_watches.at(_id).id).full; } catch (...) { return EmptyTopics; } }

7
libwhisper/WhisperPeer.cpp

@ -58,7 +58,10 @@ bool WhisperPeer::interpret(unsigned _id, RLP const& _r)
disable("Invalid protocol version."); disable("Invalid protocol version.");
for (auto const& m: host()->all()) for (auto const& m: host()->all())
{
Guard l(x_unseen);
m_unseen.insert(make_pair(0, m.first)); m_unseen.insert(make_pair(0, m.first));
}
if (session()->id() < host()->host()->id()) if (session()->id() < host()->host()->id())
sendMessages(); sendMessages();
@ -74,7 +77,7 @@ bool WhisperPeer::interpret(unsigned _id, RLP const& _r)
} }
case TopicFilterPacket: case TopicFilterPacket:
{ {
setBloom((FixedHash<TopicBloomFilterSize>)_r[0]); setBloom((TopicBloomFilterHash)_r[0]);
break; break;
} }
default: default:
@ -115,7 +118,7 @@ void WhisperPeer::noteNewMessage(h256 _h, Envelope const& _m)
m_unseen.insert(make_pair(rating(_m), _h)); m_unseen.insert(make_pair(rating(_m), _h));
} }
void WhisperPeer::sendTopicsOfInterest(FixedHash<TopicBloomFilterSize> const& _bloom) void WhisperPeer::sendTopicsOfInterest(TopicBloomFilterHash const& _bloom)
{ {
DEV_GUARDED(x_advertiseTopicsOfInterest) DEV_GUARDED(x_advertiseTopicsOfInterest)
m_advertiseTopicsOfInterest = false; m_advertiseTopicsOfInterest = false;

10
libwhisper/WhisperPeer.h

@ -53,10 +53,10 @@ public:
virtual ~WhisperPeer(); virtual ~WhisperPeer();
WhisperHost* host() const; WhisperHost* host() const;
static std::string name() { return "shh"; } static std::string name() { return "shh"; }
static u256 version() { return WhisperProtocolVersion; } static u256 version() { return c_whisperProtocolVersion; }
static unsigned messageCount() { return PacketCount; } static unsigned messageCount() { return PacketCount; }
FixedHash<TopicBloomFilterSize> bloom() const { dev::Guard g(x_bloom); return m_bloom; } TopicBloomFilterHash bloom() const { dev::Guard g(x_bloom); return m_bloom; }
void sendTopicsOfInterest(FixedHash<TopicBloomFilterSize> const& _bloom); ///< sends our bloom filter to remote peer void sendTopicsOfInterest(TopicBloomFilterHash const& _bloom); ///< sends our bloom filter to remote peer
void noteAdvertiseTopicsOfInterest() { dev::Guard g(x_advertiseTopicsOfInterest); m_advertiseTopicsOfInterest = true; } void noteAdvertiseTopicsOfInterest() { dev::Guard g(x_advertiseTopicsOfInterest); m_advertiseTopicsOfInterest = true; }
private: private:
@ -64,14 +64,14 @@ private:
void sendMessages(); void sendMessages();
unsigned rating(Envelope const&) const { return 0; } // TODO unsigned rating(Envelope const&) const { return 0; } // TODO
void noteNewMessage(h256 _h, Envelope const& _m); void noteNewMessage(h256 _h, Envelope const& _m);
void setBloom(FixedHash<TopicBloomFilterSize> const& _b) { dev::Guard g(x_bloom); m_bloom = _b; } void setBloom(TopicBloomFilterHash const& _b) { dev::Guard g(x_bloom); m_bloom = _b; }
mutable dev::Mutex x_unseen; mutable dev::Mutex x_unseen;
std::multimap<unsigned, h256> m_unseen; ///< Rated according to what they want. std::multimap<unsigned, h256> m_unseen; ///< Rated according to what they want.
std::chrono::system_clock::time_point m_timer = std::chrono::system_clock::now(); std::chrono::system_clock::time_point m_timer = std::chrono::system_clock::now();
mutable dev::Mutex x_bloom; mutable dev::Mutex x_bloom;
FixedHash<TopicBloomFilterSize> m_bloom; ///< Peer's topics of interest TopicBloomFilterHash m_bloom; ///< Peer's topics of interest
mutable dev::Mutex x_advertiseTopicsOfInterest; mutable dev::Mutex x_advertiseTopicsOfInterest;
bool m_advertiseTopicsOfInterest; bool m_advertiseTopicsOfInterest;

10
test/libp2p/net.cpp

@ -314,23 +314,23 @@ BOOST_AUTO_TEST_CASE(kademlia)
node.nodeTable->discover(); // ideally, joining with empty node table logs warning we can check for node.nodeTable->discover(); // ideally, joining with empty node table logs warning we can check for
node.setup(); node.setup();
node.populate(); node.populate();
clog << "NodeTable:\n" << *node.nodeTable.get() << endl; // clog << "NodeTable:\n" << *node.nodeTable.get() << endl;
node.populateAll(); node.populateAll();
clog << "NodeTable:\n" << *node.nodeTable.get() << endl; // clog << "NodeTable:\n" << *node.nodeTable.get() << endl;
auto nodes = node.nodeTable->nodes(); auto nodes = node.nodeTable->nodes();
nodes.sort(); nodes.sort();
node.nodeTable->reset(); node.nodeTable->reset();
clog << "NodeTable:\n" << *node.nodeTable.get() << endl; // clog << "NodeTable:\n" << *node.nodeTable.get() << endl;
node.populate(1); node.populate(1);
clog << "NodeTable:\n" << *node.nodeTable.get() << endl; // clog << "NodeTable:\n" << *node.nodeTable.get() << endl;
node.nodeTable->discover(); node.nodeTable->discover();
this_thread::sleep_for(chrono::milliseconds(2000)); this_thread::sleep_for(chrono::milliseconds(2000));
clog << "NodeTable:\n" << *node.nodeTable.get() << endl; // clog << "NodeTable:\n" << *node.nodeTable.get() << endl;
BOOST_REQUIRE_EQUAL(node.nodeTable->count(), 8); BOOST_REQUIRE_EQUAL(node.nodeTable->count(), 8);

17
test/libsolidity/SolidityNameAndTypeResolution.cpp

@ -403,6 +403,23 @@ BOOST_AUTO_TEST_CASE(abstract_contract)
BOOST_CHECK(derived->getDefinedFunctions()[0]->isFullyImplemented()); BOOST_CHECK(derived->getDefinedFunctions()[0]->isFullyImplemented());
} }
BOOST_AUTO_TEST_CASE(abstract_contract_with_overload)
{
ASTPointer<SourceUnit> sourceUnit;
char const* text = R"(
contract base { function foo(bool); }
contract derived is base { function foo(uint) {} }
)";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->getNodes();
ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[0].get());
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[1].get());
BOOST_REQUIRE(base);
BOOST_CHECK(!base->isFullyImplemented());
BOOST_REQUIRE(derived);
BOOST_CHECK(!derived->isFullyImplemented());
}
BOOST_AUTO_TEST_CASE(create_abstract_contract) BOOST_AUTO_TEST_CASE(create_abstract_contract)
{ {
ASTPointer<SourceUnit> sourceUnit; ASTPointer<SourceUnit> sourceUnit;

4
test/libwhisper/bloomFilter.cpp

@ -28,7 +28,7 @@ using namespace dev;
using namespace dev::shh; using namespace dev::shh;
using TopicBloomFilterShort = TopicBloomFilterBase<4>; using TopicBloomFilterShort = TopicBloomFilterBase<4>;
using TopicBloomFilterTest = TopicBloomFilterBase<TopicBloomFilterSize>; using TopicBloomFilterTest = TopicBloomFilterBase<c_topicBloomFilterSize>;
void testAddNonExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h) void testAddNonExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{ {
@ -244,4 +244,4 @@ BOOST_AUTO_TEST_CASE(bloomFilterRaw)
BOOST_REQUIRE(!f.contains(b00110111)); BOOST_REQUIRE(!f.contains(b00110111));
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

18
test/libwhisper/whisperTopic.cpp

@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(topicAdvertising)
Host host2("second", NetworkPreferences("127.0.0.1", 30305, false)); Host host2("second", NetworkPreferences("127.0.0.1", 30305, false));
host2.setIdealPeerCount(1); host2.setIdealPeerCount(1);
auto whost2 = host2.registerCapability(new WhisperHost()); auto whost2 = host2.registerCapability(new WhisperHost());
whost2->installWatch(BuildTopicMask("test2")); unsigned w2 = whost2->installWatch(BuildTopicMask("test2"));
host2.start(); host2.start();
while (!host2.haveNetwork()) while (!host2.haveNetwork())
@ -348,13 +348,13 @@ BOOST_AUTO_TEST_CASE(topicAdvertising)
} }
BOOST_REQUIRE(sessions.size()); BOOST_REQUIRE(sessions.size());
FixedHash<TopicBloomFilterSize> bf1 = sessions.back().first->cap<WhisperPeer>()->bloom(); TopicBloomFilterHash bf1 = sessions.back().first->cap<WhisperPeer>()->bloom();
FixedHash<TopicBloomFilterSize> bf2 = whost2->bloom(); TopicBloomFilterHash bf2 = whost2->bloom();
BOOST_REQUIRE_EQUAL(bf1, bf2); BOOST_REQUIRE_EQUAL(bf1, bf2);
BOOST_REQUIRE(bf1); BOOST_REQUIRE(bf1);
BOOST_REQUIRE(!whost1->bloom()); BOOST_REQUIRE(!whost1->bloom());
whost1->installWatch(BuildTopicMask("test1")); unsigned w1 = whost1->installWatch(BuildTopicMask("test1"));
for (int i = 0; i < 600; ++i) for (int i = 0; i < 600; ++i)
{ {
@ -372,6 +372,16 @@ BOOST_AUTO_TEST_CASE(topicAdvertising)
bf1 = whost1->bloom(); bf1 = whost1->bloom();
BOOST_REQUIRE_EQUAL(bf1, bf2); BOOST_REQUIRE_EQUAL(bf1, bf2);
BOOST_REQUIRE(bf1); BOOST_REQUIRE(bf1);
unsigned random = 0xC0FFEE;
whost1->uninstallWatch(w1);
whost1->uninstallWatch(random);
whost1->uninstallWatch(w1);
whost1->uninstallWatch(random);
whost2->uninstallWatch(random);
whost2->uninstallWatch(w2);
whost2->uninstallWatch(random);
whost2->uninstallWatch(w2);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

Loading…
Cancel
Save