/* * This file is part of the Monero P2Pool * Copyright (c) 2021-2024 SChernykh * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "common.h" #include "crypto.h" #include "p2pool.h" #include "stratum_server.h" #include "p2p_server.h" #include #ifdef WITH_RANDOMX #include "randomx.h" #endif void p2pool_usage() { printf("P2Pool %s\n" "\nUsage:\n\n" \ "--wallet Wallet address to mine to. Subaddresses and integrated addresses are not supported!\n" "--host IP address of your Monero node, default is 127.0.0.1\n" "--rpc-port monerod RPC API port number, default is 18081\n" "--zmq-port monerod ZMQ pub port number, default is 18083 (same port as in monerod's \"--zmq-pub\" command line parameter)\n" "--stratum Comma-separated list of IP:port for stratum server to listen on\n" "--p2p Comma-separated list of IP:port for p2p server to listen on\n" "--addpeers Comma-separated list of IP:port of other p2pool nodes to connect to\n" "--light-mode Don't allocate RandomX dataset, saves 2GB of RAM\n" "--loglevel Verbosity of the log, integer number between 0 and %d\n" "--config Name of the p2pool config file\n" "--data-api Path to the p2pool JSON data (use it in tandem with an external web-server)\n" "--local-api Enable /local/ path in api path for Stratum Server and built-in miner statistics\n" "--stratum-api An alias for --local-api\n" "--no-cache Disable p2pool.cache\n" "--no-color Disable colors in console output\n" #ifdef WITH_RANDOMX "--no-randomx Disable internal RandomX hasher: p2pool will use RPC calls to monerod to check PoW hashes\n" #endif "--out-peers N Maximum number of outgoing connections for p2p server (any value between 10 and 450)\n" "--in-peers N Maximum number of incoming connections for p2p server (any value between 10 and 450)\n" "--start-mining N Start built-in miner using N threads (any value between 1 and 64)\n" "--mini Connect to p2pool-mini sidechain. Note that it will also change default p2p port from %d to %d\n" "--no-autodiff Disable automatic difficulty adjustment for miners connected to stratum (WARNING: incompatible with Nicehash and MRR)\n" "--rpc-login Specify username[:password] required for Monero RPC server\n" "--socks5 Specify IP:port of a SOCKS5 proxy to use for outgoing connections\n" "--no-dns Disable DNS queries, use only IP addresses to connect to peers (seed node DNS will be unavailable too)\n" "--p2p-external-port Port number that your router uses for mapping to your local p2p port. Use it if you are behind a NAT and still want to accept incoming connections\n" #ifdef WITH_UPNP "--no-upnp Disable UPnP port forwarding\n" "--no-igd An alias for --no-upnp\n" "--upnp-stratum Port forward Stratum port (it's not forwarded by default)\n" #endif "--version Print p2pool's version and build details\n" "--help Show this help message\n\n" "Example command line:\n\n" "%s --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:%d --p2p 0.0.0.0:%d\n\n", p2pool::VERSION, p2pool::log::MAX_GLOBAL_LOG_LEVEL, p2pool::DEFAULT_P2P_PORT, p2pool::DEFAULT_P2P_PORT_MINI, #ifdef _WIN32 "p2pool.exe" #else "./p2pool" #endif , p2pool::DEFAULT_STRATUM_PORT , p2pool::DEFAULT_P2P_PORT ); } void p2pool_version() { printf("P2Pool %s\n", p2pool::VERSION); } int p2pool_test() { #ifdef WITH_RANDOMX const char myKey[] = "test key 000"; const char myInput[] = "This is a test"; char hash[RANDOMX_HASH_SIZE]; const randomx_flags flags = randomx_get_flags() | RANDOMX_FLAG_FULL_MEM; randomx_cache* myCache = randomx_alloc_cache(flags); if (!myCache) { printf("Cache allocation failed\n"); return 1; } randomx_init_cache(myCache, myKey, sizeof(myKey) - 1); randomx_dataset* myDataset = randomx_alloc_dataset(flags); if (!myDataset) { printf("Dataset allocation failed\n"); return 1; } { const uint32_t numThreads = std::max(std::thread::hardware_concurrency(), 1U); const uint32_t numItems = randomx_dataset_item_count(); std::vector threads; threads.reserve(numThreads); for (uint32_t i = 1; i < numThreads; ++i) { const uint32_t a = (numItems * i) / numThreads; const uint32_t b = (numItems * (i + 1)) / numThreads; threads.emplace_back([myDataset, myCache, a, b]() { randomx_init_dataset(myDataset, myCache, a, b - a); }); } randomx_init_dataset(myDataset, myCache, 0, numItems / numThreads); for (std::thread& t : threads) { t.join(); } } randomx_release_cache(myCache); randomx_vm* myMachine = randomx_create_vm(flags, nullptr, myDataset); if (!myMachine) { printf("Failed to create a virtual machine"); return 1; } memset(hash, 0, sizeof(hash)); memcpy(hash, myInput, sizeof(myInput)); for (size_t i = 0; i < 100; ++i) { randomx_calculate_hash(myMachine, &hash, sizeof(hash), hash); } char buf[RANDOMX_HASH_SIZE * 2 + 1] = {}; p2pool::log::Stream s(buf); s << p2pool::log::hex_buf(hash, RANDOMX_HASH_SIZE) << '\0'; constexpr char expected_hash[] = "3b5ecc2bb14f467161a04fe476b541194fba82dbbbfc7c320961f922a0294dee"; if (memcmp(buf, expected_hash, RANDOMX_HASH_SIZE * 2) != 0) { printf("Invalid hash calculated: expected %s, got %s\n", expected_hash, buf); return 1; } randomx_destroy_vm(myMachine); randomx_release_dataset(myDataset); #endif printf("Self-test passed\n"); return 0; } int main(int argc, char* argv[]) { if (argc == 1) { p2pool_usage(); return 0; } 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(); return 0; } if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "/version") || !strcmp(argv[i], "-v") || !strcmp(argv[i], "/v")) { p2pool_version(); return 0; } if (!strcmp(argv[i], "--test")) { return p2pool_test(); } } memory_tracking_start(); p2pool::init_crypto_cache(); int result = static_cast(curl_global_init_mem(CURL_GLOBAL_ALL, p2pool::malloc_hook, p2pool::free_hook, p2pool::realloc_hook, p2pool::strdup_hook, p2pool::calloc_hook)); if (result != CURLE_OK) { return result; } try { p2pool::p2pool pool(argc, argv); result = pool.run(); } catch (...) { result = 1; } curl_global_cleanup(); p2pool::destroy_crypto_cache(); if (!memory_tracking_stop()) { result = 1; } return result; }