dash(S8): arm --stratum dashd-RPC fallback via NodeRPC::getwork()#726
Merged
Conversation
The run_node stratum standup shipped its dashd-RPC fallback arm as a stub returning an empty DashWorkData (documented set-gap default). This wires it to the EXISTING NodeRPC::getwork() seam -- the same rich getblocktemplate -> DashWorkData path run_mine_block already uses -- so the stratum run-path can serve real dashd work when the embedded-GBT arm is not the source. - main_dash.cpp run_node: dashd_fallback lambda now calls rpc->getwork() when the RPC arm is ARMED; when UNARMED (no dash.conf creds) it keeps the empty set-gap default and logs [DASH-STRATUM-GBT] loudly -- never a silent drop. - Lifetime-safe: rpc (unique_ptr, decl above work_source) outlives work_source, which owns this lambda; destroyed BEFORE rpc at scope exit. - dashd-RPC fallback RETAINED (never removed). No shared-base / other-coin edit; per-coin isolation held. Embedded-P2P relay leg stays S8-gated.
frstrtr
marked this pull request as ready for review
July 17, 2026 07:39
frstrtr
added a commit
that referenced
this pull request
Jul 17, 2026
…late path + X11 submit scoring (#733) * core(stratum): runtime coin_symbol replaces hardcoded [LTC] template-wait tag The coin-agnostic core hardcoded "[LTC]" in the send_notify_work no-template warning, so a DASH binary logged LTC and sent the operator diagnosing the wrong coin (#732 secondary defect). StratumConfig now carries a runtime coin_symbol -- LTC sets it in main_ltc.cpp, BTC/DGB in their work-source ctors (DASH follows in the 4c/4d commit) -- with a neutral [Stratum] fallback when unset. No coin name remains hardcoded in src/core. * dash(stratum): 4c/4d -- serve real work + X11 submit scoring (#732) Stage 4c (template serving): bridge the armed get_work() seam (#726, embedded coin-state when seeded / retained dashd GBT fallback -- duality preserved) into the template trio the coin-agnostic session consumes. DashWorkData is cached under template_mutex_ keyed on work_generation_ + a 30s staleness TTL (5s negative cache; tip-move bumps the generation). get_current_work_template() emits exactly the fields send_notify_work() reads with LTC/BTC byte conventions; merkle branches ride the existing merkle_branches_raw/_hex SSOT; build_connection_coinbase() goes through the verifier-shared compute_dash_payouts -> coinbase::build -> split_coinb SSOTs (coinb1/coinb2 around the 8-byte nonce64 extranonce slot), so the coinbase a miner hashes is byte-identical to the verifier split by construction. Genesis case (fresh pool, empty sharechain): the connecting miner's P2PKH script carries the full worker payout + the GBT-mandated masternode/superblock outputs + donation tail; the PPLNS multi-output path rides the new set_pplns_weights_fn seam through the same SSOT arm. Ctor pins set_difficulty_multiplier to 1.0 (X11 = standard diff-1 scale) -- the scrypt 65536 default inflated the advertised difficulty 65536x (the wire=32.768 in the field report). Stage 4d (submit scoring): mining_submit() reassembles the coinbase, folds the frozen branches, serializes the 80-byte header via the block_producer SSOT, runs the selftest-pinned X11, and classifies tighten-first: WonBlock -> full block in the exact --mine-block serialization -> submit_block_fn_ dual-path dispatcher (a won block reaching no sink screams, never drops); ShareAccept -> new set_mint_share_fn seam (accept-for-vardiff + loud log while unbound); else low-difficulty reject. compute_share_difficulty() is the same reconstruction ending in diff1/x11(header) so vardiff engages. Test gate (the miss that let v0.2.2 ship): test_dash_stratum_work_source (already in the build.yml allowlist + ctest registration) now carries the 4c/4d KATs -- fixed-DashWorkData template trio with pinned encodings, set-gap honesty, branch fold vs compute_merkle_root, coinbase reassembly byte-identical to the SSOT build with pinned value splits, X11 difficulty KAT, and deterministic mining_submit classification (share accept / low-diff reject / won-block bytes / mint-seam routing). Verified: 19/19 KATs green; c2pool-dash --selftest green; live smoke (--run --stratum vs a stubbed GBT endpoint) serves mining.notify with a real job on subscribe -- the #732 field failure mode is gone. * main_ltc: route Windows RLIMIT_NOFILE notice to stdout (fix --help smoke) On Windows raise_nofile_limit() always returns 0 (no RLIMIT_NOFILE). The prior LOG_WARNING sent this benign startup notice to stderr; the CI --help smoke pipes c2pool.exe through pwsh "2>&1 | Select-Object -First N", whose early pipe-close promotes any native stderr write to a NativeCommandError and exits 1. Emit the notice on stdout under _WIN32 (matching main_dash.cpp); POSIX keeps LOG_WARNING for genuine getrlimit failures. SAFE-COSMETIC. --------- Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
frstrtr
added a commit
that referenced
this pull request
Jul 19, 2026
…lty (unstub 4b/4c) (#753) * dgb(stratum): wire external-daemon GBT prevhash+bits fallback for empty embedded chain A freshly-stood-up c2pool-dgb :5025 node whose Scrypt-only HeaderChain has not yet ingested a tip (tip_hash()==nullopt) could supply NEITHER a previousblockhash NOR nBits: the header walk cannot reconstruct MultiShield-V4 (a 5-algo window == V37), and the embedded ingest that populates the tip lands later. Result: an EMPTY mining.notify prevhash on the live testnet. Add DGBWorkSource::set_gbt_tip_fn -- a std::function seam (mirrors set_pplns_inputs_fn and dash #726 dashd_fallback) bound in main_dgb.cpp to a lambda over NodeRPC::getblocktemplate. When the embedded chain has no tip, get_current_work_template() AND get_current_gbt_prevhash() (the notify-prevhash source) draw BOTH previousblockhash and the daemon-authoritative bits from ONE GBT snapshot (consistent height). A real embedded tip always wins; the RPC transport stays in main (stratum/ holds only the seam). Unbound / no digibyted creds / RPC failure -> both fields stay a truthful ABSENCE, byte-identical to the pre-wire path -- never a fabricated tip/bits. GBT previousblockhash is the u256_be_display_hex big-endian convention the embedded path emits, so it flows verbatim (width-guarded at the bind). TTL-cached (5s) so per-heartbeat template + prevhash polls do not each trigger a blocking getblocktemplate round-trip. External-daemon GBT fallback RETAINED (never removed), per V36. Scrypt-only; no shared-base / other-coin edit; per-coin isolation held. Tests: 3 new DgbWorkSource.GbtTip* (populate / unbound-absent / nullopt-absent) over the empty-chain fixture; full dgb_work_source_test 30/30 green. * dgb(stratum): score shares via scrypt digest in compute_share_difficulty (unstub 4b/4c) DGBWorkSource::compute_share_difficulty was a Stage-4b/4c stub returning 0.0. The coin-agnostic StratumServer calls it BEFORE mining_submit and silently rejects any share scoring below the vardiff floor (stratum_server.cpp: error 23 Low difficulty share, no server-side log), so every accepted-looking share was dropped before the stage-4d classify+broadcaster ever ran -- the pool could never advance its tip. Implement it as a byte-for-byte mirror of mining_submit reconstruct: coinb1||en1||en2||coinb2 -> sha256d txid -> ascend merkle branches -> 80-byte header -> scrypt_1024_1_1_256, then bridge the coin-space u256 into core uint256 via the u256_be_display_hex SSOT and return chain::target_to_difficulty (diff-1 0x1d00ffff) -- unit-identical to the required_difficulty / pool_difficulty the gate compares. Malformed reconstruct (header != 80B) keeps the documented 0.0 not-scored sentinel. KAT: valid header scores a finite positive difficulty; malformed input still returns 0.0. 31/31 dgb_work_source_test green. --------- Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Wires the run_node --stratum dashd-RPC fallback arm from a stub (empty
DashWorkDataset-gap default) to the EXISTINGNodeRPC::getwork()seam — the same rich getblocktemplate -> DashWorkData pathrun_mine_blockalready uses.Why
The S8 stratum standup shipped the run-path caller (main_dash --stratum -> DASHWorkSource -> StratumServer) with the dashd fallback arm stubbed. This closes that gap so the stratum path serves real dashd work when the embedded-GBT arm is not the source.
Safety
[DASH-STRATUM-GBT]loudly — never a silent drop.rpc(unique_ptr, declared abovework_source) outlives the lambda-owningwork_source; destroyed BEFORErpcat scope exit.Verify
Local Linux x86_64 c2pool-dash link-verify in flight; will post CI +
--run --stratum 127.0.0.1:13333acceptor-standup result before undrafting. 1 file, +15/-4.