Skip to content

Commit c7a7b8b

Browse files
authored
Merge pull request #398 from frstrtr/dash/launcher-clean
dash: runnable c2pool-dash launcher (clean rebuild, supersedes #387)
2 parents d39f530 + dded312 commit c7a7b8b

3 files changed

Lines changed: 263 additions & 1 deletion

File tree

src/c2pool/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,30 @@ target_link_libraries(c2pool-bch
263263
${Boost_LIBRARIES}
264264
)
265265

266+
# c2pool-dash: DASH (X11 standalone parent, older-than-v35 -> V36) — EXE-WIRE
267+
# slice 2 (integrator 2026-06-23, stacked on launcher slice 1 #387). Closes the
268+
# "DASH is impl-files-only, not runnable" gap: slice 1 registered DASH in the
269+
# unified dispatch; this gives DASH its own executable driving the REAL header-
270+
# only consensus path (make_coin_params + X11 PoW + subsidy). Mirrors the
271+
# c2pool-bch --selftest tier: main_dash.cpp + the dash_x11 sph lib; params/
272+
# subsidy/utxo_adapter are header-only. Block submission (won-block dual-path
273+
# broadcaster: dashd-RPC submitblock + embedded P2P relay) is DEFERRED to the
274+
# next stacked slice and is an explicit, labelled --run stub (NOT silent). The
275+
# core OBJECT-lib link set matches c2pool-bch/the dash tests (core monolith SCC
276+
# direct-naming, #22/#39); per-coin isolation held: src/impl/dash only, no
277+
# shared-base/core SOURCE edit, dashd RPC fallback untouched.
278+
add_executable(c2pool-dash main_dash.cpp)
279+
target_compile_definitions(c2pool-dash PRIVATE C2POOL_VERSION="${C2POOL_GIT_VERSION}")
280+
target_link_libraries(c2pool-dash
281+
core pool sharechain
282+
c2pool_payout c2pool_merged_mining c2pool_hashrate c2pool_storage c2pool_difficulty
283+
dash_x11 # DASH X11 PoW sph reference (BLAKE->...->ECHO), additive static lib
284+
btclibs
285+
yaml-cpp::yaml-cpp
286+
nlohmann_json::nlohmann_json
287+
${Boost_LIBRARIES}
288+
)
289+
266290
# Windows: Boost.Asio requires Winsock libraries; /bigobj for large translation units
267291
if(WIN32)
268292
target_link_libraries(c2pool ws2_32 mswsock bcrypt dbghelp)

src/c2pool/c2pool_refactored.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,9 +669,10 @@ int main(int argc, char* argv[]) {
669669
if (blockchain_str == "xmr" || blockchain_str == "monero") return Blockchain::MONERO;
670670
if (blockchain_str == "zec" || blockchain_str == "zcash") return Blockchain::ZCASH;
671671
if (blockchain_str == "doge" || blockchain_str == "dogecoin") return Blockchain::DOGECOIN;
672+
if (blockchain_str == "dash" || blockchain_str == "darkcoin") return Blockchain::DASH;
672673

673674
LOG_ERROR << "Unknown blockchain: " << blockchain_str;
674-
LOG_INFO << "Supported blockchains: ltc, dgb, btc, doge";
675+
LOG_INFO << "Supported blockchains: ltc, dgb, btc, doge, dash";
675676
throw std::invalid_argument("Unknown blockchain type");
676677
};
677678

@@ -682,6 +683,7 @@ int main(int argc, char* argv[]) {
682683
if (symbol == "NMC" || symbol == "nmc") return testnet ? 18334 : 8334; // SSOT: src/impl/nmc/coin/chain_seeds.hpp (namecoind addrman)
683684
if (symbol == "BTC" || symbol == "btc") return testnet ? 18333 : 8333;
684685
if (symbol == "DGB" || symbol == "dgb") return testnet ? 12026 : 12024;
686+
if (symbol == "DASH" || symbol == "dash") return testnet ? 19999 : 9999; // SSOT: src/impl/dash/coin/chain_seeds.hpp (dashd addrman)
685687
if (symbol == "PEP" || symbol == "pep") return testnet ? 44874 : 33874;
686688
if (symbol == "BELLS" || symbol == "bells") return testnet ? 29919 : 19919;
687689
if (symbol == "LKY" || symbol == "lky") return testnet ? 19917 : 9917;
@@ -696,6 +698,7 @@ int main(int argc, char* argv[]) {
696698
case Blockchain::DIGIBYTE: return "DGB";
697699
case Blockchain::BITCOIN: return "BTC";
698700
case Blockchain::DOGECOIN: return "DOGE";
701+
case Blockchain::DASH: return "DASH";
699702
default: return "";
700703
}
701704
};
@@ -715,6 +718,10 @@ int main(int argc, char* argv[]) {
715718
if (symbol == "DGB" || symbol == "dgb") {
716719
return testnet ? ParseHexBytes("fdc8bddd") : ParseHexBytes("fac3b6da");
717720
}
721+
if (symbol == "DASH" || symbol == "dash") {
722+
// Dash pchMessageStart: mainnet bf0c6bbd, testnet3 cee2caff (dashd net magic).
723+
return testnet ? ParseHexBytes("cee2caff") : ParseHexBytes("bf0c6bbd");
724+
}
718725
if (symbol == "PEP" || symbol == "pep") {
719726
return testnet ? ParseHexBytes("fec1dbcc") : ParseHexBytes("c0a0f0e0");
720727
}

src/c2pool/main_dash.cpp

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
// c2pool-dash — DASH (X11 standalone parent, older-than-v35 -> V36) p2pool node
2+
// entry point.
3+
//
4+
// EXE-WIRE slice 2 (integrator 2026-06-23, stacked on launcher slice 1 #387):
5+
// closes the "DASH is impl-files-only, not runnable" gap. Slice 1 registered
6+
// DASH in the unified launcher dispatch (parse_blockchain / port / net-magic);
7+
// this slice gives DASH its own runnable executable that drives the REAL dash
8+
// consensus primitives, so `dash` is no longer a dispatch label with no body.
9+
//
10+
// PER-COIN ISOLATION: src/impl/dash headers only (params/crypto/subsidy); no
11+
// src/impl/<other-coin> edit, no shared-base/core source edit, dashd RPC
12+
// fallback untouched. Mirrors the c2pool-bch / c2pool-dgb add_executable shape,
13+
// pruned to the header-only consensus path (DASH carries no node.cpp run-loop
14+
// TU on master yet — that is the S7/S8 block-submission lane).
15+
//
16+
// ONE MODE TODAY:
17+
// --selftest (default) : drive the LIVE dash consensus paths std-only, network
18+
// free, exercising the exact code the sharechain depends on, then exit:
19+
// (1) make_coin_params — the oracle-sourced CoinParams factory wired,
20+
// incl. the X11 pow_func reachable through the coin-params seam.
21+
// (2) X11 PoW — DASH mainnet genesis + a real-node testnet3
22+
// block header reproduce their published hashes (CI-pinned KATs,
23+
// test_dash_x11_kat.cpp).
24+
// (3) subsidy — post-V20 block reward + 3/4 MN payment match
25+
// the live-validated mainnet value (test_dash_subsidy.cpp).
26+
//
27+
// BLOCK-SUBMISSION (--run) — EXPLICITLY DEFERRED, NOT a silent stub. A won DASH
28+
// block reaches the network by a dual-path broadcaster, BOTH arms of which live
29+
// in the unmerged dash-spv-embedded work and are NOT on master:
30+
// - dashd-RPC submitblock fallback: needs a DASH NodeRPC TU (rpc.cpp/rpc.hpp/
31+
// rpc_conf.hpp) — DASH has only coin/rpc_data.hpp (a data placeholder), no
32+
// RPC client. Porting it (mirroring dgb/coin/rpc.cpp) is the NEXT slice.
33+
// - embedded P2P relay arm: the broadcaster_full / reconstruct stack (S8).
34+
// The CoinParams *path* the RPC fallback consumes IS wired here (make_coin_params,
35+
// oracle-sourced via dash::PoolConfig SSOT); the block-submission SINKS are the
36+
// deferred piece. --run prints this status and exits cleanly so a smoke gate that
37+
// invokes it is never misled into thinking block relay is live.
38+
//
39+
// Conformance oracle: frstrtr/p2pool-dash (older-than-v35; transition 16 -> v36).
40+
// External dashd RPC stays as a fallback alongside the (future) embedded path.
41+
42+
#include <impl/dash/params.hpp>
43+
#include <impl/dash/crypto/hash_x11.hpp>
44+
#include <impl/dash/coin/utxo_adapter.hpp> // must precede subsidy.hpp (dash_txid in scope)
45+
#include <impl/dash/coin/subsidy.hpp>
46+
47+
#include <core/coin_params.hpp>
48+
#include <core/uint256.hpp>
49+
50+
#include <cstdint>
51+
#include <cstring>
52+
#include <iostream>
53+
#include <string>
54+
55+
#ifndef C2POOL_VERSION
56+
#define C2POOL_VERSION "dev"
57+
#endif
58+
59+
namespace {
60+
61+
using dash::coin::compute_dash_block_reward_post_v20;
62+
using dash::coin::compute_dash_mn_payment_post_v20;
63+
64+
void print_banner(const char* argv0)
65+
{
66+
std::cout
67+
<< "c2pool-dash " << C2POOL_VERSION << " — DASH (X11, older-than-v35 -> V36)\n\n"
68+
<< "Usage: " << argv0 << " [--version] [--help] [--selftest]\n"
69+
<< " " << argv0 << " --run (block-submission DEFERRED — see status)\n\n"
70+
<< "Status: consensus layer live (X11 PoW, subsidy, oracle CoinParams).\n"
71+
<< " Block submission (won-block dual-path broadcaster) is the\n"
72+
<< " next stacked slice; external dashd RPC stays the fallback.\n"
73+
<< "Consensus: X11 PoW + block identity; 2.5 min spacing; 5 DASH post-V20\n"
74+
<< " base, -1/14 per 210240; masternode payment 3/4 of block value.\n";
75+
}
76+
77+
// Serialize an 80-byte DASH block header (LE; host is LE on the x86_64 target).
78+
void serialize_header(unsigned char out[80], uint32_t version, const char* prev_hex,
79+
const char* merkle_hex, uint32_t time, uint32_t bits, uint32_t nonce)
80+
{
81+
uint256 prev_block; prev_block.SetHex(prev_hex);
82+
uint256 merkle_root; merkle_root.SetHex(merkle_hex);
83+
size_t off = 0;
84+
std::memcpy(out + off, &version, 4); off += 4;
85+
std::memcpy(out + off, prev_block.data(), 32); off += 32;
86+
std::memcpy(out + off, merkle_root.data(), 32); off += 32;
87+
std::memcpy(out + off, &time, 4); off += 4;
88+
std::memcpy(out + off, &bits, 4); off += 4;
89+
std::memcpy(out + off, &nonce, 4); off += 4;
90+
}
91+
92+
// (1) The oracle CoinParams factory is wired and self-consistent, AND the X11
93+
// pow_func is reachable through the coin-params seam (the path the work
94+
// source + block-identity checks consume).
95+
int check_coin_params()
96+
{
97+
const core::CoinParams main = dash::make_coin_params(/*testnet=*/false);
98+
const core::CoinParams test = dash::make_coin_params(/*testnet=*/true);
99+
100+
int fails = 0;
101+
auto want = [&](bool ok, const char* what) {
102+
std::cout << "[selftest] coin_params: " << what << (ok ? " ok\n" : " FAIL\n");
103+
if (!ok) ++fails;
104+
};
105+
want(main.symbol == "DASH", "symbol == DASH");
106+
// CoinParams.p2p_port is the SHARECHAIN/pool peer port (dash::PoolConfig SSOT),
107+
// distinct from the DASH coin-daemon P2P port (9999/19999) wired in slice-1's
108+
// get_coin_p2p_port. Assert the sharechain SSOT here.
109+
want(main.p2p_port == 8999, "mainnet sharechain p2p_port == 8999 (SSOT)");
110+
want(test.p2p_port == 18999, "testnet sharechain p2p_port == 18999 (SSOT)");
111+
want(main.current_share_version == 16, "share_version == 16 (older-than-v35 baseline)");
112+
want(main.address_version == 76, "mainnet pubkey addr version == 76 (X...)");
113+
want(static_cast<bool>(main.pow_func), "pow_func wired");
114+
115+
// Drive X11 THROUGH the CoinParams pow_func seam against the genesis header.
116+
if (main.pow_func) {
117+
unsigned char hdr[80];
118+
serialize_header(hdr, 1, "0000000000000000000000000000000000000000000000000000000000000000",
119+
"e0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7",
120+
1390095618u, 0x1e0ffff0u, 28917698u);
121+
const uint256 pow = main.pow_func(std::span<const unsigned char>(hdr, 80));
122+
const bool ok = pow.GetHex() == "00000ffd590b1485b3caadc19b22e6379c733355108f107a430458cdf3407ab6";
123+
want(ok, "pow_func(genesis) reproduces genesis hash");
124+
}
125+
return fails;
126+
}
127+
128+
// (2) X11 PoW KATs: mainnet genesis + a real-node testnet3 block (CI-pinned,
129+
// test_dash_x11_kat.cpp). Pins BLAKE->...->ECHO end to end via the direct
130+
// dash::crypto::hash_x11 entry.
131+
int check_x11_kats()
132+
{
133+
int fails = 0;
134+
struct Vec { const char* name; uint32_t v; const char* prev; const char* merkle;
135+
uint32_t t; uint32_t bits; uint32_t nonce; const char* expect; };
136+
const Vec vecs[] = {
137+
{ "mainnet-genesis", 1,
138+
"0000000000000000000000000000000000000000000000000000000000000000",
139+
"e0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7",
140+
1390095618u, 0x1e0ffff0u, 28917698u,
141+
"00000ffd590b1485b3caadc19b22e6379c733355108f107a430458cdf3407ab6" },
142+
{ "testnet3-#1497944", 536870912u,
143+
"000000dbbc08ee519459b38b02bb7754b455dd00cd74069a1352f08f0dd986db",
144+
"0464a4ac5f058a742f6aa42b2b3c7489abde7609b529612bcfa5da34b10bdb1b",
145+
1781737170u, 0x1e00f256u, 721236u,
146+
"000000b6a4e5ea1a0854ef83f0028dde5b96cdaacc604decd8b064d0cea38234" },
147+
};
148+
for (const auto& vc : vecs) {
149+
unsigned char hdr[80];
150+
serialize_header(hdr, vc.v, vc.prev, vc.merkle, vc.t, vc.bits, vc.nonce);
151+
const uint256 pow = dash::crypto::hash_x11(hdr, sizeof(hdr));
152+
const bool ok = pow.GetHex() == vc.expect;
153+
std::cout << "[selftest] x11 KAT " << vc.name << ": " << pow.GetHex()
154+
<< (ok ? " ok\n" : " FAIL\n");
155+
if (!ok) ++fails;
156+
}
157+
return fails;
158+
}
159+
160+
// (3) Subsidy: post-V20 block reward + 3/4 MN payment (test_dash_subsidy.cpp,
161+
// live-validated against dashd getblocktemplate at h=2459985).
162+
int check_subsidy()
163+
{
164+
int fails = 0;
165+
const int64_t reward = compute_dash_block_reward_post_v20(2459985);
166+
const bool r_ok = reward == 177'022'505LL;
167+
std::cout << "[selftest] subsidy h=2459985 reward = " << reward
168+
<< (r_ok ? " ok\n" : " FAIL (want 177022505)\n");
169+
if (!r_ok) ++fails;
170+
171+
const int64_t mn = compute_dash_mn_payment_post_v20(200'000'000LL);
172+
const bool mn_ok = mn == 150'000'000LL;
173+
std::cout << "[selftest] masternode payment 3/4 of 2.0 DASH = " << mn
174+
<< (mn_ok ? " ok\n" : " FAIL (want 150000000)\n");
175+
if (!mn_ok) ++fails;
176+
return fails;
177+
}
178+
179+
int run_selftest()
180+
{
181+
std::cout << "[selftest] driving live DASH consensus (network-free)\n";
182+
int fails = 0;
183+
fails += check_coin_params();
184+
fails += check_x11_kats();
185+
fails += check_subsidy();
186+
if (fails == 0) {
187+
std::cout << "[selftest] OK — CoinParams + X11 PoW + subsidy all conform to oracle\n";
188+
return 0;
189+
}
190+
std::cout << "[selftest] FAIL — " << fails << " consensus check(s) failed\n";
191+
return 1;
192+
}
193+
194+
// --run: block submission is DEFERRED. Print the exact deferral status so a smoke
195+
// gate is never misled, then exit cleanly (the consensus layer IS exercised by
196+
// --selftest; the run-loop standup lands with the broadcaster slice).
197+
int run_node_stub()
198+
{
199+
std::cout
200+
<< "[run] DASH block submission is DEFERRED to the next stacked slice.\n"
201+
<< "[run] - dashd-RPC submitblock fallback: needs a DASH NodeRPC TU\n"
202+
<< "[run] (rpc.cpp/rpc.hpp/rpc_conf.hpp); only coin/rpc_data.hpp exists.\n"
203+
<< "[run] - embedded P2P relay arm: S8 broadcaster/reconstruct stack.\n"
204+
<< "[run] The oracle CoinParams path the fallback consumes IS wired; run\n"
205+
<< "[run] --selftest to exercise the live consensus layer (X11 + subsidy).\n";
206+
return 0;
207+
}
208+
209+
} // namespace
210+
211+
int main(int argc, char** argv)
212+
{
213+
bool want_help = false;
214+
bool want_run = false;
215+
for (int i = 1; i < argc; ++i) {
216+
if (std::strcmp(argv[i], "--version") == 0) {
217+
std::cout << "c2pool-dash " << C2POOL_VERSION << "\n";
218+
return 0;
219+
}
220+
if (std::strcmp(argv[i], "--help") == 0) want_help = true;
221+
if (std::strcmp(argv[i], "--run") == 0) want_run = true;
222+
// --selftest is the default; accepted explicitly for symmetry.
223+
}
224+
225+
print_banner(argv[0]);
226+
if (want_help)
227+
return 0;
228+
if (want_run)
229+
return run_node_stub();
230+
return run_selftest();
231+
}

0 commit comments

Comments
 (0)