Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

misc fixes from cpp-ethereum repo. #110

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ethash.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (l *Light) Verify(block Block) bool {
// to prevent DOS attacks.
blockNum := block.NumberU64()
if blockNum >= epochLength*2048 {
log.Debug(fmt.Sprintf("block number %d too high, limit is %d", epochLength*2048))
log.Debug(fmt.Sprintf("block number %d too high, limit is %d", blockNum, epochLength*2048))
return false
}

Expand Down
96 changes: 81 additions & 15 deletions src/libethash/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ uint64_t ethash_get_cachesize(uint64_t const 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)
bool static ethash_compute_cache_nodes(
static bool ethash_compute_cache_nodes(
node* const nodes,
uint64_t cache_size,
ethash_h256_t const* seed
Expand Down Expand Up @@ -108,6 +108,9 @@ void ethash_calculate_dag_item(
__m128i xmm1 = ret->xmm[1];
__m128i xmm2 = ret->xmm[2];
__m128i xmm3 = ret->xmm[3];
#elif defined(__MIC__)
__m512i const fnv_prime = _mm512_set1_epi32(FNV_PRIME);
__m512i zmm0 = ret->zmm[0];
#endif

for (uint32_t i = 0; i != ETHASH_DATASET_PARENTS; ++i) {
Expand All @@ -131,6 +134,14 @@ void ethash_calculate_dag_item(
ret->xmm[2] = xmm2;
ret->xmm[3] = xmm3;
}
#elif defined(__MIC__)
{
zmm0 = _mm512_mullo_epi32(zmm0, fnv_prime);

// have to write to ret as values are used to compute index
zmm0 = _mm512_xor_si512(zmm0, parent->zmm[0]);
ret->zmm[0] = zmm0;
}
#else
{
for (unsigned w = 0; w != NODE_WORDS; ++w) {
Expand Down Expand Up @@ -207,10 +218,10 @@ static bool ethash_hash(

for (unsigned n = 0; n != MIX_NODES; ++n) {
node const* dag_node;
node tmp_node;
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, light);
dag_node = &tmp_node;
}
Expand All @@ -227,6 +238,14 @@ static bool ethash_hash(
mix[n].xmm[2] = _mm_xor_si128(xmm2, dag_node->xmm[2]);
mix[n].xmm[3] = _mm_xor_si128(xmm3, dag_node->xmm[3]);
}
#elif defined(__MIC__)
{
// __m512i implementation via union
// Each vector register (zmm) can store sixteen 32-bit integer numbers
__m512i fnv_prime = _mm512_set1_epi32(FNV_PRIME);
__m512i zmm0 = _mm512_mullo_epi32(fnv_prime, mix[n].zmm[0]);
mix[n].zmm[0] = _mm512_xor_si512(zmm0, dag_node->zmm[0]);
}
#else
{
for (unsigned w = 0; w != NODE_WORDS; ++w) {
Expand All @@ -238,6 +257,22 @@ static bool ethash_hash(

}

// Workaround for a GCC regression which causes a bogus -Warray-bounds warning.
// The regression was introduced in GCC 4.8.4, fixed in GCC 5.0.0 and backported to GCC 4.9.3 but
// never to the GCC 4.8.x line.
//
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
//
// This regression is affecting Debian Jesse (8.5) builds of cpp-ethereum (GCC 4.9.2) and also
// manifests in the doublethinkco armel v5 cross-builds, which use crosstool-ng and resulting
// in the use of GCC 4.8.4. The Tizen runtime wants an even older GLIBC version - the one from
// GCC 4.6.0!

#if defined(__GNUC__) && (__GNUC__ < 5)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif // define (__GNUC__)

// compress mix
for (uint32_t w = 0; w != MIX_WORDS; w += 4) {
uint32_t reduction = mix->words[w + 0];
Expand All @@ -247,6 +282,10 @@ static bool ethash_hash(
mix->words[w / 4] = reduction;
}

#if defined(__GNUC__) && (__GNUC__ < 5)
#pragma GCC diagnostic pop
#endif // define (__GNUC__)

fix_endian_arr32(mix->words, MIX_WORDS / 4);
memcpy(&ret->mix_hash, mix->bytes, 32);
// final Keccak hash
Expand Down Expand Up @@ -300,7 +339,11 @@ ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t cons
if (!ret) {
return NULL;
}
#if defined(__MIC__)
ret->cache = _mm_malloc((size_t)cache_size, 64);
#else
ret->cache = malloc((size_t)cache_size);
#endif
if (!ret->cache) {
goto fail_free_light;
}
Expand All @@ -312,7 +355,11 @@ ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t cons
return ret;

fail_free_cache_mem:
#if defined(__MIC__)
_mm_free(ret->cache);
#else
free(ret->cache);
#endif
fail_free_light:
free(ret);
return NULL;
Expand Down Expand Up @@ -399,31 +446,47 @@ ethash_full_t ethash_full_new_internal(
return NULL;
}
ret->file_size = (size_t)full_size;
switch (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, false)) {
case ETHASH_IO_FAIL:
// ethash_io_prepare will do all ETHASH_CRITICAL() logging in fail case

enum ethash_io_rc err = ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, false);
if (err == ETHASH_IO_FAIL)
goto fail_free_full;
case ETHASH_IO_MEMO_MATCH:
if (!ethash_mmap(ret, f)) {
ETHASH_CRITICAL("mmap failure()");
goto fail_close_file;
}
return ret;
case ETHASH_IO_MEMO_SIZE_MISMATCH:

if (err == ETHASH_IO_MEMO_SIZE_MISMATCH) {
// if a DAG of same filename but unexpected size is found, silently force new file creation
if (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, true) != ETHASH_IO_MEMO_MISMATCH) {
ETHASH_CRITICAL("Could not recreate DAG file after finding existing DAG with unexpected size.");
goto fail_free_full;
}
// fallthrough to the mismatch case here, DO NOT go through match
case ETHASH_IO_MEMO_MISMATCH:
// we now need to go through the mismatch case, NOT the match case
err = ETHASH_IO_MEMO_MISMATCH;
}

if (err == ETHASH_IO_MEMO_MISMATCH || err == ETHASH_IO_MEMO_MATCH) {
if (!ethash_mmap(ret, f)) {
ETHASH_CRITICAL("mmap failure()");
goto fail_close_file;
}
break;

if (err == ETHASH_IO_MEMO_MATCH) {
#if defined(__MIC__)
node* tmp_nodes = _mm_malloc((size_t)full_size, 64);
//copy all nodes from ret->data
//mmapped_nodes are not aligned properly
uint32_t const countnodes = (uint32_t) ((size_t)ret->file_size / sizeof(node));
//fprintf(stderr,"ethash_full_new_internal:countnodes:%d",countnodes);
for (uint32_t i = 1; i != countnodes; ++i) {
tmp_nodes[i] = ret->data[i];
}
ret->data = tmp_nodes;
#endif
return ret;
}
}


#if defined(__MIC__)
ret->data = _mm_malloc((size_t)full_size, 64);
#endif
if (!ethash_compute_full_data(ret->data, full_size, light, callback)) {
ETHASH_CRITICAL("Failure at computing DAG data.");
goto fail_free_full_data;
Expand All @@ -448,6 +511,9 @@ ethash_full_t ethash_full_new_internal(
fail_free_full_data:
// could check that munmap(..) == 0 but even if it did not can't really do anything here
munmap(ret->data, (size_t)full_size);
#if defined(__MIC__)
_mm_free(ret->data);
#endif
fail_close_file:
fclose(ret->file);
fail_free_full:
Expand Down
4 changes: 4 additions & 0 deletions src/libethash/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#if defined(_M_X64) && ENABLE_SSE
#include <smmintrin.h>
#elif defined(__MIC__)
#include <immintrin.h>
#endif

#ifdef __cplusplus
Expand All @@ -27,6 +29,8 @@ typedef union node {

#if defined(_M_X64) && ENABLE_SSE
__m128i xmm[NODE_WORDS/4];
#elif defined(__MIC__)
__m512i zmm[NODE_WORDS/16];
#endif

} node;
Expand Down
2 changes: 1 addition & 1 deletion src/libethash/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ enum ethash_io_rc ethash_io_prepare(
goto free_memo;
}
// make sure it's of the proper size
if (fseek(f, (long int)(file_size + ETHASH_DAG_MAGIC_NUM_SIZE - 1), SEEK_SET) != 0) {
if (ethash_fseek(f, file_size + ETHASH_DAG_MAGIC_NUM_SIZE - 1, SEEK_SET) != 0) {
fclose(f);
ETHASH_CRITICAL("Could not seek to the end of DAG file: \"%s\". Insufficient space?", tmpfile);
goto free_memo;
Expand Down
10 changes: 10 additions & 0 deletions src/libethash/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ enum ethash_io_rc ethash_io_prepare(
*/
FILE* ethash_fopen(char const* file_name, char const* mode);

/**
* An fseek wrapper for crossplatform 64-bit seek.
*
* @param f The file stream whose fd to get
* @param offset Number of bytes from @a origin
* @param origin Initial position
* @return Current offset or -1 to indicate an error
*/
int ethash_fseek(FILE* f, size_t offset, int origin);

/**
* An strncat wrapper for no-warnings crossplatform strncat.
*
Expand Down
7 changes: 7 additions & 0 deletions src/libethash/io_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ FILE* ethash_fopen(char const* file_name, char const* mode)
return fopen(file_name, mode);
}

int ethash_fseek(FILE* f, size_t offset, int origin)
{
return fseeko(f, offset, origin);
}

char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count)
{
return strlen(dest) + count + 1 <= dest_size ? strncat(dest, src, count) : NULL;
Expand Down Expand Up @@ -96,6 +101,8 @@ bool ethash_get_default_dirname(char* strbuf, size_t buffsize)
struct passwd* pwd = getpwuid(getuid());
if (pwd)
home_dir = pwd->pw_dir;
if (!home_dir)
return false;
}

size_t len = strlen(home_dir);
Expand Down
6 changes: 6 additions & 0 deletions src/libethash/io_win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,19 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <shlobj.h>
#include <io.h>

FILE* ethash_fopen(char const* file_name, char const* mode)
{
FILE* f;
return fopen_s(&f, file_name, mode) == 0 ? f : NULL;
}

int ethash_fseek(FILE* f, size_t offset, int origin)
{
return _fseeki64(f, offset, origin);
}

char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count)
{
return strncat_s(dest, dest_size, src, count) == 0 ? dest : NULL;
Expand Down