diff --git a/src/block_cache.cpp b/src/block_cache.cpp index d4bc1a4..61dcbc8 100644 --- a/src/block_cache.cpp +++ b/src/block_cache.cpp @@ -20,6 +20,7 @@ #include "pool_block.h" #include "p2p_server.h" #include "side_chain.h" +#include "params.h" LOG_CATEGORY(BlockCache) @@ -34,9 +35,9 @@ struct BlockCache::Impl : public nocopy_nomove { #if defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION) || defined(__MACH__) - Impl() + explicit Impl(const Params& params) { - const std::string cache_path = DATA_DIR + cache_name; + const std::string cache_path = params.m_dataDir + cache_name; m_fd = open(cache_path.c_str(), O_RDWR | O_CREAT, static_cast(0600)); if (m_fd == -1) { @@ -88,8 +89,8 @@ struct BlockCache::Impl : public nocopy_nomove #elif defined(_WIN32) - Impl() - : m_cachePath(DATA_DIR + cache_name) + explicit Impl(const Params& params) + : m_cachePath(params.m_dataDir + cache_name) , m_file(CreateFile(m_cachePath.c_str(), GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL)) , m_map(0) { @@ -157,8 +158,8 @@ struct BlockCache::Impl : public nocopy_nomove uint8_t* m_data = nullptr; }; -BlockCache::BlockCache() - : m_impl(new Impl()) +BlockCache::BlockCache(const Params& params) + : m_impl(new Impl(params)) , m_flushRunning(0) , m_storeIndex(0) , m_loadingStarted(0) diff --git a/src/block_cache.h b/src/block_cache.h index 2e8a035..55d1721 100644 --- a/src/block_cache.h +++ b/src/block_cache.h @@ -22,11 +22,12 @@ namespace p2pool { struct PoolBlock; class SideChain; class P2PServer; +struct Params; class BlockCache : public nocopy_nomove { public: - BlockCache(); + explicit BlockCache(const Params& params); ~BlockCache(); void store(const PoolBlock& block); diff --git a/src/block_template.cpp b/src/block_template.cpp index 88fdeed..3ed2dd1 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -204,7 +204,7 @@ void BlockTemplate::shuffle_tx_order() } } -void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const Params* params) +void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const Params& params) { if (data.major_version > HARDFORK_SUPPORTED_VERSION) { LOGERR(1, "got hardfork version " << data.major_version << ", expected <= " << HARDFORK_SUPPORTED_VERSION); @@ -269,7 +269,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const m_blockHeaderSize = m_blockHeader.size(); - m_poolBlockTemplate->m_minerWallet = params->m_miningWallet; + m_poolBlockTemplate->m_minerWallet = params.m_miningWallet; if (!m_sidechain->fill_sidechain_data(*m_poolBlockTemplate, m_shares)) { use_old_template(); @@ -595,7 +595,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const m_poolBlockTemplate->m_transactions.push_back(m_mempoolTxs[m_mempoolTxsOrder[i]].id); } - m_poolBlockTemplate->m_minerWallet = params->m_miningWallet; + m_poolBlockTemplate->m_minerWallet = params.m_miningWallet; // Layout: [software id, version, random number, sidechain extra_nonce] uint32_t* sidechain_extra = m_poolBlockTemplate->m_sidechainExtraBuf; @@ -630,16 +630,16 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const m_poolBlockTemplate->m_mergeMiningExtra.emplace(c.unique_id, std::move(v)); } - if (params->m_subaddress.valid()) { + if (params.m_subaddress.valid()) { uint8_t buf[HASH_SIZE + 2] = {}; - memcpy(buf, params->m_subaddress.view_public_key().h, HASH_SIZE); + memcpy(buf, params.m_subaddress.view_public_key().h, HASH_SIZE); m_poolBlockTemplate->m_mergeMiningExtra.emplace(keccak_subaddress_viewpub, std::vector(buf, buf + sizeof(buf))); } - if (!params->m_onionPubkey.empty()) { + if (!params.m_onionPubkey.empty()) { uint8_t buf[HASH_SIZE + 2] = {}; - memcpy(buf, params->m_onionPubkey.h, HASH_SIZE); + memcpy(buf, params.m_onionPubkey.h, HASH_SIZE); m_poolBlockTemplate->m_mergeMiningExtra.emplace(keccak_onion_address_v3, std::vector(buf, buf + sizeof(buf))); } diff --git a/src/block_template.h b/src/block_template.h index 11fbdae..e918417 100644 --- a/src/block_template.h +++ b/src/block_template.h @@ -40,7 +40,7 @@ public: BlockTemplate(const BlockTemplate& b); BlockTemplate& operator=(const BlockTemplate& b); - void update(const MinerData& data, const Mempool& mempool, const Params* params); + void update(const MinerData& data, const Mempool& mempool, const Params& params); uint64_t last_updated() const { return m_lastUpdated.load(); } bool get_difficulties(const uint32_t template_id, uint64_t& height, uint64_t& sidechain_height, difficulty_type& mainchain_difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty) const; diff --git a/src/log.cpp b/src/log.cpp index aba690c..df81aab 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -18,6 +18,7 @@ #include "common.h" #include "uv_util.h" #include "wallet.h" +#include "params.h" #include #include #include @@ -118,7 +119,7 @@ public: BUF_SIZE = SLOT_SIZE * 8192, }; - FORCEINLINE Worker() + FORCEINLINE explicit Worker(const Params& p) : m_writePos(0) , m_readPos(0) , m_stopped(false) @@ -132,7 +133,7 @@ public: std::setlocale(LC_ALL, "en_001"); - m_logFilePath = LOG_FILE_PATH.empty() ? (DATA_DIR + log_file_name) : LOG_FILE_PATH; + m_logFilePath = p.m_logFilePath.empty() ? (p.m_dataDir + log_file_name) : p.m_logFilePath; m_buf.resize(BUF_SIZE); @@ -478,16 +479,23 @@ NOINLINE Writer::~Writer() m_buf[2] = static_cast(static_cast(size >> 8)); m_buf[m_pos] = '\n'; #ifndef P2POOL_LOG_DISABLE - worker->write(m_buf, size); + if (worker) { + worker->write(m_buf, size); + } + else { + fwrite(m_buf + 3, 1, size - 3, (m_buf[0] == 1) ? stdout : stderr); + } #endif } -void start() +void start(const Params& p) { #ifndef P2POOL_LOG_DISABLE - worker = new Worker(); + worker = new Worker(p); LOGINFO(0, "started"); +#else + (void)p; #endif } diff --git a/src/log.h b/src/log.h index 469ccac..851ce71 100644 --- a/src/log.h +++ b/src/log.h @@ -20,6 +20,7 @@ namespace p2pool { class Wallet; +struct Params; namespace log { @@ -622,7 +623,7 @@ struct DummyStream #endif -void start(); +void start(const Params& p); void reopen(); void stop(); diff --git a/src/main.cpp b/src/main.cpp index a7f0caa..cfb793d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,7 +38,6 @@ #endif // WITH_GRPC #include -#include #ifdef WITH_RANDOMX #include "randomx.h" @@ -223,6 +222,22 @@ int p2pool_test() return 0; } +static p2pool::Params get_params(int argc, char* argv[]) noexcept +{ + try { + p2pool::Params params(argc, argv); + + if (params.valid()) { + return params; + } + } + catch (const std::exception&) { + } + + printf("Invalid or missing command line. Try \"p2pool --help\".\n"); + abort(); +} + int main(int argc, char* argv[]) { if (argc == 1) { @@ -230,9 +245,6 @@ int main(int argc, char* argv[]) return 0; } - bool is_mini = false; - bool is_nano = false; - for (int i = 1; i < argc; ++i) { if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "/help") || !strcmp(argv[i], "-h") || !strcmp(argv[i], "/h")) { p2pool_usage(); @@ -247,56 +259,16 @@ int main(int argc, char* argv[]) if (!strcmp(argv[i], "--test")) { return p2pool_test(); } - - if ((strcmp(argv[i], "--data-dir") == 0) && (i + 1 < argc)) { - p2pool::DATA_DIR = argv[++i]; - p2pool::fixup_path(p2pool::DATA_DIR); - } - - if ((strcmp(argv[i], "--log-file") == 0) && (i + 1 < argc)) { - p2pool::LOG_FILE_PATH = argv[++i]; - } - - if (!strcmp(argv[i], "--mini")) is_mini = true; - if (!strcmp(argv[i], "--nano")) is_nano = true; } - // If the data directory is not set, check if P2Pool has write access to the current directory - // If it doesn't, switch to user's home directory - if (p2pool::DATA_DIR.empty()) { - std::ofstream f("p2pool.tmp"); - if (f && f.put(' ')) { - f.close(); - std::remove("p2pool.tmp"); - } - else { - char buf[1024]; - size_t size = sizeof(buf); + const p2pool::Params params = get_params(argc, argv); - if (uv_os_homedir(buf, &size) == 0) { - p2pool::DATA_DIR.assign(buf, size); - p2pool::fixup_path(p2pool::DATA_DIR); + if (!params.m_dataDir.empty()) { + printf("Using \"%s\" for P2Pool files\n", params.m_dataDir.c_str()); - p2pool::DATA_DIR += ".p2pool/"; - - if (is_mini) { - p2pool::DATA_DIR += "mini/"; - } - else if (is_nano) { - p2pool::DATA_DIR += "nano/"; - } - } - } - } - - if (!p2pool::DATA_DIR.empty()) { - printf("Using \"%s\" for P2Pool files\n", p2pool::DATA_DIR.c_str()); - } - - // Try to create it if it doesn't exist - if (!p2pool::DATA_DIR.empty()) { + // Try to create it if it doesn't exist std::error_code err; - std::filesystem::create_directories(p2pool::DATA_DIR, err); + std::filesystem::create_directories(params.m_dataDir, err); } #if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG) @@ -310,7 +282,7 @@ int main(int argc, char* argv[]) // Create default loop here uv_default_loop(); - p2pool::log::start(); + p2pool::log::start(params); p2pool::init_crypto_cache(); @@ -331,7 +303,7 @@ int main(int argc, char* argv[]) #endif try { - p2pool::p2pool pool(argc, argv); + p2pool::p2pool pool(params); result = pool.run(); } catch (...) { diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp index 40cd363..0da6baa 100644 --- a/src/p2p_server.cpp +++ b/src/p2p_server.cpp @@ -66,7 +66,7 @@ static constexpr hash seed_onion_nodes[] = { P2PServer::P2PServer(p2pool* pool) : TCPServer(DEFAULT_BACKLOG, P2PClient::allocate, pool->params().m_socks5Proxy) , m_pool(pool) - , m_cache(pool->params().m_blockCache ? new BlockCache() : nullptr) + , m_cache(pool->params().m_blockCache ? new BlockCache(pool->params()) : nullptr) , m_cacheLoaded(false) , m_initialPeerList(pool->params().m_p2pPeerList) , m_cachedBlocks(nullptr) @@ -561,7 +561,9 @@ void P2PServer::save_peer_list_async() void P2PServer::save_peer_list() { - const std::string path = DATA_DIR + saved_peer_list_file_name; + const Params& params = m_pool->params(); + + const std::string path = params.m_dataDir + saved_peer_list_file_name; std::ofstream f(path, std::ios::binary); @@ -606,7 +608,7 @@ void P2PServer::save_peer_list() const SideChain& s = m_pool->side_chain(); if (s.onion_pubkeys_count() > 0) { - const std::string onion_path = DATA_DIR + saved_onion_peer_list_file_name; + const std::string onion_path = params.m_dataDir + saved_onion_peer_list_file_name; f.open(onion_path, std::ios::binary); @@ -726,7 +728,7 @@ void P2PServer::load_peer_list() // Finally load peers from p2pool_peers.txt and p2pool_onion_peers.txt for (size_t i = 0, n = (m_socks5Proxy.empty() ? 1 : 2); i < n; ++i) { - const std::string path = DATA_DIR + (i ? saved_onion_peer_list_file_name : saved_peer_list_file_name); + const std::string path = m_pool->params().m_dataDir + (i ? saved_onion_peer_list_file_name : saved_peer_list_file_name); std::ifstream f(path); diff --git a/src/p2pool.cpp b/src/p2pool.cpp index dd741c8..8b1f735 100644 --- a/src/p2pool.cpp +++ b/src/p2pool.cpp @@ -63,8 +63,9 @@ namespace p2pool { static uint64_t BLOCK_HEADERS_REQUIRED = 720; -p2pool::p2pool(int argc, char* argv[]) +p2pool::p2pool(const Params& params) : m_stopped(false) + , m_params(params) , m_updateSeed(true) , m_submitBlockData{} , m_zmqLastActive(0) @@ -73,49 +74,33 @@ p2pool::p2pool(int argc, char* argv[]) { LOGINFO(1, log::LightCyan() << VERSION); - Params* p = new Params(argc, argv); - - if (!p->valid()) { - LOGERR(1, "Invalid or missing command line. Try \"p2pool --help\"."); - delete p; - throw std::exception(); - } - - m_params = p; - // P2Pool-nano requires more Monero blocks for the initial sync - if (m_params->m_nano) { + if (m_params.m_nano) { BLOCK_HEADERS_REQUIRED = 1440; } bkg_jobs_tracker = new BackgroundJobTracker(); #ifdef WITH_UPNP - if (p->m_upnp) { + if (m_params.m_upnp) { init_upnp(); } #endif - for (Params::Host& h : p->m_hosts) { - if (!h.init_display_name(*p)) { - throw std::exception(); - } - } - m_currentHostIndex = 0; - m_hostPing.resize(p->m_hosts.size()); + m_hostPing.resize(m_params.m_hosts.size()); hash pub, sec, eph_public_key; generate_keys(pub, sec); uint8_t view_tag; - if (!p->m_miningWallet.get_eph_public_key(sec, 0, eph_public_key, view_tag)) { + if (!m_params.m_miningWallet.get_eph_public_key(sec, 0, eph_public_key, view_tag)) { LOGERR(1, "Invalid wallet address: get_eph_public_key failed"); throw std::exception(); } - const NetworkType type = p->m_miningWallet.type(); + const NetworkType type = m_params.m_miningWallet.type(); if (type == NetworkType::Testnet) { LOGWARN(1, "Mining to a testnet wallet address"); @@ -196,34 +181,17 @@ p2pool::p2pool(int argc, char* argv[]) } m_timer.data = this; - m_api = p->m_apiPath.empty() ? nullptr : new p2pool_api(p->m_apiPath, p->m_localStats); + m_api = m_params.m_apiPath.empty() ? nullptr : new p2pool_api(m_params.m_apiPath, m_params.m_localStats); - if (p->m_localStats && !m_api) { + if (m_params.m_localStats && !m_api) { LOGERR(1, "--local-api and --stratum-api command line parameters can't be used without --data-api"); throw std::exception(); } - m_sideChain = new SideChain(this, type, p->m_mini ? "mini" : (p->m_nano ? "nano" : nullptr)); - - const int p2p_port = m_sideChain->is_mini() ? DEFAULT_P2P_PORT_MINI : (m_sideChain->is_nano() ? DEFAULT_P2P_PORT_NANO : DEFAULT_P2P_PORT); - - if (p->m_noClearnetP2P) { - char buf[48] = {}; - log::Stream s(buf); - s << "127.0.0.1:" << p2p_port; - - p->m_p2pAddresses = buf; - } - else if (p->m_p2pAddresses.empty()) { - char buf[48] = {}; - log::Stream s(buf); - s << "[::]:" << p2p_port << ",0.0.0.0:" << p2p_port; - - p->m_p2pAddresses = buf; - } + m_sideChain = new SideChain(this, type, m_params.m_mini ? "mini" : (m_params.m_nano ? "nano" : nullptr)); #ifdef WITH_RANDOMX - if (p->m_disableRandomX) { + if (m_params.m_disableRandomX) { m_hasher = new RandomX_Hasher_RPC(this); } else { @@ -252,7 +220,7 @@ p2pool::p2pool(int argc, char* argv[]) p2pool::~p2pool() { #ifdef WITH_UPNP - if (m_params->m_upnp) { + if (m_params.m_upnp) { destroy_upnp(); } #endif @@ -295,7 +263,6 @@ p2pool::~p2pool() delete m_hasher; delete m_blockTemplate; delete m_mempool; - delete m_params; { auto* p = bkg_jobs_tracker; @@ -318,7 +285,7 @@ void p2pool::update_host_ping(const std::string& display_name, double ping) LOGWARN(1, display_name << " ping is " << ping << " ms, this is too high for an efficient mining. Try to use a different node, or your own local node."); } - const std::vector& v = m_params->m_hosts; + const std::vector& v = m_params.m_hosts; for (size_t i = 0, n = v.size(); i < n; ++i) { if (v[i].m_displayName == display_name) { @@ -332,8 +299,8 @@ void p2pool::print_hosts() const { const Params::Host& host = current_host(); - for (size_t i = 0, n = m_params->m_hosts.size(); i < n; ++i) { - const Params::Host& h = m_params->m_hosts[i]; + for (size_t i = 0, n = m_params.m_hosts.size(); i < n; ++i) { + const Params::Host& h = m_params.m_hosts[i]; char buf[64] = {}; if (m_hostPing[i] > 0.0) { @@ -417,7 +384,7 @@ void p2pool::handle_tx(TxMempoolData& tx) } #if TEST_MEMPOOL_PICKING_ALGORITHM - m_blockTemplate->update(miner_data(), *m_mempool, &m_params->m_wallet); + m_blockTemplate->update(miner_data(), *m_mempool, &m_params.m_wallet); #endif m_zmqLastActive = seconds_since_epoch(); @@ -557,7 +524,7 @@ void p2pool::get_missing_heights() const Params::Host& host = current_host(); - JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [this, h](const char* data, size_t size, double) { ChainMain block; @@ -801,14 +768,14 @@ void p2pool::update_aux_data(const hash& chain_id) void p2pool::send_aux_job_donation() { #ifdef WITH_TLS - if (m_params->m_authorKeyFile.empty()) { + if (m_params.m_authorKeyFile.empty()) { return; } - std::ifstream f(m_params->m_authorKeyFile, std::ios::binary | std::ios::ate); + std::ifstream f(m_params.m_authorKeyFile, std::ios::binary | std::ios::ate); if (!f.good()) { - LOGERR(1, "send_aux_job_donation: failed to open " << m_params->m_authorKeyFile); + LOGERR(1, "send_aux_job_donation: failed to open " << m_params.m_authorKeyFile); return; } @@ -816,7 +783,7 @@ void p2pool::send_aux_job_donation() ON_SCOPE_LEAVE([&key](){ secure_zero_memory(key); }); if (f.tellg() != static_cast(sizeof(key))) { - LOGERR(1, "send_aux_job_donation: " << m_params->m_authorKeyFile << " has an invalid size"); + LOGERR(1, "send_aux_job_donation: " << m_params.m_authorKeyFile << " has an invalid size"); return; } @@ -824,21 +791,21 @@ void p2pool::send_aux_job_donation() f.read(reinterpret_cast(&key), sizeof(key)); if (!f.good()) { - LOGERR(1, "send_aux_job_donation: failed to read data from " << m_params->m_authorKeyFile); + LOGERR(1, "send_aux_job_donation: failed to read data from " << m_params.m_authorKeyFile); return; } const uint64_t timestamp = time(nullptr); if (timestamp >= read_unaligned(reinterpret_cast(key.expiration_time))) { - LOGERR(1, "send_aux_job_donation: " << m_params->m_authorKeyFile << " is expired"); + LOGERR(1, "send_aux_job_donation: " << m_params.m_authorKeyFile << " is expired"); return; } const uint8_t* p = reinterpret_cast(&key); if (!ED25519_verify(p, sizeof(key.pub_key) + sizeof(key.expiration_time), key.master_key_signature, ED25519_MASTER_PUBLIC_KEY)) { - LOGERR(1, "send_aux_job_donation: " << m_params->m_authorKeyFile << ": signature verification failed"); + LOGERR(1, "send_aux_job_donation: " << m_params.m_authorKeyFile << ": signature verification failed"); return; } @@ -1162,7 +1129,7 @@ void p2pool::submit_block() const const uint64_t t1 = microseconds_since_epoch(); - JSONRPCRequest::call(host.m_address, host.m_rpcPort, request, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(host.m_address, host.m_rpcPort, request, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [height, diff, template_id, nonce, extra_nonce, merge_mining_root, is_external](const char* data, size_t size, double) { rapidjson::Document doc; @@ -1281,7 +1248,7 @@ void p2pool::download_block_headers1(uint64_t current_height) s.m_pos = 0; s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << prev_seed_height << "}}" << '\0'; - JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [this, prev_seed_height, current_height](const char* data, size_t size, double) { ChainMain block; if (parse_block_header(data, size, block)) { @@ -1314,7 +1281,7 @@ void p2pool::download_block_headers2(uint64_t current_height) s.m_pos = 0; s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << seed_height << "}}" << '\0'; - JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [this, seed_height, current_height](const char* data, size_t size, double) { ChainMain block; if (parse_block_header(data, size, block)) { @@ -1350,7 +1317,7 @@ void p2pool::download_block_headers3(uint64_t start_height, uint64_t current_hei s.m_pos = 0; s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << start_height << ",\"end_height\":" << next_height << "}}" << '\0'; - JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [this, start_height, next_height, current_height](const char* data, size_t size, double) { if (parse_block_headers_range(data, size) == next_height - start_height + 1) { download_block_headers3(next_height + 1, current_height); @@ -1383,7 +1350,7 @@ void p2pool::download_block_headers4(uint64_t start_height, uint64_t current_hei s.m_pos = 0; s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << start_height << ",\"end_height\":" << current_height - 1 << "}}" << '\0'; - JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [this, start_height, current_height, host](const char* data, size_t size, double) { if (parse_block_headers_range(data, size) == current_height - start_height) { @@ -1392,14 +1359,14 @@ void p2pool::download_block_headers4(uint64_t start_height, uint64_t current_hei m_p2pServer = new P2PServer(this); m_stratumServer = new StratumServer(this); #if defined(WITH_RANDOMX) && !defined(P2POOL_UNIT_TESTS) - if (m_params->m_minerThreads) { - start_mining(m_params->m_minerThreads); + if (m_params.m_minerThreads) { + start_mining(m_params.m_minerThreads); } { WriteLock lock(m_ZMQReaderLock); try { - m_ZMQReader = new ZMQReader(host.m_address, host.m_zmqPort, m_params->m_socks5Proxy, this); + m_ZMQReader = new ZMQReader(host.m_address, host.m_zmqPort, m_params.m_socks5Proxy, this); m_zmqLastActive = seconds_since_epoch(); } catch (const std::exception& e) { @@ -1413,10 +1380,10 @@ void p2pool::download_block_headers4(uint64_t start_height, uint64_t current_hei get_miner_data(); // Get ping times for all other hosts - for (const Params::Host& h : m_params->m_hosts) { + for (const Params::Host& h : m_params.m_hosts) { const std::string& name = h.m_displayName; if (name != host.m_displayName) { - JSONRPCRequest::call(h.m_address, h.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", h.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(h.m_address, h.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", h.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [this, name](const char*, size_t, double tcp_ping) { update_host_ping(name, tcp_ping); }, [](const char*, size_t, double) {}); } @@ -1424,7 +1391,7 @@ void p2pool::download_block_headers4(uint64_t start_height, uint64_t current_hei std::vector merge_mining_clients; - for (const auto& h : m_params->m_mergeMiningHosts) { + for (const auto& h : m_params.m_mergeMiningHosts) { IMergeMiningClient* c = IMergeMiningClient::create(this, h.m_host, h.m_wallet); if (c) { merge_mining_clients.push_back(c); @@ -1525,7 +1492,7 @@ void p2pool::get_info() { const Params::Host& host = current_host(); - JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}", host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}", host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [this](const char* data, size_t size, double) { parse_get_info_rpc(data, size); @@ -1549,7 +1516,7 @@ void p2pool::load_found_blocks() return; } - std::ifstream f(DATA_DIR + FOUND_BLOCKS_FILE); + std::ifstream f(m_params.m_dataDir + FOUND_BLOCKS_FILE); if (!f.is_open()) { return; } @@ -1644,7 +1611,7 @@ void p2pool::get_version() { const Params::Host& host = current_host(); - JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [this](const char* data, size_t size, double) { parse_get_version_rpc(data, size); @@ -1721,7 +1688,7 @@ void p2pool::get_miner_data(bool retry) const Params::Host& host = current_host(); - JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_miner_data\"}", host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, + JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_miner_data\"}", host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint, [this, host](const char* data, size_t size, double tcp_ping) { parse_get_miner_data_rpc(data, size); @@ -2085,7 +2052,7 @@ void p2pool::api_update_block_found(const ChainMain* data, const PoolBlock* bloc difficulty_type diff; if (data && get_difficulty_at_height(data->height, diff)) { - const std::string path = DATA_DIR + FOUND_BLOCKS_FILE; + const std::string path = m_params.m_dataDir + FOUND_BLOCKS_FILE; std::ofstream f(path, std::ios::app); if (f.is_open()) { f << cur_time << ' ' << data->height << ' ' << data->id << ' ' << diff << ' ' << total_hashes << '\n'; @@ -2141,7 +2108,7 @@ void p2pool::on_external_block(const PoolBlock& block) void p2pool::api_update_aux_data() { - if (!m_api || !m_params->m_localStats || m_stopped) { + if (!m_api || !m_params.m_localStats || m_stopped) { return; } @@ -2291,7 +2258,7 @@ bool p2pool::zmq_running() const const Params::Host& p2pool::switch_host() { - const std::vector& v = m_params->m_hosts; + const std::vector& v = m_params.m_hosts; return v[++m_currentHostIndex % v.size()]; } @@ -2316,7 +2283,7 @@ void p2pool::reconnect_to_host() m_ZMQReader = nullptr; try { - ZMQReader* new_reader = new ZMQReader(new_host.m_address, new_host.m_zmqPort, m_params->m_socks5Proxy, this); + ZMQReader* new_reader = new ZMQReader(new_host.m_address, new_host.m_zmqPort, m_params.m_socks5Proxy, this); m_zmqLastActive = seconds_since_epoch(); m_ZMQReader = new_reader; } @@ -2332,7 +2299,7 @@ void p2pool::reconnect_to_host() int p2pool::run() { - if (!m_params->valid()) { + if (!m_params.valid()) { LOGERR(1, "Invalid or missing command line. Try \"p2pool --help\"."); return 1; } @@ -2343,8 +2310,8 @@ int p2pool::run() } #ifdef WITH_TLS - if (!m_params->m_tlsCert.empty() && !m_params->m_tlsCertKey.empty()) { - if (!ServerTls::load_from_files(m_params->m_tlsCert.c_str(), m_params->m_tlsCertKey.c_str())) { + if (!m_params.m_tlsCert.empty() && !m_params.m_tlsCertKey.empty()) { + if (!ServerTls::load_from_files(m_params.m_tlsCert.c_str(), m_params.m_tlsCertKey.c_str())) { LOGERR(1, "Failed to load TLS files"); return 1; } diff --git a/src/p2pool.h b/src/p2pool.h index e461999..5e0aa79 100644 --- a/src/p2pool.h +++ b/src/p2pool.h @@ -40,7 +40,7 @@ struct PoolBlock; class p2pool : public MinerCallbackHandler, public nocopy_nomove { public: - p2pool(int argc, char* argv[]); + explicit p2pool(const Params& params); ~p2pool() override; int run(); @@ -48,13 +48,13 @@ public: bool stopped() const { return m_stopped; } void stop(); - const Params& params() const { return *m_params; } + const Params& params() const { return m_params; } BlockTemplate& block_template() { return *m_blockTemplate; } SideChain& side_chain() { return *m_sideChain; } FORCEINLINE const Params::Host& current_host() const { - const std::vector& v = m_params->m_hosts; + const std::vector& v = m_params.m_hosts; return v[m_currentHostIndex % v.size()]; } @@ -158,7 +158,7 @@ private: std::atomic m_stopped; - const Params* m_params; + const Params& m_params; std::vector m_hostPing; std::atomic m_currentHostIndex; diff --git a/src/params.cpp b/src/params.cpp index a4e3d9c..8e9c827 100644 --- a/src/params.cpp +++ b/src/params.cpp @@ -19,6 +19,7 @@ #include "params.h" #include "stratum_server.h" #include "p2p_server.h" +#include LOG_CATEGORY(Params) @@ -119,14 +120,12 @@ Params::Params(int argc, char* const argv[]) } if ((strcmp(argv[i], "--data-dir") == 0) && (i + 1 < argc)) { - // Processed in main.cpp - ++i; + m_dataDir = argv[++i]; ok = true; } if ((strcmp(argv[i], "--log-file") == 0) && (i + 1 < argc)) { - // Processed in main.cpp - ++i; + m_logFilePath = argv[++i]; ok = true; } @@ -328,6 +327,23 @@ Params::Params(int argc, char* const argv[]) m_hosts.emplace_back(); } + const int p2p_port = m_mini ? DEFAULT_P2P_PORT_MINI : (m_nano ? DEFAULT_P2P_PORT_NANO : DEFAULT_P2P_PORT); + + if (m_noClearnetP2P) { + char buf[48] = {}; + log::Stream s(buf); + s << "127.0.0.1:" << p2p_port; + + m_p2pAddresses = buf; + } + else if (m_p2pAddresses.empty()) { + char buf[48] = {}; + log::Stream s(buf); + s << "[::]:" << p2p_port << ",0.0.0.0:" << p2p_port; + + m_p2pAddresses = buf; + } + if (m_stratumAddresses.empty()) { const int stratum_port = DEFAULT_STRATUM_PORT; @@ -364,6 +380,43 @@ Params::Params(int argc, char* const argv[]) } m_displayWallet.assign(display_wallet_buf, Wallet::ADDRESS_LENGTH); + + for (Params::Host& h : m_hosts) { + if (!h.init_display_name(*this)) { + throw std::exception(); + } + } + + // If the data directory is not set, check if P2Pool has write access to the current directory + // If it doesn't, switch to user's home directory + if (m_dataDir.empty()) { + std::ofstream f("p2pool.tmp"); + if (f && f.put(' ')) { + f.close(); + std::remove("p2pool.tmp"); + } + else { + char buf[1024]; + size_t size = sizeof(buf); + + if (uv_os_homedir(buf, &size) == 0) { + m_dataDir.assign(buf, size); + fixup_path(m_dataDir); + + m_dataDir += ".p2pool/"; + + if (m_mini) { + m_dataDir += "mini/"; + } + else if (m_nano) { + m_dataDir += "nano/"; + } + } + } + } + else { + fixup_path(m_dataDir); + } } bool Params::valid() const diff --git a/src/params.h b/src/params.h index 257b39b..2c0af0e 100644 --- a/src/params.h +++ b/src/params.h @@ -85,6 +85,8 @@ struct Params std::string m_stratumAddresses; std::string m_p2pAddresses; std::string m_p2pPeerList; + std::string m_dataDir; + std::string m_logFilePath; std::string m_sidechainConfig; std::string m_apiPath; uint64_t m_stratumBanTime = DEFAULT_STRATUM_BAN_TIME; diff --git a/src/util.cpp b/src/util.cpp index eb77c8a..45d3e84 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -159,9 +159,6 @@ secure_zero_memory(volatile void* data, size_t size) const uint8_t ED25519_MASTER_PUBLIC_KEY[32] = {51,175,37,73,203,241,188,115,195,255,123,53,218,120,90,74,186,240,82,178,67,139,124,91,180,106,188,181,187,51,236,10}; -std::string DATA_DIR; -std::string LOG_FILE_PATH; - SoftwareID get_software_id(uint32_t value) { switch (value) { diff --git a/src/util.h b/src/util.h index bf9c3fb..6cdad5b 100644 --- a/src/util.h +++ b/src/util.h @@ -44,9 +44,6 @@ extern const char* VERSION; extern const uint8_t ED25519_MASTER_PUBLIC_KEY[32]; -extern std::string DATA_DIR; -extern std::string LOG_FILE_PATH; - enum class SoftwareID : uint32_t { P2Pool = 0, GoObserver = 0x624F6F47UL, diff --git a/tests/src/block_template_tests.cpp b/tests/src/block_template_tests.cpp index 982cd98..a45f580 100644 --- a/tests/src/block_template_tests.cpp +++ b/tests/src/block_template_tests.cpp @@ -58,7 +58,7 @@ TEST(block_template, update) params.m_miningWallet = Wallet("44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg"); // Test 1: empty template - tpl.update(data, mempool, ¶ms); + tpl.update(data, mempool, params); ASSERT_EQ(tpl.get_reward(), 600000000000ULL); const PoolBlock* b = tpl.pool_block_template(); @@ -113,7 +113,7 @@ TEST(block_template, update) } ASSERT_EQ(mempool.size(), 512); - tpl.update(data, mempool, ¶ms); + tpl.update(data, mempool, params); ASSERT_EQ(tpl.get_reward(), 612054770773ULL); ASSERT_EQ(b->m_sidechainId, H("c9df4853003ab436416b9fc9a5a072d16b4dede849e697a8be2ebb9c88c8ec72")); @@ -154,7 +154,7 @@ TEST(block_template, update) data.aux_chains.emplace_back(H("01f0cf665bd4cd31cbb2b2470236389c483522b350335e10a4a5dca34cb85990"), H("d9de1cfba7cdbd47f12f77addcb39b24c1ae7a16c35372bf28d6aee5d7579ee6"), difficulty_type(1000000)); - tpl.update(data, mempool, ¶ms); + tpl.update(data, mempool, params); ASSERT_EQ(tpl.get_reward(), 600300000000ULL); ASSERT_EQ(b->m_sidechainId, H("c32abac2cad40e263a94f5f43f90e0a7d7d4b151305b79951dbc8c88c3180613")); @@ -191,7 +191,7 @@ TEST(block_template, update) } ASSERT_EQ(mempool.size(), 10000); - tpl.update(data, mempool, ¶ms); + tpl.update(data, mempool, params); ASSERT_EQ(tpl.get_reward(), 619742028747ULL); ASSERT_EQ(b->m_sidechainId, H("69e7dd43dd99ac6be3f57ca333cc0d814189e83aee1773c99a341aca085c0d46")); @@ -251,13 +251,13 @@ TEST(block_template, submit_sidechain_block) std::mt19937_64 rng(101112); for (uint64_t i = 0, i2 = 0, i3 = 0; i < sidechain.chain_window_size() * 3; ++i) { - tpl.update(data, mempool, ¶ms); + tpl.update(data, mempool, params); if ((rng() % 31) == 0) { - tpl2.update(data, mempool, ¶ms); + tpl2.update(data, mempool, params); if ((rng() % 11) == 0) { - tpl3.update(data, mempool, ¶ms); + tpl3.update(data, mempool, params); ++i3; ASSERT_TRUE(tpl3.submit_sidechain_block(i3, 0, 0)); } diff --git a/tests/src/pool_block_tests.cpp b/tests/src/pool_block_tests.cpp index 6cb7250..cdd60e2 100644 --- a/tests/src/pool_block_tests.cpp +++ b/tests/src/pool_block_tests.cpp @@ -252,7 +252,7 @@ TEST(pool_block, verify) params.m_miningWallet = Wallet("44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg"); params.m_subaddress = Wallet("86eQxzSW4AZfvsWRSop755WZUsog6L3x32NRZukeeShnS4mBGVpcqQhS6pCNxj44usPKNwesZ45ooHyjDku6nVZdT3Q9qrz"); - tpl.update(data, mempool, ¶ms); + tpl.update(data, mempool, params); std::vector blobs; uint64_t height;