Let a miner ask for its own difficulty, as a floor it cannot go under - #74
Open
Wired4ncer wants to merge 1 commit into
Open
Let a miner ask for its own difficulty, as a floor it cannot go under#74Wired4ncer wants to merge 1 commit into
Wired4ncer wants to merge 1 commit into
Conversation
A miner has no way to influence its difficulty today. `mining.suggest_difficulty`
is a standard stratum method and is not handled, and the password field is
ignored — so an ESP-Miner, which sends suggest_difficulty unprompted on connect,
is silently disregarded on every pool running this.
Two channels, one meaning:
* `d=<n>` in the stratum password, matched at a token boundary so `id=7` is
not a request. cgminer, bosminer, Vnish and LuxOS all expose this field,
which makes it the request channel with the widest reach.
* `mining.suggest_difficulty`, the formal method, for clients that can send
it. Either may arrive before or after authorize; both end up in the same
place.
⛔ It is a FLOOR, never a pin. Vardiff may raise the connection above it and the
network-difficulty clamp still wins over it, but nothing lowers the connection
below it. A pin would be a denial-of-service hole: `d=1` from a 400 TH/s miner
is ~93,000 shares/sec at the share pipeline. As a floor that same request is
inert — max(1, whatever vardiff chose) is just vardiff's answer — while a miner
asking to go HIGHER, which is the real request, gets exactly what it asked for.
The floor is re-applied inside the vardiff retarget, not only at authorize.
Without that the request lasts exactly one window: vardiff sees a rate under
target, which is the POINT of a higher difficulty, and drags it straight back
down.
Why a miner needs this at all: vardiff tunes each CONNECTION toward
vardiff_target_spm, but a proxied fleet spreads one rig across many connections,
so the rig sees target_spm x N. At a uniform difficulty the rig's total share
rate is H/(D*2^32) — the connection count cancels — so letting the miner name D
is the one lever that works regardless of how its hashrate is split.
max_suggested_diff caps a request, default 5e7. <= 0 DISABLES requests rather
than uncapping them: "no ceiling" is not a sane reading of a limit set to zero,
and an operator who wants the feature off needs a way to say so. It still logs
what was asked for, so you can measure how many miners already send `d=` out of
habit before letting it change anything.
⚠️ Size that cap against your idle timeout rather than taste. A request lengthens
the connection's expected share interval, and an idle reaper measures inbound
silence: at 50M a 25 TH/s connection expects a share roughly every 8600s and
would be reaped from a 3600s budget while mining perfectly well.
Six tests. The load-bearing one is that `d=1` does NOT lower a connection —
mutation-verified: turning the floor into an assignment fails it. The
zero-cap test is the negative control for the cap test; without it "capped" and
"switched off" are indistinguishable from one passing assertion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A miner has no way to influence its difficulty today.
mining.suggest_difficultyis a standard stratum method and isn't handled, and the password field is ignored — so an ESP-Miner, which sendssuggest_difficultyunprompted on connect, is silently disregarded on every pool running this.Two channels, one meaning:
d=<n>in the stratum password, matched at a token boundary soid=7isn't a request. cgminer, bosminer, Vnish and LuxOS all expose this field, which makes it the request channel with the widest reach.mining.suggest_difficulty, the formal method. Either can arrive before or after authorize; both end up in the same place.It's a floor, never a pin
Vardiff may raise the connection above it and the network-difficulty clamp still wins over it, but nothing lowers the connection below it.
A pin would be a denial-of-service hole:
d=1from a 400 TH/s miner is ~93,000 shares/sec aimed at the share pipeline. As a floor that same request is inert —max(1, whatever vardiff chose)is just vardiff's answer — while a miner asking to go higher, which is the real request, gets exactly what it asked for.The floor is re-applied inside the vardiff retarget, not only at authorize. Without that the request lasts exactly one window: vardiff sees a rate under target — which is the point of a higher difficulty — and drags it straight back down.
Why a miner needs this
Vardiff tunes each connection toward
vardiff_target_spm, but a proxied fleet spreads one rig across many connections, so the rig seestarget_spm × N. At a uniform difficulty the rig's total share rate isH/(D·2³²)— the connection count cancels — so letting the miner nameDis the one lever that works regardless of how its hashrate is split.max_suggested_diff, default 5e7<= 0disables requests rather than uncapping them. "No ceiling" isn't a sane reading of a limit set to zero, and an operator who wants the feature off needs a way to say so. It still logs what was asked for, so you can measure how many of your miners already sendd=out of habit from other pools before letting it change anything.idle_timeout_authorized_secrather than taste. A request lengthens the connection's expected share interval and the reaper measures inbound silence: at 50M a 25 TH/s connection expects a share roughly every 8600s, past the 7200s default — it'd be reaped while mining perfectly well.Interaction with listener policy
A request is clamped by the network ceiling,
max_suggested_diff, and the listener'spol_vardiff_max. It's also raised topol_min_diffbyclamp_assigned_difficulty, so on a listener that promises a floor, a lowball request degrades to that floor rather than being refused — deliberate, and worth knowing.At retarget the miner's floor is applied before the listener clamps, so listener policy outranks the miner's wish.
Tests
Six. The load-bearing one is that
d=1does not lower a connection — mutation-verified: turning the floor into an assignment fails it. The zero-cap test is the negative control for the cap test; without it, "capped" and "feature switched off" are indistinguishable from one passing assertion.Note on threading
No lock is taken.
c->difficultyhas a single writer — the connection's own thread — and these writes are on that thread. The broadcast thread already reads it unsynchronized inconn_record_job_difficulty, racing the existing vardiff write exactly as it races these, so locking here alone would guard nothing. Flagged in a comment because anyone adding a broadcast-side write would break the property this relies on.