diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 447dfad0a..c72f5a045 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -297,7 +297,9 @@ public: { if (m_shouldListDevices) { +#if ETH_ETHASHCL || !ETH_TRUE EthashGPUMiner::listDevices(); +#endif exit(0); } diff --git a/libdevcore/TrieDB.h b/libdevcore/TrieDB.h index 05affa677..91d68ebd3 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 { @@ -390,6 +388,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)); } @@ -440,6 +439,7 @@ public: using Super::open; using Super::setRoot; using Super::db; + 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/BlockChain.cpp b/libethereum/BlockChain.cpp index bf2c1cc7c..9037f32e0 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -731,8 +731,10 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const& exit(-1); } - try { - State canary(_db, *this, _block.info.hash(), ImportRequirements::DontHave); + try + { + State canary(_db, BaseState::Empty); + canary.populateFromChain(*this, _block.info.hash(), ImportRequirements::DontHave); } catch (...) { diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index f99bcea83..16e5ba318 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -40,6 +40,8 @@ #include "Executive.h" #include "EthereumHost.h" #include "Utility.h" +#include "TransactionQueue.h" + using namespace std; using namespace dev; using namespace dev::eth; @@ -462,20 +464,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) @@ -484,7 +474,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); @@ -496,7 +486,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 8ea28ec1e..9839c5617 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 95bb0febb..665074788 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -73,8 +73,8 @@ OverlayDB State::openDB(std::string const& _basePath, h256 const& _genesisHash, 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) { @@ -83,6 +83,7 @@ OverlayDB State::openDB(std::string const& _basePath, h256 const& _genesisHash, } else { + cwarn << status.ToString(); cwarn << "Database already open. You appear to have another instance of ethereum running. Bailing."; BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); } @@ -119,7 +120,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); @@ -203,10 +204,6 @@ State& State::operator=(State const& _s) return *this; } -State::~State() -{ -} - StateDiff State::diff(State const& _c, bool _quick) const { StateDiff ret; @@ -237,9 +234,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); @@ -254,12 +248,12 @@ StateDiff State::diff(State const& _c, bool _quick) const return ret; } -void State::ensureCached(Address _a, bool _requireCode, bool _forceCreate) const +void State::ensureCached(Address const& _a, bool _requireCode, bool _forceCreate) const { ensureCached(m_cache, _a, _requireCode, _forceCreate); } -void State::ensureCached(std::unordered_map& _cache, Address _a, bool _requireCode, bool _forceCreate) const +void State::ensureCached(std::unordered_map& _cache, const Address& _a, bool _requireCode, bool _forceCreate) const { auto it = _cache.find(_a); if (it == _cache.end()) @@ -297,14 +291,14 @@ bool State::sync(BlockChain const& _bc, h256 const& _block, BlockInfo const& _bi 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) @@ -319,7 +313,8 @@ bool State::sync(BlockChain const& _bc, h256 const& _block, BlockInfo const& _bi 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. @@ -344,7 +339,7 @@ bool State::sync(BlockChain const& _bc, h256 const& _block, BlockInfo const& _bi cwarn << "Unable to sync to" << bi.hash() << "; state root" << bi.stateRoot() << "not found in database."; cwarn << "Database corrupt: contains block without stateRoot:" << bi; cwarn << "Try rescuing the database by running: eth --rescue"; - exit(-1); + BOOST_THROW_EXCEPTION(InvalidStateRoot() << errinfo_target(bi.stateRoot())); } m_previousBlock = bi; resetCurrent(); @@ -467,7 +462,6 @@ void State::resetCurrent() m_currentBlock.setTimestamp(max(m_previousBlock.timestamp() + 1, (u256)time(0))); m_currentBlock.populateFromParent(m_previousBlock); - // Update timestamp according to clock. // TODO: check. m_lastTx = m_db; @@ -547,7 +541,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) @@ -773,7 +766,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(); } @@ -814,45 +808,6 @@ void State::uncommitToMine() } } -bool State::amIJustParanoid(BlockChain const& _bc) -{ - (void)_bc; - /* - commitToMine(_bc); - - // Update difficulty according to timestamp. - m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); - - // Compile block: - RLPStream block; - block.appendList(3); - m_currentBlock.streamRLP(block, WithProof); - block.appendRaw(m_currentTxs); - block.appendRaw(m_currentUncles); - - State s(*this); - s.resetCurrent(); - try - { - cnote << "PARANOIA root:" << s.rootHash(); -// s.m_currentBlock.populate(&block.out(), false); -// s.m_currentBlock.verifyInternals(&block.out()); - s.enact(BlockChain::verifyBlock(block.out(), std::function(), ImportRequirements::CheckUncles | ImportRequirements::CheckTransactions), _bc); // don't check nonce for this since we haven't mined it yet. - s.cleanup(false); - return true; - } - catch (Exception const& _e) - { - cwarn << "Bad block: " << diagnostic_information(_e); - } - catch (std::exception const& _e) - { - cwarn << "Bad block: " << _e.what(); - } -*/ - return false; -} - LogBloom State::logBloom() const { LogBloom ret; @@ -865,12 +820,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; @@ -880,7 +829,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) @@ -931,9 +880,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.setLogBloom(logBloom()); m_currentBlock.setGasUsed(gasUsed()); @@ -956,7 +905,7 @@ bool State::sealBlock(bytesConstRef _header) if (!m_committedToMine) return false; - cdebug << "Sealing block!"; + clog(StateDetail) << "Sealing block!"; // Got it! // Compile block: @@ -986,7 +935,7 @@ bool State::sealBlock(bytesConstRef _header) return true; } -bool State::addressInUse(Address _id) const +bool State::addressInUse(Address const& _id) const { ensureCached(_id, false, false); auto it = m_cache.find(_id); @@ -995,7 +944,7 @@ bool State::addressInUse(Address _id) const return true; } -bool State::addressHasCode(Address _id) const +bool State::addressHasCode(Address const& _id) const { ensureCached(_id, false, false); auto it = m_cache.find(_id); @@ -1004,7 +953,7 @@ bool State::addressHasCode(Address _id) const return it->second.isFreshCode() || it->second.codeHash() != EmptySHA3; } -u256 State::balance(Address _id) const +u256 State::balance(Address const& _id) const { ensureCached(_id, false, false); auto it = m_cache.find(_id); @@ -1013,7 +962,7 @@ u256 State::balance(Address _id) const return it->second.balance(); } -void State::noteSending(Address _id) +void State::noteSending(Address const& _id) { ensureCached(_id, false, false); auto it = m_cache.find(_id); @@ -1027,7 +976,7 @@ void State::noteSending(Address _id) it->second.incNonce(); } -void State::addBalance(Address _id, u256 _amount) +void State::addBalance(Address const& _id, u256 const& _amount) { ensureCached(_id, false, false); auto it = m_cache.find(_id); @@ -1037,7 +986,7 @@ void State::addBalance(Address _id, u256 _amount) it->second.addBalance(_amount); } -void State::subBalance(Address _id, bigint _amount) +void State::subBalance(Address const& _id, bigint const& _amount) { ensureCached(_id, false, false); auto it = m_cache.find(_id); @@ -1047,7 +996,7 @@ void State::subBalance(Address _id, bigint _amount) it->second.addBalance(-_amount); } -Address State::newContract(u256 _balance, bytes const& _code) +Address State::newContract(u256 const& _balance, bytes const& _code) { auto h = sha3(_code); m_db.insert(h, &_code); @@ -1064,7 +1013,7 @@ Address State::newContract(u256 _balance, bytes const& _code) } } -u256 State::transactionsFrom(Address _id) const +u256 State::transactionsFrom(Address const& _id) const { ensureCached(_id, false, false); auto it = m_cache.find(_id); @@ -1074,7 +1023,7 @@ u256 State::transactionsFrom(Address _id) const return it->second.nonce(); } -u256 State::storage(Address _id, u256 _memory) const +u256 State::storage(Address const& _id, u256 const& _memory) const { ensureCached(_id, false, false); auto it = m_cache.find(_id); @@ -1096,7 +1045,7 @@ u256 State::storage(Address _id, u256 _memory) const return ret; } -unordered_map State::storage(Address _id) const +unordered_map State::storage(Address const& _id) const { unordered_map ret; @@ -1122,7 +1071,7 @@ unordered_map State::storage(Address _id) const return ret; } -h256 State::storageRoot(Address _id) const +h256 State::storageRoot(Address const& _id) const { string s = m_state.at(_id); if (s.size()) @@ -1133,7 +1082,7 @@ h256 State::storageRoot(Address _id) const return EmptyTrie; } -bytes const& State::code(Address _contract) const +bytes const& State::code(Address const& _contract) const { if (!addressHasCode(_contract)) return NullBytes; @@ -1141,7 +1090,7 @@ bytes const& State::code(Address _contract) const return m_cache[_contract].code(); } -h256 State::codeHash(Address _contract) const +h256 State::codeHash(Address const& _contract) const { if (!addressHasCode(_contract)) return EmptySHA3; @@ -1162,7 +1111,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. @@ -1179,14 +1128,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 diff --git a/libethereum/State.h b/libethereum/State.h index e2bda6f24..a5d3764af 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -121,8 +121,6 @@ public: /// Copy state object. State& operator=(State const& _s); - ~State(); - /// Construct state object from arbitrary point in blockchain. PopulationStatistics populateFromChain(BlockChain const& _bc, h256 const& _hash, ImportRequirements::value _ir = ImportRequirements::None); @@ -144,11 +142,6 @@ public: /// Get the header information on the present block. BlockInfo const& info() const { return m_currentBlock; } - /// @brief Checks that mining the current object will result in a valid block. - /// Effectively attempts to import the serialised block. - /// @returns true if all is ok. If it's false, worry. - bool amIJustParanoid(BlockChain const& _bc); - /// Prepares the current state for mining. /// Commits all transactions into the trie, compiles uncles and transactions list, applies all /// rewards and populates the current block header with the appropriate hashes. @@ -157,9 +150,6 @@ public: /// This may be called multiple times and without issue. void commitToMine(BlockChain const& _bc, bytes const& _extraData = {}); - /// @returns true iff commitToMine() has been called without any subsequest transactions added &c. - bool isCommittedToMine() const { return m_committedToMine; } - /// Pass in a solution to the proof-of-work. /// @returns true iff we were previously committed to mining. /// TODO: verify it prior to calling this. @@ -193,24 +183,24 @@ public: u256 gasLimitRemaining() const { return m_currentBlock.gasLimit() - gasUsed(); } /// Check if the address is in use. - bool addressInUse(Address _address) const; + bool addressInUse(Address const& _address) const; /// Check if the address contains executable code. - bool addressHasCode(Address _address) const; + bool addressHasCode(Address const& _address) const; /// Get an account's balance. /// @returns 0 if the address has never been used. - u256 balance(Address _id) const; + u256 balance(Address const& _id) const; /// Add some amount to balance. /// Will initialise the address if it has never been used. - void addBalance(Address _id, u256 _amount); + void addBalance(Address const& _id, u256 const& _amount); /** Subtract some amount from balance. * @throws NotEnoughCash if balance of @a _id is less than @a _value (or has never been used). * @note We use bigint here as we don't want any accidental problems with negative numbers. */ - void subBalance(Address _id, bigint _value); + void subBalance(Address const& _id, bigint const& _value); /** * @brief Transfers "the balance @a _value between two accounts. @@ -218,40 +208,40 @@ public: * @param _to Account to which @a _value will be added. * @param _value Amount to be transferred. */ - void transferBalance(Address _from, Address _to, u256 _value) { subBalance(_from, _value); addBalance(_to, _value); } + void transferBalance(Address const& _from, Address const& _to, u256 const& _value) { subBalance(_from, _value); addBalance(_to, _value); } /// Get the root of the storage of an account. - h256 storageRoot(Address _contract) const; + h256 storageRoot(Address const& _contract) const; /// Get the value of a storage position of an account. /// @returns 0 if no account exists at that address. - u256 storage(Address _contract, u256 _memory) const; + u256 storage(Address const& _contract, u256 const& _memory) const; /// Set the value of a storage position of an account. - void setStorage(Address _contract, u256 _location, u256 _value) { m_cache[_contract].setStorage(_location, _value); } + void setStorage(Address const& _contract, u256 const& _location, u256 const& _value) { m_cache[_contract].setStorage(_location, _value); } /// Create a new contract. - Address newContract(u256 _balance, bytes const& _code); + Address newContract(u256 const& _balance, bytes const& _code); /// Get the storage of an account. /// @note This is expensive. Don't use it unless you need to. /// @returns std::unordered_map if no account exists at that address. - std::unordered_map storage(Address _contract) const; + std::unordered_map storage(Address const& _contract) const; /// Get the code of an account. /// @returns bytes() if no account exists at that address. - bytes const& code(Address _contract) const; + bytes const& code(Address const& _contract) const; /// Get the code hash of an account. /// @returns EmptySHA3 if no account exists at that address or if there is no code associated with the address. - h256 codeHash(Address _contract) const; + h256 codeHash(Address const& _contract) const; /// Note that the given address is sending a transaction and thus increment the associated ticker. - void noteSending(Address _id); + void noteSending(Address const& _id); /// Get the number of transactions a particular address has sent (used for the transaction nonce). /// @returns 0 if the address has never been used. - u256 transactionsFrom(Address _address) const; + u256 transactionsFrom(Address const& _address) const; /// The hash of the root of our state tree. h256 rootHash() const { return m_state.root(); } @@ -317,10 +307,10 @@ private: /// If _requireMemory is true, grab the full memory should it be a contract item. /// If _forceCreate is true, then insert a default item into the cache, in the case it doesn't /// exist in the DB. - void ensureCached(Address _a, bool _requireCode, bool _forceCreate) const; + void ensureCached(Address const& _a, bool _requireCode, bool _forceCreate) const; /// Retrieve all information about a given address into a cache. - void ensureCached(std::unordered_map& _cache, Address _a, bool _requireCode, bool _forceCreate) const; + void ensureCached(std::unordered_map& _cache, Address const& _a, bool _requireCode, bool _forceCreate) const; /// Execute the given block, assuming it corresponds to m_currentBlock. /// Throws on failure.