118 lines
4.7 KiB
Diff
118 lines
4.7 KiB
Diff
diff --git a/src/stratifier.c b/src/stratifier.c
|
|
index a856b3eb..fcb9eb94 100644
|
|
--- a/src/stratifier.c
|
|
+++ b/src/stratifier.c
|
|
@@ -5477,6 +5477,69 @@ static void update_solo_client(sdata_t *sdata, workbase_t *wb, const int64_t cli
|
|
stratum_add_send(sdata, json_msg, client_id, SM_UPDATE);
|
|
}
|
|
|
|
+/* Kamado (patches/0009): restore a reconnecting miner's difficulty and
|
|
+ * grant the work it already holds a difficulty grace window.
|
|
+ *
|
|
+ * Upstream gives every new connection ckp->startdiff, so a pool restart
|
|
+ * discards the difficulty vardiff had tuned each miner to and makes it
|
|
+ * re-converge from the pool default. ckpool does persist per-worker
|
|
+ * hashrate across restarts (read_userstats, decayed by the downtime), so
|
|
+ * the starting difficulty can be derived from it with the same formula
|
|
+ * and clamps add_submit's vardiff uses.
|
|
+ *
|
|
+ * The grace window covers work in flight. A miner may hold queued jobs,
|
|
+ * and much firmware only applies a new difficulty on the following job,
|
|
+ * so its first shares can be below the difficulty we just assigned.
|
|
+ * Pointing diff_change_job_id past the current workbase makes the
|
|
+ * existing check in parse_submit validate those against old_diff (the
|
|
+ * pool minimum) instead of rejecting them as "high diff". The next
|
|
+ * mining.notify closes the window, since by then the client has had the
|
|
+ * difficulty for a whole job.
|
|
+ *
|
|
+ * Needs to be entered with no workbase or instance lock held. */
|
|
+static void resume_client_diff(ckpool_t *ckp, sdata_t *sdata, stratum_instance_t *client)
|
|
+{
|
|
+ const worker_instance_t *worker = client->worker_instance;
|
|
+ int64_t optimal, mindiff, network_diff = 0;
|
|
+ double dsps = 0;
|
|
+
|
|
+ ck_rlock(&sdata->workbase_lock);
|
|
+ if (sdata->current_workbase) {
|
|
+ network_diff = sdata->current_workbase->network_diff;
|
|
+ /* Every job sent so far, including the one about to go out,
|
|
+ * predates this client acting on its difficulty. */
|
|
+ client->diff_change_job_id = sdata->workbase_id + 1;
|
|
+ }
|
|
+ ck_runlock(&sdata->workbase_lock);
|
|
+
|
|
+ /* Read unlocked, as the vardiff path in add_submit does: these are
|
|
+ * decaying averages used as a heuristic, not accounting. */
|
|
+ if (worker)
|
|
+ dsps = worker->dsps5 > 0 ? worker->dsps5 : worker->dsps1;
|
|
+ if (dsps > 0) {
|
|
+ optimal = lround(dsps * 3.33);
|
|
+ /* Client suggest diff overrides worker mindiff */
|
|
+ if (client->suggest_diff)
|
|
+ mindiff = client->suggest_diff;
|
|
+ else
|
|
+ mindiff = worker->mindiff;
|
|
+ optimal = MAX(optimal, ckp->mindiff);
|
|
+ optimal = MAX(optimal, mindiff);
|
|
+ if (ckp->maxdiff)
|
|
+ optimal = MIN(optimal, ckp->maxdiff);
|
|
+ if (network_diff > 0)
|
|
+ optimal = MIN(optimal, network_diff);
|
|
+ if (optimal > 0 && optimal != client->diff) {
|
|
+ LOGNOTICE("Client %s resuming at diff %"PRId64" from retained hashrate instead of startdiff %"PRId64,
|
|
+ client->identity, optimal, ckp->startdiff);
|
|
+ client->diff = optimal;
|
|
+ }
|
|
+ }
|
|
+ /* Floor for the grace window only. client->diff stays what we
|
|
+ * advertise; vardiff overwrites old_diff on its first adjustment. */
|
|
+ client->old_diff = ckp->mindiff > 0 ? ckp->mindiff : 1;
|
|
+}
|
|
+
|
|
/* Needs to be entered with client holding a ref count. */
|
|
static json_t *parse_authorise(stratum_instance_t *client, const json_t *params_val,
|
|
json_t **err_val)
|
|
@@ -5558,6 +5621,19 @@ out:
|
|
sdata_t *sdata = ckp->sdata;
|
|
workbase_t *wb;
|
|
|
|
+ /* Kamado (patches/0009): pick up where vardiff left off and
|
|
+ * arm the first-job grace window. Called before any lock is
|
|
+ * taken here — it acquires the workbase lock itself. */
|
|
+ resume_client_diff(ckp, sdata, client);
|
|
+
|
|
+ /* Kamado (patches/0009): mining.set_difficulty must precede
|
|
+ * the first mining.notify. Upstream sent the job first, so a
|
|
+ * miner started hashing it at whatever difficulty its firmware
|
|
+ * defaults to and its early shares came back under the
|
|
+ * difficulty we had assigned — a burst of "high diff" rejects
|
|
+ * from every miner on every pool restart. */
|
|
+ stratum_send_diff(sdata, client);
|
|
+
|
|
/* To avoid grabbing recursive lock */
|
|
ck_wlock(&sdata->workbase_lock);
|
|
wb = sdata->current_workbase;
|
|
@@ -5573,8 +5649,6 @@ out:
|
|
ck_wlock(&sdata->workbase_lock);
|
|
wb->readcount--;
|
|
ck_wunlock(&sdata->workbase_lock);
|
|
-
|
|
- stratum_send_diff(sdata, client);
|
|
}
|
|
return json_boolean(ret);
|
|
}
|
|
@@ -6567,9 +6641,12 @@ static void update_client(const stratum_instance_t *client, const int64_t client
|
|
{
|
|
sdata_t *sdata = client->sdata;
|
|
|
|
+ /* Kamado (patches/0009): difficulty before work, so a client never
|
|
+ * starts a job without knowing the difficulty it will be judged
|
|
+ * against. Upstream sent the update first. */
|
|
+ stratum_send_diff(sdata, client);
|
|
if (!client->ckp->btcsolo)
|
|
stratum_send_update(sdata, client_id, true);
|
|
- stratum_send_diff(sdata, client);
|
|
}
|
|
|
|
static json_params_t
|