Keep work data in host byte order

This commit is contained in:
pooler 2012-03-10 13:37:33 +01:00
parent 3c78575e0f
commit c96b468d1c
4 changed files with 68 additions and 98 deletions

View file

@ -180,10 +180,8 @@ static struct option const options[] = {
}; };
struct work { struct work {
unsigned char data[128]; uint32_t data[32];
unsigned char target[32]; uint32_t target[8];
unsigned char hash[32];
}; };
static struct work g_work; 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) static bool work_decode(const json_t *val, struct work *work)
{ {
int i;
if (unlikely(!jobj_binary(val, "data", work->data, sizeof(work->data)))) { if (unlikely(!jobj_binary(val, "data", work->data, sizeof(work->data)))) {
applog(LOG_ERR, "JSON inval data"); applog(LOG_ERR, "JSON inval data");
goto err_out; goto err_out;
@ -223,7 +223,10 @@ static bool work_decode(const json_t *val, struct work *work)
goto err_out; 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; return true;
@ -231,7 +234,7 @@ err_out:
return false; 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; char *hexstr = NULL;
json_t *val, *res; json_t *val, *res;
@ -241,11 +244,16 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
bool rc = false; bool rc = false;
/* pass if the previous hash is not the current previous hash */ /* 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; return true;
}
/* build hex string */ /* 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)) { if (unlikely(!hexstr)) {
applog(LOG_ERR, "submit_upstream_work OOM"); applog(LOG_ERR, "submit_upstream_work OOM");
goto out; goto out;
@ -483,8 +491,9 @@ static void *miner_thread(void *userdata)
{ {
struct thr_info *mythr = userdata; struct thr_info *mythr = userdata;
int thr_id = mythr->id; int thr_id = mythr->id;
struct work work;
uint32_t max_nonce; uint32_t max_nonce;
uint32_t next_nonce; uint32_t end_nonce = 0xffffffffU / opt_n_threads * (thr_id + 1) - 4;
unsigned char *scratchbuf = NULL; unsigned char *scratchbuf = NULL;
/* Set worker threads to nice 19 and then preferentially to SCHED_IDLE /* Set worker threads to nice 19 and then preferentially to SCHED_IDLE
@ -504,7 +513,6 @@ static void *miner_thread(void *userdata)
} }
while (1) { while (1) {
struct work work __attribute__((aligned(128)));
unsigned long hashes_done; unsigned long hashes_done;
struct timeval tv_start, tv_end, diff; struct timeval tv_start, tv_end, diff;
int64_t max64; int64_t max64;
@ -512,7 +520,8 @@ static void *miner_thread(void *userdata)
/* obtain new work from internal workio thread */ /* obtain new work from internal workio thread */
pthread_mutex_lock(&g_work_lock); 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))) { if (unlikely(!get_work(mythr, &g_work))) {
applog(LOG_ERR, "work retrieval failed, exiting " applog(LOG_ERR, "work retrieval failed, exiting "
"mining thread %d", mythr->id); "mining thread %d", mythr->id);
@ -525,8 +534,9 @@ static void *miner_thread(void *userdata)
} }
if (memcmp(work.data, g_work.data, 76)) { if (memcmp(work.data, g_work.data, 76)) {
memcpy(&work, &g_work, sizeof(struct work)); 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); pthread_mutex_unlock(&g_work_lock);
work_restart[thr_id].restart = 0; work_restart[thr_id].restart = 0;
@ -536,10 +546,10 @@ static void *miner_thread(void *userdata)
max64 *= thr_hashrates[thr_id]; max64 *= thr_hashrates[thr_id];
if (max64 <= 0) if (max64 <= 0)
max64 = 0xfffLL; max64 = 0xfffLL;
if (next_nonce + max64 > 0xfffffffeLL) if (work.data[19] + max64 > end_nonce)
max_nonce = 0xfffffffeU; max_nonce = end_nonce;
else else
max_nonce = next_nonce + max64; max_nonce = work.data[19] + max64;
hashes_done = 0; hashes_done = 0;
gettimeofday(&tv_start, NULL); gettimeofday(&tv_start, NULL);
@ -548,7 +558,7 @@ static void *miner_thread(void *userdata)
switch (opt_algo) { switch (opt_algo) {
case ALGO_SCRYPT: case ALGO_SCRYPT:
rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target, rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target,
max_nonce, &next_nonce, &hashes_done); max_nonce, &hashes_done);
break; break;
default: default:
@ -1000,4 +1010,3 @@ int main(int argc, char *argv[])
return 0; return 0;
} }

23
miner.h
View file

@ -104,21 +104,6 @@ static inline uint32_t swab32(uint32_t v)
#endif #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) static inline uint32_t be32dec(const void *pp)
{ {
const uint8_t *p = (uint8_t const *)pp; const uint8_t *p = (uint8_t const *)pp;
@ -160,14 +145,14 @@ extern char *bin2hex(const unsigned char *p, size_t len);
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len); extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
extern unsigned char *scrypt_buffer_alloc(); extern unsigned char *scrypt_buffer_alloc();
extern int scanhash_scrypt(int thr_id, unsigned char *pdata, extern int scanhash_scrypt(int thr_id, uint32_t *pdata,
unsigned char *scratchbuf, const unsigned char *ptarget, unsigned char *scratchbuf, const uint32_t *ptarget,
uint32_t max_nonce, uint32_t *next_nonce, unsigned long *hashes_done); uint32_t max_nonce, unsigned long *hashes_done);
extern int 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 int opt_timeout;
extern bool want_longpoll; extern bool want_longpoll;

View file

@ -602,43 +602,26 @@ static void scrypt_1024_1_1_256_sp_3way(const uint32_t *input,
} }
#endif /* SCRYPT_MAX_WAYS >= 3 */ #endif /* SCRYPT_MAX_WAYS >= 3 */
__attribute__ ((noinline)) static int confirm_hash(const uint32_t *hash, int scanhash_scrypt(int thr_id, uint32_t *pdata,
const uint32_t *target) unsigned char *scratchbuf, const uint32_t *ptarget,
{ uint32_t max_nonce, unsigned long *hashes_done)
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)
{ {
uint32_t data[SCRYPT_MAX_WAYS * 20], hash[SCRYPT_MAX_WAYS * 8]; uint32_t data[SCRYPT_MAX_WAYS * 20], hash[SCRYPT_MAX_WAYS * 8];
uint32_t midstate[8]; uint32_t midstate[8];
const uint32_t first_nonce = *next_nonce; uint32_t n = pdata[19] - 1;
uint32_t n = *next_nonce; const uint32_t Htarg = ptarget[7];
const uint32_t Htarg = le32dec(&((const uint32_t *)ptarget)[7]);
const int throughput = scrypt_best_throughput(); const int throughput = scrypt_best_throughput();
int i; int i;
for (i = 0; i < 19; i++) for (i = 0; i < throughput; i++)
data[i] = be32dec(&((const uint32_t *)pdata)[i]); memcpy(data + i * 20, pdata, 80);
for (i = 1; i < throughput; i++)
memcpy(data + i * 20, data, 80);
SHA256_InitState(midstate); SHA256_InitState(midstate);
SHA256_Transform(midstate, data, 1); SHA256_Transform(midstate, data, 1);
do { do {
for (i = 0; i < throughput; i++) for (i = 0; i < throughput; i++)
data[i * 20 + 19] = n++; data[i * 20 + 19] = ++n;
#if SCRYPT_MAX_WAYS >= 3 #if SCRYPT_MAX_WAYS >= 3
if (throughput == 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); scrypt_1024_1_1_256_sp(data, hash, midstate, scratchbuf);
for (i = 0; i < throughput; i++) { for (i = 0; i < throughput; i++) {
if (hash[i * 8 + 7] <= Htarg if (hash[i * 8 + 7] <= Htarg && fulltest(hash + i * 8, ptarget)) {
&& confirm_hash(hash + i * 8, (uint32_t *)ptarget)) { *hashes_done = n - pdata[19] + 1;
be32enc(&((uint32_t *)pdata)[19], data[i * 20 + 19]); pdata[19] = data[i * 20 + 19];
*next_nonce = n;
*hashes_done = n - first_nonce;
return 1; 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 - pdata[19] + 1;
*hashes_done = n - first_nonce; pdata[19] = n;
return 0; return 0;
} }

45
util.c
View file

@ -1,4 +1,3 @@
/* /*
* Copyright 2010 Jeff Garzik, 2012 pooler * Copyright 2010 Jeff Garzik, 2012 pooler
* *
@ -16,6 +15,8 @@
#include <ctype.h> #include <ctype.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <jansson.h> #include <jansson.h>
#include <curl/curl.h> #include <curl/curl.h>
@ -464,49 +465,44 @@ timeval_subtract (
return x->tv_sec < y->tv_sec; 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; int i;
bool rc = true; bool rc = true;
char *hash_str, *target_str;
swap256(hash_swap, hash); for (i = 7; i >= 0; i--) {
swap256(target_swap, target); if (hash[i] > target[i]) {
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) {
rc = false; rc = false;
break; break;
} }
if (h32tmp < t32tmp) { if (hash[i] < target[i]) {
rc = true; rc = true;
break; break;
} }
} }
if (opt_debug) { if (opt_debug) {
hash_str = bin2hex(hash_swap, 32); uint32_t hash_be[32], target_be[32];
target_str = bin2hex(target_swap, 32); char *hash_str, *target_str;
applog(LOG_DEBUG, " Proof: %s\nTarget: %s\nTrgVal? %s", 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, "DEBUG: %s\nHash: %s\nTarget: %s",
rc ? "hash <= target"
: "hash > target (false positive)",
hash_str, hash_str,
target_str, target_str);
rc ? "YES (hash < target)" :
"no (false positive; hash > target)");
free(hash_str); free(hash_str);
free(target_str); free(target_str);
} }
return true; /* FIXME: return rc; */ return rc;
} }
struct thread_q *tq_new(void) struct thread_q *tq_new(void)
@ -621,4 +617,3 @@ out:
pthread_mutex_unlock(&tq->mutex); pthread_mutex_unlock(&tq->mutex);
return rval; return rval;
} }