From ae865ac160350954c51f5aeb5363852b4cf4a1f6 Mon Sep 17 00:00:00 2001 From: frstrtr Date: Wed, 1 Jul 2026 17:17:58 +0000 Subject: [PATCH] =?UTF-8?q?dgb:=20consume=20DGB=20merged-mining=20seam=20?= =?UTF-8?q?=E2=80=94=20embedded=20AuxChainEmbedded=20backend=20+=20AUXPOW?= =?UTF-8?q?=5FCHAIN=5FID=20+=20registration=20(-DAUX=5FDOGE=3DON)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/c2pool/c2pool_refactored.cpp | 50 ++++++ src/impl/dgb/coin/aux_chain_embedded.hpp | 184 +++++++++++++++++++++++ src/impl/dgb/params.hpp | 12 ++ 3 files changed, 246 insertions(+) create mode 100644 src/impl/dgb/coin/aux_chain_embedded.hpp diff --git a/src/c2pool/c2pool_refactored.cpp b/src/c2pool/c2pool_refactored.cpp index dc20036b7..631294447 100644 --- a/src/c2pool/c2pool_refactored.cpp +++ b/src/c2pool/c2pool_refactored.cpp @@ -262,6 +262,10 @@ static void segfault_handler(int sig) { #include // 2b-ii: embedded NMC merged-mining backend (host activation) #include +// DGB's own embedded merged-mining backend (DC seam, -DAUX_DOGE=ON). +// Header is fully wrapped in #ifdef AUX_DOGE -> compiles to nothing when off. +#include +#include // dgb::make_coin_params (SubsidyFunc), dgb::AUXPOW_CHAIN_ID // V36-compatible operational features #include @@ -5040,6 +5044,13 @@ int main(int argc, char* argv[]) { std::unique_ptr nmc_chain; std::unique_ptr nmc_pool; std::unique_ptr nmc_params_ptr; +#ifdef AUX_DOGE + // DGB's own embedded aux chain objects (DC seam; mirror DOGE/NMC). + // Guarded: the DGB HeaderChain/Mempool types are only visible via + // the self-guarded aux_chain_embedded.hpp include under AUX_DOGE. + std::unique_ptr dgb_aux_chain; + std::unique_ptr dgb_aux_pool; +#endif // AUX_DOGE // DOGE UTXO set for fee computation (no segwit/MWEB — simplified) std::unique_ptr doge_utxo_db; std::unique_ptr doge_utxo_cache; @@ -5310,6 +5321,45 @@ int main(int argc, char* argv[]) { << cfg.rpc_host << ":" << cfg.rpc_port; } } + } else if (cfg.symbol == "DGB") { +#ifdef AUX_DOGE + // DGB's OWN embedded merged-mining backend (DC seam). + // Mirrors the NMC embedded block: lazily build a DGB + // HeaderChain + Mempool, register AuxChainEmbedded as + // primary, wire the embedded P2P relay, and keep an + // AuxChainRPC (digibyted) fallback. + if (!dgb_aux_chain) + dgb_aux_chain = std::make_unique(); + if (!dgb_aux_pool) + dgb_aux_pool = std::make_unique(); + { + // DGB subsidy schedule (config_coin.hpp SSOT) feeds + // the embedded coinbasevalue via the #207 resolver. + auto dgb_cp = dgb::make_coin_params(settings->m_testnet); + auto backend = std::make_unique( + *dgb_aux_chain, *dgb_aux_pool, dgb_cp.subsidy_func, cfg); + // Embedded P2P relay for DGB flows through the + // manager-level set_block_relay_fn wired below + // (same route the DOGE embedded backend uses); + // submit_block() is log+cache, the network write + // is that relay via the CoinBroadcaster. + mm_manager->add_chain(cfg, std::move(backend)); + LOG_INFO << "Merged mining: DGB embedded (primary) chain_id=" << cfg.chain_id; + // digibyted RPC fallback (embedded primary persists). + if (cfg.rpc_port > 0 && !cfg.rpc_userpass.empty()) { + auto rpc_fallback = std::make_unique(ioc, cfg); + mm_manager->set_fallback_backend(cfg.chain_id, std::move(rpc_fallback)); + LOG_INFO << "Merged mining: DGB RPC fallback at " + << cfg.rpc_host << ":" << cfg.rpc_port; + } + } +#else + // Without -DAUX_DOGE the DGB embedded backend is absent; + // fall through to the standard RPC path so the seam is a + // no-op rather than a broken reference. + mm_manager->add_chain(cfg); + LOG_INFO << "Merged mining: added DGB via RPC (AUX_DOGE off) chain_id=" << cfg.chain_id; +#endif // AUX_DOGE } else { // Non-DOGE chain or no P2P — standard RPC path mm_manager->add_chain(cfg); diff --git a/src/impl/dgb/coin/aux_chain_embedded.hpp b/src/impl/dgb/coin/aux_chain_embedded.hpp new file mode 100644 index 000000000..2b88bb31b --- /dev/null +++ b/src/impl/dgb/coin/aux_chain_embedded.hpp @@ -0,0 +1,184 @@ +#pragma once +// =========================================================================== +// dgb::coin::AuxChainEmbedded -- DGB's OWN embedded merged-mining backend. +// +// Registers against the shared c2pool::merged::IAuxChainBackend (the DC +// merged-mining seam, src/c2pool/merged/merged_mining.hpp), giving DGB a +// daemonless aux-chain work source built ENTIRELY from in-process embedded +// chain state: the DGB HeaderChain (coin/header_chain.hpp) + EmbeddedCoinNode +// (coin/embedded_coin_node.hpp), with NO external digibyted RPC. +// +// This is the DGB analogue of doge::coin::AuxChainEmbedded and +// nmc::coin::AuxChainEmbedded -- PATTERN-mirrored from the DOGE class, but every +// consensus/identity value is DGB-native: chain_id is dgb::AUXPOW_CHAIN_ID +// (0x1AFE, NEVER DOGE's 0x0062), and the work template flows through the DGB +// build_work_template SSOT via EmbeddedCoinNode::getwork(). +// +// Work / submit contract (identical to the DOGE mirror): +// get_work_template() / create_aux_block() -> EmbeddedCoinNode::getwork(), +// GATED on is_synced() -- returns {} (empty AuxWork) until the embedded +// header-download ingest reports synced. DGB EmbeddedCoinNode::is_synced() +// is currently a truthful `false`, so this correctly returns not-ready +// work today (the empty-work contract, not a bug). +// submit_block() -> the REAL submit path: P2P relay is wired by the +// manager's set_block_relay_fn / a registration-site relay lambda +// (CoinBroadcaster). This method logs + caches the block hex for +// get_block_hex() retrieval; it does NOT itself touch the network. +// submit_aux_block() -> LOG-ONLY diagnostic fallback (no daemon to submit +// to). Mirrors the DOGE class exactly: log, return true. +// +// -DAUX_DOGE=ON only: this backend is part of the merged-mining seam that is +// compiled solely under the AUX_DOGE stretch flag (mirrors coin/node.hpp). +// =========================================================================== + +#ifdef AUX_DOGE + +#include +#include +#include +#include + +#include // core::SubsidyFunc +#include + +#include "header_chain.hpp" // c2pool::dgb::HeaderChain +#include "embedded_coin_node.hpp" // dgb::coin::EmbeddedCoinNode +#include "hash_format.hpp" // dgb::coin::u256_be_display_hex SSOT +#include "mempool.hpp" // dgb::coin::Mempool + +#include // dgb::AUXPOW_CHAIN_ID (bucket-1 SSOT) + +#include + +namespace dgb { +namespace coin { + +class AuxChainEmbedded : public c2pool::merged::IAuxChainBackend +{ +public: + // Mirror of doge::coin::AuxChainEmbedded, adapted to the DGB EmbeddedCoinNode + // ctor shape (HeaderChain& + SubsidyFunc + optional tx_source). The Mempool& + // is held for parity/future embedded fee wiring; fee-selected txs reach the + // node via an injected EmbeddedTxSource at the registration site, not here. + AuxChainEmbedded( + c2pool::dgb::HeaderChain& chain, + dgb::coin::Mempool& pool, + core::SubsidyFunc subsidy_func, + const c2pool::merged::AuxChainConfig& config, + dgb::coin::EmbeddedTxSource tx_source = {}) + : m_chain(chain) + , m_pool(pool) + , m_config(config) + , m_embedded(chain, std::move(subsidy_func), std::move(tx_source)) + {} + + bool connect() override { + // No RPC connection needed -- the embedded node is always "connected". + LOG_INFO << "[MM:" << m_config.symbol << "] Embedded backend ready (no daemon needed)"; + return true; + } + + c2pool::merged::AuxWork get_work_template() override { + // Empty-work contract: no work until the embedded header chain is synced. + // DGB EmbeddedCoinNode::is_synced() is a truthful `false` until the + // header-download ingest is wired, so this returns {} today -- correct. + if (!m_embedded.is_synced()) { + LOG_DEBUG_COIND << "[MM:" << m_config.symbol << "] Embedded: not synced" + << " (height=" << m_chain.tip_height().value_or(0) + << "), returning empty work"; + return {}; + } + + auto wd = m_embedded.getwork(); + + c2pool::merged::AuxWork work; + work.height = wd.m_data.value("height", 0); + work.coinbase_value = wd.m_data.value("coinbasevalue", uint64_t(0)); + work.chain_id = dgb::AUXPOW_CHAIN_ID; // DGB-native; never DOGE's 98 + work.block_template = wd.m_data; + + if (wd.m_data.contains("previousblockhash")) + work.prev_block_hash = wd.m_data["previousblockhash"].get(); + + // Target from bits. The DGB embedded template HOLDS BACK `bits` + // (Scrypt-only slice: a single-algo walk cannot emit the 5-algo + // MultiShield difficulty), so this branch is inert until an external + // bits source is plumbed. Left in place to mirror the DOGE seam exactly. + if (wd.m_data.contains("bits")) { + uint32_t bits = static_cast( + std::stoul(wd.m_data["bits"].get(), nullptr, 16)); + work.target.SetCompact(bits); + } + + // Aux block hash for the AuxPoW commitment -- the DGB tip's block id + // (sha256d over the 80-byte header), rendered via the DGB display-hex + // SSOT. tip_hash() is nullopt until the header ingest fills block_hash, + // so this stays a truthful absence rather than a fabricated hash. + if (auto th = m_chain.tip_hash()) + work.block_hash = uint256S(u256_be_display_hex(*th)); + + return work; + } + + c2pool::merged::AuxWork create_aux_block(const std::string& /*address*/) override { + return get_work_template(); + } + + bool submit_block(const std::string& block_hex) override { + // Embedded mode: the REAL submit path. P2P relay is performed by the + // CoinBroadcaster via the registration-site relay lambda / the manager's + // set_block_relay_fn -- this method logs + caches the block hex so + // get_block_hex() can hand it to the relay after submission. + LOG_INFO << "[MM:" << m_config.symbol << "] Embedded: block submitted (" + << block_hex.size() / 2 << " bytes)" + << " header=" << block_hex.substr(0, std::min(size_t(160), block_hex.size())); + m_last_block_hex = block_hex; + return true; + } + + bool submit_aux_block(const uint256& block_hash, const std::string& auxpow_hex) override { + // Log-only diagnostic fallback (mirror of the DOGE class). Embedded mode + // has no daemon to RPC submitauxblock -- the frozen-block path + // (submit_block + P2P relay) is the primary submission route. + LOG_WARNING << "[MM:" << m_config.symbol << "] Embedded: submit_aux_block called" + << " (fallback path) hash=" << block_hash.GetHex().substr(0, 16) << "..." + << " auxpow=" << auxpow_hex.size() / 2 << " bytes" + << " -- no daemon to submit to, relying on P2P relay"; + return true; + } + + std::string get_block_hex(const std::string& /*block_hash*/) override { + // Return the last submitted block hex (for P2P relay after submission). + if (!m_last_block_hex.empty()) + return m_last_block_hex; + return {}; + } + + std::string get_best_block_hash() override { + if (auto th = m_chain.tip_hash()) + return u256_be_display_hex(*th); + return ""; + } + + std::vector getpeerinfo() override { + // No daemon peers -- the P2P broadcaster handles its own peer discovery. + return {}; + } + + const c2pool::merged::AuxChainConfig& config() const override { return m_config; } + + /// Expose the embedded node for sync-gate / tx-source wiring at registration. + EmbeddedCoinNode& embedded_node() { return m_embedded; } + +private: + c2pool::dgb::HeaderChain& m_chain; + dgb::coin::Mempool& m_pool; + c2pool::merged::AuxChainConfig m_config; + EmbeddedCoinNode m_embedded; + std::string m_last_block_hex; // cached for get_block_hex() after submit +}; + +} // namespace coin +} // namespace dgb + +#endif // AUX_DOGE diff --git a/src/impl/dgb/params.hpp b/src/impl/dgb/params.hpp index 3d3769cd4..74e1b645e 100644 --- a/src/impl/dgb/params.hpp +++ b/src/impl/dgb/params.hpp @@ -24,6 +24,18 @@ namespace dgb { +// --- Merged-mining aux chain identity (bucket-1 isolation primitive) --------- +// DGB's OWN AuxPoW chain id, consumed when DGB registers an embedded backend +// against c2pool::merged::IAuxChainBackend (the DC merged-mining seam, -DAUX_DOGE). +// +// Derivation: the low 16 bits of DGB's network IDENTIFIER 0x4B62545B1A631AFE +// (PoolConfig::IDENTIFIER_HEX, the "switch-oracle" DGB SSOT) -> 0x1AFE (6910). +// This is a DGB-native value with no shared derivation with any other coin, so +// it CANNOT collide: DOGE = 0x0062 (98), NMC = 0x0001 -- both distinct from +// 0x1AFE. Kept per-coin (bucket-1) exactly like DOGEChainParams::AUXPOW_CHAIN_ID +// and nmc::coin::NMC_AUXPOW_CHAIN_ID; NEVER reuse DOGE's 98. +inline constexpr uint32_t AUXPOW_CHAIN_ID = 0x1AFE; // 6910 = low16(IDENTIFIER) + inline core::CoinParams make_coin_params(bool testnet) { core::CoinParams p;