37 #define tdebug clog(TrieDBChannel) 83 if (m_root == c_shaNull && !m_db->exists(m_root))
90 if (!
node(m_root).size())
91 BOOST_THROW_EXCEPTION(RootNotFound());
97 bool isEmpty()
const {
return m_root == c_shaNull &&
node(m_root).size(); }
99 h256 const&
root()
const {
if (
node(m_root).empty()) BOOST_THROW_EXCEPTION(
BadRoot(m_root));
return m_root; }
101 std::string
at(
bytes const& _key)
const {
return at(&_key); }
107 void remove(
bytes const& _key) {
remove(&_key); }
145 void incrementChild() { child = child == 16 ? 0 : child == 15 ? 17 : (child + 1); }
156 iterator
begin()
const {
return iterator(
this); }
157 iterator
end()
const {
return iterator(); }
165 if (_k == m_root && _k == c_shaNull)
167 descendList(
RLP(
node(_k)), _keyMask, _wasExt, _out, _indent);
174 descendKey(_r.
toHash<
h256>(), _keyMask, _wasExt, _out, _indent);
176 descendList(_r, _keyMask, _wasExt, _out, _indent);
187 (*_out) << std::string(_indent * 2,
' ') << (_wasExt ?
"!2 " :
"2 ") <<
sha3(_r.
data()) <<
": " << _r <<
"\n";
189 descendEntry(_r[1], _keyMask,
true, _out, _indent + 1);
194 (*_out) << std::string(_indent * 2,
' ') <<
"17 " <<
sha3(_r.
data()) <<
": " << _r <<
"\n";
195 for (
unsigned i = 0; i < 16; ++i)
196 if (!_r[i].isEmpty())
197 descendEntry(_r[i], _keyMask,
false, _out, _indent + 1);
207 descendKey(m_root, k,
false, _out);
219 bool check(
bool _requireNoLeftOvers)
const 223 return leftOvers().empty() || !_requireNoLeftOvers;
227 cwarn << boost::current_exception_diagnostic_information();
235 DB const*
db()
const {
return m_db; }
266 bytes cleve(
RLP const& _orig,
unsigned _s);
287 bool isTwoItemNode(
RLP const& _n)
const;
288 std::string deref(
RLP const& _n)
const;
290 std::string
node(
h256 const& _h)
const {
return m_db->lookup(_h); }
309 std::ostream& operator<<(std::ostream& _out, GenericTrieDB<DB>
const& _db)
311 for (
auto const& i: _db)
312 _out <<
escaped(i.first.toString(),
false) <<
": " <<
escaped(i.second.toString(),
false) << std::endl;
319 template <
class Generic,
class _KeyType>
340 using Super =
typename Generic::iterator;
353 iterator
begin()
const {
return this; }
354 iterator
end()
const {
return iterator(); }
358 template <
class Generic,
class KeyType>
359 std::ostream& operator<<(std::ostream& _out, SpecificTrieDB<Generic, KeyType>
const& _db)
361 for (
auto const& i: _db)
362 _out << i.first <<
": " <<
escaped(i.second.toString(),
false) << std::endl;
379 using Super::setRoot;
384 using Super::isEmpty;
389 using Super::leftOvers;
391 using Super::debugStructure;
435 using Super::isEmpty;
437 using Super::leftOvers;
440 using Super::setRoot;
442 using Super::debugStructure;
448 h256 hash =
sha3(_key);
449 Super::insert(hash, _value);
450 Super::db()->insertAux(hash, _key);
464 typename Super::value_type
at()
const 466 auto hashed = Super::at();
467 m_key =
static_cast<FatGenericTrieDB const*
>(Super::m_that)->db()->lookupAux(
h256(hashed.first));
468 return std::make_pair(&m_key, std::move(hashed.second));
489 auto hashed = Super::at();
490 return static_cast<FatGenericTrieDB const*
>(Super::m_that)->db()->lookupAux(
h256(hashed.first));
509 m_trail.push_back({_db->
node(_db->
m_root), std::string(1,
'\0'), 255});
516 m_trail.push_back({_db->
node(_db->
m_root), std::string(1,
'\0'), 255});
523 Node const&
b = m_trail.back();
525 assert(!(b.key[0] & 0x10));
542 Node const&
b = m_trail.back();
545 if (m_trail.back().child == 255)
558 cwarn <<
"BIG FAT ERROR. STATE TRIE CORRUPTED!!!!!";
561 auto c = rlp.itemCount();
572 auto keyOfRLP =
keyOf(rlp);
597 m_trail.back().child = 0;
607 m_trail.back().rlp = m_that->deref(rlp[1]);
616 m_trail.back().setChild(k[0]);
620 m_trail.back().setChild(16);
634 m_trail.back().incrementChild();
639 for (;; m_trail.back().incrementChild())
640 if (m_trail.back().child == 17)
647 else if (!rlp[m_trail.back().child].
isEmpty())
649 if (m_trail.back().child == 16)
655 Node const& back = m_trail.back();
656 m_trail.push_back(
Node{
657 m_that->deref(rlp[back.
child]),
679 Node const&
b = m_trail.back();
682 if (m_trail.back().child == 255)
693 cwarn <<
"BIG FAT ERROR. STATE TRIE CORRUPTED!!!!!";
696 auto c = rlp.itemCount();
711 m_trail.back().child = 0;
716 m_trail.back().rlp = m_that->deref(rlp[1]);
723 m_trail.back().setFirstChild();
736 m_trail.back().incrementChild();
741 for (;; m_trail.back().incrementChild())
742 if (m_trail.back().child == 17)
748 else if (!rlp[m_trail.back().child].
isEmpty())
750 if (m_trail.back().child == 16)
756 Node const& back = m_trail.back();
757 m_trail.push_back(
Node{
758 m_that->deref(rlp[back.
child]),
770 auto p = Super::at();
774 ret.second = p.second;
784 std::string rootValue =
node(m_root);
791 if (rootValue.size() < 32)
792 forceKillNode(m_root);
793 m_root = forceInsertNode(&b);
798 return atAux(
RLP(
node(m_root)), _key);
805 return std::string();
807 assert(_here.
isList() && (itemCount == 2 || itemCount == 17));
810 auto k =
keyOf(_here);
811 if (_key == k &&
isLeaf(_here))
816 return atAux(_here[1].isList() ? _here[1] :
RLP(
node(_here[1].toHash<h256>())), _key.
mid(k.size()));
819 return std::string();
823 if (_key.
size() == 0)
825 auto n = _here[_key[0]];
827 return std::string();
829 return atAux(n.isList() ? n :
RLP(
node(n.toHash<
h256>())), _key.mid(1));
835 return mergeAt(_orig,
sha3(_orig.
data()), _k, _v, _inLine);
850 return place(_orig, _k, _v);
853 assert(_orig.
isList() && (itemCount == 2 || itemCount == 17));
860 if (k == _k &&
isLeaf(_orig))
861 return place(_orig, _k, _v);
867 killNode(_orig, _origHash);
870 mergeAtAux(s, _orig[1], _k.
mid(k.
size()), _v);
879 auto cleved = cleve(_orig, sh);
880 return mergeAt(
RLP(cleved), _k, _v,
true);
885 auto branched = branch(_orig);
886 return mergeAt(
RLP(branched), _k, _v,
true);
895 return place(_orig, _k, _v);
899 killNode(_orig, _origHash);
904 for (
byte i = 0; i < 17; ++i)
906 mergeAtAux(r, _orig[i], _k.
mid(1), _v);
919 bool isRemovable =
false;
927 bytes b = mergeAt(r, _k, _v, !isRemovable);
937 std::string rv =
node(m_root);
942 forceKillNode(m_root);
943 m_root = forceInsertNode(&b);
979 if (k == _k &&
isLeaf(_orig))
990 if (!deleteAtAux(s, _orig[1], _k.
mid(k.
size())))
994 if (isTwoItemNode(r[1]))
1014 if (isTwoItemNode(_orig[used]))
1016 auto merged = merge(_orig, used);
1017 return graft(
RLP(merged));
1020 return merge(_orig, used);
1024 for (
byte i = 0; i < 16; ++i)
1035 for (
byte i = 0; i < 17; ++i)
1037 if (!deleteAtAux(r, _orig[i], _k.
mid(1)))
1053 if (isTwoItemNode(
rlp[used]))
1055 auto merged = merge(
rlp, used);
1056 return graft(
RLP(merged));
1059 return merge(
rlp, used);
1078 streamNode(_out, b);
1085 tdebug <<
"place " << _orig << _k;
1097 for (
unsigned i = 0; i < 16; ++i)
1110 tdebug <<
"kill " << _orig;
1115 assert(_orig.isList() && (_orig.itemCount() == 2 || _orig.itemCount() == 17));
1116 if (_orig.itemCount() == 2)
1119 for (
unsigned i = 0; i < 16; ++i)
1130 _s.
append(forceInsertNode(&_b));
1137 tdebug <<
"cleve " << _orig << _s;
1142 auto k =
keyOf(_orig);
1143 assert(_s && _s <= k.size());
1150 streamNode(top, bottom.
out());
1158 tdebug <<
"graft " << _orig;
1161 assert(_orig.isList() && _orig.itemCount() == 2);
1164 if (_orig[1].isList())
1185 tdebug <<
"merge " << _orig << (int)_i;
1192 assert(!_orig[_i].isEmpty());
1204 tdebug <<
"branch " << _orig;
1207 assert(_orig.isList() && _orig.itemCount() == 2);
1210 auto k =
keyOf(_orig);
1215 for (
unsigned i = 0; i < 16; ++i)
1222 for (
unsigned i = 0; i < 16; ++i)
1224 if (
isLeaf(_orig) || k.size() > 1)
bool check(bool _requireNoLeftOvers) const
Used for debugging, scans the whole trie.
bool operator!=(Node const &_c) const
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
value_type operator*() const
void killNode(RLP const &_d, h256 const &_h)
GenericTrieDB(DB *_db, h256 const &_root, Verification _v=Verification::Normal)
std::string toHex(T const &_data, int _w=2, HexPrefix _prefix=HexPrefix::DontAdd)
void forceInsertNode(h256 const &_h, bytesConstRef _v)
bool isNull() const
No value.
std::string at(bytesConstRef _key) const
void debugStructure(std::ostream &_out) const
Used for debugging, scans the whole trie.
void descendKey(h256 const &_k, h256Hash &_keyMask, bool _wasExt, std::ostream *_out, int _indent=0) const
Used for debugging, scans the whole trie.
iterator(HashedGenericTrieDB const *)
bool operator==(Node const &_c) const
iterator(Generic const *_db, bytesConstRef _k)
bool isList() const
List value.
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
iterator(FatGenericTrieDB const *_trie)
bytesConstRef data() const
The bare data of the RLP.
Merkle Patricia Tree "Trie": a modifed base-16 Radix tree.
RLPStream & append(unsigned _s)
Append given datum to the byte stream.
static const char * name()
std::string at(bytesConstRef _key) const
std::string hexPrefixEncode(bytes const &_hexVector, bool _leaf, int _begin, int _end)
bytes const & out() const
Read the byte stream.
bool contains(bytesConstRef _key)
h256Hash leftOvers(std::ostream *_out=nullptr) const
Used for debugging, scans the whole trie.
void mergeAtAux(RLPStream &_out, RLP const &_replace, NibbleSlice _key, bytesConstRef _value)
void descendEntry(RLP const &_r, h256Hash &_keyMask, bool _wasExt, std::ostream *_out, int _indent) const
Used for debugging, scans the whole trie.
bool isNull() const
True if the trie is uninitialised (i.e. that the DB doesn't contain the root node).
std::string atAux(RLP const &_here, NibbleSlice _key) const
void open(DB *_db, h256 const &_root, Verification _v=Verification::Normal)
typename GenericTrieDB< _DB >::iterator Super
bytes merge(RLP const &_orig, byte _i)
bool operator==(iterator const &) const
bool operator!=(iterator const &_c) const
iterator lower_bound(bytesConstRef) const
assert(len-trim+(2 *lenIndices)<=WIDTH)
Different view on a GenericTrieDB that can use different key types.
void insert(bytesConstRef _key, bytesConstRef _value)
void forceKillNode(h256 const &_h)
std::string toString(string32 const &_s)
Make normal string from fixed-length string.
bool isData() const
String value.
vector_ref< _T > cropped(size_t _begin, size_t _count) const
std::pair< bytesConstRef, bytesConstRef > value_type
FatGenericTrieDB(DB *_db=nullptr)
HashedGenericTrieDB(DB *_db=nullptr)
value_type operator->() const
bool isLeaf(RLP const &_twoItem)
bytes graft(RLP const &_orig)
bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
bool operator==(iterator const &_c) const
std::string escaped(std::string const &_s, bool _all=true)
Escapes a string into the C-string representation.
bytes mergeAt(RLP const &_replace, NibbleSlice _k, bytesConstRef _v, bool _inLine=false)
void insert(bytesConstRef _key, bytesConstRef _value)
bool contains(bytesConstRef _key)
bytes RLPNull
The empty string in RLP format.
bool deleteAtAux(RLPStream &_out, RLP const &_replace, NibbleSlice _key)
RLPStream & streamNode(RLPStream &_s, bytes const &_b)
bool operator!=(iterator const &) const
_N toHash(int _flags=Strict) const
bool isTwoItemNode(RLP const &_n) const
bytes branch(RLP const &_orig)
bytes cleve(RLP const &_orig, unsigned _s)
void killNode(RLP const &_d)
Base class for all exceptions.
HashedGenericTrieDB(DB *_db, h256 _root, Verification _v=Verification::Normal)
NibbleSlice keyOf(bytesConstRef _hpe)
iterator lower_bound(bytesConstRef _key) const
bool contains(T const &_t, V const &_v)
HashedIterator(FatGenericTrieDB const *_trie)
std::string deref(RLP const &_n) const
bool contains(bytes const &_key)
h256 const & root() const
iterator(Generic const *_db)
void insert(bytes const &_key, bytesConstRef _value)
SpecificTrieDB(DB *_db=nullptr)
NibbleSlice mid(unsigned _index) const
void insert(KeyType _k, bytesConstRef _value)
bytesConstRef payload() const
std::vector< byte > bytes
std::vector< unsigned char > toBytes() const
vector_ref< byte const > bytesConstRef
value_type operator*() const
std::string at(bytes const &_key) const
RLPStream & appendList(size_t _items)
Appends a list.
HashedIterator hashedEnd() const
std::string node(h256 const &_h) const
bytes place(RLP const &_orig, NibbleSlice _k, bytesConstRef _s)
bytes deleteAt(RLP const &_replace, NibbleSlice _k)
unsigned shared(NibbleSlice _k) const
bytes rlpList()
Export a list of items in RLP format, returning a byte array.
h256 forceInsertNode(bytesConstRef _v)
std::pair< bytesConstRef, bytesConstRef > value_type
void insert(KeyType _k, bytes const &_value)
typename Generic::iterator Super
Nibble-based view on a bytesConstRef.
typename dev::FixedHash::DB DB
uint8_t const size_t const size
static const int verbosity
bool isEmpty() const
True if the trie is initialised but empty (i.e. that the DB contains the root node which is empty)...
void * memcpy(void *a, const void *b, size_t c)
void remove(bytes const &_key)
byte uniqueInUse(RLP const &_orig, byte except)
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
value_type operator*() const
Super::value_type at() const
std::string toString(int _flags=LaissezFaire) const
Converts to string.
SpecificTrieDB(DB *_db, h256 _root, Verification _v=Verification::Normal)
void insert(bytesConstRef _key, bytes const &_value)
GenericTrieDB< DB > const * m_that
void setRoot(h256 const &_root, Verification _v=Verification::Normal)
std::string at(KeyType _k) const
void descendList(RLP const &_r, h256Hash &_keyMask, bool _wasExt, std::ostream *_out, int _indent) const
Used for debugging, scans the whole trie.
bool contains(bytesConstRef _key)
The default logging channels.
std::unordered_set< h256 > h256Hash
DB const * db() const
Get the underlying database.
bool isEarlierThan(NibbleSlice _k) const
Determine if we, a full key, are situated prior to a particular key-prefix.
bool isEmpty() const
Contains a zero-length string or zero-length list.
typename GenericTrieDB< _DB >::iterator Super
void insert(bytes const &_key, bytes const &_value)
std::vector< Node > m_trail
value_type operator->() const
std::string operator[](KeyType _k) const
bool contains(KeyType _k) const
Class for writing to an RLP bytestream.
RLPStream & appendRaw(bytesConstRef _rlp, size_t _itemCount=1)
Appends raw (pre-serialised) RLP data. Use with caution.
std::pair< KeyType, bytesConstRef > value_type
Class for interpreting Recursive Linear-Prefix Data.
FatGenericTrieDB(DB *_db, h256 _root, Verification _v=Verification::Normal)
value_type operator->() const
std::string toString() const
GenericTrieDB(DB *_db=nullptr)
void setChild(unsigned _i)
bool contains(NibbleSlice _k) const
iterator lower_bound(KeyType _k) const
HashedIterator hashedBegin() const
iterator(HashedGenericTrieDB const *, bytesConstRef)