diff --git a/libdevcore/TrieDB.h b/libdevcore/TrieDB.h index 55ca81023..beb12fe0c 100644 --- a/libdevcore/TrieDB.h +++ b/libdevcore/TrieDB.h @@ -158,8 +158,6 @@ public: iterator lower_bound(bytesConstRef _key) const { return iterator(this, _key); } - void debugPrint() {} - /// Used for debugging, scans the whole trie. void descendKey(h256 const& _k, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent = 0) const { @@ -332,6 +330,7 @@ public: void insert(KeyType _k, bytesConstRef _value) { Generic::insert(bytesConstRef((byte const*)&_k, sizeof(KeyType)), _value); } void insert(KeyType _k, bytes const& _value) { insert(_k, bytesConstRef(&_value)); } void remove(KeyType _k) { Generic::remove(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } + void debugStructure(std::ostream& _out) const { Generic::debugStructure(_out); } class iterator: public Generic::iterator { @@ -386,6 +385,7 @@ public: using Super::leftOvers; using Super::check; + using Super::debugStructure; std::string at(bytesConstRef _key) const { return Super::at(sha3(_key)); } bool contains(bytesConstRef _key) { return Super::contains(sha3(_key)); } diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h index 0ac9df5b2..8715507ba 100644 --- a/libethcore/Exceptions.h +++ b/libethcore/Exceptions.h @@ -71,6 +71,7 @@ DEV_SIMPLE_EXCEPTION(InvalidBlockHeaderItemCount); DEV_SIMPLE_EXCEPTION(InvalidBlockNonce); DEV_SIMPLE_EXCEPTION(InvalidParentHash); DEV_SIMPLE_EXCEPTION(InvalidNumber); +DEV_SIMPLE_EXCEPTION(BlockNotFound); DEV_SIMPLE_EXCEPTION(DatabaseAlreadyOpen); DEV_SIMPLE_EXCEPTION(DAGCreationFailure); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 2295904cc..574cf2efb 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -38,6 +38,8 @@ #include "Executive.h" #include "EthereumHost.h" #include "Utility.h" +#include "TransactionQueue.h" + using namespace std; using namespace dev; using namespace dev::eth; @@ -459,20 +461,8 @@ uint64_t Client::hashrate() const std::list Client::miningHistory() { - std::list ret; -/* ReadGuard l(x_localMiners); - if (m_localMiners.empty()) - return ret; - ret = m_localMiners[0].miningHistory(); - for (unsigned i = 1; i < m_localMiners.size(); ++i) - { - auto l = m_localMiners[i].miningHistory(); - auto ri = ret.begin(); - auto li = l.begin(); - for (; ri != ret.end() && li != l.end(); ++ri, ++li) - ri->combine(*li); - }*/ - return ret; + //TODO: reimplement for CPU/GPU miner + return std::list {}; } ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice, Address const& _from) @@ -481,7 +471,7 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 try { State temp; -// clog(ClientTrace) << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); + clog(ClientDetail) << "Nonce at " << _dest << " pre:" << m_preMine.transactionsFrom(_dest) << " post:" << m_postMine.transactionsFrom(_dest); DEV_READ_GUARDED(x_postMine) temp = m_postMine; temp.addBalance(_from, _value + _gasPrice * _gas); @@ -493,7 +483,7 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 } catch (...) { - // TODO: Some sort of notification of failure. + cwarn << "Client::call failed: " << boost::current_exception_diagnostic_information(); } return ret; } diff --git a/libethereum/Client.h b/libethereum/Client.h index d433ecb6d..398bf64a4 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -40,7 +40,6 @@ #include #include #include "CanonBlockChain.h" -#include "TransactionQueue.h" #include "State.h" #include "CommonNet.h" #include "ClientBase.h" diff --git a/libethereum/State.cpp b/libethereum/State.cpp index fac587557..cfe468daa 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -72,8 +72,8 @@ OverlayDB State::openDB(std::string const& _basePath, WithExisting _we) o.max_open_files = 256; o.create_if_missing = true; ldb::DB* db = nullptr; - ldb::DB::Open(o, path + "/state", &db); - if (!db) + ldb::Status status = ldb::DB::Open(o, path + "/state", &db); + if (!status.ok() || !db) { if (boost::filesystem::space(path + "/state").available < 1024) { @@ -82,6 +82,7 @@ OverlayDB State::openDB(std::string const& _basePath, WithExisting _we) } else { + cwarn << status.ToString(); cwarn << "Database already open. You appear to have another instance of ethereum running. Bailing."; BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); } @@ -129,7 +130,7 @@ PopulationStatistics State::populateFromChain(BlockChain const& _bc, h256 const& { // Might be worth throwing here. cwarn << "Invalid block given for state population: " << _h; - return ret; + BOOST_THROW_EXCEPTION(BlockNotFound() << errinfo_target(_h)); } auto b = _bc.block(_h); @@ -244,9 +245,6 @@ StateDiff State::diff(State const& _c, bool _quick) const for (auto const& i: _c.m_cache) ads.insert(i.first); -// cnote << *this; -// cnote << _c; - for (auto const& i: ads) { auto it = m_cache.find(i); @@ -305,14 +303,14 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi, Impor bool ret = false; // BLOCK BlockInfo bi = _bi ? _bi : _bc.info(_block); -/* if (!bi) +#if ETH_PARANOIA + if (!bi) while (1) { try { auto b = _bc.block(_block); bi.populate(b); -// bi.verifyInternals(_bc.block(_block)); // Unneeded - we already verify on import into the blockchain. break; } catch (Exception const& _e) @@ -327,7 +325,8 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi, Impor cerr << "ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl; cerr << _e.what() << endl; } - }*/ + } +#endif if (bi == m_currentBlock) { // We mined the last block. @@ -352,7 +351,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi, Impor cwarn << "Unable to sync to" << bi.hash() << "; state root" << bi.stateRoot << "not found in database."; cwarn << "Database corrupt: contains block without stateRoot:" << bi; cwarn << "Bailing."; - exit(-1); + BOOST_THROW_EXCEPTION(InvalidStateRoot() << errinfo_target(bi.stateRoot)); } m_previousBlock = bi; resetCurrent(); @@ -477,7 +476,6 @@ void State::resetCurrent() m_currentBlock.sha3Uncles = h256(); m_currentBlock.populateFromParent(m_previousBlock); - // Update timestamp according to clock. // TODO: check. m_lastTx = m_db; @@ -557,7 +555,6 @@ pair State::sync(BlockChain const& _bc, TransactionQu // Temporarily no gas left in current block. // OPTIMISE: could note this and then we don't evaluate until a block that does have the gas left. // for now, just leave alone. -// _tq.setFuture(t.sha3()); } } catch (Exception const& _e) @@ -782,7 +779,8 @@ void State::cleanup(bool _fullCommit) if (isChannelVisible()) // Avoid calling toHex if not needed clog(StateTrace) << "Committing to disk: stateRoot" << m_currentBlock.stateRoot << "=" << rootHash() << "=" << toHex(asBytes(m_db.lookup(rootHash()))); - try { + try + { EnforceRefs er(m_db, true); rootHash(); } @@ -835,12 +833,6 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData) { uncommitToMine(); -// cnote << "Committing to mine on block" << m_previousBlock.hash; -#if ETH_PARANOIA && 0 - commit(); - cnote << "Pre-reward stateRoot:" << m_state.root(); -#endif - m_lastTx = m_db; vector uncleBlockHeaders; @@ -850,7 +842,7 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData) if (m_previousBlock.number != 0) { // Find great-uncles (or second-cousins or whatever they are) - children of great-grandparents, great-great-grandparents... that were not already uncles in previous generations. -// cout << "Checking " << m_previousBlock.hash << ", parent=" << m_previousBlock.parentHash << endl; + clog(StateDetail) << "Checking " << m_previousBlock.hash() << ", parent=" << m_previousBlock.parentHash; h256Hash excluded = _bc.allKinFrom(m_currentBlock.parentHash, 6); auto p = m_previousBlock.parentHash; for (unsigned gen = 0; gen < 6 && p != _bc.genesisHash() && unclesCount < 2; ++gen, p = _bc.details(p).parent) @@ -907,9 +899,9 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData) // Commit any and all changes to the trie that are in the cache, then update the state root accordingly. commit(); -// cnote << "Post-reward stateRoot:" << m_state.root(); -// cnote << m_state; -// cnote << *this; + clog(StateDetail) << "Post-reward stateRoot:" << m_state.root(); + clog(StateDetail) << m_state; + clog(StateDetail) << *this; m_currentBlock.gasUsed = gasUsed(); m_currentBlock.stateRoot = m_state.root(); @@ -923,7 +915,7 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData) void State::completeMine() { - cdebug << "Completing mine!"; + clog(StateDetail) << "Completing mine!"; // Got it! // Compile block: @@ -1086,6 +1078,17 @@ unordered_map State::storage(Address const& _id) const return ret; } +h256 State::storageRoot(Address const& _id) const +{ + string s = m_state.at(_id); + if (s.size()) + { + RLP r(s); + return r[2].toHash(); + } + return EmptyTrie; +} + bytes const& State::code(Address const& _contract) const { if (!addressHasCode(_contract)) @@ -1115,7 +1118,7 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const cwarn << "LEFTOVERS" << (e ? "[enforced" : "[unenforced") << "refs]"; cnote << "Left:" << lo; cnote << "Keys:" << m_db.keys(); -// m_state.debugStructure(cerr); + m_state.debugStructure(cerr); return false; } // TODO: Enable once fixed. @@ -1132,14 +1135,12 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const { cwarn << "BAD TRIE" << (e ? "[enforced" : "[unenforced") << "refs]"; cnote << m_db.keys(); -// m_state.debugStructure(cerr); + m_state.debugStructure(cerr); return false; } return true; } -#define ETH_VMTIMER 1 - ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Permanence _p, OnOpFunc const& _onOp) { #if ETH_PARANOIA