diff --git a/bignum.cpp b/bignum.cpp index 45a0157..50312c9 100644 --- a/bignum.cpp +++ b/bignum.cpp @@ -24,3 +24,36 @@ extern "C" void bn_nbits_to_uchar(const uint32_t nBits, unsigned char *target) snprintf(buff, 65, "%s\n", bn.ToString().c_str()); buff[64] = '\0'; hex2bin(target, buff, 32); } + +extern "C" double bn_hash_target_ratio(uint32_t* hash, uint32_t* target) +{ + unsigned char* uc; + double dhash; + + if (!opt_showdiff) + return 0.0; + + CBigNum h(0), t(0); + std::vector vch(32); + + memcpy(&vch[0], (void*) target, 32); + t.setvch(vch); + memcpy(&vch[0], (void*) hash, 32); + h.setvch(vch); + + dhash = h.getuint256().getdouble(); + if (dhash > 0.) + return t.getuint256().getdouble() / dhash; + else + return dhash; +} + +// store ratio in work struct +extern "C" void bn_store_hash_target_ratio(uint32_t* hash, uint32_t* target, struct work* work) +{ + // only if the option is enabled (to reduce cpu usage) + if (opt_showdiff) { + work->shareratio = bn_hash_target_ratio(hash, target); + work->sharediff = work->targetdiff * work->shareratio; + } +} diff --git a/ccminer.cpp b/ccminer.cpp index d436ab9..7ea7977 100644 --- a/ccminer.cpp +++ b/ccminer.cpp @@ -160,9 +160,11 @@ static const char *algo_names[] = { }; bool opt_debug = false; +bool opt_debug_diff = false; bool opt_debug_threads = false; bool opt_protocol = false; bool opt_benchmark = false; +bool opt_showdiff = false; // todo: limit use of these flags, // prefer the pools[] attributes @@ -370,6 +372,7 @@ Options:\n\ --syslog-prefix=... allow to change syslog tool name\n" #endif "\ + --show-diff display submitted block and net difficulty\n\ -B, --background run the miner in the background\n\ --benchmark run in offline benchmark mode\n\ --cputest debug hashes from cpu algorithms\n\ @@ -425,6 +428,7 @@ struct option options[] = { { "retries", 1, NULL, 'r' }, { "retry-pause", 1, NULL, 'R' }, { "scantime", 1, NULL, 's' }, + { "show-diff", 0, NULL, 1013 }, { "statsavg", 1, NULL, 'N' }, { "gpu-clock", 1, NULL, 1070 }, { "mem-clock", 1, NULL, 1071 }, @@ -601,7 +605,6 @@ static void calc_network_diff(struct work *work) { // sample for diff 43.281 : 1c05ea29 uchar rtarget[48] = { 0 }; - uint64_t diffone = 0xFFFF000000000000ull; //swab64(0xFFFFull); uint64_t *data64, d64; // todo: endian reversed on longpoll could be zr5 specific... uint32_t nbits = have_longpoll ? work->data[18] : swab32(work->data[18]); @@ -609,6 +612,18 @@ static void calc_network_diff(struct work *work) uint32_t bits = (nbits & 0xffffff); int shfb = 8 * (26 - (shift - 3)); +#if 1 + uint64_t diffone = 0x0000FFFF00000000ull; + double d = (double)0x0000ffff / (double)bits; + for (int m=shift; m < 29; m++) d *= 256.0; + for (int m=29; m < shift; m++) d /= 256.0; + if (opt_debug_diff) + applog(LOG_DEBUG, "diff: %f -> shift %u, bits %08x, shfb %d", d, shift, bits, shfb); + net_diff = d; + return; +#else + uint64_t diffone = 0xFFFF000000000000ull; //swab64(0xFFFFull); + switch (opt_algo) { case ALGO_QUARK: diffone = 0xFFFFFF0000000000ull; @@ -643,10 +658,11 @@ static void calc_network_diff(struct work *work) d64 = swab64(*data64); if (!d64) d64 = 1; - net_diff = (double)diffone / d64; // 43.281 - if (opt_debug) + net_diff = (double)(diffone) / d64; // 43.281 + if (opt_debug_diff) applog(LOG_DEBUG, "diff: %08x -> shift %u, bits %08x, shfb %d -> %.5f (pool %u)", nbits, shift, bits, shfb, net_diff, work->pooln); +#endif } static bool work_decode(const json_t *val, struct work *work) @@ -679,10 +695,9 @@ static bool work_decode(const json_t *val, struct work *work) for (i = 0; i < atarget_sz; i++) work->target[i] = le32dec(work->target + i); - if (opt_max_diff > 0. && !allow_mininginfo) + if ((opt_showdiff || opt_max_diff > 0.) && !allow_mininginfo) calc_network_diff(work); - work->tx_count = use_pok = 0; if (work->data[0] & POK_BOOL_MASK) { use_pok = 1; @@ -697,10 +712,10 @@ static bool work_decode(const json_t *val, struct work *work) size_t txlen = strlen(hexstr)/2; work->tx_count++; if (work->tx_count > POK_MAX_TXS || txlen >= POK_MAX_TX_SZ) { - // when tx is too big, just reset use_pok for the bloc + // when tx is too big, just reset use_pok for the block use_pok = 0; if (opt_debug) applog(LOG_WARNING, - "pok: large bloc ignored, tx len: %u", txlen); + "pok: large block ignored, tx len: %u", txlen); work->tx_count = 0; break; } @@ -709,7 +724,7 @@ static bool work_decode(const json_t *val, struct work *work) totlen += txlen; } if (opt_debug) - applog(LOG_DEBUG, "bloc txs: %u, total len: %u", work->tx_count, totlen); + applog(LOG_DEBUG, "block txs: %u, total len: %u", work->tx_count, totlen); } } @@ -749,7 +764,7 @@ static void calc_target_diff(struct work *work) //case ALGO_SCRYPT: //case ALGO_SCRYPT_JANE: // todo/check... - work->difficulty = 0.; + work->difficulty = work->targetdiff; return; case ALGO_HEAVY: data64 = (uint64_t*)(rtarget + 2); @@ -764,8 +779,14 @@ static void calc_target_diff(struct work *work) work->difficulty /= opt_difficulty; } -static int share_result(int result, int pooln, const char *reason) +#define YES "yes!" +#define YAY "yay!!!" +#define BOO "booooo" + +static int share_result(int result, int pooln, double sharediff, const char *reason) { + const char *flag; + char suppl[32] = { 0 }; char s[32] = { 0 }; double hashrate = 0.; struct pool_infos *p = &pools[pooln]; @@ -782,15 +803,25 @@ static int share_result(int result, int pooln, const char *reason) global_hashrate = llround(hashrate); format_hashrate(hashrate, s); - applog(LOG_NOTICE, "accepted: %lu/%lu (%.2f%%), %s %s", + if (opt_showdiff) + sprintf(suppl, "diff %.3f", sharediff); + else // accepted percent + sprintf(suppl, "%.2f%%", 100. * p->accepted_count / (p->accepted_count + p->rejected_count)); + + if (!net_diff || sharediff < net_diff) { + flag = use_colors ? + (result ? CL_GRN YES : CL_RED BOO) + : (result ? "(" YES ")" : "(" BOO ")"); + } else { + flag = use_colors ? + (result ? CL_GRN YAY : CL_RED BOO) + : (result ? "(" YAY ")" : "(" BOO ")"); + } + + applog(LOG_NOTICE, "accepted: %lu/%lu (%s), %s %s", p->accepted_count, p->accepted_count + p->rejected_count, - 100. * p->accepted_count / (p->accepted_count + p->rejected_count), - s, - use_colors ? - (result ? CL_GRN "yay!!!" : CL_RED "booooo") - : (result ? "(yay!!!)" : "(booooo)")); - + suppl, s, flag); if (reason) { applog(LOG_WARNING, "reject reason: %s", reason); /* if (strncasecmp(reason, "low difficulty", 14) == 0) { @@ -814,7 +845,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work) bool stale_work = false; char s[384]; - /* discard if a newer bloc was received */ + /* discard if a newer block was received */ stale_work = work->height && work->height < g_work.height; if (have_stratum && !stale_work && opt_algo != ALGO_ZR5 && opt_algo != ALGO_SCRYPT_JANE) { pthread_mutex_lock(&g_work_lock); @@ -828,7 +859,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work) if (get_blocktemplate(curl, &wheight)) { if (work->height && work->height < wheight.height) { if (opt_debug) - applog(LOG_WARNING, "bloc %u was already solved", work->height); + applog(LOG_WARNING, "block %u was already solved", work->height); return true; } } @@ -886,6 +917,16 @@ static bool submit_upstream_work(CURL *curl, struct work *work) ntimestr = bin2hex((const uchar*)(&ntime), 4); xnonce2str = bin2hex(work->xnonce2, work->xnonce2_len); + // store to keep/display the solved ratio/diff + stratum.sharediff = work->sharediff; + + if (net_diff && stratum.sharediff > net_diff && (!opt_quiet || opt_debug_diff)) + applog(LOG_INFO, "share diff: %.5f, possible block found!!!", + stratum.sharediff); + else if (opt_debug_diff) + applog(LOG_DEBUG, "share diff: %.5f (x %.1f)", + stratum.sharediff, work->shareratio); + if (opt_algo == ALGO_HEAVY) { be16enc(&nvote, *((uint16_t*)&work->data[20])); nvotestr = bin2hex((const uchar*)(&nvote), 2); @@ -947,8 +988,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work) res = json_object_get(val, "result"); reason = json_object_get(val, "reject-reason"); - if (!share_result(json_is_true(res), - work->pooln, + if (!share_result(json_is_true(res), work->pooln, work->sharediff, reason ? json_string_value(reason) : NULL)) { if (check_dups) @@ -969,7 +1009,7 @@ static bool gbt_work_decode(const json_t *val, struct work *work) json_t *err = json_object_get(val, "error"); if (err && !json_is_null(err)) { allow_gbt = false; - applog(LOG_INFO, "GBT not supported, bloc height unavailable"); + applog(LOG_INFO, "GBT not supported, block height unavailable"); return false; } @@ -1373,7 +1413,7 @@ static bool stratum_gen_work(struct stratum_ctx *sctx, struct work *work) work->xnonce2_len = sctx->xnonce2_size; memcpy(work->xnonce2, sctx->job.xnonce2, sctx->xnonce2_size); - // also store the bloc number + // also store the block number work->height = sctx->job.height; // and the pool of the current stratum work->pooln = sctx->pooln; @@ -1415,7 +1455,7 @@ static bool stratum_gen_work(struct stratum_ctx *sctx, struct work *work) work->data[17] = le32dec(sctx->job.ntime); work->data[18] = le32dec(sctx->job.nbits); - if (opt_max_diff > 0.) + if (opt_showdiff || opt_max_diff > 0.) calc_network_diff(work); switch (opt_algo) { @@ -1460,21 +1500,21 @@ static bool stratum_gen_work(struct stratum_ctx *sctx, struct work *work) case ALGO_NEOSCRYPT: case ALGO_SCRYPT: case ALGO_SCRYPT_JANE: - diff_to_target(work->target, sctx->job.diff / (65536.0 * opt_difficulty)); + diff_to_target(work, sctx->job.diff / (65536.0 * opt_difficulty)); break; case ALGO_DMD_GR: case ALGO_FRESH: case ALGO_FUGUE256: case ALGO_GROESTL: case ALGO_LYRA2v2: - diff_to_target(work->target, sctx->job.diff / (256.0 * opt_difficulty)); + diff_to_target(work, sctx->job.diff / (256.0 * opt_difficulty)); break; case ALGO_KECCAK: case ALGO_LYRA2: - diff_to_target(work->target, sctx->job.diff / (128.0 * opt_difficulty)); + diff_to_target(work, sctx->job.diff / (128.0 * opt_difficulty)); break; default: - diff_to_target(work->target, sctx->job.diff / opt_difficulty); + diff_to_target(work, sctx->job.diff / opt_difficulty); } return true; } @@ -1919,8 +1959,7 @@ static void *miner_thread(void *userdata) break; case ALGO_LYRA2v2: - rc = scanhash_lyra2v2(thr_id, work.data, work.target, - max_nonce, &hashes_done); + rc = scanhash_lyra2v2(thr_id, &work, max_nonce, &hashes_done); break; case ALGO_NEOSCRYPT: @@ -2208,7 +2247,7 @@ longpoll_retry: if (!opt_quiet) { char netinfo[64] = { 0 }; if (net_diff > 0.) { - sprintf(netinfo, ", diff %.2f", net_diff); + sprintf(netinfo, ", diff %.3f", net_diff); } applog(LOG_BLUE, "%s detected new block%s", short_url, netinfo); } @@ -2280,7 +2319,7 @@ static bool stratum_handle_response(char *buf) // store time required to the pool to answer to a submit stratum.answer_msec = (1000 * diff.tv_sec) + (uint32_t) (0.001 * diff.tv_usec); - share_result(json_is_true(res_val), stratum.pooln, + share_result(json_is_true(res_val), stratum.pooln, stratum.sharediff, err_val ? json_string_value(json_array_get(err_val, 1)) : NULL); ret = true; @@ -2366,7 +2405,7 @@ wait_stratum_url: if (stratum.job.clean) { if (!opt_quiet) { if (net_diff > 0.) - applog(LOG_BLUE, "%s block %d, diff %.2f", algo_names[opt_algo], + applog(LOG_BLUE, "%s block %d, diff %.3f", algo_names[opt_algo], stratum.job.height, net_diff); else applog(LOG_BLUE, "%s %s block %d", pool->short_url, algo_names[opt_algo], @@ -2841,6 +2880,9 @@ void parse_arg(int key, char *arg) case 1012: opt_extranonce = false; break; + case 1013: + opt_showdiff = true; + break; case 'S': case 1018: applog(LOG_INFO, "Now logging to syslog..."); diff --git a/lyra2/lyra2REv2.cu b/lyra2/lyra2REv2.cu index 9517d20..99fc95d 100644 --- a/lyra2/lyra2REv2.cu +++ b/lyra2/lyra2REv2.cu @@ -71,10 +71,10 @@ void lyra2v2_hash(void *state, const void *input) static bool init[MAX_GPUS] = { 0 }; -extern "C" int scanhash_lyra2v2(int thr_id, uint32_t *pdata, - const uint32_t *ptarget, uint32_t max_nonce, - unsigned long *hashes_done) +extern "C" int scanhash_lyra2v2(int thr_id, struct work* work, uint32_t max_nonce, unsigned long *hashes_done) { + uint32_t *pdata = work->data; + uint32_t *ptarget = work->target; const uint32_t first_nonce = pdata[19]; int intensity = (device_sm[device_map[thr_id]] > 500 && !is_windows()) ? 18 : 17; unsigned int defthr = 1U << intensity; @@ -138,10 +138,15 @@ extern "C" int scanhash_lyra2v2(int thr_id, uint32_t *pdata, if (vhash64[7] <= Htarg && fulltest(vhash64, ptarget)) { int res = 1; + bn_store_hash_target_ratio(vhash64, ptarget, work); // check if there was another one... *hashes_done = pdata[19] - first_nonce + throughput; if (foundNonces[1] != 0) { + be32enc(&endiandata[19], foundNonces[1]); + lyra2v2_hash(vhash64, endiandata); + if (bn_hash_target_ratio(vhash64, ptarget) > work->shareratio) + bn_store_hash_target_ratio(vhash64, ptarget, work); pdata[21] = foundNonces[1]; res++; } diff --git a/miner.h b/miner.h index 683a024..e87ef13 100644 --- a/miner.h +++ b/miner.h @@ -322,8 +322,8 @@ extern int scanhash_fresh(int thr_id, uint32_t *pdata, extern int scanhash_lyra2(int thr_id, uint32_t *pdata, const uint32_t *ptarget, uint32_t max_nonce, unsigned long *hashes_done); -extern int scanhash_lyra2v2(int thr_id, uint32_t *pdata, - const uint32_t *ptarget, uint32_t max_nonce, unsigned long *hashes_done); +extern int scanhash_lyra2v2(int thr_id, struct work *work, + uint32_t max_nonce, unsigned long *hashes_done); extern int scanhash_neoscrypt(int thr_id, uint32_t *pdata, const uint32_t *ptarget, uint32_t max_nonce, unsigned long *hashes_done); @@ -495,6 +495,7 @@ extern bool opt_benchmark; extern bool opt_debug; extern bool opt_quiet; extern bool opt_protocol; +extern bool opt_showdiff; extern bool opt_tracegpu; extern int opt_n_threads; extern int active_gpus; @@ -571,13 +572,15 @@ extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len); 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); +extern void diff_to_target(struct work* work, double diff); extern void get_currentalgo(char* buf, int sz); extern uint32_t device_intensity(int thr_id, const char *func, uint32_t defcount); // bignum double bn_convert_nbits(const uint32_t nbits); void bn_nbits_to_uchar(const uint32_t nBits, uchar *target); +double bn_hash_target_ratio(uint32_t* hash, uint32_t* target); +void bn_store_hash_target_ratio(uint32_t* hash, uint32_t* target, struct work* work); struct stratum_job { char *job_id; @@ -607,6 +610,7 @@ struct stratum_ctx { char *sockbuf; double next_diff; + double sharediff; char *session_id; size_t xnonce1_size; @@ -643,7 +647,10 @@ struct work { uint64_t u64[1]; } noncerange; + double targetdiff; double difficulty; + double shareratio; + double sharediff; uint32_t height; uint8_t pooln; diff --git a/util.cpp b/util.cpp index d0b3f1d..a296eec 100644 --- a/util.cpp +++ b/util.cpp @@ -38,6 +38,7 @@ extern pthread_mutex_t stratum_sock_lock; extern pthread_mutex_t stratum_work_lock; +extern bool opt_debug_diff; bool opt_tracegpu = false; @@ -765,7 +766,7 @@ bool fulltest(const uint32_t *hash, const uint32_t *target) } } - if (!rc && opt_debug) { + if ((!rc && opt_debug) || opt_debug_diff) { uint32_t hash_be[8], target_be[8]; char *hash_str, *target_str; @@ -789,11 +790,14 @@ bool fulltest(const uint32_t *hash, const uint32_t *target) return rc; } -void diff_to_target(uint32_t *target, double diff) +void diff_to_target(struct work* work, double diff) { + uint32_t *target = work->target; uint64_t m; int k; - + + work->targetdiff = diff; + for (k = 6; k > 0 && diff > 1.0; k--) diff /= 4294967296.0; m = (uint64_t)(4294901760.0 / diff); diff --git a/zr5.cu b/zr5.cu index d298c8f..63ed68b 100644 --- a/zr5.cu +++ b/zr5.cu @@ -435,6 +435,7 @@ extern "C" int scanhash_zr5(int thr_id, struct work *work, zr5hash(vhash64, pdata); if (vhash64[7] <= ptarget[7] && fulltest(vhash64, ptarget)) { int res = 1; + bn_store_hash_target_ratio(vhash64, ptarget, work); uint32_t secNonce = cuda_check_hash_suppl(thr_id, throughput, oldp19, d_hash[thr_id], 1); if (secNonce != 0) { offset = secNonce - oldp19; @@ -444,6 +445,8 @@ extern "C" int scanhash_zr5(int thr_id, struct work *work, tmpdata[0] = pok; tmpdata[19] = secNonce; zr5hash(vhash64, tmpdata); if (vhash64[7] <= ptarget[7] && fulltest(vhash64, ptarget)) { + if (bn_hash_target_ratio(vhash64, ptarget) > work->shareratio) + bn_store_hash_target_ratio(vhash64, ptarget, work); pdata[21] = secNonce; pdata[22] = pok; res++;