Skip to content

Commit c050b17

Browse files
committed
dgb(#82): run-loop spine — io_context + graceful signal_set shutdown (--run)
Stand up the run-loop spine in main_dgb.cpp behind a new --run flag: a boost::asio::io_context plus an explicit graceful shutdown driven from signal_set(SIGINT, SIGTERM), mirroring main_btc.cpp s teardown contract. This is the lifecycle every node subsystem (sharechain peer dgb::Node, embedded digibyted P2P, Stratum acceptor) and the #82 won-block dispatch handler hangs off. Standing the spine up first keeps the next increments (node/Config construction over LevelDB, P2P listen, Stratum, and the m_on_block_found -> reconstruct_won_block -> broadcast_won_block binding landed across #163/#166/#167/#173/#174/#176/#177/#179) build-verifiable rather than landing a large unverified port in one step. --selftest / bare invocation unchanged (live ShareTracker::score() path). External digibyted RPC fallback posture preserved. Build: c2pool-dgb links EXIT=0 (-DCOIN_DGB=ON). Smoke: --selftest OK (block_period=75s SSOT); --run spine up, SIGINT -> clean shutdown exit 0.
1 parent 0c28591 commit c050b17

1 file changed

Lines changed: 80 additions & 17 deletions

File tree

src/c2pool/main_dgb.cpp

Lines changed: 80 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,32 @@
22
//
33
// Wires the real dgb sharechain/pool TU (pool pillars + score path, ported from
44
// LTC under impl/dgb/ across PRs #112/#113/#115/#121/#129/#131/#132/#134) into
5-
// the c2pool-dgb executable. This is the exe-wire slice: it replaces the
6-
// slice-#4 skeleton entry (dgb::run_skeleton/network_summary, removed when #134
7-
// dropped the real node.cpp in) and drives the LIVE chain-score path at
8-
// startup, so the coin smoke gate exercises share_tracker::score() rather than
9-
// merely linking it. node.cpp (the concrete dgb::NodeImpl) is compiled into the
10-
// target so the real node TU links; its full run-loop (NodeBridge over the
11-
// embedded digibyted P2P + Stratum) is a later Phase B slice — dgb::NodeImpl is
12-
// abstract (ICommunicator::handle is supplied by the NodeBridge wrapper), so a
13-
// bare node is not stood up here. The score path lives on dgb::ShareTracker,
14-
// which we drive directly (header-only, no network / no LevelDB).
5+
// the c2pool-dgb executable. Two entry paths:
6+
//
7+
// --selftest / bare : drive the LIVE dgb::ShareTracker::score() path so the
8+
// coin smoke gate exercises real consensus code, then exit.
9+
// --run : stand up the run-loop SPINE (this slice) — io_context +
10+
// graceful SIGINT/SIGTERM shutdown. The node/stratum/P2P
11+
// subsystems and the won-block dispatch binding
12+
// (m_on_block_found -> reconstruct_won_block ->
13+
// broadcast_won_block, #82 connecting tissue landed across
14+
// PRs #163/#166/#167/#173/#174/#176/#177/#179) bind onto
15+
// this io_context in the NEXT stacked slice. Standing the
16+
// spine up first gives those subsystems the lifecycle they
17+
// hang off and keeps each increment build-verifiable.
1518
//
1619
// V36 scope: Scrypt blocks validated; the other 4 DGB algos (SHA256d, Skein,
1720
// Qubit, Odocrypt) are accept-by-continuity / ignored — full 5-algo support is
1821
// V37. Conformance oracle: frstrtr/p2pool-dgb-scrypt (DGB-Scrypt standalone
1922
// parent; merged-v36 byte-compat WAIVED for DGB per operator 2026-06-17).
2023
// CoinParams are oracle-sourced via dgb::make_coin_params (no hardcoded bytes).
21-
// Mirrors src/c2pool/main_btc.cpp's target shape.
24+
// External digibyted RPC stays as a fallback alongside the embedded path.
25+
// Mirrors src/c2pool/main_btc.cpp s target shape.
2226

2327
#include <impl/dgb/node.hpp>
2428

29+
#include <boost/asio.hpp>
30+
2531
#include <cstdint>
2632
#include <cstring>
2733
#include <iostream>
@@ -31,6 +37,8 @@
3137
#define C2POOL_VERSION "dev"
3238
#endif
3339

40+
namespace io = boost::asio;
41+
3442
namespace {
3543

3644
// Live network summary sourced from the oracle-populated CoinParams
@@ -49,10 +57,11 @@ void print_banner(const char* argv0, const core::CoinParams& p)
4957
{
5058
std::cout
5159
<< "c2pool-dgb " << C2POOL_VERSION << " — DigiByte Scrypt-only (V36)\n\n"
52-
<< "Usage: " << argv0 << " [--version] [--help] [--selftest]\n\n"
53-
<< "Status: pool/sharechain pillars live (Phase B). The embedded-daemon\n"
54-
<< " run-loop (digibyted P2P + Stratum) lands in a later slice;\n"
55-
<< " external digibyted RPC stays as a fallback.\n"
60+
<< "Usage: " << argv0 << " [--version] [--help] [--selftest] [--run]\n\n"
61+
<< "Status: pool/sharechain pillars live (Phase B); run-loop spine up\n"
62+
<< " (--run: io_context + graceful shutdown). Node/stratum/P2P +\n"
63+
<< " won-block dispatch binding land in the next slice; external\n"
64+
<< " digibyted RPC stays as a fallback.\n"
5665
<< "Network: " << network_summary(p) << "\n";
5766
}
5867

@@ -84,19 +93,69 @@ int run_selftest(const core::CoinParams& params)
8493
return 0;
8594
}
8695

96+
// Run-loop SPINE. Stands up the io_context that every node subsystem
97+
// (sharechain peer dgb::Node, embedded digibyted P2P, Stratum acceptor) and
98+
// the #82 won-block dispatch handler will hang off, plus an explicit graceful
99+
// shutdown driven from boost::asio::signal_set.
100+
//
101+
// Why signal_set and not std::signal: std::signal handlers run in the
102+
// async-signal-only delivery context; io_context::stop is thread-safe but not
103+
// documented signal-safe. signal_set delivers SIGINT/SIGTERM as an ordinary
104+
// async callback on the io_context thread, so the shutdown path can do real
105+
// work (stop the stratum acceptor, close sessions) before ioc.stop() drains
106+
// the rest — mirrors main_btc.cpp s teardown contract.
107+
//
108+
// SEAM (next stacked slice): construct dgb::Config + dgb::Node(&ioc, &config),
109+
// listen on the sharechain P2P port, stand up the Stratum work source, and
110+
// bind make_on_block_found(reconstruct_won_block, p2p_sink) into
111+
// m_on_block_found so a won share reaches the network (closes #82). Those
112+
// subsystems open LevelDB + bind sockets, so they land as their own
113+
// build-verified increment rather than inline here.
114+
int run_node(const core::CoinParams& params)
115+
{
116+
io::io_context ioc;
117+
118+
bool shutdown_initiated = false;
119+
io::signal_set signals(ioc, SIGINT, SIGTERM);
120+
signals.async_wait(
121+
[&ioc, &shutdown_initiated](const boost::system::error_code& ec, int signo) {
122+
if (ec) return;
123+
if (shutdown_initiated) return;
124+
shutdown_initiated = true;
125+
126+
std::cout << "[DGB] received signal " << signo
127+
<< " — initiating graceful shutdown" << std::endl;
128+
// Next slice: stop stratum acceptor + close sessions here BEFORE
129+
// ioc.stop(), so their pending async ops cancel cleanly.
130+
ioc.stop();
131+
});
132+
133+
std::cout << "[DGB] run-loop spine up: " << network_summary(params) << "\n";
134+
std::cout << "[DGB] io_context running. Ctrl-C to stop. "
135+
<< "(node/stratum/P2P + won-block dispatch bind in the next slice)"
136+
<< std::endl;
137+
138+
ioc.run();
139+
140+
std::cout << "[DGB] io_context stopped — clean exit" << std::endl;
141+
return 0;
142+
}
143+
87144
} // namespace
88145

89146
int main(int argc, char** argv)
90147
{
91148
bool want_help = false;
92149
bool want_selftest = false;
150+
bool want_run = false;
93151
for (int i = 1; i < argc; ++i) {
94152
if (std::strcmp(argv[i], "--version") == 0) {
95153
std::cout << "c2pool-dgb " << C2POOL_VERSION << "\n";
96154
return 0;
97155
}
98156
if (std::strcmp(argv[i], "--help") == 0) want_help = true;
99157
if (std::strcmp(argv[i], "--selftest") == 0) want_selftest = true;
158+
if (std::strcmp(argv[i], "--run") == 0) want_run = true;
100159
}
101160

102161
const core::CoinParams params = dgb::make_coin_params(/*testnet=*/false);
@@ -105,8 +164,12 @@ int main(int argc, char** argv)
105164
if (want_help)
106165
return 0;
107166

108-
// --selftest, or a bare invocation (no run-loop yet): drive the live score
109-
// path so the binary exercises real consensus code, then exit cleanly.
167+
// --run: stand up the run-loop spine (io_context + graceful shutdown).
168+
if (want_run)
169+
return run_node(params);
170+
171+
// --selftest, or a bare invocation: drive the live score path so the
172+
// binary exercises real consensus code, then exit cleanly.
110173
(void)want_selftest;
111174
return run_selftest(params);
112175
}

0 commit comments

Comments
 (0)