Fabcoin Core  0.16.2
P2P Digital Currency
TrieHash.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #if !defined(ETH_EMSCRIPTEN)
23 
24 #include "TrieHash.h"
25 #include "TrieCommon.h"
26 #include "TrieDB.h" // @TODO replace ASAP!
27 #include "SHA3.h"
28 using namespace std;
29 using namespace dev;
30 
31 namespace dev
32 {
33 
34 /*/
35 #define APPEND_CHILD appendData
36 /*/
37 #define APPEND_CHILD appendRaw
38 /**/
39 
40 #define ENABLE_DEBUG_PRINT 0
41 
42 #if ENABLE_DEBUG_PRINT
43 bool g_hashDebug = false;
44 #endif
45 
46 void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp);
47 
48 void hash256rlp(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp)
49 {
50 #if ENABLE_DEBUG_PRINT
51  static std::string s_indent;
52  if (_preLen)
53  s_indent += " ";
54 #endif
55 
56  if (_begin == _end)
57  _rlp << ""; // NULL
58  else if (std::next(_begin) == _end)
59  {
60  // only one left - terminate with the pair.
61  _rlp.appendList(2) << hexPrefixEncode(_begin->first, true, _preLen) << _begin->second;
62 #if ENABLE_DEBUG_PRINT
63  if (g_hashDebug)
64  std::cerr << s_indent << toHex(bytesConstRef(_begin->first.data() + _preLen, _begin->first.size() - _preLen), 1) << ": " << _begin->second << " = " << sha3(_rlp.out()) << std::endl;
65 #endif
66  }
67  else
68  {
69  // find the number of common prefix nibbles shared
70  // i.e. the minimum number of nibbles shared at the beginning between the first hex string and each successive.
71  unsigned sharedPre = (unsigned)-1;
72  unsigned c = 0;
73  for (auto i = std::next(_begin); i != _end && sharedPre; ++i, ++c)
74  {
75  unsigned x = std::min(sharedPre, std::min((unsigned)_begin->first.size(), (unsigned)i->first.size()));
76  unsigned shared = _preLen;
77  for (; shared < x && _begin->first[shared] == i->first[shared]; ++shared) {}
78  sharedPre = std::min(shared, sharedPre);
79  }
80  if (sharedPre > _preLen)
81  {
82  // if they all have the same next nibble, we also want a pair.
83 #if ENABLE_DEBUG_PRINT
84  if (g_hashDebug)
85  std::cerr << s_indent << toHex(bytesConstRef(_begin->first.data() + _preLen, sharedPre), 1) << ": " << std::endl;
86 #endif
87  _rlp.appendList(2) << hexPrefixEncode(_begin->first, false, _preLen, (int)sharedPre);
88  hash256aux(_s, _begin, _end, (unsigned)sharedPre, _rlp);
89 #if ENABLE_DEBUG_PRINT
90  if (g_hashDebug)
91  std::cerr << s_indent << "= " << hex << sha3(_rlp.out()) << dec << std::endl;
92 #endif
93  }
94  else
95  {
96  // otherwise enumerate all 16+1 entries.
97  _rlp.appendList(17);
98  auto b = _begin;
99  if (_preLen == b->first.size())
100  {
101 #if ENABLE_DEBUG_PRINT
102  if (g_hashDebug)
103  std::cerr << s_indent << "@: " << b->second << std::endl;
104 #endif
105  ++b;
106  }
107  for (auto i = 0; i < 16; ++i)
108  {
109  auto n = b;
110  for (; n != _end && n->first[_preLen] == i; ++n) {}
111  if (b == n)
112  _rlp << "";
113  else
114  {
115 #if ENABLE_DEBUG_PRINT
116  if (g_hashDebug)
117  std::cerr << s_indent << std::hex << i << ": " << std::dec << std::endl;
118 #endif
119  hash256aux(_s, b, n, _preLen + 1, _rlp);
120  }
121  b = n;
122  }
123  if (_preLen == _begin->first.size())
124  _rlp << _begin->second;
125  else
126  _rlp << "";
127 
129  if (g_hashDebug)
130  std::cerr << s_indent << "= " << hex << sha3(_rlp.out()) << dec << std::endl;
131 #endif
132  }
133  }
134 #if ENABLE_DEBUG_PRINT
135  if (_preLen)
136  s_indent.resize(s_indent.size() - 2);
137 #endif
138 }
139 
140 void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp)
141 {
142  RLPStream rlp;
143  hash256rlp(_s, _begin, _end, _preLen, rlp);
144  if (rlp.out().size() < 32)
145  {
146  // RECURSIVE RLP
147 #if ENABLE_DEBUG_PRINT
148  cerr << "[INLINE: " << dec << rlp.out().size() << " < 32]" << endl;
149 #endif
150  _rlp.APPEND_CHILD(rlp.out());
151  }
152  else
153  {
154 #if ENABLE_DEBUG_PRINT
155  cerr << "[HASH: " << dec << rlp.out().size() << " >= 32]" << endl;
156 #endif
157  _rlp << sha3(rlp.out());
158  }
159 }
160 
162 {
163  // build patricia tree.
164  if (_s.empty())
165  return rlp("");
166  HexMap hexMap;
167  for (auto i = _s.rbegin(); i != _s.rend(); ++i)
168  hexMap[asNibbles(bytesConstRef(&i->first))] = i->second;
169  RLPStream s;
170  hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
171  return s.out();
172 }
173 
175 {
176  return sha3(rlp256(_s));
177 }
178 
179 h256 orderedTrieRoot(std::vector<bytes> const& _data)
180 {
181  BytesMap m;
182  unsigned j = 0;
183  for (auto i: _data)
184  m[rlp(j++)] = i;
185  return hash256(m);
186 }
187 
188 h256 orderedTrieRoot(std::vector<bytesConstRef> const& _data)
189 {
190  BytesMap m;
191  unsigned j = 0;
192  for (auto i: _data)
193  m[rlp(j++)] = i.toBytes();
194  return hash256(m);
195 }
196 
197 }
198 
199 #endif // ETH_EMSCRIPTEN
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
std::string toHex(T const &_data, int _w=2, HexPrefix _prefix=HexPrefix::DontAdd)
Definition: CommonData.h:54
std::map< bytes, bytes > BytesMap
Definition: Common.h:138
h256 orderedTrieRoot(std::vector< bytesConstRef > const &_data)
Definition: TrieHash.cpp:188
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
Definition: RLP.h:467
std::string hexPrefixEncode(bytes const &_hexVector, bool _leaf, int _begin, int _end)
Definition: TrieCommon.cpp:43
bytes const & out() const
Read the byte stream.
Definition: RLP.h:433
#define c(i)
std::hash for asio::adress
Definition: Common.h:323
ExecStats::duration min
Definition: ExecStats.cpp:35
if(a.IndicesBefore(b, len, lenIndices))
Definition: equihash.cpp:243
#define ENABLE_DEBUG_PRINT
Definition: TrieHash.cpp:40
void hash256rlp(HexMap const &_s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream &_rlp)
Definition: TrieHash.cpp:48
h256 hash256(BytesMap const &_s)
Definition: TrieHash.cpp:174
#define x(i)
std::vector< byte > bytes
Definition: Common.h:75
vector_ref< byte const > bytesConstRef
Definition: Common.h:77
RLPStream & appendList(size_t _items)
Appends a list.
Definition: RLP.cpp:276
bytes asNibbles(bytesConstRef const &_s)
Definition: CommonData.cpp:129
#define b(i, j)
std::map< bytes, bytes > HexMap
Definition: Common.h:140
bytes rlp256(BytesMap const &_s)
Definition: TrieHash.cpp:161
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
Definition: SHA3.cpp:214
Class for writing to an RLP bytestream.
Definition: RLP.h:383
void hash256aux(HexMap const &_s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream &_rlp)
Definition: TrieHash.cpp:140