Skip to content

Commit 7aacd01

Browse files
committed
dash(S8): DASHWorkSource IWorkSource skeleton (stratum accept-loop seam)
4a skeleton mirroring dgb::stratum::DGBWorkSource: concrete core::stratum::IWorkSource for DASH (X11). Declares the fused get_work() member the get_work.hpp capstone forward-refs as the eventual DASHWorkSource::get_work(); holds the node-held coin-state embedded arm + the always-reachable dashd GBT RPC fallback (never removed -- safety/[GBT-XCHECK]). All work-gen/submit methods are MVP-default; .cpp bodies + CMake OBJECT wiring + instantiation KAT land in the follow-on 4b commit once #698 is on master. Header-only declaration; not yet in any build target (inert). Stacked on #698 (get_work.hpp); held per integrator until #698 lands to avoid a stacked-PR auto-close.
1 parent e46dec8 commit 7aacd01

1 file changed

Lines changed: 197 additions & 0 deletions

File tree

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// SPDX-License-Identifier: AGPL-3.0-or-later
2+
#pragma once
3+
4+
// dash::stratum::DASHWorkSource -- concrete `core::stratum::IWorkSource`
5+
// implementation for c2pool-dash (Dash X11, V36).
6+
//
7+
// Responsibility: bridge the coin-agnostic `core::StratumServer` (TCP,
8+
// JSON-RPC, sessions, vardiff, rate monitor) to DASH-specific work
9+
// generation + share validation. It is the concrete class the fused
10+
// `dash::stratum::get_work()` capstone (get_work.hpp) refers to as the
11+
// eventual "DASHWorkSource::get_work()" -- the single miner-facing entry
12+
// point that sources a base template off the node-held coin-state and
13+
// assembles the per-miner stratum job targets over it.
14+
//
15+
// The X11 note (NOT scrypt, NOT SHA256d): DASH mines the X11 chained-hash
16+
// PoW. `compute_share_difficulty` encapsulates the X11 hash so the
17+
// coin-agnostic stratum server never hardcodes an algo; the LTC-scrypt /
18+
// BTC-sha256d / DGB-scrypt siblings each override the same seam.
19+
//
20+
// Embedded / fallback duality (MUST PERSIST): work generation sources the
21+
// base block template through `dash::stratum::get_work()`, which itself
22+
// picks the EMBEDDED arm when the node-held `coin::NodeCoinState` bundle is
23+
// populated and otherwise falls back to the always-reachable dashd GBT RPC
24+
// arm (`dashd_fallback_`). The dashd-RPC fallback is never removed -- it is
25+
// the safety + [GBT-XCHECK] cross-check path (operator standing rule).
26+
//
27+
// Lifetime: holds non-owning references to the node-held coin-state and the
28+
// header chain / mempool -- main_dash.cpp owns those for the process
29+
// lifetime, DASHWorkSource is constructed after them and destroyed before.
30+
// The submit-block callback captures whatever upstream state it needs
31+
// (a coin_node ref + the dual-path won-block dispatcher from the
32+
// block-broadcast slice: embedded P2P relay primary + submitblock RPC
33+
// fallback).
34+
//
35+
// Threading: `core::StratumServer` runs on its own io_context; methods here
36+
// may be invoked from any thread serviced by it. Internal synchronisation:
37+
// - `work_generation_`, `share_bits_`, `share_max_bits_` are atomics
38+
// - `workers_` is guarded by `workers_mutex_`
39+
// - `best_share_hash_fn_` / `mint_share_fn_` guarded by their own mutexes
40+
// - the template cache (stage 4c) is guarded by `template_mutex_`
41+
// - `coin_state_` has its own internal locking; `dashd_fallback_` is const
42+
//
43+
// What's deliberately MVP-incomplete in this 4a skeleton (mirrors
44+
// dgb::stratum::DGBWorkSource's own 4a landing): every work-generation /
45+
// submit method returns defaults or empty results; no vardiff feedback loop
46+
// yet. The skeleton compiles, instantiates, and lets the next stacked slice
47+
// validate the StratumServer wiring in main_dash.cpp end-to-end before the
48+
// substantive X11 work-assembly + share-validation logic lands (4b/4c/4d).
49+
50+
#include <core/stratum_work_source.hpp>
51+
#include <core/uint256.hpp>
52+
53+
#include <impl/dash/coin/node_coin_state.hpp> // coin::NodeCoinState, coin::DashWorkData seam
54+
#include <impl/dash/stratum/get_work.hpp> // dash::stratum::get_work() fused capstone
55+
56+
#include <atomic>
57+
#include <cstdint>
58+
#include <functional>
59+
#include <map>
60+
#include <memory>
61+
#include <mutex>
62+
#include <string>
63+
#include <utility>
64+
#include <vector>
65+
66+
// Forward declarations -- heavy headers live in the .cpp.
67+
namespace dash::coin {
68+
class HeaderChain;
69+
class Mempool;
70+
} // namespace dash::coin
71+
72+
namespace dash::stratum {
73+
74+
class DASHWorkSource : public core::stratum::IWorkSource
75+
{
76+
public:
77+
/// Callback invoked when `mining_submit` validates a submission whose
78+
/// **X11** PoW meets DASH mainnet difficulty. main_dash.cpp wires this
79+
/// to the dual-path won-block broadcaster: embedded P2P relay primary +
80+
/// submitblock RPC fallback. Raw-bytes form keeps DASHWorkSource
81+
/// decoupled from the BlockType serialization details. Returns true iff
82+
/// the won block reached at least one network sink -- a false return
83+
/// means it reached NEITHER and the won-block path must log loudly
84+
/// (no silent drop -- the block-viability gate).
85+
using SubmitBlockFn = std::function<bool(const std::vector<unsigned char>& block_bytes,
86+
uint32_t height)>;
87+
88+
/// Fused DASH work source: source the base template off the node-held
89+
/// coin-state (embedded when populated, retained dashd fallback on a
90+
/// set-gap) and assemble the per-miner job targets. This is the concrete
91+
/// DASHWorkSource::get_work() the capstone (get_work.hpp) forward-refs;
92+
/// the free function `dash::stratum::get_work()` carries the fusion so
93+
/// the member is a thin, node-bound adapter over it.
94+
GetWork get_work(const WorkJobTargetInputs& job_in) const;
95+
96+
// ── IWorkSource: config + read-only state ────────────────────────────
97+
const core::stratum::StratumConfig& get_stratum_config() const override { return config_; }
98+
std::function<uint256()> get_best_share_hash_fn() const override;
99+
std::string get_current_gbt_prevhash() const override;
100+
uint64_t get_work_generation() const override { return work_generation_.load(); }
101+
bool has_merged_chain(uint32_t chain_id) const override;
102+
103+
// ── IWorkSource: per-connection bookkeeping ──────────────────────────
104+
void register_stratum_worker(const std::string& session_id,
105+
const core::stratum::WorkerInfo& info) override;
106+
void unregister_stratum_worker(const std::string& session_id) override;
107+
void update_stratum_worker(const std::string& session_id,
108+
double hashrate, double dead_hashrate, double difficulty,
109+
uint64_t accepted, uint64_t rejected, uint64_t stale) override;
110+
111+
// ── IWorkSource: work generation ─────────────────────────────────────
112+
nlohmann::json get_current_work_template() const override;
113+
std::vector<std::string> get_stratum_merkle_branches() const override;
114+
std::pair<std::string, std::string> get_coinbase_parts() const override;
115+
core::stratum::CoinbaseResult build_connection_coinbase(
116+
const uint256& prev_share_hash,
117+
const std::string& extranonce1_hex,
118+
const std::vector<unsigned char>& payout_script,
119+
const std::vector<std::pair<uint32_t, std::vector<unsigned char>>>& merged_addrs) const override;
120+
121+
// ── IWorkSource: share submission (the hot path) ─────────────────────
122+
nlohmann::json mining_submit(
123+
const std::string& username, const std::string& job_id,
124+
const std::string& extranonce1, const std::string& extranonce2,
125+
const std::string& ntime, const std::string& nonce,
126+
const std::string& request_id,
127+
const std::map<uint32_t, std::vector<unsigned char>>& merged_addresses,
128+
const core::stratum::JobSnapshot* job) override;
129+
130+
/// Per-coin PoW-hash difficulty for a pseudoshare. DASH = X11
131+
/// (chained BLAKE/BMW/Groestl/... over the reconstructed 80-byte
132+
/// header). Stage 4b/4c implements the assembly + X11 call; the 4a
133+
/// skeleton returns 0.0 (the documented parse-error / not-yet default).
134+
double compute_share_difficulty(
135+
const std::string& coinb1, const std::string& coinb2,
136+
const std::string& extranonce1, const std::string& extranonce2,
137+
const std::string& ntime, const std::string& nonce,
138+
uint32_t version, const std::string& prevhash_hex,
139+
const std::string& nbits_hex,
140+
const std::vector<std::string>& merkle_branches) const override;
141+
142+
// ── IWorkSource: atomic state ────────────────────────────────────────
143+
uint32_t get_share_bits() const override { return share_bits_.load(); }
144+
uint32_t get_share_max_bits() const override { return share_max_bits_.load(); }
145+
146+
// ── DASH-specific control surface (called from main_dash.cpp) ────────
147+
148+
/// Increment work_generation. Called when the DASH tip moves (new
149+
/// headers / node coin-state republish) or the sharechain tip moves.
150+
/// Triggers stratum sessions to re-push work on their next heartbeat.
151+
void bump_work_generation() { work_generation_.fetch_add(1, std::memory_order_relaxed); }
152+
153+
/// Set the current share-target bits (compact-target encoding).
154+
/// `max_bits` is the easiest the share target can be. Both atomically
155+
/// visible to stratum sessions.
156+
void set_share_target(uint32_t bits, uint32_t max_bits)
157+
{
158+
share_bits_.store(bits, std::memory_order_relaxed);
159+
share_max_bits_.store(max_bits, std::memory_order_relaxed);
160+
}
161+
162+
/// Wire the share-tracker accessor that returns the current best-share
163+
/// hash. Called once at startup from main_dash.cpp after the DASH
164+
/// ShareTracker is constructed.
165+
void set_best_share_hash_fn(std::function<uint256()> fn);
166+
167+
private:
168+
// External dependencies (non-owning references) -- see Lifetime note.
169+
const coin::NodeCoinState& coin_state_; ///< embedded work arm (populated -> Embedded)
170+
std::function<coin::DashWorkData()> dashd_fallback_; ///< always-reachable dashd GBT RPC arm (never removed)
171+
172+
// Submission dispatch (dual-path won-block broadcaster).
173+
SubmitBlockFn submit_block_fn_;
174+
175+
// Config (held by value; const after construction in MVP).
176+
core::stratum::StratumConfig config_;
177+
178+
// Atomic state.
179+
std::atomic<uint64_t> work_generation_{0};
180+
std::atomic<uint32_t> share_bits_{0};
181+
std::atomic<uint32_t> share_max_bits_{0};
182+
183+
// Worker registry (per-connection metadata).
184+
mutable std::mutex workers_mutex_;
185+
std::map<std::string, core::stratum::WorkerInfo> workers_;
186+
187+
// Best-share callback (from ShareTracker). Empty until wired.
188+
mutable std::mutex best_share_mutex_;
189+
std::function<uint256()> best_share_hash_fn_;
190+
191+
// Template cache (filled lazily; invalidated when work_generation_ bumps).
192+
// Stage 4c populates these.
193+
mutable std::mutex template_mutex_;
194+
// ... cache fields land here in stage 4c
195+
};
196+
197+
} // namespace dash::stratum

0 commit comments

Comments
 (0)