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 {
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;
}

27
miner.h
View file

@ -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;

View file

@ -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;
}

47
util.c
View file

@ -1,4 +1,3 @@
/*
* Copyright 2010 Jeff Garzik, 2012 pooler
*
@ -16,6 +15,8 @@
#include <ctype.h>
#include <stdarg.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <jansson.h>
#include <curl/curl.h>
@ -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;
}