Browse Source

Refactor stale_work function to only flag actual stale shares

- Shares are only stale if one of these is true:
- - they are for a prior Bitcoin prevblock than last received from this pool
- - the pool has longpolled since the work was issued, and doesn't accept old shares
- - the full expiry time has passed since receiving the work
- Work is only stale if one of these is true:
- - it isn't for the absolute latest known Bitcoin block
- - the pool has requested work restart (longpoll)
- - at least scantime + 2/3 of expire= difference has passed since received
- - failover-only is enabled and we have switched to another pool
Luke Dashjr 13 years ago
parent
commit
b69181f4d1
2 changed files with 36 additions and 10 deletions
  1. 33 9
      cgminer.c
  2. 3 1
      miner.h

+ 33 - 9
cgminer.c

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

+ 3 - 1
miner.h

@@ -678,6 +678,8 @@ struct pool {
 	bool submit_old;
 	bool submit_old;
 	bool removed;
 	bool removed;
 	bool lp_started;
 	bool lp_started;
+	unsigned char	work_restart_id;
+	uint32_t	block_id;
 
 
 	char *hdr_path;
 	char *hdr_path;
 	char *lp_url;
 	char *lp_url;
@@ -739,7 +741,7 @@ struct work {
 	bool		mandatory;
 	bool		mandatory;
 	bool		block;
 	bool		block;
 
 
-	unsigned int	work_block;
+	unsigned char	work_restart_id;
 	int		id;
 	int		id;
 	UT_hash_handle hh;
 	UT_hash_handle hh;