Skip to content
Permalink
Browse files

scanlog: remember sharediff for multiple nonces

rpc2: handle properly secondary nonce(s) + api ping time fix

be sure to fully recompile, structures are changed
  • Loading branch information...
tpruvot committed Jan 9, 2017
1 parent 93adb56 commit 242aa4144b7f27df89b3050672b211579ec53c84
Showing with 111 additions and 63 deletions.
  1. +2 −1 bignum.cpp
  2. +33 −28 ccminer.cpp
  3. +3 −5 crypto/wildkeccak.cu
  4. +24 −21 crypto/xmr-rpc.cpp
  5. +41 −7 hashlog.cpp
  6. +8 −1 miner.h
@@ -74,6 +74,7 @@ extern "C" void bn_store_hash_target_ratio(uint32_t* hash, uint32_t* target, str
{
// only if the option is enabled (to reduce cpu usage)
if (!opt_showdiff) return;
if (nonce < 0 || nonce >= MAX_NONCES) return;

work->shareratio[nonce] = bn_hash_target_ratio(hash, target);
work->sharediff[nonce] = work->targetdiff * work->shareratio[nonce];
@@ -88,6 +89,6 @@ extern "C" void bn_set_target_ratio(struct work* work, uint32_t* hash, int nonce
// compat (only store single nonce share diff per work)
extern "C" void work_set_target_ratio(struct work* work, uint32_t* hash)
{
bn_store_hash_target_ratio(hash, work->target, work, 0);
bn_store_hash_target_ratio(hash, work->target, work, work->submit_nonce_id);
}

@@ -94,7 +94,7 @@ bool want_stratum = true;
bool have_stratum = false;
bool allow_gbt = true;
bool allow_mininginfo = true;
bool check_dups = false;
bool check_dups = true; //false;
bool check_stratum_jobs = false;

bool submit_old = false;
@@ -796,18 +796,17 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
struct pool_infos *pool = &pools[work->pooln];
json_t *val, *res, *reason;
bool stale_work = false;
int idnonce = 0;
int idnonce = work->submit_nonce_id;

if (pool->type & POOL_STRATUM && stratum.rpc2) {
struct work submit_work;
memcpy(&submit_work, work, sizeof(struct work));
bool sent = hashlog_already_submittted(submit_work.job_id, submit_work.nonces[0]);
if (sent) {
return true;
if (!hashlog_already_submittted(submit_work.job_id, submit_work.nonces[idnonce])) {
if (rpc2_stratum_submit(pool, &submit_work))
hashlog_remember_submit(&submit_work, submit_work.nonces[idnonce]);
stratum.job.shares_count++;
}
bool ret = rpc2_stratum_submit(pool, &submit_work);
hashlog_remember_submit(&submit_work, submit_work.nonces[0]);
return ret;
return true;
}

/* discard if a newer block was received */
@@ -851,7 +850,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work)

if (pool->type & POOL_STRATUM) {
uint32_t sent = 0;
uint32_t ntime, nonce;
uint32_t ntime, nonce = work->nonces[idnonce];
char *ntimestr, *noncestr, *xnonce2str, *nvotestr;
uint16_t nvote = 0;

@@ -879,7 +878,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
case ALGO_LBRY:
check_dups = true;
le32enc(&ntime, work->data[25]);
le32enc(&nonce, work->data[27]);
//le32enc(&nonce, work->data[27]);
break;
case ALGO_SIA:
be32enc(&ntime, work->data[10]);
@@ -930,18 +929,18 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
stratum.sharediff);
else if (opt_debug_diff)
applog(LOG_DEBUG, "share diff: %.5f (x %.1f)",
stratum.sharediff, work->shareratio);
stratum.sharediff, work->shareratio[idnonce]);

if (opt_vote) { // ALGO_HEAVY ALGO_DECRED
nvotestr = bin2hex((const uchar*)(&nvote), 2);
sprintf(s, "{\"method\": \"mining.submit\", \"params\": ["
"\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":%d}",
pool->user, work->job_id + 8, xnonce2str, ntimestr, noncestr, nvotestr, 10+idnonce);
"\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":%u}",
pool->user, work->job_id + 8, xnonce2str, ntimestr, noncestr, nvotestr, stratum.job.shares_count + 10);
free(nvotestr);
} else {
sprintf(s, "{\"method\": \"mining.submit\", \"params\": ["
"\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":%d}",
pool->user, work->job_id + 8, xnonce2str, ntimestr, noncestr, 10+idnonce);
"\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":%u}",
pool->user, work->job_id + 8, xnonce2str, ntimestr, noncestr, stratum.job.shares_count + 10);
}
free(xnonce2str);
free(ntimestr);
@@ -953,8 +952,9 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
return false;
}

if (check_dups)
if (check_dups || opt_showdiff)
hashlog_remember_submit(work, nonce);
stratum.job.shares_count++;

} else {

@@ -1830,6 +1830,10 @@ static void *miner_thread(void *userdata)
}
}

// reset shares id counter on new job
if (strcmp(work.job_id, g_work.job_id))
stratum.job.shares_count = 0;

if (!opt_benchmark && (g_work.height != work.height || memcmp(work.target, g_work.target, sizeof(work.target))))
{
if (opt_debug) {
@@ -2385,7 +2389,8 @@ static void *miner_thread(void *userdata)
nonceptr[0] = UINT32_MAX;
}

if (check_dups && opt_algo != ALGO_DECRED && opt_algo != ALGO_SIA)
// only required to debug purpose
if (opt_debug && check_dups && opt_algo != ALGO_DECRED && opt_algo != ALGO_SIA)
hashlog_remember_scan_range(&work);

/* output */
@@ -2441,6 +2446,7 @@ static void *miner_thread(void *userdata)

// second nonce found, submit too (on pool only!)
if (rc > 1 && work.nonces[1]) {
work.submit_nonce_id = 1;
nonceptr[0] = work.nonces[1];
if (opt_algo == ALGO_ZR5) {
// todo: use + 4..6 index for pok to allow multiple nonces
@@ -2620,7 +2626,8 @@ static bool stratum_handle_response(char *buf)
json_t *val, *err_val, *res_val, *id_val;
json_error_t err;
struct timeval tv_answer, diff;
int num = 0;
int num = 0, job_nonce_id = 0;
double sharediff = stratum.sharediff;
bool ret = false;

val = JSON_LOADS(buf, &err);
@@ -2641,30 +2648,28 @@ static bool stratum_handle_response(char *buf)
if (num < 4)
goto out;

// todo: use request id to index nonce diff data
// num = num % 10;
// We dont have the work anymore, so use the hashlog to get the right sharediff for multiple nonces
job_nonce_id = num - 10;
if (opt_showdiff && check_dups)
sharediff = hashlog_get_sharediff(g_work.job_id, job_nonce_id, sharediff);

gettimeofday(&tv_answer, NULL);
timeval_subtract(&diff, &tv_answer, &stratum.tv_submit);
// 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);

if (stratum.rpc2) {

const char* reject_reason = err_val ? json_string_value(json_object_get(err_val, "message")) : NULL;
// {"id":4,"jsonrpc":"2.0","error":null,"result":{"status":"OK"}}
share_result(json_is_null(err_val), stratum.pooln, stratum.sharediff, reject_reason);
// {"id":10,"jsonrpc":"2.0","error":null,"result":{"status":"OK"}}
share_result(json_is_null(err_val), stratum.pooln, sharediff, reject_reason);
if (reject_reason) {
g_work_time = 0;
restart_threads();
}

} else {

if (!res_val)
goto out;

share_result(json_is_true(res_val), stratum.pooln, stratum.sharediff,
share_result(json_is_true(res_val), stratum.pooln, sharediff,
err_val ? json_string_value(json_array_get(err_val, 1)) : NULL);
}

@@ -2765,7 +2770,7 @@ static void *stratum_thread(void *userdata)
stratum.job.height);
}
restart_threads();
if (check_dups)
if (check_dups || opt_showdiff)
hashlog_purge_old();
stats_purge_old();
} else if (opt_debug && !opt_quiet) {
@@ -222,16 +222,12 @@ static bool init[MAX_GPUS] = { 0 };

extern "C" int scanhash_wildkeccak(int thr_id, struct work* work, uint32_t max_nonce, unsigned long *hashes_done)
{
//uint32_t _ALIGN(64) endiandata[20];
uint32_t *ptarget = work->target;
uint32_t throughput = 0;
uint64_t n, nonce, first;
uint8_t *pdata = (uint8_t*) work->data;
memcpy(&first, &pdata[1], 8);
//memcpy(&n, &pdata[1], 4);;
n = nonce = first;
// pdata[5] = thr_id;
// memcpy(&nonce, &pdata[1], 8);

if (!scratchpad_size || !h_scratchpad[thr_id]) {
if (h_scratchpad[thr_id])
@@ -245,7 +241,8 @@ extern "C" int scanhash_wildkeccak(int thr_id, struct work* work, uint32_t max_n

if (device_config[thr_id]) {
sscanf(device_config[thr_id], "%ux%u", &WK_CUDABlocks, &WK_CUDAThreads);
gpulog(LOG_INFO, thr_id, "Using %u x %u threads kernel launch config", WK_CUDABlocks, WK_CUDAThreads);
gpulog(LOG_INFO, thr_id, "Using %u x %u kernel launch config, %u threads",
WK_CUDABlocks, WK_CUDAThreads, throughput);
} else {
throughput = cuda_default_throughput(thr_id, WK_CUDABlocks*WK_CUDAThreads);
gpulog(LOG_INFO, thr_id, "Intensity set to %g, %u cuda threads", throughput2intensity(throughput), throughput);
@@ -319,6 +316,7 @@ extern "C" int scanhash_wildkeccak(int thr_id, struct work* work, uint32_t max_n
if (n + throughput > max_nonce) {
*hashes_done = (unsigned long) (max_nonce - first);
}
work->valid_nonces = 1;
return 1;
}
}
@@ -341,7 +341,7 @@ static bool addendum_decode(const json_t *addm)
current_scratchpad_hi = hi;

if (!opt_quiet && !opt_quiet_start)
applog(LOG_BLUE, "ADDENDUM APPLIED: %lld --> %lld", old_height, current_scratchpad_hi.height);
applog(LOG_BLUE, "ADDENDUM APPLIED: Block %lld", (long long) current_scratchpad_hi.height);

return true;
err_out:
@@ -440,6 +440,8 @@ bool rpc2_job_decode(const json_t *job, struct work *work)
}

if (rpc2_job_id) {
// reset job share counter
if (strcmp(rpc2_job_id, job_id)) stratum.job.shares_count = 0;
free(rpc2_job_id);
}
rpc2_job_id = strdup(job_id);
@@ -478,8 +480,7 @@ bool rpc2_stratum_job(struct stratum_ctx *sctx, json_t *id, json_t *params)
pthread_mutex_lock(&rpc2_work_lock);
ret = rpc2_job_decode(params, &rpc2_work);
// update miner threads work
if (ret) rpc2_stratum_gen_work(sctx, &g_work);
//memcpy(&g_work, &rpc2_work, sizeof(struct work));
ret = ret && rpc2_stratum_gen_work(sctx, &g_work);
restart_threads();
pthread_mutex_unlock(&rpc2_work_lock);
return ret;
@@ -510,67 +511,69 @@ bool rpc2_stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
}

#define JSON_SUBMIT_BUF_LEN 512
// called by submit_upstream_work()
bool rpc2_stratum_submit(struct pool_infos *pool, struct work *work)
{
char _ALIGN(64) s[JSON_SUBMIT_BUF_LEN];
uint8_t _ALIGN(64) hash[32];
uint8_t _ALIGN(64) data[88];
char *noncestr, *hashhex;
int idnonce = work->submit_nonce_id;

memcpy(&data[0], work->data, 88);

if (opt_algo == ALGO_WILDKECCAK) {
// 64 bits nonce
memcpy(&data[1], work->nonces, 8);
// pass if the previous hash is not the current previous hash
if(!submit_old && memcmp(&work->data[3], &g_work.data[3], 28)) {
if (opt_debug) applog(LOG_DEBUG, "stale work detected", work->sharediff, work->targetdiff);
if (opt_debug) applog(LOG_DEBUG, "stale work detected");
pool->stales_count++;
return true;
return false;
}
noncestr = bin2hex((unsigned char*) &data[1], 8);
memcpy(&last_found_nonce, work->nonces, 8); // "nonce":"5794ec8000000000" => 0x0000000080ec9457
// "nonce":"5794ec8000000000" => 0x0000000080ec9457
memcpy(&last_found_nonce, work->nonces, 8);
wildkeccak_hash(hash, data, NULL, 0);
work_set_target_ratio(work, (uint32_t*) hash);
}

else if (opt_algo == ALGO_CRYPTOLIGHT) {
uint32_t nonce;
memcpy(&nonce, &data[39], 4);
uint32_t nonce = work->nonces[idnonce];
noncestr = bin2hex((unsigned char*) &nonce, 4);
last_found_nonce = nonce;
cryptolight_hash(hash, data, 76);
work_set_target_ratio(work, (uint32_t*) hash);
}

else if (opt_algo == ALGO_CRYPTONIGHT) {
uint32_t nonce;
memcpy(&nonce, &data[39], 4);
uint32_t nonce = work->nonces[idnonce];
noncestr = bin2hex((unsigned char*) &nonce, 4);
last_found_nonce = nonce;
cryptonight_hash(hash, data, 76);
work_set_target_ratio(work, (uint32_t*) hash);
}

//applog(LOG_DEBUG, "submit diff %g > %g", work->sharediff, work->targetdiff);
//applog_hex(data, 81);
//applog_hex(hash, 32);
if (hash[31] != 0)
return true; // prevent bad hashes
return false; // prevent bad hashes
hashhex = bin2hex((unsigned char*)hash, 32);

snprintf(s, sizeof(s), "{\"method\":\"submit\",\"params\":"
"{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}, \"id\":4}",
rpc2_id, work->job_id, noncestr, hashhex);
"{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}, \"id\":%u}",
rpc2_id, work->job_id, noncestr, hashhex, stratum.job.shares_count + 10);

free(hashhex);
free(noncestr);

gettimeofday(&stratum.tv_submit, NULL);

if(!stratum_send_line(&stratum, s)) {
applog(LOG_ERR, "submit_upstream_work stratum_send_line failed");
applog(LOG_ERR, "%s stratum_send_line failed", __func__);
return false;
}

stratum.sharediff = target_to_diff_rpc2((uint32_t*)hash);
//stratum.sharediff = target_to_diff_rpc2((uint32_t*)hash);
stratum.sharediff = work->sharediff[idnonce];

return true;
}
@@ -892,14 +895,14 @@ void GetScratchpad()
pscratchpad_buff = (uint64_t*) mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0);
if(pscratchpad_buff == MAP_FAILED)
{
applog(LOG_INFO, "hugetlb not available");
if(opt_debug) applog(LOG_DEBUG, "hugetlb not available");
pscratchpad_buff = (uint64_t*) malloc(sz);
if(!pscratchpad_buff) {
applog(LOG_ERR, "Scratchpad allocation failed");
exit(1);
}
} else {
applog(LOG_INFO, "using hugetlb");
if(opt_debug) applog(LOG_DEBUG, "using hugetlb");
}
madvise(pscratchpad_buff, sz, MADV_RANDOM | MADV_WILLNEED | MADV_HUGEPAGE);
mlock(pscratchpad_buff, sz);
@@ -1187,9 +1190,9 @@ bool rpc2_stratum_authorize(struct stratum_ctx *sctx, const char *user, const ch
bool rpc2_stratum_request_job(struct stratum_ctx *sctx)
{
json_t *val = NULL, *res_val, *err_val;
char *sret;
json_error_t err;
bool ret = false;
char *sret;
char *s = (char*) calloc(1, 10*2048);
if (!s) {
applog(LOG_ERR, "Stratum job OOM!");

0 comments on commit 242aa41

Please sign in to comment.
You can’t perform that action at this time.