Better input validation
This commit is contained in:
parent
12066842cc
commit
e3765b81fc
|
@ -56,14 +56,14 @@ exports.pow = function(opts) {
|
||||||
|
|
||||||
// Check all input params prematurely to not let promise executor or
|
// Check all input params prematurely to not let promise executor or
|
||||||
// worker to fail because of it.
|
// worker to fail because of it.
|
||||||
// 1 - UINT32_MAX
|
assert(typeof poolSize === "number", "Bad pool size");
|
||||||
assert(poolSize > 0, "Pool size is too low");
|
assert(poolSize >= 1, "Pool size is too low");
|
||||||
assert(poolSize <= 4294967295, "Pool size is too high");
|
assert(poolSize <= 1024, "Pool size is too high");
|
||||||
// 0 - (2^53 - 1)
|
|
||||||
assert(typeof opts.target === "number", "Bad target");
|
assert(typeof opts.target === "number", "Bad target");
|
||||||
assert(opts.target >= 0, "Target is too low");
|
assert(opts.target >= 0, "Target is too low");
|
||||||
assert(opts.target <= 9007199254740991, "Target is too high");
|
assert(opts.target <= 9007199254740991, "Target is too high");
|
||||||
assert(Buffer.isBuffer(opts.initialHash), "Bad initial hash");
|
assert(Buffer.isBuffer(opts.initialHash), "Bad initial hash");
|
||||||
|
assert(opts.initialHash.length === 64, "Bad initial hash");
|
||||||
|
|
||||||
// TODO(Kagami): Allow to cancel a POW (see `platform.browser.js`).
|
// TODO(Kagami): Allow to cancel a POW (see `platform.browser.js`).
|
||||||
return new promise(function(resolve, reject) {
|
return new promise(function(resolve, reject) {
|
||||||
|
|
35
src/pow.cc
35
src/pow.cc
|
@ -9,15 +9,15 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
#include "./pow.h"
|
||||||
|
|
||||||
#define HASH_SIZE 64
|
enum PowResult {
|
||||||
|
RESULT_OK = 0,
|
||||||
typedef enum {
|
RESULT_OVERFLOW = -1,
|
||||||
RESULT_NOT_READY,
|
RESULT_ERROR = -2,
|
||||||
RESULT_OK,
|
RESULT_BAD_INPUT = -3,
|
||||||
RESULT_OVERFLOW,
|
RESULT_NOT_READY = -4
|
||||||
RESULT_ERROR
|
};
|
||||||
} Result;
|
|
||||||
|
|
||||||
// Global arguments.
|
// Global arguments.
|
||||||
size_t g_pool_size;
|
size_t g_pool_size;
|
||||||
|
@ -27,7 +27,7 @@ uint64_t g_max_nonce;
|
||||||
|
|
||||||
// Shared variables for threads.
|
// Shared variables for threads.
|
||||||
pthread_mutex_t g_mutex;
|
pthread_mutex_t g_mutex;
|
||||||
Result g_result = RESULT_NOT_READY;
|
PowResult g_result = RESULT_NOT_READY;
|
||||||
uint64_t g_nonce;
|
uint64_t g_nonce;
|
||||||
|
|
||||||
inline uint64_t ntohll(uint64_t x) {
|
inline uint64_t ntohll(uint64_t x) {
|
||||||
|
@ -38,7 +38,7 @@ inline uint64_t ntohll(uint64_t x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set POW computation result in a thread-safe way.
|
// Set POW computation result in a thread-safe way.
|
||||||
void set_result(Result res, uint64_t nonce) {
|
void set_result(PowResult res, uint64_t nonce) {
|
||||||
pthread_mutex_lock(&g_mutex);
|
pthread_mutex_lock(&g_mutex);
|
||||||
if (g_result == RESULT_NOT_READY) {
|
if (g_result == RESULT_NOT_READY) {
|
||||||
g_result = res;
|
g_result = res;
|
||||||
|
@ -87,6 +87,9 @@ int pow(size_t pool_size,
|
||||||
const uint8_t* initial_hash,
|
const uint8_t* initial_hash,
|
||||||
uint64_t max_nonce,
|
uint64_t max_nonce,
|
||||||
uint64_t* nonce) {
|
uint64_t* nonce) {
|
||||||
|
if (pool_size < 1 || pool_size > MAX_POOL_SIZE) {
|
||||||
|
return RESULT_BAD_INPUT;
|
||||||
|
}
|
||||||
g_pool_size = pool_size;
|
g_pool_size = pool_size;
|
||||||
g_target = target;
|
g_target = target;
|
||||||
g_initial_hash = (uint8_t *)initial_hash;
|
g_initial_hash = (uint8_t *)initial_hash;
|
||||||
|
@ -112,18 +115,10 @@ int pow(size_t pool_size,
|
||||||
pthread_join(threads[i], NULL);
|
pthread_join(threads[i], NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (g_result) {
|
if (g_result == RESULT_OK) {
|
||||||
case RESULT_OK:
|
|
||||||
*nonce = g_nonce;
|
*nonce = g_nonce;
|
||||||
error = 0;
|
|
||||||
break;
|
|
||||||
case RESULT_OVERFLOW:
|
|
||||||
error = -1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error = -2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_destroy(&g_mutex);
|
pthread_mutex_destroy(&g_mutex);
|
||||||
return error;
|
return g_result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#ifndef BITMESSAGE_POW_H
|
#ifndef BITMESSAGE_POW_H
|
||||||
#define BITMESSAGE_POW_H
|
#define BITMESSAGE_POW_H
|
||||||
|
|
||||||
|
#define MAX_POOL_SIZE 1024
|
||||||
|
#define HASH_SIZE 64
|
||||||
|
|
||||||
int pow(size_t pool_size,
|
int pow(size_t pool_size,
|
||||||
uint64_t target,
|
uint64_t target,
|
||||||
const uint8_t* initial_hash,
|
const uint8_t* initial_hash,
|
||||||
|
|
|
@ -68,22 +68,32 @@ class PowWorker : public NanAsyncWorker {
|
||||||
NAN_METHOD(PowAsync) {
|
NAN_METHOD(PowAsync) {
|
||||||
NanScope();
|
NanScope();
|
||||||
|
|
||||||
NanCallback *callback = new NanCallback(args[3].As<Function>());
|
if (args.Length() != 4 ||
|
||||||
|
!args[0]->IsNumber() || // pool_size
|
||||||
|
!args[1]->IsNumber() || // target
|
||||||
|
!args[2]->IsObject() || // initial_hash
|
||||||
|
!args[3]->IsFunction()) { // cb
|
||||||
|
NanThrowError("Bad input");
|
||||||
|
NanReturnUndefined();
|
||||||
|
}
|
||||||
|
|
||||||
size_t pool_size = args[0]->Uint32Value();
|
size_t pool_size = args[0]->Uint32Value();
|
||||||
uint64_t target = args[1]->IntegerValue();
|
uint64_t target = args[1]->IntegerValue();
|
||||||
size_t length = Buffer::Length(args[2]->ToObject());
|
size_t length = Buffer::Length(args[2]->ToObject());
|
||||||
char* buf = Buffer::Data(args[2]->ToObject());
|
if (pool_size < 1 || pool_size > MAX_POOL_SIZE || length != HASH_SIZE) {
|
||||||
|
NanThrowError("Bad input");
|
||||||
|
NanReturnUndefined();
|
||||||
|
}
|
||||||
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("Internal error")};
|
NanThrowError("Internal error");
|
||||||
callback->Call(1, argv);
|
NanReturnUndefined();
|
||||||
} else {
|
|
||||||
memcpy(initial_hash, buf, length);
|
|
||||||
NanAsyncQueueWorker(
|
|
||||||
new PowWorker(callback, pool_size, target, initial_hash));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* buf = Buffer::Data(args[2]->ToObject());
|
||||||
|
memcpy(initial_hash, buf, length);
|
||||||
|
NanCallback* callback = new NanCallback(args[3].As<Function>());
|
||||||
|
NanAsyncQueueWorker(new PowWorker(callback, pool_size, target, initial_hash));
|
||||||
NanReturnUndefined();
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user