diff options
| author | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-02 05:44:41 +0000 |
|---|---|---|
| committer | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-02 05:44:41 +0000 |
| commit | a3666bded1553b101b631d87e99961bf3ccd0a3e (patch) | |
| tree | 7b351f42899bb5f38d6b1efdaf54cf04b8456d69 /src/sha.cpp | |
| parent | d7b1e8a1d54192df2fcf633fbcdffb43389ff8e2 (diff) | |
pool: refuse a (job, nonce) pair this connection already submitted
mining.submit validated the nonce, rebuilt the block, re-hashed it with
RandomX -- and never asked whether it had seen this exact (job_id,
nonce) pair before. Nothing in that pipeline distinguishes a replay
from a first submission: a duplicated valid share passes every check
and lands in roundShareCount[address]++ a second time, and
roundShareCount is the divisor the payout split uses, so replaying one
valid share N times multiplies that address's cut of the round by N.
Keep a per-connection set of credited nonces on the Miner, reject a
repeat with a "Duplicate share" stratum error before the rebuild and
hash it would waste, and record the nonce at the moment the share is
credited. The set is keyed to the job id the miner is currently working
and cleared inside SendJob -- the single funnel every new-job path
(initial authorize, block found, new block, 60s refresh, no-job
watchdog, vardiff retargets) goes through -- so legitimate
resubmissions across jobs are never refused. The clear is keyed on the
id rather than unconditional because the vardiff retarget and stall
watchdog re-send the CURRENT job, and an unconditional clear there
would reopen the very replay window this closes. Job ids come from a
monotonic atomic counter in RebuildJob, so an id is never recycled
within a process.
Closes #8
Diffstat (limited to 'src/sha.cpp')
0 files changed, 0 insertions, 0 deletions