Browse Source

enhance double scan checks

master
Tanguy Pruvot 10 years ago
parent
commit
806c3e8691
  1. 19
      blake32.cu
  2. 93
      cpu-miner.c
  3. 89
      hashlog.cpp
  4. 1
      miner.h
  5. 2
      util.c

19
blake32.cu

@ -29,8 +29,9 @@ extern "C" void blake32hash(void *output, const void *input)
#include "cuda_helper.h" #include "cuda_helper.h"
// in cpu-miner.c // in cpu-miner.c
extern bool opt_n_threads;
extern bool opt_benchmark; extern bool opt_benchmark;
extern bool opt_debug; //extern bool opt_debug;
extern int device_map[8]; extern int device_map[8];
extern cudaError_t MyStreamSynchronize(cudaStream_t stream, int situation, int thr_id); extern cudaError_t MyStreamSynchronize(cudaStream_t stream, int situation, int thr_id);
@ -279,7 +280,9 @@ extern "C" int scanhash_blake32(int thr_id, uint32_t *pdata, const uint32_t *pta
((uint32_t*)ptarget)[7] = 0x00000f; ((uint32_t*)ptarget)[7] = 0x00000f;
if (!init[thr_id]) { if (!init[thr_id]) {
CUDA_SAFE_CALL(cudaSetDevice(device_map[thr_id])); if (opt_n_threads > 1) {
CUDA_SAFE_CALL(cudaSetDevice(device_map[thr_id]));
}
CUDA_SAFE_CALL(cudaMallocHost(&h_resNounce[thr_id], sizeof(uint32_t))); CUDA_SAFE_CALL(cudaMallocHost(&h_resNounce[thr_id], sizeof(uint32_t)));
CUDA_SAFE_CALL(cudaMalloc(&d_resNounce[thr_id], sizeof(uint32_t))); CUDA_SAFE_CALL(cudaMalloc(&d_resNounce[thr_id], sizeof(uint32_t)));
init[thr_id] = true; init[thr_id] = true;
@ -288,11 +291,6 @@ extern "C" int scanhash_blake32(int thr_id, uint32_t *pdata, const uint32_t *pta
if (throughput < (TPB * 2048)) if (throughput < (TPB * 2048))
applog(LOG_WARNING, "throughput=%u, start=%x, max=%x", throughput, first_nonce, max_nonce); applog(LOG_WARNING, "throughput=%u, start=%x, max=%x", throughput, first_nonce, max_nonce);
if (max_nonce < first_nonce) {
applog(LOG_ERR, "start=%x > end=%x !", first_nonce, max_nonce);
return 0;
}
blake256_cpu_setBlock_80(pdata, (void*)ptarget); blake256_cpu_setBlock_80(pdata, (void*)ptarget);
do { do {
@ -340,5 +338,12 @@ extern "C" int scanhash_blake32(int thr_id, uint32_t *pdata, const uint32_t *pta
exit_scan: exit_scan:
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = pdata[19] - first_nonce + 1;
// reset the device to allow multiple instances
if (opt_n_threads == 1) {
CUDA_SAFE_CALL(cudaDeviceReset());
init[thr_id] = false;
}
// wait proper end of all threads
cudaDeviceSynchronize();
return rc; return rc;
} }

93
cpu-miner.c

@ -187,7 +187,7 @@ static int opt_scantime = 5;
static json_t *opt_config; static json_t *opt_config;
static const bool opt_time = true; static const bool opt_time = true;
static sha256_algos opt_algo = ALGO_HEAVY; static sha256_algos opt_algo = ALGO_HEAVY;
static int opt_n_threads = 0; int opt_n_threads = 0;
static double opt_difficulty = 1; // CH static double opt_difficulty = 1; // CH
bool opt_trust_pool = false; bool opt_trust_pool = false;
uint16_t opt_vote = 9999; uint16_t opt_vote = 9999;
@ -411,11 +411,11 @@ err_out:
return false; return false;
} }
static void share_result(int result, const char *reason) static int share_result(int result, const char *reason)
{ {
char s[345]; char s[345];
double hashrate; double hashrate;
int i; int i, ret = 0;
hashrate = 0.; hashrate = 0.;
pthread_mutex_lock(&stats_lock); pthread_mutex_lock(&stats_lock);
@ -434,9 +434,15 @@ static void share_result(int result, const char *reason)
(result ? CL_GRN "yay!!!" : CL_RED "booooo") (result ? CL_GRN "yay!!!" : CL_RED "booooo")
: (result ? "(yay!!!)" : "(booooo)")); : (result ? "(yay!!!)" : "(booooo)"));
if (reason) { if (reason && !opt_quiet) {
applog(LOG_WARNING, "reject reason: %s", reason); applog(LOG_WARNING, "reject reason: %s", reason);
if (strncmp(reason, "low difficulty share", 20) == 0) {
opt_difficulty = (opt_difficulty * 2.0) / 3.0;
applog(LOG_WARNING, "factor reduced to : %0.2f", opt_difficulty);
return 0;
}
} }
return 1;
} }
static bool submit_upstream_work(CURL *curl, struct work *work) static bool submit_upstream_work(CURL *curl, struct work *work)
@ -472,8 +478,10 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
sent = hashlog_already_submittted(work->job_id, nonce); sent = hashlog_already_submittted(work->job_id, nonce);
if (sent > 0) { if (sent > 0) {
sent = (uint32_t) time(NULL) - sent; sent = (uint32_t) time(NULL) - sent;
if (!opt_quiet) if (!opt_quiet) {
applog(LOG_WARNING, "skip submit, nonce %s was already sent %u seconds ago", noncestr, sent); applog(LOG_WARNING, "skip submit, nonce %s was already sent %u seconds ago", noncestr, sent);
hashlog_dump_job(work->job_id);
}
rc = true; rc = true;
goto out; goto out;
} }
@ -481,11 +489,11 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
if (opt_algo == ALGO_HEAVY) { if (opt_algo == ALGO_HEAVY) {
sprintf(s, sprintf(s,
"{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}", "{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}",
rpc_user, work->job_id, xnonce2str, ntimestr, noncestr, nvotestr); rpc_user, work->job_id + 8, xnonce2str, ntimestr, noncestr, nvotestr);
} else { } else {
sprintf(s, sprintf(s,
"{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}", "{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}",
rpc_user, work->job_id, xnonce2str, ntimestr, noncestr); rpc_user, work->job_id + 8, xnonce2str, ntimestr, noncestr);
} }
free(ntimestr); free(ntimestr);
free(noncestr); free(noncestr);
@ -528,7 +536,8 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
res = json_object_get(val, "result"); res = json_object_get(val, "result");
reason = json_object_get(val, "reject-reason"); reason = json_object_get(val, "reject-reason");
share_result(json_is_true(res), reason ? json_string_value(reason) : NULL); if (!share_result(json_is_true(res), reason ? json_string_value(reason) : NULL))
hashlog_purge_job(work->job_id);
json_decref(val); json_decref(val);
} }
@ -768,7 +777,9 @@ static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
pthread_mutex_lock(&sctx->work_lock); pthread_mutex_lock(&sctx->work_lock);
strcpy(work->job_id, sctx->job.job_id); // store the job ntime as high part of jobid
snprintf(work->job_id, sizeof(work->job_id), "%07x %s",
be32dec(sctx->job.ntime) & 0xfffffff, sctx->job.job_id);
work->xnonce2_len = sctx->xnonce2_size; work->xnonce2_len = sctx->xnonce2_size;
memcpy(work->xnonce2, sctx->job.xnonce2, sctx->xnonce2_size); memcpy(work->xnonce2, sctx->job.xnonce2, sctx->xnonce2_size);
@ -884,8 +895,6 @@ static void *miner_thread(void *userdata)
int wcmplen = 76; int wcmplen = 76;
uint32_t *nonceptr = (uint32_t*) (((char*)work.data) + wcmplen); uint32_t *nonceptr = (uint32_t*) (((char*)work.data) + wcmplen);
applog(LOG_WARNING, "job %s %08x", g_work.job_id, (*nonceptr));
if (have_stratum) { if (have_stratum) {
while (time(NULL) >= (g_work_time + opt_scantime) && !work_done) while (time(NULL) >= (g_work_time + opt_scantime) && !work_done)
usleep(500*1000); usleep(500*1000);
@ -909,29 +918,34 @@ static void *miner_thread(void *userdata)
g_work_time = time(NULL); g_work_time = time(NULL);
} }
} }
if (memcmp(work.data, g_work.data, wcmplen)) { if (memcmp(work.data, g_work.data, 72)) { // wcmplen)) {
/* if (opt_debug) {
applog(LOG_NOTICE, "job %s %08x work change", g_work.job_id, (*nonceptr)); applog(LOG_DEBUG, "job %s %08x work updated", g_work.job_id, (*nonceptr));
for (int n=0; n<wcmplen; n+=8) { for (int n=0; n<wcmplen; n+=8) {
if (memcmp(work.data + n, g_work.data + n, 8)) { if (memcmp(work.data + n, g_work.data + n, 8)) {
applog(LOG_ERR, "diff detected at offset %d", n); applog(LOG_DEBUG, "diff detected at offset %d", n);
applog_hash(work.data + n); applog_hash((uint8_t*) work.data + n);
applog_hash(g_work.data + n); applog_hash((uint8_t*) g_work.data + n);
}
} }
} }
*/
memcpy(&work, &g_work, sizeof(struct work)); memcpy(&work, &g_work, sizeof(struct work));
(*nonceptr) = (0xffffffffUL / opt_n_threads) * thr_id; // 0 if single thr (*nonceptr) = (0xffffffffUL / opt_n_threads) * thr_id; // 0 if single thr
/* } else if (memcmp(work.target, g_work.target, sizeof(work.target))) { } else if (memcmp(work.target, g_work.target, sizeof(work.target))) {
applog(LOG_NOTICE, "job %s %08x target change", g_work.job_id, (*nonceptr)); if (opt_debug) {
applog(LOG_DEBUG, "job %s %08x target change", g_work.job_id, (*nonceptr));
applog_hash((uint8_t*) work.target);
applog_hash((uint8_t*) g_work.target);
}
memcpy(work.target, g_work.target, sizeof(work.target)); memcpy(work.target, g_work.target, sizeof(work.target));
(*nonceptr) = (0xffffffffUL / opt_n_threads) * thr_id; // 0 if single thr (*nonceptr) = (0xffffffffUL / opt_n_threads) * thr_id; // 0 if single thr
*/
} else } else
(*nonceptr)++; //?? (*nonceptr)++; //??
pthread_mutex_unlock(&g_work_lock); pthread_mutex_unlock(&g_work_lock);
work_restart[thr_id].restart = 0; work_restart[thr_id].restart = 0;
applog(LOG_WARNING, "job %s %08x", g_work.job_id, (*nonceptr));
/* adjust max_nonce to meet target scan time */ /* adjust max_nonce to meet target scan time */
if (have_stratum) if (have_stratum)
max64 = LP_SCANTIME; max64 = LP_SCANTIME;
@ -959,7 +973,7 @@ static void *miner_thread(void *userdata)
start_nonce = *nonceptr; start_nonce = *nonceptr;
/* do not recompute something already scanned */ /* do not recompute something already scanned */
if (opt_algo == ALGO_BLAKE) { if (opt_algo == ALGO_BLAKE && opt_n_threads == 1) {
union { union {
uint64_t data; uint64_t data;
uint32_t scanned[2]; uint32_t scanned[2];
@ -967,24 +981,29 @@ static void *miner_thread(void *userdata)
range.data = hashlog_get_scan_range(work.job_id); range.data = hashlog_get_scan_range(work.job_id);
if (range.data) { if (range.data) {
bool stall = false;
if (range.scanned[0] == 1 && range.scanned[1] == 0xFFFFFFFFUL) { if (range.scanned[0] == 1 && range.scanned[1] == 0xFFFFFFFFUL) {
applog(LOG_WARNING, "detected a rescan of fully scanned job!"); applog(LOG_WARNING, "detected a rescan of fully scanned job!");
} else if (range.scanned[0] > 0 && range.scanned[1] > 0) { } else if (range.scanned[0] > 0 && range.scanned[1] > 0 && range.scanned[1] < 0xFFFFFFF0UL) {
/* continue scan the end */ /* continue scan the end */
start_nonce = range.scanned[1] + 1; start_nonce = range.scanned[1] + 1;
applog(LOG_WARNING, "scan the next part %x + 1", range.scanned[1]); //applog(LOG_DEBUG, "scan the next part %x + 1 (%x-%x)", range.scanned[1], range.scanned[0], range.scanned[1]);
} else if (range.scanned[0] > 1) {
/* dont scan the beginning... make loops */
//end_nonce = range.scanned[0] - 1;
//applog(LOG_WARNING, "scan the missing part 0 -> %x", end_nonce);
} }
if (start_nonce == work.scanned_from) {
/* to prevent stales, if last was in the same range */ stall = (start_nonce == work.scanned_from && end_nonce == work.scanned_to);
applog(LOG_ERR, "detected a staled job!"); stall |= (start_nonce == work.scanned_from && start_nonce == range.scanned[1] + 1);
//(*nonceptr) = end_nonce + 1; stall |= (start_nonce > range.scanned[0] && start_nonce < range.scanned[1]);
//work_done = true;
//continue; if (stall) {
start_nonce = range.scanned[1] + 1; if (opt_algo)
applog(LOG_DEBUG, "job done, wait for a new one...");
work_restart[thr_id].restart = 1;
hashlog_purge_old();
// wait a bit for a new job...
usleep(1500*1000);
(*nonceptr) = end_nonce + 1;
work_done = true;
continue;
} }
} }
} }

89
hashlog.cpp

@ -9,10 +9,12 @@
#define MK_HI64(u32) (0x100000000ULL * u32) #define MK_HI64(u32) (0x100000000ULL * u32)
struct hashlog_data { struct hashlog_data {
uint32_t ntime; uint32_t tm_sent;
uint32_t scanned_from; uint32_t scanned_from;
uint32_t scanned_to; uint32_t scanned_to;
uint32_t last_from; uint32_t last_from;
uint32_t tm_add;
uint32_t tm_upd;
}; };
static std::map<uint64_t, hashlog_data> tlastshares; static std::map<uint64_t, hashlog_data> tlastshares;
@ -41,7 +43,7 @@ extern "C" uint32_t hashlog_already_submittted(char* jobid, uint32_t nonce)
ret = hashlog_get_last_sent(jobid); ret = hashlog_get_last_sent(jobid);
} else if (tlastshares.find(key) != tlastshares.end()) { } else if (tlastshares.find(key) != tlastshares.end()) {
hashlog_data data = tlastshares[key]; hashlog_data data = tlastshares[key];
ret = data.ntime; ret = data.tm_sent;
} }
return ret; return ret;
} }
@ -56,7 +58,9 @@ extern "C" void hashlog_remember_submit(char* jobid, uint32_t nonce)
struct hashlog_data data; struct hashlog_data data;
data = tlastshares[keyall]; data = tlastshares[keyall];
data.ntime = (uint32_t) time(NULL); data.tm_upd = data.tm_sent = (uint32_t) time(NULL);
if (data.tm_add == 0)
data.tm_add = data.tm_upd;
tlastshares[key] = data; tlastshares[key] = data;
} }
@ -67,24 +71,38 @@ extern "C" void hashlog_remember_scan_range(char* jobid, uint32_t scanned_from,
{ {
uint64_t njobid = hextouint(jobid); uint64_t njobid = hextouint(jobid);
uint64_t keyall = (njobid << 32); uint64_t keyall = (njobid << 32);
uint64_t range = hashlog_get_scan_range(jobid);
struct hashlog_data data; struct hashlog_data data;
// global scan range of a job // global scan range of a job
data = tlastshares[keyall]; data = tlastshares[keyall];
if (hashlog_get_scan_range(jobid) == 0) { if (range == 0) {
memset(&data, 0, sizeof(data)); memset(&data, 0, sizeof(data));
} else {
// get min and max from all sent records
data.scanned_from = LO_DWORD(range);
data.scanned_to = HI_DWORD(range);
} }
if (data.scanned_from == 0 || scanned_to == (data.scanned_from - 1)) if (data.tm_add == 0)
data.scanned_from = scanned_from ? scanned_from : 1; // min 1 data.tm_add = (uint32_t) time(NULL);
if (data.scanned_to == 0 || scanned_from == data.scanned_to + 1)
data.scanned_to = scanned_to;
data.last_from = scanned_from; data.last_from = scanned_from;
if (scanned_from < scanned_to) {
if (data.scanned_from == 0)
data.scanned_from = scanned_from ? scanned_from : 1; // min 1
else if (scanned_from < data.scanned_from) // || scanned_to == (data.scanned_from - 1)
data.scanned_from = scanned_from;
if (data.scanned_to == 0 || scanned_from == data.scanned_to + 1)
data.scanned_to = scanned_to;
}
data.tm_upd = (uint32_t) time(NULL);
tlastshares[keyall] = data; tlastshares[keyall] = data;
applog(LOG_BLUE, "job %s range : %x %x -> %x %x (%x)", jobid, applog(LOG_BLUE, "job %s range : %x %x -> %x %x", jobid,
scanned_from, scanned_to, data.scanned_from, data.scanned_to, data.ntime);/* */ scanned_from, scanned_to, data.scanned_from, data.scanned_to);/* */
} }
/** /**
@ -96,15 +114,21 @@ extern "C" uint64_t hashlog_get_scan_range(char* jobid)
uint64_t ret = 0; uint64_t ret = 0;
uint64_t njobid = hextouint(jobid); uint64_t njobid = hextouint(jobid);
uint64_t keypfx = (njobid << 32); uint64_t keypfx = (njobid << 32);
struct hashlog_data data;
data.scanned_from = 0;
data.scanned_to = 0;
std::map<uint64_t, hashlog_data>::iterator i = tlastshares.begin(); std::map<uint64_t, hashlog_data>::iterator i = tlastshares.begin();
while (i != tlastshares.end()) { while (i != tlastshares.end()) {
if ((keypfx & i->first) == keypfx) { if ((keypfx & i->first) == keypfx && i->second.scanned_to > ret) {
hashlog_data data = i->second; if (i->second.scanned_to > data.scanned_to)
ret = data.scanned_from; data.scanned_to = i->second.scanned_to;
ret += MK_HI64(data.scanned_to); if (i->second.scanned_from < data.scanned_from || data.scanned_from == 0)
data.scanned_from = i->second.scanned_from;
} }
i++; i++;
} }
ret = data.scanned_from;
ret += MK_HI64(data.scanned_to);
return ret; return ret;
} }
@ -119,7 +143,7 @@ extern "C" uint32_t hashlog_get_last_sent(char* jobid)
uint64_t keypfx = (njobid << 32); uint64_t keypfx = (njobid << 32);
std::map<uint64_t, hashlog_data>::iterator i = tlastshares.begin(); std::map<uint64_t, hashlog_data>::iterator i = tlastshares.begin();
while (i != tlastshares.end()) { while (i != tlastshares.end()) {
if ((keypfx & i->first) == keypfx && i->second.ntime > 0) { if ((keypfx & i->first) == keypfx && i->second.tm_sent > 0) {
nonce = LO_DWORD(i->first); nonce = LO_DWORD(i->first);
} }
i++; i++;
@ -128,18 +152,25 @@ extern "C" uint32_t hashlog_get_last_sent(char* jobid)
} }
/** /**
* Remove entries of a job... not used yet * Remove entries of a job...
*/ */
extern "C" void hashlog_purge_job(char* jobid) extern "C" void hashlog_purge_job(char* jobid)
{ {
int deleted = 0;
uint64_t njobid = hextouint(jobid); uint64_t njobid = hextouint(jobid);
uint64_t keypfx = (njobid << 32); uint64_t keypfx = (njobid << 32);
uint32_t sz = tlastshares.size();
std::map<uint64_t, hashlog_data>::iterator i = tlastshares.begin(); std::map<uint64_t, hashlog_data>::iterator i = tlastshares.begin();
while (i != tlastshares.end()) { while (i != tlastshares.end()) {
if ((keypfx & i->first) == keypfx) if ((keypfx & i->first) == keypfx) {
deleted++;
tlastshares.erase(i); tlastshares.erase(i);
}
i++; i++;
} }
if (opt_debug && deleted) {
applog(LOG_DEBUG, "hashlog: purge job %s, del %d/%d", jobid, deleted, sz);
}
} }
/** /**
@ -152,7 +183,7 @@ extern "C" void hashlog_purge_old(void)
uint32_t sz = tlastshares.size(); uint32_t sz = tlastshares.size();
std::map<uint64_t, hashlog_data>::iterator i = tlastshares.begin(); std::map<uint64_t, hashlog_data>::iterator i = tlastshares.begin();
while (i != tlastshares.end()) { while (i != tlastshares.end()) {
if ((now - i->second.ntime) > LOG_PURGE_TIMEOUT) { if ((now - i->second.tm_sent) > LOG_PURGE_TIMEOUT) {
deleted++; deleted++;
tlastshares.erase(i); tlastshares.erase(i);
} }
@ -170,3 +201,25 @@ extern "C" void hashlog_purge_all(void)
{ {
tlastshares.clear(); tlastshares.clear();
} }
/**
* Can be used to debug...
*/
extern "C" void hashlog_dump_job(char* jobid)
{
int deleted = 0;
uint64_t njobid = hextouint(jobid);
uint64_t keypfx = (njobid << 32);
uint32_t sz = tlastshares.size();
std::map<uint64_t, hashlog_data>::iterator i = tlastshares.begin();
while (i != tlastshares.end()) {
if ((keypfx & i->first) == keypfx) {
applog(LOG_BLUE, "job %s range : %x %x %s added %x upd %x", jobid,
i->second.scanned_from, i->second.scanned_to,
i->second.tm_sent ? "sent" : "",
i->second.tm_add, i->second.tm_upd);/* */
}
i++;
}
}

1
miner.h

@ -399,6 +399,7 @@ uint64_t hashlog_get_scan_range(char* jobid);
void hashlog_purge_old(void); void hashlog_purge_old(void);
void hashlog_purge_job(char* jobid); void hashlog_purge_job(char* jobid);
void hashlog_purge_all(void); void hashlog_purge_all(void);
void hashlog_dump_job(char* jobid);
struct thread_q; struct thread_q;

2
util.c

@ -115,7 +115,7 @@ void applog(int prio, const char *fmt, ...)
case LOG_WARNING: color = CL_YLW; break; case LOG_WARNING: color = CL_YLW; break;
case LOG_NOTICE: color = CL_WHT; break; case LOG_NOTICE: color = CL_WHT; break;
case LOG_INFO: color = ""; break; case LOG_INFO: color = ""; break;
case LOG_DEBUG: color = ""; break; case LOG_DEBUG: color = CL_SIL; break;
case LOG_BLUE: case LOG_BLUE:
prio = LOG_NOTICE; prio = LOG_NOTICE;

Loading…
Cancel
Save