Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions src/c2pool/main_dash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ void print_banner(const char* argv0)
<< " [--listen [HOST:]PORT] [--addnode HOST:PORT]... [--connect HOST:PORT]...\n"
<< " [--stratum [HOST:]PORT] [--coin-p2p-connect HOST:PORT]...\n"
<< " [--web-port PORT] [--web-host ADDR] [--dashboard-dir PATH]\n"
<< " [--external-ip ADDR]\n"
<< " [--embedded-utxo]\n"
<< " [--give-author PCT] [-f|--fee PCT] [--node-owner-address ADDR]\n"
<< " [--redistribute pplns|fee|boost|donate]\n"
Expand Down Expand Up @@ -229,6 +230,10 @@ void print_banner(const char* argv0)
<< " are bound to the REAL DASH tracker; local hashrate comes from the\n"
<< " DASH stratum acceptor. If stratum and web ports collide the web\n"
<< " port moves to stratum+1.\n"
<< " --external-ip ADDR (alias --stratum-advertise / --public-host)\n"
<< " overrides the miner-facing host shown in the dashboard Stratum\n"
<< " URL -- for NAT / port-mapped nodes whose outbound IP is not the\n"
<< " address miners dial; unset => auto-detect (no regression).\n"
<< "Consensus: X11 PoW + block identity; 2.5 min spacing; 5 DASH post-V20\n"
<< " base, -1/14 per 210240; masternode payment 3/4 of block value.\n";
}
Expand Down Expand Up @@ -395,7 +400,8 @@ int run_node(bool testnet, const std::string& rpc_endpoint,
const std::string& redistribute_mode,
bool no_p2p_relay,
bool embedded_mainnet,
const std::string& coin_zmq_hashblock)
const std::string& coin_zmq_hashblock,
const std::string& external_ip)
{
namespace io = boost::asio;

Expand Down Expand Up @@ -568,6 +574,12 @@ int run_node(bool testnet, const std::string& rpc_endpoint,
#endif
mi->set_worker_port(stratum_port); // display only (see divergence note)
mi->set_p2p_port(bind_port);
// Serve the operator-advertised miner-facing host (--external-ip) so
// the dashboard Stratum URL renders the NAT-external address miners
// actually dial, not the auto-detected outbound gateway IP. Unset =>
// MiningInterface keeps its auto-detect path (no regression).
if (!external_ip.empty())
mi->set_external_ip(external_ip);
// p2pool-compat protocol_version for /local_stats. The core seam
// documents this exact value for DASH (web_server.hpp:565) and it
// matches the sharechain SSOT floor.
Expand Down Expand Up @@ -2267,6 +2279,9 @@ int main(int argc, char** argv)
std::string dashboard_dir = "web-static"; // --dashboard-dir static asset root
std::string redistribute_mode = "pplns"; // --redistribute pplns|fee|boost|donate
std::string coin_zmq_hashblock; // --coin-zmq-hashblock ENDPOINT (opt-in dashd ZMQ hashblock instant tip-notify, e.g. tcp://127.0.0.1:28332)
// Operator-supplied miner-facing host for the dashboard Stratum URL.
// Empty => auto-detect the outbound public IP (current behaviour).
std::string external_ip; // --external-ip / --stratum-advertise / --public-host
for (int i = 1; i < argc; ++i) {
if (std::strcmp(argv[i], "--version") == 0) {
std::cout << "c2pool-dash " << C2POOL_VERSION << "\n";
Expand Down Expand Up @@ -2337,6 +2352,14 @@ int main(int argc, char** argv)
}
else if (std::strcmp(argv[i], "--web-host") == 0 && i + 1 < argc)
web_host = argv[++i];
// Miner-facing host override for the dashboard Stratum URL. Both hotel
// nodes NAT out through one gateway, so the auto-detected outbound IP
// is NOT the address miners reach; the operator advertises the real
// external-mapped host here. Aliases match how the flag is referenced.
else if ((std::strcmp(argv[i], "--external-ip") == 0 ||
std::strcmp(argv[i], "--stratum-advertise") == 0 ||
std::strcmp(argv[i], "--public-host") == 0) && i + 1 < argc)
external_ip = argv[++i];
else if (std::strcmp(argv[i], "--dashboard-dir") == 0 && i + 1 < argc)
dashboard_dir = argv[++i];
else if (std::strcmp(argv[i], "--stratum") == 0 && i + 1 < argc) {
Expand Down Expand Up @@ -2418,7 +2441,8 @@ int main(int argc, char** argv)
embedded_utxo, dev_donation, node_owner_fee,
node_owner_address, redistribute_mode, no_p2p_relay,
embedded_mainnet,
coin_zmq_hashblock);
coin_zmq_hashblock,
external_ip);
}
return run_selftest();
}
31 changes: 30 additions & 1 deletion test/test_web_honesty_regression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,4 +574,33 @@ TEST(WebHonestyRegression, PatronSendmanySelfLabelsAsStubNeverFabricatesPayouts)
<< "never label-as-stub while surfacing payout splits -- silent lie";
EXPECT_EQ(p.value("total", std::string{}), "12.5")
<< "the echoed total must be the operator-supplied value, not invented";
}
}
// ── Stratum-URL external_ip override (DASH NAT/port-mapped nodes) ──────────
// The dashboard Stratum-URL card renders nodeInfo.external_ip
// (dashboard.html:2889-2892). When a node NATs out through a shared gateway
// (both hotel DASH nodes: LAN 192.168.1.x, one public 31.172.65.125), the
// auto-detected OUTBOUND IP is NOT the address miners dial -- they reach the
// external-mapped hosts (109.161.57.3 / 109.161.52.148). c2pool-dash exposes
// --external-ip (alias --stratum-advertise / --public-host) which feeds
// set_external_ip(); rest_node_info() must then SERVE that operator-supplied
// host verbatim so the Stratum URL is truthful. Unset must stay honest-absent
// ("0.0.0.0"), leaving the auto-detect / window.location.hostname fallback --
// no regression. Pins the flag -> served-external_ip plumbing.
TEST(WebHonestyRegression, NodeInfoExternalIpUnsetIsHonestlyUnspecified) {
MiningInterface mi(/*testnet=*/true, /*node=*/nullptr, Blockchain::DASH);
json ni = mi.rest_node_info();
EXPECT_EQ(ni.value("external_ip", std::string{}), "0.0.0.0")
<< "unset external_ip must serve the honest-absent sentinel so the "
"dashboard falls back to auto-detect / window.location.hostname";
}

TEST(WebHonestyRegression, NodeInfoExternalIpServesOperatorAdvertisedHost) {
MiningInterface mi(/*testnet=*/true, /*node=*/nullptr, Blockchain::DASH);
// Operator advertises the real miner-facing external-mapped host (primary
// hotel node), NOT the auto-detected 31.172.65.125 NAT gateway.
mi.set_external_ip("109.161.57.3");
json ni = mi.rest_node_info();
EXPECT_EQ(ni.value("external_ip", std::string{}), "109.161.57.3")
<< "served external_ip must be the operator-advertised miner-facing "
"host so the dashboard Stratum URL is not the wrong NAT IP";
}
Loading