dash(stratum): serve real work — wire GBT work data into session template path + X11 submit scoring#733
Merged
Merged
Conversation
…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.
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.
…oke) 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.
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.
Fixes #732 — the v0.2.2 DASH stratum accepts and registers miners but never serves work:
DASHWorkSourcestages 4c/4d were unimplemented skeletons, soStratumSession::send_notify_work()saw an empty template forever and re-armed its 1 s timer in a loop while the binary logged a misleading[LTC]wait line.Stage 4c — template serving
Bridges the armed
get_work()seam (#726: embedded coin-state when seeded, retained dashd GBT fallback otherwise — the duality is preserved untouched) into the template trio the coin-agnostic session consumes:cached_work()): theDashWorkDatasnapshot is cached undertemplate_mutex_, keyed onwork_generation_+ a 30 s staleness TTL, with a 5 s negative cache so a down dashd is not hammered by every session's 1 s retry timer. A refresh that observes a moved tip bumpswork_generation_so sessions re-push work between timer firings.get_current_work_template(): GBT-shaped JSON with exactly the fieldssend_notify_work()reads (previousblockhashBE display hex,version,bitsas 8-char BE hex,curtime,height,coinbasevalue), mirroring the LTC/BTC conventions. Empty object on an honest set-gap — never fabricated.get_stratum_merkle_branches(): sibling list over[coinbase placeholder, tx1..txN]in the LE-internal-bytes wire encoding (the existingdash::coinbase::merkle_branches_raw/_hexSSOT).build_connection_coinbase(): goes through the EXISTING verifier-shared SSOTs —compute_dash_payouts(worker_tx ‖ masternode/superblock payments ‖ donation tail, theshare_check.hppgentx order) →coinbase::build(BIP34 height + pool tag scriptSig, DIP3/DIP4 payload, ref_hash + nonce64 OP_RETURN tail) →split_coinb(coinb1/coinb2 around the 8-byte nonce64 extranonce slot = en1(4) ‖ en2(4)). No second payout or serialization implementation exists by construction, so the coinbase a miner hashes is byte-identical to the verifier split.{script:1}, total 1) + the GBT-mandated masternode outputs + donation tail. The PPLNS multi-output path rides the newset_pplns_weights_fnseam (ShareTracker walk bound by the run-loop) through the samecompute_dash_payoutsarm.get_coinbase_parts()serves an all-to-donation pool fallback so the core's legacy hardcoded (LTC-shaped) default coinbase is unreachable for DASH.get_current_gbt_prevhash(): same cached snapshot as the template — one truthful source.set_difficulty_multiplierto 1.0 (X11 uses the standard diff-1 scale, p2pool-dashDUMB_SCRYPT_DIFF = 1), same as the SHA256d BTC work source. The default 65536 (scrypt convention) inflated the advertised difficulty 65536× (thewire=32.768in the field report).Stage 4d — submit scoring
mining_submit(): reconstructs coinbase = coinb1 ‖ en1 ‖ en2 ‖ coinb2, sha256d txid, ascends the frozen branches, serializes the 80-byte header via theblock_producer.hppSSOT, runs the--selftest-pinneddash::crypto::hash_x11, and classifies tighten-first:--mine-blockserialization (header ‖ CompactSize(1+ntx) ‖ coinbase ‖ txs; DASH has no segwit) →submit_block_fn_, the dual-path won-block dispatcher bound inmain_dash.cpp(dashd submitblock RPC arm; embedded P2P relay leg folds into that same closure when it lands). A won block reaching no sink logs at ERROR — never a silent drop.set_mint_share_fnseam (header/coinbase/branches/payout script/pow). While unbound it accepts for vardiff and logs loudly.compute_share_difficulty(): same reconstruction ending in diff1 / x11(header), so the coin-agnostic vardiff gate engages; 0.0 on malformed input (the documented sentinel).Secondary fix —
[LTC]mistag in the coin-agnostic corestratum_server.cpphardcoded[LTC]in the "Waiting for block template" warning.StratumConfignow carries acoin_symbolset at runtime (DASH/BTC/DGB set it in their work-source ctors, LTC inmain_ltc.cpp), with a neutral[Stratum]fallback. No coin name is hardcoded insrc/core.Test gate (the miss that let v0.2.2 ship)
Extended the existing allowlisted
test_dash_stratum_work_sourcetarget (already in the build.yml--targetlist and ctest registration — the #729 compile-into-existing-target pattern, no workflow-file change needed):DashWorkData→ non-empty template with correct prevhash/bits/version/curtime encodings; set-gap fixture → honestly empty trio;compute_merkle_rootover the fixture tx set;compute_dash_payouts+coinbase::buildSSOT output, with value splits pinned (masternode output = exact GBT amount, miner + donation = worker payout, total = coinbasevalue);compute_share_difficultyKAT: fixture header → pinned X11-derived value; malformed input → 0.0;mining_submitclassification: deterministic (test-mined nonce) ShareAccept / low-diff reject / WonBlock, the WonBlock asserting the dispatched block bytes are the exact--mine-blockserialization; plus the mint-seam routing test.Verified
test_dash_stratum_work_source— 19/19 KATs green locally (Release/gcc-13, conan profileci/conan/linux-gcc13.profile);test_stratum_extensions(44),test_dash_stratum_extranonce_split(6),test_dash_stratum_submit_reassembly(7) all green.c2pool-dash --selftestgreen (X11 KATs + coinbase parity untouched).--run --stratumagainst a stubbed dashd GBT endpoint): subscribe → authorize →mining.notifyarrives with a real job — BIP34 height push +c2pooltag + PPLNS/masternode/donation/OP_RETURN outputs, correct stratum prevhash chunking,set_difficultywire value now 0.0005 (was 32.768). The exact dash: stratum serves no work — DASHWorkSource 4c/4d skeleton (v0.2.2 field report); [LTC] mistag in core #732 field failure mode (miner registered, no job, 60 s EOF loop) is gone. With no dashd reachable, the honest set-gap path logs[DASH] Waiting for block template ...— the coin-tag fix observed live.c2pool(LTC),btc_stratum,dgb_stratumtargets rebuilt green (coreStratumConfigchange is additive; no positional aggregate inits exist).Explicitly deferred (follow-ups, called out in-code)
main_dash.cppdoes not yet stand up a DASH ShareTracker in the--runloop, so the node-side share-creation seam is not cleanly reachable;set_mint_share_fnis the one-line binding point and unbound share-target submissions accept-for-vardiff with a loud log.set_pplns_weights_fnis the ShareTracker-walk binding point; until bound the genesis single-miner split is served (correct for a fresh pool's empty sharechain).