diff options
| author | bitflash-maintainer <noreply@bitflash.invalid> | 2026-08-11 20:52:09 +0000 |
|---|---|---|
| committer | bitflash-maintainer <noreply@bitflash.invalid> | 2026-08-19 22:48:27 +0000 |
| commit | e236d013e973fd00cbdbed4bea1e5f373c0d1236 (patch) | |
| tree | b184641daad4310cdef51dff8bece2743af29f8a /src/net.h | |
| parent | db2692dcd8984fe0e5a2a6a796f7b3cbee216c32 (diff) | |
pool: refuse jobs when no peer has reported a height for 20 minutes
The peer-height gate replaced a tip-age check that was wrong in both
directions. It is a strict improvement and it is still blind in the one
case that matters most.
When the node goes deaf -- peers still in vNodes, nothing arriving -- no
peer announces anything, GetPeerMedianHeight() returns -1, and the
fallback mines our best chain. That fallback is right for a node that has
not been told yet and wrong for a node that has stopped being able to
hear, and a height nobody sent cannot tell those apart. A wedged node is
exactly a node with no peer height information, so the gate was silent
for the whole of heights 3966-4085: 120 blocks, 5890.50 BTF voided.
Time can tell them apart. GetPeerHeightAgeSecs() measures how long since
any peer reported a height, counting from first use rather than the epoch
so a starting node does not refuse jobs before its first handshake. Past
20 minutes the pool stops issuing jobs and says so unconditionally in the
log. /poolmineblind overrides it: without an escape hatch a genuinely
isolated pool that is 90% of the hashrate could never restart its own
chain, which is the deadlock the tip-age check used to cause.
Also stop nStartingHeight from going stale. It was a snapshot taken once
during the version handshake and never touched again, so on a long-lived
connection the median is built from heights the peers had hours ago, and
the behind-the-network check drifts toward 'everyone is behind us' and
quietly stops firing. A peer that hands us a block is demonstrably at
least at that block's height.
(cherry picked from commit 0800c18faf703b4acde1b131d0b742d37a86d92b)
Diffstat (limited to 'src/net.h')
| -rw-r--r-- | src/net.h | 8 |
1 files changed, 8 insertions, 0 deletions
| @@ -120,6 +120,13 @@ static const unsigned int MAX_CONNECTIONS = 125; | |||
| 120 | // this long regardless of what is still buffered. | 120 | // this long regardless of what is still buffered. |
| 121 | static const int64 DISCONNECT_DRAIN_SECS = 60; | 121 | static const int64 DISCONNECT_DRAIN_SECS = 60; |
| 122 | 122 | ||
| 123 | // How long a pool may go without hearing a height from ANY peer before it | ||
| 124 | // stops issuing jobs. Long enough that ordinary peer churn and a quiet | ||
| 125 | // handshake window do not trip it; short enough that a deaf pool cannot build | ||
| 126 | // more than a few blocks of private fork before it is stopped. Heights | ||
| 127 | // 3966-4085 -- 120 blocks, 5890.50 BTF -- were mined in exactly this state. | ||
| 128 | static const int64 BTF_NO_PEER_HEIGHT_MAX_SECS = 20 * 60; | ||
| 129 | |||
| 123 | // Send a ping after this long with nothing to say, so a peer running the | 130 | // Send a ping after this long with nothing to say, so a peer running the |
| 124 | // inactivity check above does not mistake a quiet node for a dead one. Must | 131 | // inactivity check above does not mistake a quiet node for a dead one. Must |
| 125 | // stay well under BTF_RECV_TIMEOUT_SECS. | 132 | // stay well under BTF_RECV_TIMEOUT_SECS. |
| @@ -160,6 +167,7 @@ extern int nBestHeight; | |||
| 160 | // has told us anything. Median rather than maximum so one peer claiming an | 167 | // has told us anything. Median rather than maximum so one peer claiming an |
| 161 | // absurd height cannot move it. | 168 | // absurd height cannot move it. |
| 162 | int GetPeerMedianHeight(); | 169 | int GetPeerMedianHeight(); |
| 170 | int64 GetPeerHeightAgeSecs(); | ||
| 163 | 171 | ||
| 164 | // Lightweight .btf churn accounting. These counters are diagnostics only: they | 172 | // Lightweight .btf churn accounting. These counters are diagnostics only: they |
| 165 | // let an operator tell stale descriptors, relay pairing failures, and paired | 173 | // let an operator tell stale descriptors, relay pairing failures, and paired |