Browse Source

Minor fix and some part-finished work on Trie.

cl-refactor
Gav Wood 11 years ago
parent
commit
d5afc3f3ee
  1. 2
      libethereum/Transaction.h
  2. 99
      libethereum/Trie.cpp
  3. 12
      libethereum/Trie.h

2
libethereum/Transaction.h

@ -55,7 +55,7 @@ struct Transaction
void fillStream(RLPStream& _s, bool _sig = true) const; void fillStream(RLPStream& _s, bool _sig = true) const;
bytes rlp(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.out(); } bytes rlp(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.out(); }
std::string rlpString(bool _sig = true) const { return asString(rlp()); } std::string rlpString(bool _sig = true) const { return asString(rlp(_sig)); }
h256 sha3(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha3(s.out()); } h256 sha3(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha3(s.out()); }
bytes sha3Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha3Bytes(s.out()); } bytes sha3Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha3Bytes(s.out()); }
}; };

99
libethereum/Trie.cpp

@ -669,13 +669,13 @@ h256 const GenericTrieDB::c_null = sha3(RLPNull);
inline byte nibble(bytesConstRef _data, uint _i) inline byte nibble(bytesConstRef _data, uint _i)
{ {
return (i & 1) ? (_data[i / 2] & 15) : (_data[i / 2] >> 4); return (_i & 1) ? (_data[_i / 2] & 15) : (_data[_i / 2] >> 4);
} }
std::string hexPrefixEncode(bytesConstRef _data, bool _terminated, int _beginNibble, int _endNibble) std::string hexPrefixEncode(bytesConstRef _data, bool _terminated, int _beginNibble, int _endNibble)
{ {
uint begin = _begin; uint begin = _beginNibble;
uint end = _end < 0 ? _data.size() * 2 + 1 + _end : _end; uint end = _endNibble < 0 ? _data.size() * 2 + 1 + _endNibble : _endNibble;
bool odd = (end - begin) & 1; bool odd = (end - begin) & 1;
std::string ret(1, ((_terminated ? 2 : 0) | (odd ? 1 : 0)) * 16); std::string ret(1, ((_terminated ? 2 : 0) | (odd ? 1 : 0)) * 16);
@ -702,46 +702,71 @@ uint sharedNibbles(bytesConstRef _a, uint _ab, uint _ae, bytesConstRef _b, uint
// alters given RLP such that the given key[_begin:_end]/value exists under it, and puts the new RLP into _s. // alters given RLP such that the given key[_begin:_end]/value exists under it, and puts the new RLP into _s.
// _s's size could be anything. // _s's size could be anything.
void GenericTrieDB::insertHelper(RLPStream& _s, RLP const& _node, bytesConstRef _key, bytesConstRef _value, uint _begin, uint _end) void GenericTrieDB::mergeHelper(RLPStream& _s, RLP const& _replace, bytesConstRef _key, bytesConstRef _value, uint _begin, uint _end, uint _nodeBegin)
{ {
if (_node.isNull() || _node.isEmpty()) /* if (_replace.isNull() || _replace.isEmpty())
{ {
_s.insertList(2); _s.insertList(2);
_s << hexPrefixEncode(_key, true, _begin, _end); _s << hexPrefixEncode(_key, true, _begin, _end);
_s.appendString(_value); _s.appendString(_value);
} }
else if (_node.itemCount() == 2) else if (_replace.itemCount() == 2)
{ {
// split [k,v] into branch // split [k,v] into branch
auto pl = _node[0].payload(); auto pl = _replace[0].payload();
auto plb = (_node[0] & 0x10) ? 1 : 2; auto plb = ((pl[0] & 0x10) ? 1 : 2) + _nodeBegin;
auto ple = pl.size() - plb; auto ple = pl.size() - plb;
uint pivot = sharedNibbles(_key, _begin, _end, pl, plb, ple); uint pivot = sharedNibbles(_key, _begin, _end, pl, plb, ple);
// special case for pivot == first nibble, pivot == last nibble. if it's anything else, need stem, branch, 2 stems (old & new) // special case for pivot == first nibble, pivot == last nibble. if it's anything else, then it's recursive.
if (pivot == _end - _begin && pivot == ple - plb) if (pivot == ple - plb && !(pl[0] & 0x20)) // key begins with node-partial and is non-terminated - leave it as the child node's problem.
{
// share this non-termed 2-item node - merge in below.
_s.insertList(2);
_s << _replace[0];
mergeNode(_s, _replace[1], _key, _value, _begin + pivot, _end, 0);
}
else if (pivot == ple - plb && pivot == _end - _begin && (pl[0] & 0x20)) // key and value exactly the same and is terminated - just replace value.
{ {
_s.insertList(2); _s.insertList(2);
_s << _node[0]; _s << hexPrefixEncode(_key, true, _begin, _end);
_s.appendString(_value); _s.appendString(_value);
} }
else else
{ {
if (pivot == 0) if (pivot == 0)
{ {
// branch immediately // branch since the pivot is right here.
_s.insertList(17); _s.insertList(17);
if (_begin == _end)
{ auto n = plb == ple ? 16 : nibble(pl, plb);
// as value auto m = _begin == _end ? 16 : nibble(_key, _begin);
for (auto i = 0; i < 16; ++i) for (auto i = 0; i < 16; ++i)
_s << _node[i]; if (i == n)
_s << _value; remerge(_s, _replace, _nodeBegin);
else if (i == m)
mergeItem(_s, RLP(), _key, _value, _begin, _end);
else
_s << "";
if (n == 16)
{
assert(pl[0] & 0x20);
// this should be terminated - if it's not and we share the entire 2-node partial key's worth of nibbles, then why didn't we skip over the 2-item node and merge directly into the branch below?
_s.appendRaw(_replace[1]);
} }
else if (m == 16)
_s << _value;
else
s << "";
} }
else else
{
_s.insertList(2);
_s << hexPrefixEncode(_key, false, _begin, _begin + pivot);
mergeItem(_s, _replace, _key, _value, _begin + pivot, _end, _nodeBegin + pivot);
}
} }
} }
else if (_node.itemCount() == 17) else if (_replace.itemCount() == 17)
{ {
// insert into branch // insert into branch
_s.insertList(17); _s.insertList(17);
@ -749,7 +774,7 @@ void GenericTrieDB::insertHelper(RLPStream& _s, RLP const& _node, bytesConstRef
{ {
// as value // as value
for (auto i = 0; i < 16; ++i) for (auto i = 0; i < 16; ++i)
_s << _node[i]; _s << _replace[i];
_s << _value; _s << _value;
} }
else else
@ -758,36 +783,44 @@ void GenericTrieDB::insertHelper(RLPStream& _s, RLP const& _node, bytesConstRef
auto n = nibble(_key, _begin); auto n = nibble(_key, _begin);
for (auto i = 0; i < 17; ++i) for (auto i = 0; i < 17; ++i)
if (n == i) if (n == i)
insertItem(s, _node[i], _key, _value, _begin, _end); insertItem(s, _replace[i], _key, _value, _begin, _end);
else else
_s << _node[i]; _s << _replace[i];
}
} }
}*/
} }
// Inserts the given item into an RLPStream, either inline (if RLP < 32) or creating a node and inserting the hash. // Inserts the given item into an RLPStream, either inline (if RLP < 32) or creating a node and inserting the hash.
void GenericTrieDB::insertItem(RLPStream& _s, RLP const& _node, bytesConstRef _k, bytesConstRef _v, uint _begin, uint _end) // Assumes we are _nodeBegin of the way through the key of the _replace.
void GenericTrieDB::mergeItem(RLPStream& _s, RLP const& _replace, bytesConstRef _k, bytesConstRef _v, uint _begin, uint _end, uint _nodeBegin)
{ {
/*
RLPStream s;
mergeHelper(s, (_replace.isString() || _replace.isInt()) ? RLP(node(_replace.toHash())) : _replace, _k, _v, _begin, _end, _nodeBegin);
streamNode(s, s.out());
// Kill old node. // Kill old node.
if (_node.isString() || _node.isInt()) if ((_replace.isString() || _replace.isInt()) && _nodeBegin == 0)
killNode(_node.toHash()); killNode(_replace.toHash());
*/
}
RLPStream s; void GenericTrieDB::streamNode(RLPStream& _s, bytes const& _b)
insertHelper(s, _node, _k, _v, _begin, _end); {
if (s.size() < 32) if (_b.size() < 32)
_s.insertRaw(s.out()); _s.appendRaw(_b);
else else
_s << insertNode(s.out()); _s << insertNode(&_b);
} }
void GenericTrieDB::insert(bytesConstRef _key, bytesConstRef _value, ) void GenericTrieDB::insert(bytesConstRef _key, bytesConstRef _value)
{ {
string rv = node(m_root); string rv = node(m_root);
killNode(m_root); killNode(m_root);
RLPStream s; RLPStream s;
insertHelper(s, RLP(rv), _key, _value, 0, _key.size() * 2); mergeHelper(s, RLP(rv), _key, _value, 0, _key.size() * 2, 0);
m_root = insertNode(s.out()); m_root = insertNode(&s.out());
} }
void GenericTrieDB::remove(bytesConstRef _key) void GenericTrieDB::remove(bytesConstRef _key)

12
libethereum/Trie.h

@ -96,18 +96,20 @@ public:
void debugPrint() {} void debugPrint() {}
std::string at(bytesConstRef _key) const { return std::string(); } std::string at(bytesConstRef _key) const;
void insert(bytesConstRef _key, bytesConstRef _value); void insert(bytesConstRef _key, bytesConstRef _value);
void remove(bytesConstRef _key) {} void remove(bytesConstRef _key);
// TODO: iterators. // TODO: iterators.
private: private:
void insertHelper(bytesConstRef _key, bytesConstRef _value, uint _begin, uint _end); void streamNode(RLPStream& _s, bytes const& _b);
void mergeHelper(RLPStream& _s, RLP const& _replace, bytesConstRef _key, bytesConstRef _value, uint _begin, uint _end, uint _nodeBegin = 0);
void mergeItem(RLPStream& _s, RLP const& _replace, bytesConstRef _k, bytesConstRef _v, uint _begin, uint _end, uint _nodeBegin = 0);
std::string node(h256 _h) const { if (_h == c_null) return std::string(); if (m_over) { auto it = m_over->find(_h); if (it != m_over->end()) return it->second; } std::string ret; if (m_db) m_db->Get(m_readOptions, ldb::Slice((char const*)&m_root, 32), &ret); return ret; } std::string node(h256 _h) const { if (_h == c_null) return std::string(); if (m_over) { auto it = m_over->find(_h); if (it != m_over->end()) return it->second; } std::string ret; if (m_db) m_db->Get(m_readOptions, ldb::Slice((char const*)&m_root, 32), &ret); return ret; }
void insertNode(h256 _h, bytesConstRef _v) const { m_over[_h] = _v; } void insertNode(h256 _h, bytesConstRef _v) const { (*m_over)[_h] = _v.toString(); }
h256 insertNode(bytesConstRef _v) const { auto h = sha3(_v); m_over[h] = _v; return h; } h256 insertNode(bytesConstRef _v) const { auto h = sha3(_v); (*m_over)[h] = _v.toString(); return h; }
void killNode(h256 _h) const { m_over->erase(_h); } // only from overlay - no killing from DB proper. void killNode(h256 _h) const { m_over->erase(_h); } // only from overlay - no killing from DB proper.
static const h256 c_null; static const h256 c_null;

Loading…
Cancel
Save