16
16
#include < stack>
17
17
#include < vector>
18
18
19
- #ifdef WIN32
20
- # include < stdlib.h>
21
- # if BYTE_ORDER == LITTLE_ENDIAN
22
- # define htobe32 (X ) _byteswap_ulong(X)
23
- # define be32toh (X ) _byteswap_ulong(X)
24
- # define htobe64 (X ) _byteswap_uint64(X)
25
- # define be64toh (X ) _byteswap_uint64(X)
26
- # else
27
- # define htobe32 (X ) (X)
28
- # define be32toh (X ) (X)
29
- # define htobe64 (X ) (X)
30
- # define be64toh (X ) (X)
31
- # endif
32
- # undef max
33
- #endif
34
-
35
19
#ifdef HAVE_OPENSSL
36
20
# include < openssl/sha.h>
37
21
#endif
63
47
64
48
namespace merkle
65
49
{
66
- inline void serialise_size_t (size_t size, std::vector<uint8_t >& bytes)
50
+ static inline uint32_t convert_endianness (uint32_t n)
51
+ {
52
+ const uint32_t sz = sizeof (uint32_t );
53
+ #if defined(htobe32)
54
+ // If htobe32 happens to be a macro, use it.
55
+ return htobe32 (n);
56
+ #elif defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN)
57
+ // Just as fast.
58
+ uint32_t r = 0 ;
59
+ for (size_t i = 0 ; i < sz; i++)
60
+ r |= ((n >> (8 * ((sz - 1 ) - i))) & 0xFF ) << (8 * i);
61
+ return *reinterpret_cast <uint32_t *>(&r);
62
+ #else
63
+ // A little slower, but works for both endiannesses.
64
+ uint8_t r[8 ];
65
+ for (size_t i = 0 ; i < sz; i++)
66
+ r[i] = (n >> (8 * ((sz - 1 ) - i))) & 0xFF ;
67
+ return *reinterpret_cast <uint32_t *>(&r);
68
+ #endif
69
+ }
70
+
71
+ static inline void serialise_uint64_t (uint64_t n, std::vector<uint8_t >& bytes)
67
72
{
68
- size_t size_be = htobe64 (size );
69
- uint8_t * size_bytes = ( uint8_t *)&size_be ;
70
- for (size_t i = 0 ; i < sizeof ( size_t ) ; i++)
71
- bytes.push_back (size_bytes[i] );
73
+ size_t sz = sizeof ( uint64_t );
74
+ bytes. reserve (bytes. size () + sz) ;
75
+ for (uint64_t i = 0 ; i < sz ; i++)
76
+ bytes.push_back ((n >> ( 8 * (sz - i - 1 ))) & 0xFF );
72
77
}
73
78
74
- inline size_t deserialise_size_t (
79
+ static inline uint64_t deserialise_uint64_t (
75
80
const std::vector<uint8_t >& bytes, size_t & index)
76
81
{
77
- size_t result = 0 ;
78
- uint8_t * result_bytes = ( uint8_t *)&result ;
79
- for (size_t i = 0 ; i < sizeof ( size_t ) ; i++)
80
- result_bytes[i] = bytes[index ++];
81
- return be64toh (result) ;
82
+ uint64_t r = 0 ;
83
+ uint64_t sz = sizeof ( uint64_t ) ;
84
+ for (uint64_t i = 0 ; i < sz ; i++)
85
+ r |= static_cast < uint64_t >( bytes[index ++]) << ( 8 * (sz - i - 1 )) ;
86
+ return r ;
82
87
}
83
88
84
89
// / @brief Template for fixed-size hashes
@@ -163,7 +168,7 @@ namespace merkle
163
168
std::string r (num_chars, ' _' );
164
169
for (size_t i = 0 ; i < num_bytes; i++)
165
170
snprintf (
166
- r.data () + 2 * i,
171
+ const_cast < char *>( r.data () + 2 * i) ,
167
172
num_chars + 1 - 2 * i,
168
173
lower_case ? " %02x" : " %02X" ,
169
174
bytes[i]);
@@ -354,9 +359,9 @@ namespace merkle
354
359
{
355
360
MERKLECPP_TRACE (MERKLECPP_TOUT << " > PathT::serialise " << std::endl);
356
361
_leaf.serialise (bytes);
357
- serialise_size_t (_leaf_index, bytes);
358
- serialise_size_t (_max_index, bytes);
359
- serialise_size_t (elements.size (), bytes);
362
+ serialise_uint64_t (_leaf_index, bytes);
363
+ serialise_uint64_t (_max_index, bytes);
364
+ serialise_uint64_t (elements.size (), bytes);
360
365
for (auto & e : elements)
361
366
{
362
367
e.hash .serialise (bytes);
@@ -372,9 +377,9 @@ namespace merkle
372
377
MERKLECPP_TRACE (MERKLECPP_TOUT << " > PathT::deserialise " << std::endl);
373
378
elements.clear ();
374
379
_leaf.deserialise (bytes, position);
375
- _leaf_index = deserialise_size_t (bytes, position);
376
- _max_index = deserialise_size_t (bytes, position);
377
- size_t num_elements = deserialise_size_t (bytes, position);
380
+ _leaf_index = deserialise_uint64_t (bytes, position);
381
+ _max_index = deserialise_uint64_t (bytes, position);
382
+ size_t num_elements = deserialise_uint64_t (bytes, position);
378
383
for (size_t i = 0 ; i < num_elements; i++)
379
384
{
380
385
HashT<HASH_SIZE> hash (bytes, position);
@@ -452,7 +457,8 @@ namespace merkle
452
457
// / @brief Convert a path to a string
453
458
// / @param num_bytes The maximum number of bytes to convert
454
459
// / @param lower_case Enables lower-case hex characters
455
- std::string to_string (size_t num_bytes = HASH_SIZE, bool lower_case = true ) const
460
+ std::string to_string (
461
+ size_t num_bytes = HASH_SIZE, bool lower_case = true ) const
456
462
{
457
463
std::stringstream stream;
458
464
stream << _leaf.to_string (num_bytes);
@@ -1201,8 +1207,9 @@ namespace merkle
1201
1207
{
1202
1208
MERKLECPP_TRACE (MERKLECPP_TOUT << " > serialise " << std::endl;);
1203
1209
1204
- serialise_size_t (leaf_nodes.size () + uninserted_leaf_nodes.size (), bytes);
1205
- serialise_size_t (num_flushed, bytes);
1210
+ serialise_uint64_t (
1211
+ leaf_nodes.size () + uninserted_leaf_nodes.size (), bytes);
1212
+ serialise_uint64_t (num_flushed, bytes);
1206
1213
for (auto & n : leaf_nodes)
1207
1214
n->hash .serialise (bytes);
1208
1215
for (auto & n : uninserted_leaf_nodes)
@@ -1243,8 +1250,8 @@ namespace merkle
1243
1250
(to < min_index () || max_index () < to) || from > to)
1244
1251
throw std::runtime_error (" invalid leaf indices" );
1245
1252
1246
- serialise_size_t (to - from + 1 , bytes);
1247
- serialise_size_t (from, bytes);
1253
+ serialise_uint64_t (to - from + 1 , bytes);
1254
+ serialise_uint64_t (from, bytes);
1248
1255
for (size_t i = from; i <= to; i++)
1249
1256
leaf (i).serialise (bytes);
1250
1257
@@ -1294,8 +1301,8 @@ namespace merkle
1294
1301
walk_stack.clear ();
1295
1302
_root = nullptr ;
1296
1303
1297
- size_t num_leaf_nodes = deserialise_size_t (bytes, position);
1298
- num_flushed = deserialise_size_t (bytes, position);
1304
+ size_t num_leaf_nodes = deserialise_uint64_t (bytes, position);
1305
+ num_flushed = deserialise_uint64_t (bytes, position);
1299
1306
1300
1307
leaf_nodes.reserve (num_leaf_nodes);
1301
1308
for (size_t i = 0 ; i < num_leaf_nodes; i++)
@@ -1832,7 +1839,7 @@ namespace merkle
1832
1839
uint32_t cws[64 ] = {0 };
1833
1840
1834
1841
for (int i=0 ; i < 16 ; i++)
1835
- cws[i] = be32toh (((int32_t *)block)[i]);
1842
+ cws[i] = convert_endianness (((int32_t *)block)[i]);
1836
1843
1837
1844
for (int i = 16 ; i < 64 ; i++) {
1838
1845
uint32_t t16 = cws[i - 16 ];
@@ -1864,7 +1871,7 @@ namespace merkle
1864
1871
}
1865
1872
1866
1873
for (int i=0 ; i < 8 ; i++)
1867
- ((uint32_t *)out.bytes )[i] = htobe32 (s[i] + h[i]);
1874
+ ((uint32_t *)out.bytes )[i] = convert_endianness (s[i] + h[i]);
1868
1875
}
1869
1876
// clang-format on
1870
1877
@@ -1887,7 +1894,7 @@ namespace merkle
1887
1894
SHA256_Transform (&ctx, &block[0 ]);
1888
1895
1889
1896
for (int i = 0 ; i < 8 ; i++)
1890
- ((uint32_t *)out.bytes )[i] = htobe32 (((uint32_t *)ctx.h )[i]);
1897
+ ((uint32_t *)out.bytes )[i] = convert_endianness (((uint32_t *)ctx.h )[i]);
1891
1898
}
1892
1899
1893
1900
// / @brief OpenSSL SHA256
0 commit comments