diff --git a/CMakeLists.txt b/CMakeLists.txt index e3d689458..2b47d0351 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,9 +239,6 @@ include(EthExecutableHelper) message("creating build info...") createBuildInfo() -set(DB_INCLUDE_DIRS ${LEVELDB_INCLUDE_DIRS}) -set(DB_LIBRARIES ${LEVELDB_LIBRARIES}) - add_subdirectory(libdevcore) if (MINER) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index ff801ca57..b02c7ae4b 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -45,10 +45,6 @@ find_package (CryptoPP 5.6.2 REQUIRED) message(" - CryptoPP header: ${CRYPTOPP_INCLUDE_DIRS}") message(" - CryptoPP lib : ${CRYPTOPP_LIBRARIES}") -find_package (LevelDB REQUIRED) -message(" - LevelDB header: ${LEVELDB_INCLUDE_DIRS}") -message(" - LevelDB lib: ${LEVELDB_LIBRARIES}") - # TODO the Jsoncpp package does not yet check for correct version number find_package (Jsoncpp 0.60 REQUIRED) message(" - Jsoncpp header: ${JSONCPP_INCLUDE_DIRS}") diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake deleted file mode 100644 index 1c3465665..000000000 --- a/cmake/FindLevelDB.cmake +++ /dev/null @@ -1,49 +0,0 @@ -# Find leveldb -# -# Find the leveldb includes and library -# -# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH -# -# This module defines -# LEVELDB_INCLUDE_DIRS, where to find header, etc. -# LEVELDB_LIBRARIES, the libraries needed to use leveldb. -# LEVELDB_FOUND, If false, do not try to use leveldb. - -# only look in default directories -find_path( - LEVELDB_INCLUDE_DIR - NAMES leveldb/db.h - DOC "leveldb include dir" -) - -find_library( - LEVELDB_LIBRARY - NAMES leveldb - DOC "leveldb library" -) - -set(LEVELDB_INCLUDE_DIRS ${LEVELDB_INCLUDE_DIR}) -set(LEVELDB_LIBRARIES ${LEVELDB_LIBRARY}) - -# debug library on windows -# same naming convention as in qt (appending debug library with d) -# boost is using the same "hack" as us with "optimized" and "debug" -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - - find_library( - LEVELDB_LIBRARY_DEBUG - NAMES leveldbd - DOC "leveldb debug library" - ) - - set(LEVELDB_LIBRARIES optimized ${LEVELDB_LIBRARIES} debug ${LEVELDB_LIBRARY_DEBUG}) - -endif() - -# handle the QUIETLY and REQUIRED arguments and set LEVELDB_FOUND to TRUE -# if all listed variables are TRUE, hide their existence from configuration view -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(leveldb DEFAULT_MSG - LEVELDB_INCLUDE_DIR LEVELDB_LIBRARY) -mark_as_advanced (LEVELDB_INCLUDE_DIR LEVELDB_LIBRARY) - diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 9ed3c4ab3..1ee3b7789 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -5,20 +5,18 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) -include_directories(${DB_INCLUDE_DIRS}) set(EXECUTABLE devcore) file(GLOB HEADERS "*.h") -add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) +add_library(devcore ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_RANDOM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${DB_LIBRARIES}) # transitive dependencies for windows executables if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") diff --git a/libdevcore/MemoryDB.cpp b/libdevcore/MemoryDB.cpp index f71931bdd..5c3a6ec14 100644 --- a/libdevcore/MemoryDB.cpp +++ b/libdevcore/MemoryDB.cpp @@ -19,7 +19,7 @@ * @date 2014 */ -#include +#include "Common.h" #include "MemoryDB.h" using namespace std; using namespace dev; diff --git a/libdevcore/SHA3.h b/libdevcore/SHA3.h index 7be2367e9..71b02cb2c 100644 --- a/libdevcore/SHA3.h +++ b/libdevcore/SHA3.h @@ -24,8 +24,8 @@ #pragma once #include -#include -#include +#include "FixedHash.h" +#include "vector_ref.h" namespace dev { diff --git a/libdevcore/TrieDB.cpp b/libdevcore/TrieDB.cpp deleted file mode 100644 index 719bd74ad..000000000 --- a/libdevcore/TrieDB.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file TrieDB.cpp - * @author Gav Wood - * @date 2014 - */ - -#include -#include "TrieDB.h" -using namespace std; -using namespace dev; - -h256 const dev::c_shaNull = sha3(rlp("")); -h256 const dev::EmptyTrie = sha3(rlp("")); - -const char* TrieDBChannel::name() { return "-T-"; } diff --git a/libdevcore/TrieDB.h b/libdevcore/TrieDB.h deleted file mode 100644 index 0fb7cba9f..000000000 --- a/libdevcore/TrieDB.h +++ /dev/null @@ -1,1224 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file TrieDB.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include "db.h" -#include "Common.h" -#include "Log.h" -#include "Exceptions.h" -#include "SHA3.h" -#include "MemoryDB.h" -#include "TrieCommon.h" - -namespace dev -{ - -struct TrieDBChannel: public LogChannel { static const char* name(); static const int verbosity = 17; }; -#define tdebug clog(TrieDBChannel) - -struct InvalidTrie: virtual dev::Exception {}; -extern const h256 c_shaNull; -extern const h256 EmptyTrie; - -enum class Verification { - Skip, - Normal -}; - -/** - * @brief Merkle Patricia Tree "Trie": a modifed base-16 Radix tree. - * This version uses a database backend. - * Usage: - * @code - * GenericTrieDB t(&myDB); - * assert(t.isNull()); - * t.init(); - * assert(t.isEmpty()); - * t.insert(x, y); - * assert(t.at(x) == y.toString()); - * t.remove(x); - * assert(t.isEmpty()); - * @endcode - */ -template -class GenericTrieDB -{ -public: - using DB = _DB; - - explicit GenericTrieDB(DB* _db = nullptr): m_db(_db) {} - GenericTrieDB(DB* _db, h256 const& _root, Verification _v = Verification::Normal) { open(_db, _root, _v); } - ~GenericTrieDB() {} - - void open(DB* _db) { m_db = _db; } - void open(DB* _db, h256 const& _root, Verification _v = Verification::Normal) { m_db = _db; setRoot(_root, _v); } - - void init() { setRoot(forceInsertNode(&RLPNull)); assert(node(m_root).size()); } - - void setRoot(h256 const& _root, Verification _v = Verification::Normal) - { - m_root = _root; - if (_v == Verification::Normal) - { - if (m_root == c_shaNull && !m_db->exists(m_root)) - init(); - } - /*std::cout << "Setting root to " << _root << " (patched to " << m_root << ")" << std::endl;*/ -#if ETH_DEBUG - if (_v == Verification::Normal) -#endif - if (!node(m_root).size()) - BOOST_THROW_EXCEPTION(RootNotFound()); - } - - /// True if the trie is uninitialised (i.e. that the DB doesn't contain the root node). - bool isNull() const { return !node(m_root).size(); } - /// True if the trie is initialised but empty (i.e. that the DB contains the root node which is empty). - bool isEmpty() const { return m_root == c_shaNull && node(m_root).size(); } - - h256 const& root() const { if (node(m_root).empty()) BOOST_THROW_EXCEPTION(BadRoot(m_root)); /*std::cout << "Returning root as " << ret << " (really " << m_root << ")" << std::endl;*/ return m_root; } // patch the root in the case of the empty trie. TODO: handle this properly. - - std::string at(bytes const& _key) const { return at(&_key); } - std::string at(bytesConstRef _key) const; - void insert(bytes const& _key, bytes const& _value) { insert(&_key, &_value); } - void insert(bytesConstRef _key, bytes const& _value) { insert(_key, &_value); } - void insert(bytes const& _key, bytesConstRef _value) { insert(&_key, _value); } - void insert(bytesConstRef _key, bytesConstRef _value); - void remove(bytes const& _key) { remove(&_key); } - void remove(bytesConstRef _key); - bool contains(bytes const& _key) { return contains(&_key); } - bool contains(bytesConstRef _key) { return !at(_key).empty(); } - - class iterator - { - public: - using value_type = std::pair; - - iterator() {} - explicit iterator(GenericTrieDB const* _db); - iterator(GenericTrieDB const* _db, bytesConstRef _key); - - iterator& operator++() { next(); return *this; } - - value_type operator*() const { return at(); } - value_type operator->() const { return at(); } - - bool operator==(iterator const& _c) const { return _c.m_trail == m_trail; } - bool operator!=(iterator const& _c) const { return _c.m_trail != m_trail; } - - value_type at() const; - - private: - void next(); - void next(NibbleSlice _key); - - struct Node - { - std::string rlp; - std::string key; // as hexPrefixEncoding. - byte child; // 255 -> entering, 16 -> actually at the node, 17 -> exiting, 0-15 -> actual children. - - // 255 -> 16 -> 0 -> 1 -> ... -> 15 -> 17 - - void setChild(unsigned _i) { child = _i; } - void setFirstChild() { child = 16; } - void incrementChild() { child = child == 16 ? 0 : child == 15 ? 17 : (child + 1); } - - bool operator==(Node const& _c) const { return rlp == _c.rlp && key == _c.key && child == _c.child; } - bool operator!=(Node const& _c) const { return !operator==(_c); } - }; - - protected: - std::vector m_trail; - GenericTrieDB const* m_that; - }; - - iterator begin() const { return iterator(this); } - iterator end() const { return iterator(); } - - iterator lower_bound(bytesConstRef _key) const { return iterator(this, _key); } - - /// Used for debugging, scans the whole trie. - void descendKey(h256 const& _k, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent = 0) const - { - _keyMask.erase(_k); - if (_k == m_root && _k == c_shaNull) // root allowed to be empty - return; - descendList(RLP(node(_k)), _keyMask, _wasExt, _out, _indent); // if not, it must be a list - } - - /// Used for debugging, scans the whole trie. - void descendEntry(RLP const& _r, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent) const - { - if (_r.isData() && _r.size() == 32) - descendKey(_r.toHash(), _keyMask, _wasExt, _out, _indent); - else if (_r.isList()) - descendList(_r, _keyMask, _wasExt, _out, _indent); - else - BOOST_THROW_EXCEPTION(InvalidTrie()); - } - - /// Used for debugging, scans the whole trie. - void descendList(RLP const& _r, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent) const - { - if (_r.isList() && _r.itemCount() == 2 && (!_wasExt || _out)) - { - if (_out) - (*_out) << std::string(_indent * 2, ' ') << (_wasExt ? "!2 " : "2 ") << sha3(_r.data()) << ": " << _r << "\n"; - if (!isLeaf(_r)) // don't go down leaves - descendEntry(_r[1], _keyMask, true, _out, _indent + 1); - } - else if (_r.isList() && _r.itemCount() == 17) - { - if (_out) - (*_out) << std::string(_indent * 2, ' ') << "17 " << sha3(_r.data()) << ": " << _r << "\n"; - for (unsigned i = 0; i < 16; ++i) - if (!_r[i].isEmpty()) // 16 branches are allowed to be empty - descendEntry(_r[i], _keyMask, false, _out, _indent + 1); - } - else - BOOST_THROW_EXCEPTION(InvalidTrie()); - } - - /// Used for debugging, scans the whole trie. - h256Hash leftOvers(std::ostream* _out = nullptr) const - { - h256Hash k = m_db->keys(); - descendKey(m_root, k, false, _out); - return k; - } - - /// Used for debugging, scans the whole trie. - void debugStructure(std::ostream& _out) const - { - leftOvers(&_out); - } - - /// Used for debugging, scans the whole trie. - /// @param _requireNoLeftOvers if true, requires that all keys are reachable. - bool check(bool _requireNoLeftOvers) const - { - try - { - return leftOvers().empty() || !_requireNoLeftOvers; - } - catch (...) - { - cwarn << boost::current_exception_diagnostic_information(); - return false; - } - } - - /// Get the underlying database. - /// @warning This can be used to bypass the trie code. Don't use these unless you *really* - /// know what you're doing. - DB const* db() const { return m_db; } - DB* db() { return m_db; } - -private: - RLPStream& streamNode(RLPStream& _s, bytes const& _b); - - std::string atAux(RLP const& _here, NibbleSlice _key) const; - - void mergeAtAux(RLPStream& _out, RLP const& _replace, NibbleSlice _key, bytesConstRef _value); - bytes mergeAt(RLP const& _replace, NibbleSlice _k, bytesConstRef _v, bool _inLine = false); - bytes mergeAt(RLP const& _replace, h256 const& _replaceHash, NibbleSlice _k, bytesConstRef _v, bool _inLine = false); - - bool deleteAtAux(RLPStream& _out, RLP const& _replace, NibbleSlice _key); - bytes deleteAt(RLP const& _replace, NibbleSlice _k); - - // in: null (DEL) -- OR -- [_k, V] (DEL) - // out: [_k, _s] - // -- OR -- - // in: [V0, ..., V15, S16] (DEL) AND _k == {} - // out: [V0, ..., V15, _s] - bytes place(RLP const& _orig, NibbleSlice _k, bytesConstRef _s); - - // in: [K, S] (DEL) - // out: null - // -- OR -- - // in: [V0, ..., V15, S] (DEL) - // out: [V0, ..., V15, null] - bytes remove(RLP const& _orig); - - // in: [K1 & K2, V] (DEL) : nibbles(K1) == _s, 0 < _s <= nibbles(K1 & K2) - // out: [K1, H] ; [K2, V] => H (INS) (being [K1, [K2, V]] if necessary) - bytes cleve(RLP const& _orig, unsigned _s); - - // in: [K1, H] (DEL) ; H <= [K2, V] (DEL) (being [K1, [K2, V]] (DEL) if necessary) - // out: [K1 & K2, V] - bytes graft(RLP const& _orig); - - // in: [V0, ... V15, S] (DEL) - // out1: [k{i}, Vi] where i < 16 - // out2: [k{}, S] where i == 16 - bytes merge(RLP const& _orig, byte _i); - - // in: [k{}, S] (DEL) - // out: [null ** 16, S] - // -- OR -- - // in: [k{i}, N] (DEL) - // out: [null ** i, N, null ** (16 - i)] - // -- OR -- - // in: [k{i}K, V] (DEL) - // out: [null ** i, H, null ** (16 - i)] ; [K, V] => H (INS) (being [null ** i, [K, V], null ** (16 - i)] if necessary) - bytes branch(RLP const& _orig); - - bool isTwoItemNode(RLP const& _n) const; - std::string deref(RLP const& _n) const; - - std::string node(h256 const& _h) const { return m_db->lookup(_h); } - - // These are low-level node insertion functions that just go straight through into the DB. - h256 forceInsertNode(bytesConstRef _v) { auto h = sha3(_v); forceInsertNode(h, _v); return h; } - void forceInsertNode(h256 const& _h, bytesConstRef _v) { m_db->insert(_h, _v); } - void forceKillNode(h256 const& _h) { m_db->kill(_h); } - - // This are semantically-aware node insertion functions that only kills when the node's - // data is < 32 bytes. It can safely be used when pruning the trie but won't work correctly - // for the special case of the root (which is always looked up via a hash). In that case, - // use forceKillNode(). - void killNode(RLP const& _d) { if (_d.data().size() >= 32) forceKillNode(sha3(_d.data())); } - void killNode(RLP const& _d, h256 const& _h) { if (_d.data().size() >= 32) forceKillNode(_h); } - - h256 m_root; - DB* m_db = nullptr; -}; - -template -std::ostream& operator<<(std::ostream& _out, GenericTrieDB const& _db) -{ - for (auto const& i: _db) - _out << escaped(i.first.toString(), false) << ": " << escaped(i.second.toString(), false) << std::endl; - return _out; -} - -/** - * Different view on a GenericTrieDB that can use different key types. - */ -template -class SpecificTrieDB: public Generic -{ -public: - using DB = typename Generic::DB; - using KeyType = _KeyType; - - SpecificTrieDB(DB* _db = nullptr): Generic(_db) {} - SpecificTrieDB(DB* _db, h256 _root, Verification _v = Verification::Normal): Generic(_db, _root, _v) {} - - std::string operator[](KeyType _k) const { return at(_k); } - - bool contains(KeyType _k) const { return Generic::contains(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } - std::string at(KeyType _k) const { return Generic::at(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } - void insert(KeyType _k, bytesConstRef _value) { Generic::insert(bytesConstRef((byte const*)&_k, sizeof(KeyType)), _value); } - void insert(KeyType _k, bytes const& _value) { insert(_k, bytesConstRef(&_value)); } - void remove(KeyType _k) { Generic::remove(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } - - class iterator: public Generic::iterator - { - public: - using Super = typename Generic::iterator; - using value_type = std::pair; - - iterator() {} - iterator(Generic const* _db): Super(_db) {} - iterator(Generic const* _db, bytesConstRef _k): Super(_db, _k) {} - - value_type operator*() const { return at(); } - value_type operator->() const { return at(); } - - value_type at() const; - }; - - iterator begin() const { return this; } - iterator end() const { return iterator(); } - iterator lower_bound(KeyType _k) const { return iterator(this, bytesConstRef((byte const*)&_k, sizeof(KeyType))); } -}; - -template -std::ostream& operator<<(std::ostream& _out, SpecificTrieDB const& _db) -{ - for (auto const& i: _db) - _out << i.first << ": " << escaped(i.second.toString(), false) << std::endl; - return _out; -} - -template -class HashedGenericTrieDB: private SpecificTrieDB, h256> -{ - using Super = SpecificTrieDB, h256>; - -public: - using DB = _DB; - - HashedGenericTrieDB(DB* _db = nullptr): Super(_db) {} - HashedGenericTrieDB(DB* _db, h256 _root, Verification _v = Verification::Normal): Super(_db, _root, _v) {} - - using Super::open; - using Super::init; - using Super::setRoot; - - /// True if the trie is uninitialised (i.e. that the DB doesn't contain the root node). - using Super::isNull; - /// True if the trie is initialised but empty (i.e. that the DB contains the root node which is empty). - using Super::isEmpty; - - using Super::root; - using Super::db; - - using Super::leftOvers; - using Super::check; - using Super::debugStructure; - - std::string at(bytesConstRef _key) const { return Super::at(sha3(_key)); } - bool contains(bytesConstRef _key) { return Super::contains(sha3(_key)); } - void insert(bytesConstRef _key, bytesConstRef _value) { Super::insert(sha3(_key), _value); } - void remove(bytesConstRef _key) { Super::remove(sha3(_key)); } - - // empty from the PoV of the iterator interface; still need a basic iterator impl though. - class iterator - { - public: - using value_type = std::pair; - - iterator() {} - iterator(HashedGenericTrieDB const*) {} - iterator(HashedGenericTrieDB const*, bytesConstRef) {} - - iterator& operator++() { return *this; } - value_type operator*() const { return value_type(); } - value_type operator->() const { return value_type(); } - - bool operator==(iterator const&) const { return true; } - bool operator!=(iterator const&) const { return false; } - - value_type at() const { return value_type(); } - }; - iterator begin() const { return iterator(); } - iterator end() const { return iterator(); } - iterator lower_bound(bytesConstRef) const { return iterator(); } -}; - -// Hashed & Hash-key mapping -template -class FatGenericTrieDB: private SpecificTrieDB, h256> -{ - using Super = SpecificTrieDB, h256>; - -public: - using DB = _DB; - FatGenericTrieDB(DB* _db = nullptr): Super(_db) {} - FatGenericTrieDB(DB* _db, h256 _root, Verification _v = Verification::Normal): Super(_db, _root, _v) {} - - using Super::init; - using Super::isNull; - using Super::isEmpty; - using Super::root; - using Super::leftOvers; - using Super::check; - using Super::open; - using Super::setRoot; - using Super::db; - using Super::debugStructure; - - std::string at(bytesConstRef _key) const { return Super::at(sha3(_key)); } - bool contains(bytesConstRef _key) { return Super::contains(sha3(_key)); } - void insert(bytesConstRef _key, bytesConstRef _value) - { - h256 hash = sha3(_key); - Super::insert(hash, _value); - Super::db()->insertAux(hash, _key); - } - - void remove(bytesConstRef _key) { Super::remove(sha3(_key)); } - - //friend class iterator; - - class iterator : public GenericTrieDB<_DB>::iterator - { - public: - using Super = typename GenericTrieDB<_DB>::iterator; - - iterator() { } - iterator(FatGenericTrieDB const* _trie): Super(_trie) { } - - typename Super::value_type at() const - { - auto hashed = Super::at(); - m_key = static_cast(Super::m_that)->db()->lookupAux(h256(hashed.first)); - return std::make_pair(&m_key, std::move(hashed.second)); - } - - private: - mutable bytes m_key; - }; - iterator begin() const { return iterator(); } - iterator end() const { return iterator(); } -}; - -template using TrieDB = SpecificTrieDB, KeyType>; -template using SecureTrieDB = SpecificTrieDB, KeyType>; - -} - -// Template implementations... -namespace dev -{ - -template GenericTrieDB::iterator::iterator(GenericTrieDB const* _db) -{ - m_that = _db; - m_trail.push_back({_db->node(_db->m_root), std::string(1, '\0'), 255}); // one null byte is the HPE for the empty key. - next(); -} - -template GenericTrieDB::iterator::iterator(GenericTrieDB const* _db, bytesConstRef _fullKey) -{ - m_that = _db; - m_trail.push_back({_db->node(_db->m_root), std::string(1, '\0'), 255}); // one null byte is the HPE for the empty key. - next(_fullKey); -} - -template typename GenericTrieDB::iterator::value_type GenericTrieDB::iterator::at() const -{ - assert(m_trail.size()); - Node const& b = m_trail.back(); - assert(b.key.size()); - assert(!(b.key[0] & 0x10)); // should be an integer number of bytes (i.e. not an odd number of nibbles). - - RLP rlp(b.rlp); - return std::make_pair(bytesConstRef(b.key).cropped(1), rlp[rlp.itemCount() == 2 ? 1 : 16].payload()); -} - -template void GenericTrieDB::iterator::next(NibbleSlice _key) -{ - NibbleSlice k = _key; - while (true) - { - if (m_trail.empty()) - { - m_that = nullptr; - return; - } - - Node const& b = m_trail.back(); - RLP rlp(b.rlp); - - if (m_trail.back().child == 255) - { - // Entering. Look for first... - if (rlp.isEmpty()) - { - // Kill our search as soon as we hit an empty node. - k.clear(); - m_trail.pop_back(); - continue; - } - if (!rlp.isList() || (rlp.itemCount() != 2 && rlp.itemCount() != 17)) - { -#if ETH_PARANOIA - cwarn << "BIG FAT ERROR. STATE TRIE CORRUPTED!!!!!"; - cwarn << b.rlp.size() << toHex(b.rlp); - cwarn << rlp; - auto c = rlp.itemCount(); - cwarn << c; - BOOST_THROW_EXCEPTION(InvalidTrie()); -#else - m_that = nullptr; - return; -#endif - } - if (rlp.itemCount() == 2) - { - // Just turn it into a valid Branch - auto keyOfRLP = keyOf(rlp); - - // TODO: do something different depending on how keyOfRLP compares to k.mid(0, std::min(k.size(), keyOfRLP.size())); - // if == all is good - continue descent. - // if > discard key and continue descent. - // if < discard key and skip node. - - if (!k.contains(keyOfRLP)) - { - if (!k.isEarlierThan(keyOfRLP)) - { - k.clear(); - m_trail.pop_back(); - continue; - } - k.clear(); - } - - k = k.mid(std::min(k.size(), keyOfRLP.size())); - m_trail.back().key = hexPrefixEncode(keyOf(m_trail.back().key), keyOfRLP, false); - if (isLeaf(rlp)) - { - // leaf - exit now. - if (k.empty()) - { - m_trail.back().child = 0; - return; - } - // Still data in key we're supposed to be looking for when we're at a leaf. Go for next one. - k.clear(); - m_trail.pop_back(); - continue; - } - - // enter child. - m_trail.back().rlp = m_that->deref(rlp[1]); - // no need to set .child as 255 - it's already done. - continue; - } - else - { - // Already a branch - look for first valid. - if (k.size()) - { - m_trail.back().setChild(k[0]); - k = k.mid(1); - } - else - m_trail.back().setChild(16); - // run through to... - } - } - else - { - // Continuing/exiting. Look for next... - if (!(rlp.isList() && rlp.itemCount() == 17)) - { - k.clear(); - m_trail.pop_back(); - continue; - } - // else run through to... - m_trail.back().incrementChild(); - } - - // ...here. should only get here if we're a list. - assert(rlp.isList() && rlp.itemCount() == 17); - for (;; m_trail.back().incrementChild()) - if (m_trail.back().child == 17) - { - // finished here. - k.clear(); - m_trail.pop_back(); - break; - } - else if (!rlp[m_trail.back().child].isEmpty()) - { - if (m_trail.back().child == 16) - return; // have a value at this node - exit now. - else - { - // lead-on to another node - enter child. - // fixed so that Node passed into push_back is constructed *before* m_trail is potentially resized (which invalidates back and rlp) - Node const& back = m_trail.back(); - m_trail.push_back(Node{ - m_that->deref(rlp[back.child]), - hexPrefixEncode(keyOf(back.key), NibbleSlice(bytesConstRef(&back.child, 1), 1), false), - 255 - }); - break; - } - } - else - k.clear(); - } -} - -template void GenericTrieDB::iterator::next() -{ - while (true) - { - if (m_trail.empty()) - { - m_that = nullptr; - return; - } - - Node const& b = m_trail.back(); - RLP rlp(b.rlp); - - if (m_trail.back().child == 255) - { - // Entering. Look for first... - if (rlp.isEmpty()) - { - m_trail.pop_back(); - continue; - } - if (!(rlp.isList() && (rlp.itemCount() == 2 || rlp.itemCount() == 17))) - { -#if ETH_PARANOIA - cwarn << "BIG FAT ERROR. STATE TRIE CORRUPTED!!!!!"; - cwarn << b.rlp.size() << toHex(b.rlp); - cwarn << rlp; - auto c = rlp.itemCount(); - cwarn << c; - BOOST_THROW_EXCEPTION(InvalidTrie()); -#else - m_that = nullptr; - return; -#endif - } - if (rlp.itemCount() == 2) - { - // Just turn it into a valid Branch - m_trail.back().key = hexPrefixEncode(keyOf(m_trail.back().key), keyOf(rlp), false); - if (isLeaf(rlp)) - { - // leaf - exit now. - m_trail.back().child = 0; - return; - } - - // enter child. - m_trail.back().rlp = m_that->deref(rlp[1]); - // no need to set .child as 255 - it's already done. - continue; - } - else - { - // Already a branch - look for first valid. - m_trail.back().setFirstChild(); - // run through to... - } - } - else - { - // Continuing/exiting. Look for next... - if (!(rlp.isList() && rlp.itemCount() == 17)) - { - m_trail.pop_back(); - continue; - } - // else run through to... - m_trail.back().incrementChild(); - } - - // ...here. should only get here if we're a list. - assert(rlp.isList() && rlp.itemCount() == 17); - for (;; m_trail.back().incrementChild()) - if (m_trail.back().child == 17) - { - // finished here. - m_trail.pop_back(); - break; - } - else if (!rlp[m_trail.back().child].isEmpty()) - { - if (m_trail.back().child == 16) - return; // have a value at this node - exit now. - else - { - // lead-on to another node - enter child. - // fixed so that Node passed into push_back is constructed *before* m_trail is potentially resized (which invalidates back and rlp) - Node const& back = m_trail.back(); - m_trail.push_back(Node{ - m_that->deref(rlp[back.child]), - hexPrefixEncode(keyOf(back.key), NibbleSlice(bytesConstRef(&back.child, 1), 1), false), - 255 - }); - break; - } - } - } -} - -template typename SpecificTrieDB::iterator::value_type SpecificTrieDB::iterator::at() const -{ - auto p = Super::at(); - value_type ret; - assert(p.first.size() == sizeof(KeyType)); - memcpy(&ret.first, p.first.data(), sizeof(KeyType)); - ret.second = p.second; - return ret; -} - -template void GenericTrieDB::insert(bytesConstRef _key, bytesConstRef _value) -{ -#if ETH_PARANOIA - tdebug << "Insert" << toHex(_key.cropped(0, 4)) << "=>" << toHex(_value); -#endif - - std::string rootValue = node(m_root); - assert(rootValue.size()); - bytes b = mergeAt(RLP(rootValue), m_root, NibbleSlice(_key), _value); - - // mergeAt won't attempt to delete the node if it's less than 32 bytes - // However, we know it's the root node and thus always hashed. - // So, if it's less than 32 (and thus should have been deleted but wasn't) then we delete it here. - if (rootValue.size() < 32) - forceKillNode(m_root); - m_root = forceInsertNode(&b); -} - -template std::string GenericTrieDB::at(bytesConstRef _key) const -{ - return atAux(RLP(node(m_root)), _key); -} - -template std::string GenericTrieDB::atAux(RLP const& _here, NibbleSlice _key) const -{ - if (_here.isEmpty() || _here.isNull()) - // not found. - return std::string(); - unsigned itemCount = _here.itemCount(); - assert(_here.isList() && (itemCount == 2 || itemCount == 17)); - if (itemCount == 2) - { - auto k = keyOf(_here); - if (_key == k && isLeaf(_here)) - // reached leaf and it's us - return _here[1].toString(); - else if (_key.contains(k) && !isLeaf(_here)) - // not yet at leaf and it might yet be us. onwards... - return atAux(_here[1].isList() ? _here[1] : RLP(node(_here[1].toHash())), _key.mid(k.size())); - else - // not us. - return std::string(); - } - else - { - if (_key.size() == 0) - return _here[16].toString(); - auto n = _here[_key[0]]; - if (n.isEmpty()) - return std::string(); - else - return atAux(n.isList() ? n : RLP(node(n.toHash())), _key.mid(1)); - } -} - -template bytes GenericTrieDB::mergeAt(RLP const& _orig, NibbleSlice _k, bytesConstRef _v, bool _inLine) -{ - return mergeAt(_orig, sha3(_orig.data()), _k, _v, _inLine); -} - -template bytes GenericTrieDB::mergeAt(RLP const& _orig, h256 const& _origHash, NibbleSlice _k, bytesConstRef _v, bool _inLine) -{ -#if ETH_PARANOIA - tdebug << "mergeAt " << _orig << _k << sha3(_orig.data()); -#endif - - // The caller will make sure that the bytes are inserted properly. - // - This might mean inserting an entry into m_over - // We will take care to ensure that (our reference to) _orig is killed. - - // Empty - just insert here - if (_orig.isEmpty()) - return place(_orig, _k, _v); - - unsigned itemCount = _orig.itemCount(); - assert(_orig.isList() && (itemCount == 2 || itemCount == 17)); - if (itemCount == 2) - { - // pair... - NibbleSlice k = keyOf(_orig); - - // exactly our node - place value in directly. - if (k == _k && isLeaf(_orig)) - return place(_orig, _k, _v); - - // partial key is our key - move down. - if (_k.contains(k) && !isLeaf(_orig)) - { - if (!_inLine) - killNode(_orig, _origHash); - RLPStream s(2); - s.append(_orig[0]); - mergeAtAux(s, _orig[1], _k.mid(k.size()), _v); - return s.out(); - } - - auto sh = _k.shared(k); -// std::cout << _k << " sh " << k << " = " << sh << std::endl; - if (sh) - { - // shared stuff - cleve at disagreement. - auto cleved = cleve(_orig, sh); - return mergeAt(RLP(cleved), _k, _v, true); - } - else - { - // nothing shared - branch - auto branched = branch(_orig); - return mergeAt(RLP(branched), _k, _v, true); - } - } - else - { - // branch... - - // exactly our node - place value. - if (_k.size() == 0) - return place(_orig, _k, _v); - - // Kill the node. - if (!_inLine) - killNode(_orig, _origHash); - - // not exactly our node - delve to next level at the correct index. - byte n = _k[0]; - RLPStream r(17); - for (byte i = 0; i < 17; ++i) - if (i == n) - mergeAtAux(r, _orig[i], _k.mid(1), _v); - else - r.append(_orig[i]); - return r.out(); - } - -} - -template void GenericTrieDB::mergeAtAux(RLPStream& _out, RLP const& _orig, NibbleSlice _k, bytesConstRef _v) -{ -#if ETH_PARANOIA || !ETH_TRUE - tdebug << "mergeAtAux " << _orig << _k << sha3(_orig.data()) << ((_orig.isData() && _orig.size() <= 32) ? _orig.toHash().abridged() : std::string()); -#endif - - RLP r = _orig; - std::string s; - // _orig is always a segment of a node's RLP - removing it alone is pointless. However, if may be a hash, in which case we deref and we know it is removable. - bool isRemovable = false; - if (!r.isList() && !r.isEmpty()) - { - s = node(_orig.toHash()); - r = RLP(s); - assert(!r.isNull()); - isRemovable = true; - } - bytes b = mergeAt(r, _k, _v, !isRemovable); - streamNode(_out, b); -} - -template void GenericTrieDB::remove(bytesConstRef _key) -{ -#if ETH_PARANOIA - tdebug << "Remove" << toHex(_key.cropped(0, 4).toBytes()); -#endif - - std::string rv = node(m_root); - bytes b = deleteAt(RLP(rv), NibbleSlice(_key)); - if (b.size()) - { - if (rv.size() < 32) - forceKillNode(m_root); - m_root = forceInsertNode(&b); - } -} - -template bool GenericTrieDB::isTwoItemNode(RLP const& _n) const -{ - return (_n.isData() && RLP(node(_n.toHash())).itemCount() == 2) - || (_n.isList() && _n.itemCount() == 2); -} - -template std::string GenericTrieDB::deref(RLP const& _n) const -{ - return _n.isList() ? _n.data().toString() : node(_n.toHash()); -} - -template bytes GenericTrieDB::deleteAt(RLP const& _orig, NibbleSlice _k) -{ -#if ETH_PARANOIA - tdebug << "deleteAt " << _orig << _k << sha3(_orig.data()); -#endif - - // The caller will make sure that the bytes are inserted properly. - // - This might mean inserting an entry into m_over - // We will take care to ensure that (our reference to) _orig is killed. - - // Empty - not found - no change. - if (_orig.isEmpty()) - return bytes(); - - assert(_orig.isList() && (_orig.itemCount() == 2 || _orig.itemCount() == 17)); - if (_orig.itemCount() == 2) - { - // pair... - NibbleSlice k = keyOf(_orig); - - // exactly our node - return null. - if (k == _k && isLeaf(_orig)) - { - killNode(_orig); - return RLPNull; - } - - // partial key is our key - move down. - if (_k.contains(k)) - { - RLPStream s; - s.appendList(2) << _orig[0]; - if (!deleteAtAux(s, _orig[1], _k.mid(k.size()))) - return bytes(); - killNode(_orig); - RLP r(s.out()); - if (isTwoItemNode(r[1])) - return graft(r); - return s.out(); - } - else - // not found - no change. - return bytes(); - } - else - { - // branch... - - // exactly our node - remove and rejig. - if (_k.size() == 0 && !_orig[16].isEmpty()) - { - // Kill the node. - killNode(_orig); - - byte used = uniqueInUse(_orig, 16); - if (used != 255) - if (isTwoItemNode(_orig[used])) - { - auto merged = merge(_orig, used); - return graft(RLP(merged)); - } - else - return merge(_orig, used); - else - { - RLPStream r(17); - for (byte i = 0; i < 16; ++i) - r << _orig[i]; - r << ""; - return r.out(); - } - } - else - { - // not exactly our node - delve to next level at the correct index. - RLPStream r(17); - byte n = _k[0]; - for (byte i = 0; i < 17; ++i) - if (i == n) - if (!deleteAtAux(r, _orig[i], _k.mid(1))) // bomb out if the key didn't turn up. - return bytes(); - else {} - else - r << _orig[i]; - - // Kill the node. - killNode(_orig); - - // check if we ended up leaving the node invalid. - RLP rlp(r.out()); - byte used = uniqueInUse(rlp, 255); - if (used == 255) // no - all ok. - return r.out(); - - // yes; merge - if (isTwoItemNode(rlp[used])) - { - auto merged = merge(rlp, used); - return graft(RLP(merged)); - } - else - return merge(rlp, used); - } - } - -} - -template bool GenericTrieDB::deleteAtAux(RLPStream& _out, RLP const& _orig, NibbleSlice _k) -{ -#if ETH_PARANOIA || !ETH_TRUE - tdebug << "deleteAtAux " << _orig << _k << sha3(_orig.data()) << ((_orig.isData() && _orig.size() <= 32) ? _orig.toHash().abridged() : std::string()); -#endif - - bytes b = _orig.isEmpty() ? bytes() : deleteAt(_orig.isList() ? _orig : RLP(node(_orig.toHash())), _k); - - if (!b.size()) // not found - no change. - return false; - -/* if (_orig.isList()) - killNode(_orig); - else - killNode(_orig.toHash());*/ - - streamNode(_out, b); - return true; -} - -template bytes GenericTrieDB::place(RLP const& _orig, NibbleSlice _k, bytesConstRef _s) -{ -#if ETH_PARANOIA - tdebug << "place " << _orig << _k; -#endif - - killNode(_orig); - if (_orig.isEmpty()) - return rlpList(hexPrefixEncode(_k, true), _s); - - assert(_orig.isList() && (_orig.itemCount() == 2 || _orig.itemCount() == 17)); - if (_orig.itemCount() == 2) - return rlpList(_orig[0], _s); - - auto s = RLPStream(17); - for (unsigned i = 0; i < 16; ++i) - s << _orig[i]; - s << _s; - return s.out(); -} - -// in1: [K, S] (DEL) -// out1: null -// in2: [V0, ..., V15, S] (DEL) -// out2: [V0, ..., V15, null] iff exists i: !!Vi -- OR -- null otherwise -template bytes GenericTrieDB::remove(RLP const& _orig) -{ -#if ETH_PARANOIA - tdebug << "kill " << _orig; -#endif - - killNode(_orig); - - assert(_orig.isList() && (_orig.itemCount() == 2 || _orig.itemCount() == 17)); - if (_orig.itemCount() == 2) - return RLPNull; - RLPStream r(17); - for (unsigned i = 0; i < 16; ++i) - r << _orig[i]; - r << ""; - return r.out(); -} - -template RLPStream& GenericTrieDB::streamNode(RLPStream& _s, bytes const& _b) -{ - if (_b.size() < 32) - _s.appendRaw(_b); - else - _s.append(forceInsertNode(&_b)); - return _s; -} - -template bytes GenericTrieDB::cleve(RLP const& _orig, unsigned _s) -{ -#if ETH_PARANOIA - tdebug << "cleve " << _orig << _s; -#endif - - killNode(_orig); - assert(_orig.isList() && _orig.itemCount() == 2); - auto k = keyOf(_orig); - assert(_s && _s <= k.size()); - - RLPStream bottom(2); - bottom << hexPrefixEncode(k, isLeaf(_orig), /*ugh*/(int)_s) << _orig[1]; - - RLPStream top(2); - top << hexPrefixEncode(k, false, 0, /*ugh*/(int)_s); - streamNode(top, bottom.out()); - - return top.out(); -} - -template bytes GenericTrieDB::graft(RLP const& _orig) -{ -#if ETH_PARANOIA - tdebug << "graft " << _orig; -#endif - - assert(_orig.isList() && _orig.itemCount() == 2); - std::string s; - RLP n; - if (_orig[1].isList()) - n = _orig[1]; - else - { - // remove second item from the trie after derefrencing it into s & n. - auto lh = _orig[1].toHash(); - s = node(lh); - forceKillNode(lh); - n = RLP(s); - } - assert(n.itemCount() == 2); - - return rlpList(hexPrefixEncode(keyOf(_orig), keyOf(n), isLeaf(n)), n[1]); -// auto ret = -// std::cout << keyOf(_orig) << " ++ " << keyOf(n) << " == " << keyOf(RLP(ret)) << std::endl; -// return ret; -} - -template bytes GenericTrieDB::merge(RLP const& _orig, byte _i) -{ -#if ETH_PARANOIA - tdebug << "merge " << _orig << (int)_i; -#endif - - assert(_orig.isList() && _orig.itemCount() == 17); - RLPStream s(2); - if (_i != 16) - { - assert(!_orig[_i].isEmpty()); - s << hexPrefixEncode(bytesConstRef(&_i, 1), false, 1, 2, 0); - } - else - s << hexPrefixEncode(bytes(), true); - s << _orig[_i]; - return s.out(); -} - -template bytes GenericTrieDB::branch(RLP const& _orig) -{ -#if ETH_PARANOIA - tdebug << "branch " << _orig; -#endif - - assert(_orig.isList() && _orig.itemCount() == 2); - killNode(_orig); - - auto k = keyOf(_orig); - RLPStream r(17); - if (k.size() == 0) - { - assert(isLeaf(_orig)); - for (unsigned i = 0; i < 16; ++i) - r << ""; - r << _orig[1]; - } - else - { - byte b = k[0]; - for (unsigned i = 0; i < 16; ++i) - if (i == b) - if (isLeaf(_orig) || k.size() > 1) - streamNode(r, rlpList(hexPrefixEncode(k.mid(1), isLeaf(_orig)), _orig[1])); - else - r << _orig[1]; - else - r << ""; - r << ""; - } - return r.out(); -} - -} diff --git a/libdevcore/TrieHash.cpp b/libdevcore/TrieHash.cpp deleted file mode 100644 index ec31c3679..000000000 --- a/libdevcore/TrieHash.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file TrieHash.cpp - * @author Gav Wood - * @date 2014 - */ - -#include "TrieHash.h" -#include -#include // @TODO replace ASAP! -#include -using namespace std; -using namespace dev; - -namespace dev -{ - -/*/ -#define APPEND_CHILD appendData -/*/ -#define APPEND_CHILD appendRaw -/**/ - -#define ENABLE_DEBUG_PRINT 0 - -#if ENABLE_DEBUG_PRINT -bool g_hashDebug = false; -#endif - -void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp); - -void hash256rlp(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp) -{ -#if ENABLE_DEBUG_PRINT - static std::string s_indent; - if (_preLen) - s_indent += " "; -#endif - - if (_begin == _end) - _rlp << ""; // NULL - else if (std::next(_begin) == _end) - { - // only one left - terminate with the pair. - _rlp.appendList(2) << hexPrefixEncode(_begin->first, true, _preLen) << _begin->second; -#if ENABLE_DEBUG_PRINT - if (g_hashDebug) - std::cerr << s_indent << toHex(bytesConstRef(_begin->first.data() + _preLen, _begin->first.size() - _preLen), 1) << ": " << _begin->second << " = " << sha3(_rlp.out()) << std::endl; -#endif - } - else - { - // find the number of common prefix nibbles shared - // i.e. the minimum number of nibbles shared at the beginning between the first hex string and each successive. - unsigned sharedPre = (unsigned)-1; - unsigned c = 0; - for (auto i = std::next(_begin); i != _end && sharedPre; ++i, ++c) - { - unsigned x = std::min(sharedPre, std::min((unsigned)_begin->first.size(), (unsigned)i->first.size())); - unsigned shared = _preLen; - for (; shared < x && _begin->first[shared] == i->first[shared]; ++shared) {} - sharedPre = std::min(shared, sharedPre); - } - if (sharedPre > _preLen) - { - // if they all have the same next nibble, we also want a pair. -#if ENABLE_DEBUG_PRINT - if (g_hashDebug) - std::cerr << s_indent << toHex(bytesConstRef(_begin->first.data() + _preLen, sharedPre), 1) << ": " << std::endl; -#endif - _rlp.appendList(2) << hexPrefixEncode(_begin->first, false, _preLen, (int)sharedPre); - hash256aux(_s, _begin, _end, (unsigned)sharedPre, _rlp); -#if ENABLE_DEBUG_PRINT - if (g_hashDebug) - std::cerr << s_indent << "= " << hex << sha3(_rlp.out()) << dec << std::endl; -#endif - } - else - { - // otherwise enumerate all 16+1 entries. - _rlp.appendList(17); - auto b = _begin; - if (_preLen == b->first.size()) - { -#if ENABLE_DEBUG_PRINT - if (g_hashDebug) - std::cerr << s_indent << "@: " << b->second << std::endl; -#endif - ++b; - } - for (auto i = 0; i < 16; ++i) - { - auto n = b; - for (; n != _end && n->first[_preLen] == i; ++n) {} - if (b == n) - _rlp << ""; - else - { -#if ENABLE_DEBUG_PRINT - if (g_hashDebug) - std::cerr << s_indent << std::hex << i << ": " << std::dec << std::endl; -#endif - hash256aux(_s, b, n, _preLen + 1, _rlp); - } - b = n; - } - if (_preLen == _begin->first.size()) - _rlp << _begin->second; - else - _rlp << ""; - -#if ENABLE_DEBUG_PRINT - if (g_hashDebug) - std::cerr << s_indent << "= " << hex << sha3(_rlp.out()) << dec << std::endl; -#endif - } - } -#if ENABLE_DEBUG_PRINT - if (_preLen) - s_indent.resize(s_indent.size() - 2); -#endif -} - -void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp) -{ - RLPStream rlp; - hash256rlp(_s, _begin, _end, _preLen, rlp); - if (rlp.out().size() < 32) - { - // RECURSIVE RLP -#if ENABLE_DEBUG_PRINT - cerr << "[INLINE: " << dec << rlp.out().size() << " < 32]" << endl; -#endif - _rlp.APPEND_CHILD(rlp.out()); - } - else - { -#if ENABLE_DEBUG_PRINT - cerr << "[HASH: " << dec << rlp.out().size() << " >= 32]" << endl; -#endif - _rlp << sha3(rlp.out()); - } -} - -bytes rlp256(BytesMap const& _s) -{ - // build patricia tree. - if (_s.empty()) - return rlp(""); - HexMap hexMap; - for (auto i = _s.rbegin(); i != _s.rend(); ++i) - hexMap[asNibbles(bytesConstRef(&i->first))] = i->second; - RLPStream s; - hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); - return s.out(); -} - -h256 hash256(BytesMap const& _s) -{ - return sha3(rlp256(_s)); -} - -h256 orderedTrieRoot(std::vector const& _data) -{ - BytesMap m; - unsigned j = 0; - for (auto i: _data) - m[rlp(j++)] = i; - return hash256(m); -} - -h256 orderedTrieRoot(std::vector const& _data) -{ - BytesMap m; - unsigned j = 0; - for (auto i: _data) - m[rlp(j++)] = i.toBytes(); - return hash256(m); -} - -} diff --git a/libdevcore/TrieHash.h b/libdevcore/TrieHash.h deleted file mode 100644 index 9649ef0c7..000000000 --- a/libdevcore/TrieHash.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file TrieHash.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include - -namespace dev -{ - -bytes rlp256(BytesMap const& _s); -h256 hash256(BytesMap const& _s); - -h256 orderedTrieRoot(std::vector const& _data); - -template inline h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue) -{ - BytesMap m; - for (unsigned i = 0; i < _itemCount; ++i) - m[_getKey(i)] = _getValue(i); - return hash256(m); -} - -h256 orderedTrieRoot(std::vector const& _data); -h256 orderedTrieRoot(std::vector const& _data); - -} diff --git a/libdevcore/db.h b/libdevcore/db.h deleted file mode 100644 index 0abaea5cb..000000000 --- a/libdevcore/db.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file DB.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#pragma warning(push) -#pragma warning(disable: 4100 4267) -#include -#include -namespace ldb = leveldb; -#pragma warning(pop) -#define DEV_LDB 1 diff --git a/libethash-cl/CMakeLists.txt b/libethash-cl/CMakeLists.txt index 7de2d6971..cc2d5f2da 100644 --- a/libethash-cl/CMakeLists.txt +++ b/libethash-cl/CMakeLists.txt @@ -23,7 +23,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_include_directories(${EXECUTABLE} PUBLIC ${OpenCL_INCLUDE_DIR}) +target_include_directories(${EXECUTABLE} PUBLIC SYSTEM ${OpenCL_INCLUDE_DIR}) target_link_libraries(${EXECUTABLE} ${OpenCL_LIBRARIES} ethash) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 27802b582..56cd5b1eb 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -22,8 +22,6 @@ #include #include #include -#include -#include #include #include #include "EthashAux.h" @@ -33,6 +31,11 @@ using namespace std; using namespace dev; using namespace dev::eth; +namespace +{ +h256 const EmptyTrie = sha3(rlp("")); +} + BlockInfo::BlockInfo(): m_timestamp(Invalid256) { } @@ -140,56 +143,6 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s) struct BlockInfoDiagnosticsChannel: public LogChannel { static const char* name() { return EthBlue "▧" EthWhite " ◌"; } static const int verbosity = 9; }; -void BlockInfo::verifyInternals(bytesConstRef _block) const -{ - RLP root(_block); - - auto txList = root[1]; - auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data().toBytes(); }); - - clog(BlockInfoDiagnosticsChannel) << "Expected trie root:" << toString(expectedRoot); - if (m_transactionsRoot != expectedRoot) - { - MemoryDB tm; - GenericTrieDB transactionsTrie(&tm); - transactionsTrie.init(); - - vector txs; - - for (unsigned i = 0; i < txList.itemCount(); ++i) - { - RLPStream k; - k << i; - - transactionsTrie.insert(&k.out(), txList[i].data()); - - txs.push_back(txList[i].data()); - cdebug << toHex(k.out()) << toHex(txList[i].data()); - } - cdebug << "trieRootOver" << expectedRoot; - cdebug << "orderedTrieRoot" << orderedTrieRoot(txs); - cdebug << "TrieDB" << transactionsTrie.root(); - cdebug << "Contents:"; - for (auto const& t: txs) - cdebug << toHex(t); - - BOOST_THROW_EXCEPTION(InvalidTransactionsRoot() << Hash256RequirementError(expectedRoot, m_transactionsRoot)); - } - clog(BlockInfoDiagnosticsChannel) << "Expected uncle hash:" << toString(sha3(root[2].data())); - if (m_sha3Uncles != sha3(root[2].data())) - BOOST_THROW_EXCEPTION(InvalidUnclesHash() << Hash256RequirementError(sha3(root[2].data()), m_sha3Uncles)); -} - -void BlockInfo::populateFromParent(BlockInfo const& _parent) -{ - m_stateRoot = _parent.stateRoot(); - m_number = _parent.m_number + 1; - m_parentHash = _parent.m_hash; - m_gasLimit = _parent.childGasLimit(); - m_gasUsed = 0; - m_difficulty = calculateDifficulty(_parent); -} - u256 BlockInfo::childGasLimit(u256 const& _gasFloorTarget) const { u256 gasFloorTarget = @@ -213,16 +166,3 @@ u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const o = max(c_minimumDifficulty, o + (u256(1) << (periodCount - 2))); // latter will eventually become huge, so ensure it's a bigint. return o; } - -void BlockInfo::verifyParent(BlockInfo const& _parent) const -{ - // Check timestamp is after previous timestamp. - if (m_parentHash) - { - if (m_timestamp <= _parent.m_timestamp) - BOOST_THROW_EXCEPTION(InvalidTimestamp()); - - if (m_number != _parent.m_number + 1) - BOOST_THROW_EXCEPTION(InvalidNumber()); - } -} diff --git a/libethcore/BlockInfo.h b/libethcore/BlockInfo.h index 44be97fc7..adddf0f3c 100644 --- a/libethcore/BlockInfo.h +++ b/libethcore/BlockInfo.h @@ -111,10 +111,6 @@ public: } bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); } - void verifyInternals(bytesConstRef _block) const; - void verifyParent(BlockInfo const& _parent) const; - void populateFromParent(BlockInfo const& parent); - u256 calculateDifficulty(BlockInfo const& _parent) const; u256 childGasLimit(u256 const& _gasFloorTarget = UndefinedU256) const; h256 const& boundary() const; @@ -210,23 +206,6 @@ public: populateFromHeader(_bdt == BlockData ? BlockInfo::extractHeader(_data) : RLP(_data), _s, _h); } - void populateFromParent(BlockHeaderPolished const& _parent) - { - noteDirty(); - BlockInfo::m_parentHash = _parent.hash(); - BlockInfo::populateFromParent(_parent); - BlockInfoSub::populateFromParent(_parent); - } - - // TODO: consider making private. - void verifyParent(BlockHeaderPolished const& _parent) - { - if (BlockInfo::parentHash() && BlockInfo::parentHash() != _parent.hash()) - BOOST_THROW_EXCEPTION(InvalidParentHash()); - BlockInfo::verifyParent(_parent); - BlockInfoSub::verifyParent(_parent); - } - // deprecated for public API - use constructor. // TODO: make private. void populateFromHeader(RLP const& _header, Strictness _s = IgnoreSeal, h256 const& _h = h256())