Browse Source

Merge branch 'bc' of https://github.com/arkpar/cpp-ethereum into bc

cl-refactor
arkpar 10 years ago
parent
commit
41f2bdab95
  1. 1
      alethzero/MainWin.cpp
  2. 2
      cmake/EthCompilerSettings.cmake
  3. 2
      evmjit/libevmjit-cpp/JitVM.cpp
  4. 2
      libdevcrypto/CryptoPP.cpp
  5. 180
      libethereum/BlockChain.cpp
  6. 6
      libethereum/BlockChain.h
  7. 83
      libethereum/BlockQueue.cpp
  8. 7
      libethereum/BlockQueue.h
  9. 2
      libethereum/Client.cpp
  10. 5
      libethereum/Executive.cpp
  11. 4
      libethereum/ExtVM.h
  12. 56
      libethereum/State.cpp
  13. 5
      libethereum/State.h
  14. 53
      libethereum/VerifiedBlock.h
  15. 3
      libevm/ExtVMFace.cpp
  16. 3
      libevm/ExtVMFace.h
  17. 4
      libp2p/RLPxFrameIO.h
  18. 2
      test/libevm/vm.cpp

1
alethzero/MainWin.cpp

@ -805,6 +805,7 @@ void Main::readSettings(bool _skipGeometry)
ui->usePrivate->setChecked(m_privateChain.size());
ui->verbosity->setValue(s.value("verbosity", 1).toInt());
ui->jitvm->setChecked(s.value("jitvm", true).toBool());
on_jitvm_triggered();
ui->urlEdit->setText(s.value("url", "about:blank").toString()); //http://gavwood.com/gavcoin.html
on_urlEdit_returnPressed();

2
cmake/EthCompilerSettings.cmake

@ -21,7 +21,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE")
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++ -fcolor-diagnostics -Qunused-arguments -DBOOST_ASIO_HAS_CLANG_LIBCXX")

2
evmjit/libevmjit-cpp/JitVM.cpp

@ -51,7 +51,7 @@ bytesConstRef JitVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _on
m_data.timestamp = static_cast<decltype(m_data.timestamp)>(_ext.currentBlock.timestamp);
m_data.code = _ext.code.data();
m_data.codeSize = _ext.code.size();
m_data.codeHash = eth2llvm(sha3(_ext.code));
m_data.codeHash = eth2llvm(_ext.codeHash);
auto env = reinterpret_cast<Env*>(&_ext);
auto exitCode = m_engine.run(&m_data, env);

2
libdevcrypto/CryptoPP.cpp

@ -264,7 +264,6 @@ Public Secp256k1::recover(Signature _signature, bytesConstRef _message)
ECP::Element x;
{
Guard l(x_curve);
m_curve.DecodePoint(x, encodedpoint, 33);
if (!m_curve.VerifyPoint(x))
return recovered;
@ -286,7 +285,6 @@ Public Secp256k1::recover(Signature _signature, bytesConstRef _message)
ECP::Point p;
byte recoveredbytes[65];
{
Guard l(x_curve);
// todo: make generator member
p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator());
m_curve.EncodePoint(recoveredbytes, p, false);

180
libethereum/BlockChain.cpp

@ -35,6 +35,7 @@
#include <libdevcore/StructuredLogger.h>
#include <libdevcore/FileSystem.h>
#include <libethcore/Exceptions.h>
#include <libethcore/EthashAux.h>
#include <libethcore/ProofOfWork.h>
#include <libethcore/BlockInfo.h>
#include <libethcore/Params.h>
@ -42,6 +43,7 @@
#include "GenesisInfo.h"
#include "State.h"
#include "Defaults.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
@ -307,7 +309,7 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
{
// _bq.tick(*this);
vector<pair<BlockInfo, bytes>> blocks;
VerifiedBlocks blocks;
_bq.drain(blocks, _max);
h256s fresh;
@ -320,7 +322,7 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
// Nonce & uncle nonces already verified in verification thread at this point.
ImportRoute r;
DEV_TIMED_ABOVE(Block import, 500)
r = import(block.first, block.second, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles);
r = import(block.verified, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles);
fresh += r.first;
dead += r.second;
}
@ -329,14 +331,14 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
cwarn << "ODD: Import queue contains block with unknown parent." << LogTag::Error << boost::current_exception_diagnostic_information();
// NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad.
badBlocks.push_back(block.first.hash());
badBlocks.push_back(block.verified.info.hash());
}
catch (Exception const& _e)
{
cnote << "Exception while importing block. Someone (Jeff? That you?) seems to be giving us dodgy blocks!" << LogTag::Error << diagnostic_information(_e);
// NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad.
badBlocks.push_back(block.first.hash());
badBlocks.push_back(block.verified.info.hash());
}
}
return make_tuple(fresh, dead, _bq.doneDrain(badBlocks));
@ -346,7 +348,7 @@ pair<ImportResult, ImportRoute> BlockChain::attemptImport(bytes const& _block, O
{
try
{
return make_pair(ImportResult::Success, import(_block, _stateDB, _ir));
return make_pair(ImportResult::Success, import(verifyBlock(_block, _ir), _stateDB, _ir));
}
catch (UnknownParent&)
{
@ -369,14 +371,13 @@ pair<ImportResult, ImportRoute> BlockChain::attemptImport(bytes const& _block, O
ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, ImportRequirements::value _ir)
{
// VERIFY: populates from the block and checks the block is internally coherent.
BlockInfo bi;
VerifiedBlockRef block;
#if ETH_CATCH
try
#endif
{
bi.populate(&_block);
bi.verifyInternals(&_block);
block = verifyBlock(_block, _ir);
}
#if ETH_CATCH
catch (Exception const& _e)
@ -387,10 +388,10 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
}
#endif
return import(bi, _block, _db, _ir);
return import(block, _db, _ir);
}
ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, OverlayDB const& _db, ImportRequirements::value _ir)
ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const& _db, ImportRequirements::value _ir)
{
//@tidy This is a behemoth of a method - could do to be split into a few smaller ones.
@ -405,28 +406,28 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
#endif
// Check block doesn't already exist first!
if (isKnown(_bi.hash()) && (_ir & ImportRequirements::DontHave))
if (isKnown(_block.info.hash()) && (_ir & ImportRequirements::DontHave))
{
clog(BlockChainNote) << _bi.hash() << ": Not new.";
clog(BlockChainNote) << _block.info.hash() << ": Not new.";
BOOST_THROW_EXCEPTION(AlreadyHaveBlock());
}
// Work out its number as the parent's number + 1
if (!isKnown(_bi.parentHash))
if (!isKnown(_block.info.parentHash))
{
clog(BlockChainNote) << _bi.hash() << ": Unknown parent " << _bi.parentHash;
clog(BlockChainNote) << _block.info.hash() << ": Unknown parent " << _block.info.parentHash;
// We don't know the parent (yet) - discard for now. It'll get resent to us if we find out about its ancestry later on.
BOOST_THROW_EXCEPTION(UnknownParent());
}
auto pd = details(_bi.parentHash);
auto pd = details(_block.info.parentHash);
if (!pd)
{
auto pdata = pd.rlp();
clog(BlockChainDebug) << "Details is returning false despite block known:" << RLP(pdata);
auto parentBlock = block(_bi.parentHash);
clog(BlockChainDebug) << "isKnown:" << isKnown(_bi.parentHash);
clog(BlockChainDebug) << "last/number:" << m_lastBlockNumber << m_lastBlockHash << _bi.number;
auto parentBlock = block(_block.info.parentHash);
clog(BlockChainDebug) << "isKnown:" << isKnown(_block.info.parentHash);
clog(BlockChainDebug) << "last/number:" << m_lastBlockNumber << m_lastBlockHash << _block.info.number;
clog(BlockChainDebug) << "Block:" << BlockInfo(parentBlock);
clog(BlockChainDebug) << "RLP:" << RLP(parentBlock);
clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE";
@ -434,14 +435,14 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
}
// Check it's not crazy
if (_bi.timestamp > (u256)time(0))
if (_block.info.timestamp > (u256)time(0))
{
clog(BlockChainChat) << _bi.hash() << ": Future time " << _bi.timestamp << " (now at " << time(0) << ")";
clog(BlockChainChat) << _block.info.hash() << ": Future time " << _block.info.timestamp << " (now at " << time(0) << ")";
// Block has a timestamp in the future. This is no good.
BOOST_THROW_EXCEPTION(FutureTime());
}
clog(BlockChainChat) << "Attempting import of " << _bi.hash() << "...";
clog(BlockChainChat) << "Attempting import of " << _block.info.hash() << "...";
#if ETH_TIMED_IMPORTS
preliminaryChecks = t.elapsed();
@ -461,7 +462,7 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
// Check transactions are valid and that they result in a state equivalent to our state_root.
// Get total difficulty increase and update state, checking it.
State s(_db);
auto tdIncrease = s.enactOn(&_block, _bi, *this, _ir);
auto tdIncrease = s.enactOn(_block, *this, _ir);
BlockLogBlooms blb;
BlockReceipts br;
@ -497,22 +498,22 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
// together with an "ensureCachedWithUpdatableLock(l)" method.
// This is safe in practice since the caches don't get flushed nearly often enough to be
// done here.
details(_bi.parentHash);
details(_block.info.parentHash);
DEV_WRITE_GUARDED(x_details)
m_details[_bi.parentHash].children.push_back(_bi.hash());
m_details[_block.info.parentHash].children.push_back(_block.info.hash());
#if ETH_TIMED_IMPORTS || !ETH_TRUE
collation = t.elapsed();
t.restart();
#endif
blocksBatch.Put(toSlice(_bi.hash()), (ldb::Slice)ref(_block));
blocksBatch.Put(toSlice(_block.info.hash()), ldb::Slice(_block.block));
DEV_READ_GUARDED(x_details)
extrasBatch.Put(toSlice(_bi.parentHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[_bi.parentHash].rlp()));
extrasBatch.Put(toSlice(_block.info.parentHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[_block.info.parentHash].rlp()));
extrasBatch.Put(toSlice(_bi.hash(), ExtraDetails), (ldb::Slice)dev::ref(BlockDetails((unsigned)pd.number + 1, td, _bi.parentHash, {}).rlp()));
extrasBatch.Put(toSlice(_bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(blb.rlp()));
extrasBatch.Put(toSlice(_bi.hash(), ExtraReceipts), (ldb::Slice)dev::ref(br.rlp()));
extrasBatch.Put(toSlice(_block.info.hash(), ExtraDetails), (ldb::Slice)dev::ref(BlockDetails((unsigned)pd.number + 1, td, _block.info.parentHash, {}).rlp()));
extrasBatch.Put(toSlice(_block.info.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(blb.rlp()));
extrasBatch.Put(toSlice(_block.info.hash(), ExtraReceipts), (ldb::Slice)dev::ref(br.rlp()));
#if ETH_TIMED_IMPORTS || !ETH_TRUE
writing = t.elapsed();
@ -530,20 +531,20 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
{
clog(BlockChainWarn) << " Malformed block: " << diagnostic_information(_e);
_e << errinfo_comment("Malformed block ");
clog(BlockChainWarn) << "Block: " << _bi.hash();
clog(BlockChainWarn) << _bi;
clog(BlockChainWarn) << "Block parent: " << _bi.parentHash;
clog(BlockChainWarn) << BlockInfo(block(_bi.parentHash));
clog(BlockChainWarn) << "Block: " << _block.info.hash();
clog(BlockChainWarn) << _block.info;
clog(BlockChainWarn) << "Block parent: " << _block.info.parentHash;
clog(BlockChainWarn) << BlockInfo(block(_block.info.parentHash));
throw;
}
#endif
StructuredLogger::chainReceivedNewBlock(
_bi.headerHash(WithoutNonce).abridged(),
_bi.nonce.abridged(),
_block.info.headerHash(WithoutNonce).abridged(),
_block.info.nonce.abridged(),
currentHash().abridged(),
"", // TODO: remote id ??
_bi.parentHash.abridged()
_block.info.parentHash.abridged()
);
// cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children.";
@ -556,8 +557,8 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
// don't include bi.hash() in treeRoute, since it's not yet in details DB...
// just tack it on afterwards.
unsigned commonIndex;
tie(route, common, commonIndex) = treeRoute(last, _bi.parentHash);
route.push_back(_bi.hash());
tie(route, common, commonIndex) = treeRoute(last, _block.info.parentHash);
route.push_back(_block.info.hash());
// Most of the time these two will be equal - only when we're doing a chain revert will they not be
if (common != last)
@ -569,8 +570,8 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
for (auto i = route.rbegin(); i != route.rend() && *i != common; ++i)
{
BlockInfo tbi;
if (*i == _bi.hash())
tbi = _bi;
if (*i == _block.info.hash())
tbi = _block.info;
else
tbi = BlockInfo(block(*i));
@ -597,7 +598,7 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
h256s newTransactionAddresses;
{
bytes blockBytes;
RLP blockRLP(*i == _bi.hash() ? _block : (blockBytes = block(*i)));
RLP blockRLP(*i == _block.info.hash() ? _block.block : &(blockBytes = block(*i)));
TransactionAddress ta;
ta.blockHash = tbi.hash();
for (ta.index = 0; ta.index < blockRLP[1].itemCount(); ++ta.index)
@ -613,17 +614,17 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
// FINALLY! change our best hash.
{
newLastBlockHash = _bi.hash();
newLastBlockNumber = (unsigned)_bi.number;
newLastBlockHash = _block.info.hash();
newLastBlockNumber = (unsigned)_block.info.number;
}
clog(BlockChainNote) << " Imported and best" << td << " (#" << _bi.number << "). Has" << (details(_bi.parentHash).children.size() - 1) << "siblings. Route:" << route;
clog(BlockChainNote) << " Imported and best" << td << " (#" << _block.info.number << "). Has" << (details(_block.info.parentHash).children.size() - 1) << "siblings. Route:" << route;
StructuredLogger::chainNewHead(
_bi.headerHash(WithoutNonce).abridged(),
_bi.nonce.abridged(),
_block.info.headerHash(WithoutNonce).abridged(),
_block.info.nonce.abridged(),
currentHash().abridged(),
_bi.parentHash.abridged()
_block.info.parentHash.abridged()
);
}
else
@ -634,24 +635,26 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
m_blocksDB->Write(m_writeOptions, &blocksBatch);
m_extrasDB->Write(m_writeOptions, &extrasBatch);
if (isKnown(_bi.hash()) && !details(_bi.hash()))
#if ETH_DEBUG || !ETH_TRUE
if (isKnown(_block.info.hash()) && !details(_block.info.hash()))
{
clog(BlockChainDebug) << "Known block just inserted has no details.";
clog(BlockChainDebug) << "Block:" << _bi;
clog(BlockChainDebug) << "Block:" << _block.info;
clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE";
exit(-1);
}
try {
State canary(_db, *this, _bi.hash(), ImportRequirements::DontHave);
State canary(_db, *this, _block.info.hash(), ImportRequirements::DontHave);
}
catch (...)
{
clog(BlockChainDebug) << "Failed to initialise State object form imported block.";
clog(BlockChainDebug) << "Block:" << _bi;
clog(BlockChainDebug) << "Block:" << _block.info;
clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE";
exit(-1);
}
#endif
if (m_lastBlockHash != newLastBlockHash)
DEV_WRITE_GUARDED(x_lastBlockHash)
@ -1054,3 +1057,78 @@ bytes BlockChain::block(h256 const& _hash) const
return m_blocks[_hash];
}
VerifiedBlockRef BlockChain::verifyBlock(bytes const& _block, ImportRequirements::value)
{
VerifiedBlockRef res;
try
{
res.info.populate(_block, CheckEverything);
res.info.verifyInternals(&_block);
}
catch (InvalidBlockNonce&)
{
badBlock(_block, "Invalid block nonce");
cwarn << " Nonce:" << res.info.nonce.hex();
cwarn << " PoWHash:" << res.info.headerHash(WithoutNonce).hex();
cwarn << " SeedHash:" << res.info.seedHash().hex();
cwarn << " Target:" << res.info.boundary().hex();
cwarn << " MixHash:" << res.info.mixHash.hex();
Ethash::Result er = EthashAux::eval(res.info.seedHash(), res.info.headerHash(WithoutNonce), res.info.nonce);
cwarn << " Ethash v:" << er.value.hex();
cwarn << " Ethash mH:" << er.mixHash.hex();
throw;
}
catch (Exception& _e)
{
badBlock(_block, _e.what());
throw;
}
RLP r(&_block);
for (auto const& uncle: r[2])
{
try
{
BlockInfo().populateFromHeader(RLP(uncle.data()), CheckEverything);
}
catch (InvalidNonce&)
{
badBlockHeader(uncle.data(), "Invalid uncle nonce");
BlockInfo bi = BlockInfo::fromHeader(uncle.data(), CheckNothing);
cwarn << " Nonce:" << bi.nonce.hex();
cwarn << " PoWHash:" << bi.headerHash(WithoutNonce).hex();
cwarn << " SeedHash:" << bi.seedHash().hex();
cwarn << " Target:" << bi.boundary().hex();
cwarn << " MixHash:" << bi.mixHash.hex();
Ethash::Result er = EthashAux::eval(bi.seedHash(), bi.headerHash(WithoutNonce), bi.nonce);
cwarn << " Ethash v:" << er.value.hex();
cwarn << " Ethash mH:" << er.mixHash.hex();
throw;
}
catch (Exception& _e)
{
badBlockHeader(uncle.data(), _e.what());
throw;
}
}
unsigned i = 0;
for (auto const& tr: r[1])
{
try
{
res.transactions.push_back(Transaction(tr.data(), CheckTransaction::Everything));
}
catch (...)
{
badBlock(_block, "Invalid transaction");
cwarn << " Transaction Index:" << i;
throw;
}
++i;
}
res.block = bytesConstRef(&_block);
return move(res);
}

6
libethereum/BlockChain.h

@ -40,6 +40,7 @@
#include "Account.h"
#include "Transaction.h"
#include "BlockQueue.h"
#include "VerifiedBlock.h"
namespace ldb = leveldb;
namespace std
@ -120,7 +121,7 @@ public:
/// Import block into disk-backed DB
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
ImportRoute import(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir = ImportRequirements::Default);
ImportRoute import(BlockInfo const& _bi, bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir = ImportRequirements::Default);
ImportRoute import(VerifiedBlockRef const& _block, OverlayDB const& _db, ImportRequirements::value _ir = ImportRequirements::Default);
/// Returns true if the given block is known (though not necessarily a part of the canon chain).
bool isKnown(h256 const& _hash) const;
@ -256,6 +257,9 @@ public:
/// Deallocate unused data.
void garbageCollect(bool _force = false);
/// Verify block and prepare it for enactment
static VerifiedBlockRef verifyBlock(bytes const& _block, ImportRequirements::value _ir = ImportRequirements::Default);
private:
static h256 chunkId(unsigned _level, unsigned _index) { return h256(_index * 0xff + _level); }

83
libethereum/BlockQueue.cpp

@ -22,10 +22,11 @@
#include "BlockQueue.h"
#include <thread>
#include <libdevcore/Log.h>
#include <libethcore/EthashAux.h>
#include <libethcore/Exceptions.h>
#include <libethcore/BlockInfo.h>
#include "BlockChain.h"
#include "VerifiedBlock.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
@ -71,62 +72,14 @@ void BlockQueue::verifierBody()
m_unverified.pop_front();
BlockInfo bi;
bi.mixHash = work.first;
m_verifying.push_back(make_pair(bi, bytes()));
m_verifying.push_back(VerifiedBlock { VerifiedBlockRef { bytesConstRef(), move(bi), Transactions() }, bytes() });
}
std::pair<BlockInfo, bytes> res;
swap(work.second, res.second);
try {
try {
res.first.populate(res.second, CheckEverything, work.first);
res.first.verifyInternals(&res.second);
}
catch (InvalidBlockNonce&)
{
badBlock(res.second, "Invalid block nonce");
cwarn << " Nonce:" << res.first.nonce.hex();
cwarn << " PoWHash:" << res.first.headerHash(WithoutNonce).hex();
cwarn << " SeedHash:" << res.first.seedHash().hex();
cwarn << " Target:" << res.first.boundary().hex();
cwarn << " MixHash:" << res.first.mixHash.hex();
Ethash::Result er = EthashAux::eval(res.first.seedHash(), res.first.headerHash(WithoutNonce), res.first.nonce);
cwarn << " Ethash v:" << er.value.hex();
cwarn << " Ethash mH:" << er.mixHash.hex();
throw;
}
catch (Exception& _e)
{
badBlock(res.second, _e.what());
throw;
}
RLP r(&res.second);
for (auto const& uncle: r[2])
{
try
{
BlockInfo().populateFromHeader(RLP(uncle.data()), CheckEverything);
}
catch (InvalidNonce&)
{
badBlockHeader(uncle.data(), "Invalid uncle nonce");
BlockInfo bi = BlockInfo::fromHeader(uncle.data(), CheckNothing);
cwarn << " Nonce:" << bi.nonce.hex();
cwarn << " PoWHash:" << bi.headerHash(WithoutNonce).hex();
cwarn << " SeedHash:" << bi.seedHash().hex();
cwarn << " Target:" << bi.boundary().hex();
cwarn << " MixHash:" << bi.mixHash.hex();
Ethash::Result er = EthashAux::eval(bi.seedHash(), bi.headerHash(WithoutNonce), bi.nonce);
cwarn << " Ethash v:" << er.value.hex();
cwarn << " Ethash mH:" << er.mixHash.hex();
throw;
}
catch (Exception& _e)
{
badBlockHeader(uncle.data(), _e.what());
throw;
}
}
VerifiedBlock res;
swap(work.second, res.blockData);
try
{
res.verified = BlockChain::verifyBlock(res.blockData);
}
catch (...)
{
@ -141,7 +94,7 @@ void BlockQueue::verifierBody()
unique_lock<Mutex> l(m_verification);
for (auto it = m_verifying.begin(); it != m_verifying.end(); ++it)
if (it->first.mixHash == work.first)
if (it->verified.info.mixHash == work.first)
{
m_verifying.erase(it);
goto OK1;
@ -154,12 +107,12 @@ void BlockQueue::verifierBody()
bool ready = false;
{
unique_lock<Mutex> l(m_verification);
if (m_verifying.front().first.mixHash == work.first)
if (m_verifying.front().verified.info.mixHash == work.first)
{
// we're next!
m_verifying.pop_front();
m_verified.push_back(move(res));
while (m_verifying.size() && !m_verifying.front().second.empty())
while (m_verifying.size() && !m_verifying.front().blockData.empty())
{
m_verified.push_back(move(m_verifying.front()));
m_verifying.pop_front();
@ -169,7 +122,7 @@ void BlockQueue::verifierBody()
else
{
for (auto& i: m_verifying)
if (i.first.mixHash == work.first)
if (i.verified.info.mixHash == work.first)
{
i = move(res);
goto OK;
@ -277,15 +230,15 @@ bool BlockQueue::doneDrain(h256s const& _bad)
m_drainingSet.clear();
if (_bad.size())
{
vector<pair<BlockInfo, bytes>> old;
vector<VerifiedBlock> old;
DEV_GUARDED(m_verification)
swap(m_verified, old);
for (auto& b: old)
{
if (m_knownBad.count(b.first.parentHash))
if (m_knownBad.count(b.verified.info.parentHash))
{
m_knownBad.insert(b.first.hash());
m_readySet.erase(b.first.hash());
m_knownBad.insert(b.verified.info.hash());
m_readySet.erase(b.verified.info.hash());
}
else
DEV_GUARDED(m_verification)
@ -348,7 +301,7 @@ QueueStatus BlockQueue::blockStatus(h256 const& _h) const
QueueStatus::Unknown;
}
void BlockQueue::drain(std::vector<std::pair<BlockInfo, bytes>>& o_out, unsigned _max)
void BlockQueue::drain(VerifiedBlocks& o_out, unsigned _max)
{
WriteGuard l(m_lock);
DEV_INVARIANT_CHECK;
@ -364,7 +317,7 @@ void BlockQueue::drain(std::vector<std::pair<BlockInfo, bytes>>& o_out, unsigned
for (auto const& bs: o_out)
{
// TODO: @optimise use map<h256, bytes> rather than vector<bytes> & set<h256>.
auto h = bs.first.hash();
auto h = bs.verified.info.hash();
m_drainingSet.insert(h);
m_readySet.erase(h);
}

7
libethereum/BlockQueue.h

@ -31,6 +31,7 @@
#include <libdevcore/Guards.h>
#include <libethcore/Common.h>
#include <libethcore/BlockInfo.h>
#include "VerifiedBlock.h"
namespace dev
{
@ -81,7 +82,7 @@ public:
/// Grabs at most @a _max of the blocks that are ready, giving them in the correct order for insertion into the chain.
/// Don't forget to call doneDrain() once you're done importing.
void drain(std::vector<std::pair<BlockInfo, bytes>>& o_out, unsigned _max);
void drain(std::vector<VerifiedBlock>& o_out, unsigned _max);
/// Must be called after a drain() call. Notes that the drained blocks have been imported into the blockchain, so we can forget about them.
/// @returns true iff there are additional blocks ready to be processed.
@ -128,8 +129,8 @@ private:
mutable Mutex m_verification; ///< Mutex that allows writing to m_verified, m_verifying and m_unverified.
std::condition_variable m_moreToVerify; ///< Signaled when m_unverified has a new entry.
std::vector<std::pair<BlockInfo, bytes>> m_verified; ///< List of blocks, in correct order, verified and ready for chain-import.
std::deque<std::pair<BlockInfo, bytes>> m_verifying; ///< List of blocks being verified; as long as the second component (bytes) is empty, it's not finished.
std::vector<VerifiedBlock> m_verified; ///< List of blocks, in correct order, verified and ready for chain-import.
std::deque<VerifiedBlock> m_verifying; ///< List of blocks being verified; as long as the second component (bytes) is empty, it's not finished.
std::deque<std::pair<h256, bytes>> m_unverified; ///< List of blocks, in correct order, ready for verification.
std::vector<std::thread> m_verifiers; ///< Threads who only verify.

2
libethereum/Client.cpp

@ -174,7 +174,7 @@ Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _for
}
Client::Client(p2p::Host* _extNet, std::shared_ptr<GasPricer> _gp, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId):
Worker("eth"),
Worker("eth", 0),
m_vc(_dbPath),
m_bc(_dbPath, max(m_vc.action(), _forceAction), [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }),
m_gp(_gp),

5
libethereum/Executive.cpp

@ -151,7 +151,8 @@ bool Executive::call(CallParameters const& _p, u256 const& _gasPrice, Address co
{
m_outRef = _p.out; // Save ref to expected output buffer to be used in go()
bytes const& c = m_s.code(_p.codeAddress);
m_ext = make_shared<ExtVM>(m_s, m_lastHashes, _p.receiveAddress, _p.senderAddress, _origin, _p.value, _gasPrice, _p.data, &c, m_depth);
h256 codeHash = m_s.codeHash(_p.codeAddress);
m_ext = make_shared<ExtVM>(m_s, m_lastHashes, _p.receiveAddress, _p.senderAddress, _origin, _p.value, _gasPrice, _p.data, &c, codeHash, m_depth);
}
}
@ -171,7 +172,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g
// Execute _init.
if (!_init.empty())
m_ext = make_shared<ExtVM>(m_s, m_lastHashes, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_depth);
m_ext = make_shared<ExtVM>(m_s, m_lastHashes, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, sha3(_init), m_depth);
m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress), Account::ContractConception);
m_s.transferBalance(_sender, m_newAddress, _endowment);

4
libethereum/ExtVM.h

@ -39,8 +39,8 @@ class ExtVM: public ExtVMFace
{
public:
/// Full constructor.
ExtVM(State& _s, LastHashes const& _lh, Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, unsigned _depth = 0):
ExtVMFace(_myAddress, _caller, _origin, _value, _gasPrice, _data, _code.toBytes(), _s.m_previousBlock, _s.m_currentBlock, _lh, _depth), m_s(_s), m_origCache(_s.m_cache)
ExtVM(State& _s, LastHashes const& _lh, Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, h256 const& _codeHash, unsigned _depth = 0):
ExtVMFace(_myAddress, _caller, _origin, _value, _gasPrice, _data, _code.toBytes(), _codeHash, _s.m_previousBlock, _s.m_currentBlock, _lh, _depth), m_s(_s), m_origCache(_s.m_cache)
{
m_s.ensureCached(_myAddress, true, true);
}

56
libethereum/State.cpp

@ -141,7 +141,7 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h, ImportRequire
// 2. Enact the block's transactions onto this state.
m_ourAddress = bi.coinbaseAddress;
enact(&b, _bc, _ir);
enact(BlockChain::verifyBlock(b, _ir), _bc, _ir);
}
else
{
@ -382,7 +382,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi, Impor
return ret;
}
u256 State::enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const& _bc, ImportRequirements::value _ir)
u256 State::enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportRequirements::value _ir)
{
#if ETH_TIMED_ENACTMENTS
boost::timer t;
@ -393,8 +393,8 @@ u256 State::enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const
#endif
// Check family:
BlockInfo biParent = _bc.info(_bi.parentHash);
_bi.verifyParent(biParent);
BlockInfo biParent = _bc.info(_block.info.parentHash);
_block.info.verifyParent(biParent);
#if ETH_TIMED_ENACTMENTS
populateVerify = t.elapsed();
@ -410,7 +410,7 @@ u256 State::enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const
t.restart();
#endif
sync(_bc, _bi.parentHash, BlockInfo(), _ir);
sync(_bc, _block.info.parentHash, BlockInfo(), _ir);
resetCurrent();
#if ETH_TIMED_ENACTMENTS
@ -592,15 +592,12 @@ string State::vmTrace(bytesConstRef _block, BlockChain const& _bc, ImportRequire
return ss.str();
}
u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirements::value _ir)
u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportRequirements::value _ir)
{
// m_currentBlock is assumed to be prepopulated and reset.
BlockInfo bi(_block, (_ir & ImportRequirements::ValidNonce) ? CheckEverything : IgnoreNonce);
#if !ETH_RELEASE
assert(m_previousBlock.hash() == bi.parentHash);
assert(m_currentBlock.parentHash == bi.parentHash);
assert(m_previousBlock.hash() == _block.info.parentHash);
assert(m_currentBlock.parentHash == _block.info.parentHash);
assert(rootHash() == m_previousBlock.stateRoot);
#endif
@ -608,32 +605,31 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
BOOST_THROW_EXCEPTION(InvalidParentHash());
// Populate m_currentBlock with the correct values.
m_currentBlock = bi;
m_currentBlock.verifyInternals(_block);
m_currentBlock = _block.info;
m_currentBlock.noteDirty();
// cnote << "playback begins:" << m_state.root();
// cnote << m_state;
LastHashes lh = _bc.lastHashes((unsigned)m_previousBlock.number);
RLP rlp(_block);
RLP rlp(_block.block);
vector<bytes> receipts;
// All ok with the block generally. Play back the transactions now...
unsigned i = 0;
for (auto const& tr: rlp[1])
for (auto const& tr: _block.transactions)
{
try {
LogOverride<ExecutiveWarnChannel> o(false);
execute(lh, Transaction(tr.data(), CheckTransaction::Everything));
execute(lh, tr);
}
catch (...)
{
badBlock(_block, "Invalid transaction");
badBlock(_block.block, "Invalid transaction");
cwarn << " Transaction Index:" << i;
LogOverride<ExecutiveWarnChannel> o(true);
execute(lh, Transaction(tr.data(), CheckTransaction::Everything));
execute(lh, tr);
throw;
}
@ -646,7 +642,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
auto receiptsRoot = orderedTrieRoot(receipts);
if (receiptsRoot != m_currentBlock.receiptsRoot)
{
badBlock(_block, "Bad receipts state root");
badBlock(_block.block, "Bad receipts state root");
cwarn << " Received: " << toString(m_currentBlock.receiptsRoot);
cwarn << " Expected: " << toString(receiptsRoot) << " which is:";
for (unsigned j = 0; j < i; ++j)
@ -657,13 +653,13 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
cwarn << " Hex: " << toHex(b);
cwarn << " " << TransactionReceipt(&b);
}
cwarn << " VMTrace:\n" << vmTrace(_block, _bc, _ir);
cwarn << " VMTrace:\n" << vmTrace(_block.block, _bc, _ir);
BOOST_THROW_EXCEPTION(InvalidReceiptsStateRoot());
}
if (m_currentBlock.logBloom != logBloom())
{
badBlock(_block, "Bad log bloom");
badBlock(_block.block, "Bad log bloom");
cwarn << " Receipt blooms:";
for (unsigned j = 0; j < i; ++j)
{
@ -680,7 +676,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
// Check uncles & apply their rewards to state.
if (rlp[2].itemCount() > 2)
{
badBlock(_block, "Too many uncles");
badBlock(_block.block, "Too many uncles");
BOOST_THROW_EXCEPTION(TooManyUncles());
}
@ -693,7 +689,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
auto h = sha3(i.data());
if (excluded.count(h))
{
badBlock(_block, "Invalid uncle included");
badBlock(_block.block, "Invalid uncle included");
BOOST_THROW_EXCEPTION(UncleInChain() << errinfo_comment("Uncle in block already mentioned") << errinfo_data(toString(excluded)) << errinfo_hash256(sha3(i.data())));
}
excluded.insert(h);
@ -702,7 +698,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
BlockInfo uncleParent(_bc.block(uncle.parentHash));
if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 7)
{
badBlock(_block, "Uncle too old");
badBlock(_block.block, "Uncle too old");
cwarn << " Uncle number: " << uncle.number;
cwarn << " Uncle parent number: " << uncleParent.number;
cwarn << " Block number: " << m_currentBlock.number;
@ -710,7 +706,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
}
else if (uncle.number == m_currentBlock.number)
{
badBlock(_block, "Uncle is brother");
badBlock(_block.block, "Uncle is brother");
cwarn << " Uncle number: " << uncle.number;
cwarn << " Uncle parent number: " << uncleParent.number;
cwarn << " Block number: " << m_currentBlock.number;
@ -730,12 +726,12 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
// Hash the state trie and check against the state_root hash in m_currentBlock.
if (m_currentBlock.stateRoot != m_previousBlock.stateRoot && m_currentBlock.stateRoot != rootHash())
{
badBlock(_block, "Bad state root");
badBlock(_block.block, "Bad state root");
cnote << " Given to be:" << m_currentBlock.stateRoot;
// TODO: Fix
// cnote << SecureTrieDB<Address, OverlayDB>(&m_db, m_currentBlock.stateRoot);
cnote << " Calculated to be:" << rootHash();
cwarn << " VMTrace:\n" << vmTrace(_block, _bc, _ir);
cwarn << " VMTrace:\n" << vmTrace(_block.block, _bc, _ir);
// cnote << m_state;
// Rollback the trie.
m_db.rollback();
@ -745,7 +741,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
if (m_currentBlock.gasUsed != gasUsed())
{
// Rollback the trie.
badBlock(_block, "Invalid gas used");
badBlock(_block.block, "Invalid gas used");
m_db.rollback();
BOOST_THROW_EXCEPTION(InvalidGasUsed() << RequirementError(bigint(gasUsed()), bigint(m_currentBlock.gasUsed)));
}
@ -823,7 +819,7 @@ bool State::amIJustParanoid(BlockChain const& _bc)
cnote << "PARANOIA root:" << s.rootHash();
// s.m_currentBlock.populate(&block.out(), false);
// s.m_currentBlock.verifyInternals(&block.out());
s.enact(&block.out(), _bc, false); // don't check nonce for this since we haven't mined it yet.
s.enact(BlockChain::verifyBlock(block.out()), _bc, false); // don't check nonce for this since we haven't mined it yet.
s.cleanup(false);
return true;
}
@ -1122,6 +1118,8 @@ h256 State::codeHash(Address _contract) const
{
if (!addressHasCode(_contract))
return EmptySHA3;
if (m_cache[_contract].isFreshCode())
return sha3(code(_contract));
return m_cache[_contract].codeHash();
}

5
libethereum/State.h

@ -48,6 +48,7 @@ namespace eth
class BlockChain;
class State;
struct VerifiedBlockRef;
struct StateChat: public LogChannel { static const char* name(); static const int verbosity = 4; };
struct StateTrace: public LogChannel { static const char* name(); static const int verbosity = 5; };
@ -308,7 +309,7 @@ public:
/// Execute all transactions within a given block.
/// @returns the additional total difficulty.
u256 enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const& _bc, ImportRequirements::value _ir = ImportRequirements::Default);
u256 enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportRequirements::value _ir = ImportRequirements::Default);
/// Returns back to a pristine state after having done a playback.
/// @arg _fullCommit if true flush everything out to disk. If false, this effectively only validates
@ -349,7 +350,7 @@ private:
/// Execute the given block, assuming it corresponds to m_currentBlock.
/// Throws on failure.
u256 enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirements::value _ir = ImportRequirements::Default);
u256 enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportRequirements::value _ir = ImportRequirements::Default);
/// Finalise the block, applying the earned rewards.
void applyRewards(std::vector<BlockInfo> const& _uncleBlockHeaders);

53
libethereum/VerifiedBlock.h

@ -0,0 +1,53 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file VerfiedBlock.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include <libdevcore/Common.h>
#include <libethcore/BlockInfo.h>
#pragma once
namespace dev
{
namespace eth
{
class Transaction;
/// @brief Verified block info, does not hold block data, but a reference instead
struct VerifiedBlockRef
{
bytesConstRef block; ///< Block data reference
BlockInfo info; ///< Prepopulated block info
std::vector<Transaction> transactions; ///< Verified list of block transactions
};
/// @brief Verified block info, combines block data and verified info/transactions
struct VerifiedBlock
{
VerifiedBlockRef verified; ///< Verified block structures
bytes blockData; ///< Block data
};
using VerifiedBlocks = std::vector<VerifiedBlock>;
}
}

3
libevm/ExtVMFace.cpp

@ -25,7 +25,7 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth):
ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, h256 const& _codeHash, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth):
myAddress(_myAddress),
caller(_caller),
origin(_origin),
@ -33,6 +33,7 @@ ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256
gasPrice(_gasPrice),
data(_data),
code(_code),
codeHash(_codeHash),
lastHashes(_lh),
previousBlock(_previousBlock),
currentBlock(_currentBlock),

3
libevm/ExtVMFace.h

@ -130,7 +130,7 @@ public:
ExtVMFace() = default;
/// Full constructor.
ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth);
ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, h256 const& _codeHash, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth);
virtual ~ExtVMFace() = default;
@ -186,6 +186,7 @@ public:
u256 gasPrice; ///< Price of gas (that we already paid).
bytesConstRef data; ///< Current input data.
bytes code; ///< Current code that is executing.
h256 codeHash; ///< SHA3 hash of the executing code
LastHashes lastHashes; ///< Most recent 256 blocks' hashes.
BlockInfo previousBlock; ///< The previous block's information. TODO: PoC-8: REMOVE
BlockInfo currentBlock; ///< The current block's information.

4
libp2p/RLPxFrameIO.h

@ -56,7 +56,7 @@ public:
bool isConnected() const { return m_socket.is_open(); }
void close() { try { boost::system::error_code ec; m_socket.shutdown(bi::tcp::socket::shutdown_both, ec); if (m_socket.is_open()) m_socket.close(); } catch (...){} }
bi::tcp::endpoint remoteEndpoint() { try { return m_socket.remote_endpoint(); } catch (...){ return bi::tcp::endpoint(); } }
bi::tcp::endpoint remoteEndpoint() { boost::system::error_code ec; return m_socket.remote_endpoint(ec); }
bi::tcp::socket& ref() { return m_socket; }
protected:
@ -130,4 +130,4 @@ private:
};
}
}
}

2
test/libevm/vm.cpp

@ -33,7 +33,7 @@ using namespace dev::eth;
using namespace dev::test;
FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth): /// TODO: XXX: remove the default argument & fix.
ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), _previousBlock, _currentBlock, test::lastHashes(_currentBlock.number), _depth) {}
ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), EmptySHA3, _previousBlock, _currentBlock, test::lastHashes(_currentBlock.number), _depth) {}
h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&)
{

Loading…
Cancel
Save