Skip to content

Commit

Permalink
Added -M / --max-diff option
Browse files Browse the repository at this point in the history
This option allows you to save on power and CPU burn by not mining if
difficulty exceeds some threshold. It is intended for testnet miners
that only want to mine on testnet when difficulty drops to 1.0.
  • Loading branch information
cculianu committed May 10, 2020
1 parent f9ef30f commit d0e8e0e
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 32 deletions.
68 changes: 44 additions & 24 deletions cpu-miner.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ static inline void affine_to_cpu(int id, int cpu)
{
}
#endif

enum workio_commands {
WC_GET_WORK,
WC_SUBMIT_WORK,
Expand Down Expand Up @@ -146,6 +146,7 @@ int longpoll_thr_id = -1;
int stratum_thr_id = -1;
struct work_restart *work_restart = NULL;
static struct stratum_ctx stratum;
static double max_diff = 0.;

pthread_mutex_t applog_lock;
static pthread_mutex_t stats_lock;
Expand Down Expand Up @@ -192,6 +193,10 @@ Options:\n\
--no-gbt disable getblocktemplate support\n\
--no-stratum disable X-Stratum support\n\
--no-redirect ignore requests to change the URL of the mining server\n\
-M, --max-diff=N specify a floating point value for the maximum block\n\
difficulty that we will mine (default: inf); this\n\
option is intended for testnet miners wishing to only\n\
mine when difficulty drops to 1.0\n\
-q, --quiet disable per-thread hashmeter output\n\
-D, --debug enable debug output\n\
-P, --protocol-dump verbose dump of protocol-level activities\n"
Expand All @@ -217,7 +222,7 @@ static char const short_options[] =
#ifdef HAVE_SYSLOG_H
"S"
#endif
"a:c:Dhp:Px:qr:R:s:t:T:o:u:O:V";
"a:c:DhM:p:Px:qr:R:s:t:T:o:u:O:V";

static struct option const options[] = {
{ "algo", 1, NULL, 'a' },
Expand All @@ -236,6 +241,7 @@ static struct option const options[] = {
{ "no-longpoll", 0, NULL, 1003 },
{ "no-redirect", 0, NULL, 1009 },
{ "no-stratum", 0, NULL, 1007 },
{ "max-diff", 1, NULL, 'M' },
{ "pass", 1, NULL, 'p' },
{ "protocol-dump", 0, NULL, 'P' },
{ "proxy", 1, NULL, 'x' },
Expand Down Expand Up @@ -673,7 +679,7 @@ static void share_result(int result, const char *reason)
hashrate += thr_hashrates[i];
result ? accepted_count++ : rejected_count++;
pthread_mutex_unlock(&stats_lock);

sprintf(s, hashrate >= 1e6 ? "%.0f" : "%.2f", 1e-3 * hashrate);
applog(LOG_INFO, "accepted: %lu/%lu (%.2f%%), %s khash/s %s",
accepted_count,
Expand Down Expand Up @@ -1028,7 +1034,7 @@ static bool get_work(struct thr_info *thr, struct work *work)
static bool submit_work(struct thr_info *thr, const struct work *work_in)
{
struct workio_cmd *wc;

/* fill out work request message */
wc = calloc(1, sizeof(*wc));
if (!wc)
Expand Down Expand Up @@ -1072,7 +1078,7 @@ static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
memcpy(merkle_root + 32, sctx->job.merkle[i], 32);
sha256d(merkle_root, merkle_root, 64);
}

/* Increment extranonce2 */
for (i = 0; i < sctx->xnonce2_size && !++sctx->job.xnonce2[i]; i++);

Expand Down Expand Up @@ -1130,7 +1136,7 @@ static void *miner_thread(void *userdata)
thr_id, thr_id % num_processors);
affine_to_cpu(thr_id, thr_id % num_processors);
}

if (opt_algo == ALGO_SCRYPT) {
scratchbuf = scrypt_buffer_alloc(opt_scrypt_n);
if (!scratchbuf) {
Expand All @@ -1145,6 +1151,7 @@ static void *miner_thread(void *userdata)
struct timeval tv_start, tv_end, diff;
int64_t max64;
int rc;
double work_diff;

if (have_stratum) {
while (time(NULL) >= g_work_time + 120)
Expand Down Expand Up @@ -1181,7 +1188,7 @@ static void *miner_thread(void *userdata)
work.data[19]++;
pthread_mutex_unlock(&g_work_lock);
work_restart[thr_id].restart = 0;

/* adjust max_nonce to meet target scan time */
if (have_stratum)
max64 = LP_SCANTIME;
Expand All @@ -1203,25 +1210,32 @@ static void *miner_thread(void *userdata)
max_nonce = end_nonce;
else
max_nonce = work.data[19] + max64;

hashes_done = 0;
gettimeofday(&tv_start, NULL);

/* scan nonces for a proof-of-work hash */
switch (opt_algo) {
case ALGO_SCRYPT:
rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target,
max_nonce, &hashes_done, opt_scrypt_n);
break;
if (max_diff > 1.0 && (work_diff = diff_from_nbits(&work.data[18])) > max_diff) {
rc = 0;
applog(LOG_INFO, "thread %d: %1.1lf > max_diff %1.1lf, sleeping 10 secs",
thr_id, work_diff, max_diff);
sleep(10);
} else {
/* scan nonces for a proof-of-work hash */
switch (opt_algo) {
case ALGO_SCRYPT:
rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target,
max_nonce, &hashes_done, opt_scrypt_n);
break;

case ALGO_SHA256D:
rc = scanhash_sha256d(thr_id, work.data, work.target,
max_nonce, &hashes_done);
break;
case ALGO_SHA256D:
rc = scanhash_sha256d(thr_id, work.data, work.target,
max_nonce, &hashes_done);
break;

default:
/* should never happen */
goto out;
default:
/* should never happen */
goto out;
}
}

/* record scanhash elapsed time */
Expand Down Expand Up @@ -1291,7 +1305,7 @@ static void *longpoll_thread(void *userdata)
lp_url = hdr_path;
hdr_path = NULL;
}

/* absolute path, on current server */
else {
copy_start = (*hdr_path == '/') ? (hdr_path + 1) : hdr_path;
Expand Down Expand Up @@ -1445,7 +1459,7 @@ static void *stratum_thread(void *userdata)
restart_threads();
}
}

if (!stratum_socket_full(&stratum, 120)) {
applog(LOG_ERR, "Stratum connection timed out");
s = NULL;
Expand Down Expand Up @@ -1757,6 +1771,12 @@ static void parse_arg(int key, char *arg, char *pname)
}
strcpy(coinbase_sig, arg);
break;
case 'M': /* --max-diff */
if (sscanf(arg, "%lf", &max_diff) != 1 || max_diff <= 1.0) {
fprintf(stderr, "%s: invalid max_diff: %s\n", pname, arg);
show_usage_and_exit(1);
}
break;
case 'S':
use_syslog = true;
break;
Expand Down Expand Up @@ -1931,7 +1951,7 @@ int main(int argc, char *argv[])
thr_info = calloc(opt_n_threads + 3, sizeof(*thr));
if (!thr_info)
return 1;

thr_hashrates = (double *) calloc(opt_n_threads, sizeof(double));
if (!thr_hashrates)
return 1;
Expand Down
2 changes: 2 additions & 0 deletions miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ extern int timeval_subtract(struct timeval *result, struct timeval *x,
struct timeval *y);
extern bool fulltest(const uint32_t *hash, const uint32_t *target);
extern void diff_to_target(uint32_t *target, double diff);
/* Return the network difficulty from the work.data[18] bits as a double. */
extern double diff_from_nbits(const void *nbits);

struct stratum_job {
char *job_id;
Expand Down
35 changes: 27 additions & 8 deletions util.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void applog(int prio, const char *fmt, ...)
va_list ap2;
char *buf;
int len;

va_copy(ap2, ap);
len = vsnprintf(NULL, 0, fmt, ap2) + 1;
va_end(ap2);
Expand Down Expand Up @@ -228,7 +228,7 @@ static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb,
static int seek_data_cb(void *user_data, curl_off_t offset, int origin)
{
struct upload_buffer *ub = user_data;

switch (origin) {
case SEEK_SET:
ub->pos = offset;
Expand Down Expand Up @@ -855,7 +855,7 @@ bool fulltest(const uint32_t *hash, const uint32_t *target)
{
int i;
bool rc = true;

for (i = 7; i >= 0; i--) {
if (hash[i] > target[i]) {
rc = false;
Expand All @@ -870,7 +870,7 @@ bool fulltest(const uint32_t *hash, const uint32_t *target)
if (opt_debug) {
uint32_t hash_be[8], target_be[8];
char hash_str[65], target_str[65];

for (i = 0; i < 8; i++) {
be32enc(hash_be + i, hash[7 - i]);
be32enc(target_be + i, target[7 - i]);
Expand All @@ -892,7 +892,7 @@ void diff_to_target(uint32_t *target, double diff)
{
uint64_t m;
int k;

for (k = 6; k > 0 && diff > 1.0; k--)
diff /= 4294967296.0;
m = 4294901760.0 / diff;
Expand All @@ -905,6 +905,25 @@ void diff_to_target(uint32_t *target, double diff)
}
}

double diff_from_nbits(const void *nbits_in)
{
double numerator;
uint32_t diff32;
uint8_t pow;
int powdiff;
const uint32_t possibly_unswabbed_bits = le32dec(nbits_in);
const uint8_t * const nbits = (const uint8_t *)&possibly_unswabbed_bits;

pow = nbits[0];
powdiff = (8 * (0x1d - 3)) - (8 * (pow - 3));
if (powdiff < 0) // testnet only
powdiff = 0;
diff32 = be32dec(nbits) & 0x00FFFFFF;
numerator = 0xFFFFULL << powdiff;

return numerator / (double)diff32;
}

#ifdef WIN32
#define socket_blocks() (WSAGetLastError() == WSAEWOULDBLOCK)
#else
Expand All @@ -914,7 +933,7 @@ void diff_to_target(uint32_t *target, double diff)
static bool send_line(struct stratum_ctx *sctx, char *s)
{
ssize_t len, sent = 0;

len = strlen(s);
s[len++] = '\n';

Expand Down Expand Up @@ -1471,7 +1490,7 @@ static bool stratum_get_version(struct stratum_ctx *sctx, json_t *id)
char *s;
json_t *val;
bool ret;

if (!id || json_is_null(id))
return false;

Expand All @@ -1496,7 +1515,7 @@ static bool stratum_show_message(struct stratum_ctx *sctx, json_t *id, json_t *p
val = json_array_get(params, 0);
if (val)
applog(LOG_NOTICE, "MESSAGE FROM SERVER: %s", json_string_value(val));

if (!id || json_is_null(id))
return true;

Expand Down

0 comments on commit d0e8e0e

Please sign in to comment.