6666#include < map>
6767#include < memory>
6868#include < string>
69+ #include < vector>
6970
7071#ifndef C2POOL_VERSION
7172#define C2POOL_VERSION " dev"
7273#endif
7374
7475namespace {
7576
77+ // -- Sharechain (pool-to-pool) peering CONTRACT (launcher-peering-cli slice) --
78+ // The DASH dual-pool G2 ratchet (LIVE rows C1-C4) needs main_dash to accept the
79+ // peering argv the way main_btc does (--sharechain-port + bootstrap). This slice
80+ // lands the argv CONTRACT + validation those rows invoke. The LIVE bind/dial is
81+ // driven by DASH's sharechain pool Node (the pool::NodeBridge analog of btc::Node
82+ // / dgb::Node = node.hpp + peer/messages/share_tracker), which is NOT yet on
83+ // master and is the next S8 leaf; this surface wires straight into it when it
84+ // lands. No shared-base / other-coin edit; dashd-RPC fallback untouched.
85+ struct PeeringConfig {
86+ std::string listen_host = " 0.0.0.0" ; // --listen [HOST:]PORT bind interface
87+ uint16_t listen_port = 0 ; // 0 => sharechain SSOT default (8999/18999)
88+ bool listen_set = false ;
89+ std::vector<NetService> addnodes; // --addnode HOST:PORT (persistent outbound)
90+ std::vector<NetService> connects; // --connect HOST:PORT (connect-only; no listen/discovery)
91+ };
92+
93+ // Parse "HOST:PORT" (PORT mandatory; IPv4/hostname single-colon form).
94+ bool parse_hostport (const std::string& str, NetService& out)
95+ {
96+ const auto colon = str.rfind (' :' );
97+ if (colon == std::string::npos || colon == 0 || colon + 1 >= str.size ())
98+ return false ;
99+ const std::string host = str.substr (0 , colon);
100+ const std::string pstr = str.substr (colon + 1 );
101+ if (pstr.find_first_not_of (" 0123456789" ) != std::string::npos) return false ;
102+ const long p = std::strtol (pstr.c_str (), nullptr , 10 );
103+ if (p <= 0 || p > 65535 ) return false ;
104+ out = NetService (host, static_cast <uint16_t >(p));
105+ return true ;
106+ }
107+
108+ // Parse "[HOST:]PORT". Bare PORT keeps the caller-supplied default host.
109+ bool parse_listen (const std::string& str, std::string& host, uint16_t & port)
110+ {
111+ const auto colon = str.rfind (' :' );
112+ std::string pstr = (colon == std::string::npos) ? str : str.substr (colon + 1 );
113+ if (colon != std::string::npos) {
114+ if (colon == 0 ) return false ;
115+ host = str.substr (0 , colon);
116+ }
117+ if (pstr.empty () || pstr.find_first_not_of (" 0123456789" ) != std::string::npos) return false ;
118+ const long p = std::strtol (pstr.c_str (), nullptr , 10 );
119+ if (p <= 0 || p > 65535 ) return false ;
120+ port = static_cast <uint16_t >(p);
121+ return true ;
122+ }
123+
124+ // Report the requested sharechain peering topology at run-loop bring-up. Honest
125+ // about the deferred live bind: a won/seen share does NOT yet cross the wire
126+ // until the sharechain pool-node leaf lands.
127+ void report_peering (const PeeringConfig& peer, bool testnet)
128+ {
129+ const uint16_t ssot = testnet ? 18999 : 8999 ;
130+ const uint16_t bind = peer.listen_port ? peer.listen_port : ssot;
131+ if (!peer.connects .empty () && !peer.listen_set ) {
132+ std::cout << " [run] sharechain peering: --connect mode ("
133+ << peer.connects .size () << " peer[s]); listen + discovery suppressed\n " ;
134+ } else {
135+ std::cout << " [run] sharechain peering: listen " << peer.listen_host << " :" << bind
136+ << (peer.listen_set ? " (--listen)\n " : " (sharechain SSOT default)\n " );
137+ }
138+ for (const auto & a : peer.addnodes )
139+ std::cout << " [run] addnode (persistent outbound) -> " << a.to_string () << " \n " ;
140+ for (const auto & c : peer.connects )
141+ std::cout << " [run] connect (connect-only) -> " << c.to_string () << " \n " ;
142+ std::cout << " [run] NOTE: peering argv contract + validation are LIVE; the bind/dial\n "
143+ " [run] wires when the DASH sharechain pool Node (node.hpp/peer/\n "
144+ " [run] messages/share_tracker, mirror btc::Node) lands -- next S8 leaf.\n " ;
145+ }
146+
76147using dash::coin::compute_dash_block_reward_post_v20;
77148using dash::coin::compute_dash_mn_payment_post_v20;
78149
@@ -83,6 +154,7 @@ void print_banner(const char* argv0)
83154 << " Usage: " << argv0 << " [--version] [--help] [--selftest]\n "
84155 << " " << argv0 << " --run [--coin-rpc H:P] [--coin-rpc-auth PATH]\n "
85156 << " [--testnet] [--submit-block HEX | --submit-block-file PATH]\n "
157+ << " [--listen [HOST:]PORT] [--addnode HOST:PORT]... [--connect HOST:PORT]...\n "
86158 << " " << argv0 << " --mine-block [--coin-rpc H:P] [--coin-rpc-auth PATH]\n "
87159 << " [--testnet] [--payout-pubkey-hash HEX] [--max-nonce N]\n\n "
88160 << " Status: consensus layer live (X11 PoW, subsidy, oracle CoinParams).\n "
@@ -229,7 +301,8 @@ int run_selftest()
229301// A synthetic-only pass does NOT earn block-viable; the live dashd-reached run is
230302// the gate.
231303int run_node (bool testnet, const std::string& rpc_endpoint,
232- const std::string& rpc_conf_path, const std::string& submit_hex)
304+ const std::string& rpc_conf_path, const std::string& submit_hex,
305+ const PeeringConfig& peer)
233306{
234307 namespace io = boost::asio;
235308
@@ -278,6 +351,7 @@ int run_node(bool testnet, const std::string& rpc_endpoint,
278351 return accepted ? 0 : 1 ;
279352 }
280353
354+ report_peering (peer, testnet);
281355 std::cout << " [run] run-loop up (Ctrl-C to stop); won blocks relay via the\n "
282356 " [run] dashd-RPC submitblock fallback. Embedded P2P relay = S8.\n " ;
283357 ioc.run ();
@@ -403,6 +477,9 @@ int main(int argc, char** argv)
403477 std::string rpc_conf_path; // --coin-rpc-auth PATH (creds; default ~/.dashcore/dash.conf)
404478 std::string submit_hex; // --submit-block HEX (one-shot won-block submit)
405479 std::string submit_file; // --submit-block-file PATH
480+ std::string listen_raw; // --listen [HOST:]PORT (sharechain bind)
481+ std::vector<std::string> addnode_raw; // --addnode HOST:PORT (persistent outbound)
482+ std::vector<std::string> connect_raw; // --connect HOST:PORT (connect-only)
406483 for (int i = 1 ; i < argc; ++i) {
407484 if (std::strcmp (argv[i], " --version" ) == 0 ) {
408485 std::cout << " c2pool-dash " << C2POOL_VERSION << " \n " ;
@@ -426,6 +503,12 @@ int main(int argc, char** argv)
426503 submit_hex = argv[++i];
427504 else if (std::strcmp (argv[i], " --submit-block-file" ) == 0 && i + 1 < argc)
428505 submit_file = argv[++i];
506+ else if (std::strcmp (argv[i], " --listen" ) == 0 && i + 1 < argc)
507+ listen_raw = argv[++i];
508+ else if (std::strcmp (argv[i], " --addnode" ) == 0 && i + 1 < argc)
509+ addnode_raw.emplace_back (argv[++i]);
510+ else if (std::strcmp (argv[i], " --connect" ) == 0 && i + 1 < argc)
511+ connect_raw.emplace_back (argv[++i]);
429512 // --selftest is the default; accepted explicitly for symmetry.
430513 }
431514
@@ -448,7 +531,31 @@ int main(int argc, char** argv)
448531 submit_hex.back () == ' ' || submit_hex.back () == ' \t ' ))
449532 submit_hex.pop_back ();
450533 }
451- return run_node (testnet, rpc_endpoint, rpc_conf_path, submit_hex);
534+ PeeringConfig peer;
535+ for (const auto & raw : addnode_raw) {
536+ NetService ns;
537+ if (!parse_hostport (raw, ns)) {
538+ std::cout << " [run] --addnode malformed (want HOST:PORT): " << raw << " \n " ;
539+ return 2 ;
540+ }
541+ peer.addnodes .push_back (ns);
542+ }
543+ for (const auto & raw : connect_raw) {
544+ NetService ns;
545+ if (!parse_hostport (raw, ns)) {
546+ std::cout << " [run] --connect malformed (want HOST:PORT): " << raw << " \n " ;
547+ return 2 ;
548+ }
549+ peer.connects .push_back (ns);
550+ }
551+ if (!listen_raw.empty ()) {
552+ if (!parse_listen (listen_raw, peer.listen_host , peer.listen_port )) {
553+ std::cout << " [run] --listen malformed (want [HOST:]PORT): " << listen_raw << " \n " ;
554+ return 2 ;
555+ }
556+ peer.listen_set = true ;
557+ }
558+ return run_node (testnet, rpc_endpoint, rpc_conf_path, submit_hex, peer);
452559 }
453560 return run_selftest ();
454561}
0 commit comments