From 6d244fe69a1d959dd6fb9d47a26f551ee276f52b Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 25 Mar 2015 18:18:29 +0100 Subject: [PATCH] Use ethash_blockhash_t over the codebase - Using a typedef struct instead of passing an array of hard coded length of 32 bytes everywhere. It's much better C practise and also gives us typechecking. - Also corrected style in places I touched. I think a style PR should follow after that. --- ethash.h | 113 ++++++++++++++++++++++++++++------------------ internal.c | 98 ++++++++++++++++++++++------------------ internal.h | 23 ++++------ io.h | 2 - sha3.h | 12 +++-- sha3_cryptopp.cpp | 9 ++-- sha3_cryptopp.h | 8 +++- 7 files changed, 153 insertions(+), 112 deletions(-) diff --git a/ethash.h b/ethash.h index eb3097307..fad964449 100644 --- a/ethash.h +++ b/ethash.h @@ -47,9 +47,26 @@ typedef struct ethash_params { uint64_t cache_size; // Size of compute cache (in bytes, multiple of node size (64)). } ethash_params; +/// Type of a blockhash +typedef struct ethash_blockhash { uint8_t b[32]; } ethash_blockhash_t; +static inline uint8_t ethash_blockhash_get(ethash_blockhash_t const* hash, unsigned int i) +{ + return hash->b[i]; +} + +static inline void ethash_blockhash_set(ethash_blockhash_t *hash, unsigned int i, uint8_t v) +{ + hash->b[i] = v; +} + +static inline void ethash_blockhash_reset(ethash_blockhash_t *hash) +{ + memset(hash, 0, 32); +} + typedef struct ethash_return_value { - uint8_t result[32]; - uint8_t mix_hash[32]; + ethash_blockhash_t result; + ethash_blockhash_t mix_hash; } ethash_return_value; uint64_t ethash_get_datasize(const uint32_t block_number); @@ -65,58 +82,68 @@ typedef struct ethash_cache { void *mem; } ethash_cache; -void ethash_mkcache(ethash_cache *cache, ethash_params const *params, const uint8_t seed[32]); +void ethash_mkcache(ethash_cache *cache, ethash_params const *params, ethash_blockhash_t const *seed); void ethash_compute_full_data(void *mem, ethash_params const *params, ethash_cache const *cache); -void ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce); -void ethash_light(ethash_return_value *ret, ethash_cache const *cache, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce); -void ethash_get_seedhash(uint8_t seedhash[32], const uint32_t block_number); - -static inline void ethash_prep_light(void *cache, ethash_params const *params, const uint8_t seed[32]) { - ethash_cache c; - c.mem = cache; - ethash_mkcache(&c, params, seed); +void ethash_full(ethash_return_value *ret, + void const *full_mem, + ethash_params const *params, + ethash_blockhash_t const *header_hash, + const uint64_t nonce); +void ethash_light(ethash_return_value *ret, + ethash_cache const *cache, + ethash_params const *params, + ethash_blockhash_t const *header_hash, + const uint64_t nonce); +void ethash_get_seedhash(ethash_blockhash_t *seedhash, const uint32_t block_number); + +static inline void ethash_prep_light(void *cache, ethash_params const *params, ethash_blockhash_t const* seed) +{ + ethash_cache c; + c.mem = cache; + ethash_mkcache(&c, params, seed); } -static inline void ethash_compute_light(ethash_return_value *ret, void const *cache, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce) { - ethash_cache c; - c.mem = (void *) cache; - ethash_light(ret, &c, params, header_hash, nonce); +static inline void ethash_compute_light(ethash_return_value *ret, void const *cache, ethash_params const *params, ethash_blockhash_t const *header_hash, const uint64_t nonce) +{ + ethash_cache c; + c.mem = (void *) cache; + ethash_light(ret, &c, params, header_hash, nonce); } -static inline void ethash_prep_full(void *full, ethash_params const *params, void const *cache) { - ethash_cache c; - c.mem = (void *) cache; - ethash_compute_full_data(full, params, &c); +static inline void ethash_prep_full(void *full, ethash_params const *params, void const *cache) +{ + ethash_cache c; + c.mem = (void *) cache; + ethash_compute_full_data(full, params, &c); } -static inline void ethash_compute_full(ethash_return_value *ret, void const *full, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce) { - ethash_full(ret, full, params, header_hash, nonce); +static inline void ethash_compute_full(ethash_return_value *ret, + void const *full, + ethash_params const *params, + ethash_blockhash_t const *header_hash, + const uint64_t nonce) +{ + ethash_full(ret, full, params, header_hash, nonce); } -/// @brief Compare two s256-bit big-endian values. -/// @returns 1 if @a a is less than or equal to @a b, 0 otherwise. -/// Both parameters are 256-bit big-endian values. -static inline int ethash_leq_be256(const uint8_t a[32], const uint8_t b[32]) { - // Boundary is big endian - for (int i = 0; i < 32; i++) { - if (a[i] == b[i]) - continue; - return a[i] < b[i]; - } - return 1; +// Returns if hash is less than or equal to difficulty +static inline int ethash_check_difficulty(ethash_blockhash_t const *hash, + ethash_blockhash_t const *difficulty) +{ + // Difficulty is big endian + for (int i = 0; i < 32; i++) { + if (ethash_blockhash_get(hash, i) == ethash_blockhash_get(difficulty, i)) { + continue; + } + return ethash_blockhash_get(hash, i) < ethash_blockhash_get(difficulty, i); + } + return 1; } -/// Perofrms a cursory check on the validity of the nonce. -/// @returns 1 if the nonce may possibly be valid for the given header_hash & boundary. -/// @p boundary equivalent to 2 ^ 256 / block_difficulty, represented as a 256-bit big-endian. -int ethash_preliminary_check_boundary( - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32], - const uint8_t boundary[32]); - -#define ethash_quick_check_difficulty ethash_preliminary_check_boundary -#define ethash_check_difficulty ethash_leq_be256 +int ethash_quick_check_difficulty(ethash_blockhash_t const *header_hash, + const uint64_t nonce, + ethash_blockhash_t const *mix_hash, + ethash_blockhash_t const *difficulty); #ifdef __cplusplus } diff --git a/internal.c b/internal.c index ae9b95065..5009d52f5 100644 --- a/internal.c +++ b/internal.c @@ -50,14 +50,14 @@ uint64_t ethash_get_cachesize(const uint32_t block_number) { // Follows Sergio's "STRICT MEMORY HARD HASHING FUNCTIONS" (2014) // https://bitslog.files.wordpress.com/2013/12/memohash-v0-3.pdf // SeqMemoHash(s, R, N) -void static ethash_compute_cache_nodes( - node *const nodes, - ethash_params const *params, - const uint8_t seed[32]) { +void static ethash_compute_cache_nodes(node *const nodes, + ethash_params const *params, + ethash_blockhash_t const* seed) +{ assert((params->cache_size % sizeof(node)) == 0); uint32_t const num_nodes = (uint32_t) (params->cache_size / sizeof(node)); - SHA3_512(nodes[0].bytes, seed, 32); + SHA3_512(nodes[0].bytes, (uint8_t*)seed, 32); for (unsigned i = 1; i != num_nodes; ++i) { SHA3_512(nodes[i].bytes, nodes[i - 1].bytes, 64); @@ -84,20 +84,19 @@ void static ethash_compute_cache_nodes( #endif } -void ethash_mkcache( - ethash_cache *cache, - ethash_params const *params, - const uint8_t seed[32]) { +void ethash_mkcache(ethash_cache *cache, + ethash_params const *params, + ethash_blockhash_t const* seed) +{ node *nodes = (node *) cache->mem; ethash_compute_cache_nodes(nodes, params, seed); } -void ethash_calculate_dag_item( - node *const ret, - const unsigned node_index, - const struct ethash_params *params, - const struct ethash_cache *cache) { - +void ethash_calculate_dag_item(node *const ret, + const unsigned node_index, + const struct ethash_params *params, + const struct ethash_cache *cache) +{ uint32_t num_parent_nodes = (uint32_t) (params->cache_size / sizeof(node)); node const *cache_nodes = (node const *) cache->mem; node const *init = &cache_nodes[node_index % num_parent_nodes]; @@ -161,13 +160,13 @@ void ethash_compute_full_data( } } -static void ethash_hash( - ethash_return_value *ret, - node const *full_nodes, - ethash_cache const *cache, - ethash_params const *params, - const uint8_t header_hash[32], - const uint64_t nonce) { +static void ethash_hash(ethash_return_value *ret, + node const *full_nodes, + ethash_cache const *cache, + ethash_params const *params, + ethash_blockhash_t const *header_hash, + const uint64_t nonce) +{ assert((params->full_size % MIX_WORDS) == 0); @@ -251,16 +250,16 @@ static void ethash_hash( } #endif - memcpy(ret->mix_hash, mix->bytes, 32); + memcpy(&ret->mix_hash, mix->bytes, 32); // final Keccak hash - SHA3_256(ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix) + SHA3_256(&ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix) } -void ethash_quick_hash( - uint8_t return_hash[32], - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32]) { +void ethash_quick_hash(ethash_blockhash_t *return_hash, + ethash_blockhash_t const *header_hash, + const uint64_t nonce, + ethash_blockhash_t const *mix_hash) +{ uint8_t buf[64 + 32]; memcpy(buf, header_hash, 32); @@ -273,28 +272,39 @@ void ethash_quick_hash( SHA3_256(return_hash, buf, 64 + 32); } -void ethash_get_seedhash(uint8_t seedhash[32], const uint32_t block_number) { - memset(seedhash, 0, 32); +void ethash_get_seedhash(ethash_blockhash_t *seedhash, const uint32_t block_number) +{ + ethash_blockhash_reset(seedhash); const uint32_t epochs = block_number / EPOCH_LENGTH; for (uint32_t i = 0; i < epochs; ++i) - SHA3_256(seedhash, seedhash, 32); + SHA3_256(seedhash, (uint8_t*)seedhash, 32); } -int ethash_preliminary_check_boundary( - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32], - const uint8_t difficulty[32]) { +int ethash_quick_check_difficulty(ethash_blockhash_t const *header_hash, + const uint64_t nonce, + ethash_blockhash_t const *mix_hash, + ethash_blockhash_t const *difficulty) +{ - uint8_t return_hash[32]; - ethash_quick_hash(return_hash, header_hash, nonce, mix_hash); - return ethash_leq_be256(return_hash, difficulty); + ethash_blockhash_t return_hash; + ethash_quick_hash(&return_hash, header_hash, nonce, mix_hash); + return ethash_check_difficulty(&return_hash, difficulty); } -void ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) { - ethash_hash(ret, (node const *) full_mem, NULL, params, previous_hash, nonce); +void ethash_full(ethash_return_value *ret, + void const *full_mem, + ethash_params const *params, + ethash_blockhash_t const *header_hash, + const uint64_t nonce) +{ + ethash_hash(ret, (node const *) full_mem, NULL, params, header_hash, nonce); } -void ethash_light(ethash_return_value *ret, ethash_cache const *cache, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) { - ethash_hash(ret, NULL, cache, params, previous_hash, nonce); +void ethash_light(ethash_return_value *ret, + ethash_cache const *cache, + ethash_params const *params, + ethash_blockhash_t const *header_hash, + const uint64_t nonce) +{ + ethash_hash(ret, NULL, cache, params, header_hash, nonce); } diff --git a/internal.h b/internal.h index ddd06e8f4..1e19cd1fd 100644 --- a/internal.h +++ b/internal.h @@ -30,19 +30,16 @@ typedef union node { } node; -void ethash_calculate_dag_item( - node *const ret, - const unsigned node_index, - ethash_params const *params, - ethash_cache const *cache -); - -void ethash_quick_hash( - uint8_t return_hash[32], - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32]); +void ethash_calculate_dag_item(node *const ret, + const unsigned node_index, + ethash_params const *params, + ethash_cache const *cache); + +void ethash_quick_hash(ethash_blockhash_t *return_hash, + ethash_blockhash_t const *header_hash, + const uint64_t nonce, + ethash_blockhash_t const *mix_hash); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/io.h b/io.h index 80e45c669..8cf8b69bf 100644 --- a/io.h +++ b/io.h @@ -28,8 +28,6 @@ extern "C" { #endif -typedef struct ethash_blockhash { uint8_t b[32]; } ethash_blockhash_t; - static const char DAG_FILE_NAME[] = "full"; static const char DAG_MEMO_NAME[] = "full.info"; // MSVC thinks that "static const unsigned int" is not a compile time variable. Sorry for the #define :( diff --git a/sha3.h b/sha3.h index 36a0a5301..4974a9bbc 100644 --- a/sha3.h +++ b/sha3.h @@ -8,20 +8,24 @@ extern "C" { #include #include +struct ethash_blockhash; + #define decsha3(bits) \ int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); decsha3(256) decsha3(512) -static inline void SHA3_256(uint8_t * const ret, uint8_t const *data, const size_t size) { - sha3_256(ret, 32, data, size); +static inline void SHA3_256(struct ethash_blockhash const* ret, uint8_t const *data, const size_t size) +{ + sha3_256((uint8_t*)ret, 32, data, size); } -static inline void SHA3_512(uint8_t * const ret, uint8_t const *data, const size_t size) { +static inline void SHA3_512(uint8_t const *ret, uint8_t const *data, const size_t size) +{ sha3_512(ret, 64, data, size); } #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/sha3_cryptopp.cpp b/sha3_cryptopp.cpp index 6cbbcad8f..e4d8b1855 100644 --- a/sha3_cryptopp.cpp +++ b/sha3_cryptopp.cpp @@ -19,16 +19,17 @@ * @author Tim Hughes * @date 2015 */ - #include #include extern "C" { -void SHA3_256(uint8_t *const ret, const uint8_t *data, size_t size) { - CryptoPP::SHA3_256().CalculateDigest(ret, data, size); +struct ethash_blockhash; +typedef struct ethash_blockhash ethash_blockhash_t; +void SHA3_256(ethash_blockhash_t const* ret, const uint8_t *data, size_t size) { + CryptoPP::SHA3_256().CalculateDigest((uint8_t*)ret, data, size); } void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size) { CryptoPP::SHA3_512().CalculateDigest(ret, data, size); } -} \ No newline at end of file +} diff --git a/sha3_cryptopp.h b/sha3_cryptopp.h index f910960e1..6b257b87c 100644 --- a/sha3_cryptopp.h +++ b/sha3_cryptopp.h @@ -2,14 +2,18 @@ #include "compiler.h" #include +#include #ifdef __cplusplus extern "C" { #endif -void SHA3_256(uint8_t *const ret, const uint8_t *data, size_t size); +struct ethash_blockhash; +typedef struct ethash_blockhash ethash_blockhash_t; + +void SHA3_256(ethash_blockhash_t *const ret, const uint8_t *data, size_t size); void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif