Browse Source

Avoid compiling neth/serpent on MSVC.

cl-refactor
Gav Wood 10 years ago
parent
commit
622367b274
  1. 8
      CMakeLists.txt
  2. 4
      alethzero/MainWin.cpp
  3. 3
      libethcore/Common.h
  4. 52
      libethereum/BlockChain.cpp
  5. 10
      libethereum/BlockChain.h
  6. 44
      libethereum/BlockQueue.cpp
  7. 3
      libethereum/BlockQueue.h
  8. 24
      libethereum/Client.cpp
  9. 12
      libethereum/EthereumHost.cpp
  10. 4
      libethereum/EthereumPeer.cpp

8
CMakeLists.txt

@ -190,7 +190,7 @@ else ()
set(SOLIDITY OFF) set(SOLIDITY OFF)
endif() endif()
if (SERPENT) if (SERPENT)
set(SERPENT ON) set(SERPENT ${DECENT_PLATFORM})
else () else ()
set(SERPENT OFF) set(SERPENT OFF)
endif() endif()
@ -216,7 +216,7 @@ else ()
set(ETHASHCL OFF) set(ETHASHCL OFF)
endif() endif()
if (NCURSES) if (NCURSES)
set(NCURSES ON) set(NCURSES ${DECENT_PLATFORM})
else () else ()
set(NCURSES OFF) set(NCURSES OFF)
endif () endif ()
@ -230,7 +230,7 @@ if (BUNDLE STREQUAL "minimal")
set(TOOLS ON) set(TOOLS ON)
set(TESTS OFF) set(TESTS OFF)
elseif (BUNDLE STREQUAL "full") elseif (BUNDLE STREQUAL "full")
set(SERPENT ON) set(SERPENT ${DECENT_PLATFORM})
set(SOLIDITY ON) set(SOLIDITY ON)
set(USENPM ON) set(USENPM ON)
set(GUI ON) set(GUI ON)
@ -239,7 +239,7 @@ elseif (BUNDLE STREQUAL "full")
set(TESTS ON) set(TESTS ON)
set(FATDB ON) set(FATDB ON)
elseif (BUNDLE STREQUAL "tests") elseif (BUNDLE STREQUAL "tests")
set(SERPENT ON) set(SERPENT ${DECENT_PLATFORM})
set(SOLIDITY ON) set(SOLIDITY ON)
set(USENPM OFF) set(USENPM OFF)
set(GUI OFF) set(GUI OFF)

4
alethzero/MainWin.cpp

@ -307,10 +307,10 @@ void Main::uninstallWatch(unsigned _w)
void Main::installWatches() void Main::installWatches()
{ {
installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){ onNewBlock(); });
installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){ onNewPending(); });
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); }); installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); });
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); }); installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); });
installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){ onNewPending(); });
installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){ onNewBlock(); });
} }
Address Main::getNameReg() const Address Main::getNameReg() const

3
libethcore/Common.h

@ -92,7 +92,8 @@ enum class ImportResult
FutureTime, FutureTime,
AlreadyInChain, AlreadyInChain,
AlreadyKnown, AlreadyKnown,
Malformed Malformed,
BadChain
}; };
} }

52
libethereum/BlockChain.cpp

@ -306,39 +306,49 @@ LastHashes BlockChain::lastHashes(unsigned _n) const
return m_lastLastHashes; return m_lastLastHashes;
} }
pair<h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max) tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max)
{ {
_bq.tick(*this); _bq.tick(*this);
vector<bytes> blocks; vector<bytes> blocks;
_bq.drain(blocks, _max); _bq.drain(blocks, _max);
h256s ret; h256s fresh;
h256s dead;
h256s badBlocks;
for (auto const& block: blocks) for (auto const& block: blocks)
{ {
try try
{ {
for (auto h: import(block, _stateDB)) auto r = import(block, _stateDB);
ret.push_back(h); bool isOld = true;
for (auto const& h: r.first)
if (h == r.second)
isOld = false;
else if (isOld)
dead.push_back(h);
else
fresh.push_back(h);
} }
catch (UnknownParent) catch (UnknownParent)
{ {
cwarn << "Unknown parent of block!!!" << BlockInfo::headerHash(block).abridged() << boost::current_exception_diagnostic_information(); cwarn << "ODD: Import queue contains block with unknown parent." << boost::current_exception_diagnostic_information();
_bq.import(&block, *this); // NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad.
badBlocks.push_back(BlockInfo::headerHash(block));
} }
catch (Exception const& _e) catch (Exception const& _e)
{ {
cwarn << "Unexpected exception!" << diagnostic_information(_e); cnote << "Exception while importing block. Someone (Jeff? That you?) seems to be giving us dodgy blocks!" << diagnostic_information(_e);
_bq.import(&block, *this); // NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad.
badBlocks.push_back(BlockInfo::headerHash(block));
} }
catch (...)
{}
} }
bool yetMore = _bq.doneDrain(); return make_tuple(fresh, dead, _bq.doneDrain(badBlocks));
return make_pair(ret, yetMore);
} }
h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force) noexcept pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force) noexcept
{ {
try try
{ {
@ -347,11 +357,11 @@ h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB,
catch (...) catch (...)
{ {
cwarn << "Unexpected exception! Could not import block!" << boost::current_exception_diagnostic_information(); cwarn << "Unexpected exception! Could not import block!" << boost::current_exception_diagnostic_information();
return h256s(); return make_pair(h256s(), h256());
} }
} }
h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force) pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
{ {
//@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.
@ -532,14 +542,14 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
); );
// cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children."; // cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children.";
h256s ret; h256s route;
h256 common;
// This might be the new best block... // This might be the new best block...
h256 last = currentHash(); h256 last = currentHash();
if (td > details(last).totalDifficulty) if (td > details(last).totalDifficulty)
{ {
h256 common;
unsigned commonIndex; unsigned commonIndex;
tie(ret, common, commonIndex) = treeRoute(last, newHash); tie(route, common, commonIndex) = treeRoute(last, newHash);
{ {
WriteGuard l(x_lastBlockHash); WriteGuard l(x_lastBlockHash);
m_lastBlockHash = newHash; m_lastBlockHash = newHash;
@ -554,7 +564,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
clearBlockBlooms(number(common) + 1, number(last) + 1); clearBlockBlooms(number(common) + 1, number(last) + 1);
// Go through ret backwards until hash != last.parent and update m_transactionAddresses, m_blockHashes // Go through ret backwards until hash != last.parent and update m_transactionAddresses, m_blockHashes
for (auto i = ret.rbegin(); i != ret.rend() && *i != common; ++i) for (auto i = route.rbegin(); i != route.rend() && *i != common; ++i)
{ {
auto b = block(*i); auto b = block(*i);
BlockInfo bi(b); BlockInfo bi(b);
@ -606,7 +616,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
m_extrasDB->Put(m_writeOptions, toSlice(h, ExtraTransactionAddress), (ldb::Slice)dev::ref(m_transactionAddresses[h].rlp())); m_extrasDB->Put(m_writeOptions, toSlice(h, ExtraTransactionAddress), (ldb::Slice)dev::ref(m_transactionAddresses[h].rlp()));
} }
clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret); clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(route);
noteCanonChanged(); noteCanonChanged();
StructuredLogger::chainNewHead( StructuredLogger::chainNewHead(
@ -631,7 +641,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
cnote << "checkBest:" << checkBest; cnote << "checkBest:" << checkBest;
#endif #endif
return ret; return make_pair(route, common);
} }
void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end) void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end)

10
libethereum/BlockChain.h

@ -100,15 +100,15 @@ public:
void process(); void process();
/// Sync the chain with any incoming blocks. All blocks should, if processed in order /// Sync the chain with any incoming blocks. All blocks should, if processed in order
std::pair<h256s, bool> sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max); std::tuple<h256s, h256s, bool> sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max);
/// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB. /// Attempt to import the given block directly into the CanonBlockChain and sync with the state 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.
h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force = false) noexcept; std::pair<h256s, h256> attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force = false) noexcept;
/// 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.
h256s import(bytes const& _block, OverlayDB const& _stateDB, bool _force = false); std::pair<h256s, h256> import(bytes const& _block, OverlayDB const& _stateDB, bool _force = false);
/// 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;
@ -178,6 +178,10 @@ public:
bytes transaction(h256 const& _blockHash, unsigned _i) const { bytes b = block(_blockHash); return RLP(b)[1][_i].data().toBytes(); } bytes transaction(h256 const& _blockHash, unsigned _i) const { bytes b = block(_blockHash); return RLP(b)[1][_i].data().toBytes(); }
bytes transaction(unsigned _i) const { return transaction(currentHash(), _i); } bytes transaction(unsigned _i) const { return transaction(currentHash(), _i); }
/// Get all transactions from a block.
std::vector<bytes> transactions(h256 const& _blockHash) const { bytes b = block(_blockHash); std::vector<bytes> ret; for (auto const& i: RLP(b)[1]) ret.push_back(i.data().toBytes()); return ret; }
std::vector<bytes> transactions() const { return transactions(currentHash()); }
/// Get a number for the given hash (or the most recent mined if none given). Thread-safe. /// Get a number for the given hash (or the most recent mined if none given). Thread-safe.
unsigned number(h256 const& _hash) const { return details(_hash).number; } unsigned number(h256 const& _hash) const { return details(_hash).number; }
unsigned number() const { return number(currentHash()); } unsigned number() const { return number(currentHash()); }

44
libethereum/BlockQueue.cpp

@ -38,7 +38,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
UpgradableGuard l(m_lock); UpgradableGuard l(m_lock);
if (m_readySet.count(h) || m_drainingSet.count(h) || m_unknownSet.count(h)) if (m_readySet.count(h) || m_drainingSet.count(h) || m_unknownSet.count(h) || m_knownBad.count(h))
{ {
// Already know about this one. // Already know about this one.
cblockq << "Already known."; cblockq << "Already known.";
@ -48,20 +48,17 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
// 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; BlockInfo bi;
#if ETH_CATCH
try try
#endif
{ {
// TODO: quick verify
bi.populate(_block); bi.populate(_block);
bi.verifyInternals(_block); bi.verifyInternals(_block);
} }
#if ETH_CATCH
catch (Exception const& _e) catch (Exception const& _e)
{ {
cwarn << "Ignoring malformed block: " << diagnostic_information(_e); cwarn << "Ignoring malformed block: " << diagnostic_information(_e);
return ImportResult::Malformed; return ImportResult::Malformed;
} }
#endif
// Check block doesn't already exist first! // Check block doesn't already exist first!
if (_bc.details(h)) if (_bc.details(h))
@ -82,7 +79,13 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
else else
{ {
// We now know it. // We now know it.
if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash)) if (m_knownBad.count(bi.parentHash))
{
m_knownBad.insert(bi.hash());
// bad parent; this is bad too, note it as such
return ImportResult::BadChain;
}
else if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash))
{ {
// We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on. // We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on.
cblockq << "OK - queued as unknown parent:" << bi.parentHash.abridged(); cblockq << "OK - queued as unknown parent:" << bi.parentHash.abridged();
@ -104,6 +107,35 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
} }
} }
namespace dev {
template <class T, class U> std::set<T>& operator+=(std::set<T>& _a, U const& _b)
{
for (auto const& i: _b)
_a.insert(i);
return _a;
} }
bool BlockQueue::doneDrain(h256s const& _bad)
{
WriteGuard l(m_lock);
m_drainingSet.clear();
if (_bad.size())
{
vector<bytes> old;
swap(m_ready, old);
for (auto& b: old)
{
BlockInfo bi(b);
if (m_knownBad.count(bi.parentHash))
m_knownBad.insert(bi.hash());
else
m_ready.push_back(std::move(b));
}
}
m_knownBad += _bad;
return !m_readySet.empty();
}
void BlockQueue::tick(BlockChain const& _bc) void BlockQueue::tick(BlockChain const& _bc)
{ {
unsigned t = time(0); unsigned t = time(0);

3
libethereum/BlockQueue.h

@ -58,7 +58,7 @@ public:
/// 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.
bool doneDrain() { WriteGuard l(m_lock); m_drainingSet.clear(); return !m_readySet.empty(); } bool doneDrain(h256s const& _knownBad = h256s());
/// Notify the queue that the chain has changed and a new block has attained 'ready' status (i.e. is in the chain). /// Notify the queue that the chain has changed and a new block has attained 'ready' status (i.e. is in the chain).
void noteReady(h256 _b) { WriteGuard l(m_lock); noteReadyWithoutWriteGuard(_b); } void noteReady(h256 _b) { WriteGuard l(m_lock); noteReadyWithoutWriteGuard(_b); }
@ -83,6 +83,7 @@ private:
std::set<h256> m_unknownSet; ///< Set of all blocks whose parents are not ready/in-chain. std::set<h256> m_unknownSet; ///< Set of all blocks whose parents are not ready/in-chain.
std::multimap<h256, std::pair<h256, bytes>> m_unknown; ///< For transactions that have an unknown parent; we map their parent hash to the block stuff, and insert once the block appears. std::multimap<h256, std::pair<h256, bytes>> m_unknown; ///< For transactions that have an unknown parent; we map their parent hash to the block stuff, and insert once the block appears.
std::multimap<unsigned, bytes> m_future; ///< Set of blocks that are not yet valid. std::multimap<unsigned, bytes> m_future; ///< Set of blocks that are not yet valid.
std::set<h256> m_knownBad; ///< Set of blocks that we know will never be valid.
}; };
} }

24
libethereum/Client.cpp

@ -453,6 +453,7 @@ void Client::doWork()
// TODO: enable a short-circuit option since we mined it. will need to get the end state from the miner. // TODO: enable a short-circuit option since we mined it. will need to get the end state from the miner.
auto lm = dynamic_cast<LocalMiner*>(&m); auto lm = dynamic_cast<LocalMiner*>(&m);
h256s hs; h256s hs;
h256 c;
if (false && lm && !m_verifyOwnBlocks) if (false && lm && !m_verifyOwnBlocks)
{ {
// TODO: implement // TODO: implement
@ -463,11 +464,12 @@ void Client::doWork()
{ {
cwork << "CHAIN <== postSTATE"; cwork << "CHAIN <== postSTATE";
WriteGuard l(x_stateDB); WriteGuard l(x_stateDB);
hs = m_bc.attemptImport(m.blockData(), m_stateDB); tie(hs, c) = m_bc.attemptImport(m.blockData(), m_stateDB);
} }
if (hs.size()) if (hs.size())
{ {
for (auto const& h: hs) for (auto const& h: hs)
if (h != c)
appendFromNewBlock(h, changeds); appendFromNewBlock(h, changeds);
changeds.insert(ChainChangedFilter); changeds.insert(ChainChangedFilter);
} }
@ -498,18 +500,28 @@ void Client::doWork()
cwork << "BQ ==> CHAIN ==> STATE"; cwork << "BQ ==> CHAIN ==> STATE";
OverlayDB db = m_stateDB; OverlayDB db = m_stateDB;
x_stateDB.unlock(); x_stateDB.unlock();
h256s newBlocks; h256s fresh;
h256s dead;
bool sgw; bool sgw;
tie(newBlocks, sgw) = m_bc.sync(m_bq, db, 100); // TODO: remove transactions from m_tq nicely rather than relying on out of date nonce later on. tie(fresh, dead, sgw) = m_bc.sync(m_bq, db, 100);
// TODO: remove transactions from m_tq nicely rather than relying on out of date nonce later on.
for (auto const& h: dead)
for (auto const& t: m_bc.transactions(h))
m_tq.import(t);
for (auto const& h: fresh)
for (auto const& th: m_bc.transactionHashes(h))
m_tq.drop(th);
stillGotWork = stillGotWork | sgw; stillGotWork = stillGotWork | sgw;
if (newBlocks.size()) if (fresh.size())
{ {
for (auto i: newBlocks) for (auto i: fresh)
appendFromNewBlock(i, changeds); appendFromNewBlock(i, changeds);
changeds.insert(ChainChangedFilter); changeds.insert(ChainChangedFilter);
} }
x_stateDB.lock(); x_stateDB.lock();
if (newBlocks.size()) if (fresh.size())
m_stateDB = db; m_stateDB = db;
cwork << "preSTATE <== CHAIN"; cwork << "preSTATE <== CHAIN";

12
libethereum/EthereumHost.cpp

@ -201,15 +201,21 @@ void EthereumHost::maintainBlocks(h256 _currentHash)
{ {
clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")";
for (auto j: peerSessions()) std::vector<std::shared_ptr<EthereumPeer>> dispersal;
for (auto const& j: peerSessions())
if (!j.first->cap<EthereumPeer>()->m_knownBlocks.count(_currentHash))
dispersal.push_back(j.first->cap<EthereumPeer>());
for (unsigned i = (dispersal.size() + 3) / 4; i--;)
{ {
auto p = j.first->cap<EthereumPeer>().get(); unsigned n = rand() % dispersal.size();
auto p = std::move(dispersal[n]);
dispersal.erase(dispersal.begin() + n);
RLPStream ts; RLPStream ts;
p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(), 1).append(m_chain.details().totalDifficulty); p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(), 1).append(m_chain.details().totalDifficulty);
Guard l(p->x_knownBlocks); Guard l(p->x_knownBlocks);
if (!p->m_knownBlocks.count(_currentHash))
p->sealAndSend(ts); p->sealAndSend(ts);
p->m_knownBlocks.clear(); p->m_knownBlocks.clear();
} }

4
libethereum/EthereumPeer.cpp

@ -451,6 +451,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
break; break;
case ImportResult::Malformed: case ImportResult::Malformed:
case ImportResult::BadChain:
disable("Malformed block received."); disable("Malformed block received.");
return true; return true;
@ -505,8 +506,9 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
break; break;
case ImportResult::Malformed: case ImportResult::Malformed:
case ImportResult::BadChain:
disable("Malformed block received."); disable("Malformed block received.");
break; return true;
case ImportResult::AlreadyInChain: case ImportResult::AlreadyInChain:
case ImportResult::AlreadyKnown: case ImportResult::AlreadyKnown:

Loading…
Cancel
Save