|
|
@@ -101,8 +101,6 @@ void stratumsrv_send_set_difficulty(struct stratumsrv_conn * const conn, const f
|
|
|
bufferevent_write(bev, buf, bufsz);
|
|
|
}
|
|
|
|
|
|
-#define _ssm_gen_dummy_work work2d_gen_dummy_work
|
|
|
-
|
|
|
static
|
|
|
float stratumsrv_choose_share_pdiff(const struct stratumsrv_conn * const conn, const struct mining_algorithm * const malgo)
|
|
|
{
|
|
|
@@ -112,27 +110,75 @@ float stratumsrv_choose_share_pdiff(const struct stratumsrv_conn * const conn, c
|
|
|
return conn_pdiff;
|
|
|
}
|
|
|
|
|
|
+static void stratumsrv_boot_all_subscribed(const char *);
|
|
|
+static void _ssj_free(struct stratumsrv_job *);
|
|
|
+static void stratumsrv_job_pruner();
|
|
|
+
|
|
|
static
|
|
|
-bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
|
|
|
+bool stratumsrv_update_notify_str(struct pool * const pool)
|
|
|
{
|
|
|
+ const bool clean = _ssm_cur_job_work.pool ? stale_work(&_ssm_cur_job_work, true) : true;
|
|
|
+ struct timeval tv_now;
|
|
|
+
|
|
|
cg_rlock(&pool->data_lock);
|
|
|
|
|
|
+ if (!pool_has_usable_swork(pool))
|
|
|
+ {
|
|
|
+fail:
|
|
|
+ cg_runlock(&pool->data_lock);
|
|
|
+ applog(LOG_WARNING, "SSM: No usable 2D work upstream!");
|
|
|
+ if (clean)
|
|
|
+ stratumsrv_boot_all_subscribed("Current upstream pool does not have usable 2D work");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ timer_set_now(&tv_now);
|
|
|
+
|
|
|
+ {
|
|
|
+ struct work work;
|
|
|
+ work2d_gen_dummy_work_for_stale_check(&work, &pool->swork, &tv_now, NULL);
|
|
|
+
|
|
|
+ const bool is_stale = stale_work(&work, false);
|
|
|
+
|
|
|
+ clean_work(&work);
|
|
|
+
|
|
|
+ if (is_stale) {
|
|
|
+ cg_runlock(&pool->data_lock);
|
|
|
+ applog(LOG_DEBUG, "SSM: Ignoring work update notification while pool %d has stale swork", pool->pool_no);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
struct stratumsrv_conn *conn;
|
|
|
const struct stratum_work * const swork = &pool->swork;
|
|
|
const int n2size = pool->swork.n2size;
|
|
|
+ const size_t coinb2_offset = swork->nonce2_offset + n2size;
|
|
|
+ const size_t coinb2_len = bytes_len(&swork->coinbase) - swork->nonce2_offset - n2size;
|
|
|
+
|
|
|
+ if (_ssm_last_ssj &&
|
|
|
+ !(memcmp(&swork->header1[0], &_ssm_last_ssj->swork.header1[0], 0x24)
|
|
|
+ || swork->nonce2_offset != _ssm_last_ssj->swork.nonce2_offset
|
|
|
+ || bytes_len(&swork->coinbase) != bytes_len(&_ssm_last_ssj->swork.coinbase)
|
|
|
+ || memcmp(bytes_buf(&swork->coinbase), bytes_buf(&_ssm_last_ssj->swork.coinbase), swork->nonce2_offset)
|
|
|
+ || memcmp(&bytes_buf(&swork->coinbase)[coinb2_offset], &bytes_buf(&_ssm_last_ssj->swork.coinbase)[coinb2_offset], coinb2_len)
|
|
|
+ || memcmp(swork->diffbits, _ssm_last_ssj->swork.diffbits, 4)
|
|
|
+ )) {
|
|
|
+ cg_runlock(&pool->data_lock);
|
|
|
+ applog(LOG_DEBUG, "SSM: Updating with (near?-)identical work2d; skipping...");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
char my_job_id[33];
|
|
|
int i;
|
|
|
struct stratumsrv_job *ssj;
|
|
|
ssize_t n2pad = work2d_pad_xnonce_size(swork);
|
|
|
if (n2pad < 0)
|
|
|
{
|
|
|
- cg_runlock(&pool->data_lock);
|
|
|
- return false;
|
|
|
+ goto fail;
|
|
|
}
|
|
|
size_t coinb1in_lenx = swork->nonce2_offset * 2;
|
|
|
size_t n2padx = n2pad * 2;
|
|
|
size_t coinb1_lenx = coinb1in_lenx + n2padx;
|
|
|
- size_t coinb2_len = bytes_len(&swork->coinbase) - swork->nonce2_offset - n2size;
|
|
|
size_t coinb2_lenx = coinb2_len * 2;
|
|
|
sprintf(my_job_id, "%"PRIx64"-%"PRIx64, (uint64_t)time(NULL), _ssm_jobid++);
|
|
|
// NOTE: The buffer has up to 2 extra/unused bytes:
|
|
|
@@ -147,7 +193,7 @@ bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
|
|
|
bin2hex(coinb1, bytes_buf(&swork->coinbase), swork->nonce2_offset);
|
|
|
work2d_pad_xnonce(&coinb1[coinb1in_lenx], swork, true);
|
|
|
coinb1[coinb1_lenx] = '\0';
|
|
|
- bin2hex(coinb2, &bytes_buf(&swork->coinbase)[swork->nonce2_offset + n2size], coinb2_len);
|
|
|
+ bin2hex(coinb2, &bytes_buf(&swork->coinbase)[coinb2_offset], coinb2_len);
|
|
|
p += sprintf(p, "{\"params\":[\"%s\",\"%s\",\"%s\",\"%s\",[", my_job_id, prevhash, coinb1, coinb2);
|
|
|
for (i = 0; i < swork->merkles; ++i)
|
|
|
{
|
|
|
@@ -172,17 +218,30 @@ bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
|
|
|
*ssj = (struct stratumsrv_job){
|
|
|
.my_job_id = strdup(my_job_id),
|
|
|
};
|
|
|
- timer_set_now(&ssj->tv_prepared);
|
|
|
+ ssj->tv_prepared = tv_now;
|
|
|
stratum_work_cpy(&ssj->swork, swork);
|
|
|
|
|
|
cg_runlock(&pool->data_lock);
|
|
|
|
|
|
- ssj->swork.data_lock_p = NULL;
|
|
|
+ if (clean)
|
|
|
+ {
|
|
|
+ struct stratumsrv_job *ssj, *tmp;
|
|
|
+
|
|
|
+ applog(LOG_DEBUG, "SSM: Current replacing job stale, pruning all jobs");
|
|
|
+ HASH_ITER(hh, _ssm_jobs, ssj, tmp)
|
|
|
+ {
|
|
|
+ HASH_DEL(_ssm_jobs, ssj);
|
|
|
+ _ssj_free(ssj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ stratumsrv_job_pruner();
|
|
|
+
|
|
|
HASH_ADD_KEYPTR(hh, _ssm_jobs, ssj->my_job_id, strlen(ssj->my_job_id), ssj);
|
|
|
|
|
|
if (likely(_ssm_cur_job_work.pool))
|
|
|
clean_work(&_ssm_cur_job_work);
|
|
|
- _ssm_gen_dummy_work(&_ssm_cur_job_work, &ssj->swork, &ssj->tv_prepared, NULL, 0);
|
|
|
+ work2d_gen_dummy_work_for_stale_check(&_ssm_cur_job_work, &ssj->swork, &ssj->tv_prepared, NULL);
|
|
|
|
|
|
_ssm_notify_sz = p - buf;
|
|
|
assert(_ssm_notify_sz <= bufsz);
|
|
|
@@ -329,7 +388,6 @@ static
|
|
|
void _stratumsrv_update_notify(evutil_socket_t fd, short what, __maybe_unused void *p)
|
|
|
{
|
|
|
struct pool *pool = current_pool();
|
|
|
- bool clean;
|
|
|
|
|
|
if (fd == _ssm_update_notifier[0])
|
|
|
{
|
|
|
@@ -338,37 +396,8 @@ void _stratumsrv_update_notify(evutil_socket_t fd, short what, __maybe_unused vo
|
|
|
applog(LOG_DEBUG, "SSM: Update triggered by notifier");
|
|
|
}
|
|
|
|
|
|
- clean = _ssm_cur_job_work.pool ? stale_work(&_ssm_cur_job_work, true) : true;
|
|
|
- if (clean)
|
|
|
- {
|
|
|
- struct stratumsrv_job *ssj, *tmp;
|
|
|
-
|
|
|
- applog(LOG_DEBUG, "SSM: Current replacing job stale, pruning all jobs");
|
|
|
- HASH_ITER(hh, _ssm_jobs, ssj, tmp)
|
|
|
- {
|
|
|
- HASH_DEL(_ssm_jobs, ssj);
|
|
|
- _ssj_free(ssj);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- stratumsrv_job_pruner();
|
|
|
-
|
|
|
- if (!pool_has_usable_swork(pool))
|
|
|
- {
|
|
|
- applog(LOG_WARNING, "SSM: No usable 2D work upstream!");
|
|
|
- if (clean)
|
|
|
- stratumsrv_boot_all_subscribed("Current upstream pool does not have usable 2D work");
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- if (!stratumsrv_update_notify_str(pool, clean))
|
|
|
- {
|
|
|
- applog(LOG_WARNING, "SSM: Failed to subdivide upstream stratum notify!");
|
|
|
- if (clean)
|
|
|
- stratumsrv_boot_all_subscribed("Current upstream pool does not have active stratum");
|
|
|
- }
|
|
|
+ stratumsrv_update_notify_str(pool);
|
|
|
|
|
|
-out: ;
|
|
|
struct timeval tv_scantime = {
|
|
|
.tv_sec = opt_scantime,
|
|
|
};
|