@ -66,7 +66,7 @@ class GenericTrieDB
public :
using DB = _DB ;
GenericTrieDB ( DB * _db = nullptr ) : m_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 ( ) { }
@ -96,11 +96,72 @@ public:
/// 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 ) . size ( ) ) BOOST_THROW_EXCEPTION ( BadRoot ( ) ) ; /*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.
h256 const & root ( ) const { if ( node ( m_root ) . empty ( ) ) BOOST_THROW_EXCEPTION ( BadRoot ( ) ) ; /*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 < bytesConstRef , bytesConstRef > ;
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 < Node > m_trail ;
GenericTrieDB < DB > const * m_that ;
} ;
iterator begin ( ) const { return iterator ( this ) ; }
iterator end ( ) const { return iterator ( ) ; }
iterator lower_bound ( bytesConstRef _key ) const { return iterator ( this , _key ) ; }
void debugPrint ( ) { }
void descendKey ( h256 _k , h256Hash & _keyMask , bool _wasExt , std : : ostream * _out , int _indent = 0 ) const
/// 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
@ -108,6 +169,7 @@ public:
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 )
@ -118,6 +180,7 @@ public:
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 ) )
@ -139,6 +202,7 @@ public:
BOOST_THROW_EXCEPTION ( InvalidTrie ( ) ) ;
}
/// Used for debugging, scans the whole trie.
h256Hash leftOvers ( std : : ostream * _out = nullptr ) const
{
h256Hash k = m_db - > keys ( ) ;
@ -146,11 +210,14 @@ public:
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
@ -164,66 +231,6 @@ public:
}
}
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 < bytesConstRef , bytesConstRef > ;
iterator ( ) { }
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 < Node > m_trail ;
GenericTrieDB < DB > const * m_that ;
} ;
iterator begin ( ) const { return this ; }
iterator end ( ) const { return iterator ( ) ; }
iterator lower_bound ( bytesConstRef _key ) const { return iterator ( this , _key ) ; }
protected :
DB * db ( ) const { return m_db ; }
@ -279,12 +286,12 @@ private:
bool isTwoItemNode ( RLP const & _n ) const ;
std : : string deref ( RLP const & _n ) const ;
std : : string node ( h256 _h ) const { return m_db - > lookup ( _h ) ; }
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 _h , bytesConstRef _v ) { m_db - > insert ( _h , _v ) ; }
void forceKillNode ( h256 _h ) { m_db - > kill ( _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
@ -305,6 +312,9 @@ std::ostream& operator<<(std::ostream& _out, GenericTrieDB<DB> const& _db)
return _out ;
}
/**
* Different view on a GenericTrieDB that can use different key types .
*/
template < class Generic , class _KeyType >
class SpecificTrieDB : public Generic
{
@ -753,14 +763,14 @@ template <class DB> void GenericTrieDB<DB>::insert(bytesConstRef _key, bytesCons
tdebug < < " Insert " < < toHex ( _key . cropped ( 0 , 4 ) ) < < " => " < < toHex ( _value ) ;
# endif
std : : string rv = node ( m_root ) ;
assert ( rv . size ( ) ) ;
bytes b = mergeAt ( RLP ( rv ) , m_root , NibbleSlice ( _key ) , _value ) ;
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 ( rv . size ( ) < 32 )
if ( rootValue . size ( ) < 32 )
forceKillNode ( m_root ) ;
m_root = forceInsertNode ( & b ) ;
}
@ -1066,11 +1076,11 @@ template <class DB> bytes GenericTrieDB<DB>::place(RLP const& _orig, NibbleSlice
killNode ( _orig ) ;
if ( _orig . isEmpty ( ) )
return ( RLPStream ( 2 ) < < hexPrefixEncode ( _k , true ) < < _s ) . out ( ) ;
return rlpList ( hexPrefixEncode ( _k , true ) , _s ) ;
assert ( _orig . isList ( ) & & ( _orig . itemCount ( ) = = 2 | | _orig . itemCount ( ) = = 17 ) ) ;
if ( _orig . itemCount ( ) = = 2 )
return ( RLPStream ( 2 ) < < _orig [ 0 ] < < _s ) . out ( ) ;
return rlpList ( _orig [ 0 ] , _s ) ;
auto s = RLPStream ( 17 ) ;
for ( unsigned i = 0 ; i < 16 ; + + i )
@ -1152,7 +1162,7 @@ template <class DB> bytes GenericTrieDB<DB>::graft(RLP const& _orig)
}
assert ( n . itemCount ( ) = = 2 ) ;
return ( RLPStream ( 2 ) < < hexPrefixEncode ( keyOf ( _orig ) , keyOf ( n ) , isLeaf ( n ) ) < < n [ 1 ] ) . out ( ) ;
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;
@ -1201,11 +1211,7 @@ template <class DB> bytes GenericTrieDB<DB>::branch(RLP const& _orig)
for ( unsigned i = 0 ; i < 16 ; + + i )
if ( i = = b )
if ( isLeaf ( _orig ) | | k . size ( ) > 1 )
{
RLPStream bottom ( 2 ) ;
bottom < < hexPrefixEncode ( k . mid ( 1 ) , isLeaf ( _orig ) ) < < _orig [ 1 ] ;
streamNode ( r , bottom . out ( ) ) ;
}
streamNode ( r , rlpList ( hexPrefixEncode ( k . mid ( 1 ) , isLeaf ( _orig ) ) , _orig [ 1 ] ) ) ;
else
r < < _orig [ 1 ] ;
else