Browse Source

Coding style "adjustment"

- Adjusting the coding style for consistency after the talk we had
cl-refactor
Lefteris Karapetsas 10 years ago
parent
commit
7fd1dd36f5
  1. 1476
      data_sizes.h
  2. 102
      ethash.h
  3. 578
      internal.c
  4. 26
      internal.h
  5. 88
      io.c
  6. 54
      io.h
  7. 74
      io_posix.c
  8. 76
      io_win32.c
  9. 194
      sha3.c
  10. 6
      sha3.h
  11. 10
      sha3_cryptopp.cpp
  12. 2
      util.c

1476
data_sizes.h

File diff suppressed because it is too large

102
ethash.h

@ -44,27 +44,27 @@ extern "C" {
// LTODO: for consistency's sake maybe use ethash_params_t?
typedef struct ethash_params {
/// Size of full data set (in bytes, multiple of mix size (128)).
uint64_t full_size;
/// Size of compute cache (in bytes, multiple of node size (64)).
uint64_t cache_size;
/// Size of full data set (in bytes, multiple of mix size (128)).
uint64_t full_size;
/// Size of compute cache (in bytes, multiple of node size (64)).
uint64_t cache_size;
} ethash_params;
/// Type of a seedhash/blockhash e.t.c.
typedef struct ethash_h256 { uint8_t b[32]; } ethash_h256_t;
static inline uint8_t ethash_h256_get(ethash_h256_t const* hash, unsigned int i)
{
return hash->b[i];
return hash->b[i];
}
static inline void ethash_h256_set(ethash_h256_t *hash, unsigned int i, uint8_t v)
{
hash->b[i] = v;
hash->b[i] = v;
}
static inline void ethash_h256_reset(ethash_h256_t *hash)
{
memset(hash, 0, 32);
memset(hash, 0, 32);
}
struct ethash_light;
@ -75,8 +75,8 @@ typedef int(*ethash_callback_t)(unsigned);
// LTODO: for consistency's sake maybe use ethash_return_value_t?
typedef struct ethash_return_value {
ethash_h256_t result;
ethash_h256_t mix_hash;
ethash_h256_t result;
ethash_h256_t mix_hash;
} ethash_return_value;
uint64_t ethash_get_datasize(const uint32_t block_number);
@ -84,13 +84,13 @@ uint64_t ethash_get_cachesize(const uint32_t block_number);
// initialize the parameters
static inline void ethash_params_init(ethash_params *params, const uint32_t block_number) {
params->full_size = ethash_get_datasize(block_number);
params->cache_size = ethash_get_cachesize(block_number);
params->full_size = ethash_get_datasize(block_number);
params->cache_size = ethash_get_cachesize(block_number);
}
// LTODO: for consistency's sake maybe use ethash_cache_t?
typedef struct ethash_cache {
void *mem;
void *mem;
} ethash_cache;
/**
@ -106,7 +106,7 @@ typedef struct ethash_cache {
ethash_cache *ethash_cache_new(ethash_params const *params, ethash_h256_t const *seed);
/**
* Frees a previously allocated ethash_cache
* @param c The object to free
* @param c The object to free
*/
void ethash_cache_delete(ethash_cache *c);
@ -123,7 +123,7 @@ void ethash_cache_delete(ethash_cache *c);
ethash_light_t ethash_light_new(ethash_params const *params, ethash_h256_t const *seed);
/**
* Frees a previously allocated ethash_light handler
* @param light The light handler to free
* @param light The light handler to free
*/
void ethash_light_delete(ethash_light_t light);
/**
@ -138,10 +138,10 @@ void ethash_light_delete(ethash_light_t light);
* parameters given.
*/
bool ethash_light_compute(ethash_return_value *ret,
ethash_light_t light,
ethash_params const *params,
const ethash_h256_t *header_hash,
const uint64_t nonce);
ethash_light_t light,
ethash_params const *params,
const ethash_h256_t *header_hash,
const uint64_t nonce);
/**
* Get a pointer to the cache object held by the light client
*
@ -176,8 +176,8 @@ ethash_cache *ethash_light_acquire_cache(ethash_light_t light);
* ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data()
*/
ethash_full_t ethash_full_new(ethash_params const* params,
ethash_cache const* cache,
ethash_callback_t callback);
ethash_cache const* cache,
ethash_callback_t callback);
/**
* Frees a previously allocated ethash_full handler
* @param full The light handler to free
@ -190,16 +190,16 @@ void ethash_full_delete(ethash_full_t full);
* @param full The full client handler
* @param params The parameters to use
* @param header_hash The header hash to pack into the mix
* @param nonce The nonce to pack into the mix
* @param nonce The nonce to pack into the mix
* @return true if all went well and false if there were invalid
* parameters given or if there was a callback given and
* at some point return a non-zero value
*/
bool ethash_full_compute(ethash_return_value *ret,
ethash_full_t full,
ethash_params const *params,
const ethash_h256_t *header_hash,
const uint64_t nonce);
ethash_full_t full,
ethash_params const *params,
const ethash_h256_t *header_hash,
const uint64_t nonce);
/**
* Get a pointer to the cache object held by the full client
*
@ -221,27 +221,27 @@ void ethash_get_seedhash(ethash_h256_t *seedhash, const uint32_t block_number);
// Returns if hash is less than or equal to difficulty
static inline int ethash_check_difficulty(ethash_h256_t const *hash,
ethash_h256_t const *difficulty)
ethash_h256_t const *difficulty)
{
// Difficulty is big endian
for (int i = 0; i < 32; i++) {
if (ethash_h256_get(hash, i) == ethash_h256_get(difficulty, i)) {
continue;
}
return ethash_h256_get(hash, i) < ethash_h256_get(difficulty, i);
}
return 1;
// Difficulty is big endian
for (int i = 0; i < 32; i++) {
if (ethash_h256_get(hash, i) == ethash_h256_get(difficulty, i)) {
continue;
}
return ethash_h256_get(hash, i) < ethash_h256_get(difficulty, i);
}
return 1;
}
int ethash_quick_check_difficulty(ethash_h256_t const *header_hash,
const uint64_t nonce,
ethash_h256_t const *mix_hash,
ethash_h256_t const *difficulty);
const uint64_t nonce,
ethash_h256_t const *mix_hash,
ethash_h256_t const *difficulty);
/**
* =========================
* = DEPRECATED API =
* = DEPRECATED API =
* =========================
*
* Kept for backwards compatibility with whoever still uses it. Please consider
@ -249,22 +249,22 @@ int ethash_quick_check_difficulty(ethash_h256_t const *header_hash,
*/
void ethash_mkcache(ethash_cache *cache, ethash_params const *params, ethash_h256_t const *seed);
void ethash_full(ethash_return_value *ret,
void const *full_mem,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce);
void const *full_mem,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce);
void ethash_light(ethash_return_value *ret,
ethash_cache const *cache,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce);
ethash_cache const *cache,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce);
/**
* Compute the memory data for a full node's memory
*
* @param mem A pointer to an ethash full's memory
* @param params The parameters to compute the data with
* @param cache A cache object to use in the calculation
* @return true if all went fine and false for invalid parameters
*
* @param mem A pointer to an ethash full's memory
* @param params The parameters to compute the data with
* @param cache A cache object to use in the calculation
* @return true if all went fine and false for invalid parameters
*/
bool ethash_compute_full_data(void *mem, ethash_params const *params, ethash_cache const *cache);

578
internal.c

@ -8,11 +8,11 @@
ethash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file internal.c
* @author Tim Hughes <tim@twistedfury.com>
@ -38,411 +38,413 @@
#endif // WITH_CRYPTOPP
uint64_t ethash_get_datasize(const uint32_t block_number) {
assert(block_number / EPOCH_LENGTH < 2048);
return dag_sizes[block_number / EPOCH_LENGTH];
assert(block_number / EPOCH_LENGTH < 2048);
return dag_sizes[block_number / EPOCH_LENGTH];
}
uint64_t ethash_get_cachesize(const uint32_t block_number) {
assert(block_number / EPOCH_LENGTH < 2048);
return cache_sizes[block_number / EPOCH_LENGTH];
assert(block_number / EPOCH_LENGTH < 2048);
return cache_sizes[block_number / EPOCH_LENGTH];
}
// Follows Sergio's "STRICT MEMORY HARD HASHING FUNCTIONS" (2014)
// https://bitslog.files.wordpress.com/2013/12/memohash-v0-3.pdf
// SeqMemoHash(s, R, N)
bool static ethash_compute_cache_nodes(node *const nodes,
ethash_params const *params,
ethash_h256_t const* seed)
ethash_params const *params,
ethash_h256_t const* seed)
{
if (params->cache_size % sizeof(node) != 0) {
return false;
}
uint32_t const num_nodes = (uint32_t) (params->cache_size / sizeof(node));
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);
}
for (unsigned j = 0; j != CACHE_ROUNDS; j++) {
for (unsigned i = 0; i != num_nodes; i++) {
uint32_t const idx = nodes[i].words[0] % num_nodes;
node data;
data = nodes[(num_nodes - 1 + i) % num_nodes];
for (unsigned w = 0; w != NODE_WORDS; ++w) {
data.words[w] ^= nodes[idx].words[w];
}
SHA3_512(nodes[i].bytes, data.bytes, sizeof(data));
}
}
fix_endian_arr32(nodes->words, num_nodes * NODE_WORDS);
return true;
if (params->cache_size % sizeof(node) != 0) {
return false;
}
uint32_t const num_nodes = (uint32_t) (params->cache_size / sizeof(node));
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);
}
for (unsigned j = 0; j != CACHE_ROUNDS; j++) {
for (unsigned i = 0; i != num_nodes; i++) {
uint32_t const idx = nodes[i].words[0] % num_nodes;
node data;
data = nodes[(num_nodes - 1 + i) % num_nodes];
for (unsigned w = 0; w != NODE_WORDS; ++w) {
data.words[w] ^= nodes[idx].words[w];
}
SHA3_512(nodes[i].bytes, data.bytes, sizeof(data));
}
}
// now perform endian conversion
fix_endian_arr32(nodes->words, num_nodes * NODE_WORDS);
return true;
}
ethash_cache *ethash_cache_new(ethash_params const *params, ethash_h256_t const *seed)
{
ethash_cache *ret;
ret = malloc(sizeof(*ret));
if (!ret) {
return NULL;
}
ret->mem = malloc((size_t)params->cache_size);
if (!ret->mem) {
goto fail_free_cache;
}
node *nodes = (node*)ret->mem;
if (!ethash_compute_cache_nodes(nodes, params, seed)) {
goto fail_free_cache_mem;
}
return ret;
ethash_cache *ret;
ret = malloc(sizeof(*ret));
if (!ret) {
return NULL;
}
ret->mem = malloc((size_t)params->cache_size);
if (!ret->mem) {
goto fail_free_cache;
}
node *nodes = (node*)ret->mem;
if (!ethash_compute_cache_nodes(nodes, params, seed)) {
goto fail_free_cache_mem;
}
return ret;
fail_free_cache_mem:
free(ret->mem);
free(ret->mem);
fail_free_cache:
free(ret);
return NULL;
free(ret);
return NULL;
}
void ethash_cache_delete(ethash_cache *c)
{
free(c->mem);
free(c);
free(c->mem);
free(c);
}
void ethash_calculate_dag_item(node *const ret,
const unsigned node_index,
const struct ethash_params *params,
const struct ethash_cache *cache)
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];
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];
memcpy(ret, init, sizeof(node));
ret->words[0] ^= node_index;
SHA3_512(ret->bytes, ret->bytes, sizeof(node));
memcpy(ret, init, sizeof(node));
ret->words[0] ^= node_index;
SHA3_512(ret->bytes, ret->bytes, sizeof(node));
#if defined(_M_X64) && ENABLE_SSE
__m128i const fnv_prime = _mm_set1_epi32(FNV_PRIME);
__m128i xmm0 = ret->xmm[0];
__m128i xmm1 = ret->xmm[1];
__m128i xmm2 = ret->xmm[2];
__m128i xmm3 = ret->xmm[3];
__m128i const fnv_prime = _mm_set1_epi32(FNV_PRIME);
__m128i xmm0 = ret->xmm[0];
__m128i xmm1 = ret->xmm[1];
__m128i xmm2 = ret->xmm[2];
__m128i xmm3 = ret->xmm[3];
#endif
for (unsigned i = 0; i != DATASET_PARENTS; ++i) {
uint32_t parent_index = ((node_index ^ i) * FNV_PRIME ^ ret->words[i % NODE_WORDS]) % num_parent_nodes;
node const *parent = &cache_nodes[parent_index];
for (unsigned i = 0; i != DATASET_PARENTS; ++i) {
uint32_t parent_index = ((node_index ^ i) * FNV_PRIME ^ ret->words[i % NODE_WORDS]) % num_parent_nodes;
node const *parent = &cache_nodes[parent_index];
#if defined(_M_X64) && ENABLE_SSE
{
xmm0 = _mm_mullo_epi32(xmm0, fnv_prime);
xmm1 = _mm_mullo_epi32(xmm1, fnv_prime);
xmm2 = _mm_mullo_epi32(xmm2, fnv_prime);
xmm3 = _mm_mullo_epi32(xmm3, fnv_prime);
xmm0 = _mm_xor_si128(xmm0, parent->xmm[0]);
xmm1 = _mm_xor_si128(xmm1, parent->xmm[1]);
xmm2 = _mm_xor_si128(xmm2, parent->xmm[2]);
xmm3 = _mm_xor_si128(xmm3, parent->xmm[3]);
// have to write to ret as values are used to compute index
ret->xmm[0] = xmm0;
ret->xmm[1] = xmm1;
ret->xmm[2] = xmm2;
ret->xmm[3] = xmm3;
}
#else
{
for (unsigned w = 0; w != NODE_WORDS; ++w) {
ret->words[w] = fnv_hash(ret->words[w], parent->words[w]);
}
}
{
xmm0 = _mm_mullo_epi32(xmm0, fnv_prime);
xmm1 = _mm_mullo_epi32(xmm1, fnv_prime);
xmm2 = _mm_mullo_epi32(xmm2, fnv_prime);
xmm3 = _mm_mullo_epi32(xmm3, fnv_prime);
xmm0 = _mm_xor_si128(xmm0, parent->xmm[0]);
xmm1 = _mm_xor_si128(xmm1, parent->xmm[1]);
xmm2 = _mm_xor_si128(xmm2, parent->xmm[2]);
xmm3 = _mm_xor_si128(xmm3, parent->xmm[3]);
// have to write to ret as values are used to compute index
ret->xmm[0] = xmm0;
ret->xmm[1] = xmm1;
ret->xmm[2] = xmm2;
ret->xmm[3] = xmm3;
}
#else
{
for (unsigned w = 0; w != NODE_WORDS; ++w) {
ret->words[w] = fnv_hash(ret->words[w], parent->words[w]);
}
}
#endif
}
}
SHA3_512(ret->bytes, ret->bytes, sizeof(node));
SHA3_512(ret->bytes, ret->bytes, sizeof(node));
}
bool ethash_compute_full_data(void *mem,
ethash_params const *params,
ethash_cache const *cache)
ethash_params const *params,
ethash_cache const *cache)
{
if (params->full_size % (sizeof(uint32_t) * MIX_WORDS) != 0 ||
(params->full_size % sizeof(node)) != 0) {
return false;
}
node *full_nodes = mem;
// now compute full nodes
for (unsigned n = 0; n != (params->full_size / sizeof(node)); ++n) {
ethash_calculate_dag_item(&(full_nodes[n]), n, params, cache);
}
return true;
if (params->full_size % (sizeof(uint32_t) * MIX_WORDS) != 0 ||
(params->full_size % sizeof(node)) != 0) {
return false;
}
node *full_nodes = mem;
// now compute full nodes
for (unsigned n = 0; n != (params->full_size / sizeof(node)); ++n) {
ethash_calculate_dag_item(&(full_nodes[n]), n, params, cache);
}
return true;
}
static bool ethash_hash(ethash_return_value *ret,
node const *full_nodes,
ethash_cache const *cache,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce,
ethash_callback_t callback)
node const *full_nodes,
ethash_cache const *cache,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce,
ethash_callback_t callback)
{
if (params->full_size % MIX_WORDS != 0) {
return false;
}
// pack hash and nonce together into first 40 bytes of s_mix
assert(sizeof(node) * 8 == 512);
node s_mix[MIX_NODES + 1];
memcpy(s_mix[0].bytes, header_hash, 32);
fix_endian64(s_mix[0].double_words[4], nonce);
// compute sha3-512 hash and replicate across mix
SHA3_512(s_mix->bytes, s_mix->bytes, 40);
fix_endian_arr32(s_mix[0].words, 16);
node *const mix = s_mix + 1;
for (unsigned w = 0; w != MIX_WORDS; ++w) {
mix->words[w] = s_mix[0].words[w % NODE_WORDS];
}
unsigned const
page_size = sizeof(uint32_t) * MIX_WORDS,
num_full_pages = (unsigned) (params->full_size / page_size);
for (unsigned i = 0; i != ACCESSES; ++i) {
uint32_t const index = ((s_mix->words[0] ^ i) * FNV_PRIME ^ mix->words[i % MIX_WORDS]) % num_full_pages;
for (unsigned n = 0; n != MIX_NODES; ++n) {
const node *dag_node;
if (callback &&
callback(((float)(i * n) / (float)(ACCESSES * MIX_NODES) * 100) != 0)) {
return false;
}
if (full_nodes) {
dag_node = &full_nodes[MIX_NODES * index + n];
} else {
node tmp_node;
ethash_calculate_dag_item(&tmp_node, index * MIX_NODES + n, params, cache);
dag_node = &tmp_node;
}
if (params->full_size % MIX_WORDS != 0) {
return false;
}
// pack hash and nonce together into first 40 bytes of s_mix
assert(sizeof(node) * 8 == 512);
node s_mix[MIX_NODES + 1];
memcpy(s_mix[0].bytes, header_hash, 32);
fix_endian64(s_mix[0].double_words[4], nonce);
// compute sha3-512 hash and replicate across mix
SHA3_512(s_mix->bytes, s_mix->bytes, 40);
fix_endian_arr32(s_mix[0].words, 16);
node *const mix = s_mix + 1;
for (unsigned w = 0; w != MIX_WORDS; ++w) {
mix->words[w] = s_mix[0].words[w % NODE_WORDS];
}
unsigned const
page_size = sizeof(uint32_t) * MIX_WORDS,
num_full_pages = (unsigned) (params->full_size / page_size);
for (unsigned i = 0; i != ACCESSES; ++i) {
uint32_t const index = ((s_mix->words[0] ^ i) * FNV_PRIME ^ mix->words[i % MIX_WORDS]) % num_full_pages;
for (unsigned n = 0; n != MIX_NODES; ++n) {
const node *dag_node;
if (callback &&
callback(((float)(i * n) / (float)(ACCESSES * MIX_NODES) * 100) != 0)) {
return false;
}
if (full_nodes) {
dag_node = &full_nodes[MIX_NODES * index + n];
} else {
node tmp_node;
ethash_calculate_dag_item(&tmp_node, index * MIX_NODES + n, params, cache);
dag_node = &tmp_node;
}
#if defined(_M_X64) && ENABLE_SSE
{
__m128i fnv_prime = _mm_set1_epi32(FNV_PRIME);
__m128i xmm0 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[0]);
__m128i xmm1 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[1]);
__m128i xmm2 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[2]);
__m128i xmm3 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[3]);
mix[n].xmm[0] = _mm_xor_si128(xmm0, dag_node->xmm[0]);
mix[n].xmm[1] = _mm_xor_si128(xmm1, dag_node->xmm[1]);
mix[n].xmm[2] = _mm_xor_si128(xmm2, dag_node->xmm[2]);
mix[n].xmm[3] = _mm_xor_si128(xmm3, dag_node->xmm[3]);
}
#else
{
for (unsigned w = 0; w != NODE_WORDS; ++w) {
mix[n].words[w] = fnv_hash(mix[n].words[w], dag_node->words[w]);
}
}
{
__m128i fnv_prime = _mm_set1_epi32(FNV_PRIME);
__m128i xmm0 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[0]);
__m128i xmm1 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[1]);
__m128i xmm2 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[2]);
__m128i xmm3 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[3]);
mix[n].xmm[0] = _mm_xor_si128(xmm0, dag_node->xmm[0]);
mix[n].xmm[1] = _mm_xor_si128(xmm1, dag_node->xmm[1]);
mix[n].xmm[2] = _mm_xor_si128(xmm2, dag_node->xmm[2]);
mix[n].xmm[3] = _mm_xor_si128(xmm3, dag_node->xmm[3]);
}
#else
{
for (unsigned w = 0; w != NODE_WORDS; ++w) {
mix[n].words[w] = fnv_hash(mix[n].words[w], dag_node->words[w]);
}
}
#endif
}
}
// compress mix
for (unsigned w = 0; w != MIX_WORDS; w += 4) {
uint32_t reduction = mix->words[w + 0];
reduction = reduction * FNV_PRIME ^ mix->words[w + 1];
reduction = reduction * FNV_PRIME ^ mix->words[w + 2];
reduction = reduction * FNV_PRIME ^ mix->words[w + 3];
mix->words[w / 4] = reduction;
}
fix_endian_arr32(mix->words, MIX_WORDS / 4);
memcpy(&ret->mix_hash, mix->bytes, 32);
// final Keccak hash
SHA3_256(&ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix)
return true;
}
}
// compress mix
for (unsigned w = 0; w != MIX_WORDS; w += 4) {
uint32_t reduction = mix->words[w + 0];
reduction = reduction * FNV_PRIME ^ mix->words[w + 1];
reduction = reduction * FNV_PRIME ^ mix->words[w + 2];
reduction = reduction * FNV_PRIME ^ mix->words[w + 3];
mix->words[w / 4] = reduction;
}
fix_endian_arr32(mix->words, MIX_WORDS / 4);
memcpy(&ret->mix_hash, mix->bytes, 32);
// final Keccak hash
SHA3_256(&ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix)
return true;
}
void ethash_quick_hash(ethash_h256_t *return_hash,
ethash_h256_t const *header_hash,
const uint64_t nonce,
ethash_h256_t const *mix_hash)
ethash_h256_t const *header_hash,
const uint64_t nonce,
ethash_h256_t const *mix_hash)
{
uint8_t buf[64 + 32];
memcpy(buf, header_hash, 32);
fix_endian64_same(nonce);
memcpy(&(buf[32]), &nonce, 8);
SHA3_512(buf, buf, 40);
memcpy(&(buf[64]), mix_hash, 32);
SHA3_256(return_hash, buf, 64 + 32);
uint8_t buf[64 + 32];
memcpy(buf, header_hash, 32);
fix_endian64_same(nonce);
memcpy(&(buf[32]), &nonce, 8);
SHA3_512(buf, buf, 40);
memcpy(&(buf[64]), mix_hash, 32);
SHA3_256(return_hash, buf, 64 + 32);
}
void ethash_get_seedhash(ethash_h256_t *seedhash, const uint32_t block_number)
{
ethash_h256_reset(seedhash);
const uint32_t epochs = block_number / EPOCH_LENGTH;
for (uint32_t i = 0; i < epochs; ++i)
SHA3_256(seedhash, (uint8_t*)seedhash, 32);
ethash_h256_reset(seedhash);
const uint32_t epochs = block_number / EPOCH_LENGTH;
for (uint32_t i = 0; i < epochs; ++i)
SHA3_256(seedhash, (uint8_t*)seedhash, 32);
}
int ethash_quick_check_difficulty(ethash_h256_t const *header_hash,
const uint64_t nonce,
ethash_h256_t const *mix_hash,
ethash_h256_t const *difficulty)
const uint64_t nonce,
ethash_h256_t const *mix_hash,
ethash_h256_t const *difficulty)
{
ethash_h256_t return_hash;
ethash_quick_hash(&return_hash, header_hash, nonce, mix_hash);
return ethash_check_difficulty(&return_hash, difficulty);
ethash_h256_t return_hash;
ethash_quick_hash(&return_hash, header_hash, nonce, mix_hash);
return ethash_check_difficulty(&return_hash, difficulty);
}
ethash_light_t ethash_light_new(ethash_params const *params, ethash_h256_t const *seed)
{
struct ethash_light *ret;
ret = calloc(sizeof(*ret), 1);
if (!ret) {
return NULL;
}
ret->cache = ethash_cache_new(params, seed);
if (!ret->cache) {
goto fail_free_light;
}
return ret;
struct ethash_light *ret;
ret = calloc(sizeof(*ret), 1);
if (!ret) {
return NULL;
}
ret->cache = ethash_cache_new(params, seed);
if (!ret->cache) {
goto fail_free_light;
}
return ret;
fail_free_light:
free(ret);
return NULL;
free(ret);
return NULL;
}
void ethash_light_delete(ethash_light_t light)
{
if (light->cache) {
ethash_cache_delete(light->cache);
}
free(light);
if (light->cache) {
ethash_cache_delete(light->cache);
}
free(light);
}
bool ethash_light_compute(ethash_return_value *ret,
ethash_light_t light,
ethash_params const *params,
const ethash_h256_t *header_hash,
const uint64_t nonce)
ethash_light_t light,
ethash_params const *params,
const ethash_h256_t *header_hash,
const uint64_t nonce)
{
return ethash_hash(ret, NULL, light->cache, params, header_hash, nonce, NULL);
return ethash_hash(ret, NULL, light->cache, params, header_hash, nonce, NULL);
}
ethash_cache *ethash_light_get_cache(ethash_light_t light)
{
return light->cache;
return light->cache;
}
ethash_cache *ethash_light_acquire_cache(ethash_light_t light)
{
ethash_cache* ret = light->cache;
light->cache = 0;
return ret;
ethash_cache* ret = light->cache;
light->cache = 0;
return ret;
}
ethash_full_t ethash_full_new(ethash_params const* params,
ethash_cache const* cache,
ethash_callback_t callback)
ethash_cache const* cache,
ethash_callback_t callback)
{
struct ethash_full *ret;
ret = calloc(sizeof(*ret), 1);
if (!ret) {
return NULL;
}
ret->cache = (ethash_cache*)cache;
ret->data = malloc((size_t)params->full_size);
if (!ret->data) {
goto fail_free_full;
}
if (!ethash_compute_full_data(ret->data, params, cache)) {
goto fail_free_full_data;
}
ret->callback = callback;
return ret;
struct ethash_full *ret;
ret = calloc(sizeof(*ret), 1);
if (!ret) {
return NULL;
}
ret->cache = (ethash_cache*)cache;
ret->data = malloc((size_t)params->full_size);
if (!ret->data) {
goto fail_free_full;
}
if (!ethash_compute_full_data(ret->data, params, cache)) {
goto fail_free_full_data;
}
ret->callback = callback;
return ret;
fail_free_full_data:
free(ret->data);
free(ret->data);
fail_free_full:
free(ret);
return NULL;
free(ret);
return NULL;
}
void ethash_full_delete(ethash_full_t full)
{
if (full->cache) {
ethash_cache_delete(full->cache);
}
free(full->data);
free(full);
if (full->cache) {
ethash_cache_delete(full->cache);
}
free(full->data);
free(full);
}
bool ethash_full_compute(ethash_return_value *ret,
ethash_full_t full,
ethash_params const *params,
const ethash_h256_t *header_hash,
const uint64_t nonce)
ethash_full_t full,
ethash_params const *params,
const ethash_h256_t *header_hash,
const uint64_t nonce)
{
return ethash_hash(ret,
(node const*)full->data,
NULL,
params,
header_hash,
nonce,
full->callback);
return ethash_hash(ret,
(node const*)full->data,
NULL,
params,
header_hash,
nonce,
full->callback);
}
ethash_cache *ethash_full_get_cache(ethash_full_t full)
{
return full->cache;
return full->cache;
}
ethash_cache *ethash_full_acquire_cache(ethash_full_t full)
{
ethash_cache* ret = full->cache;
full->cache = 0;
return ret;
ethash_cache* ret = full->cache;
full->cache = 0;
return ret;
}
/**
* =========================
* = DEPRECATED API =
* = DEPRECATED API =
* =========================
*
* Kept for backwards compatibility with whoever still uses it. Please consider
* switching to the new API (look above)
*/
void ethash_mkcache(ethash_cache *cache,
ethash_params const *params,
ethash_h256_t const* seed)
ethash_params const *params,
ethash_h256_t const* seed)
{
node *nodes = (node*) cache->mem;
ethash_compute_cache_nodes(nodes, params, seed);
node *nodes = (node*) cache->mem;
ethash_compute_cache_nodes(nodes, params, seed);
}
void ethash_full(ethash_return_value *ret,
void const *full_mem,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce)
void const *full_mem,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce)
{
ethash_hash(ret, (node const *) full_mem, NULL, params, header_hash, nonce, NULL);
ethash_hash(ret, (node const *) full_mem, NULL, params, header_hash, nonce, NULL);
}
void ethash_light(ethash_return_value *ret,
ethash_cache const *cache,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce)
ethash_cache const *cache,
ethash_params const *params,
ethash_h256_t const *header_hash,
const uint64_t nonce)
{
ethash_hash(ret, NULL, cache, params, header_hash, nonce, NULL);
ethash_hash(ret, NULL, cache, params, header_hash, nonce, NULL);
}

26
internal.h

@ -20,9 +20,9 @@ extern "C" {
#include <stdint.h>
typedef union node {
uint8_t bytes[NODE_WORDS * 4];
uint32_t words[NODE_WORDS];
uint64_t double_words[NODE_WORDS / 2];
uint8_t bytes[NODE_WORDS * 4];
uint32_t words[NODE_WORDS];
uint64_t double_words[NODE_WORDS / 2];
#if defined(_M_X64) && ENABLE_SSE
__m128i xmm[NODE_WORDS/4];
@ -31,24 +31,24 @@ typedef union node {
} node;
struct ethash_light {
ethash_cache *cache;
ethash_cache *cache;
};
struct ethash_full {
ethash_cache *cache;
node *data;
ethash_callback_t callback;
ethash_cache *cache;
node *data;
ethash_callback_t callback;
};
void ethash_calculate_dag_item(node *const ret,
const unsigned node_index,
ethash_params const *params,
ethash_cache const *cache);
const unsigned node_index,
ethash_params const *params,
ethash_cache const *cache);
void ethash_quick_hash(ethash_h256_t *return_hash,
ethash_h256_t const *header_hash,
const uint64_t nonce,
ethash_h256_t const *mix_hash);
ethash_h256_t const *header_hash,
const uint64_t nonce,
ethash_h256_t const *mix_hash);
#ifdef __cplusplus
}

88
io.c

@ -26,64 +26,64 @@
#define PASS_ARR(c_) (c_), sizeof(c_)
static bool ethash_io_write_file(char const *dirname,
char const* filename,
size_t filename_length,
void const* data,
size_t data_size)
char const* filename,
size_t filename_length,
void const* data,
size_t data_size)
{
bool ret = false;
char *fullname = ethash_io_create_filename(dirname, filename, filename_length);
if (!fullname) {
return false;
}
FILE *f = ethash_fopen(fullname, "wb");
if (!f) {
goto free_name;
}
if (data_size != fwrite(data, 1, data_size, f)) {
goto close;
}
bool ret = false;
char *fullname = ethash_io_create_filename(dirname, filename, filename_length);
if (!fullname) {
return false;
}
FILE *f = ethash_fopen(fullname, "wb");
if (!f) {
goto free_name;
}
if (data_size != fwrite(data, 1, data_size, f)) {
goto close;
}
ret = true;
ret = true;
close:
fclose(f);
fclose(f);
free_name:
free(fullname);
return ret;
free(fullname);
return ret;
}
bool ethash_io_write(char const *dirname,
ethash_params const* params,
ethash_h256_t seedhash,
void const* cache,
uint8_t **data,
uint64_t *data_size)
ethash_params const* params,
ethash_h256_t seedhash,
void const* cache,
uint8_t **data,
uint64_t *data_size)
{
char info_buffer[DAG_MEMO_BYTESIZE];
// allocate the bytes
uint8_t *temp_data_ptr = malloc((size_t)params->full_size);
if (!temp_data_ptr) {
goto end;
}
ethash_compute_full_data(temp_data_ptr, params, cache);
char info_buffer[DAG_MEMO_BYTESIZE];
// allocate the bytes
uint8_t *temp_data_ptr = malloc((size_t)params->full_size);
if (!temp_data_ptr) {
goto end;
}
ethash_compute_full_data(temp_data_ptr, params, cache);
if (!ethash_io_write_file(dirname, PASS_ARR(DAG_FILE_NAME), temp_data_ptr, (size_t)params->full_size)) {
goto fail_free;
}
if (!ethash_io_write_file(dirname, PASS_ARR(DAG_FILE_NAME), temp_data_ptr, (size_t)params->full_size)) {
goto fail_free;
}
ethash_io_serialize_info(REVISION, seedhash, info_buffer);
if (!ethash_io_write_file(dirname, PASS_ARR(DAG_MEMO_NAME), info_buffer, DAG_MEMO_BYTESIZE)) {
goto fail_free;
}
ethash_io_serialize_info(REVISION, seedhash, info_buffer);
if (!ethash_io_write_file(dirname, PASS_ARR(DAG_MEMO_NAME), info_buffer, DAG_MEMO_BYTESIZE)) {
goto fail_free;
}
*data = temp_data_ptr;
*data_size = params->full_size;
return true;
*data = temp_data_ptr;
*data_size = params->full_size;
return true;
fail_free:
free(temp_data_ptr);
free(temp_data_ptr);
end:
return false;
return false;
}
#undef PASS_ARR

54
io.h

@ -36,9 +36,9 @@ static const char DAG_MEMO_NAME[] = "full.info";
/// Possible return values of @see ethash_io_prepare
enum ethash_io_rc {
ETHASH_IO_FAIL = 0, ///< There has been an IO failure
ETHASH_IO_MEMO_MISMATCH, ///< Memo file either did not exist or there was content mismatch
ETHASH_IO_MEMO_MATCH, ///< Memo file existed and contents matched. No need to do anything
ETHASH_IO_FAIL = 0, ///< There has been an IO failure
ETHASH_IO_MEMO_MISMATCH, ///< Memo file either did not exist or there was content mismatch
ETHASH_IO_MEMO_MATCH, ///< Memo file existed and contents matched. No need to do anything
};
/**
@ -79,17 +79,17 @@ enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_h256_t seedhash)
* @return True for success and false in case of failure.
*/
bool ethash_io_write(char const *dirname,
ethash_params const* params,
ethash_h256_t seedhash,
void const* cache,
uint8_t **data,
uint64_t *data_size);
ethash_params const* params,
ethash_h256_t seedhash,
void const* cache,
uint8_t **data,
uint64_t *data_size);
/**
* An fopen wrapper for no-warnings crossplatform fopen.
*
* Msvc compiler considers fopen to be insecure and suggests to use their
* alternative. This is a wrapper for this alternative. Another way is to
* alternative. This is a wrapper for this alternative. Another way is to
* #define _CRT_SECURE_NO_WARNINGS, but disabling all security warnings does
* not sound like a good idea.
*
@ -102,7 +102,7 @@ FILE *ethash_fopen(const char *file_name, const char *mode);
* An stncat wrapper for no-warnings crossplatform strncat.
*
* Msvc compiler considers strncat to be insecure and suggests to use their
* alternative. This is a wrapper for this alternative. Another way is to
* alternative. This is a wrapper for this alternative. Another way is to
* #define _CRT_SECURE_NO_WARNINGS, but disabling all security warnings does
* not sound like a good idea.
*
@ -117,29 +117,29 @@ FILE *ethash_fopen(const char *file_name, const char *mode);
char *ethash_strncat(char *dest, size_t dest_size, const char *src, size_t count);
static inline void ethash_io_serialize_info(uint32_t revision,
ethash_h256_t seed_hash,
char *output)
ethash_h256_t seed_hash,
char *output)
{
// if .info is only consumed locally we don't really care about endianess
memcpy(output, &revision, 4);
memcpy(output + 4, &seed_hash, 32);
// if .info is only consumed locally we don't really care about endianess
memcpy(output, &revision, 4);
memcpy(output + 4, &seed_hash, 32);
}
static inline char *ethash_io_create_filename(char const *dirname,
char const* filename,
size_t filename_length)
char const* filename,
size_t filename_length)
{
size_t dirlen = strlen(dirname);
// in C the cast is not needed, but a C++ compiler will complain for invalid conversion
char *name = (char*)malloc(dirlen + filename_length + 1);
if (!name) {
return NULL;
}
size_t dirlen = strlen(dirname);
// in C the cast is not needed, but a C++ compiler will complain for invalid conversion
char *name = (char*)malloc(dirlen + filename_length + 1);
if (!name) {
return NULL;
}
name[0] = '\0';
ethash_strncat(name, dirlen + filename_length + 1, dirname, dirlen);
ethash_strncat(name, dirlen + filename_length + 1, filename, filename_length);
return name;
name[0] = '\0';
ethash_strncat(name, dirlen + filename_length + 1, dirname, dirlen);
ethash_strncat(name, dirlen + filename_length + 1, filename, filename_length);
return name;
}

74
io_posix.c

@ -29,58 +29,58 @@
FILE *ethash_fopen(const char *file_name, const char *mode)
{
return fopen(file_name, mode);
return fopen(file_name, mode);
}
char *ethash_strncat(char *dest, size_t dest_size, const char *src, size_t count)
{
return strlen(dest) + count + 1 <= dest_size ? strncat(dest, src, count) : NULL;
{
return strlen(dest) + count + 1 <= dest_size ? strncat(dest, src, count) : NULL;
}
enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_h256_t seedhash)
{
char read_buffer[DAG_MEMO_BYTESIZE];
char expect_buffer[DAG_MEMO_BYTESIZE];
enum ethash_io_rc ret = ETHASH_IO_FAIL;
char read_buffer[DAG_MEMO_BYTESIZE];
char expect_buffer[DAG_MEMO_BYTESIZE];
enum ethash_io_rc ret = ETHASH_IO_FAIL;
// assert directory exists, full owner permissions and read/search for others
int rc = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (rc == -1 && errno != EEXIST) {
goto end;
}
// assert directory exists, full owner permissions and read/search for others
int rc = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (rc == -1 && errno != EEXIST) {
goto end;
}
char *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME));
if (!memofile) {
goto end;
}
char *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME));
if (!memofile) {
goto end;
}
// try to open memo file
FILE *f = ethash_fopen(memofile, "rb");
if (!f) {
// file does not exist, so no checking happens. All is fine.
ret = ETHASH_IO_MEMO_MISMATCH;
goto free_memo;
}
// try to open memo file
FILE *f = ethash_fopen(memofile, "rb");
if (!f) {
// file does not exist, so no checking happens. All is fine.
ret = ETHASH_IO_MEMO_MISMATCH;
goto free_memo;
}
if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) {
goto close;
}
if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) {
goto close;
}
ethash_io_serialize_info(REVISION, seedhash, expect_buffer);
if (memcmp(read_buffer, expect_buffer, DAG_MEMO_BYTESIZE) != 0) {
// we have different memo contents so delete the memo file
if (unlink(memofile) != 0) {
goto close;
}
ret = ETHASH_IO_MEMO_MISMATCH;
}
ethash_io_serialize_info(REVISION, seedhash, expect_buffer);
if (memcmp(read_buffer, expect_buffer, DAG_MEMO_BYTESIZE) != 0) {
// we have different memo contents so delete the memo file
if (unlink(memofile) != 0) {
goto close;
}
ret = ETHASH_IO_MEMO_MISMATCH;
}
ret = ETHASH_IO_MEMO_MATCH;
ret = ETHASH_IO_MEMO_MATCH;
close:
fclose(f);
fclose(f);
free_memo:
free(memofile);
free(memofile);
end:
return ret;
return ret;
}

76
io_win32.c

@ -26,59 +26,59 @@
FILE *ethash_fopen(const char *file_name, const char *mode)
{
FILE *f;
return fopen_s(&f, file_name, mode) == 0 ? f : NULL;
FILE *f;
return fopen_s(&f, file_name, mode) == 0 ? f : NULL;
}
char *ethash_strncat(char *dest, size_t dest_size, const char *src, size_t count)
{
return strncat_s(dest, dest_size, src, count) == 0 ? dest : NULL;
{
return strncat_s(dest, dest_size, src, count) == 0 ? dest : NULL;
}
enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_h256_t seedhash)
{
char read_buffer[DAG_MEMO_BYTESIZE];
char expect_buffer[DAG_MEMO_BYTESIZE];
enum ethash_io_rc ret = ETHASH_IO_FAIL;
char read_buffer[DAG_MEMO_BYTESIZE];
char expect_buffer[DAG_MEMO_BYTESIZE];
enum ethash_io_rc ret = ETHASH_IO_FAIL;
// assert directory exists
int rc = _mkdir(dirname);
if (rc == -1 && errno != EEXIST) {
goto end;
}
// assert directory exists
int rc = _mkdir(dirname);
if (rc == -1 && errno != EEXIST) {
goto end;
}
char *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME));
if (!memofile) {
goto end;
}
char *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME));
if (!memofile) {
goto end;
}
// try to open memo file
FILE *f = ethash_fopen(memofile, "rb");
if (!f) {
// file does not exist, so no checking happens. All is fine.
ret = ETHASH_IO_MEMO_MISMATCH;
goto free_memo;
}
// try to open memo file
FILE *f = ethash_fopen(memofile, "rb");
if (!f) {
// file does not exist, so no checking happens. All is fine.
ret = ETHASH_IO_MEMO_MISMATCH;
goto free_memo;
}
if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) {
goto close;
}
if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) {
goto close;
}
ethash_io_serialize_info(REVISION, seedhash, expect_buffer);
if (memcmp(read_buffer, expect_buffer, DAG_MEMO_BYTESIZE) != 0) {
// we have different memo contents so delete the memo file
if (_unlink(memofile) != 0) {
goto close;
}
ret = ETHASH_IO_MEMO_MISMATCH;
}
ethash_io_serialize_info(REVISION, seedhash, expect_buffer);
if (memcmp(read_buffer, expect_buffer, DAG_MEMO_BYTESIZE) != 0) {
// we have different memo contents so delete the memo file
if (_unlink(memofile) != 0) {
goto close;
}
ret = ETHASH_IO_MEMO_MISMATCH;
}
ret = ETHASH_IO_MEMO_MATCH;
ret = ETHASH_IO_MEMO_MATCH;
close:
fclose(f);
fclose(f);
free_memo:
free(memofile);
free(memofile);
end:
return ret;
return ret;
}

194
sha3.c

@ -17,65 +17,65 @@
/*** Constants. ***/
static const uint8_t rho[24] = \
{ 1, 3, 6, 10, 15, 21,
28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43,
62, 18, 39, 61, 20, 44};
{ 1, 3, 6, 10, 15, 21,
28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43,
62, 18, 39, 61, 20, 44};
static const uint8_t pi[24] = \
{10, 7, 11, 17, 18, 3,
5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2,
20, 14, 22, 9, 6, 1};
{10, 7, 11, 17, 18, 3,
5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2,
20, 14, 22, 9, 6, 1};
static const uint64_t RC[24] = \
{1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
{1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
/*** Helper macros to unroll the permutation. ***/
#define rol(x, s) (((x) << s) | ((x) >> (64 - s)))
#define REPEAT6(e) e e e e e e
#define REPEAT24(e) REPEAT6(e e e e)
#define REPEAT5(e) e e e e e
#define FOR5(v, s, e) \
v = 0; \
REPEAT5(e; v += s;)
#define FOR5(v, s, e) \
v = 0; \
REPEAT5(e; v += s;)
/*** Keccak-f[1600] ***/
static inline void keccakf(void* state) {
uint64_t* a = (uint64_t*)state;
uint64_t b[5] = {0};
uint64_t t = 0;
uint8_t x, y;
uint64_t* a = (uint64_t*)state;
uint64_t b[5] = {0};
uint64_t t = 0;
uint8_t x, y;
for (int i = 0; i < 24; i++) {
// Theta
FOR5(x, 1,
b[x] = 0;
FOR5(y, 5,
b[x] ^= a[x + y]; ))
FOR5(x, 1,
FOR5(y, 5,
a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
// Rho and pi
t = a[1];
x = 0;
REPEAT24(b[0] = a[pi[x]];
a[pi[x]] = rol(t, rho[x]);
t = b[0];
x++; )
// Chi
FOR5(y,
5,
FOR5(x, 1,
b[x] = a[y + x];)
FOR5(x, 1,
a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
// Iota
a[0] ^= RC[i];
}
for (int i = 0; i < 24; i++) {
// Theta
FOR5(x, 1,
b[x] = 0;
FOR5(y, 5,
b[x] ^= a[x + y]; ))
FOR5(x, 1,
FOR5(y, 5,
a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
// Rho and pi
t = a[1];
x = 0;
REPEAT24(b[0] = a[pi[x]];
a[pi[x]] = rol(t, rho[x]);
t = b[0];
x++; )
// Chi
FOR5(y,
5,
FOR5(x, 1,
b[x] = a[y + x];)
FOR5(x, 1,
a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
// Iota
a[0] ^= RC[i];
}
}
/******** The FIPS202-defined functions. ********/
@ -83,20 +83,20 @@ static inline void keccakf(void* state) {
/*** Some helper macros. ***/
#define _(S) do { S } while (0)
#define FOR(i, ST, L, S) \
_(for (size_t i = 0; i < L; i += ST) { S; })
#define mkapply_ds(NAME, S) \
static inline void NAME(uint8_t* dst, \
const uint8_t* src, \
size_t len) { \
FOR(i, 1, len, S); \
}
#define mkapply_sd(NAME, S) \
static inline void NAME(const uint8_t* src, \
uint8_t* dst, \
size_t len) { \
FOR(i, 1, len, S); \
}
#define FOR(i, ST, L, S) \
_(for (size_t i = 0; i < L; i += ST) { S; })
#define mkapply_ds(NAME, S) \
static inline void NAME(uint8_t* dst, \
const uint8_t* src, \
size_t len) { \
FOR(i, 1, len, S); \
}
#define mkapply_sd(NAME, S) \
static inline void NAME(const uint8_t* src, \
uint8_t* dst, \
size_t len) { \
FOR(i, 1, len, S); \
}
mkapply_ds(xorin, dst[i] ^= src[i]) // xorin
mkapply_sd(setout, dst[i] = src[i]) // setout
@ -105,47 +105,47 @@ mkapply_sd(setout, dst[i] = src[i]) // setout
#define Plen 200
// Fold P*F over the full blocks of an input.
#define foldP(I, L, F) \
while (L >= rate) { \
F(a, I, rate); \
P(a); \
I += rate; \
L -= rate; \
}
#define foldP(I, L, F) \
while (L >= rate) { \
F(a, I, rate); \
P(a); \
I += rate; \
L -= rate; \
}
/** The sponge-based hash construction. **/
static inline int hash(uint8_t* out, size_t outlen,
const uint8_t* in, size_t inlen,
size_t rate, uint8_t delim) {
if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) {
return -1;
}
uint8_t a[Plen] = {0};
// Absorb input.
foldP(in, inlen, xorin);
// Xor in the DS and pad frame.
a[inlen] ^= delim;
a[rate - 1] ^= 0x80;
// Xor in the last block.
xorin(a, in, inlen);
// Apply P
P(a);
// Squeeze output.
foldP(out, outlen, setout);
setout(a, out, outlen);
memset(a, 0, 200);
return 0;
const uint8_t* in, size_t inlen,
size_t rate, uint8_t delim) {
if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) {
return -1;
}
uint8_t a[Plen] = {0};
// Absorb input.
foldP(in, inlen, xorin);
// Xor in the DS and pad frame.
a[inlen] ^= delim;
a[rate - 1] ^= 0x80;
// Xor in the last block.
xorin(a, in, inlen);
// Apply P
P(a);
// Squeeze output.
foldP(out, outlen, setout);
setout(a, out, outlen);
memset(a, 0, 200);
return 0;
}
#define defsha3(bits) \
int sha3_##bits(uint8_t* out, size_t outlen, \
const uint8_t* in, size_t inlen) { \
if (outlen > (bits/8)) { \
return -1; \
} \
return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \
}
#define defsha3(bits) \
int sha3_##bits(uint8_t* out, size_t outlen, \
const uint8_t* in, size_t inlen) { \
if (outlen > (bits/8)) { \
return -1; \
} \
return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \
}
/*** FIPS202 SHA3 FOFs ***/
defsha3(256)
defsha3(512)
defsha3(512)

6
sha3.h

@ -11,19 +11,19 @@ extern "C" {
struct ethash_h256;
#define decsha3(bits) \
int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t);
int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t);
decsha3(256)
decsha3(512)
static inline void SHA3_256(struct ethash_h256 const* ret, uint8_t const *data, const size_t size)
{
sha3_256((uint8_t*)ret, 32, data, size);
sha3_256((uint8_t*)ret, 32, data, size);
}
static inline void SHA3_512(uint8_t *ret, uint8_t const *data, const size_t size)
{
sha3_512(ret, 64, data, size);
sha3_512(ret, 64, data, size);
}
#ifdef __cplusplus

10
sha3_cryptopp.cpp

@ -25,11 +25,13 @@
extern "C" {
struct ethash_h256;
typedef struct ethash_h256 ethash_h256_t;
void SHA3_256(ethash_h256_t const* ret, const uint8_t *data, size_t size) {
CryptoPP::SHA3_256().CalculateDigest((uint8_t*)ret, data, size);
void SHA3_256(ethash_h256_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);
void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size)
{
CryptoPP::SHA3_512().CalculateDigest(ret, data, size);
}
}

2
util.c

@ -30,7 +30,7 @@ __declspec(dllimport) void __stdcall OutputDebugStringA(const char* lpOutputStri
void debugf(const char *str, ...)
{
va_list args;
va_start(args, str);
va_start(args, str);
char buf[1<<16];
_vsnprintf_s(buf, sizeof(buf), sizeof(buf), str, args);

Loading…
Cancel
Save