Added support for params config file

This commit is contained in:
SChernykh
2025-11-21 20:13:13 +01:00
parent d9cea1cfc3
commit de28201edc
9 changed files with 255 additions and 18 deletions
+32 -4
View File
@@ -108,6 +108,7 @@ void p2pool_usage()
"--full-validation Enables full share validation / increases CPU usage\n"
"--onion-address Tell other peers to use this .onion address to connect to this node through TOR\n"
"--no-clearnet-p2p Forces P2P server to listen on 127.0.0.1 and to not connect to clearnet IPs\n"
"--params-file File name to load parameters from. It can't be used together with any other command line parameters\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",
@@ -222,10 +223,10 @@ int p2pool_test()
return 0;
}
static p2pool::Params get_params(int argc, char* argv[]) noexcept
static p2pool::Params get_params(int argc, const char* const argv[]) noexcept
{
try {
std::vector<std::vector<std::string_view>> args;
std::vector<std::vector<std::string>> args;
args.reserve(argc);
// Group command-line parameters by the pattern "--name [data1 data2 ... data_n]"
@@ -236,7 +237,7 @@ static p2pool::Params get_params(int argc, char* argv[]) noexcept
if ((arg.size() > 2) && (arg[0] == '-') && (arg[1] == '-')) {
// Store the parameter name without the "--" prefix
arg.remove_prefix(2);
args.emplace_back(std::vector<std::string_view>(1, std::move(arg)));
args.emplace_back(std::vector<std::string>(1, std::string(arg)));
}
else if (!args.empty()) {
args.back().emplace_back(std::move(arg));
@@ -256,6 +257,22 @@ static p2pool::Params get_params(int argc, char* argv[]) noexcept
abort();
}
static p2pool::Params get_params(const std::string& params_file) noexcept
{
try {
p2pool::Params params(p2pool::parse_config(params_file));
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) {
@@ -263,6 +280,8 @@ int main(int argc, char* argv[])
return 0;
}
std::string params_file;
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "/help") || !strcmp(argv[i], "-h") || !strcmp(argv[i], "/h") || !strcmp(argv[i], "/?")) {
p2pool_usage();
@@ -277,6 +296,15 @@ int main(int argc, char* argv[])
if (!strcmp(argv[i], "--test")) {
return p2pool_test();
}
if (!strcmp(argv[i], "--params-file") && (i + 1 < argc)) {
params_file = argv[++i];
}
}
if (!params_file.empty() && (argc != 3)) {
fprintf(stderr, "--params-file can't be combined with other command line parameters\n");
return 1;
}
#if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
@@ -292,7 +320,7 @@ int main(int argc, char* argv[])
// Some P2Pool code will not work without libuv initialized, so the code above this line must be minimal
uv_default_loop();
const p2pool::Params params = get_params(argc, argv);
const p2pool::Params params = params_file.empty() ? get_params(argc, argv) : get_params(params_file);
if (!params.m_dataDir.empty()) {
printf("Using \"%s\" for P2Pool files\n", params.m_dataDir.c_str());
+13 -13
View File
@@ -30,7 +30,7 @@ namespace p2pool {
static constexpr uint64_t MIN_STRATUM_BAN_TIME = UINT64_C(1);
static constexpr uint64_t MAX_STRATUM_BAN_TIME = (UINT64_C(1) << 34) - 1;
Params::Params(const std::vector<std::vector<std::string_view>>& args)
Params::Params(const std::vector<std::vector<std::string>>& args)
{
auto has1 = [](const auto& v) { return (v.size() > 1) && !v[1].empty();};
auto has2 = [](const auto& v) { return (v.size() > 2) && !v[2].empty();};
@@ -44,7 +44,7 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
bool ok = false;
if ((arg[0] == "host") && has1(arg)) {
const char* address = arg[1].data();
const char* address = arg[1].c_str();
if (m_hosts.empty()) {
m_hosts.emplace_back();
@@ -63,7 +63,7 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
m_hosts.emplace_back();
}
m_hosts.back().m_rpcPort = static_cast<int32_t>(std::min(std::max(strtoul(arg[1].data(), nullptr, 10), 1UL), 65535UL));
m_hosts.back().m_rpcPort = static_cast<int32_t>(std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 1UL), 65535UL));
ok = true;
}
@@ -72,7 +72,7 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
m_hosts.emplace_back();
}
m_hosts.back().m_zmqPort = static_cast<int32_t>(std::min(std::max(strtoul(arg[1].data(), nullptr, 10), 1UL), 65535UL));
m_hosts.back().m_zmqPort = static_cast<int32_t>(std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 1UL), 65535UL));
ok = true;
}
@@ -82,7 +82,7 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
}
if ((arg[0] == "wallet") && has1(arg)) {
const char* s = arg[1].data();
const char* s = arg[1].c_str();
if (!m_mainWallet.decode(s)) {
LOGERR(1, "Wallet " << s << " failed to decode");
@@ -92,7 +92,7 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
}
if ((arg[0] == "subaddress") && has1(arg)) {
const char* s = arg[1].data();
const char* s = arg[1].c_str();
if (!m_subaddress.decode(s)) {
LOGERR(1, "Subaddress " << s << " failed to decode");
@@ -107,7 +107,7 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
}
if ((arg[0] == "stratum-ban-time") && has1(arg)) {
m_stratumBanTime = strtoull(arg[1].data(), nullptr, 10);
m_stratumBanTime = strtoull(arg[1].c_str(), nullptr, 10);
ok = true;
}
@@ -122,7 +122,7 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
}
if ((arg[0] == "loglevel") && has1(arg)) {
const int level = std::min(std::max<int>(static_cast<int>(strtol(arg[1].data(), nullptr, 10)), 0), log::MAX_GLOBAL_LOG_LEVEL);
const int level = std::min(std::max<int>(static_cast<int>(strtol(arg[1].c_str(), nullptr, 10)), 0), log::MAX_GLOBAL_LOG_LEVEL);
log::GLOBAL_LOG_LEVEL = level;
ok = true;
}
@@ -170,17 +170,17 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
#endif
if (((arg[0] == "out-peers") || (arg[0] == "outpeers")) && has1(arg)) {
m_maxOutgoingPeers = std::min(std::max(strtoul(arg[1].data(), nullptr, 10), 10UL), 450UL);
m_maxOutgoingPeers = std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 10UL), 450UL);
ok = true;
}
if (((arg[0] == "in-peers") || (arg[0] == "inpeers")) && has1(arg)) {
m_maxIncomingPeers = std::min(std::max(strtoul(arg[1].data(), nullptr, 10), 10UL), 450UL);
m_maxIncomingPeers = std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 10UL), 450UL);
ok = true;
}
if ((arg[0] == "start-mining") && has1(arg)) {
m_minerThreads = std::min(std::max(strtoul(arg[1].data(), nullptr, 10), 1UL), 64UL);
m_minerThreads = std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 1UL), 64UL);
ok = true;
}
@@ -240,7 +240,7 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
}
if ((arg[0] == "p2p-external-port") && has1(arg)) {
m_p2pExternalPort = static_cast<int32_t>(std::min(std::max(strtoul(arg[1].data(), nullptr, 10), 1UL), 65535UL));
m_p2pExternalPort = static_cast<int32_t>(std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 1UL), 65535UL));
ok = true;
}
@@ -301,7 +301,7 @@ Params::Params(const std::vector<std::vector<std::string_view>>& args)
}
if (!ok) {
fprintf(stderr, "Unknown or invalid command line parameter \"%s\"\n\n", arg[0].data());
fprintf(stderr, "Unknown or invalid command line parameter \"%s\"\n\n", arg[0].c_str());
p2pool_usage();
throw std::exception();
}
+1 -1
View File
@@ -29,7 +29,7 @@ struct Params
FORCEINLINE Params() {}
#endif
Params(const std::vector<std::vector<std::string_view>>& args);
explicit Params(const std::vector<std::vector<std::string>>& args);
bool valid() const;
+111
View File
@@ -27,6 +27,7 @@ extern "C" {
#include <map>
#include <istream>
#include <ostream>
#include <fstream>
#if !defined(_WIN32) && defined(HAVE_SCHED)
#include <sched.h>
@@ -1033,4 +1034,114 @@ hash from_onion_v3(const std::string& address)
return result;
}
std::vector<std::vector<std::string>> parse_config(const std::string& file_name)
{
std::ifstream f(file_name);
if (!f.is_open() || !f.good()) {
throw std::exception();
}
std::vector<std::vector<std::string>> args;
auto is_alpha = [](char c) { return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); };
auto is_num = [](char c) { return ('0' <= c && c <= '9'); };
std::string s;
while (std::getline(f, s).good()) {
if (s.empty()) {
continue;
}
bool quoted = false;
enum {
BEFORE_NAME,
COMMENT,
NAME,
AFTER_NAME,
VALUE,
VALUE_ESCAPE_CHAR,
} state = BEFORE_NAME;
for (const char c : s) {
switch (state) {
case BEFORE_NAME:
if (is_alpha(c)) {
state = NAME;
args.emplace_back(std::vector<std::string>(1, std::string(1, c)));
}
else if (c == '#') {
state = COMMENT;
}
break;
case COMMENT:
break;
case NAME:
if (is_alpha(c) || is_num(c) || (c == '-')) {
args.back()[0] += c;
}
else if (c == '#') {
state = COMMENT;
}
else {
state = AFTER_NAME;
}
break;
case AFTER_NAME:
if (c == '#') {
state = COMMENT;
}
else if ((c != '\t') && (c != ' ') && (c != '=')) {
state = VALUE;
quoted = (c == '"');
if (quoted) {
args.back().emplace_back(std::string());
}
else {
args.back().emplace_back(std::string(1, c));
}
}
break;
case VALUE:
if (quoted) {
if (c == '"') {
state = AFTER_NAME;
}
else if (c == '\\') {
state = VALUE_ESCAPE_CHAR;
}
else {
args.back().back() += c;
}
}
else {
if (c == ' ') {
state = AFTER_NAME;
}
else if (c == '#') {
state = COMMENT;
}
else {
args.back().back() += c;
}
}
break;
case VALUE_ESCAPE_CHAR:
args.back().back() += c;
state = VALUE;
break;
}
}
}
return args;
}
} // namespace p2pool
+2
View File
@@ -441,6 +441,8 @@ static FORCEINLINE constexpr hash from_onion_v3_const(const char* address)
return result;
}
std::vector<std::vector<std::string>> parse_config(const std::string& file_name);
} // namespace p2pool
void memory_tracking_start();