diff options
| author | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-02 17:13:06 +0000 |
|---|---|---|
| committer | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-02 17:13:06 +0000 |
| commit | ca03f8e9416837acfac825f02a6c592e07e0c4df (patch) | |
| tree | 209130adc821e853d389f10db25491df114d063f /src/main.cpp | |
| parent | 738d5b411bab4e13e176a11f8ae6e6f70337381e (diff) | |
worker: count a session as productive only if the pool sent a job
PoolParticipantMiner returned true from its normal cleanup path whether or
not the pool had ever sent work, so a pool that completed the tunnel and
then dropped was indistinguishable from a healthy one. The caller reset
nRetrySecs to 10 on every such "session", pinning the reconnect at a flat
10s and defeating the backoff in precisely the case it was added for. It
cleared nFailingSince as well, so the "failing for N minutes" line never
printed either -- the worker went back to idling silently.
Return true only once at least one well-formed mining.notify has arrived.
The existing early returns are unaffected: they already mean "no session",
which stays the right answer for any path that leaves the worker without
work, a failed hash-thread spawn included.
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/src/main.cpp b/src/main.cpp index b0cdab2..b0bdb8c 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -3662,6 +3662,14 @@ static void ParticipantHashWorker(ParticipantJobShared* sh, int idx, int nWorker | |||
| 3662 | RandomXDestroyMinerVM(vm); | 3662 | RandomXDestroyMinerVM(vm); |
| 3663 | } | 3663 | } |
| 3664 | 3664 | ||
| 3665 | // Run one participant session: resolve the pool, open the tunnel, subscribe, | ||
| 3666 | // hash, submit shares. Returns true only if the pool actually handed out work | ||
| 3667 | // -- at least one well-formed mining.notify arrived. Everything else is false, | ||
| 3668 | // including a tunnel that opened and was dropped before any job. | ||
| 3669 | // | ||
| 3670 | // The caller's reconnect backoff keys off this return value, so any path added | ||
| 3671 | // here that leaves the session without work MUST return false. "The session | ||
| 3672 | // ended tidily" is not the question being asked. | ||
| 3665 | static bool PoolParticipantMiner() | 3673 | static bool PoolParticipantMiner() |
| 3666 | { | 3674 | { |
| 3667 | // ------------------------------------------------------------------ | 3675 | // ------------------------------------------------------------------ |
| @@ -3944,6 +3952,7 @@ connected: | |||
| 3944 | uint256 target; | 3952 | uint256 target; |
| 3945 | double currentDifficulty = 1.0; // updated by mining.set_difficulty from pool | 3953 | double currentDifficulty = 1.0; // updated by mining.set_difficulty from pool |
| 3946 | bool haveJob = false; | 3954 | bool haveJob = false; |
| 3955 | bool gotAnyJob = false; // any job at all this session -- the return value | ||
| 3947 | bool gotSubscribeAck = false; | 3956 | bool gotSubscribeAck = false; |
| 3948 | bool gotAuthorizeAck = false; | 3957 | bool gotAuthorizeAck = false; |
| 3949 | int64 authWaitStart = 0; | 3958 | int64 authWaitStart = 0; |
| @@ -4060,8 +4069,9 @@ connected: | |||
| 4060 | jobId = newJobId; | 4069 | jobId = newJobId; |
| 4061 | memcpy(header, hdrBytes.data(), 80); | 4070 | memcpy(header, hdrBytes.data(), 80); |
| 4062 | memcpy(&target, tgtBytes.data(), 32); | 4071 | memcpy(&target, tgtBytes.data(), 32); |
| 4063 | haveJob = true; | 4072 | haveJob = true; |
| 4064 | nNonce = 1; | 4073 | gotAnyJob = true; |
| 4074 | nNonce = 1; | ||
| 4065 | { | 4075 | { |
| 4066 | std::lock_guard<std::mutex> lk(jobShared.mtx); | 4076 | std::lock_guard<std::mutex> lk(jobShared.mtx); |
| 4067 | memcpy(jobShared.header, header, 80); | 4077 | memcpy(jobShared.header, header, 80); |
| @@ -4197,7 +4207,11 @@ connected: | |||
| 4197 | (unsigned long long)hashesSinceSample, | 4207 | (unsigned long long)hashesSinceSample, |
| 4198 | (unsigned long long)sessionSharesSent, | 4208 | (unsigned long long)sessionSharesSent, |
| 4199 | (unsigned long long)sessionSharesAccepted); | 4209 | (unsigned long long)sessionSharesAccepted); |
| 4200 | return true; | 4210 | // Not "we got here", which is true of a tunnel the pool accepted and then |
| 4211 | // dropped without ever sending a job -- exactly the case the caller's | ||
| 4212 | // backoff exists for. Reaching the end of the session is not evidence the | ||
| 4213 | // session was worth anything; a job is. | ||
| 4214 | return gotAnyJob; | ||
| 4201 | } | 4215 | } |
| 4202 | 4216 | ||
| 4203 | // --------------------------------------------------------------------------- | 4217 | // --------------------------------------------------------------------------- |
| @@ -4394,17 +4408,23 @@ bool BitcoinMiner(int nThreadId) | |||
| 4394 | // Participant mode: connect to external pool instead of mining solo/operator | 4408 | // Participant mode: connect to external pool instead of mining solo/operator |
| 4395 | if (nMineMode == MINE_PARTICIPANT) | 4409 | if (nMineMode == MINE_PARTICIPANT) |
| 4396 | { | 4410 | { |
| 4397 | // An attempt that never got a session backs off (10s doubling to | 4411 | // An attempt that never got work backs off (10s doubling to 120s) |
| 4398 | // 120s) instead of hammering the same path every flat 10s, and a | 4412 | // instead of hammering the same path every flat 10s, and a streak |
| 4399 | // streak lasting minutes is said at printf level: the identical | 4413 | // lasting minutes is said at printf level: the identical once-per-10s |
| 4400 | // once-per-10s LogPrint line is how a worker idled all night | 4414 | // LogPrint line is how a worker idled all night unnoticed (issue #17). |
| 4401 | // unnoticed (issue #17). A completed session resets both. | 4415 | // |
| 4416 | // Only a session the pool actually sent a job to resets either. The | ||
| 4417 | // weaker test -- "the session returned" -- was gameable: a pool that | ||
| 4418 | // completes the tunnel and drops without ever sending work leaves by | ||
| 4419 | // the same tidy cleanup path a healthy one does, which would pin the | ||
| 4420 | // retry at 10s forever and defeat the backoff in exactly the scenario | ||
| 4421 | // it exists for. | ||
| 4402 | int nRetrySecs = 10; | 4422 | int nRetrySecs = 10; |
| 4403 | int64 nFailingSince = 0; | 4423 | int64 nFailingSince = 0; |
| 4404 | while (fGenerateBitcoins && nMineMode == MINE_PARTICIPANT && !fShutdown) { | 4424 | while (fGenerateBitcoins && nMineMode == MINE_PARTICIPANT && !fShutdown) { |
| 4405 | bool fHadSession = PoolParticipantMiner(); | 4425 | bool fGotWork = PoolParticipantMiner(); |
| 4406 | if (fGenerateBitcoins && nMineMode == MINE_PARTICIPANT && !fShutdown) { | 4426 | if (fGenerateBitcoins && nMineMode == MINE_PARTICIPANT && !fShutdown) { |
| 4407 | if (fHadSession) { | 4427 | if (fGotWork) { |
| 4408 | nRetrySecs = 10; | 4428 | nRetrySecs = 10; |
| 4409 | nFailingSince = 0; | 4429 | nFailingSince = 0; |
| 4410 | } else { | 4430 | } else { |
| @@ -4428,7 +4448,7 @@ bool BitcoinMiner(int nThreadId) | |||
| 4428 | for (int i = 0; i < nRetrySecs && !fShutdown && fGenerateBitcoins | 4448 | for (int i = 0; i < nRetrySecs && !fShutdown && fGenerateBitcoins |
| 4429 | && nMineMode == MINE_PARTICIPANT; i++) | 4449 | && nMineMode == MINE_PARTICIPANT; i++) |
| 4430 | Sleep(1000); | 4450 | Sleep(1000); |
| 4431 | if (!fHadSession && nRetrySecs < 120) { | 4451 | if (!fGotWork && nRetrySecs < 120) { |
| 4432 | nRetrySecs *= 2; | 4452 | nRetrySecs *= 2; |
| 4433 | if (nRetrySecs > 120) | 4453 | if (nRetrySecs > 120) |
| 4434 | nRetrySecs = 120; | 4454 | nRetrySecs = 120; |