Browse Source

use TrieHash for transactions and receipts roots

cl-refactor
arkpar 10 years ago
parent
commit
e19ac5054c
  1. 3
      libdevcore/Common.h
  2. 12
      libdevcore/CommonData.cpp
  3. 1
      libdevcore/CommonData.h
  4. 29
      libdevcrypto/TrieHash.cpp
  5. 5
      libdevcrypto/TrieHash.h
  6. 20
      libethereum/State.cpp
  7. 57
      test/libdevcrypto/trie.cpp

3
libdevcore/Common.h

@ -86,8 +86,9 @@ extern const u256 UndefinedU256;
// Map types.
using StringMap = std::map<std::string, std::string>;
using BytesMap = std::map<bytes, bytes>;
using u256Map = std::map<u256, u256>;
using HexMap = std::map<bytes, std::string>;
using HexMap = std::map<bytes, bytes>;
// Hash types.
using StringHashMap = std::unordered_map<std::string, std::string>;

12
libdevcore/CommonData.cpp

@ -115,6 +115,18 @@ bytes dev::fromHex(std::string const& _s, WhenError _throw)
return ret;
}
bytes dev::asNibbles(bytes const& _s)
{
std::vector<uint8_t> ret;
ret.reserve(_s.size() * 2);
for (auto i: _s)
{
ret.push_back(i / 16);
ret.push_back(i % 16);
}
return ret;
}
bytes dev::asNibbles(std::string const& _s)
{
std::vector<uint8_t> ret;

1
libdevcore/CommonData.h

@ -96,6 +96,7 @@ inline bytes asBytes(std::string const& _b)
/// Converts a string into the big-endian base-16 stream of integers (NOT ASCII).
/// @example asNibbles("A")[0] == 4 && asNibbles("A")[1] == 1
bytes asNibbles(std::string const& _s);
bytes asNibbles(bytes const& _s);
// Big-endian to/from host endian conversion functions.

29
libdevcrypto/TrieHash.cpp

@ -158,43 +158,48 @@ void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_i
}
}
h256 hash256(StringMap const& _s)
bytes rlp256(BytesMap const& _s)
{
// build patricia tree.
if (_s.empty())
return sha3(rlp(""));
return rlp("");
HexMap hexMap;
for (auto i = _s.rbegin(); i != _s.rend(); ++i)
hexMap[asNibbles(i->first)] = i->second;
RLPStream s;
hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
return sha3(s.out());
return s.out();
}
bytes rlp256(StringMap const& _s)
h256 hash256(BytesMap const& _s)
{
return sha3(rlp256(_s));
}
h256 hash256(StringMap const& _s)
{
// build patricia tree.
if (_s.empty())
return rlp("");
return sha3(rlp(""));
HexMap hexMap;
for (auto i = _s.rbegin(); i != _s.rend(); ++i)
hexMap[asNibbles(i->first)] = i->second;
hexMap[asNibbles(i->first)] = bytes(i->second.begin(), i->second.end());
RLPStream s;
hash256aux(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
return s.out();
hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
return sha3(s.out());
}
h256 hash256(u256Map const& _s)
bytes rlp256(StringMap const& _s)
{
// build patricia tree.
if (_s.empty())
return sha3(rlp(""));
return rlp("");
HexMap hexMap;
for (auto i = _s.rbegin(); i != _s.rend(); ++i)
hexMap[asNibbles(toBigEndianString(i->first))] = asString(rlp(i->second));
hexMap[asNibbles(i->first)] = bytes(i->second.begin(), i->second.end());
RLPStream s;
hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
return sha3(s.out());
return s.out();
}
/*h256 orderedTrieRoot(std::vector<bytes> const& _data)

5
libdevcrypto/TrieHash.h

@ -27,9 +27,10 @@
namespace dev
{
bytes rlp256(BytesMap const& _s);
h256 hash256(BytesMap const& _s);
bytes rlp256(StringMap const& _s);
h256 hash256(StringMap const& _s);
h256 hash256(u256Map const& _s);
/*h256 orderedTrieRoot(std::vector<bytes> const& _data);
@ -41,8 +42,6 @@ template <class T, class U> inline h256 trieRootOver(unsigned _itemCount, T cons
return hash256(m);
}*/
using bytesMap = std::unordered_map<bytes, bytes>;
h256 orderedTrieRoot(std::vector<bytesConstRef> const& _data);
h256 orderedTrieRoot(std::vector<bytes> const& _data);

20
libethereum/State.cpp

@ -840,16 +840,8 @@ void State::commitToMine(BlockChain const& _bc)
}
}
// TODO: move over to using TrieHash
MemoryDB tm;
GenericTrieDB<MemoryDB> transactionsTrie(&tm);
transactionsTrie.init();
MemoryDB rm;
GenericTrieDB<MemoryDB> receiptsTrie(&rm);
receiptsTrie.init();
BytesMap transactionsMap;
BytesMap receiptsMap;
RLPStream txs;
txs.appendList(m_transactions.size());
@ -861,11 +853,11 @@ void State::commitToMine(BlockChain const& _bc)
RLPStream receiptrlp;
m_receipts[i].streamRLP(receiptrlp);
receiptsTrie.insert(&k.out(), &receiptrlp.out());
receiptsMap.insert(std::make_pair(k.out(), receiptrlp.out()));
RLPStream txrlp;
m_transactions[i].streamRLP(txrlp);
transactionsTrie.insert(&k.out(), &txrlp.out());
transactionsMap.insert(std::make_pair(k.out(), txrlp.out()));
txs.appendRaw(txrlp.out());
}
@ -874,8 +866,8 @@ void State::commitToMine(BlockChain const& _bc)
RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles);
m_currentBlock.transactionsRoot = transactionsTrie.root();
m_currentBlock.receiptsRoot = receiptsTrie.root();
m_currentBlock.transactionsRoot = hash256(transactionsMap);
m_currentBlock.receiptsRoot = hash256(receiptsMap);
m_currentBlock.logBloom = logBloom();
m_currentBlock.sha3Uncles = sha3(m_currentUncles);

57
test/libdevcrypto/trie.cpp

@ -294,15 +294,27 @@ BOOST_AUTO_TEST_CASE(trie_tests_ordered)
}
}
inline h256 stringMapHash256(StringMap const& _s)
h256 stringMapHash256(StringMap const& _s)
{
return hash256(_s);
//return hash256(_s);
BytesMap bytesMap;
for (auto const& _v: _s)
bytesMap.insert(std::make_pair(bytes(_v.first.begin(), _v.first.end()), bytes(_v.second.begin(), _v.second.end())));
return hash256(bytesMap);
}
bytes stringMapRlp256(StringMap const& _s)
{
//return rlp256(_s);
BytesMap bytesMap;
for (auto const& _v: _s)
bytesMap.insert(std::make_pair(bytes(_v.first.begin(), _v.first.end()), bytes(_v.second.begin(), _v.second.end())));
return rlp256(bytesMap);
}
BOOST_AUTO_TEST_CASE(moreTrieTests)
{
cnote << "Testing Trie more...";
#if 0
// More tests...
{
MemoryDB m;
@ -311,7 +323,7 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
cout << t;
cout << m;
cout << t.root() << endl;
cout << hash256(StringMap()) << endl;
cout << stringMapHash256(StringMap()) << endl;
t.insert(string("tesz"), string("test"));
cout << t;
@ -336,7 +348,7 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
t.remove(string("test"));
cout << m;
cout << t.root() << endl;
cout << hash256(StringMap()) << endl;
cout << stringMapHash256(StringMap()) << endl;
}
{
MemoryDB m;
@ -348,20 +360,23 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
cout << m;
cout << t.root() << endl;
cout << stringMapHash256({{"b", "B"}, {"a", "A"}}) << endl;
cout << RLP(rlp256({{"b", "B"}, {"a", "A"}})) << endl;
bytes r(stringMapRlp256({{"b", "B"}, {"a", "A"}}));
cout << RLP(r) << endl;
}
{
MemTrie t;
t.insert("dog", "puppy");
cout << hex << t.hash256() << endl;
cout << RLP(t.rlp()) << endl;
bytes r(t.rlp());
cout << RLP(r) << endl;
}
{
MemTrie t;
t.insert("bed", "d");
t.insert("be", "e");
cout << hex << t.hash256() << endl;
cout << RLP(t.rlp()) << endl;
bytes r(t.rlp());
cout << RLP(r) << endl;
}
{
cout << hex << stringMapHash256({{"dog", "puppy"}, {"doe", "reindeer"}}) << endl;
@ -369,10 +384,10 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
t.insert("dog", "puppy");
t.insert("doe", "reindeer");
cout << hex << t.hash256() << endl;
cout << RLP(t.rlp()) << endl;
bytes r(t.rlp());
cout << RLP(r) << endl;
cout << toHex(t.rlp()) << endl;
}
#endif
{
MemoryDB m;
EnforceRefs r(m, true);
@ -387,16 +402,17 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
t.insert(a, b);
s[a] = b;
/*cout << endl << "-------------------------------" << endl;
cout << endl << "-------------------------------" << endl;
cout << a << " -> " << b << endl;
cout << d;
cout << m;
cout << d.root() << endl;
cout << hash256(s) << endl;*/
cout << hash256(s) << endl;
cout << stringMapHash256(s) << endl;
BOOST_REQUIRE(d.check(true));
BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s));
BOOST_REQUIRE_EQUAL(d.root(), hash256(s));
BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s));
BOOST_REQUIRE_EQUAL(d.root(), stringMapHash256(s));
for (auto const& i: s)
{
(void)i;
@ -421,8 +437,8 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
BOOST_REQUIRE(d.check(true));
BOOST_REQUIRE(t.at(a).empty());
BOOST_REQUIRE(d.at(string(a)).empty());
BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s));
BOOST_REQUIRE_EQUAL(d.root(), hash256(s));
BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s));
BOOST_REQUIRE_EQUAL(d.root(), stringMapHash256(s));
for (auto const& i: s)
{
(void)i;
@ -493,7 +509,6 @@ BOOST_AUTO_TEST_CASE(trieLowerBound)
BOOST_AUTO_TEST_CASE(trieStess)
{
cnote << "Stress-testing Trie...";
if (0)
{
MemoryDB m;
MemoryDB dm;
@ -512,8 +527,8 @@ BOOST_AUTO_TEST_CASE(trieStess)
m[k] = v;
t.insert(k, v);
d.insert(k, v);
BOOST_REQUIRE_EQUAL(hash256(m), t.hash256());
BOOST_REQUIRE_EQUAL(hash256(m), d.root());
BOOST_REQUIRE_EQUAL(stringMapHash256(m), t.hash256());
BOOST_REQUIRE_EQUAL(stringMapHash256(m), d.root());
BOOST_REQUIRE(d.check(true));
}
while (!m.empty())
@ -557,8 +572,8 @@ BOOST_AUTO_TEST_CASE(trieStess)
cwarn << "Good?" << d2.root();
}
BOOST_REQUIRE(d.check(true));
BOOST_REQUIRE_EQUAL(hash256(m), t.hash256());
BOOST_REQUIRE_EQUAL(hash256(m), d.root());
BOOST_REQUIRE_EQUAL(stringMapHash256(m), t.hash256());
BOOST_REQUIRE_EQUAL(stringMapHash256(m), d.root());
}
}
}

Loading…
Cancel
Save