Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions src/c2pool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,31 @@ target_link_libraries(c2pool-btc
# json/Boost. Per-coin isolation held. The embedded run-loop (NodeBridge over
# digibyted P2P + Stratum) and its pool-runtime link land in a later Phase B
# slice.
add_executable(c2pool-dgb
main_dgb.cpp
${CMAKE_SOURCE_DIR}/src/core/uint256.cpp
)
# RUN-LOOP slice (#82): main_dgb.cpp --run now constructs dgb::Config + the
# dgb::Node sharechain peer (pool::NodeBridge<NodeImpl,...>) and binds its P2P
# listener, so the exe must link the real dgb pool runtime — not just the
# header-only score path. We link the `dgb` OBJECT lib (node.cpp + protocol
# handlers) and the shared core/pool/sharechain/storage base it sits on,
# mirroring the c2pool-btc link set. c2pool_merged_mining is pulled for SYMBOL
# RESOLUTION of the core web_server/stratum tangle ONLY (same reason c2pool-btc
# links it) — it does NOT enable -DAUX_DOGE; DGB default build stays standalone
# (no DOGE aux). core provides core/uint256.cpp, so the explicit source is
# dropped to avoid a duplicate-symbol link. Per-coin isolation holds: only the
# c2pool-dgb target stanza changes.
add_executable(c2pool-dgb main_dgb.cpp)
target_compile_definitions(c2pool-dgb PRIVATE C2POOL_VERSION="${C2POOL_GIT_VERSION}")
target_link_libraries(c2pool-dgb
btclibs # STATIC util lib: HexStr/HexDigit (strencodings) for base_uint hex - pure utility, no pool runtime
yaml-cpp::yaml-cpp # config_{coin,pool}.hpp -> core/netaddress.hpp -> <yaml-cpp/yaml.h>
c2pool_payout
c2pool_merged_mining # symbol resolution for core web_server tangle (NOT -DAUX_DOGE)
c2pool_hashrate
core
dgb # DGB pool-layer OBJECT lib: node.cpp NodeImpl + protocol handlers
dgb_coin # DGB coin-layer: embedded P2P + mempool + transaction ctors
pool
sharechain
c2pool_storage
btclibs
yaml-cpp::yaml-cpp
nlohmann_json::nlohmann_json
${Boost_LIBRARIES}
)
Expand Down
144 changes: 127 additions & 17 deletions src/c2pool/main_dgb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,48 @@
//
// Wires the real dgb sharechain/pool TU (pool pillars + score path, ported from
// LTC under impl/dgb/ across PRs #112/#113/#115/#121/#129/#131/#132/#134) into
// the c2pool-dgb executable. This is the exe-wire slice: it replaces the
// slice-#4 skeleton entry (dgb::run_skeleton/network_summary, removed when #134
// dropped the real node.cpp in) and drives the LIVE chain-score path at
// startup, so the coin smoke gate exercises share_tracker::score() rather than
// merely linking it. node.cpp (the concrete dgb::NodeImpl) is compiled into the
// target so the real node TU links; its full run-loop (NodeBridge over the
// embedded digibyted P2P + Stratum) is a later Phase B slice — dgb::NodeImpl is
// abstract (ICommunicator::handle is supplied by the NodeBridge wrapper), so a
// bare node is not stood up here. The score path lives on dgb::ShareTracker,
// which we drive directly (header-only, no network / no LevelDB).
// the c2pool-dgb executable. Two entry paths:
//
// --selftest / bare : drive the LIVE dgb::ShareTracker::score() path so the
// coin smoke gate exercises real consensus code, then exit.
// --run : stand up the run-loop SPINE (this slice) — io_context +
// graceful SIGINT/SIGTERM shutdown. The node/stratum/P2P
// subsystems and the won-block dispatch binding
// (m_on_block_found -> reconstruct_won_block ->
// broadcast_won_block, #82 connecting tissue landed across
// PRs #163/#166/#167/#173/#174/#176/#177/#179) bind onto
// this io_context in the NEXT stacked slice. Standing the
// spine up first gives those subsystems the lifecycle they
// hang off and keeps each increment build-verifiable.
//
// V36 scope: Scrypt blocks validated; the other 4 DGB algos (SHA256d, Skein,
// Qubit, Odocrypt) are accept-by-continuity / ignored — full 5-algo support is
// V37. Conformance oracle: frstrtr/p2pool-dgb-scrypt (DGB-Scrypt standalone
// parent; merged-v36 byte-compat WAIVED for DGB per operator 2026-06-17).
// CoinParams are oracle-sourced via dgb::make_coin_params (no hardcoded bytes).
// Mirrors src/c2pool/main_btc.cpp's target shape.
// External digibyted RPC stays as a fallback alongside the embedded path.
// Mirrors src/c2pool/main_btc.cpp s target shape.

#include <impl/dgb/node.hpp>

#include <core/filesystem.hpp>
#include <btclibs/util/strencodings.h>

#include <boost/asio.hpp>

#include <cstdint>
#include <cstring>
#include <filesystem>
#include <iostream>
#include <string>
#include <system_error>

#ifndef C2POOL_VERSION
#define C2POOL_VERSION "dev"
#endif

namespace io = boost::asio;

namespace {

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

Expand Down Expand Up @@ -84,19 +98,111 @@ int run_selftest(const core::CoinParams& params)
return 0;
}

// Run-loop SPINE + sharechain peer bring-up. Stands up the io_context that
// every node subsystem hangs off, an explicit graceful shutdown driven from
// boost::asio::signal_set, and (this slice) constructs the dgb::Config +
// dgb::Node sharechain peer and binds its P2P listener.
//
// Why signal_set and not std::signal: std::signal handlers run in the
// async-signal-only delivery context; io_context::stop is thread-safe but not
// documented signal-safe. signal_set delivers SIGINT/SIGTERM as an ordinary
// async callback on the io_context thread, so the shutdown path can do real
// work (stop the stratum acceptor, close sessions) before ioc.stop() drains
// the rest — mirrors main_btc.cpp's teardown contract.
//
// SEAM (next stacked slice): stand up the Stratum work source and bind
// make_on_block_found(reconstruct_won_block, p2p_sink) into m_on_block_found
// so a won share reaches the network (closes #82's embedded P2P relay path);
// the submitblock RPC fallback (rpc.cpp:387, already real — NOT a stub) is the
// second arm of the dual-path broadcaster gate.
int run_node(const core::CoinParams& params, bool testnet)
{
io::io_context ioc;

// Per-coin config root: ~/.c2pool/<net>/ (sharechain LevelDB + addrs.json
// open underneath). Bucket-1 isolation primitive: DGB never shares LTC's
// net dir — keep the subdir per-coin in v36 AND v37.
const std::string net_subdir = testnet ? "digibyte_testnet" : "digibyte";
const std::filesystem::path net_dir =
core::filesystem::config_path() / net_subdir;
std::error_code mkdir_ec;
std::filesystem::create_directories(net_dir, mkdir_ec); // best effort

// dgb::Config = core::Config<PoolConfig, CoinConfig>. Skip Config::init()
// (it would load pool.yaml + coin.yaml from disk); set the sharechain
// identity directly from the oracle-sourced constants instead — the same
// contract main_btc.cpp uses for its net smoke. prefix/identifier come from
// the p2pool-dgb-scrypt oracle (PREFIX 1c0553f2…, IDENTIFIER 4b62545b…).
dgb::Config config(net_subdir);
config.pool()->m_prefix = ParseHexBytes(dgb::PoolConfig::DEFAULT_PREFIX_HEX);
config.m_testnet = testnet;
// DEFAULT_BOOTSTRAP_HOSTS is empty until DGB p2pool nodes come online, so
// there are no outbound seeds to dial this slice — the node binds its
// listener and waits for inbound sharechain peers.
for (const auto& host : dgb::PoolConfig::DEFAULT_BOOTSTRAP_HOSTS) {
const std::string addr = host.find(':') == std::string::npos
? host + ":" + std::to_string(dgb::PoolConfig::P2P_PORT)
: host;
config.pool()->m_bootstrap_addrs.emplace_back(addr);
}

bool shutdown_initiated = false;
io::signal_set signals(ioc, SIGINT, SIGTERM);
signals.async_wait(
[&ioc, &shutdown_initiated](const boost::system::error_code& ec, int signo) {
if (ec) return;
if (shutdown_initiated) return;
shutdown_initiated = true;

std::cout << "[DGB] received signal " << signo
<< " — initiating graceful shutdown" << std::endl;
// Next slice: stop stratum acceptor + close sessions here BEFORE
// ioc.stop(), so their pending async ops cancel cleanly. The
// sharechain peer's sockets close when p2p_node destructs at scope
// exit after ioc.run() returns.
ioc.stop();
});

// Sharechain peer node: pool::NodeBridge<NodeImpl, Legacy, Actual>. The
// NodeImpl ctor opens ~/.c2pool/<net>/sharechain_leveldb and seeds the addr
// store from m_bootstrap_addrs, so config must be populated BEFORE
// construction (above).
dgb::Node p2p_node(&ioc, &config);
p2p_node.set_target_outbound_peers(4);
p2p_node.core::Server::listen(dgb::PoolConfig::P2P_PORT);
std::cout << "[DGB] sharechain peer listening on port "
<< dgb::PoolConfig::P2P_PORT
<< " — proto adv=" << dgb::PoolConfig::ADVERTISED_PROTOCOL_VERSION
<< " min=" << dgb::PoolConfig::MINIMUM_PROTOCOL_VERSION
<< " prefix=" << dgb::PoolConfig::DEFAULT_PREFIX_HEX << std::endl;
p2p_node.start_outbound_connections(); // no-op until seed hosts exist

std::cout << "[DGB] run-loop up: " << network_summary(params) << "\n";
std::cout << "[DGB] io_context running. Ctrl-C to stop. "
<< "(Stratum work source + won-block dispatch bind in the next slice)"
<< std::endl;

ioc.run();

std::cout << "[DGB] io_context stopped — clean exit" << std::endl;
return 0;
}

} // namespace

int main(int argc, char** argv)
{
bool want_help = false;
bool want_selftest = false;
bool want_run = false;
for (int i = 1; i < argc; ++i) {
if (std::strcmp(argv[i], "--version") == 0) {
std::cout << "c2pool-dgb " << C2POOL_VERSION << "\n";
return 0;
}
if (std::strcmp(argv[i], "--help") == 0) want_help = true;
if (std::strcmp(argv[i], "--selftest") == 0) want_selftest = true;
if (std::strcmp(argv[i], "--run") == 0) want_run = true;
}

const core::CoinParams params = dgb::make_coin_params(/*testnet=*/false);
Expand All @@ -105,8 +211,12 @@ int main(int argc, char** argv)
if (want_help)
return 0;

// --selftest, or a bare invocation (no run-loop yet): drive the live score
// path so the binary exercises real consensus code, then exit cleanly.
// --run: stand up the run-loop spine (io_context + graceful shutdown).
if (want_run)
return run_node(params, /*testnet=*/false);

// --selftest, or a bare invocation: drive the live score path so the
// binary exercises real consensus code, then exit cleanly.
(void)want_selftest;
return run_selftest(params);
}
49 changes: 25 additions & 24 deletions src/impl/dgb/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# c2pool-dgb coin module (V36). Built when -DCOIN_DGB=ON.
# Mirrors src/impl/btc/CMakeLists.txt; emits the c2pool-dgb binary.
# c2pool-dgb coin module (V36). Mirrors src/impl/btc/CMakeLists.txt.
# Per-coin binary scheme: project_v36_per_coin_binary_v37_unified_process.
# Impl plan: c2pool-dgb-embedded-impl-plan.md (frstrtr/the docs/v36, 8ef8d2d).
#
Expand All @@ -11,30 +10,32 @@
# in this module yet: parked behind the Phase 5.8 settle (ltc-doge owns the
# shared DOGE-aux surface). Do not add AUX_DOGE plumbing here at M2.
#
# TODO(M3): add_library(impl_dgb ...) sources as an OBJECT lib (ci-steward
# PR-CMake-object-library convention; impl_dgb = 1 of 5 per-coin OBJECT libs),
# link bitcoin_family/Scrypt shared base, wire embedded DigiByte Core daemon
# slice under daemon/. Top-level add_subdirectory(src/impl/dgb) registration
# follows the OBJECT-lib convention PR; held ~2-3 heartbeats, not raced here.
# LIB GATING (mirrors btc/ltc): the dgb_coin (coin-layer) and dgb (pool-layer)
# OBJECT libs are defined UNCONDITIONALLY — the c2pool-dgb executable links
# them, and the coin-matrix CI builds that exe WITHOUT -DCOIN_DGB, so the
# targets MUST exist regardless of the flag (gating them behind COIN_DGB makes
# the linker fall back to raw -ldgb/-ldgb_coin and fail). Only the test subtree
# stays behind COIN_DGB; build.yml sets -DCOIN_DGB=ON and builds those targets.
add_subdirectory(coin)
# add_subdirectory(daemon)

# dgb -- DGB Scrypt pool-layer OBJECT lib. Mirrors the ltc/btc OBJECT lib:
# compiles the real NodeImpl translation unit (node.cpp + protocol handlers)
# so share_tracker.hpp / share_check.hpp are pulled into a compiled TU. Links
# the shared core / pool / sharechain base plus dgb_coin (embedded P2P+mempool)
# and c2pool_storage (LevelDB sharechain).
add_library(dgb OBJECT
config_coin.hpp config_coin.cpp config_pool.hpp config_pool.cpp
node.hpp node.cpp
peer.hpp
protocol_actual.cpp protocol_legacy.cpp
messages.hpp
share_types.hpp share.hpp
)
target_link_libraries(dgb core pool sharechain dgb_coin btclibs c2pool_storage ${SECP256K1_LIBRARIES})

if(COIN_DGB)
message(STATUS "c2pool: DGB Scrypt-only coin module enabled")
add_subdirectory(coin)
add_subdirectory(stratum) # dgb_stratum: IWorkSource (#82 miner-facing path)
# add_subdirectory(daemon)
add_subdirectory(test)

# dgb -- DGB Scrypt pool-layer OBJECT lib. Mirrors the ltc OBJECT lib
# (src/impl/ltc/CMakeLists.txt): compiles the real NodeImpl translation unit
# (node.cpp + protocol handlers) so share_tracker.hpp / share_check.hpp are
# pulled into a compiled TU. Links the shared core / pool / sharechain base
# plus dgb_coin (embedded P2P+mempool) and c2pool_storage (LevelDB sharechain).
add_library(dgb OBJECT
config_coin.hpp config_coin.cpp config_pool.hpp config_pool.cpp
node.hpp node.cpp
peer.hpp
protocol_actual.cpp protocol_legacy.cpp
messages.hpp
share_types.hpp share.hpp
)
target_link_libraries(dgb core pool sharechain dgb_coin btclibs c2pool_storage ${SECP256K1_LIBRARIES})
endif()
Loading