|
|
@@ -184,7 +184,6 @@ int total_accepted, total_rejected;
|
|
|
int total_getworks, total_stale, total_discarded;
|
|
|
static int total_queued;
|
|
|
unsigned int new_blocks;
|
|
|
-static unsigned int work_block;
|
|
|
unsigned int found_blocks;
|
|
|
|
|
|
unsigned int local_work;
|
|
|
@@ -205,6 +204,7 @@ static bool curses_active;
|
|
|
|
|
|
static char current_block[37];
|
|
|
static char *current_hash;
|
|
|
+static uint32_t current_block_id;
|
|
|
static char datestamp[40];
|
|
|
static char blocktime[30];
|
|
|
|
|
|
@@ -2161,14 +2161,25 @@ static bool stale_work(struct work *work, bool share)
|
|
|
struct timeval now;
|
|
|
time_t work_expiry;
|
|
|
struct pool *pool;
|
|
|
+ uint32_t block_id;
|
|
|
int getwork_delay;
|
|
|
|
|
|
if (work->mandatory)
|
|
|
return false;
|
|
|
|
|
|
+ block_id = ((uint32_t*)work->data)[1];
|
|
|
pool = work->pool;
|
|
|
|
|
|
if (share) {
|
|
|
+ /* If the share isn't on this pool's latest block, it's stale */
|
|
|
+ if (pool->block_id != block_id)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ /* If the pool doesn't want old shares, then any found in work before
|
|
|
+ * the most recent longpoll is stale */
|
|
|
+ if ((!pool->submit_old) && work->work_restart_id != pool->work_restart_id)
|
|
|
+ return true;
|
|
|
+
|
|
|
/* Technically the rolltime should be correct but some pools
|
|
|
* advertise a broken expire= that is lower than a meaningful
|
|
|
* scantime */
|
|
|
@@ -2177,6 +2188,14 @@ static bool stale_work(struct work *work, bool share)
|
|
|
else
|
|
|
work_expiry = opt_expiry;
|
|
|
} else {
|
|
|
+ /* If this work isn't for the latest Bitcoin block, it's stale */
|
|
|
+ if (current_block_id != block_id)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ /* If the pool has asked us to restart since this work, it's stale */
|
|
|
+ if (work->work_restart_id != pool->work_restart_id)
|
|
|
+ return true;
|
|
|
+
|
|
|
/* Don't keep rolling work right up to the expiration */
|
|
|
if (work->rolltime > opt_scantime)
|
|
|
work_expiry = (work->rolltime - opt_scantime) * 2 / 3 + opt_scantime;
|
|
|
@@ -2196,9 +2215,8 @@ static bool stale_work(struct work *work, bool share)
|
|
|
if ((now.tv_sec - work->tv_staged.tv_sec) >= work_expiry)
|
|
|
return true;
|
|
|
|
|
|
- if (work->work_block != work_block)
|
|
|
- return true;
|
|
|
-
|
|
|
+ /* If the user only wants strict failover, any work from a pool other than
|
|
|
+ * the current one is always considered stale */
|
|
|
if (opt_fail_only && !share && pool != current_pool() && pool->enabled != POOL_REJECTING)
|
|
|
return true;
|
|
|
|
|
|
@@ -2484,6 +2502,7 @@ static void set_curblock(char *hexstr, unsigned char *hash)
|
|
|
struct timeval tv_now;
|
|
|
char *old_hash;
|
|
|
|
|
|
+ current_block_id = ((uint32_t*)hash)[1];
|
|
|
strcpy(current_block, hexstr);
|
|
|
gettimeofday(&tv_now, NULL);
|
|
|
get_timestamp(blocktime, &tv_now);
|
|
|
@@ -2537,6 +2556,8 @@ static void test_work_current(struct work *work)
|
|
|
if (work->mandatory)
|
|
|
return;
|
|
|
|
|
|
+ uint32_t block_id = ((uint32_t*)(work->data))[1];
|
|
|
+
|
|
|
hexstr = bin2hex(work->data, 18);
|
|
|
if (unlikely(!hexstr)) {
|
|
|
applog(LOG_ERR, "stage_thread OOM");
|
|
|
@@ -2554,12 +2575,11 @@ static void test_work_current(struct work *work)
|
|
|
wr_lock(&blk_lock);
|
|
|
HASH_ADD_STR(blocks, hash, s);
|
|
|
wr_unlock(&blk_lock);
|
|
|
+ work->pool->block_id = block_id;
|
|
|
set_curblock(hexstr, work->data);
|
|
|
if (unlikely(++new_blocks == 1))
|
|
|
goto out_free;
|
|
|
|
|
|
- work_block++;
|
|
|
-
|
|
|
if (work->longpoll) {
|
|
|
applog(LOG_NOTICE, "LONGPOLL from pool %d detected new block",
|
|
|
work->pool->pool_no);
|
|
|
@@ -2569,14 +2589,18 @@ static void test_work_current(struct work *work)
|
|
|
else
|
|
|
applog(LOG_NOTICE, "New block detected on network");
|
|
|
restart_threads();
|
|
|
- } else if (work->longpoll) {
|
|
|
+ } else {
|
|
|
+ if (block_id == current_block_id)
|
|
|
+ work->pool->block_id = block_id;
|
|
|
+ if (work->longpoll) {
|
|
|
work->longpoll = false;
|
|
|
+ ++work->pool->work_restart_id;
|
|
|
if (work->pool == current_pool()) {
|
|
|
applog(LOG_NOTICE, "LONGPOLL from pool %d requested work restart",
|
|
|
work->pool->pool_no);
|
|
|
- work_block++;
|
|
|
restart_threads();
|
|
|
}
|
|
|
+ }
|
|
|
}
|
|
|
out_free:
|
|
|
free(hexstr);
|
|
|
@@ -2622,7 +2646,7 @@ static void *stage_thread(void *userdata)
|
|
|
ok = false;
|
|
|
break;
|
|
|
}
|
|
|
- work->work_block = work_block;
|
|
|
+ work->work_restart_id = work->pool->work_restart_id;
|
|
|
|
|
|
test_work_current(work);
|
|
|
|