|
@ -62,17 +62,21 @@ extern const h256 EmptyTrie; |
|
|
* assert(t.isEmpty()); |
|
|
* assert(t.isEmpty()); |
|
|
* @endcode |
|
|
* @endcode |
|
|
*/ |
|
|
*/ |
|
|
template <class DB> |
|
|
template <class _DB> |
|
|
class GenericTrieDB |
|
|
class GenericTrieDB |
|
|
{ |
|
|
{ |
|
|
public: |
|
|
public: |
|
|
|
|
|
using DB = _DB; |
|
|
|
|
|
|
|
|
GenericTrieDB(DB* _db): m_db(_db) {} |
|
|
GenericTrieDB(DB* _db): m_db(_db) {} |
|
|
GenericTrieDB(DB* _db, h256 _root) { open(_db, _root); } |
|
|
GenericTrieDB(DB* _db, h256 _root) { open(_db, _root); } |
|
|
~GenericTrieDB() {} |
|
|
~GenericTrieDB() {} |
|
|
|
|
|
|
|
|
|
|
|
void open(DB* _db) { m_db = _db; } |
|
|
void open(DB* _db, h256 _root) { m_db = _db; setRoot(_root); } |
|
|
void open(DB* _db, h256 _root) { m_db = _db; setRoot(_root); } |
|
|
|
|
|
|
|
|
void init(); |
|
|
void init() { setRoot(insertNode(&RLPNull)); assert(node(m_root).size()); } |
|
|
|
|
|
|
|
|
void setRoot(h256 _root) |
|
|
void setRoot(h256 _root) |
|
|
{ |
|
|
{ |
|
|
m_root = _root; |
|
|
m_root = _root; |
|
@ -83,7 +87,6 @@ public: |
|
|
if (!node(m_root).size()) |
|
|
if (!node(m_root).size()) |
|
|
BOOST_THROW_EXCEPTION(RootNotFound()); |
|
|
BOOST_THROW_EXCEPTION(RootNotFound()); |
|
|
} |
|
|
} |
|
|
bool haveRoot(h256 _root, bool _enforceRefs = true) { return _root == c_shaNull ? true : m_db->lookup(_root, _enforceRefs).size(); } |
|
|
|
|
|
|
|
|
|
|
|
/// True if the trie is uninitialised (i.e. that the DB doesn't contain the root node).
|
|
|
/// 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(); } |
|
|
bool isNull() const { return !node(m_root).size(); } |
|
@ -211,6 +214,9 @@ public: |
|
|
|
|
|
|
|
|
iterator lower_bound(bytesConstRef _key) const { return iterator(this, _key); } |
|
|
iterator lower_bound(bytesConstRef _key) const { return iterator(this, _key); } |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
DB* db() const { return m_db; } |
|
|
|
|
|
|
|
|
private: |
|
|
private: |
|
|
RLPStream& streamNode(RLPStream& _s, bytes const& _b); |
|
|
RLPStream& streamNode(RLPStream& _s, bytes const& _b); |
|
|
|
|
|
|
|
@ -281,30 +287,33 @@ std::ostream& operator<<(std::ostream& _out, GenericTrieDB<DB> const& _db) |
|
|
return _out; |
|
|
return _out; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <class KeyType, class DB> |
|
|
template <class Generic, class _KeyType> |
|
|
class TrieDB: public GenericTrieDB<DB> |
|
|
class SpecificTrieDB: public Generic |
|
|
{ |
|
|
{ |
|
|
public: |
|
|
public: |
|
|
TrieDB(DB* _db): GenericTrieDB<DB>(_db) {} |
|
|
using DB = typename Generic::DB; |
|
|
TrieDB(DB* _db, h256 _root): GenericTrieDB<DB>(_db, _root) {} |
|
|
using KeyType = _KeyType; |
|
|
|
|
|
|
|
|
|
|
|
SpecificTrieDB(DB* _db): Generic(_db) {} |
|
|
|
|
|
SpecificTrieDB(DB* _db, h256 _root): Generic(_db, _root) {} |
|
|
|
|
|
|
|
|
std::string operator[](KeyType _k) const { return at(_k); } |
|
|
std::string operator[](KeyType _k) const { return at(_k); } |
|
|
|
|
|
|
|
|
bool contains(KeyType _k) const { return GenericTrieDB<DB>::contains(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } |
|
|
bool contains(KeyType _k) const { return Generic::contains(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } |
|
|
std::string at(KeyType _k) const { return GenericTrieDB<DB>::at(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) { GenericTrieDB<DB>::insert(bytesConstRef((byte const*)&_k, sizeof(KeyType)), _value); } |
|
|
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 insert(KeyType _k, bytes const& _value) { insert(_k, bytesConstRef(&_value)); } |
|
|
void remove(KeyType _k) { GenericTrieDB<DB>::remove(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } |
|
|
void remove(KeyType _k) { Generic::remove(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } |
|
|
|
|
|
|
|
|
class iterator: public GenericTrieDB<DB>::iterator |
|
|
class iterator: public Generic::iterator |
|
|
{ |
|
|
{ |
|
|
public: |
|
|
public: |
|
|
using Super = typename GenericTrieDB<DB>::iterator; |
|
|
using Super = typename Generic::iterator; |
|
|
using value_type = std::pair<KeyType, bytesConstRef>; |
|
|
using value_type = std::pair<KeyType, bytesConstRef>; |
|
|
|
|
|
|
|
|
iterator() {} |
|
|
iterator() {} |
|
|
iterator(TrieDB const* _db): Super(_db) {} |
|
|
iterator(Generic const* _db): Super(_db) {} |
|
|
iterator(TrieDB const* _db, bytesConstRef _k): Super(_db, _k) {} |
|
|
iterator(Generic const* _db, bytesConstRef _k): Super(_db, _k) {} |
|
|
|
|
|
|
|
|
value_type operator*() const { return at(); } |
|
|
value_type operator*() const { return at(); } |
|
|
value_type operator->() const { return at(); } |
|
|
value_type operator->() const { return at(); } |
|
@ -317,27 +326,28 @@ public: |
|
|
iterator lower_bound(KeyType _k) const { return iterator(this, bytesConstRef((byte const*)&_k, sizeof(KeyType))); } |
|
|
iterator lower_bound(KeyType _k) const { return iterator(this, bytesConstRef((byte const*)&_k, sizeof(KeyType))); } |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
template <class KeyType, class DB> |
|
|
template <class Generic, class KeyType> |
|
|
std::ostream& operator<<(std::ostream& _out, TrieDB<KeyType, DB> const& _db) |
|
|
std::ostream& operator<<(std::ostream& _out, SpecificTrieDB<Generic, KeyType> const& _db) |
|
|
{ |
|
|
{ |
|
|
for (auto const& i: _db) |
|
|
for (auto const& i: _db) |
|
|
_out << i.first << ": " << escaped(i.second.toString(), false) << std::endl; |
|
|
_out << i.first << ": " << escaped(i.second.toString(), false) << std::endl; |
|
|
return _out; |
|
|
return _out; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <class DB> |
|
|
template <class _DB> |
|
|
class SecureGenericTrieDB: private TrieDB<h256, DB> |
|
|
class HashedGenericTrieDB: private SpecificTrieDB<GenericTrieDB<_DB>, h256> |
|
|
{ |
|
|
{ |
|
|
using Super = TrieDB<h256, DB>; |
|
|
using Super = SpecificTrieDB<GenericTrieDB<_DB>, h256>; |
|
|
|
|
|
|
|
|
public: |
|
|
public: |
|
|
SecureGenericTrieDB(DB* _db): Super(_db) {} |
|
|
using DB = _DB; |
|
|
SecureGenericTrieDB(DB* _db, h256 _root): Super(_db, _root) {} |
|
|
|
|
|
|
|
|
HashedGenericTrieDB(DB* _db): Super(_db) {} |
|
|
|
|
|
HashedGenericTrieDB(DB* _db, h256 _root): Super(_db, _root) {} |
|
|
|
|
|
|
|
|
using Super::open; |
|
|
using Super::open; |
|
|
using Super::init; |
|
|
using Super::init; |
|
|
using Super::setRoot; |
|
|
using Super::setRoot; |
|
|
using Super::haveRoot; |
|
|
|
|
|
|
|
|
|
|
|
/// True if the trie is uninitialised (i.e. that the DB doesn't contain the root node).
|
|
|
/// True if the trie is uninitialised (i.e. that the DB doesn't contain the root node).
|
|
|
using Super::isNull; |
|
|
using Super::isNull; |
|
@ -350,29 +360,63 @@ public: |
|
|
using Super::check; |
|
|
using Super::check; |
|
|
|
|
|
|
|
|
std::string at(bytesConstRef _key) const { return Super::at(sha3(_key)); } |
|
|
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 insert(bytesConstRef _key, bytesConstRef _value) { Super::insert(sha3(_key), _value); } |
|
|
void remove(bytesConstRef _key) { Super::remove(sha3(_key)); } |
|
|
void remove(bytesConstRef _key) { Super::remove(sha3(_key)); } |
|
|
bool contains(bytesConstRef _key) { return Super::contains(sha3(_key)); } |
|
|
|
|
|
|
|
|
// empty from the PoV of the iterator interface.
|
|
|
|
|
|
using iterator = void*; |
|
|
|
|
|
iterator begin() const { return nullptr; } |
|
|
|
|
|
iterator end() const { return nullptr; } |
|
|
|
|
|
iterator lower_bound(bytesConstRef) const { return end(); } |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
template <class KeyType, class DB> |
|
|
// Hashed & Basic
|
|
|
class SecureTrieDB: public SecureGenericTrieDB<DB> |
|
|
template <class DB> |
|
|
|
|
|
class FatGenericTrieDB: public GenericTrieDB<DB> |
|
|
{ |
|
|
{ |
|
|
using Super = SecureGenericTrieDB<DB>; |
|
|
using Super = GenericTrieDB<DB>; |
|
|
|
|
|
|
|
|
public: |
|
|
public: |
|
|
SecureTrieDB(DB* _db): Super(_db) {} |
|
|
FatGenericTrieDB(DB* _db): Super(_db), m_secure(_db) {} |
|
|
SecureTrieDB(DB* _db, h256 _root): Super(_db, _root) {} |
|
|
FatGenericTrieDB(DB* _db, h256 _root) { open(_db, _root); } |
|
|
|
|
|
|
|
|
std::string operator[](KeyType _k) const { return at(_k); } |
|
|
void open(DB* _db, h256 _root) { Super::open(_db); m_secure.open(_db); setRoot(_root); } |
|
|
|
|
|
|
|
|
bool contains(KeyType _k) const { return Super::contains(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } |
|
|
void init() { Super::init(); m_secure.init(); syncRoot(); } |
|
|
std::string at(KeyType _k) const { return Super::at(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } |
|
|
|
|
|
void insert(KeyType _k, bytesConstRef _value) { Super::insert(bytesConstRef((byte const*)&_k, sizeof(KeyType)), _value); } |
|
|
void setRoot(h256 _root) |
|
|
void insert(KeyType _k, bytes const& _value) { insert(_k, bytesConstRef(&_value)); } |
|
|
{ |
|
|
void remove(KeyType _k) { Super::remove(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } |
|
|
m_secure.setRoot(_root); |
|
|
|
|
|
Super::setRoot(h256(Super::db()->lookupAux(m_secure.root()))); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
h256 root() const { return m_secure.root(); } |
|
|
|
|
|
|
|
|
|
|
|
void insert(bytesConstRef _key, bytesConstRef _value) { Super::insert(_key, _value); m_secure.insert(_key, _value); syncRoot(); } |
|
|
|
|
|
void remove(bytesConstRef _key) { Super::remove(_key); m_secure.remove(_key); syncRoot(); } |
|
|
|
|
|
|
|
|
|
|
|
std::set<h256> leftOvers(std::ostream* = nullptr) const { return {}; } |
|
|
|
|
|
bool check(bool) const { return m_secure.check(false) && Super::check(false); } |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
void syncRoot() |
|
|
|
|
|
{ |
|
|
|
|
|
// Root changed. Need to record the mapping so we can determine on setRoot.
|
|
|
|
|
|
Super::db()->insertAux(m_secure.root(), Super::root().ref()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HashedGenericTrieDB<DB> m_secure; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
template <class KeyType, class DB> using TrieDB = SpecificTrieDB<GenericTrieDB<DB>, KeyType>; |
|
|
|
|
|
|
|
|
|
|
|
#if ETH_FAT_DB |
|
|
|
|
|
template <class KeyType, class DB> using SecureTrieDB = SpecificTrieDB<FatGenericTrieDB<DB>, KeyType>; |
|
|
|
|
|
#else |
|
|
|
|
|
template <class KeyType, class DB> using SecureTrieDB = SpecificTrieDB<HashedGenericTrieDB<DB>, KeyType>; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Template implementations...
|
|
|
// Template implementations...
|
|
@ -641,7 +685,7 @@ template <class DB> void GenericTrieDB<DB>::iterator::next() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <class KeyType, class DB> typename TrieDB<KeyType, DB>::iterator::value_type TrieDB<KeyType, DB>::iterator::at() const |
|
|
template <class KeyType, class DB> typename SpecificTrieDB<KeyType, DB>::iterator::value_type SpecificTrieDB<KeyType, DB>::iterator::at() const |
|
|
{ |
|
|
{ |
|
|
auto p = Super::at(); |
|
|
auto p = Super::at(); |
|
|
value_type ret; |
|
|
value_type ret; |
|
@ -651,13 +695,6 @@ template <class KeyType, class DB> typename TrieDB<KeyType, DB>::iterator::value |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <class DB> void GenericTrieDB<DB>::init() |
|
|
|
|
|
{ |
|
|
|
|
|
m_root = insertNode(&RLPNull); |
|
|
|
|
|
// std::cout << "Initialised root to " << m_root << std::endl;
|
|
|
|
|
|
assert(node(m_root).size()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <class DB> void GenericTrieDB<DB>::insert(bytesConstRef _key, bytesConstRef _value) |
|
|
template <class DB> void GenericTrieDB<DB>::insert(bytesConstRef _key, bytesConstRef _value) |
|
|
{ |
|
|
{ |
|
|
#if ETH_PARANOIA |
|
|
#if ETH_PARANOIA |
|
|