| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -47,7 +47,7 @@ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define DB_VLOCK "1" | 
					 | 
					 | 
					 | 
					#define DB_VLOCK "1" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define DB_VERSION "0.7" | 
					 | 
					 | 
					 | 
					#define DB_VERSION "0.7" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define CKDB_VERSION DB_VERSION"-0.102" | 
					 | 
					 | 
					 | 
					#define CKDB_VERSION DB_VERSION"-0.106" | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define WHERE_FFL " - from %s %s() line %d" | 
					 | 
					 | 
					 | 
					#define WHERE_FFL " - from %s %s() line %d" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define WHERE_FFL_HERE __FILE__, __func__, __LINE__ | 
					 | 
					 | 
					 | 
					#define WHERE_FFL_HERE __FILE__, __func__, __LINE__ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -774,6 +774,7 @@ enum cmd_values { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						CMD_USERSTAT, | 
					 | 
					 | 
					 | 
						CMD_USERSTAT, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						CMD_BLOCK, | 
					 | 
					 | 
					 | 
						CMD_BLOCK, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						CMD_BLOCKLIST, | 
					 | 
					 | 
					 | 
						CMD_BLOCKLIST, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						CMD_BLOCKSTATUS, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						CMD_NEWID, | 
					 | 
					 | 
					 | 
						CMD_NEWID, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						CMD_PAYMENTS, | 
					 | 
					 | 
					 | 
						CMD_PAYMENTS, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						CMD_WORKERS, | 
					 | 
					 | 
					 | 
						CMD_WORKERS, | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1187,10 +1188,18 @@ typedef struct blocks { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define DATA_BLOCKS(_item) ((BLOCKS *)(_item->data)) | 
					 | 
					 | 
					 | 
					#define DATA_BLOCKS(_item) ((BLOCKS *)(_item->data)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define BLOCKS_NEW 'n' | 
					 | 
					 | 
					 | 
					#define BLOCKS_NEW 'n' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#define BLOCKS_NEW_STR "n" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define BLOCKS_CONFIRM '1' | 
					 | 
					 | 
					 | 
					#define BLOCKS_CONFIRM '1' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#define BLOCKS_CONFIRM_STR "1" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#define BLOCKS_42 'F' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#define BLOCKS_42_STR "F" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#define BLOCKS_ORPHAN 'O' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#define BLOCKS_ORPHAN_STR "O" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const char *blocks_new = "New"; | 
					 | 
					 | 
					 | 
					static const char *blocks_new = "New"; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const char *blocks_confirm = "1-Confirm"; | 
					 | 
					 | 
					 | 
					static const char *blocks_confirm = "1-Confirm"; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static const char *blocks_42 = "42-Confirm"; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static const char *blocks_orphan = "Orphan"; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const char *blocks_unknown = "?Unknown?"; | 
					 | 
					 | 
					 | 
					static const char *blocks_unknown = "?Unknown?"; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define KANO -27972 | 
					 | 
					 | 
					 | 
					#define KANO -27972 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -3640,6 +3649,7 @@ static void auto_age_older(PGconn *conn, int64_t workinfoid, char *poolinstance, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									char *by, char *code, char *inet, tv_t *cd) | 
					 | 
					 | 
					 | 
									char *by, char *code, char *inet, tv_t *cd) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						static int64_t last_attempted_id = -1; | 
					 | 
					 | 
					 | 
						static int64_t last_attempted_id = -1; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						static int64_t prev_found = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						static int repeat; | 
					 | 
					 | 
					 | 
						static int repeat; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						char min_buf[DATE_BUFSIZ], max_buf[DATE_BUFSIZ]; | 
					 | 
					 | 
					 | 
						char min_buf[DATE_BUFSIZ], max_buf[DATE_BUFSIZ]; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -3648,37 +3658,51 @@ static void auto_age_older(PGconn *conn, int64_t workinfoid, char *poolinstance, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						tv_t ss_first_min, ss_last_max; | 
					 | 
					 | 
					 | 
						tv_t ss_first_min, ss_last_max; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						tv_t ss_first, ss_last; | 
					 | 
					 | 
					 | 
						tv_t ss_first, ss_last; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int32_t wid_count; | 
					 | 
					 | 
					 | 
						int32_t wid_count; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						SHARESUMMARY sharesummary; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						K_TREE_CTX ctx[1]; | 
					 | 
					 | 
					 | 
						K_TREE_CTX ctx[1]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						K_ITEM *ss_item; | 
					 | 
					 | 
					 | 
						K_ITEM look, *ss_item; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int64_t age_id, do_id, to_id; | 
					 | 
					 | 
					 | 
						int64_t age_id, do_id, to_id; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool ok; | 
					 | 
					 | 
					 | 
						bool ok, found; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						LOGDEBUG("%s(): workinfoid=%"PRId64" prev=%"PRId64, __func__, workinfoid, prev_found); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LOGDEBUG("%s(): %"PRId64, __func__, workinfoid); | 
					 | 
					 | 
					 | 
						age_id = prev_found; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						// Find the oldest 'unaged' sharesummary < workinfoid and >= prev_found
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						sharesummary.workinfoid = prev_found; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						sharesummary.userid = -1; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						sharesummary.workername[0] = '\0'; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						look.data = (void *)(&sharesummary); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ss_item = find_after_in_ktree(sharesummary_workinfoid_root, &look, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									      cmp_sharesummary_workinfoid, ctx); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ss_first_min.tv_sec = ss_first_min.tv_usec = | 
					 | 
					 | 
					 | 
						ss_first_min.tv_sec = ss_first_min.tv_usec = | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ss_last_max.tv_sec = ss_last_max.tv_usec = 0; | 
					 | 
					 | 
					 | 
						ss_last_max.tv_sec = ss_last_max.tv_usec = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ss_count_tot = s_count_tot = s_diff_tot = 0; | 
					 | 
					 | 
					 | 
						ss_count_tot = s_count_tot = s_diff_tot = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						age_id = 0; | 
					 | 
					 | 
					 | 
						found = false; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Find the oldest 'unaged' sharesummary < workinfoid
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ss_item = first_in_ktree(sharesummary_workinfoid_root, ctx); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						while (ss_item && DATA_SHARESUMMARY(ss_item)->workinfoid < workinfoid) { | 
					 | 
					 | 
					 | 
						while (ss_item && DATA_SHARESUMMARY(ss_item)->workinfoid < workinfoid) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (DATA_SHARESUMMARY(ss_item)->complete[0] == SUMMARY_NEW) { | 
					 | 
					 | 
					 | 
							if (DATA_SHARESUMMARY(ss_item)->complete[0] == SUMMARY_NEW) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								age_id = DATA_SHARESUMMARY(ss_item)->workinfoid; | 
					 | 
					 | 
					 | 
								age_id = DATA_SHARESUMMARY(ss_item)->workinfoid; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								prev_found = age_id; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								found = true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							ss_item = next_in_ktree(ctx); | 
					 | 
					 | 
					 | 
							ss_item = next_in_ktree(ctx); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LOGDEBUG("%s(): age_id=%"PRId64, __func__, age_id); | 
					 | 
					 | 
					 | 
						LOGDEBUG("%s(): age_id=%"PRId64" found=%d", __func__, age_id, found); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* Process all the consecutive sharesummaries that's aren't aged
 | 
					 | 
					 | 
					 | 
						// Don't repeat searching old items to avoid accessing their ram
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						 * This way we find each oldest 'batch' of sharesummaries that have | 
					 | 
					 | 
					 | 
						if (!found) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						 *  been missed and can report the range of data that was aged, | 
					 | 
					 | 
					 | 
							prev_found = workinfoid; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						 *  which would normally just be an approx 10min set of workinfoids | 
					 | 
					 | 
					 | 
						else { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						 *  from the last time ckpool stopped | 
					 | 
					 | 
					 | 
							/* Process all the consecutive sharesummaries that's aren't aged
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						 * Each next group of unaged sharesummaries following this, will be | 
					 | 
					 | 
					 | 
							 * This way we find each oldest 'batch' of sharesummaries that have | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						 *  picked up by each next aging */ | 
					 | 
					 | 
					 | 
							 *  been missed and can report the range of data that was aged, | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (age_id) { | 
					 | 
					 | 
					 | 
							 *  which would normally just be an approx 10min set of workinfoids | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							 *  from the last time ckpool stopped | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							 * Each next group of unaged sharesummaries following this, will be | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							 *  picked up by each next aging */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							wid_count = 0; | 
					 | 
					 | 
					 | 
							wid_count = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							do_id = age_id; | 
					 | 
					 | 
					 | 
							do_id = age_id; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							to_id = 0; | 
					 | 
					 | 
					 | 
							to_id = 0; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -4851,11 +4875,14 @@ static const char *blocks_confirmed(char *confirmed) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								return blocks_new; | 
					 | 
					 | 
					 | 
								return blocks_new; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case BLOCKS_CONFIRM: | 
					 | 
					 | 
					 | 
							case BLOCKS_CONFIRM: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								return blocks_confirm; | 
					 | 
					 | 
					 | 
								return blocks_confirm; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							case BLOCKS_42: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								return blocks_42; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							case BLOCKS_ORPHAN: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								return blocks_orphan; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return blocks_unknown; | 
					 | 
					 | 
					 | 
						return blocks_unknown; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// TODO: determine how to handle orphan blocks after 1 confirm
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static bool blocks_add(PGconn *conn, char *height, char *blockhash, | 
					 | 
					 | 
					 | 
					static bool blocks_add(PGconn *conn, char *height, char *blockhash, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								char *confirmed, char *workinfoid, char *username, | 
					 | 
					 | 
					 | 
								char *confirmed, char *workinfoid, char *username, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								char *workername, char *clientid, char *enonce1, | 
					 | 
					 | 
					 | 
								char *workername, char *clientid, char *enonce1, | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -4875,6 +4902,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						char *params[11 + HISTORYDATECOUNT]; | 
					 | 
					 | 
					 | 
						char *params[11 + HISTORYDATECOUNT]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool ok = false, update_old = false; | 
					 | 
					 | 
					 | 
						bool ok = false, update_old = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int par = 0; | 
					 | 
					 | 
					 | 
						int par = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						char want = '?'; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int n; | 
					 | 
					 | 
					 | 
						int n; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LOGDEBUG("%s(): add", __func__); | 
					 | 
					 | 
					 | 
						LOGDEBUG("%s(): add", __func__); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -4969,32 +4997,46 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									goto unparam; | 
					 | 
					 | 
					 | 
									goto unparam; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							case BLOCKS_ORPHAN: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							case BLOCKS_42: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								// These shouldn't be possible until startup completes
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								if (!startup_complete) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									K_WUNLOCK(blocks_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									tv_to_buf(cd, cd_buf, sizeof(cd_buf)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									LOGERR("%s(): Status: %s invalid during startup. " | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										"Ignored: Block: %s/...%s/%s", | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										__func__, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										blocks_confirmed(confirmed), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										height, blk_dsp, cd_buf); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									goto flail; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								want = BLOCKS_CONFIRM; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case BLOCKS_CONFIRM: | 
					 | 
					 | 
					 | 
							case BLOCKS_CONFIRM: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (!old_b_item) { | 
					 | 
					 | 
					 | 
								if (!old_b_item) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									k_add_head(blocks_free, b_item); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									K_WUNLOCK(blocks_free); | 
					 | 
					 | 
					 | 
									K_WUNLOCK(blocks_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									tv_to_buf(cd, cd_buf, sizeof(cd_buf)); | 
					 | 
					 | 
					 | 
									tv_to_buf(cd, cd_buf, sizeof(cd_buf)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									LOGERR("%s(): Can't confirm a non-existent block, Status: " | 
					 | 
					 | 
					 | 
									LOGERR("%s(): Can't %s a non-existent Block: %s/...%s/%s", | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										"%s, Block: %s/...%s/%s", | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										__func__, blocks_confirmed(confirmed), | 
					 | 
					 | 
					 | 
										__func__, blocks_confirmed(confirmed), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										height, blk_dsp, cd_buf); | 
					 | 
					 | 
					 | 
										height, blk_dsp, cd_buf); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									return false; | 
					 | 
					 | 
					 | 
									goto flail; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								/* This will also treat an unrecognised 'confirmed' as a
 | 
					 | 
					 | 
					 | 
								if (confirmed[0] == BLOCKS_CONFIRM) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								 * duplicate since they shouldn't exist anyway */ | 
					 | 
					 | 
					 | 
									want = BLOCKS_NEW; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (DATA_BLOCKS(old_b_item)->confirmed[0] != BLOCKS_NEW) { | 
					 | 
					 | 
					 | 
								if (DATA_BLOCKS(old_b_item)->confirmed[0] != want) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									k_add_head(blocks_free, b_item); | 
					 | 
					 | 
					 | 
									k_add_head(blocks_free, b_item); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									K_WUNLOCK(blocks_free); | 
					 | 
					 | 
					 | 
									K_WUNLOCK(blocks_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if (!igndup || DATA_BLOCKS(old_b_item)->confirmed[0] != BLOCKS_CONFIRM) { | 
					 | 
					 | 
					 | 
									// No mismatch messages during startup
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									if (!startup_complete) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										tv_to_buf(cd, cd_buf, sizeof(cd_buf)); | 
					 | 
					 | 
					 | 
										tv_to_buf(cd, cd_buf, sizeof(cd_buf)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										LOGERR("%s(): Duplicate (%s) blocks ignored, Status: " | 
					 | 
					 | 
					 | 
										LOGERR("%s(): Request Status: %s requires Status: %s. " | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											"%s, Block: %s/...%s/%s", | 
					 | 
					 | 
					 | 
											"Ignored: Status: %s, Block: %s/...%s/%s", | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											__func__, | 
					 | 
					 | 
					 | 
											__func__, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											blocks_confirmed(DATA_BLOCKS(old_b_item)->confirmed), | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											blocks_confirmed(confirmed), | 
					 | 
					 | 
					 | 
											blocks_confirmed(confirmed), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											blocks_confirmed(BLOCKS_CONFIRM_STR), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											blocks_confirmed(DATA_BLOCKS(old_b_item)->confirmed), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											height, blk_dsp, cd_buf); | 
					 | 
					 | 
					 | 
											height, blk_dsp, cd_buf); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} | 
					 | 
					 | 
					 | 
									} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									return true; | 
					 | 
					 | 
					 | 
									goto flail; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								K_WUNLOCK(blocks_free); | 
					 | 
					 | 
					 | 
								K_WUNLOCK(blocks_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -5102,44 +5144,55 @@ flail: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						K_WUNLOCK(blocks_free); | 
					 | 
					 | 
					 | 
						K_WUNLOCK(blocks_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (ok) { | 
					 | 
					 | 
					 | 
						if (ok) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							char pct[16] = "?"; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							char est[16] = ""; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							K_ITEM *w_item; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							char tmp[256]; | 
					 | 
					 | 
					 | 
							char tmp[256]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							bool blk; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (confirmed[0] != BLOCKS_NEW) | 
					 | 
					 | 
					 | 
							switch (confirmed[0]) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								tmp[0] = '\0'; | 
					 | 
					 | 
					 | 
								case BLOCKS_NEW: | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							else { | 
					 | 
					 | 
					 | 
									blk = true; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								char pct[16] = "?"; | 
					 | 
					 | 
					 | 
									tmp[0] = '\0'; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								char est[16] = ""; | 
					 | 
					 | 
					 | 
									break; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								K_ITEM *w_item; | 
					 | 
					 | 
					 | 
								case BLOCKS_CONFIRM: | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
									blk = true; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								w_item = find_workinfo(DATA_BLOCKS(b_item)->workinfoid); | 
					 | 
					 | 
					 | 
									w_item = find_workinfo(DATA_BLOCKS(b_item)->workinfoid); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (w_item) { | 
					 | 
					 | 
					 | 
									if (w_item) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									char wdiffbin[TXT_SML+1]; | 
					 | 
					 | 
					 | 
										char wdiffbin[TXT_SML+1]; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									double wdiff; | 
					 | 
					 | 
					 | 
										double wdiff; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									hex2bin(wdiffbin, DATA_WORKINFO(w_item)->bits, 4); | 
					 | 
					 | 
					 | 
										hex2bin(wdiffbin, DATA_WORKINFO(w_item)->bits, 4); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									wdiff = diff_from_nbits(wdiffbin); | 
					 | 
					 | 
					 | 
										wdiff = diff_from_nbits(wdiffbin); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if (wdiff > 0.0) { | 
					 | 
					 | 
					 | 
										if (wdiff > 0.0) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										snprintf(pct, sizeof(pct), "%.2f", | 
					 | 
					 | 
					 | 
											snprintf(pct, sizeof(pct), "%.2f", | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											 100.0 * pool.diffacc / wdiff); | 
					 | 
					 | 
					 | 
												 100.0 * pool.diffacc / wdiff); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} | 
					 | 
					 | 
					 | 
									} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
									if (pool.diffacc >= 1000000.0) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (pool.diffacc >= 1000000.0) { | 
					 | 
					 | 
					 | 
										suffix_string(pool.diffacc, est, sizeof(est)-1, 1); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									suffix_string(pool.diffacc, est, sizeof(est)-1, 1); | 
					 | 
					 | 
					 | 
										strcat(est, " "); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									strcat(est, " "); | 
					 | 
					 | 
					 | 
									} | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
									tv_to_buf(&(DATA_BLOCKS(b_item)->createdate), cd_buf, sizeof(cd_buf)); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								tv_to_buf(&(DATA_BLOCKS(b_item)->createdate), cd_buf, sizeof(cd_buf)); | 
					 | 
					 | 
					 | 
									snprintf(tmp, sizeof(tmp), | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								snprintf(tmp, sizeof(tmp), | 
					 | 
					 | 
					 | 
										 " Reward: %f, User: %s, Worker: %s, ShareEst: %.1f %s%s%% UTC:%s", | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									 " Reward: %f, User: %s, Worker: %s, ShareEst: %.1f %s%s%% UTC:%s", | 
					 | 
					 | 
					 | 
										 BTC_TO_D(DATA_BLOCKS(b_item)->reward), | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									 BTC_TO_D(DATA_BLOCKS(b_item)->reward), | 
					 | 
					 | 
					 | 
										 username, workername, pool.diffacc, est, pct, cd_buf); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									 username, workername, pool.diffacc, est, pct, cd_buf); | 
					 | 
					 | 
					 | 
									if (pool.workinfoid < DATA_BLOCKS(b_item)->workinfoid) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (pool.workinfoid < DATA_BLOCKS(b_item)->workinfoid) { | 
					 | 
					 | 
					 | 
										pool.workinfoid = DATA_BLOCKS(b_item)->workinfoid; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pool.workinfoid = DATA_BLOCKS(b_item)->workinfoid; | 
					 | 
					 | 
					 | 
										pool.diffacc = pool.differr = | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pool.diffacc = pool.differr = | 
					 | 
					 | 
					 | 
										pool.best_sdiff = 0.0; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pool.best_sdiff = 0.0; | 
					 | 
					 | 
					 | 
									} | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
									break; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								case BLOCKS_ORPHAN: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								case BLOCKS_42: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								default: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									blk = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									tmp[0] = '\0'; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							LOGWARNING("%s(): BLOCK! Status: %s, Block: %s/...%s%s", | 
					 | 
					 | 
					 | 
							LOGWARNING("%s(): %sStatus: %s, Block: %s/...%s%s", | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								   __func__, | 
					 | 
					 | 
					 | 
								   __func__, blk ? "BLOCK! " : "", | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								   blocks_confirmed(confirmed), | 
					 | 
					 | 
					 | 
								   blocks_confirmed(confirmed), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								   height, blk_dsp, tmp); | 
					 | 
					 | 
					 | 
								   height, blk_dsp, tmp); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -7220,20 +7273,18 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						char *buf; | 
					 | 
					 | 
					 | 
						char *buf; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						size_t len, off; | 
					 | 
					 | 
					 | 
						size_t len, off; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int rows; | 
					 | 
					 | 
					 | 
						int rows; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int32_t height; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LOGDEBUG("%s(): cmd '%s'", __func__, cmd); | 
					 | 
					 | 
					 | 
						LOGDEBUG("%s(): cmd '%s'", __func__, cmd); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						b_item = last_in_ktree(blocks_root, ctx); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						APPEND_REALLOC_INIT(buf, off, len); | 
					 | 
					 | 
					 | 
						APPEND_REALLOC_INIT(buf, off, len); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						APPEND_REALLOC(buf, off, len, "ok."); | 
					 | 
					 | 
					 | 
						APPEND_REALLOC(buf, off, len, "ok."); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						rows = 0; | 
					 | 
					 | 
					 | 
						rows = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						height = -1; | 
					 | 
					 | 
					 | 
						K_RLOCK(blocks_free); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						b_item = last_in_ktree(blocks_root, ctx); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						while (b_item && rows < 42) { | 
					 | 
					 | 
					 | 
						while (b_item && rows < 42) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (height != DATA_BLOCKS(b_item)->height) { | 
					 | 
					 | 
					 | 
							if (CURRENT(&(DATA_BLOCKS(b_item)->expirydate))) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								height = DATA_BLOCKS(b_item)->height; | 
					 | 
					 | 
					 | 
								int_to_buf(DATA_BLOCKS(b_item)->height, reply, sizeof(reply)); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
								snprintf(tmp, sizeof(tmp), "height%d=%s%c", rows, reply, FLDSEP); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								snprintf(tmp, sizeof(tmp), "height%d=%d%c", rows, height, FLDSEP); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								APPEND_REALLOC(buf, off, len, tmp); | 
					 | 
					 | 
					 | 
								APPEND_REALLOC(buf, off, len, tmp); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								str_to_buf(DATA_BLOCKS(b_item)->blockhash, reply, sizeof(reply)); | 
					 | 
					 | 
					 | 
								str_to_buf(DATA_BLOCKS(b_item)->blockhash, reply, sizeof(reply)); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -7266,6 +7317,7 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							b_item = prev_in_ktree(ctx); | 
					 | 
					 | 
					 | 
							b_item = prev_in_ktree(ctx); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						K_RUNLOCK(blocks_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						snprintf(tmp, sizeof(tmp), "rows=%d", rows); | 
					 | 
					 | 
					 | 
						snprintf(tmp, sizeof(tmp), "rows=%d", rows); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						APPEND_REALLOC(buf, off, len, tmp); | 
					 | 
					 | 
					 | 
						APPEND_REALLOC(buf, off, len, tmp); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -7273,6 +7325,90 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return buf; | 
					 | 
					 | 
					 | 
						return buf; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static char *cmd_blockstatus(__maybe_unused PGconn *conn, char *cmd, char *id, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								     tv_t *now, char *by, char *code, char *inet, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								     __maybe_unused tv_t *cd, K_TREE *trf_root) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						K_ITEM *i_height, *i_blockhash, *i_action; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						char reply[1024] = ""; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						size_t siz = sizeof(reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						K_ITEM *b_item; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						BLOCKS *blocks; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						int32_t height; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						char *action; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						bool ok = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						LOGDEBUG("%s(): cmd '%s'", __func__, cmd); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						i_height = require_name(trf_root, "height", 1, NULL, reply, siz); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (!i_height) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							return strdup(reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						TXT_TO_INT("height", DATA_TRANSFER(i_height)->data, height); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						i_blockhash = require_name(trf_root, "blockhash", 1, NULL, reply, siz); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (!i_blockhash) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							return strdup(reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						i_action = require_name(trf_root, "action", 1, NULL, reply, siz); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (!i_action) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							return strdup(reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						action = DATA_TRANSFER(i_action)->data; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						K_RLOCK(blocks_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						b_item = find_blocks(height, DATA_TRANSFER(i_blockhash)->data); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						K_RUNLOCK(blocks_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (!b_item) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							snprintf(reply, siz, "ERR.unknown block"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							LOGERR("%s.%s", id, reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							return strdup(reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						blocks = DATA_BLOCKS(b_item); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (strcasecmp(action, "orphan") == 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							switch (blocks->confirmed[0]) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								case BLOCKS_NEW: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								case BLOCKS_CONFIRM: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									ok = blocks_add(conn, DATA_TRANSFER(i_height)->data, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											      blocks->blockhash, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											      BLOCKS_ORPHAN_STR, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											      EMPTY, EMPTY, EMPTY, EMPTY, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											      EMPTY, EMPTY, EMPTY, EMPTY, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											      by, code, inet, now, false, id, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											      trf_root); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									if (!ok) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										snprintf(reply, siz, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											 "DBE.action '%s'", | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											 action); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										LOGERR("%s.%s", id, reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										return strdup(reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									// TODO: reset the share counter?
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								default: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									snprintf(reply, siz, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										 "ERR.invalid action '%.*s%s' for block state '%s'", | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										 CMD_SIZ, action, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										 (strlen(action) > CMD_SIZ) ? "..." : "", | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										 blocks_confirmed(blocks->confirmed)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									LOGERR("%s.%s", id, reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									return strdup(reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						} else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							snprintf(reply, siz, "ERR.unknown action '%s'", | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								 DATA_TRANSFER(i_action)->data); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							LOGERR("%s.%s", id, reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							return strdup(reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						snprintf(reply, siz, "ok.%s %d", DATA_TRANSFER(i_action)->data, height); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						LOGDEBUG("%s.%s", id, reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						return strdup(reply); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static char *cmd_newid(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, | 
					 | 
					 | 
					 | 
					static char *cmd_newid(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								char *code, char *inet, __maybe_unused tv_t *cd, | 
					 | 
					 | 
					 | 
								char *code, char *inet, __maybe_unused tv_t *cd, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								K_TREE *trf_root) | 
					 | 
					 | 
					 | 
								K_TREE *trf_root) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -8835,6 +8971,7 @@ static struct CMDS { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ CMD_USERSTAT,	"userstats",	false,	true,	cmd_userstats,	ACCESS_POOL }, | 
					 | 
					 | 
					 | 
						{ CMD_USERSTAT,	"userstats",	false,	true,	cmd_userstats,	ACCESS_POOL }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ CMD_BLOCK,	"block",	false,	true,	cmd_blocks,	ACCESS_POOL }, | 
					 | 
					 | 
					 | 
						{ CMD_BLOCK,	"block",	false,	true,	cmd_blocks,	ACCESS_POOL }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ CMD_BLOCKLIST,"blocklist",	false,	false,	cmd_blocklist,	ACCESS_WEB }, | 
					 | 
					 | 
					 | 
						{ CMD_BLOCKLIST,"blocklist",	false,	false,	cmd_blocklist,	ACCESS_WEB }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						{ CMD_BLOCKSTATUS,"blockstatus",false,	false,	cmd_blockstatus,ACCESS_WEB }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ CMD_NEWID,	"newid",	false,	false,	cmd_newid,	ACCESS_SYSTEM }, | 
					 | 
					 | 
					 | 
						{ CMD_NEWID,	"newid",	false,	false,	cmd_newid,	ACCESS_SYSTEM }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ CMD_PAYMENTS,	"payments",	false,	false,	cmd_payments,	ACCESS_WEB }, | 
					 | 
					 | 
					 | 
						{ CMD_PAYMENTS,	"payments",	false,	false,	cmd_payments,	ACCESS_WEB }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ CMD_WORKERS,	"workers",	false,	false,	cmd_workers,	ACCESS_WEB }, | 
					 | 
					 | 
					 | 
						{ CMD_WORKERS,	"workers",	false,	false,	cmd_workers,	ACCESS_WEB }, | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -9581,6 +9718,7 @@ static void *socketer(__maybe_unused void *arg) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										case CMD_PAYMENTS: | 
					 | 
					 | 
					 | 
										case CMD_PAYMENTS: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										case CMD_PPLNS: | 
					 | 
					 | 
					 | 
										case CMD_PPLNS: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										case CMD_DSP: | 
					 | 
					 | 
					 | 
										case CMD_DSP: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										case CMD_BLOCKSTATUS: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											if (!startup_complete) { | 
					 | 
					 | 
					 | 
											if (!startup_complete) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
												snprintf(reply, sizeof(reply), | 
					 | 
					 | 
					 | 
												snprintf(reply, sizeof(reply), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
													 "%s.%ld.loading.%s", | 
					 | 
					 | 
					 | 
													 "%s.%ld.loading.%s", | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -9685,8 +9823,11 @@ static void *socketer(__maybe_unused void *arg) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								K_WLOCK(transfer_free); | 
					 | 
					 | 
					 | 
								K_WLOCK(transfer_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								k_list_transfer_to_head(trf_store, transfer_free); | 
					 | 
					 | 
					 | 
								k_list_transfer_to_head(trf_store, transfer_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								K_WUNLOCK(transfer_free); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								trf_store = k_free_store(trf_store); | 
					 | 
					 | 
					 | 
								trf_store = k_free_store(trf_store); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								if (transfer_free->count == transfer_free->total && | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								    transfer_free->total > ALLOC_TRANSFER * 64) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									k_cull_list(transfer_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								K_WUNLOCK(transfer_free); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -9750,6 +9891,7 @@ static bool reload_line(PGconn *conn, char *filename, uint64_t count, char *buf) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case CMD_NEWPASS: | 
					 | 
					 | 
					 | 
								case CMD_NEWPASS: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case CMD_CHKPASS: | 
					 | 
					 | 
					 | 
								case CMD_CHKPASS: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case CMD_BLOCKLIST: | 
					 | 
					 | 
					 | 
								case CMD_BLOCKLIST: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								case CMD_BLOCKSTATUS: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case CMD_NEWID: | 
					 | 
					 | 
					 | 
								case CMD_NEWID: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case CMD_PAYMENTS: | 
					 | 
					 | 
					 | 
								case CMD_PAYMENTS: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case CMD_WORKERS: | 
					 | 
					 | 
					 | 
								case CMD_WORKERS: | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -10035,7 +10177,8 @@ static void *listener(void *arg) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							startup_complete = true; | 
					 | 
					 | 
					 | 
							startup_complete = true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						conn = dbconnect(); | 
					 | 
					 | 
					 | 
						if (!everyone_die) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							conn = dbconnect(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Process queued work
 | 
					 | 
					 | 
					 | 
						// Process queued work
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						while (!everyone_die) { | 
					 | 
					 | 
					 | 
						while (!everyone_die) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -10060,7 +10203,8 @@ static void *listener(void *arg) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PQfinish(conn); | 
					 | 
					 | 
					 | 
						if (conn) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							PQfinish(conn); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return NULL; | 
					 | 
					 | 
					 | 
						return NULL; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -10601,6 +10745,7 @@ static struct option long_options[] = { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ "name",		required_argument,	0,	'n' }, | 
					 | 
					 | 
					 | 
						{ "name",		required_argument,	0,	'n' }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ "dbpass",		required_argument,	0,	'p' }, | 
					 | 
					 | 
					 | 
						{ "dbpass",		required_argument,	0,	'p' }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ "ckpool-logdir",	required_argument,	0,	'r' }, | 
					 | 
					 | 
					 | 
						{ "ckpool-logdir",	required_argument,	0,	'r' }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						{ "logdir",		required_argument,	0,	'R' }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ "sockdir",		required_argument,	0,	's' }, | 
					 | 
					 | 
					 | 
						{ "sockdir",		required_argument,	0,	's' }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ "dbuser",		required_argument,	0,	'u' }, | 
					 | 
					 | 
					 | 
						{ "dbuser",		required_argument,	0,	'u' }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ "version",		no_argument,		0,	'v' }, | 
					 | 
					 | 
					 | 
						{ "version",		no_argument,		0,	'v' }, | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -10634,7 +10779,7 @@ int main(int argc, char **argv) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						memset(&ckp, 0, sizeof(ckp)); | 
					 | 
					 | 
					 | 
						memset(&ckp, 0, sizeof(ckp)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ckp.loglevel = LOG_NOTICE; | 
					 | 
					 | 
					 | 
						ckp.loglevel = LOG_NOTICE; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						while ((c = getopt_long(argc, argv, "c:d:hkl:n:p:r:s:u:vyY:", long_options, &i)) != -1) { | 
					 | 
					 | 
					 | 
						while ((c = getopt_long(argc, argv, "c:d:hkl:n:p:r:R:s:u:vyY:", long_options, &i)) != -1) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							switch(c) { | 
					 | 
					 | 
					 | 
							switch(c) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case 'c': | 
					 | 
					 | 
					 | 
								case 'c': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									ckp.config = strdup(optarg); | 
					 | 
					 | 
					 | 
									ckp.config = strdup(optarg); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -10686,6 +10831,9 @@ int main(int argc, char **argv) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case 'r': | 
					 | 
					 | 
					 | 
								case 'r': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									restorefrom = strdup(optarg); | 
					 | 
					 | 
					 | 
									restorefrom = strdup(optarg); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									break; | 
					 | 
					 | 
					 | 
									break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								case 'R': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									ckp.logdir = strdup(optarg); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case 's': | 
					 | 
					 | 
					 | 
								case 's': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									ckp.socket_dir = strdup(optarg); | 
					 | 
					 | 
					 | 
									ckp.socket_dir = strdup(optarg); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									break; | 
					 | 
					 | 
					 | 
									break; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |