Skip to content

Commit cacda88

Browse files
committed
Coalesce bestblock notifications to prevent event loop freeze
Multiple peers announcing the same block caused N full MWEB+PPLNS rebuild cycles (~800ms each), saturating the io_context and triggering the freeze watchdog. Use a 50ms steady_timer to coalesce rapid bestblock notifications into a single refresh — mirrors p2pool's natural Twisted reactor coalescing.
1 parent 03e7cc5 commit cacda88

2 files changed

Lines changed: 30 additions & 7 deletions

File tree

src/c2pool/c2pool_refactored.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,12 +2631,35 @@ int main(int argc, char* argv[]) {
26312631

26322632
// Block scan moved AFTER callbacks are wired (see below)
26332633

2634-
// When a peer announces a new best block, refresh our mining template
2635-
p2p_node->set_on_bestblock([&web_server, &p2p_node]() {
2636-
web_server.trigger_work_refresh();
2637-
// p2pool: bitcoind_work.changed → set_best_share() → think()
2638-
p2p_node->run_think();
2639-
LOG_INFO << "[LTC] bestblock received from P2P peer — work+think refreshed";
2634+
// When a peer announces a new best block, refresh our mining template.
2635+
// Coalesce: multiple peers (or duplicate inv) announcing the same block
2636+
// within a short window triggers only ONE expensive refresh cycle.
2637+
// p2pool is naturally immune (Twisted reactor tick coalesces), we must
2638+
// do it explicitly.
2639+
auto bestblock_timer = std::make_shared<boost::asio::steady_timer>(ioc);
2640+
auto bestblock_pending = std::make_shared<bool>(false);
2641+
2642+
p2p_node->set_on_bestblock([&web_server, &p2p_node,
2643+
bestblock_timer, bestblock_pending]() {
2644+
// Mark that a refresh is needed
2645+
*bestblock_pending = true;
2646+
2647+
// Coalesce: cancel any pending timer and restart the 50ms window.
2648+
// If bestblocks keep arriving, we keep deferring until a 50ms gap.
2649+
// 50ms is imperceptible to miners but collapses N duplicate
2650+
// announcements into a single MWEB+PPLNS rebuild.
2651+
bestblock_timer->expires_after(std::chrono::milliseconds(50));
2652+
bestblock_timer->async_wait([&web_server, &p2p_node,
2653+
bestblock_pending](const boost::system::error_code& ec) {
2654+
if (ec) return; // cancelled by a newer bestblock — good
2655+
if (!*bestblock_pending) return;
2656+
*bestblock_pending = false;
2657+
2658+
web_server.trigger_work_refresh();
2659+
// p2pool: bitcoind_work.changed → set_best_share() → think()
2660+
p2p_node->run_think();
2661+
LOG_INFO << "[LTC] bestblock received from P2P peer — work+think refreshed";
2662+
});
26402663
});
26412664

26422665
// When best_share changes (new share on chain), refresh work for all

src/core/web_server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7482,7 +7482,7 @@ void WebServer::trigger_work_refresh()
74827482
mining_interface_->refresh_work();
74837483
// Push new work to all miners immediately (p2pool: new_work_event).
74847484
// Old jobs stay valid — miner submits by job_id, which maps to frozen data.
7485-
// Stale shares only occur when MAX_ACTIVE_JOBS (32) is exceeded.
7485+
// Stale shares only occur when MAX_ACTIVE_JOBS (256) is exceeded.
74867486
if (stratum_server_)
74877487
stratum_server_->notify_all();
74887488
}

0 commit comments

Comments
 (0)