Keep work data in host byte order
This commit is contained in:
parent
3c78575e0f
commit
c96b468d1c
4 changed files with 68 additions and 98 deletions
45
cpu-miner.c
45
cpu-miner.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
miner.h
27
miner.h
|
@ -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;
|
||||||
|
@ -155,19 +140,19 @@ extern bool opt_debug;
|
||||||
extern bool opt_protocol;
|
extern bool opt_protocol;
|
||||||
|
|
||||||
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
|
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 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;
|
||||||
|
|
47
scrypt.c
47
scrypt.c
|
@ -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
45
util.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue