Files
KamadoPool/ckpool/patches/0009-resume-client-diff-on-reconnect.patch
T

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