Browse Source

Moved transaction verification to verifier thread

cl-refactor
arkpar 10 years ago
parent
commit
5eb685da7c
  1. 3
      alethzero/MainWin.cpp
  2. 2
      cmake/EthCompilerSettings.cmake
  3. 4
      libdevcrypto/CryptoPP.cpp
  4. 182
      libethereum/BlockChain.cpp
  5. 6
      libethereum/BlockChain.h
  6. 80
      libethereum/BlockQueue.cpp
  7. 7
      libethereum/BlockQueue.h
  8. 64
      libethereum/State.cpp
  9. 18
      libethereum/State.h
  10. 51
      libethereum/VerifiedBlock.h
  11. 2
      libp2p/RLPxFrameIO.h

3
alethzero/MainWin.cpp

@ -774,6 +774,7 @@ void Main::readSettings(bool _skipGeometry)
ui->usePrivate->setChecked(m_privateChain.size()); ui->usePrivate->setChecked(m_privateChain.size());
ui->verbosity->setValue(s.value("verbosity", 1).toInt()); ui->verbosity->setValue(s.value("verbosity", 1).toInt());
ui->jitvm->setChecked(s.value("jitvm", true).toBool()); 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 ui->urlEdit->setText(s.value("url", "about:blank").toString()); //http://gavwood.com/gavcoin.html
on_urlEdit_returnPressed(); on_urlEdit_returnPressed();
@ -1262,6 +1263,7 @@ void Main::refreshBlockChain()
if (oldSelected == hba) if (oldSelected == hba)
blockItem->setSelected(true); blockItem->setSelected(true);
/*
int n = 0; int n = 0;
try { try {
auto b = bc.block(h); auto b = bc.block(h);
@ -1290,6 +1292,7 @@ void Main::refreshBlockChain()
} }
} }
catch (...) {} catch (...) {}
*/
}; };
if (filters.empty()) if (filters.empty())

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_DEBUG "-O0 -g -DETH_DEBUG")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -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") if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++ -fcolor-diagnostics -Qunused-arguments -DBOOST_ASIO_HAS_CLANG_LIBCXX") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++ -fcolor-diagnostics -Qunused-arguments -DBOOST_ASIO_HAS_CLANG_LIBCXX")

4
libdevcrypto/CryptoPP.cpp

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

182
libethereum/BlockChain.cpp

@ -35,6 +35,7 @@
#include <libdevcore/StructuredLogger.h> #include <libdevcore/StructuredLogger.h>
#include <libdevcore/FileSystem.h> #include <libdevcore/FileSystem.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libethcore/EthashAux.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include <libethcore/Params.h> #include <libethcore/Params.h>
@ -42,6 +43,7 @@
#include "GenesisInfo.h" #include "GenesisInfo.h"
#include "State.h" #include "State.h"
#include "Defaults.h" #include "Defaults.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -261,7 +263,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
return; return;
} }
lastHash = bi.hash(); lastHash = bi.hash();
import(b, s.db(), 0); import(std::move(b), s.db(), 0);
} }
catch (...) catch (...)
{ {
@ -307,7 +309,7 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
{ {
// _bq.tick(*this); // _bq.tick(*this);
vector<pair<BlockInfo, bytes>> blocks; VerifiedBlocks blocks;
_bq.drain(blocks, _max); _bq.drain(blocks, _max);
h256s fresh; 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. // Nonce & uncle nonces already verified in verification thread at this point.
ImportRoute r; ImportRoute r;
DEV_TIMED_ABOVE(Block import, 500) 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; fresh += r.first;
dead += r.second; 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(); 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. // NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad. // Can't continue - chain bad.
badBlocks.push_back(block.first.hash()); badBlocks.push_back(block.verified.info.hash());
} }
catch (Exception const& _e) 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); 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. // NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad. // 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)); return make_tuple(fresh, dead, _bq.doneDrain(badBlocks));
@ -346,7 +348,7 @@ pair<ImportResult, ImportRoute> BlockChain::attemptImport(bytes const& _block, O
{ {
try try
{ {
return make_pair(ImportResult::Success, import(_block, _stateDB, _ir)); return make_pair(ImportResult::Success, import(verifyBlock(_block, _ir), _stateDB, _ir));
} }
catch (UnknownParent&) 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) ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, ImportRequirements::value _ir)
{ {
// VERIFY: populates from the block and checks the block is internally coherent. // VERIFY: populates from the block and checks the block is internally coherent.
BlockInfo bi; VerifiedBlockRef block;
#if ETH_CATCH #if ETH_CATCH
try try
#endif #endif
{ {
bi.populate(&_block); block = verifyBlock(_block, _ir);
bi.verifyInternals(&_block);
} }
#if ETH_CATCH #if ETH_CATCH
catch (Exception const& _e) catch (Exception const& _e)
@ -387,10 +388,10 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
} }
#endif #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. //@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 #endif
// Check block doesn't already exist first! // 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()); BOOST_THROW_EXCEPTION(AlreadyHaveBlock());
} }
// Work out its number as the parent's number + 1 // 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. // 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()); BOOST_THROW_EXCEPTION(UnknownParent());
} }
auto pd = details(_bi.parentHash); auto pd = details(_block.info.parentHash);
if (!pd) if (!pd)
{ {
auto pdata = pd.rlp(); auto pdata = pd.rlp();
clog(BlockChainDebug) << "Details is returning false despite block known:" << RLP(pdata); clog(BlockChainDebug) << "Details is returning false despite block known:" << RLP(pdata);
auto parentBlock = block(_bi.parentHash); auto parentBlock = block(_block.info.parentHash);
clog(BlockChainDebug) << "isKnown:" << isKnown(_bi.parentHash); clog(BlockChainDebug) << "isKnown:" << isKnown(_block.info.parentHash);
clog(BlockChainDebug) << "last/number:" << m_lastBlockNumber << m_lastBlockHash << _bi.number; clog(BlockChainDebug) << "last/number:" << m_lastBlockNumber << m_lastBlockHash << _block.info.number;
clog(BlockChainDebug) << "Block:" << BlockInfo(parentBlock); clog(BlockChainDebug) << "Block:" << BlockInfo(parentBlock);
clog(BlockChainDebug) << "RLP:" << RLP(parentBlock); clog(BlockChainDebug) << "RLP:" << RLP(parentBlock);
clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE"; 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 // 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. // Block has a timestamp in the future. This is no good.
BOOST_THROW_EXCEPTION(FutureTime()); BOOST_THROW_EXCEPTION(FutureTime());
} }
clog(BlockChainChat) << "Attempting import of " << _bi.hash() << "..."; clog(BlockChainChat) << "Attempting import of " << _block.info.hash() << "...";
#if ETH_TIMED_IMPORTS #if ETH_TIMED_IMPORTS
preliminaryChecks = t.elapsed(); 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. // 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. // Get total difficulty increase and update state, checking it.
State s(_db); State s(_db);
auto tdIncrease = s.enactOn(&_block, _bi, *this, _ir); auto tdIncrease = s.enactOn(_block, *this, _ir);
BlockLogBlooms blb; BlockLogBlooms blb;
BlockReceipts br; BlockReceipts br;
@ -497,22 +498,22 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
// together with an "ensureCachedWithUpdatableLock(l)" method. // together with an "ensureCachedWithUpdatableLock(l)" method.
// This is safe in practice since the caches don't get flushed nearly often enough to be // This is safe in practice since the caches don't get flushed nearly often enough to be
// done here. // done here.
details(_bi.parentHash); details(_block.info.parentHash);
DEV_WRITE_GUARDED(x_details) 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 #if ETH_TIMED_IMPORTS || !ETH_TRUE
collation = t.elapsed(); collation = t.elapsed();
t.restart(); t.restart();
#endif #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) 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(_block.info.hash(), ExtraDetails), (ldb::Slice)dev::ref(BlockDetails((unsigned)pd.number + 1, td, _block.info.parentHash, {}).rlp()));
extrasBatch.Put(toSlice(_bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(blb.rlp())); extrasBatch.Put(toSlice(_block.info.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(), ExtraReceipts), (ldb::Slice)dev::ref(br.rlp()));
#if ETH_TIMED_IMPORTS || !ETH_TRUE #if ETH_TIMED_IMPORTS || !ETH_TRUE
writing = t.elapsed(); writing = t.elapsed();
@ -530,20 +531,20 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
{ {
clog(BlockChainWarn) << " Malformed block: " << diagnostic_information(_e); clog(BlockChainWarn) << " Malformed block: " << diagnostic_information(_e);
_e << errinfo_comment("Malformed block "); _e << errinfo_comment("Malformed block ");
clog(BlockChainWarn) << "Block: " << _bi.hash(); clog(BlockChainWarn) << "Block: " << _block.info.hash();
clog(BlockChainWarn) << _bi; clog(BlockChainWarn) << _block.info;
clog(BlockChainWarn) << "Block parent: " << _bi.parentHash; clog(BlockChainWarn) << "Block parent: " << _block.info.parentHash;
clog(BlockChainWarn) << BlockInfo(block(_bi.parentHash)); clog(BlockChainWarn) << BlockInfo(block(_block.info.parentHash));
throw; throw;
} }
#endif #endif
StructuredLogger::chainReceivedNewBlock( StructuredLogger::chainReceivedNewBlock(
_bi.headerHash(WithoutNonce).abridged(), _block.info.headerHash(WithoutNonce).abridged(),
_bi.nonce.abridged(), _block.info.nonce.abridged(),
currentHash().abridged(), currentHash().abridged(),
"", // TODO: remote id ?? "", // TODO: remote id ??
_bi.parentHash.abridged() _block.info.parentHash.abridged()
); );
// cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children."; // 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... // don't include bi.hash() in treeRoute, since it's not yet in details DB...
// just tack it on afterwards. // just tack it on afterwards.
unsigned commonIndex; unsigned commonIndex;
tie(route, common, commonIndex) = treeRoute(last, _bi.parentHash); tie(route, common, commonIndex) = treeRoute(last, _block.info.parentHash);
route.push_back(_bi.hash()); 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 // Most of the time these two will be equal - only when we're doing a chain revert will they not be
if (common != last) 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) for (auto i = route.rbegin(); i != route.rend() && *i != common; ++i)
{ {
BlockInfo tbi; BlockInfo tbi;
if (*i == _bi.hash()) if (*i == _block.info.hash())
tbi = _bi; tbi = _block.info;
else else
tbi = BlockInfo(block(*i)); tbi = BlockInfo(block(*i));
@ -597,7 +598,7 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
h256s newTransactionAddresses; h256s newTransactionAddresses;
{ {
bytes blockBytes; bytes blockBytes;
RLP blockRLP(*i == _bi.hash() ? _block : (blockBytes = block(*i))); RLP blockRLP(*i == _block.info.hash() ? _block.block : &(blockBytes = block(*i)));
TransactionAddress ta; TransactionAddress ta;
ta.blockHash = tbi.hash(); ta.blockHash = tbi.hash();
for (ta.index = 0; ta.index < blockRLP[1].itemCount(); ++ta.index) 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. // FINALLY! change our best hash.
{ {
newLastBlockHash = _bi.hash(); newLastBlockHash = _block.info.hash();
newLastBlockNumber = (unsigned)_bi.number; 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( StructuredLogger::chainNewHead(
_bi.headerHash(WithoutNonce).abridged(), _block.info.headerHash(WithoutNonce).abridged(),
_bi.nonce.abridged(), _block.info.nonce.abridged(),
currentHash().abridged(), currentHash().abridged(),
_bi.parentHash.abridged() _block.info.parentHash.abridged()
); );
} }
else else
@ -634,24 +635,26 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
m_blocksDB->Write(m_writeOptions, &blocksBatch); m_blocksDB->Write(m_writeOptions, &blocksBatch);
m_extrasDB->Write(m_writeOptions, &extrasBatch); 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) << "Known block just inserted has no details.";
clog(BlockChainDebug) << "Block:" << _bi; clog(BlockChainDebug) << "Block:" << _block.info;
clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE"; clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE";
exit(-1); exit(-1);
} }
try { try {
State canary(_db, *this, _bi.hash(), ImportRequirements::DontHave); //State canary(_db, *this, _block.info.hash(), ImportRequirements::DontHave);
} }
catch (...) catch (...)
{ {
clog(BlockChainDebug) << "Failed to initialise State object form imported block."; 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"; clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE";
exit(-1); exit(-1);
} }
#endif
if (m_lastBlockHash != newLastBlockHash) if (m_lastBlockHash != newLastBlockHash)
DEV_WRITE_GUARDED(x_lastBlockHash) DEV_WRITE_GUARDED(x_lastBlockHash)
@ -1054,3 +1057,78 @@ bytes BlockChain::block(h256 const& _hash) const
return m_blocks[_hash]; 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 (InvalidNonce&)
{
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 "Account.h"
#include "Transaction.h" #include "Transaction.h"
#include "BlockQueue.h" #include "BlockQueue.h"
#include "VerifiedBlock.h"
namespace ldb = leveldb; namespace ldb = leveldb;
namespace std namespace std
@ -120,7 +121,7 @@ public:
/// Import block into disk-backed DB /// Import block into disk-backed DB
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain. /// @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(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). /// Returns true if the given block is known (though not necessarily a part of the canon chain).
bool isKnown(h256 const& _hash) const; bool isKnown(h256 const& _hash) const;
@ -256,6 +257,9 @@ public:
/// Deallocate unused data. /// Deallocate unused data.
void garbageCollect(bool _force = false); void garbageCollect(bool _force = false);
/// Verify block and prepare it for enactment
static VerifiedBlockRef verifyBlock(bytes const& _block, ImportRequirements::value _ir = ImportRequirements::Default);
private: private:
static h256 chunkId(unsigned _level, unsigned _index) { return h256(_index * 0xff + _level); } static h256 chunkId(unsigned _level, unsigned _index) { return h256(_index * 0xff + _level); }

80
libethereum/BlockQueue.cpp

@ -22,10 +22,11 @@
#include "BlockQueue.h" #include "BlockQueue.h"
#include <thread> #include <thread>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libethcore/EthashAux.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include "BlockChain.h" #include "BlockChain.h"
#include "VerifiedBlock.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -71,62 +72,13 @@ void BlockQueue::verifierBody()
m_unverified.pop_front(); m_unverified.pop_front();
BlockInfo bi; BlockInfo bi;
bi.mixHash = work.first; 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; VerifiedBlock res;
swap(work.second, res.second); swap(work.second, res.blockData);
try {
try { try {
res.first.populate(res.second, CheckEverything, work.first); res.verified = BlockChain::verifyBlock(res.blockData);
res.first.verifyInternals(&res.second);
}
catch (InvalidNonce&)
{
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;
}
}
} }
catch (...) catch (...)
{ {
@ -141,7 +93,7 @@ void BlockQueue::verifierBody()
unique_lock<Mutex> l(m_verification); unique_lock<Mutex> l(m_verification);
for (auto it = m_verifying.begin(); it != m_verifying.end(); ++it) 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); m_verifying.erase(it);
goto OK1; goto OK1;
@ -154,12 +106,12 @@ void BlockQueue::verifierBody()
bool ready = false; bool ready = false;
{ {
unique_lock<Mutex> l(m_verification); 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! // we're next!
m_verifying.pop_front(); m_verifying.pop_front();
m_verified.push_back(move(res)); 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_verified.push_back(move(m_verifying.front()));
m_verifying.pop_front(); m_verifying.pop_front();
@ -169,7 +121,7 @@ void BlockQueue::verifierBody()
else else
{ {
for (auto& i: m_verifying) for (auto& i: m_verifying)
if (i.first.mixHash == work.first) if (i.verified.info.mixHash == work.first)
{ {
i = move(res); i = move(res);
goto OK; goto OK;
@ -277,15 +229,15 @@ bool BlockQueue::doneDrain(h256s const& _bad)
m_drainingSet.clear(); m_drainingSet.clear();
if (_bad.size()) if (_bad.size())
{ {
vector<pair<BlockInfo, bytes>> old; vector<VerifiedBlock> old;
DEV_GUARDED(m_verification) DEV_GUARDED(m_verification)
swap(m_verified, old); swap(m_verified, old);
for (auto& b: 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_knownBad.insert(b.verified.info.hash());
m_readySet.erase(b.first.hash()); m_readySet.erase(b.verified.info.hash());
} }
else else
DEV_GUARDED(m_verification) DEV_GUARDED(m_verification)
@ -348,7 +300,7 @@ QueueStatus BlockQueue::blockStatus(h256 const& _h) const
QueueStatus::Unknown; 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); WriteGuard l(m_lock);
DEV_INVARIANT_CHECK; DEV_INVARIANT_CHECK;
@ -364,7 +316,7 @@ void BlockQueue::drain(std::vector<std::pair<BlockInfo, bytes>>& o_out, unsigned
for (auto const& bs: o_out) for (auto const& bs: o_out)
{ {
// TODO: @optimise use map<h256, bytes> rather than vector<bytes> & set<h256>. // 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_drainingSet.insert(h);
m_readySet.erase(h); m_readySet.erase(h);
} }

7
libethereum/BlockQueue.h

@ -39,6 +39,7 @@ namespace eth
{ {
class BlockChain; class BlockChain;
struct VerifiedBlock;
struct BlockQueueChannel: public LogChannel { static const char* name(); static const int verbosity = 4; }; struct BlockQueueChannel: public LogChannel { static const char* name(); static const int verbosity = 4; };
#define cblockq dev::LogOutputStream<dev::eth::BlockQueueChannel, true>() #define cblockq dev::LogOutputStream<dev::eth::BlockQueueChannel, true>()
@ -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. /// 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. /// 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. /// 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. /// @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. 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::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::vector<VerifiedBlock> 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::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::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. std::vector<std::thread> m_verifiers; ///< Threads who only verify.

64
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. // 2. Enact the block's transactions onto this state.
m_ourAddress = bi.coinbaseAddress; m_ourAddress = bi.coinbaseAddress;
enact(&b, _bc, _ir); enact(BlockChain::verifyBlock(b, _ir), _bc, _ir);
} }
else else
{ {
@ -382,7 +382,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi, Impor
return ret; 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 #if ETH_TIMED_ENACTMENTS
boost::timer t; boost::timer t;
@ -393,8 +393,8 @@ u256 State::enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const
#endif #endif
// Check family: // Check family:
BlockInfo biParent = _bc.info(_bi.parentHash); BlockInfo biParent = _bc.info(_block.info.parentHash);
_bi.verifyParent(biParent); _block.info.verifyParent(biParent);
#if ETH_TIMED_ENACTMENTS #if ETH_TIMED_ENACTMENTS
populateVerify = t.elapsed(); populateVerify = t.elapsed();
@ -410,7 +410,7 @@ u256 State::enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const
t.restart(); t.restart();
#endif #endif
sync(_bc, _bi.parentHash, BlockInfo(), _ir); sync(_bc, _block.info.parentHash, BlockInfo(), _ir);
resetCurrent(); resetCurrent();
#if ETH_TIMED_ENACTMENTS #if ETH_TIMED_ENACTMENTS
@ -596,29 +596,34 @@ template <class Channel>
class LogOverride class LogOverride
{ {
public: public:
LogOverride(bool _value): m_old(g_logOverride.count(&typeid(Channel)) ? (int)g_logOverride[&typeid(Channel)] : c_null) { g_logOverride[&typeid(Channel)] = _value; } LogOverride(bool _value):
m_old(g_logOverride.count(&typeid(Channel)) ? (int)g_logOverride[&typeid(Channel)] : c_null)
{
x_sync.lock();
g_logOverride[&typeid(Channel)] = _value;
}
~LogOverride() ~LogOverride()
{ {
if (m_old == c_null) if (m_old == c_null)
g_logOverride.erase(&typeid(Channel)); g_logOverride.erase(&typeid(Channel));
else else
g_logOverride[&typeid(Channel)] = (bool)m_old; g_logOverride[&typeid(Channel)] = (bool)m_old;
x_sync.unlock();
} }
private: private:
static const int c_null = -1; static const int c_null = -1;
int m_old; int m_old;
Mutex x_sync;
}; };
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. // m_currentBlock is assumed to be prepopulated and reset.
BlockInfo bi(_block, (_ir & ImportRequirements::ValidNonce) ? CheckEverything : IgnoreNonce);
#if !ETH_RELEASE #if !ETH_RELEASE
assert(m_previousBlock.hash() == bi.parentHash); assert(m_previousBlock.hash() == _block.info.parentHash);
assert(m_currentBlock.parentHash == bi.parentHash); assert(m_currentBlock.parentHash == _block.info.parentHash);
assert(rootHash() == m_previousBlock.stateRoot); assert(rootHash() == m_previousBlock.stateRoot);
#endif #endif
@ -626,32 +631,31 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
BOOST_THROW_EXCEPTION(InvalidParentHash()); BOOST_THROW_EXCEPTION(InvalidParentHash());
// Populate m_currentBlock with the correct values. // Populate m_currentBlock with the correct values.
m_currentBlock = bi; m_currentBlock = _block.info;
m_currentBlock.verifyInternals(_block);
m_currentBlock.noteDirty(); m_currentBlock.noteDirty();
// cnote << "playback begins:" << m_state.root(); // cnote << "playback begins:" << m_state.root();
// cnote << m_state; // cnote << m_state;
LastHashes lh = _bc.lastHashes((unsigned)m_previousBlock.number); LastHashes lh = _bc.lastHashes((unsigned)m_previousBlock.number);
RLP rlp(_block); RLP rlp(_block.block);
vector<bytes> receipts; vector<bytes> receipts;
// All ok with the block generally. Play back the transactions now... // All ok with the block generally. Play back the transactions now...
unsigned i = 0; unsigned i = 0;
for (auto const& tr: rlp[1]) for (auto const& tr: _block.transactions)
{ {
try { try {
LogOverride<ExecutiveWarnChannel> o(false); LogOverride<ExecutiveWarnChannel> o(false);
execute(lh, Transaction(tr.data(), CheckTransaction::Everything)); execute(lh, tr);
} }
catch (...) catch (...)
{ {
badBlock(_block, "Invalid transaction"); badBlock(_block.block, "Invalid transaction");
cwarn << " Transaction Index:" << i; cwarn << " Transaction Index:" << i;
LogOverride<ExecutiveWarnChannel> o(true); LogOverride<ExecutiveWarnChannel> o(true);
execute(lh, Transaction(tr.data(), CheckTransaction::Everything)); execute(lh, tr);
throw; throw;
} }
@ -664,7 +668,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
auto receiptsRoot = orderedTrieRoot(receipts); auto receiptsRoot = orderedTrieRoot(receipts);
if (receiptsRoot != m_currentBlock.receiptsRoot) 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 << " Received: " << toString(m_currentBlock.receiptsRoot);
cwarn << " Expected: " << toString(receiptsRoot) << " which is:"; cwarn << " Expected: " << toString(receiptsRoot) << " which is:";
for (unsigned j = 0; j < i; ++j) for (unsigned j = 0; j < i; ++j)
@ -675,13 +679,13 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
cwarn << " Hex: " << toHex(b); cwarn << " Hex: " << toHex(b);
cwarn << " " << TransactionReceipt(&b); cwarn << " " << TransactionReceipt(&b);
} }
cwarn << " VMTrace:\n" << vmTrace(_block, _bc, _ir); cwarn << " VMTrace:\n" << vmTrace(_block.block, _bc, _ir);
BOOST_THROW_EXCEPTION(InvalidReceiptsStateRoot()); BOOST_THROW_EXCEPTION(InvalidReceiptsStateRoot());
} }
if (m_currentBlock.logBloom != logBloom()) if (m_currentBlock.logBloom != logBloom())
{ {
badBlock(_block, "Bad log bloom"); badBlock(_block.block, "Bad log bloom");
cwarn << " Receipt blooms:"; cwarn << " Receipt blooms:";
for (unsigned j = 0; j < i; ++j) for (unsigned j = 0; j < i; ++j)
{ {
@ -698,7 +702,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
// Check uncles & apply their rewards to state. // Check uncles & apply their rewards to state.
if (rlp[2].itemCount() > 2) if (rlp[2].itemCount() > 2)
{ {
badBlock(_block, "Too many uncles"); badBlock(_block.block, "Too many uncles");
BOOST_THROW_EXCEPTION(TooManyUncles()); BOOST_THROW_EXCEPTION(TooManyUncles());
} }
@ -711,7 +715,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
auto h = sha3(i.data()); auto h = sha3(i.data());
if (excluded.count(h)) 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()))); BOOST_THROW_EXCEPTION(UncleInChain() << errinfo_comment("Uncle in block already mentioned") << errinfo_data(toString(excluded)) << errinfo_hash256(sha3(i.data())));
} }
excluded.insert(h); excluded.insert(h);
@ -720,7 +724,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
BlockInfo uncleParent(_bc.block(uncle.parentHash)); BlockInfo uncleParent(_bc.block(uncle.parentHash));
if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 7) 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 number: " << uncle.number;
cwarn << " Uncle parent number: " << uncleParent.number; cwarn << " Uncle parent number: " << uncleParent.number;
cwarn << " Block number: " << m_currentBlock.number; cwarn << " Block number: " << m_currentBlock.number;
@ -728,7 +732,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
} }
else if (uncle.number == m_currentBlock.number) 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 number: " << uncle.number;
cwarn << " Uncle parent number: " << uncleParent.number; cwarn << " Uncle parent number: " << uncleParent.number;
cwarn << " Block number: " << m_currentBlock.number; cwarn << " Block number: " << m_currentBlock.number;
@ -748,12 +752,12 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
// Hash the state trie and check against the state_root hash in m_currentBlock. // 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()) 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; cnote << " Given to be:" << m_currentBlock.stateRoot;
// TODO: Fix // TODO: Fix
// cnote << SecureTrieDB<Address, OverlayDB>(&m_db, m_currentBlock.stateRoot); // cnote << SecureTrieDB<Address, OverlayDB>(&m_db, m_currentBlock.stateRoot);
cnote << " Calculated to be:" << rootHash(); cnote << " Calculated to be:" << rootHash();
cwarn << " VMTrace:\n" << vmTrace(_block, _bc, _ir); cwarn << " VMTrace:\n" << vmTrace(_block.block, _bc, _ir);
// cnote << m_state; // cnote << m_state;
// Rollback the trie. // Rollback the trie.
m_db.rollback(); m_db.rollback();
@ -763,7 +767,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
if (m_currentBlock.gasUsed != gasUsed()) if (m_currentBlock.gasUsed != gasUsed())
{ {
// Rollback the trie. // Rollback the trie.
badBlock(_block, "Invalid gas used"); badBlock(_block.block, "Invalid gas used");
m_db.rollback(); m_db.rollback();
BOOST_THROW_EXCEPTION(InvalidGasUsed() << RequirementError(bigint(gasUsed()), bigint(m_currentBlock.gasUsed))); BOOST_THROW_EXCEPTION(InvalidGasUsed() << RequirementError(bigint(gasUsed()), bigint(m_currentBlock.gasUsed)));
} }
@ -841,7 +845,7 @@ bool State::amIJustParanoid(BlockChain const& _bc)
cnote << "PARANOIA root:" << s.rootHash(); cnote << "PARANOIA root:" << s.rootHash();
// s.m_currentBlock.populate(&block.out(), false); // s.m_currentBlock.populate(&block.out(), false);
// s.m_currentBlock.verifyInternals(&block.out()); // 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); s.cleanup(false);
return true; return true;
} }

18
libethereum/State.h

@ -48,6 +48,7 @@ namespace eth
class BlockChain; class BlockChain;
class State; class State;
struct VerifiedBlockRef;
struct StateChat: public LogChannel { static const char* name(); static const int verbosity = 4; }; 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; }; struct StateTrace: public LogChannel { static const char* name(); static const int verbosity = 5; };
@ -84,16 +85,9 @@ public:
class TrivialGasPricer: public GasPricer class TrivialGasPricer: public GasPricer
{ {
public: protected:
TrivialGasPricer() = default; u256 ask(State const&) const override { return 10 * szabo; }
TrivialGasPricer(u256 const& _ask, u256 const& _bid): m_ask(_ask), m_bid(_bid) {} u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return 10 * szabo; }
u256 ask(State const&) const override { return m_ask; }
u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return m_bid; }
private:
u256 m_ask = 10 * szabo;
u256 m_bid = 10 * szabo;
}; };
enum class Permanence enum class Permanence
@ -304,7 +298,7 @@ public:
/// Execute all transactions within a given block. /// Execute all transactions within a given block.
/// @returns the additional total difficulty. /// @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. /// 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 /// @arg _fullCommit if true flush everything out to disk. If false, this effectively only validates
@ -345,7 +339,7 @@ private:
/// Execute the given block, assuming it corresponds to m_currentBlock. /// Execute the given block, assuming it corresponds to m_currentBlock.
/// Throws on failure. /// 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. /// Finalise the block, applying the earned rewards.
void applyRewards(std::vector<BlockInfo> const& _uncleBlockHeaders); void applyRewards(std::vector<BlockInfo> const& _uncleBlockHeaders);

51
libethereum/VerifiedBlock.h

@ -0,0 +1,51 @@
/*
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;
struct VerifiedBlockRef
{
bytesConstRef block;
BlockInfo info;
std::vector<Transaction> transactions;
};
struct VerifiedBlock
{
VerifiedBlockRef verified;
bytes blockData;
};
using VerifiedBlocks = std::vector<VerifiedBlock>;
}
}

2
libp2p/RLPxFrameIO.h

@ -56,7 +56,7 @@ public:
bool isConnected() const { return m_socket.is_open(); } 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 (...){} } 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; } bi::tcp::socket& ref() { return m_socket; }
protected: protected:

Loading…
Cancel
Save