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>
3137#define C2POOL_VERSION " dev"
3238#endif
3339
40+ namespace io = boost::asio;
41+
3442namespace {
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
89146int 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