diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 4126fbf08..04fc7757c 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -1285,6 +1285,7 @@ void Main::on_blocks_currentItemChanged()
s << "
" << sha3(i.data()).abridged();// << ": " << i[1].toHash() << " [" << i[2].toInt() << " used]";
s << "
Post: " << info.stateRoot << "";
s << "
Dump: " << toHex(block[0].data()) << "";
+ s << "
Receipts-Hex: " << toHex(ethereum()->blockChain().receipts(h).rlp()) << "
";
}
else
{
diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp
index 744e85a27..5f9332ad8 100644
--- a/libethcore/CommonEth.cpp
+++ b/libethcore/CommonEth.cpp
@@ -33,7 +33,7 @@ namespace dev
namespace eth
{
-const unsigned c_protocolVersion = 46;
+const unsigned c_protocolVersion = 48;
const unsigned c_databaseVersion = 5;
static const vector> g_units =
diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h
index 9e6601d0a..4a175ff4e 100644
--- a/libevm/ExtVMFace.h
+++ b/libevm/ExtVMFace.h
@@ -36,20 +36,12 @@ namespace dev
namespace eth
{
-template inline std::set toSet(std::vector const& _ts)
-{
- std::set ret;
- for (auto const& t: _ts)
- ret.insert(t);
- return ret;
-}
-
using LogBloom = h512;
struct LogEntry
{
LogEntry() {}
- LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = (h256s)_r[1]; data = _r[2].toBytes(); }
+ LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = _r[1].toVector(); data = _r[2].toBytes(); }
LogEntry(Address const& _address, h256s const& _ts, bytes&& _d): address(_address), topics(_ts), data(std::move(_d)) {}
void streamRLP(RLPStream& _s) const { _s.appendList(3) << address << topics << data; }
@@ -88,6 +80,7 @@ struct SubState
{
suicides += _s.suicides;
refunds += _s.refunds;
+ logs += _s.logs;
return *this;
}
};
diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp
index cad1b179c..7d08910aa 100644
--- a/libp2p/Host.cpp
+++ b/libp2p/Host.cpp
@@ -34,6 +34,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -199,7 +200,7 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool
m_clientVersion(_clientVersion),
m_netPrefs(_n),
m_ifAddresses(getInterfaceAddresses()),
- m_ioService(new ba::io_service),
+ m_ioService(new ba::io_service(2)),
m_acceptor(new bi::tcp::acceptor(*m_ioService)),
m_socket(new bi::tcp::socket(*m_ioService)),
m_key(KeyPair::create())
@@ -227,7 +228,7 @@ void Host::stop()
{
{
// prevent m_run from being set to false at same time as set to true by start()
- lock_guard l(x_runtimer);
+ Guard l(x_runTimer);
// once m_run is false the scheduler will shutdown network and stopWorking()
m_run = false;
}
@@ -536,7 +537,16 @@ void Host::connect(std::shared_ptr const& _n)
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
-
+
+ // prevent concurrently connecting to a node; todo: better abstraction
+ Node *nptr = _n.get();
+ {
+ Guard l(x_pendingNodeConns);
+ if (m_pendingNodeConns.count(nptr))
+ return;
+ m_pendingNodeConns.insert(nptr);
+ }
+
clog(NetConnect) << "Attempting connection to node" << _n->id.abridged() << "@" << _n->address << "from" << id().abridged();
_n->lastAttempted = std::chrono::system_clock::now();
_n->failedAttempts++;
@@ -559,6 +569,8 @@ void Host::connect(std::shared_ptr const& _n)
p->start();
}
delete s;
+ Guard l(x_pendingNodeConns);
+ m_pendingNodeConns.erase(nptr);
});
}
@@ -685,11 +697,10 @@ PeerInfos Host::peers(bool _updatePing) const
ret.push_back(j->m_info);
return ret;
}
-
+
void Host::run(boost::system::error_code const& error)
{
- static unsigned s_lasttick = 0;
- s_lasttick += c_timerInterval;
+ m_lastTick += c_timerInterval;
if (error || !m_ioService)
{
@@ -701,11 +712,11 @@ void Host::run(boost::system::error_code const& error)
// network running
if (m_run)
{
- if (s_lasttick >= c_timerInterval * 50)
+ if (m_lastTick >= c_timerInterval * 10)
{
growPeers();
prunePeers();
- s_lasttick = 0;
+ m_lastTick = 0;
}
if (m_hadNewNodes)
@@ -771,7 +782,7 @@ void Host::run(boost::system::error_code const& error)
m_socket->close();
// m_run is false, so we're stopping; kill timer
- s_lasttick = 0;
+ m_lastTick = 0;
// causes parent thread's stop() to continue which calls stopWorking()
m_timer.reset();
@@ -794,7 +805,7 @@ void Host::startedWorking()
// prevent m_run from being set to true at same time as set to false by stop()
// don't release mutex until m_timer is set so in case stop() is called at same
// time, stop will wait on m_timer and graceful network shutdown.
- lock_guard l(x_runtimer);
+ Guard l(x_runTimer);
// reset io service and create deadline timer
m_timer.reset(new boost::asio::deadline_timer(*m_ioService));
m_run = true;
diff --git a/libp2p/Host.h b/libp2p/Host.h
index c82ecf84c..644afeb69 100644
--- a/libp2p/Host.h
+++ b/libp2p/Host.h
@@ -224,7 +224,7 @@ private:
Nodes potentialPeers(RangeMask const& _known);
bool m_run = false; ///< Whether network is running.
- std::mutex x_runtimer; ///< Start/stop mutex.
+ std::mutex x_runTimer; ///< Start/stop mutex.
std::string m_clientVersion; ///< Our version string.
@@ -241,6 +241,10 @@ private:
std::unique_ptr m_timer; ///< Timer which, when network is running, calls scheduler() every c_timerInterval ms.
static const unsigned c_timerInterval = 100; ///< Interval which m_timer is run when network is connected.
+ unsigned m_lastTick = 0; ///< Used by run() for scheduling; must not be mutated outside of run().
+
+ std::set m_pendingNodeConns; /// Used only by connect(Node&) to limit concurrently connecting to same node. See connect(shared_ptrconst&).
+ Mutex x_pendingNodeConns;
bi::tcp::endpoint m_public; ///< Our public listening endpoint.
KeyPair m_key; ///< Our unique ID.
diff --git a/libsolidity/AST.h b/libsolidity/AST.h
index 2b532d763..d2fb15a45 100644
--- a/libsolidity/AST.h
+++ b/libsolidity/AST.h
@@ -238,7 +238,7 @@ public:
Block& getBody() { return *m_body; }
/// @return A shared pointer of an ASTString.
/// Can contain a nullptr in which case indicates absence of documentation
- ASTPointer const& getDocumentation() { return m_documentation; }
+ ASTPointer const& getDocumentation() const { return m_documentation; }
void addLocalVariable(VariableDeclaration const& _localVariable) { m_localVariables.push_back(&_localVariable); }
std::vector const& getLocalVariables() const { return m_localVariables; }
diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt
index ea2ef4b74..b5147ced3 100644
--- a/libsolidity/CMakeLists.txt
+++ b/libsolidity/CMakeLists.txt
@@ -16,6 +16,10 @@ endif()
include_directories(..)
target_link_libraries(${EXECUTABLE} evmcore devcore)
+# TODO: Temporary until PR 532 https://github.com/ethereum/cpp-ethereum/pull/532
+# gets accepted. Then we can simply add jsoncpp as a dependency and not the
+# whole of JSONRPC as we are doing right here
+target_link_libraries(${EXECUTABLE} ${JSONRPC_LS})
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )
diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp
index 198ded090..621723848 100644
--- a/libsolidity/CompilerStack.cpp
+++ b/libsolidity/CompilerStack.cpp
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
using namespace std;
@@ -127,45 +128,34 @@ void CompilerStack::streamAssembly(ostream& _outStream, string const& _contractN
string const& CompilerStack::getInterface(std::string const& _contractName)
{
+ return getJsonDocumentation(_contractName, ABI_INTERFACE);
+}
+
+std::string const& CompilerStack::getJsonDocumentation(std::string const& _contractName, enum DocumentationType _type)
+{
+ if (!m_parseSuccessful)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+
Contract& contract = getContract(_contractName);
- if (contract.interface.empty())
+
+ std::unique_ptr* doc;
+ switch (_type)
{
- stringstream interface;
- interface << '[';
- vector exportedFunctions = contract.contract->getInterfaceFunctions();
- unsigned functionsCount = exportedFunctions.size();
- for (FunctionDefinition const* f: exportedFunctions)
- {
- auto streamVariables = [&](vector> const& _vars)
- {
- unsigned varCount = _vars.size();
- for (ASTPointer const& var: _vars)
- {
- interface << "{"
- << "\"name\":" << escaped(var->getName(), false) << ","
- << "\"type\":" << escaped(var->getType()->toString(), false)
- << "}";
- if (--varCount > 0)
- interface << ",";
- }
- };
-
- interface << '{'
- << "\"name\":" << escaped(f->getName(), false) << ","
- << "\"inputs\":[";
- streamVariables(f->getParameters());
- interface << "],"
- << "\"outputs\":[";
- streamVariables(f->getReturnParameters());
- interface << "]"
- << "}";
- if (--functionsCount > 0)
- interface << ",";
- }
- interface << ']';
- contract.interface = interface.str();
+ case NATSPEC_USER:
+ doc = &contract.userDocumentation;
+ break;
+ case NATSPEC_DEV:
+ doc = &contract.devDocumentation;
+ break;
+ case ABI_INTERFACE:
+ doc = &contract.interface;
+ break;
+ default:
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal documentation type."));
}
- return contract.interface;
+ if (!*doc)
+ *doc = contract.interfaceHandler->getDocumentation(*contract.contract, _type);
+ return *(*doc);
}
Scanner const& CompilerStack::getScanner(string const& _sourceName)
@@ -193,7 +183,6 @@ void CompilerStack::reset(bool _keepSources)
else
m_sources.clear();
m_globalContext.reset();
- m_compiler.reset();
m_sourceOrder.clear();
m_contracts.clear();
}
@@ -247,5 +236,8 @@ CompilerStack::Source& CompilerStack::getSource(string const& _sourceName)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Given source file not found."));
return it->second;
}
+
+CompilerStack::Contract::Contract(): interfaceHandler(make_shared()) {}
+
}
}
diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h
index a5b8ec41e..34178841a 100644
--- a/libsolidity/CompilerStack.h
+++ b/libsolidity/CompilerStack.h
@@ -33,10 +33,18 @@ namespace solidity {
// forward declarations
class Scanner;
+class ContractDefinition;
class SourceUnit;
class Compiler;
class GlobalContext;
-class ContractDefinition;
+class InterfaceHandler;
+
+enum DocumentationType: unsigned short
+{
+ NATSPEC_USER = 1,
+ NATSPEC_DEV,
+ ABI_INTERFACE
+};
/**
* Easy to use and self-contained Solidity compiler with as few header dependencies as possible.
@@ -47,6 +55,7 @@ class CompilerStack: boost::noncopyable
{
public:
CompilerStack(): m_parseSuccessful(false) {}
+
/// Adds a source object (e.g. file) to the parser. After this, parse has to be called again.
void addSource(std::string const& _name, std::string const& _content);
void setSource(std::string const& _sourceCode);
@@ -71,6 +80,11 @@ public:
/// Returns a string representing the contract interface in JSON.
/// Prerequisite: Successful call to parse or compile.
std::string const& getInterface(std::string const& _contractName = "");
+ /// Returns a string representing the contract's documentation in JSON.
+ /// Prerequisite: Successful call to parse or compile.
+ /// @param type The type of the documentation to get.
+ /// Can be one of 3 types defined at @c DocumentationType
+ std::string const& getJsonDocumentation(std::string const& _contractName, enum DocumentationType _type);
/// Returns the previously used scanner, useful for counting lines during error reporting.
Scanner const& getScanner(std::string const& _sourceName = "");
@@ -94,10 +108,15 @@ private:
struct Contract
{
- ContractDefinition const* contract;
- std::string interface;
+ ContractDefinition* contract;
std::shared_ptr compiler;
bytes bytecode;
+ std::shared_ptr interfaceHandler;
+ std::unique_ptr interface;
+ std::unique_ptr userDocumentation;
+ std::unique_ptr devDocumentation;
+
+ Contract();
};
void reset(bool _keepSources = false);
@@ -109,7 +128,6 @@ private:
bool m_parseSuccessful;
std::map m_sources;
std::shared_ptr m_globalContext;
- std::shared_ptr m_compiler;
std::vector