Multithread POW
This commit is contained in:
parent
997ee55f85
commit
4c5fc4d3eb
110
src/pow.cc
110
src/pow.cc
|
@ -6,37 +6,62 @@
|
||||||
#define __STDC_LIMIT_MACROS
|
#define __STDC_LIMIT_MACROS
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
#define HASH_SIZE 64
|
#define HASH_SIZE 64
|
||||||
#define NTOHLL(x) ( ( (uint64_t)(ntohl( (unsigned int)((x << 32) >> 32) )) << 32) | ntohl( ((unsigned int)(x >> 32)) ) )
|
#define NTOHLL(x) \
|
||||||
|
( \
|
||||||
|
((uint64_t)(ntohl( (unsigned int)((x << 32) >> 32) )) << 32) | \
|
||||||
|
ntohl( ((unsigned int)(x >> 32)) ) \
|
||||||
|
)
|
||||||
|
#define SET_RESULT(res, nonce) \
|
||||||
|
{ \
|
||||||
|
pthread_mutex_lock(&g_mutex); \
|
||||||
|
if (g_result == RESULT_NOT_READY) { \
|
||||||
|
g_result = res; \
|
||||||
|
g_nonce = nonce; \
|
||||||
|
} \
|
||||||
|
pthread_mutex_unlock(&g_mutex); \
|
||||||
|
}
|
||||||
|
|
||||||
int pow(size_t pool_size,
|
typedef enum {
|
||||||
uint64_t target,
|
RESULT_NOT_READY,
|
||||||
const uint8_t* initial_hash,
|
RESULT_OK,
|
||||||
uint64_t max_nonce,
|
RESULT_OVERFLOW,
|
||||||
uint64_t* nonce) {
|
RESULT_ERROR
|
||||||
|
} Result;
|
||||||
|
|
||||||
|
// Global arguments.
|
||||||
|
size_t g_pool_size;
|
||||||
|
uint64_t g_target;
|
||||||
|
uint8_t* g_initial_hash;
|
||||||
|
uint64_t g_max_nonce;
|
||||||
|
|
||||||
|
// Shared variables for threads.
|
||||||
|
pthread_mutex_t g_mutex;
|
||||||
|
Result g_result = RESULT_NOT_READY;
|
||||||
|
uint64_t g_nonce;
|
||||||
|
|
||||||
|
void* pow_thread(void* num) {
|
||||||
|
uint64_t i = *((size_t *)num);
|
||||||
uint8_t message[HASH_SIZE+sizeof(uint64_t)];
|
uint8_t message[HASH_SIZE+sizeof(uint64_t)];
|
||||||
uint8_t digest[HASH_SIZE];
|
uint8_t digest[HASH_SIZE];
|
||||||
uint64_t* be_nonce;
|
uint64_t* be_nonce;
|
||||||
uint64_t* be_trial;
|
uint64_t* be_trial;
|
||||||
uint64_t i;
|
|
||||||
SHA512_CTX sha;
|
SHA512_CTX sha;
|
||||||
|
|
||||||
if (!max_nonce) {
|
memcpy(message+sizeof(uint64_t), g_initial_hash, HASH_SIZE);
|
||||||
max_nonce = UINT64_MAX;
|
|
||||||
}
|
|
||||||
memcpy(message+sizeof(uint64_t), initial_hash, HASH_SIZE);
|
|
||||||
be_nonce = (uint64_t *)message;
|
be_nonce = (uint64_t *)message;
|
||||||
be_trial = (uint64_t *)digest;
|
be_trial = (uint64_t *)digest;
|
||||||
i = 0;
|
|
||||||
|
|
||||||
while (1) {
|
while (g_result == RESULT_NOT_READY) {
|
||||||
// This is very unlikely to be ever happen but it's better to be
|
// This is very unlikely to be ever happen but it's better to be
|
||||||
// sure anyway.
|
// sure anyway.
|
||||||
if (i > max_nonce) {
|
if (i > g_max_nonce) {
|
||||||
return -1;
|
SET_RESULT(RESULT_OVERFLOW, 0);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
*be_nonce = NTOHLL(i);
|
*be_nonce = NTOHLL(i);
|
||||||
SHA512_Init(&sha);
|
SHA512_Init(&sha);
|
||||||
|
@ -45,12 +70,57 @@ int pow(size_t pool_size,
|
||||||
SHA512_Init(&sha);
|
SHA512_Init(&sha);
|
||||||
SHA512_Update(&sha, digest, HASH_SIZE);
|
SHA512_Update(&sha, digest, HASH_SIZE);
|
||||||
SHA512_Final(digest, &sha);
|
SHA512_Final(digest, &sha);
|
||||||
if (NTOHLL(*be_trial) <= target) {
|
if (NTOHLL(*be_trial) <= g_target) {
|
||||||
break;
|
SET_RESULT(RESULT_OK, i);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
i++;
|
i += g_pool_size;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*nonce = i;
|
int pow(size_t pool_size,
|
||||||
return 0;
|
uint64_t target,
|
||||||
|
const uint8_t* initial_hash,
|
||||||
|
uint64_t max_nonce,
|
||||||
|
uint64_t* nonce) {
|
||||||
|
g_pool_size = pool_size;
|
||||||
|
g_target = target;
|
||||||
|
g_initial_hash = (uint8_t *)initial_hash;
|
||||||
|
g_max_nonce = max_nonce ? max_nonce : UINT64_MAX;
|
||||||
|
|
||||||
|
pthread_mutex_init(&g_mutex, NULL);
|
||||||
|
pthread_t threads[pool_size];
|
||||||
|
size_t args[pool_size];
|
||||||
|
size_t i;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
for (i = 0; i < pool_size; i++) {
|
||||||
|
args[i] = i;
|
||||||
|
error = pthread_create(&threads[i], NULL, pow_thread, &args[i]);
|
||||||
|
if (error) {
|
||||||
|
SET_RESULT(RESULT_ERROR, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for only spawned threads.
|
||||||
|
while (i--) {
|
||||||
|
pthread_join(threads[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (g_result) {
|
||||||
|
case RESULT_OK:
|
||||||
|
*nonce = g_nonce;
|
||||||
|
error = 0;
|
||||||
|
break;
|
||||||
|
case RESULT_OVERFLOW:
|
||||||
|
error = -1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&g_mutex);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,12 @@ class PowWorker : public NanAsyncWorker {
|
||||||
void HandleOKCallback () {
|
void HandleOKCallback () {
|
||||||
NanScope();
|
NanScope();
|
||||||
if (error) {
|
if (error) {
|
||||||
Local<Value> argv[] = {NanError("Max safe integer overflow")};
|
Local<Value> argv[1];
|
||||||
|
if (error == -1) {
|
||||||
|
argv[0] = NanError("Max safe integer overflow");
|
||||||
|
} else {
|
||||||
|
argv[0] = NanError("Internal error");
|
||||||
|
}
|
||||||
callback->Call(1, argv);
|
callback->Call(1, argv);
|
||||||
} else {
|
} else {
|
||||||
Local<Value> argv[] = {NanNull(), NanNew<Integer>(nonce)};
|
Local<Value> argv[] = {NanNull(), NanNew<Integer>(nonce)};
|
||||||
|
@ -70,7 +75,7 @@ NAN_METHOD(PowAsync) {
|
||||||
uint8_t* initial_hash = (uint8_t *)malloc(length);
|
uint8_t* initial_hash = (uint8_t *)malloc(length);
|
||||||
|
|
||||||
if (initial_hash == NULL) {
|
if (initial_hash == NULL) {
|
||||||
Local<Value> argv[] = {NanError("Cannot allocate memory")};
|
Local<Value> argv[] = {NanError("Internal error")};
|
||||||
callback->Call(1, argv);
|
callback->Call(1, argv);
|
||||||
} else {
|
} else {
|
||||||
memcpy(initial_hash, buf, length);
|
memcpy(initial_hash, buf, length);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user