Browse Source

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

cl-refactor
Paweł Bylica 10 years ago
parent
commit
11e9448a58
  1. 1
      eth/main.cpp
  2. 1
      ethminer/MinerAux.h
  3. 7
      evmjit/CMakeLists.txt
  4. 60
      libdevcore/concurrent_queue.h
  5. 4
      libethcore/EthashSealEngine.cpp
  6. 1
      libethcore/Miner.h
  7. 47
      libethereum/BlockChainSync.cpp
  8. 1
      libethereum/BlockChainSync.h
  9. 7
      libethereum/Client.cpp
  10. 2
      libethereum/Client.h
  11. 25
      libethereum/EthereumHost.cpp
  12. 2
      libethereum/EthereumHost.h
  13. 4
      libethereum/EthereumPeer.cpp
  14. 11
      libethereum/Executive.cpp
  15. 43
      libevm/SmartVM.cpp
  16. 23
      libp2p/Common.cpp
  17. 5
      libp2p/Common.h
  18. 3
      solc/docker_emscripten/Dockerfile
  19. 2
      test/fuzzTesting/CMakeLists.txt
  20. 37
      test/fuzzTesting/createRandomTest.cpp
  21. 150
      test/fuzzTesting/fuzzHelper.cpp
  22. 17
      test/fuzzTesting/fuzzHelper.h
  23. 34
      test/libdevcore/rlp.cpp

1
eth/main.cpp

@ -1700,6 +1700,7 @@ int main(int argc, char** argv)
c->setGasPricer(gasPricer); c->setGasPricer(gasPricer);
c->setForceMining(forceMining); c->setForceMining(forceMining);
// TODO: expose sealant interface. // TODO: expose sealant interface.
c->setShouldPrecomputeDAG(m.shouldPrecompute());
c->setTurboMining(m.minerType() == MinerCLI::MinerType::GPU); c->setTurboMining(m.minerType() == MinerCLI::MinerType::GPU);
c->setAddress(beneficiary); c->setAddress(beneficiary);
c->setNetworkId(networkId); c->setNetworkId(networkId);

1
ethminer/MinerAux.h

@ -380,6 +380,7 @@ public:
}; };
MinerType minerType() const { return m_minerType; } MinerType minerType() const { return m_minerType; }
bool shouldPrecompute() const { return m_precompute; }
private: private:
void doInitDAG(unsigned _n) void doInitDAG(unsigned _n)

7
evmjit/CMakeLists.txt

@ -34,8 +34,11 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT LLVM_DIR)
set(LLVM_DEFINITIONS "-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS") set(LLVM_DEFINITIONS "-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
link_directories(/usr/lib/llvm-3.7/lib) link_directories(/usr/lib/llvm-3.7/lib)
else() else()
find_package(LLVM 3.7 REQUIRED CONFIG) find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") if (${LLVM_VERSION} VERSION_LESS 3.7)
message(FATAL_ERROR "Incompatible LLVM version ${LLVM_VERSION}")
endif()
message(STATUS "Found LLVM ${LLVM_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
llvm_map_components_to_libnames(LLVM_LIBS core support mcjit x86asmparser x86codegen ipo) llvm_map_components_to_libnames(LLVM_LIBS core support mcjit x86asmparser x86codegen ipo)
endif() endif()

60
libdevcore/concurrent_queue.h

@ -0,0 +1,60 @@
/*
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/>.
*/
#pragma once
#include <utility>
#include <queue>
#include <condition_variable>
#include <mutex>
namespace dev
{
/// Concurrent queue.
/// You can push and pop elements to/from the queue. Pop will block until the queue is not empty.
/// The default backend (_QueueT) is std::queue. It can be changed to any type that has
/// proper push(), pop(), empty() and front() methods.
template<typename _T, typename _QueueT = std::queue<_T>>
class concurrent_queue
{
public:
template<typename _U>
void push(_U&& _elem)
{
{
std::lock_guard<decltype(x_mutex)> guard{x_mutex};
m_queue.push(std::forward<_U>(_elem));
}
m_cv.notify_one();
}
_T pop()
{
std::unique_lock<std::mutex> lock{x_mutex};
m_cv.wait(lock, [this]{ return !m_queue.empty(); });
auto item = std::move(m_queue.front());
m_queue.pop();
return item;
}
private:
_QueueT m_queue;
std::mutex x_mutex;
std::condition_variable m_cv;
};
}

4
libethcore/EthashSealEngine.cpp

@ -54,7 +54,9 @@ void EthashSealEngine::generateSeal(BlockInfo const& _bi)
m_farm.setWork(m_sealing); m_farm.setWork(m_sealing);
m_farm.start(m_sealer); m_farm.start(m_sealer);
m_farm.setWork(m_sealing); // TODO: take out one before or one after... m_farm.setWork(m_sealing); // TODO: take out one before or one after...
Ethash::ensurePrecomputed((unsigned)_bi.number()); bytes shouldPrecompute = option("precomputeDAG");
if (!shouldPrecompute.empty() && shouldPrecompute[0] == 1)
Ethash::ensurePrecomputed((unsigned)_bi.number());
} }
void EthashSealEngine::onSealGenerated(std::function<void(bytes const&)> const& _f) void EthashSealEngine::onSealGenerated(std::function<void(bytes const&)> const& _f)

1
libethcore/Miner.h

@ -84,6 +84,7 @@ public:
m_farm(_ci.first), m_farm(_ci.first),
m_index(_ci.second) m_index(_ci.second)
{} {}
virtual ~GenericMiner() {}
// API FOR THE FARM TO CALL IN WITH // API FOR THE FARM TO CALL IN WITH

47
libethereum/BlockChainSync.cpp

@ -300,7 +300,7 @@ void BlockChainSync::onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP con
u256 totalDifficulty = _r[1].toInt<u256>(); u256 totalDifficulty = _r[1].toInt<u256>();
if (totalDifficulty > _peer->m_totalDifficulty) if (totalDifficulty > _peer->m_totalDifficulty)
{ {
clog(NetMessageDetail) << "Received block with no known parent. Resyncing..."; clog(NetMessageDetail) << "Received block with no known parent. Peer needs syncing...";
resetSyncFor(_peer, h, totalDifficulty); resetSyncFor(_peer, h, totalDifficulty);
} }
break; break;
@ -648,12 +648,10 @@ void PV60Sync::noteDoneBlocks(std::shared_ptr<EthereumPeer> _peer, bool _clemenc
clog(NetNote) << "Chain download failed. Aborted while incomplete."; clog(NetNote) << "Chain download failed. Aborted while incomplete.";
else else
{ {
// Done our chain-get. // This can happen when the leading peer aborts and the one that is selected instead does not have all the blocks.
clog(NetWarn) << "Chain download failed. Peer with blocks didn't have them all. This peer is bad and should be punished."; // Just stop syncing to this peer. Sync will restart if there are no more peers to sync with.
clog(NetWarn) << downloadMan().remaining(); clog(NetNote) << "Peer does not have required blocks";
clog(NetWarn) << "WOULD BAN."; resetNeedsSyncing(_peer);
// m_banned.insert(_peer->session()->id()); // We know who you are!
// _peer->disable("Peer sent hashes but was unable to provide the blocks.");
} }
resetSync(); resetSync();
downloadMan().reset(); downloadMan().reset();
@ -747,7 +745,7 @@ void PV60Sync::onPeerNewHashes(std::shared_ptr<EthereumPeer> _peer, h256s const&
RecursiveGuard l(x_sync); RecursiveGuard l(x_sync);
if (isSyncing() && (m_state != SyncState::NewBlocks || isSyncing(_peer))) if (isSyncing() && (m_state != SyncState::NewBlocks || isSyncing(_peer)))
{ {
clog(NetMessageSummary) << "Ignoring since we're already downloading."; clog(NetMessageDetail) << "Ignoring new hashes since we're already downloading.";
return; return;
} }
clog(NetMessageDetail) << "Not syncing and new block hash discovered: syncing without help."; clog(NetMessageDetail) << "Not syncing and new block hash discovered: syncing without help.";
@ -838,7 +836,7 @@ void PV60Sync::onPeerAborting()
// Can't check invariants here since the peers is already removed from the list and the state is not updated yet. // Can't check invariants here since the peers is already removed from the list and the state is not updated yet.
if (m_syncer.expired() && m_state != SyncState::Idle) if (m_syncer.expired() && m_state != SyncState::Idle)
{ {
clog(NetWarn) << "Syncing peer disconnected, restarting sync"; clog(NetNote) << "Syncing peer disconnected";
m_syncer.reset(); m_syncer.reset();
abortSync(); abortSync();
} }
@ -969,11 +967,17 @@ void PV61Sync::completeSubchain(std::shared_ptr<EthereumPeer> _peer, unsigned _n
{ {
//Done chain-get //Done chain-get
m_syncingNeededBlocks.clear(); m_syncingNeededBlocks.clear();
// Add hashes to download skipping onces that are already downloaded
for (auto h = m_completeChainMap.rbegin(); h != m_completeChainMap.rend(); ++h) for (auto h = m_completeChainMap.rbegin(); h != m_completeChainMap.rend(); ++h)
m_syncingNeededBlocks.insert(m_syncingNeededBlocks.end(), h->second.hashes.begin(), h->second.hashes.end()); if (!host().chain().isKnown(h->second.hashes.front()) && !host().chain().isKnown(h->second.hashes.back()))
m_completeChainMap.clear(); {
m_knownHashes.clear(); if (host().bq().blockStatus(h->second.hashes.front()) == QueueStatus::Unknown || host().bq().blockStatus(h->second.hashes.back()) == QueueStatus::Unknown)
m_syncingBlockNumber = 0; m_syncingNeededBlocks.insert(m_syncingNeededBlocks.end(), h->second.hashes.begin(), h->second.hashes.end());
else
for (h256 const& hash: h->second.hashes)
if (!host().chain().isKnown(hash) && host().bq().blockStatus(hash) == QueueStatus::Unknown)
m_syncingNeededBlocks.insert(m_syncingNeededBlocks.end(), hash);
}
transition(syncer, SyncState::Blocks); transition(syncer, SyncState::Blocks);
} }
else else
@ -1007,6 +1011,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _h
{ {
// End of hash chain, add last chunk to download // End of hash chain, add last chunk to download
m_readyChainMap.insert(make_pair(m_syncingBlockNumber, SubChain{ h256s{ _peer->m_latestHash }, _peer->m_latestHash })); m_readyChainMap.insert(make_pair(m_syncingBlockNumber, SubChain{ h256s{ _peer->m_latestHash }, _peer->m_latestHash }));
m_knownHashes.insert(_peer->m_latestHash);
m_hashScanComplete = true; m_hashScanComplete = true;
_peer->m_syncHashNumber = 0; _peer->m_syncHashNumber = 0;
requestSubchain(_peer); requestSubchain(_peer);
@ -1032,7 +1037,13 @@ void PV61Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _h
if (isSyncing(_peer) && _peer->m_syncHashNumber == m_syncingBlockNumber) if (isSyncing(_peer) && _peer->m_syncHashNumber == m_syncingBlockNumber)
{ {
// Got new subchain marker // Got new subchain marker
assert(_hashes.size() == 1); if (_hashes.size() != 1)
{
clog(NetWarn) << "Peer sent too many hashes";
_peer->disable("Too many hashes");
restartSync();
return;
}
m_knownHashes.insert(_hashes[0]); m_knownHashes.insert(_hashes[0]);
m_readyChainMap.insert(make_pair(m_syncingBlockNumber, SubChain{ h256s{ _hashes[0] }, _hashes[0] })); m_readyChainMap.insert(make_pair(m_syncingBlockNumber, SubChain{ h256s{ _hashes[0] }, _hashes[0] }));
if ((m_readyChainMap.size() + m_downloadingChainMap.size() + m_completeChainMap.size()) * c_hashSubchainSize > _peer->m_expectedHashes) if ((m_readyChainMap.size() + m_downloadingChainMap.size() + m_completeChainMap.size()) * c_hashSubchainSize > _peer->m_expectedHashes)
@ -1186,6 +1197,14 @@ bool PV61Sync::isPV61Syncing() const
return m_syncingBlockNumber != 0; return m_syncingBlockNumber != 0;
} }
void PV61Sync::completeSync()
{
m_completeChainMap.clear();
m_knownHashes.clear();
m_syncingBlockNumber = 0;
PV60Sync::completeSync();
}
bool PV61Sync::invariants() const bool PV61Sync::invariants() const
{ {
if (m_state == SyncState::Hashes) if (m_state == SyncState::Hashes)

1
libethereum/BlockChainSync.h

@ -292,6 +292,7 @@ public:
protected: protected:
void restartSync() override; void restartSync() override;
void completeSync() override;
void requestSubchain(std::shared_ptr<EthereumPeer> _peer) override; void requestSubchain(std::shared_ptr<EthereumPeer> _peer) override;
void syncHashes(std::shared_ptr<EthereumPeer> _peer) override; void syncHashes(std::shared_ptr<EthereumPeer> _peer) override;
void onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes) override; void onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes) override;

7
libethereum/Client.cpp

@ -443,6 +443,13 @@ void Client::setForceMining(bool _enable)
startMining(); startMining();
} }
void Client::setShouldPrecomputeDAG(bool _precompute)
{
bytes trueBytes {1};
bytes falseBytes {0};
sealEngine()->setOption("precomputeDAG", _precompute ? trueBytes: falseBytes);
}
bool Client::isMining() const bool Client::isMining() const
{ {
return Ethash::isWorking(m_sealEngine.get()); return Ethash::isWorking(m_sealEngine.get());

2
libethereum/Client.h

@ -140,6 +140,8 @@ public:
bool turboMining() const { return m_turboMining; } bool turboMining() const { return m_turboMining; }
/// Enable/disable GPU mining. /// Enable/disable GPU mining.
void setTurboMining(bool _enable = true) { m_turboMining = _enable; if (isMining()) startMining(); } void setTurboMining(bool _enable = true) { m_turboMining = _enable; if (isMining()) startMining(); }
/// Enable/disable precomputing of the DAG for next epoch
void setShouldPrecomputeDAG(bool _precompute);
/// Check to see if we'd mine on an apparently bad chain. /// Check to see if we'd mine on an apparently bad chain.
bool mineOnBadChain() const { return m_mineOnBadChain; } bool mineOnBadChain() const { return m_mineOnBadChain; }

25
libethereum/EthereumHost.cpp

@ -84,7 +84,7 @@ bool EthereumHost::ensureInitialised()
void EthereumHost::reset() void EthereumHost::reset()
{ {
Guard l(x_sync); RecursiveGuard l(x_sync);
if (m_sync) if (m_sync)
m_sync->abortSync(); m_sync->abortSync();
m_sync.reset(); m_sync.reset();
@ -118,7 +118,7 @@ void EthereumHost::doWork()
if (m_syncStart) if (m_syncStart)
{ {
DEV_GUARDED(x_sync) DEV_RECURSIVE_GUARDED(x_sync)
if (!m_sync) if (!m_sync)
{ {
time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now());
@ -288,46 +288,41 @@ BlockChainSync* EthereumHost::sync()
void EthereumHost::onPeerStatus(std::shared_ptr<EthereumPeer> _peer) void EthereumHost::onPeerStatus(std::shared_ptr<EthereumPeer> _peer)
{ {
Guard l(x_sync); RecursiveGuard l(x_sync);
if (sync()) if (sync())
sync()->onPeerStatus(_peer); sync()->onPeerStatus(_peer);
} }
void EthereumHost::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes) void EthereumHost::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes)
{ {
Guard l(x_sync); RecursiveGuard l(x_sync);
if (sync()) if (sync())
sync()->onPeerHashes(_peer, _hashes); sync()->onPeerHashes(_peer, _hashes);
} }
void EthereumHost::onPeerBlocks(std::shared_ptr<EthereumPeer> _peer, RLP const& _r) void EthereumHost::onPeerBlocks(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{ {
Guard l(x_sync); RecursiveGuard l(x_sync);
if (sync()) if (sync())
sync()->onPeerBlocks(_peer, _r); sync()->onPeerBlocks(_peer, _r);
} }
void EthereumHost::onPeerNewHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes) void EthereumHost::onPeerNewHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes)
{ {
Guard l(x_sync); RecursiveGuard l(x_sync);
if (sync()) if (sync())
sync()->onPeerNewHashes(_peer, _hashes); sync()->onPeerNewHashes(_peer, _hashes);
} }
void EthereumHost::onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP const& _r) void EthereumHost::onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{ {
Guard l(x_sync); RecursiveGuard l(x_sync);
if (sync()) if (sync())
sync()->onPeerNewBlock(_peer, _r); sync()->onPeerNewBlock(_peer, _r);
} }
void EthereumHost::onPeerTransactions(std::shared_ptr<EthereumPeer> _peer, RLP const& _r) void EthereumHost::onPeerTransactions(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{ {
if (_peer->isCriticalSyncing())
{
clog(EthereumHostTrace) << "Ignoring transaction from peer we are syncing with";
return;
}
unsigned itemCount = _r.itemCount(); unsigned itemCount = _r.itemCount();
clog(EthereumHostTrace) << "Transactions (" << dec << itemCount << "entries)"; clog(EthereumHostTrace) << "Transactions (" << dec << itemCount << "entries)";
m_tq.enqueue(_r, _peer->session()->id()); m_tq.enqueue(_r, _peer->session()->id());
@ -335,7 +330,7 @@ void EthereumHost::onPeerTransactions(std::shared_ptr<EthereumPeer> _peer, RLP c
void EthereumHost::onPeerAborting() void EthereumHost::onPeerAborting()
{ {
Guard l(x_sync); RecursiveGuard l(x_sync);
try try
{ {
if (m_sync) if (m_sync)
@ -349,7 +344,7 @@ void EthereumHost::onPeerAborting()
bool EthereumHost::isSyncing() const bool EthereumHost::isSyncing() const
{ {
Guard l(x_sync); RecursiveGuard l(x_sync);
if (!m_sync) if (!m_sync)
return false; return false;
return m_sync->isSyncing(); return m_sync->isSyncing();
@ -357,7 +352,7 @@ bool EthereumHost::isSyncing() const
SyncStatus EthereumHost::status() const SyncStatus EthereumHost::status() const
{ {
Guard l(x_sync); RecursiveGuard l(x_sync);
if (!m_sync) if (!m_sync)
return SyncStatus(); return SyncStatus();
return m_sync->status(); return m_sync->status();

2
libethereum/EthereumHost.h

@ -134,7 +134,7 @@ private:
bool m_newTransactions = false; bool m_newTransactions = false;
bool m_newBlocks = false; bool m_newBlocks = false;
mutable Mutex x_sync; mutable RecursiveMutex x_sync;
mutable Mutex x_transactions; mutable Mutex x_transactions;
DownloadMan m_man; DownloadMan m_man;
std::unique_ptr<BlockChainSync> m_sync; std::unique_ptr<BlockChainSync> m_sync;

4
libethereum/EthereumPeer.cpp

@ -145,7 +145,7 @@ void EthereumPeer::requestHashes(u256 _number, unsigned _count)
setAsking(Asking::Hashes); setAsking(Asking::Hashes);
RLPStream s; RLPStream s;
prep(s, GetBlockHashesByNumberPacket, 2) << m_syncHashNumber << _count; prep(s, GetBlockHashesByNumberPacket, 2) << m_syncHashNumber << _count;
clog(NetMessageDetail) << "Requesting block hashes for numbers " << m_syncHashNumber << "-" << m_syncHashNumber + c_maxHashesAsk - 1; clog(NetMessageDetail) << "Requesting block hashes for numbers " << m_syncHashNumber << "-" << m_syncHashNumber + _count - 1;
sealAndSend(s); sealAndSend(s);
} }
@ -298,7 +298,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
if (m_asking != Asking::Hashes) if (m_asking != Asking::Hashes)
{ {
clog(NetWarn) << "Peer giving us hashes when we didn't ask for them."; clog(NetAllDetail) << "Peer giving us hashes when we didn't ask for them.";
break; break;
} }
setIdle(); setIdle();

11
libethereum/Executive.cpp

@ -399,11 +399,14 @@ void Executive::finalize()
m_refunded = m_ext ? min((m_t.gas() - m_gas) / 2, m_ext->sub.refunds) : 0; m_refunded = m_ext ? min((m_t.gas() - m_gas) / 2, m_ext->sub.refunds) : 0;
m_gas += m_refunded; m_gas += m_refunded;
// cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")"; if (m_t)
m_s.addBalance(m_t.sender(), m_gas * m_t.gasPrice()); {
// cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")";
m_s.addBalance(m_t.sender(), m_gas * m_t.gasPrice());
u256 feesEarned = (m_t.gas() - m_gas) * m_t.gasPrice(); u256 feesEarned = (m_t.gas() - m_gas) * m_t.gasPrice();
m_s.addBalance(m_s.m_currentBlock.coinbaseAddress(), feesEarned); m_s.addBalance(m_s.m_currentBlock.coinbaseAddress(), feesEarned);
}
// Suicides... // Suicides...
if (m_ext) if (m_ext)

43
libevm/SmartVM.cpp

@ -21,9 +21,7 @@
#include "SmartVM.h" #include "SmartVM.h"
#include <unordered_map> #include <unordered_map>
#include <thread> #include <thread>
#include <mutex> #include <libdevcore/concurrent_queue.h>
#include <condition_variable>
#include <queue>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/SHA3.h> #include <libdevcore/SHA3.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
@ -51,34 +49,26 @@ namespace
{ {
bytes code; bytes code;
h256 codeHash; h256 codeHash;
static JitTask createStopSentinel() { return JitTask(); }
bool isStopSentinel()
{
assert((!code.empty() || !codeHash) && "'empty code => empty hash' invariand failed");
return code.empty();
}
}; };
class JitWorker class JitWorker
{ {
bool m_finished = false;
std::mutex x_mutex;
std::condition_variable m_cv;
std::thread m_worker; std::thread m_worker;
std::queue<JitTask> m_queue; concurrent_queue<JitTask> m_queue;
bool pop(JitTask& o_task)
{
std::unique_lock<std::mutex> lock{x_mutex};
m_cv.wait(lock, [this]{ return m_finished || !m_queue.empty(); });
if (m_finished)
return false;
assert(!m_queue.empty());
o_task = std::move(m_queue.front());
m_queue.pop();
return true;
}
void work() void work()
{ {
clog(JitInfo) << "JIT worker started."; clog(JitInfo) << "JIT worker started.";
JitTask task; JitTask task;
while (pop(task)) while (!(task = m_queue.pop()).isStopSentinel())
{ {
clog(JitInfo) << "Compilation... " << task.codeHash; clog(JitInfo) << "Compilation... " << task.codeHash;
evmjit::JIT::compile(task.code.data(), task.code.size(), eth2jit(task.codeHash)); evmjit::JIT::compile(task.code.data(), task.code.size(), eth2jit(task.codeHash));
@ -93,18 +83,11 @@ namespace
~JitWorker() ~JitWorker()
{ {
DEV_GUARDED(x_mutex) push(JitTask::createStopSentinel());
m_finished = true;
m_cv.notify_one();
m_worker.join(); m_worker.join();
} }
void push(JitTask&& _task) void push(JitTask&& _task) { m_queue.push(std::move(_task)); }
{
DEV_GUARDED(x_mutex)
m_queue.push(std::move(_task));
m_cv.notify_one();
}
}; };
} }

23
libp2p/Common.cpp

@ -176,6 +176,29 @@ void NodeIPEndpoint::interpretRLP(RLP const& _r)
tcpPort = _r[2].toInt<uint16_t>(); tcpPort = _r[2].toInt<uint16_t>();
} }
void DeadlineOps::reap()
{
if (m_stopped)
return;
Guard l(x_timers);
std::vector<DeadlineOp>::iterator t = m_timers.begin();
while (t != m_timers.end())
if (t->expired())
{
t->wait();
t = m_timers.erase(t);
}
else
t++;
m_timers.emplace_back(m_io, m_reapIntervalMs, [this](boost::system::error_code const& ec)
{
if (!ec && !m_stopped)
reap();
});
}
namespace dev { namespace dev {
std::ostream& operator<<(std::ostream& _out, dev::p2p::NodeIPEndpoint const& _ep) std::ostream& operator<<(std::ostream& _out, dev::p2p::NodeIPEndpoint const& _ep)

5
libp2p/Common.h

@ -235,15 +235,14 @@ class DeadlineOps
}; };
public: public:
DeadlineOps(ba::io_service& _io, unsigned _reapIntervalMs = 100): m_io(_io), m_reapIntervalMs(_reapIntervalMs), m_stopped({false}) { reap(); } DeadlineOps(ba::io_service& _io, unsigned _reapIntervalMs = 100): m_io(_io), m_reapIntervalMs(_reapIntervalMs), m_stopped(false) { reap(); }
~DeadlineOps() { stop(); } ~DeadlineOps() { stop(); }
void schedule(unsigned _msInFuture, std::function<void(boost::system::error_code const&)> const& _f) { if (m_stopped) return; DEV_GUARDED(x_timers) m_timers.emplace_back(m_io, _msInFuture, _f); } void schedule(unsigned _msInFuture, std::function<void(boost::system::error_code const&)> const& _f) { if (m_stopped) return; DEV_GUARDED(x_timers) m_timers.emplace_back(m_io, _msInFuture, _f); }
void stop() { m_stopped = true; DEV_GUARDED(x_timers) m_timers.clear(); } void stop() { m_stopped = true; DEV_GUARDED(x_timers) m_timers.clear(); }
protected: protected:
void reap() { Guard l(x_timers); auto t = m_timers.begin(); while (t != m_timers.end()) if (t->expired()) { t->wait(); m_timers.erase(t); } else t++; m_timers.emplace_back(m_io, m_reapIntervalMs, [this](boost::system::error_code const& ec){ if (!ec) reap(); }); } void reap();
private: private:
ba::io_service& m_io; ba::io_service& m_io;

3
solc/docker_emscripten/Dockerfile

@ -66,6 +66,5 @@ RUN emcmake cmake -DETH_STATIC=1 -DSOLIDITY=ON -DGUI=0 -DCMAKE_CXX_COMPILER=/hom
RUN emmake make -j 6 soljson RUN emmake make -j 6 soljson
WORKDIR /home/user/cpp-ethereum/solc WORKDIR /home/user/cpp-ethereum/solc
# somehow it does not work to pipe out both files ENTRYPOINT cat soljson.js
#ENTRYPOINT tar -c soljson.js soljson.js.mem | base64

2
test/fuzzTesting/CMakeLists.txt

@ -8,7 +8,7 @@ include_directories(${Boost_INCLUDE_DIRS})
include_directories(${CRYPTOPP_INCLUDE_DIRS}) include_directories(${CRYPTOPP_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
add_executable(createRandomTest "./createRandomTest.cpp" "../TestHelper.cpp" "../Stats.cpp" "fuzzHelper.cpp" "../libethereum/transaction.cpp" "../libethereum/state.cpp" "../libevm/vm.cpp" "../libethereum/blockchain.cpp") add_executable(createRandomTest "./createRandomTest.cpp" "../TestHelper.cpp" "../Stats.cpp" "fuzzHelper.cpp" "../libethereum/transaction.cpp" "../libethereum/state.cpp" "../libevm/vm.cpp" "../libethereum/blockchain.cpp" "../libdevcore/rlp.cpp")
add_executable(createRandomVMTest "./createRandomVMTest.cpp" "../libevm/vm.cpp" "../TestHelper.cpp" "../Stats.cpp") add_executable(createRandomVMTest "./createRandomVMTest.cpp" "../libevm/vm.cpp" "../TestHelper.cpp" "../Stats.cpp")
add_executable(createRandomStateTest "./createRandomStateTest.cpp" "../TestHelper.cpp" "../Stats.cpp" "fuzzHelper.cpp") add_executable(createRandomStateTest "./createRandomStateTest.cpp" "../TestHelper.cpp" "../Stats.cpp" "fuzzHelper.cpp")

37
test/fuzzTesting/createRandomTest.cpp

@ -34,6 +34,7 @@ extern std::string const c_testExampleStateTest;
extern std::string const c_testExampleTransactionTest; extern std::string const c_testExampleTransactionTest;
extern std::string const c_testExampleVMTest; extern std::string const c_testExampleVMTest;
extern std::string const c_testExampleBlockchainTest; extern std::string const c_testExampleBlockchainTest;
extern std::string const c_testExampleRLPTest;
//Main Test functinos //Main Test functinos
void fillRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, std::string const& _testString, bool _debug = false); void fillRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, std::string const& _testString, bool _debug = false);
@ -62,7 +63,8 @@ int main(int argc, char *argv[])
if (arg == "-t" && i + 1 < argc) if (arg == "-t" && i + 1 < argc)
{ {
testSuite = argv[i + 1]; testSuite = argv[i + 1];
if (testSuite != "BlockChainTests" && testSuite != "TransactionTests" && testSuite != "StateTests" && testSuite != "VMTests") if (testSuite != "BlockChainTests" && testSuite != "TransactionTests" && testSuite != "StateTests"
&& testSuite != "VMTests" && testSuite != "RLPTests")
testSuite = ""; testSuite = "";
} }
else else
@ -139,6 +141,14 @@ int main(int argc, char *argv[])
else else
fillRandomTest(dev::test::doVMTests, (filltest) ? testFillString : c_testExampleVMTest, filldebug); fillRandomTest(dev::test::doVMTests, (filltest) ? testFillString : c_testExampleVMTest, filldebug);
} }
else
if (testSuite == "RLPTests")
{
if (checktest)
return checkRandomTest(dev::test::doRlpTests, testmValue, debug);
else
fillRandomTest(dev::test::doRlpTests, (filltest) ? testFillString : c_testExampleRLPTest, filldebug);
}
} }
return 0; return 0;
@ -239,12 +249,23 @@ void parseTestWithTypes(std::string& _test)
std::size_t pos = _test.find(types.at(i)); std::size_t pos = _test.find(types.at(i));
while (pos != std::string::npos) while (pos != std::string::npos)
{ {
if (types.at(i) == "[RLP]")
{
std::string debug;
int randomDepth = 1 + dev::test::RandomCode::randomUniInt() % 10;
_test.replace(pos, 5, dev::test::RandomCode::rndRLPSequence(randomDepth, debug));
cnote << debug;
}
else
if (types.at(i) == "[CODE]") if (types.at(i) == "[CODE]")
_test.replace(pos, 6, "0x"+dev::test::RandomCode::generate(10, options)); _test.replace(pos, 6, "0x"+dev::test::RandomCode::generate(10, options));
else else
if (types.at(i) == "[HEX]") if (types.at(i) == "[HEX]")
_test.replace(pos, 5, dev::test::RandomCode::randomUniIntHex()); _test.replace(pos, 5, dev::test::RandomCode::randomUniIntHex());
else else
if (types.at(i) == "[HEX32]")
_test.replace(pos, 7, dev::test::RandomCode::randomUniIntHex(std::numeric_limits<uint32_t>::max()));
else
if (types.at(i) == "[GASLIMIT]") if (types.at(i) == "[GASLIMIT]")
_test.replace(pos, 10, dev::test::RandomCode::randomUniIntHex(dev::u256("3000000000"))); _test.replace(pos, 10, dev::test::RandomCode::randomUniIntHex(dev::u256("3000000000")));
else else
@ -276,7 +297,7 @@ void parseTestWithTypes(std::string& _test)
std::vector<std::string> getTypes() std::vector<std::string> getTypes()
{ {
return {"[CODE]", "[HEX]", "[HASH20]", "[HASH32]", "[0xHASH32]", "[V]", "[GASLIMIT]"}; return {"[RLP]", "[CODE]", "[HEX]", "[HEX32]", "[HASH20]", "[HASH32]", "[0xHASH32]", "[V]", "[GASLIMIT]"};
} }
std::string const c_testExampleTransactionTest = R"( std::string const c_testExampleTransactionTest = R"(
@ -305,7 +326,7 @@ std::string const c_testExampleStateTest = R"(
"currentCoinbase" : "[HASH20]", "currentCoinbase" : "[HASH20]",
"currentDifficulty" : "[HEX]", "currentDifficulty" : "[HEX]",
"currentGasLimit" : "[GASLIMIT]", "currentGasLimit" : "[GASLIMIT]",
"currentNumber" : "[HEX]", "currentNumber" : "[HEX32]",
"currentTimestamp" : "[HEX]", "currentTimestamp" : "[HEX]",
"previousHash" : "[HASH32]" "previousHash" : "[HASH32]"
}, },
@ -335,7 +356,7 @@ std::string const c_testExampleStateTest = R"(
"transaction" : { "transaction" : {
"data" : "[CODE]", "data" : "[CODE]",
"gasLimit" : "[HEX]", "gasLimit" : "[HEX]",
"gasPrice" : "[V]", "gasPrice" : "[HEX32]",
"nonce" : "0", "nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
@ -377,6 +398,14 @@ std::string const c_testExampleVMTest = R"(
} }
)"; )";
std::string const c_testExampleRLPTest = R"(
{
"randomRLPTest" : {
"out" : "[RLP]"
}
}
)";
std::string const c_testExampleBlockchainTest = R"( std::string const c_testExampleBlockchainTest = R"(
{ {
"randomBlockTest" : { "randomBlockTest" : {

150
test/fuzzTesting/fuzzHelper.cpp

@ -42,11 +42,157 @@ boostIntGenerator RandomCode::randOpLengGen = boostIntGenerator(gen, opLengDist)
boostIntGenerator RandomCode::randUniIntGen = boostIntGenerator(gen, uniIntDist); boostIntGenerator RandomCode::randUniIntGen = boostIntGenerator(gen, uniIntDist);
boostUInt64Generator RandomCode::randUInt64Gen = boostUInt64Generator(gen, uInt64Dist); boostUInt64Generator RandomCode::randUInt64Gen = boostUInt64Generator(gen, uInt64Dist);
std::string RandomCode::rndByteSequence(int _length, SizeStrictness _sizeType) int RandomCode::recursiveRLP(std::string& _result, int _depth, std::string& _debug)
{
bool genValidRlp = true;
int bugProbability = randUniIntGen() % 100;
if (bugProbability < 80)
genValidRlp = false;
if (_depth > 1)
{
//create rlp blocks
int size = 1 + randUniIntGen() % 4;
for (auto i = 0; i < size; i++)
{
std::string blockstr;
std::string blockDebug;
recursiveRLP(blockstr, _depth - 1, blockDebug);
_result += blockstr;
_debug += blockDebug;
}
//make rlp header
int length = _result.size() / 2;
std::string header;
int rtype = 0;
int rnd = randUniIntGen() % 100;
if (rnd < 10)
{
//make header as array
if (length <= 55)
{
header = toCompactHex(128 + length);
rtype = 1;
}
else
{
std::string hexlength = toCompactHex(length);
header = toCompactHex(183 + hexlength.size() / 2) + hexlength;
rtype = 2;
}
}
else
{
//make header as list
if (length <= 55)
{
header = toCompactHex(192 + length);
rtype = 3;
}
else
{
std::string hexlength = toCompactHex(length, HexPrefix::DontAdd, 1);
header = toCompactHex(247 + hexlength.size() / 2) + hexlength;
rtype = 4;
}
}
_result = header + _result;
_debug = "[" + header + "(" + toString(length) + "){" + toString(rtype) + "}]" + _debug;
return _result.size() / 2;
}
if (_depth == 1)
{
bool genbug = false;
bool genbug2 = false;
int bugProbability = randUniIntGen() % 100;
if (bugProbability < 50 && !genValidRlp)
genbug = true;
bugProbability = randUniIntGen() % 100; //more randomness
if (bugProbability < 50 && !genValidRlp)
genbug2 = true;
std::string emptyZeros = genValidRlp ? "" : genbug ? "00" : "";
std::string emptyZeros2 = genValidRlp ? "" : genbug2 ? "00" : "";
int rnd = randUniIntGen() % 5;
switch (rnd)
{
case 0:
{
//single byte [0x00, 0x7f]
std::string rlp = emptyZeros + toCompactHex(genbug ? randUniIntGen() % 255 : randUniIntGen() % 128, HexPrefix::DontAdd, 1);
_result.insert(0, rlp);
_debug.insert(0, "[" + rlp + "]");
return 1;
}
case 1:
{
//string 0-55 [0x80, 0xb7] + string
int len = genbug ? randUniIntGen() % 255 : randUniIntGen() % 55;
std::string hex = rndByteSequence(len);
if (len == 1)
if (genValidRlp && fromHex(hex)[0] < 128)
hex = toCompactHex((u64)128);
_result.insert(0, toCompactHex(128 + len) + emptyZeros + hex);
_debug.insert(0, "[" + toCompactHex(128 + len) + "(" + toString(len) + ")]" + emptyZeros + hex);
return len + 1;
}
case 2:
{
//string more 55 [0xb8, 0xbf] + length + string
int len = randUniIntGen() % 100;
if (len < 56 && genValidRlp)
len = 56;
std::string hex = rndByteSequence(len);
std::string hexlen = emptyZeros2 + toCompactHex(len, HexPrefix::DontAdd, 1);
std::string rlpblock = toCompactHex(183 + hexlen.size() / 2) + hexlen + emptyZeros + hex;
_debug.insert(0, "[" + toCompactHex(183 + hexlen.size() / 2) + hexlen + "(" + toString(len) + "){2}]" + emptyZeros + hex);
_result.insert(0, rlpblock);
return rlpblock.size() / 2;
}
case 3:
{
//list 0-55 [0xc0, 0xf7] + data
int len = genbug ? randUniIntGen() % 255 : randUniIntGen() % 55;
std::string hex = emptyZeros + rndByteSequence(len);
_result.insert(0, toCompactHex(192 + len) + hex);
_debug.insert(0, "[" + toCompactHex(192 + len) + "(" + toString(len) + "){3}]" + hex);
return len + 1;
}
case 4:
{
//list more 55 [0xf8, 0xff] + length + data
int len = randUniIntGen() % 100;
if (len < 56 && genValidRlp)
len = 56;
std::string hexlen = emptyZeros2 + toCompactHex(len, HexPrefix::DontAdd, 1);
std::string rlpblock = toCompactHex(247 + hexlen.size() / 2) + hexlen + emptyZeros + rndByteSequence(len);
_debug.insert(0, "[" + toCompactHex(247 + hexlen.size() / 2) + hexlen + "(" + toString(len) + "){4}]" + emptyZeros + rndByteSequence(len));
_result.insert(0, rlpblock);
return rlpblock.size() / 2;
}
}
}
return 0;
}
std::string RandomCode::rndRLPSequence(int _depth, std::string& _debug)
{ {
refreshSeed(); refreshSeed();
std::string hash; std::string hash;
_length = (_sizeType == SizeStrictness::Strict) ? std::max(1, _length) : randomUniInt() % _length; _depth = std::min(std::max(1, _depth), 7); //limit depth to avoid overkill
recursiveRLP(hash, _depth, _debug);
return hash;
}
std::string RandomCode::rndByteSequence(int _length, SizeStrictness _sizeType)
{
refreshSeed();
std::string hash = "";
_length = (_sizeType == SizeStrictness::Strict) ? std::max(0, _length) : randomUniInt() % _length;
for (auto i = 0; i < _length; i++) for (auto i = 0; i < _length; i++)
{ {
uint8_t byte = randOpCodeGen(); uint8_t byte = randOpCodeGen();

17
test/fuzzTesting/fuzzHelper.h

@ -66,6 +66,12 @@ enum class SizeStrictness
Random Random
}; };
struct RlpDebug
{
std::string rlp;
int insertions;
};
class RandomCode class RandomCode
{ {
public: public:
@ -75,6 +81,16 @@ public:
/// Generate random byte string of a given length /// Generate random byte string of a given length
static std::string rndByteSequence(int _length = 1, SizeStrictness _sizeType = SizeStrictness::Strict); static std::string rndByteSequence(int _length = 1, SizeStrictness _sizeType = SizeStrictness::Strict);
/// Generate random rlp byte sequence of a given depth (e.g [[[]],[]]). max depth level = 20.
/// The _debug string contains returned rlp string with analysed sections
/// [] - length section/ or single byte rlp encoding
/// () - decimal representation of length
/// {1} - Array
/// {2} - Array more than 55
/// {3} - List
/// {4} - List more than 55
static std::string rndRLPSequence(int _depth, std::string& _debug);
/// Generate random int64 /// Generate random int64
static std::string randomUniIntHex(u256 _maxVal = 0); static std::string randomUniIntHex(u256 _maxVal = 0);
static int randomUniInt(); static int randomUniInt();
@ -83,6 +99,7 @@ private:
static std::string fillArguments(dev::eth::Instruction _opcode, RandomCodeOptions const& _options); static std::string fillArguments(dev::eth::Instruction _opcode, RandomCodeOptions const& _options);
static std::string getPushCode(int _value); static std::string getPushCode(int _value);
static std::string getPushCode(std::string const& _hex); static std::string getPushCode(std::string const& _hex);
static int recursiveRLP(std::string& _result, int _depth, std::string& _debug);
static void refreshSeed(); static void refreshSeed();
static boost::random::mt19937 gen; ///< Random generator static boost::random::mt19937 gen; ///< Random generator

34
test/libdevcore/rlp.cpp

@ -30,8 +30,8 @@
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <algorithm> #include <algorithm>
#include "../JsonSpiritHeaders.h" #include "test/JsonSpiritHeaders.h"
#include "../TestHelper.h" #include "test/TestHelper.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
@ -72,8 +72,6 @@ namespace dev
bytes payloadToDecode = fromHex(o["out"].get_str()); bytes payloadToDecode = fromHex(o["out"].get_str());
RLP payload(payloadToDecode); RLP payload(payloadToDecode);
ostringstream() << payload; ostringstream() << payload;
if (payload.isEmpty())
BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("Decoded Empty RLP!"));
o["in"] = "VALID"; o["in"] = "VALID";
} }
catch (Exception const& _e) catch (Exception const& _e)
@ -129,6 +127,8 @@ namespace dev
{ {
bytes payloadToDecode = fromHex(o["out"].get_str()); bytes payloadToDecode = fromHex(o["out"].get_str());
RLP payload(payloadToDecode); RLP payload(payloadToDecode);
//attempt to read all the contents of RLP
ostringstream() << payload; ostringstream() << payload;
if (rlpType == RlpType::Test) if (rlpType == RlpType::Test)
@ -144,6 +144,10 @@ namespace dev
cnote << "rlp exception: " << _e.what(); cnote << "rlp exception: " << _e.what();
was_exception = true; was_exception = true;
} }
catch (...)
{
was_exception = true;
}
//Expect exception as input is INVALID //Expect exception as input is INVALID
if (rlpType == RlpType::Invalid && was_exception) if (rlpType == RlpType::Invalid && was_exception)
@ -238,6 +242,28 @@ namespace dev
BOOST_AUTO_TEST_SUITE(RlpTests) BOOST_AUTO_TEST_SUITE(RlpTests)
BOOST_AUTO_TEST_CASE(EmptyArrayList)
{
try
{
bytes payloadToDecode = fromHex("80");
RLP payload(payloadToDecode);
ostringstream() << payload;
payloadToDecode = fromHex("с0");
RLP payload2(payloadToDecode);
ostringstream() << payload2;
}
catch (Exception const& _e)
{
TBOOST_ERROR("Failed test with Exception: " << _e.what());
}
catch (exception const& _e)
{
TBOOST_ERROR("Failed test with Exception: " << _e.what());
}
}
BOOST_AUTO_TEST_CASE(invalidRLPtest) BOOST_AUTO_TEST_CASE(invalidRLPtest)
{ {
dev::test::executeTests("invalidRLPTest", "/RLPTests", dev::test::getFolder(__FILE__) + "/RLPTestsFiller", dev::test::doRlpTests); dev::test::executeTests("invalidRLPTest", "/RLPTests", dev::test::getFolder(__FILE__) + "/RLPTestsFiller", dev::test::doRlpTests);

Loading…
Cancel
Save