From fb876453cadbd1b6299fb0b6ebd0e01ed9ea7b34 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Thu, 2 Oct 2014 14:20:33 +0200 Subject: [PATCH] Restructured exceptions. Boost::exception is now used primarily. --- alethzero/MainWin.cpp | 22 ++++++++--- libdevcore/Common.h | 2 +- libdevcore/CommonData.cpp | 7 ++-- libdevcore/Exceptions.h | 41 +++++++------------ libdevcore/RLP.h | 14 +++---- libdevcrypto/FileSystem.cpp | 2 +- libdevcrypto/TrieDB.h | 12 +++--- libethcore/BlockInfo.cpp | 45 ++++++++------------- libethcore/Exceptions.h | 68 ++++++++++++++++---------------- libethereum/BlockChain.cpp | 21 +++++----- libethereum/BlockChain.h | 7 ++-- libethereum/BlockQueue.cpp | 2 +- libethereum/Client.cpp | 5 ++- libethereum/Executive.cpp | 14 +++---- libethereum/State.cpp | 51 ++++++++++++++---------- libethereum/Transaction.cpp | 10 +++-- libethereum/TransactionQueue.cpp | 4 +- libevm/VM.h | 18 ++++----- libevmface/Instruction.cpp | 2 + liblll/Assembly.cpp | 2 +- liblll/Assembly.h | 2 +- liblll/CodeFragment.h | 2 +- liblll/Compiler.cpp | 7 +++- liblll/Parser.cpp | 2 +- libp2p/Host.cpp | 23 ++++++++--- libp2p/Session.cpp | 2 +- libp2p/UPnP.cpp | 2 +- libserpent/util.cpp | 5 ++- libwebthree/WebThree.h | 14 +++---- neth/main.cpp | 4 +- sc/cmdline.cpp | 3 +- test/vm.cpp | 25 +++++++++--- 32 files changed, 243 insertions(+), 197 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index d454e7d7d..50a948400 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -597,7 +597,7 @@ void Main::on_importKeyFile_triggered() } } else - throw 0; + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("encseed type is not js::str_type") ); if (std::find(m_myKeys.begin(), m_myKeys.end(), k) == m_myKeys.end()) { m_myKeys.append(k); @@ -609,6 +609,9 @@ void Main::on_importKeyFile_triggered() } catch (...) { + cerr << "Unhandled exception!" << endl << + boost::current_exception_diagnostic_information(); + QMessageBox::warning(this, "Key File Invalid", "Could not find secret key definition. This is probably not an Ethereum key file."); } } @@ -821,10 +824,8 @@ static bool blockMatch(string const& _f, dev::eth::BlockDetails const& _b, h256 } catch (...) { - std::cerr << "Unhandled exception!" << std::endl << + cerr << "Unhandled exception!" << endl << boost::current_exception_diagnostic_information(); - // possible output would include: function name, __FILE__, __LINE__ (at throw) and all added information, - // such has the block header info added in BlockInfo.cpp line 101-102. } if (toHex(_h.ref()).find(_f) != string::npos) return true; @@ -1284,6 +1285,14 @@ void Main::on_contracts_currentItemChanged() { ui->contractInfo->appendHtml("Corrupted trie."); } + catch (dev::Exception &_e) + { + _e << dev::errinfo_comment("Could not get contract info."); + cerr << "Unhandled exception!" << endl << + boost::diagnostic_information(_e); + throw; + } + ui->contractInfo->moveCursor(QTextCursor::Start); } } @@ -1623,7 +1632,8 @@ void Main::on_debug_clicked() } catch (dev::Exception const& _e) { - statusBar()->showMessage("Error running transaction: " + QString::fromStdString(_e.description())); + statusBar()->showMessage("Error running transaction: " + QString::fromStdString(diagnostic_information(_e))); + // this output is aimed at developers, reconsider using _e.what for more user friendly output. } } @@ -1909,6 +1919,8 @@ void Main::updateDebugger() } catch (...) { + cerr << "Unhandled exception!" << endl << + boost::current_exception_diagnostic_information(); break; // probably hit data segment } } diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 132429010..332081ec8 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -39,7 +39,7 @@ #include #include "vector_ref.h" -// CryptoPP defines byte in the global namespace, so so must we. +// CryptoPP defines byte in the global namespace, so must we. using byte = uint8_t; // Quote a given token stream to turn it into a string. diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index 6e889a6b0..bfcbc5e2e 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -23,6 +23,7 @@ #include #include "Exceptions.h" +#include using namespace std; using namespace dev; @@ -67,7 +68,7 @@ int dev::fromHex(char _i) return _i - 'a' + 10; if (_i >= 'A' && _i <= 'F') return _i - 'A' + 10; - throw BadHexCharacter(); + BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i)); } bytes dev::fromHex(std::string const& _s) @@ -81,13 +82,13 @@ bytes dev::fromHex(std::string const& _s) { ret.push_back(fromHex(_s[s++])); } - catch (...){ ret.push_back(0); } + catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } for (unsigned i = s; i < _s.size(); i += 2) try { ret.push_back((byte)(fromHex(_s[i]) * 16 + fromHex(_s[i + 1]))); } - catch (...){ ret.push_back(0); } + catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } return ret; } diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h index c1d65badc..f7aee4227 100644 --- a/libdevcore/Exceptions.h +++ b/libdevcore/Exceptions.h @@ -30,30 +30,19 @@ namespace dev { - -class Exception: public std::exception -{ -public: - virtual std::string description() const { return typeid(*this).name(); } - virtual char const* what() const noexcept { return typeid(*this).name(); } -}; - -// As an exemplar case I only restructure BadRLP, if I would restrucutre everything the above Exception class -// can be replaced completely. - -struct BException: virtual boost::exception, virtual std::exception {}; - -// there is no need to derive from any other class then BException just to add more information. -// This can be done dynamically during runtime. - -struct BadRLP: virtual BException {}; - - -class BadHexCharacter: public Exception {}; -class RLPException: public BException {}; -class BadCast: public RLPException {}; -class NoNetworking: public Exception {}; -class NoUPnPDevice: public Exception {}; -class RootNotFound: public Exception {}; - +// base class for all exceptions +struct Exception: virtual std::exception, virtual boost::exception {}; + +struct BadHexCharacter: virtual Exception {}; +struct RLPException: virtual Exception {}; +struct BadCast: virtual RLPException {}; +struct BadRLP: virtual RLPException {}; +struct NoNetworking: virtual Exception {}; +struct NoUPnPDevice: virtual Exception {}; +struct RootNotFound: virtual Exception {}; +struct FileError: virtual Exception {}; + +// error information to be added to exceptions +typedef boost::error_info errinfo_invalidSymbol; +typedef boost::error_info errinfo_comment; } diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h index 35e1d1dcf..19145a464 100644 --- a/libdevcore/RLP.h +++ b/libdevcore/RLP.h @@ -100,11 +100,11 @@ public: /// @returns the number of items in the list, or zero if it isn't a list. unsigned itemCount() const { return isList() ? items() : 0; } - unsigned itemCountStrict() const { if (!isList()) throw BadCast(); return items(); } + unsigned itemCountStrict() const { if (!isList()) BOOST_THROW_EXCEPTION(BadCast()); return items(); } /// @returns the number of bytes in the data, or zero if it isn't data. unsigned size() const { return isData() ? length() : 0; } - unsigned sizeStrict() const { if (!isData()) throw BadCast(); return length(); } + unsigned sizeStrict() const { if (!isData()) BOOST_THROW_EXCEPTION(BadCast()); return length(); } /// Equality operators; does best-effort conversion and checks for equality. bool operator==(char const* _s) const { return isData() && toString() == _s; } @@ -175,7 +175,7 @@ public: /// Converts to string. @returns the empty string if not a string. std::string toString() const { if (!isData()) return std::string(); return payload().cropped(0, length()).toString(); } /// Converts to string. @throws BadCast if not a string. - std::string toStringStrict() const { if (!isData()) throw BadCast(); return payload().cropped(0, length()).toString(); } + std::string toStringStrict() const { if (!isData()) BOOST_THROW_EXCEPTION(BadCast()); return payload().cropped(0, length()).toString(); } template std::vector toVector() const @@ -222,7 +222,7 @@ public: std::array toArray() const { if (itemCount() != N || !isList()) - throw BadCast(); + BOOST_THROW_EXCEPTION(BadCast()); std::array ret; for (unsigned i = 0; i < N; ++i) { @@ -246,7 +246,7 @@ public: { if ((!isInt() && !(_flags & AllowNonCanon)) || isList() || isNull()) if (_flags & ThrowOnFail) - throw BadCast(); + BOOST_THROW_EXCEPTION(BadCast()); else return 0; else {} @@ -254,7 +254,7 @@ public: auto p = payload(); if (p.size() > intTraits<_T>::maxSize && (_flags & FailIfTooBig)) if (_flags & ThrowOnFail) - throw BadCast(); + BOOST_THROW_EXCEPTION(BadCast()); else return 0; else {} @@ -266,7 +266,7 @@ public: { if (!isData() || (length() > _N::size && (_flags & FailIfTooBig))) if (_flags & ThrowOnFail) - throw BadCast(); + BOOST_THROW_EXCEPTION(BadCast()); else return _N(); else{} diff --git a/libdevcrypto/FileSystem.cpp b/libdevcrypto/FileSystem.cpp index e161c3234..81b23e886 100644 --- a/libdevcrypto/FileSystem.cpp +++ b/libdevcrypto/FileSystem.cpp @@ -43,7 +43,7 @@ std::string dev::getDataDir() #ifndef _MSC_VER // todo? cwarn << "getDataDir(): SHGetSpecialFolderPathA() failed."; #endif - throw std::runtime_error("getDataDir() - SHGetSpecialFolderPathA() failed."); + BOOST_THROW_EXCEPTION(std::runtime_error("getDataDir() - SHGetSpecialFolderPathA() failed.")); } #else boost::filesystem::path dataDirPath; diff --git a/libdevcrypto/TrieDB.h b/libdevcrypto/TrieDB.h index 8ee6f3bca..576bb9607 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcrypto/TrieDB.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "MemoryDB.h" #include "OverlayDB.h" @@ -44,7 +45,7 @@ namespace eth struct TrieDBChannel: public LogChannel { static const char* name() { return "-T-"; } static const int verbosity = 6; }; #define tdebug clog(TrieDBChannel) -class InvalidTrie: public std::exception {}; +struct InvalidTrie: virtual dev::Exception {}; extern const h256 c_shaNull; /** @@ -81,7 +82,7 @@ public: /*std::cout << "Setting root to " << _root << " (patched to " << m_root << ")" << std::endl;*/ if (!node(m_root).size()) - throw RootNotFound(); + BOOST_THROW_EXCEPTION(RootNotFound()); } bool haveRoot(h256 _root, bool _enforceRefs = true) { return _root == h256() ? true : m_db->lookup(_root, _enforceRefs).size(); } @@ -109,7 +110,7 @@ public: else if (_r.isList()) descendList(_r, _keyMask, _wasExt, _out, _indent); else - throw InvalidTrie(); + BOOST_THROW_EXCEPTION(InvalidTrie()); } void descendList(RLP const& _r, std::set& _keyMask, bool _wasExt, std::ostream* _out, int _indent) const @@ -130,7 +131,7 @@ public: descendEntry(_r[i], _keyMask, false, _out, _indent + 1); } else - throw InvalidTrie(); + BOOST_THROW_EXCEPTION(InvalidTrie()); } std::set leftOvers(std::ostream* _out = nullptr) const @@ -153,6 +154,7 @@ public: } catch (...) { + cwarn << boost::current_exception_diagnostic_information(); return false; } } @@ -374,7 +376,7 @@ template void GenericTrieDB::iterator::next() cwarn << rlp; auto c = rlp.itemCount(); cwarn << c; - throw InvalidTrie(); + BOOST_THROW_EXCEPTION(InvalidTrie()); #else m_that = nullptr; return; diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 0ea2ff5f7..f6d5731b3 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -91,33 +91,22 @@ void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce) extraData = _header[field = 11].toBytes(); nonce = _header[field = 12].toHash(); } - catch (BException const& e) - { - // define error information to be added to the exception - typedef boost::error_info InvalidBlockHeaderFormat_field; - typedef boost::error_info InvalidBlockHeaderFormat_header_field_data; - - // instead of using a new exception type, we add information to the existing exception - e << InvalidBlockHeaderFormat_field(field); - e << InvalidBlockHeaderFormat_header_field_data(toHex(_header[field].data().toBytes())); - throw; - } - // this block would be replaced - catch (RLPException const&) + catch (Exception & _e) { - throw InvalidBlockHeaderFormat(field, _header[field].data()); + _e << errinfo_name("invalid block header format") << BadFieldError(field, toHex(_header[field].data().toBytes())); + throw; } // check it hashes according to proof of work or that it's the genesis block. if (_checkNonce && parentHash && !Dagger::verify(headerHashWithoutNonce(), nonce, difficulty)) - throw InvalidBlockNonce(headerHashWithoutNonce(), nonce, difficulty); + BOOST_THROW_EXCEPTION(InvalidBlockNonce(headerHashWithoutNonce(), nonce, difficulty)); if (gasUsed > gasLimit) - throw TooMuchGasUsed(); + BOOST_THROW_EXCEPTION(TooMuchGasUsed()); if (number && extraData.size() > 1024) - throw ExtraDataTooBig(); + BOOST_THROW_EXCEPTION(ExtraDataTooBig()); } void BlockInfo::populate(bytesConstRef _block, bool _checkNonce) @@ -126,13 +115,13 @@ void BlockInfo::populate(bytesConstRef _block, bool _checkNonce) RLP header = root[0]; if (!header.isList()) - throw InvalidBlockFormat(0, header.data()); + BOOST_THROW_EXCEPTION(InvalidBlockFormat(0,header.data())); populateFromHeader(header, _checkNonce); if (!root[1].isList()) - throw InvalidBlockFormat(1, root[1].data()); + BOOST_THROW_EXCEPTION(InvalidBlockFormat(1, root[1].data())); if (!root[2].isList()) - throw InvalidBlockFormat(2, root[2].data()); + BOOST_THROW_EXCEPTION(InvalidBlockFormat(2, root[2].data())); } void BlockInfo::verifyInternals(bytesConstRef _block) const @@ -154,13 +143,13 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const ++i; } if (transactionsRoot != t.root()) - throw InvalidTransactionsHash(t.root(), transactionsRoot); + BOOST_THROW_EXCEPTION(InvalidTransactionsHash(t.root(), transactionsRoot)); if (minGasPrice > mgp) - throw InvalidMinGasPrice(minGasPrice, mgp); + BOOST_THROW_EXCEPTION(InvalidMinGasPrice(minGasPrice, mgp)); if (sha3Uncles != sha3(root[2].data())) - throw InvalidUnclesHash(); + BOOST_THROW_EXCEPTION(InvalidUnclesHash()); } void BlockInfo::populateFromParent(BlockInfo const& _parent) @@ -193,22 +182,22 @@ void BlockInfo::verifyParent(BlockInfo const& _parent) const { // Check difficulty is correct given the two timestamps. if (difficulty != calculateDifficulty(_parent)) - throw InvalidDifficulty(); + BOOST_THROW_EXCEPTION(InvalidDifficulty()); if (gasLimit != calculateGasLimit(_parent)) - throw InvalidGasLimit(gasLimit, calculateGasLimit(_parent)); + BOOST_THROW_EXCEPTION(InvalidGasLimit(gasLimit, calculateGasLimit(_parent))); // Check timestamp is after previous timestamp. if (parentHash) { if (parentHash != _parent.hash) - throw InvalidParentHash(); + BOOST_THROW_EXCEPTION(InvalidParentHash()); if (timestamp < _parent.timestamp) - throw InvalidTimestamp(); + BOOST_THROW_EXCEPTION(InvalidTimestamp()); if (number != _parent.number + 1) - throw InvalidNumber(); + BOOST_THROW_EXCEPTION(InvalidNumber()); } } diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h index 8a15cd80f..6cf974e78 100644 --- a/libethcore/Exceptions.h +++ b/libethcore/Exceptions.h @@ -7,40 +7,42 @@ namespace dev namespace eth { -class DatabaseAlreadyOpen: public dev::Exception {}; +// information to add to exceptions +typedef boost::error_info errinfo_name; +typedef boost::error_info errinfo_field; +typedef boost::error_info errinfo_data; +typedef boost::tuple BadFieldError; -class NotEnoughCash: public dev::Exception {}; - -class GasPriceTooLow: public dev::Exception {}; -class BlockGasLimitReached: public dev::Exception {}; -class NoSuchContract: public dev::Exception {}; -class ContractAddressCollision: public dev::Exception {}; -class FeeTooSmall: public dev::Exception {}; -class TooMuchGasUsed: public dev::Exception {}; -class ExtraDataTooBig: public dev::Exception {}; -class InvalidSignature: public dev::Exception {}; -class InvalidTransactionFormat: public dev::Exception { public: InvalidTransactionFormat(int _f, bytesConstRef _d): m_f(_f), m_d(_d.toBytes()) {} int m_f; bytes m_d; virtual std::string description() const { return "Invalid transaction format: Bad field " + toString(m_f) + " (" + toHex(m_d) + ")"; } }; -class InvalidBlockFormat: public dev::Exception { public: InvalidBlockFormat(int _f, bytesConstRef _d): m_f(_f), m_d(_d.toBytes()) {} int m_f; bytes m_d; virtual std::string description() const { return "Invalid block format: Bad field " + toString(m_f) + " (" + toHex(m_d) + ")"; } }; -class InvalidBlockHeaderFormat: public dev::Exception { public: InvalidBlockHeaderFormat(int _f, bytesConstRef _d): m_f(_f), m_d(_d.toBytes()) {} int m_f; bytes m_d; virtual std::string description() const { return "Invalid block header format: Bad field " + toString(m_f) + " (" + toHex(m_d) + ")"; } }; -class InvalidUnclesHash: public dev::Exception {}; -class InvalidUncle: public dev::Exception {}; -class UncleTooOld: public dev::Exception {}; -class UncleInChain: public dev::Exception { public: UncleInChain(h256Set _uncles, h256 _block): m_uncles(_uncles), m_block(_block) {} h256Set m_uncles; h256 m_block; virtual std::string description() const { return "Uncle in block already mentioned: Uncles " + toString(m_uncles) + " (" + m_block.abridged() + ")"; } }; -class DuplicateUncleNonce: public dev::Exception {}; -class InvalidStateRoot: public dev::Exception {}; -class InvalidTransactionsHash: public dev::Exception { public: InvalidTransactionsHash(h256 _head, h256 _real): m_head(_head), m_real(_real) {} h256 m_head; h256 m_real; virtual std::string description() const { return "Invalid transactions hash: header says: " + toHex(m_head.ref()) + " block is:" + toHex(m_real.ref()); } }; -class InvalidTransaction: public dev::Exception {}; -class InvalidDifficulty: public dev::Exception {}; -class InvalidGasLimit: public dev::Exception { public: InvalidGasLimit(u256 _provided = 0, u256 _valid = 0): provided(_provided), valid(_valid) {} u256 provided; u256 valid; virtual std::string description() const { return "Invalid gas limit (provided: " + toString(provided) + " valid:" + toString(valid) + ")"; } }; -class InvalidMinGasPrice: public dev::Exception { public: InvalidMinGasPrice(u256 _provided = 0, u256 _limit = 0): provided(_provided), limit(_limit) {} u256 provided; u256 limit; virtual std::string description() const { return "Invalid minimum gas price (provided: " + toString(provided) + " limit:" + toString(limit) + ")"; } }; -class InvalidTransactionGasUsed: public dev::Exception {}; -class InvalidTransactionStateRoot: public dev::Exception {}; -class InvalidTimestamp: public dev::Exception {}; -class InvalidNonce: public dev::Exception { public: InvalidNonce(u256 _required = 0, u256 _candidate = 0): required(_required), candidate(_candidate) {} u256 required; u256 candidate; virtual std::string description() const { return "Invalid nonce (r: " + toString(required) + " c:" + toString(candidate) + ")"; } }; -class InvalidBlockNonce: public dev::Exception { public: InvalidBlockNonce(h256 _h = h256(), h256 _n = h256(), u256 _d = 0): h(_h), n(_n), d(_d) {} h256 h; h256 n; u256 d; virtual std::string description() const { return "Invalid nonce (h: " + toString(h) + " n:" + toString(n) + " d:" + toString(d) + ")"; } }; -class InvalidParentHash: public dev::Exception {}; -class InvalidNumber: public dev::Exception {}; -class InvalidContractAddress: public dev::Exception {}; +struct DatabaseAlreadyOpen: virtual dev::Exception {}; +struct NotEnoughCash: virtual dev::Exception {}; +struct GasPriceTooLow: virtual dev::Exception {}; +struct BlockGasLimitReached: virtual dev::Exception {}; +struct NoSuchContract: virtual dev::Exception {}; +struct ContractAddressCollision: virtual dev::Exception {}; +struct FeeTooSmall: virtual dev::Exception {}; +struct TooMuchGasUsed: virtual dev::Exception {}; +struct ExtraDataTooBig: virtual dev::Exception {}; +struct InvalidSignature: virtual dev::Exception {}; +class InvalidBlockFormat: public dev::Exception { public: InvalidBlockFormat(int _f, bytesConstRef _d): m_f(_f), m_d(_d.toBytes()) {} int m_f; bytes m_d; virtual const char* what() const noexcept { return ("Invalid block format: Bad field " + toString(m_f) + " (" + toHex(m_d) + ")").c_str(); } }; +struct InvalidUnclesHash: virtual dev::Exception {}; +struct InvalidUncle: virtual dev::Exception {}; +struct UncleTooOld: virtual dev::Exception {}; +class UncleInChain: public dev::Exception { public: UncleInChain(h256Set _uncles, h256 _block): m_uncles(_uncles), m_block(_block) {} h256Set m_uncles; h256 m_block;virtual const char* what() const noexcept { return ("Uncle in block already mentioned: Uncles " + toString(m_uncles) + " (" + m_block.abridged() + ")").c_str(); } }; +struct DuplicateUncleNonce: virtual dev::Exception {}; +struct InvalidStateRoot: virtual dev::Exception {}; +class InvalidTransactionsHash: public dev::Exception { public: InvalidTransactionsHash(h256 _head, h256 _real): m_head(_head), m_real(_real) {} h256 m_head; h256 m_real; virtual const char* what() const noexcept { return ("Invalid transactions hash: header says: " + toHex(m_head.ref()) + " block is:" + toHex(m_real.ref())).c_str(); } }; +struct InvalidTransaction: virtual dev::Exception {}; +struct InvalidDifficulty: virtual dev::Exception {}; +class InvalidGasLimit: public dev::Exception { public: InvalidGasLimit(u256 _provided = 0, u256 _valid = 0): provided(_provided), valid(_valid) {} u256 provided; u256 valid; virtual const char* what() const noexcept { return ("Invalid gas limit (provided: " + toString(provided) + " valid:" + toString(valid) + ")").c_str(); } }; +class InvalidMinGasPrice: public dev::Exception { public: InvalidMinGasPrice(u256 _provided = 0, u256 _limit = 0): provided(_provided), limit(_limit) {} u256 provided; u256 limit; virtual const char* what() const noexcept { return ("Invalid minimum gas price (provided: " + toString(provided) + " limit:" + toString(limit) + ")").c_str(); } }; +struct InvalidTransactionGasUsed: virtual dev::Exception {}; +struct InvalidTransactionStateRoot: virtual dev::Exception {}; +struct InvalidTimestamp: virtual dev::Exception {}; +class InvalidNonce: public dev::Exception { public: InvalidNonce(u256 _required = 0, u256 _candidate = 0): required(_required), candidate(_candidate) {} u256 required; u256 candidate; virtual const char* what() const noexcept { return ("Invalid nonce (r: " + toString(required) + " c:" + toString(candidate) + ")").c_str(); } }; +class InvalidBlockNonce: public dev::Exception { public: InvalidBlockNonce(h256 _h = h256(), h256 _n = h256(), u256 _d = 0): h(_h), n(_n), d(_d) {} h256 h; h256 n; u256 d; virtual const char* what() const noexcept { return ("Invalid nonce (h: " + toString(h) + " n:" + toString(n) + " d:" + toString(d) + ")").c_str(); } }; +struct InvalidParentHash: virtual dev::Exception {}; +struct InvalidNumber: virtual dev::Exception {}; +struct InvalidContractAddress: virtual dev::Exception {}; } } diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index f375adfcb..8e85deb88 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -137,9 +137,9 @@ void BlockChain::open(std::string _path, bool _killExisting) ldb::DB::Open(o, _path + "/blocks", &m_db); ldb::DB::Open(o, _path + "/details", &m_extrasDB); if (!m_db) - throw DatabaseAlreadyOpen(); + BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); if (!m_extrasDB) - throw DatabaseAlreadyOpen(); + BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); if (!details(m_genesisHash)) { @@ -211,12 +211,12 @@ h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max } catch (UnknownParent) { - cwarn << "Unknown parent of block!!!" << BlockInfo::headerHash(block).abridged(); + cwarn << "Unknown parent of block!!!" << BlockInfo::headerHash(block).abridged() << boost::current_exception_diagnostic_information(); _bq.import(&block, *this); } catch (Exception const& _e) { - cwarn << "Unexpected exception!" << _e.description(); + cwarn << "Unexpected exception!" << diagnostic_information(_e); _bq.import(&block, *this); } catch (...) @@ -234,6 +234,7 @@ h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB) } catch (...) { + cwarn << "Unexpected exception! Could not import block!" << boost::current_exception_diagnostic_information(); return h256s(); } } @@ -253,7 +254,8 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) #if ETH_CATCH catch (Exception const& _e) { - clog(BlockChainNote) << " Malformed block (" << _e.description() << ")."; + clog(BlockChainNote) << " Malformed block: " << diagnostic_information(_e); + _e << errinfo_comment("Malformed block "); throw; } #endif @@ -263,7 +265,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) if (isKnown(newHash)) { clog(BlockChainNote) << newHash << ": Not new."; - throw AlreadyHaveBlock(); + BOOST_THROW_EXCEPTION(AlreadyHaveBlock()); } // Work out its number as the parent's number + 1 @@ -271,7 +273,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) { clog(BlockChainNote) << newHash << ": Unknown parent " << bi.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. - throw UnknownParent(); + BOOST_THROW_EXCEPTION(UnknownParent()); } auto pd = details(bi.parentHash); @@ -286,7 +288,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) { clog(BlockChainNote) << newHash << ": Future time " << bi.timestamp << " (now at " << time(0) << ")"; // Block has a timestamp in the future. This is no good. - throw FutureTime(); + BOOST_THROW_EXCEPTION(FutureTime()); } clog(BlockChainNote) << "Attempting import of " << newHash.abridged() << "..."; @@ -342,7 +344,8 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) #if ETH_CATCH catch (Exception const& _e) { - clog(BlockChainNote) << " Malformed block (" << _e.description() << ")."; + clog(BlockChainNote) << " Malformed block: " << diagnostic_information(_e); + _e << errinfo_comment("Malformed block "); throw; } #endif diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index cf33a5104..b723ed38d 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -46,9 +47,9 @@ static const h256s NullH256s; class State; class OverlayDB; -class AlreadyHaveBlock: public std::exception {}; -class UnknownParent: public std::exception {}; -class FutureTime: public std::exception {}; +struct AlreadyHaveBlock: virtual Exception {}; +struct UnknownParent: virtual Exception {}; +struct FutureTime: virtual Exception {}; struct BlockChainChat: public LogChannel { static const char* name() { return "-B-"; } static const int verbosity = 7; }; struct BlockChainNote: public LogChannel { static const char* name() { return "=B="; } static const int verbosity = 4; }; diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index a845965d5..3477a692d 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -58,7 +58,7 @@ bool BlockQueue::import(bytesConstRef _block, BlockChain const& _bc) #if ETH_CATCH catch (Exception const& _e) { - cwarn << "Ignoring malformed block: " << _e.description(); + cwarn << "Ignoring malformed block: " << diagnostic_information(_e); return false; } #endif diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index de0077f89..a878f503e 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -47,7 +47,10 @@ void VersionChecker::setOk() { boost::filesystem::create_directory(m_path); } - catch (...) {} + catch (...) + { + cwarn << "Unhandled exception! Failed to create directory: " << m_path << "\n" << boost::current_exception_diagnostic_information(); + } writeFile(m_path + "/protocol", rlp(c_protocolVersion)); writeFile(m_path + "/database", rlp(c_databaseVersion)); } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index a6b57a05c..d9d373bb2 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -54,14 +54,14 @@ bool Executive::setup(bytesConstRef _rlp) if (m_t.nonce != nonceReq) { clog(StateChat) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce; - throw InvalidNonce(nonceReq, m_t.nonce); + BOOST_THROW_EXCEPTION(InvalidNonce(nonceReq, m_t.nonce)); } // Don't like transactions whose gas price is too low. NOTE: this won't stay here forever - it's just until we get a proper gas price discovery protocol going. if (m_t.gasPrice < m_s.m_currentBlock.minGasPrice) { clog(StateChat) << "Offered gas-price is too low: Require >" << m_s.m_currentBlock.minGasPrice << " Got" << m_t.gasPrice; - throw GasPriceTooLow(); + BOOST_THROW_EXCEPTION(GasPriceTooLow()); } // Check gas cost is enough. @@ -70,7 +70,7 @@ bool Executive::setup(bytesConstRef _rlp) if (m_t.gas < gasCost) { clog(StateChat) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas; - throw OutOfGas(); + BOOST_THROW_EXCEPTION(OutOfGas()); } u256 cost = m_t.value + m_t.gas * m_t.gasPrice; @@ -79,14 +79,14 @@ bool Executive::setup(bytesConstRef _rlp) if (m_s.balance(m_sender) < cost) { clog(StateChat) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender); - throw NotEnoughCash(); + BOOST_THROW_EXCEPTION(NotEnoughCash()); } u256 startGasUsed = m_s.gasUsed(); if (startGasUsed + m_t.gas > m_s.m_currentBlock.gasLimit) { clog(StateChat) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas; - throw BlockGasLimitReached(); + BOOST_THROW_EXCEPTION(BlockGasLimitReached()); } // Increment associated nonce for sender. @@ -186,12 +186,12 @@ bool Executive::go(OnOpFunc const& _onOp) } catch (VMException const& _e) { - clog(StateChat) << "VM Exception: " << _e.description(); + clog(StateChat) << "VM Exception: " << diagnostic_information(_e); m_endGas = m_vm->gas(); } catch (Exception const& _e) { - clog(StateChat) << "Exception in VM: " << _e.description(); + clog(StateChat) << "Exception in VM: " << diagnostic_information(_e); } catch (std::exception const& _e) { diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 8fa6141a5..7c7a40754 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -54,7 +54,7 @@ OverlayDB State::openDB(std::string _path, bool _killExisting) ldb::DB* db = nullptr; ldb::DB::Open(o, _path + "/state", &db); if (!db) - throw DatabaseAlreadyOpen(); + BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); cnote << "Opened state DB."; return OverlayDB(db); @@ -133,7 +133,7 @@ void State::paranoia(std::string const& _when, bool _enforceRefs) const if (!isTrieGood(_enforceRefs, false)) { cwarn << "BAD TRIE" << _when; - throw InvalidTrie(); + BOOST_THROW_EXCEPTION(InvalidTrie()); } #else (void)_when; @@ -334,7 +334,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi) { // TODO: Slightly nicer handling? :-) cerr << "ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl; - cerr << _e.description() << endl; + cerr << diagnostic_information(_e) << endl; } catch (std::exception const& _e) { @@ -386,6 +386,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi) { // TODO: Slightly nicer handling? :-) cerr << "ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl; + cerr << boost::current_exception_diagnostic_information() << endl; exit(1); } @@ -503,6 +504,14 @@ h256s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged) else _tq.setFuture(i); } + catch (Exception const& _e) + { + // Something else went wrong - drop it. + _tq.drop(i.first); + if (o_transactionQueueChanged) + *o_transactionQueueChanged = true; + cwarn << "Sync went wrong\n" << diagnostic_information(_e); + } catch (std::exception const&) { // Something else went wrong - drop it. @@ -527,7 +536,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) #endif if (m_currentBlock.parentHash != m_previousBlock.hash) - throw InvalidParentHash(); + BOOST_THROW_EXCEPTION(InvalidParentHash()); // Populate m_currentBlock with the correct values. m_currentBlock.populate(_block, _checkNonce); @@ -553,10 +562,10 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) cnote << m_state.root() << "\n" << m_state; cnote << *this; cnote << "INVALID: " << tr[1].toHash(); - throw InvalidTransactionStateRoot(); + BOOST_THROW_EXCEPTION(InvalidTransactionStateRoot()); } if (tr[2].toInt() != gasUsed()) - throw InvalidTransactionGasUsed(); + BOOST_THROW_EXCEPTION(InvalidTransactionGasUsed()); bytes k = rlp(i); transactionManifest.insert(&k, tr.data()); ++i; @@ -565,7 +574,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) if (m_currentBlock.transactionsRoot && transactionManifest.root() != m_currentBlock.transactionsRoot) { cwarn << "Bad transactions state root!"; - throw InvalidTransactionStateRoot(); + BOOST_THROW_EXCEPTION(InvalidTransactionStateRoot()); } // Initialise total difficulty calculation. @@ -578,16 +587,16 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) for (auto const& i: RLP(_block)[2]) { if (knownUncles.count(sha3(i.data()))) - throw UncleInChain(knownUncles, sha3(i.data())); + BOOST_THROW_EXCEPTION(UncleInChain(knownUncles, sha3(i.data()) )); BlockInfo uncle = BlockInfo::fromHeader(i.data()); if (nonces.count(uncle.nonce)) - throw DuplicateUncleNonce(); + BOOST_THROW_EXCEPTION(DuplicateUncleNonce()); if (_bc) { BlockInfo uncleParent(_bc->block(uncle.parentHash)); if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 6) - throw UncleTooOld(); + BOOST_THROW_EXCEPTION(UncleTooOld()); uncle.verifyParent(uncleParent); } @@ -611,7 +620,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) cnote << *this; // Rollback the trie. m_db.rollback(); - throw InvalidStateRoot(); + BOOST_THROW_EXCEPTION(InvalidStateRoot()); } return tdIncrease; @@ -677,13 +686,13 @@ bool State::amIJustParanoid(BlockChain const& _bc) s.cleanup(false); return true; } - catch (Exception const& e) + catch (Exception const& _e) { - cwarn << "Bad block: " << e.description(); + cwarn << "Bad block: " << diagnostic_information(_e); } - catch (std::exception const& e) + catch (std::exception const& _e) { - cwarn << "Bad block: " << e.what(); + cwarn << "Bad block: " << _e.what(); } return false; @@ -863,7 +872,7 @@ void State::subBalance(Address _id, bigint _amount) ensureCached(_id, false, false); auto it = m_cache.find(_id); if (it == m_cache.end() || (bigint)it->second.balance() < _amount) - throw NotEnoughCash(); + BOOST_THROW_EXCEPTION(NotEnoughCash()); else it->second.addBalance(-_amount); } @@ -1038,7 +1047,7 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) if (storageRoot(e.t().receiveAddress) && m_db.lookup(storageRoot(e.t().receiveAddress)).empty()) { cwarn << "TRIE immediately after execution; no node for receiveAddress"; - throw InvalidTrie(); + BOOST_THROW_EXCEPTION(InvalidTrie()); } } #endif @@ -1093,11 +1102,11 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA } catch (VMException const& _e) { - clog(StateChat) << "VM Exception: " << _e.description(); + clog(StateChat) << "VM Exception: " << diagnostic_information(_e); } catch (Exception const& _e) { - clog(StateChat) << "Exception in VM: " << _e.description(); + clog(StateChat) << "Exception in VM: " << diagnostic_information(_e); } catch (std::exception const& _e) { @@ -1160,11 +1169,11 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, } catch (VMException const& _e) { - clog(StateChat) << "VM Exception: " << _e.description(); + clog(StateChat) << "VM Exception: " << diagnostic_information(_e); } catch (Exception const& _e) { - clog(StateChat) << "Exception in VM: " << _e.description(); + clog(StateChat) << "Exception in VM: " << diagnostic_information(_e); } catch (std::exception const& _e) { diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index f607dc3b4..70dae3557 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -46,9 +46,10 @@ Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender) if (_checkSender) m_sender = sender(); } - catch (RLPException const&) + catch (Exception & _e) { - throw InvalidTransactionFormat(field, rlp[field].data()); + _e << errinfo_name("invalid transaction format") << BadFieldError(field,toHex(rlp[field].data().toBytes())); + throw; } } @@ -60,6 +61,7 @@ Address Transaction::safeSender() const noexcept } catch (...) { + cwarn << "safeSender() did throw an exception: " << boost::current_exception_diagnostic_information(); return Address(); } } @@ -76,7 +78,7 @@ Address Transaction::sender() const byte pubkey[65]; int pubkeylen = 65; if (!secp256k1_ecdsa_recover_compact(msg.data(), 32, sig[0].data(), pubkey, &pubkeylen, 0, (int)vrs.v - 27)) - throw InvalidSignature(); + BOOST_THROW_EXCEPTION(InvalidSignature()); // TODO: check right160 is correct and shouldn't be left160. m_sender = right160(dev::eth::sha3(bytesConstRef(&(pubkey[1]), 64))); @@ -103,7 +105,7 @@ void Transaction::sign(Secret _priv) h256 nonce = kFromMessage(msg, _priv); if (!secp256k1_ecdsa_sign_compact(msg.data(), 32, sig[0].data(), _priv.data(), nonce.data(), &v)) - throw InvalidSignature(); + BOOST_THROW_EXCEPTION(InvalidSignature()); #if ETH_ADDRESS_DEBUG cout << "---- SIGN -------------------------------" << endl; cout << "MSG: " << msg << endl; diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index f15cefc26..6248f38c9 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -49,9 +49,9 @@ bool TransactionQueue::import(bytesConstRef _transactionRLP) m_current[h] = _transactionRLP.toBytes(); m_known.insert(h); } - catch (InvalidTransactionFormat const& _e) + catch (Exception const& _e) { - cwarn << "Ignoring invalid transaction: " << _e.description(); + cwarn << "Ignoring invalid transaction: " << diagnostic_information(_e); return false; } catch (std::exception const& _e) diff --git a/libevm/VM.h b/libevm/VM.h index 3cac55b1f..04804ffd5 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -35,11 +35,11 @@ namespace dev namespace eth { -class VMException: public Exception {}; -class StepsDone: public VMException {}; -class BreakPointHit: public VMException {}; -class BadInstruction: public VMException {}; -class OutOfGas: public VMException {}; +struct VMException: virtual Exception {}; +struct StepsDone: virtual VMException {}; +struct BreakPointHit: virtual VMException {}; +struct BadInstruction: virtual VMException {}; +struct OutOfGas: virtual VMException {}; class StackTooSmall: public VMException { public: StackTooSmall(u256 _req, u256 _got): req(_req), got(_got) {} u256 req; u256 got; }; // Convert from a 256-bit integer stack/memory entry into a 160-bit Address hash. @@ -70,7 +70,7 @@ public: template bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); - void require(u256 _n) { if (m_stack.size() < _n) throw StackTooSmall(_n, m_stack.size()); } + void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall(_n, m_stack.size())); } void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } } u256 gas() const { return m_gas; } u256 curPC() const { return m_curPC; } @@ -208,7 +208,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con { // Out of gas! m_gas = 0; - throw OutOfGas(); + BOOST_THROW_EXCEPTION(OutOfGas()); } m_gas = (u256)((bigint)m_gas - runGas); @@ -686,11 +686,11 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con break; } default: - throw BadInstruction(); + BOOST_THROW_EXCEPTION(BadInstruction()); } } if (_steps == (uint64_t)-1) - throw StepsDone(); + BOOST_THROW_EXCEPTION(StepsDone()); return bytesConstRef(); } } diff --git a/libevmface/Instruction.cpp b/libevmface/Instruction.cpp index 7577c2aab..f8c7f5078 100644 --- a/libevmface/Instruction.cpp +++ b/libevmface/Instruction.cpp @@ -22,6 +22,7 @@ #include "Instruction.h" #include +#include using namespace std; using namespace dev; using namespace dev::eth; @@ -312,6 +313,7 @@ InstructionInfo dev::eth::instructionInfo(Instruction _inst) } catch (...) { + cwarn << "\n" << boost::current_exception_diagnostic_information(); return InstructionInfo({"", 0, 0, 0}); } } diff --git a/liblll/Assembly.cpp b/liblll/Assembly.cpp index 2250a71fe..9b6dee947 100644 --- a/liblll/Assembly.cpp +++ b/liblll/Assembly.cpp @@ -102,7 +102,7 @@ void Assembly::append(Assembly const& _a) void Assembly::append(Assembly const& _a, int _deposit) { if (_deposit > _a.m_deposit) - throw InvalidDeposit(); + BOOST_THROW_EXCEPTION(InvalidDeposit()); else { append(_a); diff --git a/liblll/Assembly.h b/liblll/Assembly.h index b8152fe02..b7feaf4f4 100644 --- a/liblll/Assembly.h +++ b/liblll/Assembly.h @@ -111,7 +111,7 @@ public: std::ostream& streamOut(std::ostream& _out, std::string const& _prefix = "") const; private: - void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) throw InvalidDeposit(); } + void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); } unsigned bytesRequired() const; unsigned m_usedTags = 0; diff --git a/liblll/CodeFragment.h b/liblll/CodeFragment.h index 60ab7c6de..d6ca86bbe 100644 --- a/liblll/CodeFragment.h +++ b/liblll/CodeFragment.h @@ -50,7 +50,7 @@ public: private: void finalise(CompilerState const& _cs); - template void error() const { throw T(); } + template void error() const { BOOST_THROW_EXCEPTION(T() ); } void constructOperation(sp::utree const& _t, CompilerState& _s); bool m_finalised = false; diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp index 389c10be2..37fb3c340 100644 --- a/liblll/Compiler.cpp +++ b/liblll/Compiler.cpp @@ -43,7 +43,10 @@ bytes dev::eth::compileLLL(string const& _src, bool _opt, vector* _error catch (Exception const& _e) { if (_errors) - _errors->push_back(_e.description()); + { + _errors->push_back("Parse error."); + _errors->push_back(diagnostic_information(_e)); + } } catch (std::exception) { @@ -67,7 +70,7 @@ std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::v catch (Exception const& _e) { if (_errors) - _errors->push_back(_e.description()); + _errors->push_back(diagnostic_information(_e)); } catch (std::exception) { diff --git a/liblll/Parser.cpp b/liblll/Parser.cpp index 52a05174b..e94e88e19 100644 --- a/liblll/Parser.cpp +++ b/liblll/Parser.cpp @@ -140,6 +140,6 @@ void dev::eth::parseTreeLLL(string const& _s, sp::utree& o_out) qi::phrase_parse(ret, s.cend(), element, space, qi::skip_flag::dont_postskip, o_out); for (auto i = ret; i != s.cend(); ++i) if (!isspace(*i)) - throw std::exception(); + BOOST_THROW_EXCEPTION(std::exception()); } diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 2517002ea..43758f0f5 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -96,7 +96,7 @@ void Host::start() { if (i) { - cwarn << "Couldn't start accepting connections on host. Something very wrong with network?"; + cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information(); return; } m_acceptor.close(); @@ -238,14 +238,14 @@ void Host::populateAddresses() #ifdef _WIN32 WSAData wsaData; if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) - throw NoNetworking(); + BOOST_THROW_EXCEPTION(NoNetworking()); char ac[80]; if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) { clog(NetWarn) << "Error " << WSAGetLastError() << " when getting local host name."; WSACleanup(); - throw NoNetworking(); + BOOST_THROW_EXCEPTION(NoNetworking()); } struct hostent* phe = gethostbyname(ac); @@ -253,7 +253,7 @@ void Host::populateAddresses() { clog(NetWarn) << "Bad host lookup."; WSACleanup(); - throw NoNetworking(); + BOOST_THROW_EXCEPTION(NoNetworking()); } for (int i = 0; phe->h_addr_list[i] != 0; ++i) @@ -273,7 +273,7 @@ void Host::populateAddresses() #else ifaddrs* ifaddr; if (getifaddrs(&ifaddr) == -1) - throw NoNetworking(); + BOOST_THROW_EXCEPTION(NoNetworking()); bi::tcp::resolver r(m_ioService); @@ -341,6 +341,7 @@ void Host::ensureAccepting() m_acceptor.async_accept(m_socket, [=](boost::system::error_code ec) { if (!ec) + { try { try { @@ -351,10 +352,15 @@ void Host::ensureAccepting() auto p = std::make_shared(this, std::move(m_socket), remoteAddress); p->start(); } + catch (Exception const& _e) + { + clog(NetWarn) << "ERROR: " << diagnostic_information(_e); + } catch (std::exception const& _e) { clog(NetWarn) << "ERROR: " << _e.what(); } + } m_accepting = false; if (ec.value() < 1) ensureAccepting(); @@ -372,6 +378,7 @@ string Host::pocHost() void Host::connect(std::string const& _addr, unsigned short _port) noexcept { for (int i = 0; i < 2; ++i) + { try { if (i == 0) @@ -383,11 +390,17 @@ void Host::connect(std::string const& _addr, unsigned short _port) noexcept connect(bi::tcp::endpoint(bi::address::from_string(_addr), _port)); break; } + catch (Exception const& _e) + { + // Couldn't connect + clog(NetConnect) << "Bad host " << _addr << "\n" << diagnostic_information(_e); + } catch (exception const& e) { // Couldn't connect clog(NetConnect) << "Bad host " << _addr << " (" << e.what() << ")"; } + } } void Host::connect(bi::tcp::endpoint const& _ep) diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index e449d03b7..9225a92f9 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -418,7 +418,7 @@ void Session::doRead() } catch (Exception const& _e) { - clogS(NetWarn) << "ERROR: " << _e.description(); + clogS(NetWarn) << "ERROR: " << diagnostic_information(_e); dropped(); } catch (std::exception const& _e) diff --git a/libp2p/UPnP.cpp b/libp2p/UPnP.cpp index 4fe01159a..5ac3e9427 100644 --- a/libp2p/UPnP.cpp +++ b/libp2p/UPnP.cpp @@ -87,7 +87,7 @@ UPnP::UPnP() #endif { cnote << "UPnP device not found."; - throw NoUPnPDevice(); + BOOST_THROW_EXCEPTION(NoUPnPDevice()); } } diff --git a/libserpent/util.cpp b/libserpent/util.cpp index 0f7570a18..dbd87ea2e 100644 --- a/libserpent/util.cpp +++ b/libserpent/util.cpp @@ -6,6 +6,7 @@ #include "bignum.h" #include #include +#include //Token or value node constructor Node token(std::string val, Metadata met) { @@ -211,7 +212,7 @@ std::string get_file_contents(std::string filename) in.close(); return(contents); } - throw(errno); + BOOST_THROW_EXCEPTION(dev::FileError() << boost::errinfo_file_name(filename) << boost::errinfo_errno(errno)); } //Report error @@ -220,7 +221,7 @@ void err(std::string errtext, Metadata met) { unsignedToDecimal(met.ln + 1) + ", char " + unsignedToDecimal(met.ch) + "): " + errtext; std::cerr << err << "\n"; - throw(err); + BOOST_THROW_EXCEPTION(dev::Exception() << dev::errinfo_comment(err)); } //Bin to hex diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index cae6fd6f8..44dbaaf57 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -38,7 +38,7 @@ namespace dev { -class InterfaceNotSupported: public Exception { public: InterfaceNotSupported(std::string _f): m_f(_f) {} virtual std::string description() const { return "Interface " + m_f + " not supported."; } private: std::string m_f; }; +class InterfaceNotSupported: public Exception { public: InterfaceNotSupported(std::string _f): m_f(_f) {} virtual const char* what() const noexcept { return ("Interface " + m_f + " not supported.").c_str(); } private: std::string m_f; }; enum WorkState { @@ -73,9 +73,9 @@ public: // The mainline interfaces: - eth::Client* ethereum() const { if (!m_ethereum) throw InterfaceNotSupported("eth"); return m_ethereum.get(); } - shh::WhisperHost* whisper() const { if (!m_whisper) throw InterfaceNotSupported("shh"); return m_whisper.get(); } - bzz::Interface* swarm() const { throw InterfaceNotSupported("bzz"); } + eth::Client* ethereum() const { if (!m_ethereum) BOOST_THROW_EXCEPTION(InterfaceNotSupported("eth")); return m_ethereum.get(); } + shh::WhisperHost* whisper() const { if (!m_whisper) BOOST_THROW_EXCEPTION(InterfaceNotSupported("shh")); return m_whisper.get(); } + bzz::Interface* swarm() const { BOOST_THROW_EXCEPTION(InterfaceNotSupported("bzz")); } // Misc stuff: @@ -183,9 +183,9 @@ public: // The mainline interfaces. - eth::Interface* ethereum() const { if (!m_ethereum) throw InterfaceNotSupported("eth"); return m_ethereum; } - shh::Interface* whisper() const { if (!m_whisper) throw InterfaceNotSupported("shh"); return m_whisper; } - bzz::Interface* swarm() const { throw InterfaceNotSupported("bzz"); } + eth::Interface* ethereum() const { if (!m_ethereum) BOOST_THROW_EXCEPTION(InterfaceNotSupported("eth")); return m_ethereum; } + shh::Interface* whisper() const { if (!m_whisper) BOOST_THROW_EXCEPTION(InterfaceNotSupported("shh")); return m_whisper; } + bzz::Interface* swarm() const { BOOST_THROW_EXCEPTION(InterfaceNotSupported("bzz")); } // Peer network stuff - forward through RPCSlave, probably with P2PNetworkSlave/Master classes like Whisper & Ethereum. diff --git a/neth/main.cpp b/neth/main.cpp index 0dc552e39..cac19727c 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -805,9 +805,9 @@ int main(int argc, char** argv) cnote << "Saved" << rechex << "to" << outFile; } - catch (dev::eth::InvalidTrie) + catch (dev::eth::InvalidTrie const& _e) { - cwarn << "Corrupted trie."; + cwarn << "Corrupted trie.\n" << diagnostic_information(_e); } } } diff --git a/sc/cmdline.cpp b/sc/cmdline.cpp index b7a15634a..cfa5f2db0 100644 --- a/sc/cmdline.cpp +++ b/sc/cmdline.cpp @@ -5,6 +5,7 @@ #include #include #include +#include int main(int argv, char** argc) { if (argv == 1) { @@ -28,7 +29,7 @@ int main(int argv, char** argc) { else { if (argv == 2) { std::cerr << "Not enough arguments for serpent cmdline\n"; - throw(0); + BOOST_THROW_EXCEPTION(dev::Exception() << dev::errinfo_comment("Not enough arguments for serpent cmdline")); } input = argc[2]; secondInput = argv == 3 ? "" : argc[3]; diff --git a/test/vm.cpp b/test/vm.cpp index f2f30e230..96eeb4d1b 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -435,9 +435,14 @@ void doTests(json_spirit::mValue& v, bool _fillin) { output = vm.go(fev).toBytes(); } - catch (std::exception const& e) + catch (Exception const& _e) { - cnote << "VM did throw an exception: " << e.what(); + cnote << "VM did throw an exception: " << diagnostic_information(_e); + //BOOST_ERROR("Failed VM Test with Exception: " << e.what()); + } + catch (std::exception const& _e) + { + cnote << "VM did throw an exception: " << _e.what(); //BOOST_ERROR("Failed VM Test with Exception: " << e.what()); } @@ -537,9 +542,13 @@ void executeTests(const string& _name) dev::test::doTests(v, true); writeFile("../../../tests/" + _name + ".json", asBytes(json_spirit::write_string(v, true))); } - catch (std::exception const& e) + catch (Exception const& _e) { - BOOST_ERROR("Failed VM Test with Exception: " << e.what()); + BOOST_ERROR("Failed VM Test with Exception: " << diagnostic_information(_e)); + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed VM Test with Exception: " << _e.what()); } #endif @@ -552,9 +561,13 @@ void executeTests(const string& _name) json_spirit::read_string(s, v); dev::test::doTests(v, false); } - catch (std::exception const& e) + catch (Exception const& _e) + { + BOOST_ERROR("Failed VM Test with Exception: " << diagnostic_information(_e)); + } + catch (std::exception const& _e) { - BOOST_ERROR("Failed VM Test with Exception: " << e.what()); + BOOST_ERROR("Failed VM Test with Exception: " << _e.what()); } }