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
|
||||
// worker to fail because of it.
|
||||
// 1 - UINT32_MAX
|
||||
assert(poolSize > 0, "Pool size is too low");
|
||||
assert(poolSize <= 4294967295, "Pool size is too high");
|
||||
// 0 - (2^53 - 1)
|
||||
assert(typeof poolSize === "number", "Bad pool size");
|
||||
assert(poolSize >= 1, "Pool size is too low");
|
||||
assert(poolSize <= 1024, "Pool size is too high");
|
||||
assert(typeof opts.target === "number", "Bad target");
|
||||
assert(opts.target >= 0, "Target is too low");
|
||||
assert(opts.target <= 9007199254740991, "Target is too high");
|
||||
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`).
|
||||
return new promise(function(resolve, reject) {
|
||||
|
|
37
src/pow.cc
37
src/pow.cc
|
@ -9,15 +9,15 @@
|
|||
#include <pthread.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <openssl/sha.h>
|
||||
#include "./pow.h"
|
||||
|
||||
#define HASH_SIZE 64
|
||||
|
||||
typedef enum {
|
||||
RESULT_NOT_READY,
|
||||
RESULT_OK,
|
||||
RESULT_OVERFLOW,
|
||||
RESULT_ERROR
|
||||
} Result;
|
||||
enum PowResult {
|
||||
RESULT_OK = 0,
|
||||
RESULT_OVERFLOW = -1,
|
||||
RESULT_ERROR = -2,
|
||||
RESULT_BAD_INPUT = -3,
|
||||
RESULT_NOT_READY = -4
|
||||
};
|
||||
|
||||
// Global arguments.
|
||||
size_t g_pool_size;
|
||||
|
@ -27,7 +27,7 @@ uint64_t g_max_nonce;
|
|||
|
||||
// Shared variables for threads.
|
||||
pthread_mutex_t g_mutex;
|
||||
Result g_result = RESULT_NOT_READY;
|
||||
PowResult g_result = RESULT_NOT_READY;
|
||||
uint64_t g_nonce;
|
||||
|
||||
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.
|
||||
void set_result(Result res, uint64_t nonce) {
|
||||
void set_result(PowResult res, uint64_t nonce) {
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
if (g_result == RESULT_NOT_READY) {
|
||||
g_result = res;
|
||||
|
@ -87,6 +87,9 @@ int pow(size_t pool_size,
|
|||
const uint8_t* initial_hash,
|
||||
uint64_t max_nonce,
|
||||
uint64_t* nonce) {
|
||||
if (pool_size < 1 || pool_size > MAX_POOL_SIZE) {
|
||||
return RESULT_BAD_INPUT;
|
||||
}
|
||||
g_pool_size = pool_size;
|
||||
g_target = target;
|
||||
g_initial_hash = (uint8_t *)initial_hash;
|
||||
|
@ -112,18 +115,10 @@ int pow(size_t pool_size,
|
|||
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;
|
||||
if (g_result == RESULT_OK) {
|
||||
*nonce = g_nonce;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&g_mutex);
|
||||
return error;
|
||||
return g_result;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef BITMESSAGE_POW_H
|
||||
#define BITMESSAGE_POW_H
|
||||
|
||||
#define MAX_POOL_SIZE 1024
|
||||
#define HASH_SIZE 64
|
||||
|
||||
int pow(size_t pool_size,
|
||||
uint64_t target,
|
||||
const uint8_t* initial_hash,
|
||||
|
|
|
@ -68,22 +68,32 @@ class PowWorker : public NanAsyncWorker {
|
|||
NAN_METHOD(PowAsync) {
|
||||
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();
|
||||
uint64_t target = args[1]->IntegerValue();
|
||||
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);
|
||||
|
||||
if (initial_hash == NULL) {
|
||||
Local<Value> argv[] = {NanError("Internal error")};
|
||||
callback->Call(1, argv);
|
||||
} else {
|
||||
memcpy(initial_hash, buf, length);
|
||||
NanAsyncQueueWorker(
|
||||
new PowWorker(callback, pool_size, target, initial_hash));
|
||||
NanThrowError("Internal error");
|
||||
NanReturnUndefined();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user