Browse Source

Merkle hash implementation. Needs testing.

cl-refactor
Gav Wood 11 years ago
parent
commit
f5e62823f2
  1. 8
      Common.h
  2. 77
      PatriciaTree.h
  3. 41
      RLP.h
  4. 44
      main.cpp

8
Common.h

@ -23,4 +23,12 @@ using sint = int64_t;
template <class _T> std::string toString(_T const& _t) { std::ostringstream o; o << _t; return o.str(); }
template <class _T> inline std::string asHex(_T const& _data)
{
std::ostringstream ret;
for (auto i: _data)
ret << std::hex << std::setfill('0') << std::setw(2) << (int)i;
return ret.str();
}
}

77
PatriciaTree.h

@ -25,7 +25,7 @@ using HexMap = std::map<bytes, std::string>;
* [1,2,3,4,T] 0x201234
*/
inline std::string fromHex(bytes const& _hexVector, bool _terminated = false, int _begin = 0, int _end = -1)
inline std::string hexPrefixEncode(bytes const& _hexVector, bool _terminated = false, int _begin = 0, int _end = -1)
{
uint begin = _begin;
uint end = _end < 0 ? _hexVector.size() + 1 + _end : _end;
@ -43,42 +43,73 @@ inline std::string fromHex(bytes const& _hexVector, bool _terminated = false, in
return ret;
}
inline u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen)
inline bytes toHex(std::string const& _s)
{
unsigned c = 0;
for (auto i = _begin; i != _end; ++i, ++c) {}
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;
}
assert(c > 0);
inline u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen)
{
RLPStream rlp;
if (c == 1)
if (_begin == _end)
{
rlp << ""; // NULL
}
else if (std::next(_begin) == _end)
{
// only one left - terminate with the pair.
rlp << RLPList(2) << fromHex(_begin->first, true, _preLen) << _begin->second;
rlp << RLPList(2) << hexPrefixEncode(_begin->first, true, _preLen) << _begin->second;
}
else
{
// if they all have the same next nibble, we also want a pair.
// otherwise enumerate all 16+1 entries.
for (auto i = 0; i < 16; ++i)
// find the number of common prefix nibbles shared
// i.e. the minimum number of nibbles shared at the beginning between the first hex string and each successive.
uint sharedPre = (uint)-1;
uint c = 0;
for (auto i = std::next(_begin); i != _end && sharedPre; ++i, ++c)
{
uint x = std::min(sharedPre, std::min(_begin->first.size(), i->first.size()));
uint shared = _preLen;
for (; shared < x && _begin->first[shared] == i->first[shared]; ++shared) {}
sharedPre = std::min(shared, sharedPre);
}
if (sharedPre > _preLen)
{
// if they all have the same next nibble, we also want a pair.
rlp << RLPList(2) << hexPrefixEncode(_begin->first, false, _preLen, sharedPre) << hash256aux(_s, _begin, _end, sharedPre);
}
else
{
// otherwise enumerate all 16+1 entries.
rlp << RLPList(17);
auto b = _begin;
if (_preLen == b->first.size())
++b;
for (auto i = 0; i < 16; ++i)
{
auto n = b;
for (; n != _end && n->first[_preLen] == i; ++n) {}
if (b == n)
rlp << "";
else
rlp << hash256aux(_s, b, n, _preLen + 1);
b = n;
}
if (_preLen == _begin->first.size())
rlp << _begin->second;
}
}
std::cout << std::hex << sha256(rlp.out()) << ": " << RLP(rlp.out()) << std::endl;
return sha256(rlp.out());
}
inline bytes toHex(std::string const& _s)
{
std::vector<uint8_t> ret(_s.size() * 2 + 1);
for (auto i: _s)
{
ret.push_back(i / 16);
ret.push_back(i % 16);
}
ret.push_back(16);
return ret;
}
inline u256 hash256(StringMap const& _s)
{
// build patricia tree.

41
RLP.h

@ -1,6 +1,7 @@
#pragma once
#include <iostream>
#include <iomanip>
#include "foreign.h"
#include "Common.h"
@ -142,6 +143,8 @@ private:
uint size() const
{
if (isNull())
return 0;
if (isInt())
return 1 + intSize();
if (isString())
@ -210,12 +213,12 @@ public:
pushCount(_count, 0x80);
}
RLPStream operator<<(uint _i) { append(_i); return *this; }
RLPStream operator<<(u256 _i) { append(_i); return *this; }
RLPStream operator<<(bigint _i) { append(_i); return *this; }
RLPStream operator<<(char const* _s) { append(std::string(_s)); return *this; }
RLPStream operator<<(std::string const& _s) { append(_s); return *this; }
RLPStream operator<<(RLPList _l) { appendList(_l.count); return *this; }
RLPStream& operator<<(uint _i) { append(_i); return *this; }
RLPStream& operator<<(u256 _i) { append(_i); return *this; }
RLPStream& operator<<(bigint _i) { append(_i); return *this; }
RLPStream& operator<<(char const* _s) { append(std::string(_s)); return *this; }
RLPStream& operator<<(std::string const& _s) { append(_s); return *this; }
RLPStream& operator<<(RLPList _l) { appendList(_l.count); return *this; }
bytes const& out() const { return m_out; }
std::string str() const { return std::string((char const*)m_out.data(), (char const*)(m_out.data() + m_out.size())); }
@ -292,14 +295,36 @@ private:
}
inline std::string escaped(std::string const& _s)
{
std::string ret;
ret.reserve(_s.size());
ret.push_back('"');
for (auto i: _s)
if (i == '"')
ret += "\\\"";
else if (i == '\\')
ret += "\\\\";
else if (i < ' ' || i > 127)
{
ret += "\\x";
ret.push_back("0123456789abcdef"[i / 16]);
ret.push_back("0123456789abcdef"[i % 16]);
}
else
ret.push_back(i);
ret.push_back('"');
return ret;
}
inline std::ostream& operator<<(std::ostream& _out, eth::RLP _d)
{
if (_d.isNull())
_out << "null";
else if (_d.isInt())
_out << _d.toBigInt();
_out << std::showbase << std::hex << std::nouppercase << _d.toBigInt();
else if (_d.isString())
_out << "\"" << _d.toString() << "\"";
_out << escaped(_d.toString());
else if (_d.isList())
{
_out << "[";

44
main.cpp

@ -1,25 +1,10 @@
#include "Common.h"
#include "RLP.h"
#include "PatriciaTree.h"
#include "VirtualMachine.h"
using namespace std;
using namespace eth;
std::string asHex(std::string const& _data)
{
std::ostringstream ret;
for (auto i: _data)
ret << hex << setfill('0') << setw(2) << (int)i;
return ret.str();
}
std::string asHex(bytes const& _data)
{
std::ostringstream ret;
for (auto i: _data)
ret << hex << setfill('0') << setw(2) << (int)i;
return ret.str();
}
template <class _T> void rlpListAux(RLPStream& _out, _T _t)
{
_out << _t;
@ -48,6 +33,11 @@ template <class ... _Ts> std::string rlpList(_Ts ... _ts)
int main()
{
cout << hex << hash256({{"dog", "puppy"}}) << endl;
cout << hex << hash256({{"dog", "puppy"}, {"horse", "stallion"}}) << endl;
cout << hex << hash256({{"dog", "puppy"}, {"doge", "coin"}}) << endl;
cout << hex << hash256({{"dog", "puppy"}, {"horse", "stallion"}, {"do", "verb"}, {"doge", "coin"}}) << endl;
// int of value 15
assert(RLP("\x0f") == 15);
assert(rlp(15) == "\x0f");
@ -95,17 +85,17 @@ int main()
* [1,2,3,4,5,T] 0x312345
* [1,2,3,4,T] 0x201234
*/
assert(asHex(fromHex({0, 0, 1, 2, 3, 4, 5}, false)) == "10012345");
assert(asHex(fromHex({0, 1, 2, 3, 4, 5}, false)) == "00012345");
assert(asHex(fromHex({1, 2, 3, 4, 5}, false)) == "112345");
assert(asHex(fromHex({0, 0, 1, 2, 3, 4}, false)) == "00001234");
assert(asHex(fromHex({0, 1, 2, 3, 4}, false)) == "101234");
assert(asHex(fromHex({1, 2, 3, 4}, false)) == "001234");
assert(asHex(fromHex({0, 0, 1, 2, 3, 4, 5}, true)) == "30012345");
assert(asHex(fromHex({0, 0, 1, 2, 3, 4}, true)) == "20001234");
assert(asHex(fromHex({0, 1, 2, 3, 4, 5}, true)) == "20012345");
assert(asHex(fromHex({1, 2, 3, 4, 5}, true)) == "312345");
assert(asHex(fromHex({1, 2, 3, 4}, true)) == "201234");
assert(asHex(hexPrefixEncode({0, 0, 1, 2, 3, 4, 5}, false)) == "10012345");
assert(asHex(hexPrefixEncode({0, 1, 2, 3, 4, 5}, false)) == "00012345");
assert(asHex(hexPrefixEncode({1, 2, 3, 4, 5}, false)) == "112345");
assert(asHex(hexPrefixEncode({0, 0, 1, 2, 3, 4}, false)) == "00001234");
assert(asHex(hexPrefixEncode({0, 1, 2, 3, 4}, false)) == "101234");
assert(asHex(hexPrefixEncode({1, 2, 3, 4}, false)) == "001234");
assert(asHex(hexPrefixEncode({0, 0, 1, 2, 3, 4, 5}, true)) == "30012345");
assert(asHex(hexPrefixEncode({0, 0, 1, 2, 3, 4}, true)) == "20001234");
assert(asHex(hexPrefixEncode({0, 1, 2, 3, 4, 5}, true)) == "20012345");
assert(asHex(hexPrefixEncode({1, 2, 3, 4, 5}, true)) == "312345");
assert(asHex(hexPrefixEncode({1, 2, 3, 4}, true)) == "201234");
return 0;
}

Loading…
Cancel
Save