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.cpp | |
| 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.cpp')
| -rw-r--r-- | src/net.cpp | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/src/net.cpp b/src/net.cpp index 5cf2f8c..964097b 100644 --- a/src/net.cpp +++ b/src/net.cpp | |||
| @@ -1700,6 +1700,13 @@ void ThreadMessageHandler(void* parg) | |||
| 1700 | } | 1700 | } |
| 1701 | } | 1701 | } |
| 1702 | 1702 | ||
| 1703 | // When any peer last told us a height. A wedged node -- one that still has | ||
| 1704 | // peers but has stopped hearing them -- is exactly a node where this stops | ||
| 1705 | // advancing, and that is the one thing the height comparison itself cannot | ||
| 1706 | // see: there is no height to compare. | ||
| 1707 | static int64 nLastPeerHeightSeen = 0; | ||
| 1708 | static int64 nPeerHeightFirstAsked = 0; | ||
| 1709 | |||
| 1703 | int GetPeerMedianHeight() | 1710 | int GetPeerMedianHeight() |
| 1704 | { | 1711 | { |
| 1705 | vector<int> vHeights; | 1712 | vector<int> vHeights; |
| @@ -1711,10 +1718,26 @@ int GetPeerMedianHeight() | |||
| 1711 | if (vHeights.empty()) | 1718 | if (vHeights.empty()) |
| 1712 | return -1; | 1719 | return -1; |
| 1713 | 1720 | ||
| 1721 | nLastPeerHeightSeen = GetTime(); | ||
| 1714 | sort(vHeights.begin(), vHeights.end()); | 1722 | sort(vHeights.begin(), vHeights.end()); |
| 1715 | return vHeights[vHeights.size() / 2]; | 1723 | return vHeights[vHeights.size() / 2]; |
| 1716 | } | 1724 | } |
| 1717 | 1725 | ||
| 1726 | // Seconds since any peer last reported a height. | ||
| 1727 | // | ||
| 1728 | // Before ever hearing one, measure from the first time somebody asked rather | ||
| 1729 | // than from the epoch -- otherwise a node refuses jobs the instant it starts, | ||
| 1730 | // before it has had a chance to complete a single handshake. | ||
| 1731 | int64 GetPeerHeightAgeSecs() | ||
| 1732 | { | ||
| 1733 | int64 nNow = GetTime(); | ||
| 1734 | if (nPeerHeightFirstAsked == 0) | ||
| 1735 | nPeerHeightFirstAsked = nNow; | ||
| 1736 | if (nLastPeerHeightSeen == 0) | ||
| 1737 | return nNow - nPeerHeightFirstAsked; | ||
| 1738 | return nNow - nLastPeerHeightSeen; | ||
| 1739 | } | ||
| 1740 | |||
| 1718 | 1741 | ||
| 1719 | // Say out loud when we are behind the network. | 1742 | // Say out loud when we are behind the network. |
| 1720 | // | 1743 | // |