forked from UNOMP/node-multi-hashing
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathnrghash.h
712 lines (588 loc) · 23.5 KB
/
nrghash.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
// Copyright (c) 2017 Ryan Lucchese
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <stdint.h>
#ifdef __cplusplus
#include <functional>
#include <memory>
#include <stdexcept>
#include <type_traits>
#include <vector>
#include <cstring>
namespace n_nrghash
{
bool test_function() noexcept;
namespace constants
{
/** \brief DAG_MAGIC_BYTES is the starting sequence of a DAG file, used for identification.
*/
static constexpr char DAG_MAGIC_BYTES[] = "NRGHASH_DAG";
/** \brief DAG_FILE_HEADER_SIZE is the expected size of a DAG file header.
*/
static constexpr uint32_t DAG_FILE_HEADER_SIZE = 64u;
/** \brief DAG_FILE_MINIMUM_SIZE is the size of the DAG file at epoch 0.
*/
static constexpr uint64_t DAG_FILE_MINIMUM_SIZE = 2641099136;
/** \brief CALLBACK_FREQUENCY determines how often callbacks will be called.
*
* 1 means every iteration, 10 means every 10th iteration, and so on...
*/
static constexpr uint32_t CALLBACK_FREQUENCY = 1024u;
/** \brief The major version of nrghash
*/
static constexpr uint32_t MAJOR_VERSION = 1u;
/** \brief The revision number (middle version digit) of nrghash
*/
static constexpr uint32_t REVISION = 23u;
/** \brief The minor version number of nrghash
*/
static constexpr uint32_t MINOR_VERSION = 0u;
/** \brief Number of bytes in a hash word.
*/
static constexpr uint32_t WORD_BYTES = 4u;
/** \brief The growth of the dataset in bytes per epoch.
*/
static constexpr uint32_t DATASET_BYTES_GROWTH = 1u << 23u;
/** \brief The number of bytes in the dataset at genesis.
*/
static constexpr uint32_t DATASET_BYTES_INIT = (1u << 30u) + (DATASET_BYTES_GROWTH * 182);
/** \brief The growth of the cache in bytes per epoch.
*/
static constexpr uint32_t CACHE_BYTES_GROWTH = 1u << 17u;
/** \brief The number of bytes in the cache at genesis.
*/
static constexpr uint32_t CACHE_BYTES_INIT = (1u << 24u) + (CACHE_BYTES_GROWTH * 182);
/** \brief Ratio of the size of the DAG in bytes relative to the size of the cache in bytes..
*/
static constexpr uint32_t CACHE_MULTIPLIER=1024u;
/** \brief The number of blocks which constitute one epoch.
*
* The DAG and cache must be regenerated once per epoch. (approximately 120 hours)
*/
static constexpr uint32_t EPOCH_LENGTH = 7200u;
/** \brief The width of the mix hash for egihash.
*/
static constexpr uint32_t MIX_BYTES = 128u;
/** \brief The size of an egihash in bytes.
*/
static constexpr uint32_t HASH_BYTES = 64u;
/** \brief The number of parents for each element in the DAG.
*/
static constexpr uint32_t DATASET_PARENTS = 256u;
/** \brief The number of hashing rounds used to produce the cache.
*/
static constexpr uint32_t CACHE_ROUNDS = 3u;
/** \brief The number of DAG lookups to compute an egihash.
*/
static constexpr uint32_t ACCESSES = 64u;
}
/** \brief node union is used instead of the native integer to allow both bytes level access and as a 4 byte hash word
*
*/
#pragma pack(push, 1)
union node
{
uint32_t hword;
uint8_t bytes[4];
node()
:hword{}
{}
node(uint8_t bytes_[4])
{
::memcpy(bytes, bytes_, 4);
}
node(uint32_t hword_):hword(hword_)
{}
};
#pragma pack(pop)
static_assert(sizeof(node) == sizeof(uint32_t), "Invalid hash node size");
/** \brief hash_exception indicates an error or cancellation when performing a task within nrghash.
*
* All functions not marked noexcept may be assumed to throw hash_exception or C++ runtime exceptions.
*/
class hash_exception : public ::std::runtime_error
{
public:
/** \brief construct a hash_exception from a std::string const &
*/
hash_exception(std::string const & what_arg) noexcept
: runtime_error(what_arg)
{
}
/** \brief construct a hash_exception from a char const *
*/
hash_exception(char const * what_arg) noexcept
: runtime_error(what_arg)
{
}
};
/** \brief epoch0_seedhash is is the seed hash for the genesis block and first epoch of the DAG.
* All seed hashes for subsequent epochs will be generated from this seedhash.
* This hash was chosen as: seed = SHA256(SHA256(Concatenate(EthereumBlock5439314Hash, DashBlock853406Hash)))
* Using two block hashes from other blockchains serves as a proof of the timestamp in the genesis block.
*
* This represents a keccak-256 hash that will be used as input for building the DAG/cache.
*/
static constexpr char epoch0_seedhash[] = "\xe8\xbc\xb1\xcf\x8a\x60\x16\x25\x11\x7e\x59\xb5\xf2\xdc\x8c\x36\x6e\x14\x04\x83\x0a\xe9\xd2\x5f\x65\x2b\xe6\x7a\xc9\xbb\x81\x5b";
static constexpr uint8_t size_epoch0_seedhash = sizeof(epoch0_seedhash) - 1;
static_assert(size_epoch0_seedhash == 32, "Invalid seedhash");
/** \brief h256_t represents a the result of a keccak-256 hash.
*/
struct h256_t
{
using size_type = ::std::size_t;
static constexpr size_type hash_size = 32;
/** \brief Default constructor for h256_t fills data field b with 0 bytes
*/
constexpr h256_t(): b{0} {}
/** \brief Default copy constructor
*/
h256_t(h256_t const &) = default;
/** \brief Default copy assignment operator
*/
h256_t & operator=(h256_t const &) = default;
/** \brief Default move constructor
*/
h256_t(h256_t &&) = default;
/** \brief Default move assignment operator
*/
h256_t & operator=(h256_t &&) = default;
/** \brief Default destructor
*/
~h256_t() = default;
/** \brief Construct and compute a hash from a data source.
*
* \param input_data A pointer to the start of the data to be hashed
* \param input_size The number of bytes of input data to hash
* \throws hash_exception on error
*/
h256_t(void const * input_data, size_type input_size);
/** \brief Get the hex-encoded value for this h256_t.
*
* \returns std::string containing hex encoded value for this h256_t.
*/
::std::string to_hex() const;
/** \brief Test if this hash is valid. Returns true if hash data is not all 0 bytes.
*/
operator bool() const;
/** \brief Compare this h256_t to another h256_t.
*
* \return true if the hashes are equal.
*/
bool operator==(h256_t const &) const;
/** \brief This member stores the 256-bit hash data
*/
uint8_t b[hash_size];
};
/** \brief A default constructed h256_t has all empty bytes.
*/
static constexpr h256_t empty_h256;
/** \brief h512_t represents a the result of a keccak-512 hash.
*/
struct h512_t
{
using size_type = ::std::size_t;
static constexpr size_type hash_size = 64;
/** \brief Default constructor for h512_t fills data field b with 0 bytes
*/
constexpr h512_t(): b{0} {}
/** \brief Default copy constructor
*/
h512_t(h512_t const &) = default;
/** \brief Default copy assignment operator
*/
h512_t & operator=(h512_t const &) = default;
/** \brief Default move constructor
*/
h512_t(h512_t &&) = default;
/** \brief Default move assignment operator
*/
h512_t & operator=(h512_t &&) = default;
/** \brief Default destructor
*/
~h512_t() = default;
/** \brief Construct and compute a hash from a data source.
*
* \param input_data A pointer to the start of the data to be hashed
* \param input_size The number of bytes of input data to hash
* \throws hash_exception on error
*/
h512_t(void const * input_data, size_type input_size);
/** \brief Get the hex-encoded value for this h512_t.
*
* \returns std::string containing hex encoded value for this h512_t.
*/
::std::string to_hex() const;
/** \brief Test if this hash is valid. Returns true if hash data is not all 0 bytes.
*/
operator bool() const;
/** \brief Compare this h512_t to another h512_t.
*
* \return true if the hashes are equal.
*/
bool operator==(h512_t const &) const;
/** \brief This member stores the 512-bit hash data
*/
uint8_t b[hash_size];
};
/** \brief A default constructed h512_t has all empty bytes.
*/
static constexpr h512_t empty_h512;
/** \brief result_t represents the result of an nrghash.
*/
struct result_t
{
/** \brief Default constructor
*/
constexpr result_t() = default;
/** \brief Default copy constructor
*/
result_t(result_t const &) = default;
/** \brief Default copy assignment operator
*/
result_t & operator=(result_t const &) = default;
/** \brief Default move constructor
*/
result_t(result_t &&) = default;
/** \brief Default move assignment operator
*/
result_t & operator=(result_t &&) = default;
/** \brief Default destructor
*/
~result_t() = default;
/** \brief Test if this hash is valid. Returs true of hash data is not all 0 bytes.
*/
operator bool() const;
/** \brief Compare this result_t to another result_t.
*
* \return true if both the value and mixhash are equal.
*/
bool operator==(result_t const &) const;
/** \brief This member contains the nrghash result value.
*/
h256_t value;
/** \brief This member contains the mix hash to produce this result.
*/
h256_t mixhash;
};
/** \brief A default constructed result_t has all empty bytes.
*/
static constexpr result_t empty_result;
/** \brief progress_callback_phase values represent different stages at which a progress callback may be called.
*/
enum progress_callback_phase
{
cache_seeding, /**< cache_seeding means fill the cache with hashes of seed hashes: { cache_0 = seedhash; cache_n = keccak512(cache_n-1) } */
cache_generation, /**< cache_generation is performed with a memory hard hashing function of a seeded cache */
cache_saving, /**< cache_saving is saving the cache to disk */
cache_loading, /**< cache_loading is loading the cache from disk */
dag_generation, /**< dag_generation is computing the DAG for a given epoch (block_number) */
dag_saving, /**< dag_saving is saving the DAG to disk */
dag_loading /**< dag_loading is loading the DAG from disk */
};
/** \brief progress_callback_type is a function which may be passed to any phase of DAG/cache or generation to receive progress updates.
*
* \param step is the count of the step just compeleted before this call of the callback.
* \param max is the maximum number of steps that will be performed for this progress_callback_phase.
* \param phase the progress_callback_phase indicating what is being computed at the time of the callback.
* \return false to cancel whatever action is being performed, true to continue.
*/
using progress_callback_type = ::std::function<bool (::std::size_t step, ::std::size_t max, progress_callback_phase phase)>;
/** \brief read_function_type is a function which passed to various objects which perform loading of a file, such as the cache and DAG.
*
* Note that this function will own whatever data it needs to perform the read, i.e. the filestream.
* \param dst points to the memory location that should be read into.
* \param count represents the number of bytes to read.
* \throws hash_exception if the read failed
*/
using read_function_type = ::std::function<void(void * dst, ::std::size_t count)>;
/** \brief cache_t is the cache used to compute a DAG for a given epoch.
*
* Each DAG owns a cache_t and the size of the cache grows linearly in time.
*/
struct cache_t
{
/** \brief size_type represents sizes used by a cache.
*/
using size_type = uint64_t;
/** \brief data_type is the underlying data store which stores a cache.
*/
using data_type = ::std::vector<::std::vector<node>>;
/** \brief default copy constructor.
*/
cache_t(const cache_t &) = default;
/** \brief default copy assignment operator.
*/
cache_t & operator=(cache_t const &) = default;
/** \brief default move constructor.
*/
cache_t(cache_t &&) = default;
/** \brief default move assignment operator.
*/
cache_t & operator=(cache_t &&) = default;
/** \brief default destructor.
*/
~cache_t() = default;
/** \brief explicitly deleted default constructor.
*/
cache_t() = delete;
/** \brief Construct a cache_t given a block number and a progress callback function.
*
* \param block_number is the block number for which this cache_t is to be constructed.
* \param callback (optional) may be used to monitor the progress of cache generation. Return false to cancel, true to continue.
*/
cache_t(uint64_t block_number, progress_callback_type callback = [](size_type, size_type, int){ return true; });
/** \brief Get the epoch number for which this cache is valid.
*
* \returns uint64_t representing the epoch number (block_number / constants::EPOCH_LENGTH)
*/
uint64_t epoch() const;
/** \brief Get the size of the cache data in bytes.
*
* \returns size_type representing the size of the cache data in bytes.
*/
size_type size() const;
/** \brief Get the data the cache contains.
*
* \returns data_type const & to the actual cache data.
*/
data_type const & data() const;
/** \brief Get the seedhash for this cache.
*
* /returns h256_t seed hash for this cache.
*/
h256_t seedhash() const;
/** \brief Unload cache.
*
* To actually free a cache from memory, call this function on a cache.
* The cache will then be released from the internal cache.
* Once all references to the cache for this epoch are destroyed, it will be freed.
*/
void unload() const;
/** \brief Get the size of the cache data in bytes.
*
* \param block_number is the block number for which cache size to compute.
* \returns size_type representing the size of the cache data in bytes.
*/
static size_type get_cache_size(uint64_t const block_number) noexcept;
/** \brief get_seedhash(uint64_t) will compute the seedhash for a given block number.
*
* \param block_number An unsigned 64-bit integer representing the block number for which to compute the seed hash.
* \return An h256_t keccak-256 seed hash for the given block number.
*/
static h256_t get_seedhash(uint64_t const block_number);
/** \brief Determine whether the cache_t for this epoch is already loaded
*
* \param epoch is the epoch number for which to determine if a cache_t is already loaded.
* \return bool true if we have this cache_t epoch loaded, false otherwise.
*/
static bool is_loaded(uint64_t const epoch);
/** \brief Get the epoch numbers for which we already have a cache_t loaded.
*
* \return ::std::vector containing epoch numbers for cache_t's that are already loaded.
*/
static ::std::vector<uint64_t> get_loaded();
/** \brief cache_t internal implementation.
*/
struct impl_t;
private:
friend struct dag_t;
/** \brief Construct a cache_t by loading from disk.
*
* \param epoch is the number of the epoch for the cache we are loading.
* \param size is the size in bytes of the cache we are loading.
* \param read A function which will read cache data from disk.
* \param callback (optional) may be used to monitor the progress of cache loading. Return false to cancel, true to continue.
*/
cache_t(uint64_t epoch, uint64_t size, read_function_type read, progress_callback_type callback = [](size_type, size_type, int){ return true; });
/** \brief Load a cache from disk.
*
* \param read A function which will read cache data from disk.
* \param callback (optional) may be used to monitor the progress of cache loading. Return false to cancel, true to continue.
*/
void load(read_function_type read, progress_callback_type callback = [](size_type, size_type, int){ return true; });
/** \brief shared_ptr to impl allows default moving/copying of cache. Internally, only one cache_t::impl_t per epoch will exist.
*/
::std::shared_ptr<impl_t> impl;
};
/** \brief dag_t is the DAG which is used by full nodes and miners to compute nrghashes.
*
* The DAG gives nrghash it's ASIC resistance, ensuring that this hashing function is memory bound not compute bound.
* The DAG must be updated once per constants::EPOCH_LENGTH block numbers.
* The DAG for epoch 0 is 1073739904 bytes in size and will grow linearly with each following epoch.
* The DAG can take a long time to generate. It is recommended to save the DAG to disk to avoid having to regenerate it each time.
* It makes sense to pre-compute the DAG for the next epoch, so generating it does not interrupt mining / operation of a full node.
* Whether by generation or by loading, the DAG will own a cache_t which corresponds to cache for the same epoch.
*/
struct dag_t
{
/** \brief size_type represents sizes used by a cache.
*/
using size_type = ::std::size_t;
/** \brief data_type is the underlying data store which stores a cache.
*/
using data_type = ::std::vector<::std::vector<node>>;
/** \brief default copy constructor.
*/
dag_t(dag_t const &) = default;
/** \brief default copy assignment operator.
*/
dag_t & operator=(dag_t const &) = default;
/** \brief default move constructor.
*/
dag_t(dag_t &&) = default;
/** \brief default move assignment operator.
*/
dag_t & operator=(dag_t &&) = default;
/** \brief default destructor.
*/
~dag_t() = default;
/** \brief explicitly deleted default constructor.
*/
dag_t() = delete;
/** \brief generate a DAG for a given block_number.
*
* DAG's are cached in a singleton per epoch. If this DAG is already loaded in memory it will be returned quickly.
* If this DAG is not yet loaded, this will take a long time.
* \param block_number is the block number for which to generate a DAG.
* \param callback (optional) may be used to monitor the progress of DAG generation. Return false to cancel, true to continue.
*/
dag_t(uint64_t const block_number, progress_callback_type = [](size_type, size_type, int){ return true; });
/** \brief load a DAG from a file.
*
* DAG's are cached in a singleton per epoch. If this DAG is already loaded in memory it will be returned quickly.
* \param file_path is the path to the file the DAG should be loaded from.
* \param callback (optional) may be used to monitor the progress of DAG loading. Return false to cancel, true to continue.
*/
dag_t(::std::string const & file_path, progress_callback_type = [](size_type, size_type, int){ return true; });
/** \brief Get the epoch number for which this DAG is valid.
*
* \returns uint64_t representing the epoch number (block_number / constants::EPOCH_LENGTH)
*/
uint64_t epoch() const;
/** \brief Get the size of the DAG data in bytes.
*
* \returns size_type representing the size of the DAG data in bytes.
*/
size_type size() const;
/** \brief Get the data the DAG contains.
*
* \returns data_type const & to the actual DAG data.
*/
data_type const & data() const;
/** \brief Save the DAG to a file fur future loading.
*
* \param file_path is the path to the file the DAG should be saved to.
* \param callback (optional) may be used to monitor the progress of DAG saving. Return false to cancel, true to continue.
*/
void save(::std::string const & file_path, progress_callback_type callback = [](size_type, size_type, int){ return true; }) const;
/** \brief Get the cache for this DAG.
*
* \return cache_t of the cache for this DAG.
*/
cache_t get_cache() const;
/** \brief Unload a DAG.
*
* To actually free a DAG from memory, call this function on a DAG. The DAG will then be released from the internal cache.
* Once all references to the DAG for this epoch are destroyed, it will be freed.
*/
void unload() const;
/** \brief Get the size of the DAG data in bytes.
*
* \param block_number is the block number for which DAG size to compute.
* \return size_type representing the size of the DAG data in bytes.
*/
static size_type get_full_size(uint64_t const block_number) noexcept;
/** \brief Determine whether the DAG for this epoch is already loaded
*
* \param epoch is the epoch number for which to determine if a DAG is already loaded.
* \return bool true if we have this DAG epoch loaded, false otherwise.
*/
static bool is_loaded(uint64_t const epoch);
/** \brief Get the epoch numbers for which we already have a DAG loaded.
*
* \return ::std::vector containing epoch numbers for DAGs that are already loaded.
*/
static ::std::vector<uint64_t> get_loaded();
/** \brief dag_t private implementation.
*/
struct impl_t;
/** \brief shared_ptr to impl allows default moving/copying of cache. Internally, only one dag_t::impl_t per epoch will exist.
*
* Since DAGs consume a large amount of memory, it is important that they are cached.
*/
::std::shared_ptr<impl_t> impl;
};
namespace full
{
/** \brief The full Egihash function to be used by full nodes and miners.
*
* \param dag A const reference to the DAG for the current epoch
* \param input_data A pointer to the start of the data to be hashed
* \param input_size The number of bytes of input data to hash
* \throws hash_exception on error
* \return result_t containing hashed data
*/
result_t hash(dag_t const & dag, void const * input_data, dag_t::size_type input_size);
/** \brief The full Egihash function to be used by full nodes and miners.
*
* \param dag A const reference to the DAG for the current epoch.
* \param start_ptr A pointer to the start of the data to be hashed
* \param end_ptr A pointer to the end of the data to be hashed
* \throws hash_exception on error
* \return result_t containing hashed data
*/
template <typename ptr_t>
typename ::std::enable_if<::std::is_pointer<ptr_t>::value, result_t>::type
/*result_t*/ hash(dag_t const & dag, ptr_t const start_ptr, ptr_t const end_ptr)
{
return hash(dag, start_ptr, static_cast<dag_t::size_type>((end_ptr - start_ptr) * sizeof(start_ptr[0])));
}
/** \brief The full Egihash function to be used by full nodes and miners.
*
* \param dag A const reference to the DAG for the current epoch
* \param header_hash A h256_t (Keccak-256) hash of the truncated block header
* \param nonce An unsigned 64-bit integer stored in little endian byte order
* \throws hash_exception on error
* \return result_t containing hashed data
*/
result_t hash(dag_t const & dag, h256_t const & header_hash, uint64_t const nonce);
}
namespace light
{
/** \brief The light Egihash function to be used by light wallets & light verification clients.
*
* \param cache A const reference to the cache for the current epoch
* \param input_data A pointer to the start of the data to be hashed
* \param input_size The number of bytes of input data to hash
* \throws hash_exception on error
* \return result_t containing hashed data
*/
result_t hash(cache_t const & cache, void const * input_data, cache_t::size_type input_size);
/** \brief The light Egihash function to be used by light wallets & light verification clients.
*
* \param cache A const reference to the cache for the current epoch.
* \param start_ptr A pointer to the start of the data to be hashed
* \param end_ptr A pointer to the end of the data to be hashed
* \throws hash_exception on error
* \return result_t containing hashed data
*/
template <typename ptr_t>
typename ::std::enable_if<::std::is_pointer<ptr_t>::value, result_t>::type
/*result_t*/ hash(cache_t const & cache, ptr_t const start_ptr, ptr_t const end_ptr)
{
return hash(cache, start_ptr, static_cast<cache_t::size_type>((end_ptr - start_ptr) * sizeof(start_ptr[0])));
}
/** \brief The light Egihash function to be used by light wallets & light verification clients.
*
* \param dag A const reference to the DAG for the current epoch
* \param header_hash A h256_t (Keccak-256) hash of the truncated block header
* \param nonce An unsigned 64-bit integer stored in little endian byte order
* \throws hash_exception on error
* \return result_t containing hashed data
*/
result_t hash(cache_t const & cache, h256_t const & header_hash, uint64_t const nonce);
}
}
#endif // __cplusplus