|
@@ -2521,19 +2521,22 @@ static double DIFFEXACTONE = 269599466671506397946670150870196306736371444225405
|
|
|
/*
|
|
/*
|
|
|
* Calculate the work share difficulty
|
|
* Calculate the work share difficulty
|
|
|
*/
|
|
*/
|
|
|
-static void calc_diff(struct work *work)
|
|
|
|
|
|
|
+static void calc_diff(struct work *work, int known)
|
|
|
{
|
|
{
|
|
|
struct cgminer_pool_stats *pool_stats = &(work->pool->cgminer_pool_stats);
|
|
struct cgminer_pool_stats *pool_stats = &(work->pool->cgminer_pool_stats);
|
|
|
double targ;
|
|
double targ;
|
|
|
int i;
|
|
int i;
|
|
|
|
|
|
|
|
- targ = 0;
|
|
|
|
|
- for (i = 31; i >= 0; i--) {
|
|
|
|
|
- targ *= 256;
|
|
|
|
|
- targ += work->target[i];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (!known) {
|
|
|
|
|
+ targ = 0;
|
|
|
|
|
+ for (i = 31; i >= 0; i--) {
|
|
|
|
|
+ targ *= 256;
|
|
|
|
|
+ targ += work->target[i];
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- work->work_difficulty = DIFFEXACTONE / (targ ? : DIFFEXACTONE);
|
|
|
|
|
|
|
+ work->work_difficulty = DIFFEXACTONE / (targ ? : DIFFEXACTONE);
|
|
|
|
|
+ } else
|
|
|
|
|
+ work->work_difficulty = known;
|
|
|
|
|
|
|
|
pool_stats->last_diff = work->work_difficulty;
|
|
pool_stats->last_diff = work->work_difficulty;
|
|
|
|
|
|
|
@@ -2567,7 +2570,7 @@ static void get_benchmark_work(struct work *work)
|
|
|
gettimeofday(&(work->tv_getwork), NULL);
|
|
gettimeofday(&(work->tv_getwork), NULL);
|
|
|
memcpy(&(work->tv_getwork_reply), &(work->tv_getwork), sizeof(struct timeval));
|
|
memcpy(&(work->tv_getwork_reply), &(work->tv_getwork), sizeof(struct timeval));
|
|
|
work->getwork_mode = GETWORK_MODE_BENCHMARK;
|
|
work->getwork_mode = GETWORK_MODE_BENCHMARK;
|
|
|
- calc_diff(work);
|
|
|
|
|
|
|
+ calc_diff(work, 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static char *prepare_rpc_req(struct work *work, enum pool_protocol proto, const char *lpid)
|
|
static char *prepare_rpc_req(struct work *work, enum pool_protocol proto, const char *lpid)
|
|
@@ -2693,7 +2696,7 @@ tryagain:
|
|
|
work->pool = pool;
|
|
work->pool = pool;
|
|
|
work->longpoll = false;
|
|
work->longpoll = false;
|
|
|
work->getwork_mode = GETWORK_MODE_POOL;
|
|
work->getwork_mode = GETWORK_MODE_POOL;
|
|
|
- calc_diff(work);
|
|
|
|
|
|
|
+ calc_diff(work, 0);
|
|
|
total_getworks++;
|
|
total_getworks++;
|
|
|
pool->getwork_requested++;
|
|
pool->getwork_requested++;
|
|
|
|
|
|
|
@@ -2988,6 +2991,8 @@ static inline bool should_roll(struct work *work)
|
|
|
* reject blocks as invalid. */
|
|
* reject blocks as invalid. */
|
|
|
static inline bool can_roll(struct work *work)
|
|
static inline bool can_roll(struct work *work)
|
|
|
{
|
|
{
|
|
|
|
|
+ if (work->stratum)
|
|
|
|
|
+ return false;
|
|
|
if (!(work->pool && !work->clone))
|
|
if (!(work->pool && !work->clone))
|
|
|
return false;
|
|
return false;
|
|
|
if (work->tmpl) {
|
|
if (work->tmpl) {
|
|
@@ -3101,6 +3106,8 @@ static void pool_died(struct pool *pool)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void gen_stratum_work(struct pool *pool, struct work *work);
|
|
|
|
|
+
|
|
|
static void *get_work_thread(void *userdata)
|
|
static void *get_work_thread(void *userdata)
|
|
|
{
|
|
{
|
|
|
struct workio_cmd *wc = (struct workio_cmd *)userdata;
|
|
struct workio_cmd *wc = (struct workio_cmd *)userdata;
|
|
@@ -3115,6 +3122,17 @@ static void *get_work_thread(void *userdata)
|
|
|
|
|
|
|
|
pool = wc->pool;
|
|
pool = wc->pool;
|
|
|
|
|
|
|
|
|
|
+ if (pool->has_stratum) {
|
|
|
|
|
+ ret_work = make_work();
|
|
|
|
|
+ gen_stratum_work(pool, ret_work);
|
|
|
|
|
+ if (unlikely(!stage_work(ret_work))) {
|
|
|
|
|
+ applog(LOG_ERR, "Failed to stage stratum work in get_work_thread");
|
|
|
|
|
+ kill_work();
|
|
|
|
|
+ free(ret_work);
|
|
|
|
|
+ }
|
|
|
|
|
+ goto out;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (clone_available()) {
|
|
if (clone_available()) {
|
|
|
applog(LOG_DEBUG, "dec_queued from get_work_thread due to clone available\n");
|
|
applog(LOG_DEBUG, "dec_queued from get_work_thread due to clone available\n");
|
|
|
dec_queued(pool);
|
|
dec_queued(pool);
|
|
@@ -3737,15 +3755,17 @@ static void test_work_current(struct work *work)
|
|
|
if (unlikely(new_blocks == 1))
|
|
if (unlikely(new_blocks == 1))
|
|
|
goto out_free;
|
|
goto out_free;
|
|
|
|
|
|
|
|
- if (work->longpoll) {
|
|
|
|
|
- applog(LOG_NOTICE, "LONGPOLL from pool %d detected new block",
|
|
|
|
|
- work->pool->pool_no);
|
|
|
|
|
- work->longpoll = false;
|
|
|
|
|
- } else if (have_longpoll)
|
|
|
|
|
- applog(LOG_NOTICE, "New block detected on network before longpoll");
|
|
|
|
|
- else
|
|
|
|
|
- applog(LOG_NOTICE, "New block detected on network");
|
|
|
|
|
- restart_threads();
|
|
|
|
|
|
|
+ if (!work->stratum) {
|
|
|
|
|
+ if (work->longpoll) {
|
|
|
|
|
+ applog(LOG_NOTICE, "LONGPOLL from pool %d detected new block",
|
|
|
|
|
+ work->pool->pool_no);
|
|
|
|
|
+ work->longpoll = false;
|
|
|
|
|
+ } else if (have_longpoll)
|
|
|
|
|
+ applog(LOG_NOTICE, "New block detected on network before longpoll");
|
|
|
|
|
+ else
|
|
|
|
|
+ applog(LOG_NOTICE, "New block detected on network");
|
|
|
|
|
+ restart_threads();
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
bool restart = false;
|
|
bool restart = false;
|
|
|
struct pool *curpool = NULL;
|
|
struct pool *curpool = NULL;
|
|
@@ -4929,7 +4949,7 @@ tryagain:
|
|
|
memcpy(&(work->tv_getwork), &tv_getwork, sizeof(struct timeval));
|
|
memcpy(&(work->tv_getwork), &tv_getwork, sizeof(struct timeval));
|
|
|
memcpy(&(work->tv_getwork_reply), &tv_getwork_reply, sizeof(struct timeval));
|
|
memcpy(&(work->tv_getwork_reply), &tv_getwork_reply, sizeof(struct timeval));
|
|
|
work->getwork_mode = GETWORK_MODE_TESTPOOL;
|
|
work->getwork_mode = GETWORK_MODE_TESTPOOL;
|
|
|
- calc_diff(work);
|
|
|
|
|
|
|
+ calc_diff(work, 0);
|
|
|
applog(LOG_DEBUG, "Pushing pooltest work to base pool");
|
|
applog(LOG_DEBUG, "Pushing pooltest work to base pool");
|
|
|
|
|
|
|
|
tq_push(thr_info[stage_thr_id].q, work);
|
|
tq_push(thr_info[stage_thr_id].q, work);
|
|
@@ -5090,6 +5110,12 @@ static struct work *hash_pop(const struct timespec *abstime)
|
|
|
|
|
|
|
|
static bool reuse_work(struct work *work)
|
|
static bool reuse_work(struct work *work)
|
|
|
{
|
|
{
|
|
|
|
|
+ if (work->stratum && !work->pool->idle) {
|
|
|
|
|
+ applog(LOG_DEBUG, "Reusing stratum work");
|
|
|
|
|
+ gen_stratum_work(work->pool, work);;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (can_roll(work) && should_roll(work)) {
|
|
if (can_roll(work) && should_roll(work)) {
|
|
|
roll_work(work);
|
|
roll_work(work);
|
|
|
return true;
|
|
return true;
|
|
@@ -5217,6 +5243,16 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
|
|
|
strcat((char *)work->target, buf);
|
|
strcat((char *)work->target, buf);
|
|
|
free(buf);
|
|
free(buf);
|
|
|
applog(LOG_DEBUG, "Generated target %s", work->target);
|
|
applog(LOG_DEBUG, "Generated target %s", work->target);
|
|
|
|
|
+
|
|
|
|
|
+ work->pool = pool;
|
|
|
|
|
+ work->stratum = true;
|
|
|
|
|
+ work->blk.nonce = 0;
|
|
|
|
|
+ work->id = total_work++;
|
|
|
|
|
+ work->longpoll = false;
|
|
|
|
|
+ work->getwork_mode = GETWORK_MODE_STRATUM;
|
|
|
|
|
+ calc_diff(work, diff);
|
|
|
|
|
+
|
|
|
|
|
+ gettimeofday(&work->tv_staged, NULL);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void get_work(struct work *work, struct thr_info *thr, const int thr_id)
|
|
static void get_work(struct work *work, struct thr_info *thr, const int thr_id)
|
|
@@ -5238,11 +5274,6 @@ static void get_work(struct work *work, struct thr_info *thr, const int thr_id)
|
|
|
retry:
|
|
retry:
|
|
|
pool = current_pool();
|
|
pool = current_pool();
|
|
|
|
|
|
|
|
- if (pool->has_stratum) {
|
|
|
|
|
- gen_stratum_work(pool, work);
|
|
|
|
|
- goto out;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
if (reuse_work(work))
|
|
if (reuse_work(work))
|
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
|
@@ -5664,7 +5695,7 @@ static void convert_to_work(json_t *val, int rolltime, struct pool *pool, struct
|
|
|
memcpy(&(work->tv_getwork), tv_lp, sizeof(struct timeval));
|
|
memcpy(&(work->tv_getwork), tv_lp, sizeof(struct timeval));
|
|
|
memcpy(&(work->tv_getwork_reply), tv_lp_reply, sizeof(struct timeval));
|
|
memcpy(&(work->tv_getwork_reply), tv_lp_reply, sizeof(struct timeval));
|
|
|
work->getwork_mode = GETWORK_MODE_LP;
|
|
work->getwork_mode = GETWORK_MODE_LP;
|
|
|
- calc_diff(work);
|
|
|
|
|
|
|
+ calc_diff(work, 0);
|
|
|
|
|
|
|
|
if (pool->enabled == POOL_REJECTING)
|
|
if (pool->enabled == POOL_REJECTING)
|
|
|
work->mandatory = true;
|
|
work->mandatory = true;
|