diff --git a/cpu-miner.c b/cpu-miner.c index 8c755fe..3796fdd 100644 --- a/cpu-miner.c +++ b/cpu-miner.c @@ -180,10 +180,8 @@ static struct option const options[] = { }; struct work { - unsigned char data[128]; - unsigned char target[32]; - - unsigned char hash[32]; + uint32_t data[32]; + uint32_t target[8]; }; static struct work g_work; @@ -214,6 +212,8 @@ static bool jobj_binary(const json_t *obj, const char *key, static bool work_decode(const json_t *val, struct work *work) { + int i; + if (unlikely(!jobj_binary(val, "data", work->data, sizeof(work->data)))) { applog(LOG_ERR, "JSON inval data"); goto err_out; @@ -223,7 +223,10 @@ static bool work_decode(const json_t *val, struct work *work) goto err_out; } - memset(work->hash, 0, sizeof(work->hash)); + for (i = 0; i < ARRAY_SIZE(work->data); i++) + work->data[i] = be32dec(work->data + i); + for (i = 0; i < ARRAY_SIZE(work->target); i++) + work->target[i] = le32dec(work->target + i); return true; @@ -231,7 +234,7 @@ err_out: return false; } -static bool submit_upstream_work(CURL *curl, const struct work *work) +static bool submit_upstream_work(CURL *curl, struct work *work) { char *hexstr = NULL; json_t *val, *res; @@ -241,11 +244,16 @@ static bool submit_upstream_work(CURL *curl, const struct work *work) bool rc = false; /* pass if the previous hash is not the current previous hash */ - if (!submit_old && memcmp(work->data + 4, g_work.data + 4, 32)) + if (!submit_old && memcmp(work->data + 1, g_work.data + 1, 32)) { + if (opt_debug) + applog(LOG_DEBUG, "DEBUG: stale work detected, discarding"); return true; + } /* build hex string */ - hexstr = bin2hex(work->data, sizeof(work->data)); + for (i = 0; i < ARRAY_SIZE(work->data); i++) + be32enc(work->data + i, work->data[i]); + hexstr = bin2hex((unsigned char *)work->data, sizeof(work->data)); if (unlikely(!hexstr)) { applog(LOG_ERR, "submit_upstream_work OOM"); goto out; @@ -483,8 +491,9 @@ static void *miner_thread(void *userdata) { struct thr_info *mythr = userdata; int thr_id = mythr->id; + struct work work; uint32_t max_nonce; - uint32_t next_nonce; + uint32_t end_nonce = 0xffffffffU / opt_n_threads * (thr_id + 1) - 4; unsigned char *scratchbuf = NULL; /* Set worker threads to nice 19 and then preferentially to SCHED_IDLE @@ -504,7 +513,6 @@ static void *miner_thread(void *userdata) } while (1) { - struct work work __attribute__((aligned(128))); unsigned long hashes_done; struct timeval tv_start, tv_end, diff; int64_t max64; @@ -512,7 +520,8 @@ static void *miner_thread(void *userdata) /* obtain new work from internal workio thread */ pthread_mutex_lock(&g_work_lock); - if (!have_longpoll || time(NULL) >= g_work_time + LP_SCANTIME*3/4) { + if (!have_longpoll || time(NULL) >= g_work_time + LP_SCANTIME*3/4 + || work.data[19] >= end_nonce) { if (unlikely(!get_work(mythr, &g_work))) { applog(LOG_ERR, "work retrieval failed, exiting " "mining thread %d", mythr->id); @@ -525,8 +534,9 @@ static void *miner_thread(void *userdata) } if (memcmp(work.data, g_work.data, 76)) { memcpy(&work, &g_work, sizeof(struct work)); - next_nonce = 0xffffffffU / opt_n_threads * thr_id; - } + work.data[19] = 0xffffffffU / opt_n_threads * thr_id; + } else + work.data[19]++; pthread_mutex_unlock(&g_work_lock); work_restart[thr_id].restart = 0; @@ -536,10 +546,10 @@ static void *miner_thread(void *userdata) max64 *= thr_hashrates[thr_id]; if (max64 <= 0) max64 = 0xfffLL; - if (next_nonce + max64 > 0xfffffffeLL) - max_nonce = 0xfffffffeU; + if (work.data[19] + max64 > end_nonce) + max_nonce = end_nonce; else - max_nonce = next_nonce + max64; + max_nonce = work.data[19] + max64; hashes_done = 0; gettimeofday(&tv_start, NULL); @@ -548,7 +558,7 @@ static void *miner_thread(void *userdata) switch (opt_algo) { case ALGO_SCRYPT: rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target, - max_nonce, &next_nonce, &hashes_done); + max_nonce, &hashes_done); break; default: @@ -1000,4 +1010,3 @@ int main(int argc, char *argv[]) return 0; } - diff --git a/miner.h b/miner.h index d6fa160..d4b24e1 100644 --- a/miner.h +++ b/miner.h @@ -104,21 +104,6 @@ static inline uint32_t swab32(uint32_t v) #endif } -static inline void swap256(void *dest_p, const void *src_p) -{ - uint32_t *dest = dest_p; - const uint32_t *src = src_p; - - dest[0] = src[7]; - dest[1] = src[6]; - dest[2] = src[5]; - dest[3] = src[4]; - dest[4] = src[3]; - dest[5] = src[2]; - dest[6] = src[1]; - dest[7] = src[0]; -} - static inline uint32_t be32dec(const void *pp) { const uint8_t *p = (uint8_t const *)pp; @@ -155,19 +140,19 @@ extern bool opt_debug; extern bool opt_protocol; extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, - const char *rpc_req, bool, bool, int *); + const char *rpc_req, bool, bool, int *); extern char *bin2hex(const unsigned char *p, size_t len); extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len); extern unsigned char *scrypt_buffer_alloc(); -extern int scanhash_scrypt(int thr_id, unsigned char *pdata, - unsigned char *scratchbuf, const unsigned char *ptarget, - uint32_t max_nonce, uint32_t *next_nonce, unsigned long *hashes_done); +extern int scanhash_scrypt(int thr_id, uint32_t *pdata, + unsigned char *scratchbuf, const uint32_t *ptarget, + uint32_t max_nonce, unsigned long *hashes_done); extern int -timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y); +timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); -extern bool fulltest(const unsigned char *hash, const unsigned char *target); +extern bool fulltest(const uint32_t *hash, const uint32_t *target); extern int opt_timeout; extern bool want_longpoll; diff --git a/scrypt.c b/scrypt.c index 212840b..5f55021 100644 --- a/scrypt.c +++ b/scrypt.c @@ -602,43 +602,26 @@ static void scrypt_1024_1_1_256_sp_3way(const uint32_t *input, } #endif /* SCRYPT_MAX_WAYS >= 3 */ -__attribute__ ((noinline)) static int confirm_hash(const uint32_t *hash, - const uint32_t *target) -{ - int i; - for (i = 7; i >= 0; i--) { - uint32_t t = le32dec(&target[i]); - if (hash[i] > t) - return 0; - if (hash[i] < t) - return 1; - } - return 1; -} - -int scanhash_scrypt(int thr_id, unsigned char *pdata, - unsigned char *scratchbuf, const unsigned char *ptarget, - uint32_t max_nonce, uint32_t *next_nonce, unsigned long *hashes_done) +int scanhash_scrypt(int thr_id, uint32_t *pdata, + unsigned char *scratchbuf, const uint32_t *ptarget, + uint32_t max_nonce, unsigned long *hashes_done) { uint32_t data[SCRYPT_MAX_WAYS * 20], hash[SCRYPT_MAX_WAYS * 8]; uint32_t midstate[8]; - const uint32_t first_nonce = *next_nonce; - uint32_t n = *next_nonce; - const uint32_t Htarg = le32dec(&((const uint32_t *)ptarget)[7]); + uint32_t n = pdata[19] - 1; + const uint32_t Htarg = ptarget[7]; const int throughput = scrypt_best_throughput(); int i; - for (i = 0; i < 19; i++) - data[i] = be32dec(&((const uint32_t *)pdata)[i]); - for (i = 1; i < throughput; i++) - memcpy(data + i * 20, data, 80); + for (i = 0; i < throughput; i++) + memcpy(data + i * 20, pdata, 80); SHA256_InitState(midstate); SHA256_Transform(midstate, data, 1); do { for (i = 0; i < throughput; i++) - data[i * 20 + 19] = n++; + data[i * 20 + 19] = ++n; #if SCRYPT_MAX_WAYS >= 3 if (throughput == 3) @@ -653,17 +636,15 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, scrypt_1024_1_1_256_sp(data, hash, midstate, scratchbuf); for (i = 0; i < throughput; i++) { - if (hash[i * 8 + 7] <= Htarg - && confirm_hash(hash + i * 8, (uint32_t *)ptarget)) { - be32enc(&((uint32_t *)pdata)[19], data[i * 20 + 19]); - *next_nonce = n; - *hashes_done = n - first_nonce; + if (hash[i * 8 + 7] <= Htarg && fulltest(hash + i * 8, ptarget)) { + *hashes_done = n - pdata[19] + 1; + pdata[19] = data[i * 20 + 19]; return 1; } } - } while (n <= max_nonce && !work_restart[thr_id].restart); + } while (n < max_nonce && !work_restart[thr_id].restart); - *next_nonce = n; - *hashes_done = n - first_nonce; + *hashes_done = n - pdata[19] + 1; + pdata[19] = n; return 0; } diff --git a/util.c b/util.c index 4a2b826..3ba1099 100644 --- a/util.c +++ b/util.c @@ -1,4 +1,3 @@ - /* * Copyright 2010 Jeff Garzik, 2012 pooler * @@ -16,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -464,49 +465,44 @@ timeval_subtract ( return x->tv_sec < y->tv_sec; } -bool fulltest(const unsigned char *hash, const unsigned char *target) +bool fulltest(const uint32_t *hash, const uint32_t *target) { - unsigned char hash_swap[32], target_swap[32]; - uint32_t *hash32 = (uint32_t *) hash_swap; - uint32_t *target32 = (uint32_t *) target_swap; int i; bool rc = true; - char *hash_str, *target_str; - - swap256(hash_swap, hash); - swap256(target_swap, target); - - for (i = 0; i < 32/4; i++) { - uint32_t h32tmp = swab32(hash32[i]); - uint32_t t32tmp = target32[i]; - - target32[i] = swab32(target32[i]); /* for printing */ - - if (h32tmp > t32tmp) { + + for (i = 7; i >= 0; i--) { + if (hash[i] > target[i]) { rc = false; break; } - if (h32tmp < t32tmp) { + if (hash[i] < target[i]) { rc = true; break; } } if (opt_debug) { - hash_str = bin2hex(hash_swap, 32); - target_str = bin2hex(target_swap, 32); + uint32_t hash_be[32], target_be[32]; + char *hash_str, *target_str; + + for (i = 0; i < 8; i++) { + be32enc(hash_be + i, hash[7 - i]); + be32enc(target_be + i, target[7 - i]); + } + hash_str = bin2hex((unsigned char *)hash_be, 32); + target_str = bin2hex((unsigned char *)target_be, 32); - applog(LOG_DEBUG, " Proof: %s\nTarget: %s\nTrgVal? %s", + applog(LOG_DEBUG, "DEBUG: %s\nHash: %s\nTarget: %s", + rc ? "hash <= target" + : "hash > target (false positive)", hash_str, - target_str, - rc ? "YES (hash < target)" : - "no (false positive; hash > target)"); + target_str); free(hash_str); free(target_str); } - return true; /* FIXME: return rc; */ + return rc; } struct thread_q *tq_new(void) @@ -621,4 +617,3 @@ out: pthread_mutex_unlock(&tq->mutex); return rval; } -