From 82afcff98264b9c7c0bf59bd3c607a5cb5b7c305 Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Wed, 16 Oct 2019 22:24:11 -0700 Subject: [PATCH 01/17] Improve database error logging --- libethcore/Exceptions.h | 2 ++ libethereum/BlockChain.cpp | 73 +++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h index 6f5d4905a41..1b4c6b45783 100644 --- a/libethcore/Exceptions.h +++ b/libethcore/Exceptions.h @@ -74,6 +74,8 @@ DEV_SIMPLE_EXCEPTION(UnknownError); DEV_SIMPLE_EXCEPTION(InvalidDatabaseKind); DEV_SIMPLE_EXCEPTION(DatabaseAlreadyOpen); +DEV_SIMPLE_EXCEPTION(DatabaseCorruption); + DEV_SIMPLE_EXCEPTION(DAGCreationFailure); DEV_SIMPLE_EXCEPTION(DAGComputeFailure); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 03f66263004..5d78bda7e82 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -194,9 +194,15 @@ void BlockChain::init(ChainParams const& _p) unsigned BlockChain::open(fs::path const& _path, WithExisting _we) { - fs::path path = _path.empty() ? db::databasePath() : _path; - fs::path chainPath = path / fs::path(toHex(m_genesisHash.ref().cropped(0, 4))); - fs::path extrasPath = chainPath / fs::path(toString(c_databaseVersion)); + fs::path const path = _path.empty() ? db::databasePath() : _path; + fs::path const chainPath = path / fs::path(toHex(m_genesisHash.ref().cropped(0, 4))); + fs::path const chainSubPathBlocks = chainPath / fs::path("blocks"); + fs::path const extrasPath = chainPath / fs::path(toString(c_databaseVersion)); + fs::path const extrasSubPathExtras = extrasPath / fs::path("extras"); + fs::path const extrasSubPathOldExtras = extrasPath / fs::path("extras.old"); + fs::path const extrasSubPathOldDetails = extrasPath / fs::path("details.old"); + fs::path const extrasSubPathState = extrasPath / fs::path("state"); + fs::path const extrasSubPathMinor = extrasPath / fs::path("minor"); unsigned lastMinor = c_minorProtocolVersion; if (db::isDiskDatabase()) @@ -204,61 +210,64 @@ unsigned BlockChain::open(fs::path const& _path, WithExisting _we) fs::create_directories(extrasPath); DEV_IGNORE_EXCEPTIONS(fs::permissions(extrasPath, fs::owner_all)); - bytes status = contents(extrasPath / fs::path("minor")); + bytes const status = contents(extrasSubPathMinor); if (!status.empty()) DEV_IGNORE_EXCEPTIONS(lastMinor = (unsigned)RLP(status)); if (c_minorProtocolVersion != lastMinor) { - cnote << "Killing extras database (DB minor version:" << lastMinor << " != our miner version: " << c_minorProtocolVersion << ")."; - DEV_IGNORE_EXCEPTIONS(fs::remove_all(extrasPath / fs::path("details.old"))); - fs::rename(extrasPath / fs::path("extras"), extrasPath / fs::path("extras.old")); - fs::remove_all(extrasPath / fs::path("state")); - writeFile(extrasPath / fs::path("minor"), rlp(c_minorProtocolVersion)); + cnote << "Killing extras database " << extrasPath << " (DB minor version:" << lastMinor + << " != our minor version: " << c_minorProtocolVersion << ")."; + DEV_IGNORE_EXCEPTIONS(fs::remove_all(extrasSubPathOldDetails)); + fs::rename(extrasSubPathExtras, extrasSubPathOldExtras); + fs::remove_all(extrasSubPathState); + writeFile(extrasSubPathMinor, rlp(c_minorProtocolVersion)); lastMinor = (unsigned)RLP(status); } if (_we == WithExisting::Kill) { - cnote << "Killing blockchain & extras database (WithExisting::Kill)."; - fs::remove_all(chainPath / fs::path("blocks")); - fs::remove_all(extrasPath / fs::path("extras")); + cnote << "Killing blockchain (" << chainSubPathBlocks << ") & extras (" + << extrasSubPathExtras << ") databases (WithExisting::Kill)."; + fs::remove_all(chainSubPathBlocks); + fs::remove_all(extrasSubPathExtras); } } try { - m_blocksDB = db::DBFactory::create(chainPath / fs::path("blocks")); - m_extrasDB = db::DBFactory::create(extrasPath / fs::path("extras")); + m_blocksDB = db::DBFactory::create(chainSubPathBlocks); + m_extrasDB = db::DBFactory::create(extrasSubPathExtras); } catch (db::DatabaseError const& ex) { - // Check the exact reason of errror, in case of IOError we can display user-friendly message - if (*boost::get_error_info(ex) != db::DatabaseStatus::IOError) - throw; - + fs::path const dbPath = !m_blocksDB.get() ? chainSubPathBlocks : extrasSubPathExtras; if (db::isDiskDatabase()) { - if (fs::space(chainPath / fs::path("blocks")).available < 1024) + db::DatabaseStatus const dbStatus = + *boost::get_error_info(ex); + if (fs::space(path).available < 1024) { - cwarn << "Not enough available space found on hard drive. Please free some up and then re-run. Bailing."; + cwarn << "Failed to create database (" << dbPath + << "). Not enough available space found on hard drive. Please free some up " + "and re-run."; BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace()); } - else + else if (dbStatus == db::DatabaseStatus::Corruption) + { + cwarn << "Database corrupted (" << dbPath << ")"; + BOOST_THROW_EXCEPTION(DatabaseCorruption()); + } + else if (dbStatus == db::DatabaseStatus::IOError) { - cwarn << - "Database " << - (chainPath / fs::path("blocks")) << - "or " << - (extrasPath / fs::path("extras")) << - "already open. You appear to have another instance of ethereum running. Bailing."; + cwarn << "Database already open (" << dbPath + << "). You appear to have another instance of ethereum running."; BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); } } - else - { - cwarn << "Unknown database error occurred during in-memory database creation"; - throw; - } + + cwarn << "Unknown error occurred when creating database (" << dbPath + << "). Exception details: " << ex.what(); + throw; } if (_we != WithExisting::Verify && !details(m_genesisHash)) From 6034e736cab084ebb769d30f136d7be077019806 Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Thu, 17 Oct 2019 08:04:29 -0700 Subject: [PATCH 02/17] Change db open logs from warnings to errors --- libethereum/BlockChain.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 5d78bda7e82..a503a679bc0 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -247,25 +247,25 @@ unsigned BlockChain::open(fs::path const& _path, WithExisting _we) *boost::get_error_info(ex); if (fs::space(path).available < 1024) { - cwarn << "Failed to create database (" << dbPath + cerr << "Failed to create database (" << dbPath << "). Not enough available space found on hard drive. Please free some up " "and re-run."; BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace()); } else if (dbStatus == db::DatabaseStatus::Corruption) { - cwarn << "Database corrupted (" << dbPath << ")"; + cerr << "Database corrupted (" << dbPath << ")"; BOOST_THROW_EXCEPTION(DatabaseCorruption()); } else if (dbStatus == db::DatabaseStatus::IOError) { - cwarn << "Database already open (" << dbPath + cerr << "Database already open (" << dbPath << "). You appear to have another instance of ethereum running."; BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); } } - cwarn << "Unknown error occurred when creating database (" << dbPath + cerr << "Unknown error occurred when creating database (" << dbPath << "). Exception details: " << ex.what(); throw; } From 44c22344cfb2d478539c0c20f83b7db955b606eb Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Tue, 22 Oct 2019 22:05:39 -0700 Subject: [PATCH 03/17] Refactor Block::populateFromChain Refactor Block::populateFromChain so that the function doesn't do any unnecessary work (e.g. verify a block, execute transactions). --- libethereum/Block.cpp | 59 +++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index 2dde2bd47c1..0ef9d3d89c4 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -138,45 +138,44 @@ void Block::noteChain(BlockChain const& _bc) PopulationStatistics Block::populateFromChain(BlockChain const& _bc, h256 const& _h, ImportRequirements::value _ir) { - noteChain(_bc); - - PopulationStatistics ret { 0.0, 0.0 }; - if (!_bc.isKnown(_h)) { - // Might be worth throwing here. - cwarn << "Invalid block given for state population: " << _h; + cerr << "Invalid block given for state population: " << _h; BOOST_THROW_EXCEPTION(BlockNotFound() << errinfo_target(_h)); } - auto b = _bc.block(_h); - BlockHeader bi(b); // No need to check - it's already in the DB. - if (bi.number()) - { - // Non-genesis: - - // 1. Start at parent's end state (state root). - BlockHeader bip(_bc.block(bi.parentHash())); - sync(_bc, bi.parentHash(), bip); - - // 2. Enact the block's transactions onto this state. - m_author = bi.author(); - Timer t; - auto vb = _bc.verifyBlock(&b, function(), _ir | ImportRequirements::TransactionBasic); - ret.verify = t.elapsed(); - t.restart(); - enact(vb, _bc); - ret.enact = t.elapsed(); - } + auto const& blockBytes = _bc.block(_h); + m_currentBytes = blockBytes; + + auto const& blockHeader = BlockHeader{blockBytes}; + m_currentBlock = blockHeader; + + // Set state root and precommit state + m_state.setRoot(blockHeader.stateRoot()); + m_precommit = m_state; + + if (blockHeader.number()) + m_previousBlock = _bc.info(blockHeader.hash()); else + m_previousBlock = m_currentBlock; + + RLP blockRLP{blockBytes}; + auto const& txListRLP = blockRLP[1]; + for (auto const& txRLP : txListRLP) { - // Genesis required: - // We know there are no transactions, so just populate directly. - m_state = State(m_state.accountStartNonce(), m_state.db(), BaseState::Empty); // TODO: try with PreExisting. - sync(_bc, _h, bi); + m_transactions.push_back(Transaction{txRLP.data(), CheckTransaction::None}); + m_transactionSet.insert(m_transactions.back().sha3()); } + m_receipts = _bc.receipts(_h).receipts; - return ret; + m_currentTxs = txListRLP.data().toBytes(); + m_currentUncles = blockRLP[2].data().toBytes(); + m_author = blockHeader.author(); + + m_committedToSeal = false; + m_sealEngine = _bc.sealEngine(); + + return PopulationStatistics{}; } bool Block::sync(BlockChain const& _bc) From 253489d7d0d22ee0b1f58a5fd3bc51e5eadf954f Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Thu, 24 Oct 2019 22:14:23 -0700 Subject: [PATCH 04/17] Remove reprocess RPC method and associated type The reprocess admin RPC method is the only function which depends on the old Block::populateFromChain functionality where it replays each tx in the block. There's no need for the function so we can remove it. Additionally, check for StateDB corruption in Block::populateFromChain before setting the state root so that we can log a user-friendly error message. --- libethereum/Block.cpp | 29 ++++++++++++++----- libethereum/Block.h | 8 +---- libethereum/Client.cpp | 26 +++-------------- libethereum/Client.h | 4 --- libweb3jsonrpc/AdminEth.cpp | 12 -------- libweb3jsonrpc/AdminEth.h | 1 - libweb3jsonrpc/AdminEthFace.h | 6 ---- libweb3jsonrpc/admin_eth.json | 1 - .../libweb3jsonrpc/WebThreeStubClient.h | 11 ------- 9 files changed, 26 insertions(+), 72 deletions(-) diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index 0ef9d3d89c4..84fa260ccb5 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -136,7 +136,7 @@ void Block::noteChain(BlockChain const& _bc) } } -PopulationStatistics Block::populateFromChain(BlockChain const& _bc, h256 const& _h, ImportRequirements::value _ir) +void Block::populateFromChain(BlockChain const& _bc, h256 const& _h) { if (!_bc.isKnown(_h)) { @@ -147,18 +147,33 @@ PopulationStatistics Block::populateFromChain(BlockChain const& _bc, h256 const& auto const& blockBytes = _bc.block(_h); m_currentBytes = blockBytes; + // Set block headers auto const& blockHeader = BlockHeader{blockBytes}; m_currentBlock = blockHeader; - // Set state root and precommit state - m_state.setRoot(blockHeader.stateRoot()); - m_precommit = m_state; - if (blockHeader.number()) - m_previousBlock = _bc.info(blockHeader.hash()); + m_previousBlock = _bc.info(blockHeader.parentHash()); else m_previousBlock = m_currentBlock; + // Set state root and precommit state + // + // First check for database corruption by looking up the state root in the state database. Note + // that we don't technically need to do this since if the state DB is corrupt setting a new + // state root will throw anyway, but checking here enables us to log a user-friendly error + // message. + if (m_state.db().lookup(blockHeader.stateRoot()).empty()) + { + cerr << "Unable to populate block " << blockHeader.hash() << " - state root " + << blockHeader.stateRoot() << " not found in database."; + cerr << "Database corrupt: contains block without state root: " << blockHeader; + cerr << "Try rescuing the database by running: eth --rescue"; + BOOST_THROW_EXCEPTION(InvalidStateRoot() << errinfo_target(blockHeader.stateRoot())); + } + + m_state.setRoot(blockHeader.stateRoot()); + m_precommit = m_state; + RLP blockRLP{blockBytes}; auto const& txListRLP = blockRLP[1]; for (auto const& txRLP : txListRLP) @@ -174,8 +189,6 @@ PopulationStatistics Block::populateFromChain(BlockChain const& _bc, h256 const& m_committedToSeal = false; m_sealEngine = _bc.sealEngine(); - - return PopulationStatistics{}; } bool Block::sync(BlockChain const& _bc) diff --git a/libethereum/Block.h b/libethereum/Block.h index 6133d52b90d..ac55b6d5675 100644 --- a/libethereum/Block.h +++ b/libethereum/Block.h @@ -35,12 +35,6 @@ class TransactionQueue; struct VerifiedBlockRef; class LastBlockHashesFace; -struct PopulationStatistics -{ - double verify; - double enact; -}; - DEV_SIMPLE_EXCEPTION(ChainOperationWithUnknownBlockChain); DEV_SIMPLE_EXCEPTION(InvalidOperationOnSealedBlock); @@ -190,7 +184,7 @@ class Block // State-change operations /// Construct state object from arbitrary point in blockchain. - PopulationStatistics populateFromChain(BlockChain const& _bc, h256 const& _hash, ImportRequirements::value _ir = ImportRequirements::None); + void populateFromChain(BlockChain const& _bc, h256 const& _hash); /// Execute a given transaction. /// This will append @a _t to the transaction list and change the state accordingly. diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 16f2905abfe..371f21730d2 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -759,37 +759,19 @@ void Client::prepareForTransaction() startWorking(); } -Block Client::block(h256 const& _block) const +Block Client::block(h256 const& _blockHash) const { try { - Block ret(bc(), m_stateDB); - ret.populateFromChain(bc(), _block); - return ret; - } - catch (Exception& ex) - { - ex << errinfo_block(bc().block(_block)); - onBadBlock(ex); - return Block(bc()); - } -} - -Block Client::block(h256 const& _blockHash, PopulationStatistics* o_stats) const -{ - try - { - Block ret(bc(), m_stateDB); - PopulationStatistics s = ret.populateFromChain(bc(), _blockHash); - if (o_stats) - swap(s, *o_stats); + Block ret{bc(), m_stateDB}; + ret.populateFromChain(bc(), _blockHash); return ret; } catch (Exception& ex) { ex << errinfo_block(bc().block(_blockHash)); onBadBlock(ex); - return Block(bc()); + return Block{bc()}; } } diff --git a/libethereum/Client.h b/libethereum/Client.h index 952d73fedd6..983d82c70f6 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -100,10 +100,6 @@ class Client: public ClientBase, protected Worker /// Get the gas bid price u256 gasBidPrice() const override { return m_gp->bid(); } - // [PRIVATE API - only relevant for base clients, not available in general] - /// Get the block. - dev::eth::Block block(h256 const& _blockHash, PopulationStatistics* o_stats) const; - /// Get the object representing the current state of Ethereum. dev::eth::Block postState() const { ReadGuard l(x_postSeal); return m_postSeal; } /// Get the object representing the current canonical blockchain. diff --git a/libweb3jsonrpc/AdminEth.cpp b/libweb3jsonrpc/AdminEth.cpp index 2630046885f..09c48bb1183 100644 --- a/libweb3jsonrpc/AdminEth.cpp +++ b/libweb3jsonrpc/AdminEth.cpp @@ -179,18 +179,6 @@ h256 AdminEth::blockHash(string const& _blockNumberOrHash) const } } -Json::Value AdminEth::admin_eth_reprocess(string const& _blockNumberOrHash, string const& _session) -{ - RPC_ADMIN; - Json::Value ret; - PopulationStatistics ps; - m_eth.block(blockHash(_blockNumberOrHash), &ps); - ret["enact"] = ps.enact; - ret["verify"] = ps.verify; - ret["total"] = ps.verify + ps.enact; - return ret; -} - Json::Value AdminEth::admin_eth_vmTrace(string const& _blockNumberOrHash, int _txIndex, string const& _session) { RPC_ADMIN; diff --git a/libweb3jsonrpc/AdminEth.h b/libweb3jsonrpc/AdminEth.h index b41a1815c9b..a7914c57436 100644 --- a/libweb3jsonrpc/AdminEth.h +++ b/libweb3jsonrpc/AdminEth.h @@ -38,7 +38,6 @@ class AdminEth: public AdminEthFace virtual Json::Value admin_eth_newAccount(const Json::Value& _info, std::string const& _session) override; virtual bool admin_eth_setMiningBenefactor(std::string const& _uuidOrAddress, std::string const& _session) override; virtual Json::Value admin_eth_inspect(std::string const& _address, std::string const& _session) override; - virtual Json::Value admin_eth_reprocess(std::string const& _blockNumberOrHash, std::string const& _session) override; virtual Json::Value admin_eth_vmTrace(std::string const& _blockNumberOrHash, int _txIndex, std::string const& _session) override; virtual Json::Value admin_eth_getReceiptByHashAndIndex(std::string const& _blockNumberOrHash, int _txIndex, std::string const& _session) override; virtual bool miner_start(int _threads) override; diff --git a/libweb3jsonrpc/AdminEthFace.h b/libweb3jsonrpc/AdminEthFace.h index 87669b3c9b1..6cb00b93f05 100644 --- a/libweb3jsonrpc/AdminEthFace.h +++ b/libweb3jsonrpc/AdminEthFace.h @@ -25,7 +25,6 @@ namespace dev { this->bindAndAddMethod(jsonrpc::Procedure("admin_eth_newAccount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_OBJECT,"param2",jsonrpc::JSON_STRING, NULL), &dev::rpc::AdminEthFace::admin_eth_newAccountI); this->bindAndAddMethod(jsonrpc::Procedure("admin_eth_setMiningBenefactor", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &dev::rpc::AdminEthFace::admin_eth_setMiningBenefactorI); this->bindAndAddMethod(jsonrpc::Procedure("admin_eth_inspect", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &dev::rpc::AdminEthFace::admin_eth_inspectI); - this->bindAndAddMethod(jsonrpc::Procedure("admin_eth_reprocess", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &dev::rpc::AdminEthFace::admin_eth_reprocessI); this->bindAndAddMethod(jsonrpc::Procedure("admin_eth_vmTrace", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER,"param3",jsonrpc::JSON_STRING, NULL), &dev::rpc::AdminEthFace::admin_eth_vmTraceI); this->bindAndAddMethod(jsonrpc::Procedure("admin_eth_getReceiptByHashAndIndex", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER,"param3",jsonrpc::JSON_STRING, NULL), &dev::rpc::AdminEthFace::admin_eth_getReceiptByHashAndIndexI); this->bindAndAddMethod(jsonrpc::Procedure("miner_start", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &dev::rpc::AdminEthFace::miner_startI); @@ -80,10 +79,6 @@ namespace dev { { response = this->admin_eth_inspect(request[0u].asString(), request[1u].asString()); } - inline virtual void admin_eth_reprocessI(const Json::Value &request, Json::Value &response) - { - response = this->admin_eth_reprocess(request[0u].asString(), request[1u].asString()); - } inline virtual void admin_eth_vmTraceI(const Json::Value &request, Json::Value &response) { response = this->admin_eth_vmTrace(request[0u].asString(), request[1u].asInt(), request[2u].asString()); @@ -129,7 +124,6 @@ namespace dev { virtual Json::Value admin_eth_newAccount(const Json::Value& param1, const std::string& param2) = 0; virtual bool admin_eth_setMiningBenefactor(const std::string& param1, const std::string& param2) = 0; virtual Json::Value admin_eth_inspect(const std::string& param1, const std::string& param2) = 0; - virtual Json::Value admin_eth_reprocess(const std::string& param1, const std::string& param2) = 0; virtual Json::Value admin_eth_vmTrace(const std::string& param1, int param2, const std::string& param3) = 0; virtual Json::Value admin_eth_getReceiptByHashAndIndex(const std::string& param1, int param2, const std::string& param3) = 0; virtual bool miner_start(int param1) = 0; diff --git a/libweb3jsonrpc/admin_eth.json b/libweb3jsonrpc/admin_eth.json index 8b8f12a2617..405d2771f87 100644 --- a/libweb3jsonrpc/admin_eth.json +++ b/libweb3jsonrpc/admin_eth.json @@ -10,7 +10,6 @@ { "name": "admin_eth_newAccount", "params": [{}, ""], "returns": {} }, { "name": "admin_eth_setMiningBenefactor", "params": ["", ""], "returns": true }, { "name": "admin_eth_inspect", "params": ["", ""], "returns": {} }, -{ "name": "admin_eth_reprocess", "params": ["", ""], "returns": {} }, { "name": "admin_eth_vmTrace", "params": ["", 0, ""], "returns": {} }, { "name": "admin_eth_getReceiptByHashAndIndex", "params": ["", 0, ""], "returns": {} }, { "name": "miner_start", "params": [0], "returns": true }, diff --git a/test/unittests/libweb3jsonrpc/WebThreeStubClient.h b/test/unittests/libweb3jsonrpc/WebThreeStubClient.h index 3324c84b365..9503a0ebaf3 100644 --- a/test/unittests/libweb3jsonrpc/WebThreeStubClient.h +++ b/test/unittests/libweb3jsonrpc/WebThreeStubClient.h @@ -924,17 +924,6 @@ class WebThreeStubClient : public jsonrpc::Client else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - Json::Value admin_eth_reprocess(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) - { - Json::Value p; - p.append(param1); - p.append(param2); - Json::Value result = this->CallMethod("admin_eth_reprocess",p); - if (result.isObject()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - } Json::Value admin_eth_vmTrace(const std::string& param1, int param2, const std::string& param3) throw (jsonrpc::JsonRpcException) { Json::Value p; From c54a1fd2c7849b3ca4e618ebbf19cc6f65cd29b1 Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Thu, 24 Oct 2019 22:44:52 -0700 Subject: [PATCH 05/17] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 517b53369b9..1530a5a0fb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ - Added: [#5699](https://github.com/ethereum/aleth/pull/5699) EIP 2046: Reduced gas cost for static calls made to precompiles. - Added: [#5752](https://github.com/ethereum/aleth/pull/5752) [#5753](https://github.com/ethereum/aleth/pull/5753) Implement EIP1380 (reduced gas costs for call-to-self). -- Removed: [#5760](https://github.com/ethereum/aleth/pull/5760) Official support for Visual Studio 2015 has been dropped. Compilation with this compiler is expected to stop working after migration to C++14. +- Removed: [#5760](https://github.com/ethereum/aleth/pull/5760) Official support for Visual Studio 2015 has been dropped. Compilation with this compiler is expected to stop working after migration to C++14. +- Fixed: [#5792](https://github.com/ethereum/aleth/pull/5792) Faster and cheaper execution of RPC functions which query blockchain state (e.g. getBalance). ## [1.7.0] - Unreleased From dccb09f0ca7d411024d71c142a03430299d552c0 Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Sat, 26 Oct 2019 20:36:29 -0700 Subject: [PATCH 06/17] Remove retrieved block's seal in Client::call Seal must be removed since Client::call executes a tx which can mutate the block's state. --- libethereum/Block.h | 4 ++++ libethereum/Client.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/libethereum/Block.h b/libethereum/Block.h index ac55b6d5675..d93ed24fb06 100644 --- a/libethereum/Block.h +++ b/libethereum/Block.h @@ -243,6 +243,10 @@ class Block /// @returns true if sealed - in this case you can no longer append transactions. bool isSealed() const { return !m_currentBytes.empty(); } + /// Clears the block bytes - typically used in cases where we want to mutate a sealed + /// block's state (e.g. eth_call) + void unseal() { m_currentBytes.clear(); } + /// Get the complete current block, including valid nonce. /// Only valid when isSealed() is true. bytes const& blockData() const { return m_currentBytes; } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 371f21730d2..3876aa5014c 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -901,6 +901,7 @@ ExecutionResult Client::call(Address const& _from, u256 _value, Address _dest, b try { Block temp = blockByNumber(_blockNumber); + temp.unseal(); // Unseal block since we're going to be executing a transaction u256 nonce = max(temp.transactionsFrom(_from), m_tq.maxNonce(_from)); u256 gas = _gas == Invalid256 ? gasLimitRemaining() : _gas; u256 gasPrice = _gasPrice == Invalid256 ? gasBidPrice() : _gasPrice; From aa6500a00be942b4e4f15cfd85c1ef1cdcc263d8 Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Sat, 26 Oct 2019 21:18:04 -0700 Subject: [PATCH 07/17] Removed unnecessary path var definitions in BlockChain Removed path var definitions which were only used once in BlockChain::open --- libethereum/BlockChain.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index a503a679bc0..bb8d6f030f2 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -199,10 +199,6 @@ unsigned BlockChain::open(fs::path const& _path, WithExisting _we) fs::path const chainSubPathBlocks = chainPath / fs::path("blocks"); fs::path const extrasPath = chainPath / fs::path(toString(c_databaseVersion)); fs::path const extrasSubPathExtras = extrasPath / fs::path("extras"); - fs::path const extrasSubPathOldExtras = extrasPath / fs::path("extras.old"); - fs::path const extrasSubPathOldDetails = extrasPath / fs::path("details.old"); - fs::path const extrasSubPathState = extrasPath / fs::path("state"); - fs::path const extrasSubPathMinor = extrasPath / fs::path("minor"); unsigned lastMinor = c_minorProtocolVersion; if (db::isDiskDatabase()) @@ -210,6 +206,7 @@ unsigned BlockChain::open(fs::path const& _path, WithExisting _we) fs::create_directories(extrasPath); DEV_IGNORE_EXCEPTIONS(fs::permissions(extrasPath, fs::owner_all)); + fs::path const extrasSubPathMinor = extrasPath / fs::path("minor"); bytes const status = contents(extrasSubPathMinor); if (!status.empty()) DEV_IGNORE_EXCEPTIONS(lastMinor = (unsigned)RLP(status)); @@ -217,9 +214,9 @@ unsigned BlockChain::open(fs::path const& _path, WithExisting _we) { cnote << "Killing extras database " << extrasPath << " (DB minor version:" << lastMinor << " != our minor version: " << c_minorProtocolVersion << ")."; - DEV_IGNORE_EXCEPTIONS(fs::remove_all(extrasSubPathOldDetails)); - fs::rename(extrasSubPathExtras, extrasSubPathOldExtras); - fs::remove_all(extrasSubPathState); + DEV_IGNORE_EXCEPTIONS(fs::remove_all(extrasPath / fs::path("details.old"))); + fs::rename(extrasSubPathExtras, extrasPath / fs::path("extras.old")); + fs::remove_all(extrasPath / fs::path("state")); writeFile(extrasSubPathMinor, rlp(c_minorProtocolVersion)); lastMinor = (unsigned)RLP(status); } From be3efc206cb83d94494ee75bcebf95ad7ec97f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 28 Oct 2019 09:03:25 +0100 Subject: [PATCH 08/17] Replace tabs with spaces in FixedHash.h --- libdevcore/FixedHash.h | 522 ++++++++++++++++++++--------------------- 1 file changed, 261 insertions(+), 261 deletions(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index cb914d6bb9d..19d4a9d8090 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -29,304 +29,304 @@ template class FixedHash { public: - /// The corresponding arithmetic type. - using Arith = boost::multiprecision::number>; + /// The corresponding arithmetic type. + using Arith = boost::multiprecision::number>; - /// The size of the container. - enum { size = N }; + /// The size of the container. + enum { size = N }; - /// A dummy flag to avoid accidental construction from pointer. - enum ConstructFromPointerType { ConstructFromPointer }; + /// A dummy flag to avoid accidental construction from pointer. + enum ConstructFromPointerType { ConstructFromPointer }; - /// Method to convert from a string. - enum ConstructFromStringType { FromHex, FromBinary }; + /// Method to convert from a string. + enum ConstructFromStringType { FromHex, FromBinary }; - /// Method to convert from a string. - enum ConstructFromHashType { AlignLeft, AlignRight, FailIfDifferent }; + /// Method to convert from a string. + enum ConstructFromHashType { AlignLeft, AlignRight, FailIfDifferent }; - /// Construct an empty hash. - FixedHash() { m_data.fill(0); } + /// Construct an empty hash. + FixedHash() { m_data.fill(0); } - /// Construct from another hash, filling with zeroes or cropping as necessary. - template explicit FixedHash(FixedHash const& _h, ConstructFromHashType _t = AlignLeft) { m_data.fill(0); unsigned c = std::min(M, N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; } + /// Construct from another hash, filling with zeroes or cropping as necessary. + template explicit FixedHash(FixedHash const& _h, ConstructFromHashType _t = AlignLeft) { m_data.fill(0); unsigned c = std::min(M, N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; } - /// Convert from the corresponding arithmetic type. - FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } + /// Convert from the corresponding arithmetic type. + FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } - /// Convert from unsigned - explicit FixedHash(unsigned _u) { toBigEndian(_u, m_data); } + /// Convert from unsigned + explicit FixedHash(unsigned _u) { toBigEndian(_u, m_data); } - /// Explicitly construct, copying from a byte array. - explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } } + /// Explicitly construct, copying from a byte array. + explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } } - /// Explicitly construct, copying from a byte array. - explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } } + /// Explicitly construct, copying from a byte array. + explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } } - /// Explicitly construct, copying from a bytes in memory with given pointer. - explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); } + /// Explicitly construct, copying from a bytes in memory with given pointer. + explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); } - /// Explicitly construct, copying from a string. - explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): FixedHash(_t == FromHex ? fromHex(_s, WhenError::Throw) : dev::asBytes(_s), _ht) {} + /// Explicitly construct, copying from a string. + explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): FixedHash(_t == FromHex ? fromHex(_s, WhenError::Throw) : dev::asBytes(_s), _ht) {} - /// Convert to arithmetic type. - operator Arith() const { return fromBigEndian(m_data); } + /// Convert to arithmetic type. + operator Arith() const { return fromBigEndian(m_data); } - /// @returns true iff this is the empty hash. - explicit operator bool() const { return std::any_of(m_data.begin(), m_data.end(), [](byte _b) { return _b != 0; }); } + /// @returns true iff this is the empty hash. + explicit operator bool() const { return std::any_of(m_data.begin(), m_data.end(), [](byte _b) { return _b != 0; }); } - // The obvious comparison operators. - bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; } - bool operator!=(FixedHash const& _c) const { return m_data != _c.m_data; } - bool operator<(FixedHash const& _c) const { for (unsigned i = 0; i < N; ++i) if (m_data[i] < _c.m_data[i]) return true; else if (m_data[i] > _c.m_data[i]) return false; return false; } - bool operator>=(FixedHash const& _c) const { return !operator<(_c); } - bool operator<=(FixedHash const& _c) const { return operator==(_c) || operator<(_c); } - bool operator>(FixedHash const& _c) const { return !operator<=(_c); } + // The obvious comparison operators. + bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; } + bool operator!=(FixedHash const& _c) const { return m_data != _c.m_data; } + bool operator<(FixedHash const& _c) const { for (unsigned i = 0; i < N; ++i) if (m_data[i] < _c.m_data[i]) return true; else if (m_data[i] > _c.m_data[i]) return false; return false; } + bool operator>=(FixedHash const& _c) const { return !operator<(_c); } + bool operator<=(FixedHash const& _c) const { return operator==(_c) || operator<(_c); } + bool operator>(FixedHash const& _c) const { return !operator<=(_c); } - // The obvious binary operators. - FixedHash& operator^=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] ^= _c.m_data[i]; return *this; } - FixedHash operator^(FixedHash const& _c) const { return FixedHash(*this) ^= _c; } - FixedHash& operator|=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] |= _c.m_data[i]; return *this; } - FixedHash operator|(FixedHash const& _c) const { return FixedHash(*this) |= _c; } - FixedHash& operator&=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] &= _c.m_data[i]; return *this; } - FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; } - FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; } + // The obvious binary operators. + FixedHash& operator^=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] ^= _c.m_data[i]; return *this; } + FixedHash operator^(FixedHash const& _c) const { return FixedHash(*this) ^= _c; } + FixedHash& operator|=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] |= _c.m_data[i]; return *this; } + FixedHash operator|(FixedHash const& _c) const { return FixedHash(*this) |= _c; } + FixedHash& operator&=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] &= _c.m_data[i]; return *this; } + FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; } + FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; } - // Big-endian increment. - FixedHash& operator++() { for (unsigned i = size; i > 0 && !++m_data[--i]; ) {} return *this; } - - /// @returns true if all one-bits in @a _c are set in this object. - bool contains(FixedHash const& _c) const { return (*this & _c) == _c; } - - /// @returns a particular byte from the hash. - byte& operator[](unsigned _i) { return m_data[_i]; } - /// @returns a particular byte from the hash. - byte operator[](unsigned _i) const { return m_data[_i]; } - - /// @returns an abridged version of the hash as a user-readable hex string. - std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; } - - /// @returns a version of the hash as a user-readable hex string that leaves out the middle part. - std::string abridgedMiddle() const { return toHex(ref().cropped(0, 4)) + "\342\200\246" + toHex(ref().cropped(N - 4)); } - - /// @returns the hash as a user-readable hex string. - std::string hex() const { return toHex(ref()); } - - /// @returns a mutable byte vector_ref to the object's data. - bytesRef ref() { return bytesRef(m_data.data(), N); } - - /// @returns a constant byte vector_ref to the object's data. - bytesConstRef ref() const { return bytesConstRef(m_data.data(), N); } - - /// @returns a mutable byte pointer to the object's data. - byte* data() { return m_data.data(); } - - /// @returns a constant byte pointer to the object's data. - byte const* data() const { return m_data.data(); } - - /// @returns begin iterator. - auto begin() const -> typename std::array::const_iterator { return m_data.begin(); } - - /// @returns end iterator. - auto end() const -> typename std::array::const_iterator { return m_data.end(); } - - /// @returns a copy of the object's data as a byte vector. - bytes asBytes() const { return bytes(data(), data() + N); } - - /// @returns a mutable reference to the object's data as an STL array. - std::array& asArray() { return m_data; } - - /// @returns a constant reference to the object's data as an STL array. - std::array const& asArray() const { return m_data; } - - /// Populate with random data. - template - void randomize(Engine& _eng) - { - for (auto& i: m_data) - i = (uint8_t)std::uniform_int_distribution(0, 255)(_eng); - } - - /// @returns a random valued object. - static FixedHash random() { FixedHash ret; ret.randomize(s_fixedHashEngine); return ret; } - - struct hash - { - /// Make a hash of the object's data. - size_t operator()(FixedHash const& _value) const { return boost::hash_range(_value.m_data.cbegin(), _value.m_data.cend()); } - }; - - template inline FixedHash& shiftBloom(FixedHash const& _h) - { - return (*this |= _h.template bloomPart()); - } - - template inline bool containsBloom(FixedHash const& _h) - { - return contains(_h.template bloomPart()); - } - - template inline FixedHash bloomPart() const - { - unsigned const c_bloomBits = M * 8; - unsigned const c_mask = c_bloomBits - 1; - unsigned const c_bloomBytes = (StaticLog2::result + 7) / 8; - - static_assert((M & (M - 1)) == 0, "M must be power-of-two"); - static_assert(P * c_bloomBytes <= N, "out of range"); - - FixedHash ret; - byte const* p = data(); - for (unsigned i = 0; i < P; ++i) - { - unsigned index = 0; - for (unsigned j = 0; j < c_bloomBytes; ++j, ++p) - index = (index << 8) | *p; - index &= c_mask; - ret[M - 1 - index / 8] |= (1 << (index % 8)); - } - return ret; - } - - /// Returns the index of the first bit set to one, or size() * 8 if no bits are set. - inline unsigned firstBitSet() const - { - unsigned ret = 0; - for (auto d: m_data) - if (d) - { - for (;; ++ret, d <<= 1) - { - if (d & 0x80) - return ret; - } - } - else - ret += 8; - return ret; - } - - void clear() { m_data.fill(0); } + // Big-endian increment. + FixedHash& operator++() { for (unsigned i = size; i > 0 && !++m_data[--i]; ) {} return *this; } + + /// @returns true if all one-bits in @a _c are set in this object. + bool contains(FixedHash const& _c) const { return (*this & _c) == _c; } + + /// @returns a particular byte from the hash. + byte& operator[](unsigned _i) { return m_data[_i]; } + /// @returns a particular byte from the hash. + byte operator[](unsigned _i) const { return m_data[_i]; } + + /// @returns an abridged version of the hash as a user-readable hex string. + std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; } + + /// @returns a version of the hash as a user-readable hex string that leaves out the middle part. + std::string abridgedMiddle() const { return toHex(ref().cropped(0, 4)) + "\342\200\246" + toHex(ref().cropped(N - 4)); } + + /// @returns the hash as a user-readable hex string. + std::string hex() const { return toHex(ref()); } + + /// @returns a mutable byte vector_ref to the object's data. + bytesRef ref() { return bytesRef(m_data.data(), N); } + + /// @returns a constant byte vector_ref to the object's data. + bytesConstRef ref() const { return bytesConstRef(m_data.data(), N); } + + /// @returns a mutable byte pointer to the object's data. + byte* data() { return m_data.data(); } + + /// @returns a constant byte pointer to the object's data. + byte const* data() const { return m_data.data(); } + + /// @returns begin iterator. + auto begin() const -> typename std::array::const_iterator { return m_data.begin(); } + + /// @returns end iterator. + auto end() const -> typename std::array::const_iterator { return m_data.end(); } + + /// @returns a copy of the object's data as a byte vector. + bytes asBytes() const { return bytes(data(), data() + N); } + + /// @returns a mutable reference to the object's data as an STL array. + std::array& asArray() { return m_data; } + + /// @returns a constant reference to the object's data as an STL array. + std::array const& asArray() const { return m_data; } + + /// Populate with random data. + template + void randomize(Engine& _eng) + { + for (auto& i: m_data) + i = (uint8_t)std::uniform_int_distribution(0, 255)(_eng); + } + + /// @returns a random valued object. + static FixedHash random() { FixedHash ret; ret.randomize(s_fixedHashEngine); return ret; } + + struct hash + { + /// Make a hash of the object's data. + size_t operator()(FixedHash const& _value) const { return boost::hash_range(_value.m_data.cbegin(), _value.m_data.cend()); } + }; + + template inline FixedHash& shiftBloom(FixedHash const& _h) + { + return (*this |= _h.template bloomPart()); + } + + template inline bool containsBloom(FixedHash const& _h) + { + return contains(_h.template bloomPart()); + } + + template inline FixedHash bloomPart() const + { + unsigned const c_bloomBits = M * 8; + unsigned const c_mask = c_bloomBits - 1; + unsigned const c_bloomBytes = (StaticLog2::result + 7) / 8; + + static_assert((M & (M - 1)) == 0, "M must be power-of-two"); + static_assert(P * c_bloomBytes <= N, "out of range"); + + FixedHash ret; + byte const* p = data(); + for (unsigned i = 0; i < P; ++i) + { + unsigned index = 0; + for (unsigned j = 0; j < c_bloomBytes; ++j, ++p) + index = (index << 8) | *p; + index &= c_mask; + ret[M - 1 - index / 8] |= (1 << (index % 8)); + } + return ret; + } + + /// Returns the index of the first bit set to one, or size() * 8 if no bits are set. + inline unsigned firstBitSet() const + { + unsigned ret = 0; + for (auto d: m_data) + if (d) + { + for (;; ++ret, d <<= 1) + { + if (d & 0x80) + return ret; + } + } + else + ret += 8; + return ret; + } + + void clear() { m_data.fill(0); } private: - std::array m_data; ///< The binary data. + std::array m_data; ///< The binary data. }; template class SecureFixedHash: private FixedHash { public: - using ConstructFromHashType = typename FixedHash::ConstructFromHashType; - using ConstructFromStringType = typename FixedHash::ConstructFromStringType; - using ConstructFromPointerType = typename FixedHash::ConstructFromPointerType; - SecureFixedHash() = default; - explicit SecureFixedHash(bytes const& _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b, _t) {} - explicit SecureFixedHash(bytesConstRef _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b, _t) {} - explicit SecureFixedHash(bytesSec const& _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b.ref(), _t) {} - template explicit SecureFixedHash(FixedHash const& _h, ConstructFromHashType _t = FixedHash::AlignLeft): FixedHash(_h, _t) {} - template explicit SecureFixedHash(SecureFixedHash const& _h, ConstructFromHashType _t = FixedHash::AlignLeft): FixedHash(_h.makeInsecure(), _t) {} - explicit SecureFixedHash(std::string const& _s, ConstructFromStringType _t = FixedHash::FromHex, ConstructFromHashType _ht = FixedHash::FailIfDifferent): FixedHash(_s, _t, _ht) {} - explicit SecureFixedHash(byte const* _d, ConstructFromPointerType _t): FixedHash(_d, _t) {} - ~SecureFixedHash() { ref().cleanse(); } - - SecureFixedHash& operator=(SecureFixedHash const& _c) - { - if (&_c == this) - return *this; - ref().cleanse(); - FixedHash::operator=(static_cast const&>(_c)); - return *this; - } - - using FixedHash::size; - - bytesSec asBytesSec() const { return bytesSec(ref()); } - - FixedHash const& makeInsecure() const { return static_cast const&>(*this); } - FixedHash& writable() { clear(); return static_cast&>(*this); } - - using FixedHash::operator bool; - - // The obvious comparison operators. - bool operator==(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator==(static_cast const&>(_c)); } - bool operator!=(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator!=(static_cast const&>(_c)); } - bool operator<(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator<(static_cast const&>(_c)); } - bool operator>=(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator>=(static_cast const&>(_c)); } - bool operator<=(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator<=(static_cast const&>(_c)); } - bool operator>(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator>(static_cast const&>(_c)); } - - using FixedHash::operator==; - using FixedHash::operator!=; - using FixedHash::operator<; - using FixedHash::operator>=; - using FixedHash::operator<=; - using FixedHash::operator>; - - // The obvious binary operators. - SecureFixedHash& operator^=(FixedHash const& _c) { static_cast&>(*this).operator^=(_c); return *this; } - SecureFixedHash operator^(FixedHash const& _c) const { return SecureFixedHash(*this) ^= _c; } - SecureFixedHash& operator|=(FixedHash const& _c) { static_cast&>(*this).operator^=(_c); return *this; } - SecureFixedHash operator|(FixedHash const& _c) const { return SecureFixedHash(*this) |= _c; } - SecureFixedHash& operator&=(FixedHash const& _c) { static_cast&>(*this).operator^=(_c); return *this; } - SecureFixedHash operator&(FixedHash const& _c) const { return SecureFixedHash(*this) &= _c; } - - SecureFixedHash& operator^=(SecureFixedHash const& _c) { static_cast&>(*this).operator^=(static_cast const&>(_c)); return *this; } - SecureFixedHash operator^(SecureFixedHash const& _c) const { return SecureFixedHash(*this) ^= _c; } - SecureFixedHash& operator|=(SecureFixedHash const& _c) { static_cast&>(*this).operator^=(static_cast const&>(_c)); return *this; } - SecureFixedHash operator|(SecureFixedHash const& _c) const { return SecureFixedHash(*this) |= _c; } - SecureFixedHash& operator&=(SecureFixedHash const& _c) { static_cast&>(*this).operator^=(static_cast const&>(_c)); return *this; } - SecureFixedHash operator&(SecureFixedHash const& _c) const { return SecureFixedHash(*this) &= _c; } - SecureFixedHash operator~() const { auto r = ~static_cast const&>(*this); return static_cast(r); } - - using FixedHash::abridged; - using FixedHash::abridgedMiddle; - - bytesConstRef ref() const { return FixedHash::ref(); } - byte const* data() const { return FixedHash::data(); } - - static SecureFixedHash random() { SecureFixedHash ret; ret.randomize(s_fixedHashEngine); return ret; } - using FixedHash::firstBitSet; - - void clear() { ref().cleanse(); } + using ConstructFromHashType = typename FixedHash::ConstructFromHashType; + using ConstructFromStringType = typename FixedHash::ConstructFromStringType; + using ConstructFromPointerType = typename FixedHash::ConstructFromPointerType; + SecureFixedHash() = default; + explicit SecureFixedHash(bytes const& _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b, _t) {} + explicit SecureFixedHash(bytesConstRef _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b, _t) {} + explicit SecureFixedHash(bytesSec const& _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b.ref(), _t) {} + template explicit SecureFixedHash(FixedHash const& _h, ConstructFromHashType _t = FixedHash::AlignLeft): FixedHash(_h, _t) {} + template explicit SecureFixedHash(SecureFixedHash const& _h, ConstructFromHashType _t = FixedHash::AlignLeft): FixedHash(_h.makeInsecure(), _t) {} + explicit SecureFixedHash(std::string const& _s, ConstructFromStringType _t = FixedHash::FromHex, ConstructFromHashType _ht = FixedHash::FailIfDifferent): FixedHash(_s, _t, _ht) {} + explicit SecureFixedHash(byte const* _d, ConstructFromPointerType _t): FixedHash(_d, _t) {} + ~SecureFixedHash() { ref().cleanse(); } + + SecureFixedHash& operator=(SecureFixedHash const& _c) + { + if (&_c == this) + return *this; + ref().cleanse(); + FixedHash::operator=(static_cast const&>(_c)); + return *this; + } + + using FixedHash::size; + + bytesSec asBytesSec() const { return bytesSec(ref()); } + + FixedHash const& makeInsecure() const { return static_cast const&>(*this); } + FixedHash& writable() { clear(); return static_cast&>(*this); } + + using FixedHash::operator bool; + + // The obvious comparison operators. + bool operator==(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator==(static_cast const&>(_c)); } + bool operator!=(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator!=(static_cast const&>(_c)); } + bool operator<(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator<(static_cast const&>(_c)); } + bool operator>=(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator>=(static_cast const&>(_c)); } + bool operator<=(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator<=(static_cast const&>(_c)); } + bool operator>(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator>(static_cast const&>(_c)); } + + using FixedHash::operator==; + using FixedHash::operator!=; + using FixedHash::operator<; + using FixedHash::operator>=; + using FixedHash::operator<=; + using FixedHash::operator>; + + // The obvious binary operators. + SecureFixedHash& operator^=(FixedHash const& _c) { static_cast&>(*this).operator^=(_c); return *this; } + SecureFixedHash operator^(FixedHash const& _c) const { return SecureFixedHash(*this) ^= _c; } + SecureFixedHash& operator|=(FixedHash const& _c) { static_cast&>(*this).operator^=(_c); return *this; } + SecureFixedHash operator|(FixedHash const& _c) const { return SecureFixedHash(*this) |= _c; } + SecureFixedHash& operator&=(FixedHash const& _c) { static_cast&>(*this).operator^=(_c); return *this; } + SecureFixedHash operator&(FixedHash const& _c) const { return SecureFixedHash(*this) &= _c; } + + SecureFixedHash& operator^=(SecureFixedHash const& _c) { static_cast&>(*this).operator^=(static_cast const&>(_c)); return *this; } + SecureFixedHash operator^(SecureFixedHash const& _c) const { return SecureFixedHash(*this) ^= _c; } + SecureFixedHash& operator|=(SecureFixedHash const& _c) { static_cast&>(*this).operator^=(static_cast const&>(_c)); return *this; } + SecureFixedHash operator|(SecureFixedHash const& _c) const { return SecureFixedHash(*this) |= _c; } + SecureFixedHash& operator&=(SecureFixedHash const& _c) { static_cast&>(*this).operator^=(static_cast const&>(_c)); return *this; } + SecureFixedHash operator&(SecureFixedHash const& _c) const { return SecureFixedHash(*this) &= _c; } + SecureFixedHash operator~() const { auto r = ~static_cast const&>(*this); return static_cast(r); } + + using FixedHash::abridged; + using FixedHash::abridgedMiddle; + + bytesConstRef ref() const { return FixedHash::ref(); } + byte const* data() const { return FixedHash::data(); } + + static SecureFixedHash random() { SecureFixedHash ret; ret.randomize(s_fixedHashEngine); return ret; } + using FixedHash::firstBitSet; + + void clear() { ref().cleanse(); } }; /// Fast equality operator for h256. template<> inline bool FixedHash<32>::operator==(FixedHash<32> const& _other) const { - const uint64_t* hash1 = (const uint64_t*)data(); - const uint64_t* hash2 = (const uint64_t*)_other.data(); - return (hash1[0] == hash2[0]) && (hash1[1] == hash2[1]) && (hash1[2] == hash2[2]) && (hash1[3] == hash2[3]); + const uint64_t* hash1 = (const uint64_t*)data(); + const uint64_t* hash2 = (const uint64_t*)_other.data(); + return (hash1[0] == hash2[0]) && (hash1[1] == hash2[1]) && (hash1[2] == hash2[2]) && (hash1[3] == hash2[3]); } /// Fast std::hash compatible hash function object for h256. template<> inline size_t FixedHash<32>::hash::operator()(FixedHash<32> const& value) const { - uint64_t const* data = reinterpret_cast(value.data()); - return boost::hash_range(data, data + 4); + uint64_t const* data = reinterpret_cast(value.data()); + return boost::hash_range(data, data + 4); } /// Stream I/O for the FixedHash class. template inline std::ostream& operator<<(std::ostream& _out, FixedHash const& _h) { - _out << toHex(_h); - return _out; + _out << toHex(_h); + return _out; } template inline std::istream& operator>>(std::istream& _in, FixedHash& o_h) { - std::string s; - _in >> s; - o_h = FixedHash(s, FixedHash::FromHex, FixedHash::AlignRight); - return _in; + std::string s; + _in >> s; + o_h = FixedHash(s, FixedHash::FromHex, FixedHash::AlignRight); + return _in; } /// Stream I/O for the SecureFixedHash class. template inline std::ostream& operator<<(std::ostream& _out, SecureFixedHash const& _h) { - _out << "SecureFixedHash#" << std::hex << typename FixedHash::hash()(_h.makeInsecure()) << std::dec; - return _out; + _out << "SecureFixedHash#" << std::hex << typename FixedHash::hash()(_h.makeInsecure()) << std::dec; + return _out; } // Common types of FixedHash. @@ -349,9 +349,9 @@ using h160Hash = std::unordered_set; /// Convert the given value into h160 (160-bit unsigned integer) using the right 20 bytes. inline h160 right160(h256 const& _t) { - h160 ret; - memcpy(ret.data(), _t.data() + 12, 20); - return ret; + h160 ret; + memcpy(ret.data(), _t.data() + 12, 20); + return ret; } h128 fromUUID(std::string const& _uuid); @@ -360,22 +360,22 @@ std::string toUUID(h128 const& _uuid); inline std::string toString(h256s const& _bs) { - std::ostringstream out; - out << "[ "; - for (h256 const& i: _bs) - out << i.abridged() << ", "; - out << "]"; - return out.str(); + std::ostringstream out; + out << "[ "; + for (h256 const& i: _bs) + out << i.abridged() << ", "; + out << "]"; + return out.str(); } } namespace std { - /// Forward std::hash to dev::FixedHash::hash. - template<> struct hash: dev::h64::hash {}; - template<> struct hash: dev::h128::hash {}; - template<> struct hash: dev::h160::hash {}; - template<> struct hash: dev::h256::hash {}; - template<> struct hash: dev::h512::hash {}; + /// Forward std::hash to dev::FixedHash::hash. + template<> struct hash: dev::h64::hash {}; + template<> struct hash: dev::h128::hash {}; + template<> struct hash: dev::h160::hash {}; + template<> struct hash: dev::h256::hash {}; + template<> struct hash: dev::h512::hash {}; } From 3739d40aec72f98b646b25661945ba12525fa8c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 28 Oct 2019 09:09:01 +0100 Subject: [PATCH 09/17] FixedHash: Add explicit copy constructor to SecureFixedHash As of C++11, the implicitly declared copy constructor is deprecated if a class has user-defined assignment operator. GCC 9 has added a warning for it. --- libdevcore/FixedHash.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 19d4a9d8090..996ac311d46 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -219,6 +219,7 @@ class SecureFixedHash: private FixedHash using ConstructFromStringType = typename FixedHash::ConstructFromStringType; using ConstructFromPointerType = typename FixedHash::ConstructFromPointerType; SecureFixedHash() = default; + SecureFixedHash(SecureFixedHash const&) = default; explicit SecureFixedHash(bytes const& _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b, _t) {} explicit SecureFixedHash(bytesConstRef _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b, _t) {} explicit SecureFixedHash(bytesSec const& _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b.ref(), _t) {} From 75d30bf2a3d2f17f0d918672c561b5f48f39304e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 28 Oct 2019 09:35:05 +0100 Subject: [PATCH 10/17] rpc: Fix usage of strncpy() If strncpy() is used the requested count of characters must be lower than the destination buffer. Otherwise in the edge case the result string will not have the null terminator. This change fixes the issue by making the "max path" constant 1 char smaller. --- libweb3jsonrpc/UnixSocketServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libweb3jsonrpc/UnixSocketServer.cpp b/libweb3jsonrpc/UnixSocketServer.cpp index 027adcfdbbe..b7c724af615 100644 --- a/libweb3jsonrpc/UnixSocketServer.cpp +++ b/libweb3jsonrpc/UnixSocketServer.cpp @@ -27,7 +27,7 @@ namespace fs = boost::filesystem; namespace { -size_t const c_socketPathMaxLength = sizeof(sockaddr_un::sun_path) / sizeof(sockaddr_un::sun_path[0]); +size_t const c_socketPathMaxLength = sizeof(sockaddr_un::sun_path) / sizeof(sockaddr_un::sun_path[0]) - 1; fs::path getIpcPathOrDataDir() { From c459c938ce7f09d38fb10b111e97addaf23f511a Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Sun, 27 Oct 2019 20:43:06 -0700 Subject: [PATCH 11/17] Refactor State::openDB error handling and fix bug Bug was that calling State::openDB with WithExisting::Kill wouldn't kill the state database due to the wrong path being passed to fs::remove_all --- libethereum/State.cpp | 71 +++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 0c6cc8048a8..37a94a938ad 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -42,45 +42,64 @@ State::State(State const& _s): OverlayDB State::openDB(fs::path const& _basePath, h256 const& _genesisHash, WithExisting _we) { - fs::path path = _basePath.empty() ? db::databasePath() : _basePath; + auto const path = _basePath.empty() ? db::databasePath() : _basePath; + auto const chainPath = path / fs::path(toHex(_genesisHash.ref().cropped(0, 4))) / + fs::path(toString(c_databaseVersion)); + auto const statePath = chainPath / fs::path("state"); - if (db::isDiskDatabase() && _we == WithExisting::Kill) - { - clog(VerbosityDebug, "statedb") << "Killing state database (WithExisting::Kill)."; - fs::remove_all(path / fs::path("state")); - } - - path /= fs::path(toHex(_genesisHash.ref().cropped(0, 4))) / fs::path(toString(c_databaseVersion)); if (db::isDiskDatabase()) { - fs::create_directories(path); - DEV_IGNORE_EXCEPTIONS(fs::permissions(path, fs::owner_all)); + if (_we == WithExisting::Kill) + { + clog(VerbosityDebug, "statedb") + << "Killing state database (" << statePath << ") (WithExisting::Kill)"; + fs::remove_all(statePath); + } + + clog(VerbosityDebug, "statedb") << "Verifying path exists (and creating if not present): " << chainPath; + fs::create_directories(chainPath); + clog(VerbosityDebug, "statedb") << "Ensuring permissions are set for path: " << chainPath; + DEV_IGNORE_EXCEPTIONS(fs::permissions(chainPath, fs::owner_all)); } try { - std::unique_ptr db = db::DBFactory::create(path / fs::path("state")); - clog(VerbosityTrace, "statedb") << "Opened state DB."; + clog(VerbosityTrace, "statedb") << "Opening state database: " << statePath; + std::unique_ptr db = db::DBFactory::create(statePath); return OverlayDB(std::move(db)); } catch (boost::exception const& ex) { - cwarn << boost::diagnostic_information(ex) << '\n'; - if (!db::isDiskDatabase()) - throw; - else if (fs::space(path / fs::path("state")).available < 1024) - { - cwarn << "Not enough available space found on hard drive. Please free some up and then re-run. Bailing."; - BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace()); - } - else + clog(VerbosityError, "statedb") << "Error opening state database: " << statePath; + if (db::isDiskDatabase()) { - cwarn << - "Database " << - (path / fs::path("state")) << - "already open. You appear to have another instance of ethereum running. Bailing."; - BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); + db::DatabaseStatus const dbStatus = + *boost::get_error_info(ex); + if (fs::space(statePath).available < 1024) + { + clog(VerbosityError, "statedb") + << "Not enough available space found on hard drive. Please free some up and " + "then re-run. Bailing."; + BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace()); + } + else if (dbStatus == db::DatabaseStatus::Corruption) + { + clog(VerbosityError, "statedb") + << "Database corruption detected. Please see the exception for corruption " + "details. Exception: " + << ex.what(); + BOOST_THROW_EXCEPTION(DatabaseCorruption()); + } + else if (dbStatus == db::DatabaseStatus::IOError) + { + clog(VerbosityError, "statedb") << "Database already open. You appear to have " + "another instance of Aleth running."; + BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); + } } + clog(VerbosityError, "statedb") << "Unknown error encountered. Exception details: " + << boost::diagnostic_information(ex); + throw; } } From acf4429dfc96b0bb1fae2ef841f8b41bff868161 Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Sun, 27 Oct 2019 20:54:59 -0700 Subject: [PATCH 12/17] Minor cleanup of BlockChain::open --- libethereum/BlockChain.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index bb8d6f030f2..43d41b56aec 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -194,11 +194,11 @@ void BlockChain::init(ChainParams const& _p) unsigned BlockChain::open(fs::path const& _path, WithExisting _we) { - fs::path const path = _path.empty() ? db::databasePath() : _path; - fs::path const chainPath = path / fs::path(toHex(m_genesisHash.ref().cropped(0, 4))); - fs::path const chainSubPathBlocks = chainPath / fs::path("blocks"); - fs::path const extrasPath = chainPath / fs::path(toString(c_databaseVersion)); - fs::path const extrasSubPathExtras = extrasPath / fs::path("extras"); + auto const path = _path.empty() ? db::databasePath() : _path; + auto const chainPath = path / fs::path(toHex(m_genesisHash.ref().cropped(0, 4))); + auto const chainSubPathBlocks = chainPath / fs::path("blocks"); + auto const extrasPath = chainPath / fs::path(toString(c_databaseVersion)); + auto const extrasSubPathExtras = extrasPath / fs::path("extras"); unsigned lastMinor = c_minorProtocolVersion; if (db::isDiskDatabase()) @@ -206,7 +206,7 @@ unsigned BlockChain::open(fs::path const& _path, WithExisting _we) fs::create_directories(extrasPath); DEV_IGNORE_EXCEPTIONS(fs::permissions(extrasPath, fs::owner_all)); - fs::path const extrasSubPathMinor = extrasPath / fs::path("minor"); + auto const extrasSubPathMinor = extrasPath / fs::path("minor"); bytes const status = contents(extrasSubPathMinor); if (!status.empty()) DEV_IGNORE_EXCEPTIONS(lastMinor = (unsigned)RLP(status)); @@ -237,33 +237,34 @@ unsigned BlockChain::open(fs::path const& _path, WithExisting _we) } catch (db::DatabaseError const& ex) { - fs::path const dbPath = !m_blocksDB.get() ? chainSubPathBlocks : extrasSubPathExtras; + // Determine which database open call failed + auto const dbPath = !m_blocksDB.get() ? chainSubPathBlocks : extrasSubPathExtras; + cerr << "Error opening database: " << dbPath; + if (db::isDiskDatabase()) { - db::DatabaseStatus const dbStatus = - *boost::get_error_info(ex); + db::DatabaseStatus const dbStatus = *boost::get_error_info(ex); if (fs::space(path).available < 1024) { - cerr << "Failed to create database (" << dbPath - << "). Not enough available space found on hard drive. Please free some up " - "and re-run."; + cerr << "Not enough available space found on hard drive. Please free some up and " + "re-run."; BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace()); } else if (dbStatus == db::DatabaseStatus::Corruption) { - cerr << "Database corrupted (" << dbPath << ")"; + cerr << "Database corruption detected. Please see the exception for corruption " + "details. Exception: " + << ex.what(); BOOST_THROW_EXCEPTION(DatabaseCorruption()); } else if (dbStatus == db::DatabaseStatus::IOError) { - cerr << "Database already open (" << dbPath - << "). You appear to have another instance of ethereum running."; + cerr << "Database already open. You appear to have another instance of Aleth running."; BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); } } - - cerr << "Unknown error occurred when creating database (" << dbPath - << "). Exception details: " << ex.what(); + + cerr << "Unknown error occurred. Exception details: " << ex.what(); throw; } From 3015ca050fc05bd22a53c0c38aad233234d80315 Mon Sep 17 00:00:00 2001 From: Andrei Maiboroda Date: Tue, 29 Oct 2019 16:00:15 +0100 Subject: [PATCH 13/17] Use cerror logger for blockchain DB open errors --- libethereum/BlockChain.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 43d41b56aec..83d59592d83 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -239,32 +239,32 @@ unsigned BlockChain::open(fs::path const& _path, WithExisting _we) { // Determine which database open call failed auto const dbPath = !m_blocksDB.get() ? chainSubPathBlocks : extrasSubPathExtras; - cerr << "Error opening database: " << dbPath; + cerror << "Error opening database: " << dbPath; if (db::isDiskDatabase()) { db::DatabaseStatus const dbStatus = *boost::get_error_info(ex); if (fs::space(path).available < 1024) { - cerr << "Not enough available space found on hard drive. Please free some up and " + cerror << "Not enough available space found on hard drive. Please free some up and " "re-run."; BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace()); } else if (dbStatus == db::DatabaseStatus::Corruption) { - cerr << "Database corruption detected. Please see the exception for corruption " + cerror << "Database corruption detected. Please see the exception for corruption " "details. Exception: " << ex.what(); BOOST_THROW_EXCEPTION(DatabaseCorruption()); } else if (dbStatus == db::DatabaseStatus::IOError) { - cerr << "Database already open. You appear to have another instance of Aleth running."; + cerror << "Database already open. You appear to have another instance of Aleth running."; BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen()); } } - cerr << "Unknown error occurred. Exception details: " << ex.what(); + cerror << "Unknown error occurred. Exception details: " << ex.what(); throw; } From 5e3dcadbcd23f190ec6448dfa7d5aff0345a60dd Mon Sep 17 00:00:00 2001 From: Andrei Maiboroda Date: Tue, 29 Oct 2019 16:08:15 +0100 Subject: [PATCH 14/17] Fix outputting exception diagnostic info --- libethereum/State.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 37a94a938ad..c6b753c68c8 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -87,7 +87,7 @@ OverlayDB State::openDB(fs::path const& _basePath, h256 const& _genesisHash, Wit clog(VerbosityError, "statedb") << "Database corruption detected. Please see the exception for corruption " "details. Exception: " - << ex.what(); + << boost::diagnostic_information(ex); BOOST_THROW_EXCEPTION(DatabaseCorruption()); } else if (dbStatus == db::DatabaseStatus::IOError) From 7b5adecb6c1e97a3dab4c3bb8d498f650cea1886 Mon Sep 17 00:00:00 2001 From: Andrei Maiboroda Date: Tue, 29 Oct 2019 19:17:30 +0100 Subject: [PATCH 15/17] Convert tabs to spaces in ChainParams --- libethereum/ChainParams.h | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/libethereum/ChainParams.h b/libethereum/ChainParams.h index 33050a55ab5..b37e9c3b479 100644 --- a/libethereum/ChainParams.h +++ b/libethereum/ChainParams.h @@ -20,32 +20,32 @@ class SealEngineFace; struct ChainParams: public ChainOperationParams { - ChainParams(); - ChainParams(ChainParams const& /*_org*/) = default; - ChainParams(std::string const& _s, h256 const& _stateRoot = h256()); - ChainParams(bytes const& _genesisRLP, AccountMap const& _state) { populateFromGenesis(_genesisRLP, _state); } - ChainParams(std::string const& _json, bytes const& _genesisRLP, AccountMap const& _state): ChainParams(_json) { populateFromGenesis(_genesisRLP, _state); } - - SealEngineFace* createSealEngine(); - - /// Genesis params. - h256 parentHash = h256(); - Address author = Address(); - u256 difficulty = 1; - u256 gasLimit = 1 << 31; - u256 gasUsed = 0; - u256 timestamp = 0; - bytes extraData; - mutable h256 stateRoot; ///< Only pre-populate if known equivalent to genesisState's root. If they're different Bad Things Will Happen. - AccountMap genesisState; - - unsigned sealFields = 0; - bytes sealRLP; - - h256 calculateStateRoot(bool _force = false) const; - - /// Genesis block info. - bytes genesisBlock() const; + ChainParams(); + ChainParams(ChainParams const& /*_org*/) = default; + ChainParams(std::string const& _s, h256 const& _stateRoot = h256()); + ChainParams(bytes const& _genesisRLP, AccountMap const& _state) { populateFromGenesis(_genesisRLP, _state); } + ChainParams(std::string const& _json, bytes const& _genesisRLP, AccountMap const& _state): ChainParams(_json) { populateFromGenesis(_genesisRLP, _state); } + + SealEngineFace* createSealEngine(); + + /// Genesis params. + h256 parentHash = h256(); + Address author = Address(); + u256 difficulty = 1; + u256 gasLimit = 1 << 31; + u256 gasUsed = 0; + u256 timestamp = 0; + bytes extraData; + mutable h256 stateRoot; ///< Only pre-populate if known equivalent to genesisState's root. If they're different Bad Things Will Happen. + AccountMap genesisState; + + unsigned sealFields = 0; + bytes sealRLP; + + h256 calculateStateRoot(bool _force = false) const; + + /// Genesis block info. + bytes genesisBlock() const; /// load config ChainParams loadConfig(std::string const& _json, h256 const& _stateRoot = {}, From 6c9ab13a488440ee735888ee3cdb9922ad37004f Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Thu, 31 Oct 2019 18:56:17 -0700 Subject: [PATCH 16/17] Address PR feedback Don't save block bytes in block and log "block not found" as warning rather than error --- libethereum/Block.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index 84fa260ccb5..b5a850cd6a7 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -140,15 +140,14 @@ void Block::populateFromChain(BlockChain const& _bc, h256 const& _h) { if (!_bc.isKnown(_h)) { - cerr << "Invalid block given for state population: " << _h; + cwarn << "Invalid block given for state population: " << _h; BOOST_THROW_EXCEPTION(BlockNotFound() << errinfo_target(_h)); } auto const& blockBytes = _bc.block(_h); - m_currentBytes = blockBytes; // Set block headers - auto const& blockHeader = BlockHeader{blockBytes}; + auto const blockHeader = BlockHeader{blockBytes}; m_currentBlock = blockHeader; if (blockHeader.number()) From 155cd8a743916ca1c6b9e22843bd3de347011809 Mon Sep 17 00:00:00 2001 From: Nils-Erik Frantzell Date: Fri, 1 Nov 2019 21:22:53 -0700 Subject: [PATCH 17/17] Remove unnecessary unseal function Also don't populate RLP representation of txs and uncles in Block::populateFromChain since they are only useful during mining. --- libethereum/Block.cpp | 2 -- libethereum/Block.h | 4 ---- libethereum/Client.cpp | 1 - 3 files changed, 7 deletions(-) diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index b5a850cd6a7..d4f0b48b4be 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -182,8 +182,6 @@ void Block::populateFromChain(BlockChain const& _bc, h256 const& _h) } m_receipts = _bc.receipts(_h).receipts; - m_currentTxs = txListRLP.data().toBytes(); - m_currentUncles = blockRLP[2].data().toBytes(); m_author = blockHeader.author(); m_committedToSeal = false; diff --git a/libethereum/Block.h b/libethereum/Block.h index d93ed24fb06..ac55b6d5675 100644 --- a/libethereum/Block.h +++ b/libethereum/Block.h @@ -243,10 +243,6 @@ class Block /// @returns true if sealed - in this case you can no longer append transactions. bool isSealed() const { return !m_currentBytes.empty(); } - /// Clears the block bytes - typically used in cases where we want to mutate a sealed - /// block's state (e.g. eth_call) - void unseal() { m_currentBytes.clear(); } - /// Get the complete current block, including valid nonce. /// Only valid when isSealed() is true. bytes const& blockData() const { return m_currentBytes; } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 3876aa5014c..371f21730d2 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -901,7 +901,6 @@ ExecutionResult Client::call(Address const& _from, u256 _value, Address _dest, b try { Block temp = blockByNumber(_blockNumber); - temp.unseal(); // Unseal block since we're going to be executing a transaction u256 nonce = max(temp.transactionsFrom(_from), m_tq.maxNonce(_from)); u256 gas = _gas == Invalid256 ? gasLimitRemaining() : _gas; u256 gasPrice = _gasPrice == Invalid256 ? gasBidPrice() : _gasPrice;