Add an opt-in "Host a mining pool (stratum)" toggle so a v1.3.0+ node can run its native RandomX stratum server for other miners to point at. Settings toggle + optional allow-IP/CIDR; passes -stratum (+ -stratumallowip) to the daemon launch args, mirroring the -maxconnections plumbing (EmbeddedDaemon::setStratumHosting <- DaemonController::syncSettings <- Settings). Backwards compatible / safe by default: - UI gated on daemon_version >= 1030000, so it's never offered where it would do nothing. - The launch flag is harmless on older daemons (they ignore unknown args), and the toggle can only be enabled while connected to a v1.3.0+ node anyway. - Blank allow-IP => the daemon serves loopback only (its safe default); entering a subnet opens it to that LAN, with an explicit exposure warning in the UI. - Takes effect on the next daemon start/restart. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
162 lines
4.4 KiB
C++
162 lines
4.4 KiB
C++
#include "daemon_controller.h"
|
|
#include "../config/settings.h"
|
|
#include "../util/platform.h"
|
|
|
|
#include <algorithm>
|
|
#include <filesystem>
|
|
#include <system_error>
|
|
|
|
namespace dragonx {
|
|
namespace daemon {
|
|
|
|
DaemonController::DaemonController()
|
|
: daemon_(std::make_unique<EmbeddedDaemon>())
|
|
{
|
|
}
|
|
|
|
DaemonController::~DaemonController() = default;
|
|
|
|
void DaemonController::setStateCallback(StateCallback callback)
|
|
{
|
|
daemon_->setStateCallback(std::move(callback));
|
|
}
|
|
|
|
void DaemonController::syncSettings(const config::Settings* settings)
|
|
{
|
|
if (!settings) return;
|
|
daemon_->setDebugCategories(settings->getDebugCategories());
|
|
daemon_->setMaxConnections(settings->getMaxConnections());
|
|
daemon_->setStratumHosting(settings->getStratumHost(), settings->getStratumAllowIp());
|
|
|
|
std::string walletFile = settings->getActiveWalletFile();
|
|
// The Wallets dialog opens an out-of-datadir wallet by linking it into the datadir under a
|
|
// "wallet-ip-<hash>.dat" name. If that link went dangling (the external file was moved / a USB was
|
|
// unplugged between sessions), don't let the daemon create a fresh EMPTY wallet at that name — fall
|
|
// back to the default this launch. fs::exists follows the link, so it's false for a dangling one.
|
|
if (walletFile.rfind("wallet-ip-", 0) == 0) {
|
|
std::error_code ec;
|
|
if (!std::filesystem::exists(util::Platform::getDragonXDataDir() + "/" + walletFile, ec))
|
|
walletFile = "wallet.dat";
|
|
}
|
|
daemon_->setWalletFile(walletFile);
|
|
}
|
|
|
|
bool DaemonController::start(const config::Settings* settings)
|
|
{
|
|
syncSettings(settings);
|
|
return daemon_->start();
|
|
}
|
|
|
|
void DaemonController::stop(int waitMs)
|
|
{
|
|
daemon_->stop(waitMs);
|
|
}
|
|
|
|
bool DaemonController::isRunning() const
|
|
{
|
|
return daemon_->isRunning();
|
|
}
|
|
|
|
bool DaemonController::externalDaemonDetected() const
|
|
{
|
|
return daemon_->externalDaemonDetected();
|
|
}
|
|
|
|
void DaemonController::clearExternalDaemonDetected()
|
|
{
|
|
daemon_->clearExternalDaemonDetected();
|
|
}
|
|
|
|
DaemonController::State DaemonController::state() const
|
|
{
|
|
return daemon_->getState();
|
|
}
|
|
|
|
std::string DaemonController::lastError() const
|
|
{
|
|
// By value — getLastError() now returns a mutex-locked COPY, so forwarding it by reference would
|
|
// dangle (bind a reference to that temporary). (M-04 follow-through)
|
|
return daemon_ ? daemon_->getLastError() : std::string();
|
|
}
|
|
|
|
int DaemonController::crashCount() const
|
|
{
|
|
return daemon_->getCrashCount();
|
|
}
|
|
|
|
int DaemonController::lastBlockHeight() const
|
|
{
|
|
return daemon_ ? daemon_->getLastBlockHeight() : 0;
|
|
}
|
|
|
|
double DaemonController::memoryUsageMB() const
|
|
{
|
|
return daemon_ ? daemon_->getMemoryUsageMB() : 0.0;
|
|
}
|
|
|
|
std::vector<std::string> DaemonController::recentLines(std::size_t count) const
|
|
{
|
|
return daemon_ ? daemon_->getRecentLines(count) : std::vector<std::string>{};
|
|
}
|
|
|
|
std::string DaemonController::outputSince(std::size_t& offset) const
|
|
{
|
|
return daemon_ ? daemon_->getOutputSince(offset) : std::string{};
|
|
}
|
|
|
|
void DaemonController::resetCrashCount()
|
|
{
|
|
daemon_->resetCrashCount();
|
|
}
|
|
|
|
void DaemonController::setRescanOnNextStart(bool enabled)
|
|
{
|
|
daemon_->setRescanOnNextStart(enabled);
|
|
}
|
|
|
|
bool DaemonController::rescanOnNextStart() const
|
|
{
|
|
return daemon_->rescanOnNextStart();
|
|
}
|
|
|
|
void DaemonController::setZapOnNextStart(bool enabled)
|
|
{
|
|
daemon_->setZapOnNextStart(enabled);
|
|
}
|
|
|
|
void DaemonController::setSalvageOnNextStart(bool enabled)
|
|
{
|
|
daemon_->setSalvageOnNextStart(enabled);
|
|
}
|
|
|
|
void DaemonController::setReindexOnNextStart(bool enabled)
|
|
{
|
|
daemon_->setReindexOnNextStart(enabled);
|
|
}
|
|
|
|
bool DaemonController::zapOnNextStart() const
|
|
{
|
|
return daemon_->zapOnNextStart();
|
|
}
|
|
|
|
void DaemonController::prepareLifecycleOperation(const LifecycleDecision& decision,
|
|
const config::Settings* settings)
|
|
{
|
|
if (settings) syncSettings(settings);
|
|
if (decision.resetCrashCount) resetCrashCount();
|
|
if (decision.setRescanOnNextStart) setRescanOnNextStart(true);
|
|
if (decision.setZapOnNextStart) setZapOnNextStart(true);
|
|
}
|
|
|
|
DaemonController::ShutdownDecision DaemonController::shutdownDecision(
|
|
bool keepDaemonRunning, bool stopExternalDaemon) const
|
|
{
|
|
return evaluateShutdownPolicy(static_cast<bool>(daemon_),
|
|
daemon_ && daemon_->externalDaemonDetected(),
|
|
keepDaemonRunning,
|
|
stopExternalDaemon);
|
|
}
|
|
|
|
} // namespace daemon
|
|
} // namespace dragonx
|