ethash 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.gitmodules +3 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +26 -0
- data/LICENSE +21 -0
- data/README.md +31 -0
- data/Rakefile +15 -0
- data/ethash.gemspec +23 -0
- data/ext/ethash/ethash.c +75 -0
- data/ext/ethash/extconf.rb +7 -0
- data/ext/ethash/headers/compiler.h +33 -0
- data/ext/ethash/headers/data_sizes.h +812 -0
- data/ext/ethash/headers/endian.h +79 -0
- data/ext/ethash/headers/ethash.h +147 -0
- data/ext/ethash/headers/fnv.h +43 -0
- data/ext/ethash/headers/internal.h +179 -0
- data/ext/ethash/headers/io.h +202 -0
- data/ext/ethash/headers/mmap.h +47 -0
- data/ext/ethash/headers/sha3.h +31 -0
- data/ext/ethash/headers/sha3_cryptopp.h +18 -0
- data/ext/ethash/headers/util.h +47 -0
- data/ext/ethash/internal.c +508 -0
- data/ext/ethash/io.c +119 -0
- data/ext/ethash/sha3.c +151 -0
- data/lib/ethash.rb +3 -0
- data/lib/ethash/version.rb +5 -0
- data/test/ethash_test.rb +26 -0
- metadata +130 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <stdint.h>
|
4
|
+
#include "compiler.h"
|
5
|
+
|
6
|
+
#if defined(__MINGW32__) || defined(_WIN32)
|
7
|
+
# define LITTLE_ENDIAN 1234
|
8
|
+
# define BYTE_ORDER LITTLE_ENDIAN
|
9
|
+
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
|
10
|
+
# include <sys/endian.h>
|
11
|
+
#elif defined(__OpenBSD__) || defined(__SVR4)
|
12
|
+
# include <sys/types.h>
|
13
|
+
#elif defined(__APPLE__)
|
14
|
+
# include <machine/endian.h>
|
15
|
+
#elif defined( BSD ) && (BSD >= 199103)
|
16
|
+
# include <machine/endian.h>
|
17
|
+
#elif defined( __QNXNTO__ ) && defined( __LITTLEENDIAN__ )
|
18
|
+
# define LITTLE_ENDIAN 1234
|
19
|
+
# define BYTE_ORDER LITTLE_ENDIAN
|
20
|
+
#elif defined( __QNXNTO__ ) && defined( __BIGENDIAN__ )
|
21
|
+
# define BIG_ENDIAN 1234
|
22
|
+
# define BYTE_ORDER BIG_ENDIAN
|
23
|
+
#else
|
24
|
+
# include <endian.h>
|
25
|
+
#endif
|
26
|
+
|
27
|
+
#if defined(_WIN32)
|
28
|
+
#include <stdlib.h>
|
29
|
+
#define ethash_swap_u32(input_) _byteswap_ulong(input_)
|
30
|
+
#define ethash_swap_u64(input_) _byteswap_uint64(input_)
|
31
|
+
#elif defined(__APPLE__)
|
32
|
+
#include <libkern/OSByteOrder.h>
|
33
|
+
#define ethash_swap_u32(input_) OSSwapInt32(input_)
|
34
|
+
#define ethash_swap_u64(input_) OSSwapInt64(input_)
|
35
|
+
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
|
36
|
+
#define ethash_swap_u32(input_) bswap32(input_)
|
37
|
+
#define ethash_swap_u64(input_) bswap64(input_)
|
38
|
+
#elif defined(__OpenBSD__)
|
39
|
+
#include <endian.h>
|
40
|
+
#define ethash_swap_u32(input_) swap32(input_)
|
41
|
+
#define ethash_swap_u64(input_) swap64(input_)
|
42
|
+
#else // posix
|
43
|
+
#include <byteswap.h>
|
44
|
+
#define ethash_swap_u32(input_) bswap_32(input_)
|
45
|
+
#define ethash_swap_u64(input_) bswap_64(input_)
|
46
|
+
#endif
|
47
|
+
|
48
|
+
|
49
|
+
#if LITTLE_ENDIAN == BYTE_ORDER
|
50
|
+
|
51
|
+
#define fix_endian32(dst_ ,src_) dst_ = src_
|
52
|
+
#define fix_endian32_same(val_)
|
53
|
+
#define fix_endian64(dst_, src_) dst_ = src_
|
54
|
+
#define fix_endian64_same(val_)
|
55
|
+
#define fix_endian_arr32(arr_, size_)
|
56
|
+
#define fix_endian_arr64(arr_, size_)
|
57
|
+
|
58
|
+
#elif BIG_ENDIAN == BYTE_ORDER
|
59
|
+
|
60
|
+
#define fix_endian32(dst_, src_) dst_ = ethash_swap_u32(src_)
|
61
|
+
#define fix_endian32_same(val_) val_ = ethash_swap_u32(val_)
|
62
|
+
#define fix_endian64(dst_, src_) dst_ = ethash_swap_u64(src_
|
63
|
+
#define fix_endian64_same(val_) val_ = ethash_swap_u64(val_)
|
64
|
+
#define fix_endian_arr32(arr_, size_) \
|
65
|
+
do { \
|
66
|
+
for (unsigned i_ = 0; i_ < (size_), ++i_) { \
|
67
|
+
arr_[i_] = ethash_swap_u32(arr_[i_]); \
|
68
|
+
} \
|
69
|
+
while (0)
|
70
|
+
#define fix_endian_arr64(arr_, size_) \
|
71
|
+
do { \
|
72
|
+
for (unsigned i_ = 0; i_ < (size_), ++i_) { \
|
73
|
+
arr_[i_] = ethash_swap_u64(arr_[i_]); \
|
74
|
+
} \
|
75
|
+
while (0) \
|
76
|
+
|
77
|
+
#else
|
78
|
+
# error "endian not supported"
|
79
|
+
#endif // BYTE_ORDER
|
@@ -0,0 +1,147 @@
|
|
1
|
+
/*
|
2
|
+
This file is part of ethash.
|
3
|
+
|
4
|
+
ethash 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
|
+
ethash 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 ethash. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
*/
|
17
|
+
|
18
|
+
/** @file ethash.h
|
19
|
+
* @date 2015
|
20
|
+
*/
|
21
|
+
#pragma once
|
22
|
+
|
23
|
+
#include <stdint.h>
|
24
|
+
#include <stdbool.h>
|
25
|
+
#include <string.h>
|
26
|
+
#include <stddef.h>
|
27
|
+
#include "compiler.h"
|
28
|
+
|
29
|
+
#define ETHASH_REVISION 23
|
30
|
+
#define ETHASH_DATASET_BYTES_INIT 1073741824U // 2**30
|
31
|
+
#define ETHASH_DATASET_BYTES_GROWTH 8388608U // 2**23
|
32
|
+
#define ETHASH_CACHE_BYTES_INIT 1073741824U // 2**24
|
33
|
+
#define ETHASH_CACHE_BYTES_GROWTH 131072U // 2**17
|
34
|
+
#define ETHASH_EPOCH_LENGTH 30000U
|
35
|
+
#define ETHASH_MIX_BYTES 128
|
36
|
+
#define ETHASH_HASH_BYTES 64
|
37
|
+
#define ETHASH_DATASET_PARENTS 256
|
38
|
+
#define ETHASH_CACHE_ROUNDS 3
|
39
|
+
#define ETHASH_ACCESSES 64
|
40
|
+
#define ETHASH_DAG_MAGIC_NUM_SIZE 8
|
41
|
+
#define ETHASH_DAG_MAGIC_NUM 0xFEE1DEADBADDCAFE
|
42
|
+
|
43
|
+
#ifdef __cplusplus
|
44
|
+
extern "C" {
|
45
|
+
#endif
|
46
|
+
|
47
|
+
/// Type of a seedhash/blockhash e.t.c.
|
48
|
+
typedef struct ethash_h256 { uint8_t b[32]; } ethash_h256_t;
|
49
|
+
|
50
|
+
// convenience macro to statically initialize an h256_t
|
51
|
+
// usage:
|
52
|
+
// ethash_h256_t a = ethash_h256_static_init(1, 2, 3, ... )
|
53
|
+
// have to provide all 32 values. If you don't provide all the rest
|
54
|
+
// will simply be unitialized (not guranteed to be 0)
|
55
|
+
#define ethash_h256_static_init(...) \
|
56
|
+
{ {__VA_ARGS__} }
|
57
|
+
|
58
|
+
struct ethash_light;
|
59
|
+
typedef struct ethash_light* ethash_light_t;
|
60
|
+
struct ethash_full;
|
61
|
+
typedef struct ethash_full* ethash_full_t;
|
62
|
+
typedef int(*ethash_callback_t)(unsigned);
|
63
|
+
|
64
|
+
typedef struct ethash_return_value {
|
65
|
+
ethash_h256_t result;
|
66
|
+
ethash_h256_t mix_hash;
|
67
|
+
bool success;
|
68
|
+
} ethash_return_value_t;
|
69
|
+
|
70
|
+
/**
|
71
|
+
* Allocate and initialize a new ethash_light handler
|
72
|
+
*
|
73
|
+
* @param block_number The block number for which to create the handler
|
74
|
+
* @return Newly allocated ethash_light handler or NULL in case of
|
75
|
+
* ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes()
|
76
|
+
*/
|
77
|
+
ethash_light_t ethash_light_new(uint64_t block_number);
|
78
|
+
/**
|
79
|
+
* Frees a previously allocated ethash_light handler
|
80
|
+
* @param light The light handler to free
|
81
|
+
*/
|
82
|
+
void ethash_light_delete(ethash_light_t light);
|
83
|
+
/**
|
84
|
+
* Calculate the light client data
|
85
|
+
*
|
86
|
+
* @param light The light client handler
|
87
|
+
* @param header_hash The header hash to pack into the mix
|
88
|
+
* @param nonce The nonce to pack into the mix
|
89
|
+
* @return an object of ethash_return_value_t holding the return values
|
90
|
+
*/
|
91
|
+
ethash_return_value_t ethash_light_compute(
|
92
|
+
ethash_light_t light,
|
93
|
+
ethash_h256_t const header_hash,
|
94
|
+
uint64_t nonce
|
95
|
+
);
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Allocate and initialize a new ethash_full handler
|
99
|
+
*
|
100
|
+
* @param light The light handler containing the cache.
|
101
|
+
* @param callback A callback function with signature of @ref ethash_callback_t
|
102
|
+
* It accepts an unsigned with which a progress of DAG calculation
|
103
|
+
* can be displayed. If all goes well the callback should return 0.
|
104
|
+
* If a non-zero value is returned then DAG generation will stop.
|
105
|
+
* Be advised. A progress value of 100 means that DAG creation is
|
106
|
+
* almost complete and that this function will soon return succesfully.
|
107
|
+
* It does not mean that the function has already had a succesfull return.
|
108
|
+
* @return Newly allocated ethash_full handler or NULL in case of
|
109
|
+
* ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data()
|
110
|
+
*/
|
111
|
+
ethash_full_t ethash_full_new(ethash_light_t light, ethash_callback_t callback);
|
112
|
+
|
113
|
+
/**
|
114
|
+
* Frees a previously allocated ethash_full handler
|
115
|
+
* @param full The light handler to free
|
116
|
+
*/
|
117
|
+
void ethash_full_delete(ethash_full_t full);
|
118
|
+
/**
|
119
|
+
* Calculate the full client data
|
120
|
+
*
|
121
|
+
* @param full The full client handler
|
122
|
+
* @param header_hash The header hash to pack into the mix
|
123
|
+
* @param nonce The nonce to pack into the mix
|
124
|
+
* @return An object of ethash_return_value to hold the return value
|
125
|
+
*/
|
126
|
+
ethash_return_value_t ethash_full_compute(
|
127
|
+
ethash_full_t full,
|
128
|
+
ethash_h256_t const header_hash,
|
129
|
+
uint64_t nonce
|
130
|
+
);
|
131
|
+
/**
|
132
|
+
* Get a pointer to the full DAG data
|
133
|
+
*/
|
134
|
+
void const* ethash_full_dag(ethash_full_t full);
|
135
|
+
/**
|
136
|
+
* Get the size of the DAG data
|
137
|
+
*/
|
138
|
+
uint64_t ethash_full_dag_size(ethash_full_t full);
|
139
|
+
|
140
|
+
/**
|
141
|
+
* Calculate the seedhash for a given block number
|
142
|
+
*/
|
143
|
+
ethash_h256_t ethash_get_seedhash(uint64_t block_number);
|
144
|
+
|
145
|
+
#ifdef __cplusplus
|
146
|
+
}
|
147
|
+
#endif
|
@@ -0,0 +1,43 @@
|
|
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
|
+
*/
|
17
|
+
/** @file fnv.h
|
18
|
+
* @author Matthew Wampler-Doty <negacthulhu@gmail.com>
|
19
|
+
* @date 2015
|
20
|
+
*/
|
21
|
+
|
22
|
+
#pragma once
|
23
|
+
#include <stdint.h>
|
24
|
+
#include "compiler.h"
|
25
|
+
|
26
|
+
#ifdef __cplusplus
|
27
|
+
extern "C" {
|
28
|
+
#endif
|
29
|
+
|
30
|
+
#define FNV_PRIME 0x01000193
|
31
|
+
|
32
|
+
/* The FNV-1 spec multiplies the prime with the input one byte (octet) in turn.
|
33
|
+
We instead multiply it with the full 32-bit input.
|
34
|
+
This gives a different result compared to a canonical FNV-1 implementation.
|
35
|
+
*/
|
36
|
+
static inline uint32_t fnv_hash(uint32_t const x, uint32_t const y)
|
37
|
+
{
|
38
|
+
return x * FNV_PRIME ^ y;
|
39
|
+
}
|
40
|
+
|
41
|
+
#ifdef __cplusplus
|
42
|
+
}
|
43
|
+
#endif
|
@@ -0,0 +1,179 @@
|
|
1
|
+
#pragma once
|
2
|
+
#include "compiler.h"
|
3
|
+
#include "endian.h"
|
4
|
+
#include "ethash.h"
|
5
|
+
#include <stdio.h>
|
6
|
+
|
7
|
+
#define ENABLE_SSE 0
|
8
|
+
|
9
|
+
#if defined(_M_X64) && ENABLE_SSE
|
10
|
+
#include <smmintrin.h>
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#ifdef __cplusplus
|
14
|
+
extern "C" {
|
15
|
+
#endif
|
16
|
+
|
17
|
+
// compile time settings
|
18
|
+
#define NODE_WORDS (64/4)
|
19
|
+
#define MIX_WORDS (ETHASH_MIX_BYTES/4)
|
20
|
+
#define MIX_NODES (MIX_WORDS / NODE_WORDS)
|
21
|
+
#include <stdint.h>
|
22
|
+
|
23
|
+
typedef union node {
|
24
|
+
uint8_t bytes[NODE_WORDS * 4];
|
25
|
+
uint32_t words[NODE_WORDS];
|
26
|
+
uint64_t double_words[NODE_WORDS / 2];
|
27
|
+
|
28
|
+
#if defined(_M_X64) && ENABLE_SSE
|
29
|
+
__m128i xmm[NODE_WORDS/4];
|
30
|
+
#endif
|
31
|
+
|
32
|
+
} node;
|
33
|
+
|
34
|
+
static inline uint8_t ethash_h256_get(ethash_h256_t const* hash, unsigned int i)
|
35
|
+
{
|
36
|
+
return hash->b[i];
|
37
|
+
}
|
38
|
+
|
39
|
+
static inline void ethash_h256_set(ethash_h256_t* hash, unsigned int i, uint8_t v)
|
40
|
+
{
|
41
|
+
hash->b[i] = v;
|
42
|
+
}
|
43
|
+
|
44
|
+
static inline void ethash_h256_reset(ethash_h256_t* hash)
|
45
|
+
{
|
46
|
+
memset(hash, 0, 32);
|
47
|
+
}
|
48
|
+
|
49
|
+
// Returns if hash is less than or equal to boundary (2^256/difficulty)
|
50
|
+
static inline bool ethash_check_difficulty(
|
51
|
+
ethash_h256_t const* hash,
|
52
|
+
ethash_h256_t const* boundary
|
53
|
+
)
|
54
|
+
{
|
55
|
+
// Boundary is big endian
|
56
|
+
for (int i = 0; i < 32; i++) {
|
57
|
+
if (ethash_h256_get(hash, i) == ethash_h256_get(boundary, i)) {
|
58
|
+
continue;
|
59
|
+
}
|
60
|
+
return ethash_h256_get(hash, i) < ethash_h256_get(boundary, i);
|
61
|
+
}
|
62
|
+
return true;
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Difficulty quick check for POW preverification
|
67
|
+
*
|
68
|
+
* @param header_hash The hash of the header
|
69
|
+
* @param nonce The block's nonce
|
70
|
+
* @param mix_hash The mix digest hash
|
71
|
+
* @param boundary The boundary is defined as (2^256 / difficulty)
|
72
|
+
* @return true for succesful pre-verification and false otherwise
|
73
|
+
*/
|
74
|
+
bool ethash_quick_check_difficulty(
|
75
|
+
ethash_h256_t const* header_hash,
|
76
|
+
uint64_t const nonce,
|
77
|
+
ethash_h256_t const* mix_hash,
|
78
|
+
ethash_h256_t const* boundary
|
79
|
+
);
|
80
|
+
|
81
|
+
struct ethash_light {
|
82
|
+
void* cache;
|
83
|
+
uint64_t cache_size;
|
84
|
+
uint64_t block_number;
|
85
|
+
};
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Allocate and initialize a new ethash_light handler. Internal version
|
89
|
+
*
|
90
|
+
* @param cache_size The size of the cache in bytes
|
91
|
+
* @param seed Block seedhash to be used during the computation of the
|
92
|
+
* cache nodes
|
93
|
+
* @return Newly allocated ethash_light handler or NULL in case of
|
94
|
+
* ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes()
|
95
|
+
*/
|
96
|
+
ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const* seed);
|
97
|
+
|
98
|
+
/**
|
99
|
+
* Calculate the light client data. Internal version.
|
100
|
+
*
|
101
|
+
* @param light The light client handler
|
102
|
+
* @param full_size The size of the full data in bytes.
|
103
|
+
* @param header_hash The header hash to pack into the mix
|
104
|
+
* @param nonce The nonce to pack into the mix
|
105
|
+
* @return The resulting hash.
|
106
|
+
*/
|
107
|
+
ethash_return_value_t ethash_light_compute_internal(
|
108
|
+
ethash_light_t light,
|
109
|
+
uint64_t full_size,
|
110
|
+
ethash_h256_t const header_hash,
|
111
|
+
uint64_t nonce
|
112
|
+
);
|
113
|
+
|
114
|
+
struct ethash_full {
|
115
|
+
FILE* file;
|
116
|
+
uint64_t file_size;
|
117
|
+
node* data;
|
118
|
+
};
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Allocate and initialize a new ethash_full handler. Internal version.
|
122
|
+
*
|
123
|
+
* @param dirname The directory in which to put the DAG file.
|
124
|
+
* @param seedhash The seed hash of the block. Used in the DAG file naming.
|
125
|
+
* @param full_size The size of the full data in bytes.
|
126
|
+
* @param cache A cache object to use that was allocated with @ref ethash_cache_new().
|
127
|
+
* Iff this function succeeds the ethash_full_t will take memory
|
128
|
+
* memory ownership of the cache and free it at deletion. If
|
129
|
+
* not then the user still has to handle freeing of the cache himself.
|
130
|
+
* @param callback A callback function with signature of @ref ethash_callback_t
|
131
|
+
* It accepts an unsigned with which a progress of DAG calculation
|
132
|
+
* can be displayed. If all goes well the callback should return 0.
|
133
|
+
* If a non-zero value is returned then DAG generation will stop.
|
134
|
+
* @return Newly allocated ethash_full handler or NULL in case of
|
135
|
+
* ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data()
|
136
|
+
*/
|
137
|
+
ethash_full_t ethash_full_new_internal(
|
138
|
+
char const* dirname,
|
139
|
+
ethash_h256_t const seed_hash,
|
140
|
+
uint64_t full_size,
|
141
|
+
ethash_light_t const light,
|
142
|
+
ethash_callback_t callback
|
143
|
+
);
|
144
|
+
|
145
|
+
void ethash_calculate_dag_item(
|
146
|
+
node* const ret,
|
147
|
+
uint32_t node_index,
|
148
|
+
ethash_light_t const cache
|
149
|
+
);
|
150
|
+
|
151
|
+
void ethash_quick_hash(
|
152
|
+
ethash_h256_t* return_hash,
|
153
|
+
ethash_h256_t const* header_hash,
|
154
|
+
const uint64_t nonce,
|
155
|
+
ethash_h256_t const* mix_hash
|
156
|
+
);
|
157
|
+
|
158
|
+
uint64_t ethash_get_datasize(uint64_t const block_number);
|
159
|
+
uint64_t ethash_get_cachesize(uint64_t const block_number);
|
160
|
+
|
161
|
+
/**
|
162
|
+
* Compute the memory data for a full node's memory
|
163
|
+
*
|
164
|
+
* @param mem A pointer to an ethash full's memory
|
165
|
+
* @param full_size The size of the full data in bytes
|
166
|
+
* @param cache A cache object to use in the calculation
|
167
|
+
* @param callback The callback function. Check @ref ethash_full_new() for details.
|
168
|
+
* @return true if all went fine and false for invalid parameters
|
169
|
+
*/
|
170
|
+
bool ethash_compute_full_data(
|
171
|
+
void* mem,
|
172
|
+
uint64_t full_size,
|
173
|
+
ethash_light_t const light,
|
174
|
+
ethash_callback_t callback
|
175
|
+
);
|
176
|
+
|
177
|
+
#ifdef __cplusplus
|
178
|
+
}
|
179
|
+
#endif
|