diff --git a/src/resources/embedded_resources.cpp b/src/resources/embedded_resources.cpp index 3b88f63..87ea337 100644 --- a/src/resources/embedded_resources.cpp +++ b/src/resources/embedded_resources.cpp @@ -243,15 +243,15 @@ std::mutex& provisionMutex() { static std::mutex m; return m; } struct ProvisionEntry { const char* name; - bool refreshOnSizeMismatch; // re-extract when the bundled size differs (params, asmap, xmrig) + bool refreshOnSizeMismatch; // re-extract when the bundled size differs (params, asmap) bool executable; bool fullNodeOnly; // not written by Lite builds (the lite backend bakes in its own params) bool startupTrigger; // makes needsParamsExtraction() true }; -// The same files and rules as the old hand-written extraction: params/asmap/xmrig follow the bundled size; -// the node binaries and the rebuild helper are placed only when MISSING (the user may run a specific dragonxd; -// replacing it is the explicit Settings action). asmap/cli/tx/rebuild are written along, never a trigger. +// Params and asmap follow the bundled size; the node binaries, the rebuild helper and the miner are placed only +// when MISSING (user-updatable via the updaters: the user may run a specific dragonxd or an "Update miner..." +// build; replacing the node is the explicit Settings action). asmap/cli/tx/rebuild are written along, never a trigger. const ProvisionEntry kProvisionEntries[] = { { RESOURCE_SAPLING_SPEND, true, false, true, true }, { RESOURCE_SAPLING_OUTPUT, true, false, true, true }, @@ -262,7 +262,7 @@ const ProvisionEntry kProvisionEntries[] = { { RESOURCE_DRAGONX_TX, false, true, true, false }, #endif #ifdef HAS_EMBEDDED_XMRIG - { RESOURCE_XMRIG, true, true, false, true }, + { RESOURCE_XMRIG, kXmrigRefreshOnSizeMismatch, true, false, true }, #endif #ifdef HAS_EMBEDDED_WALLET_REBUILD { RESOURCE_DRAGONX_WALLET_REBUILD, false, true, true, false }, @@ -790,22 +790,6 @@ std::string getDaemonPath() return ""; } -bool needsXmrigExtraction() -{ -#ifdef HAS_EMBEDDED_XMRIG - std::string daemonDir = getDaemonDirectory(); -#ifdef _WIN32 - std::string xmrigPath = daemonDir + "\\xmrig.exe"; -#else - std::string xmrigPath = daemonDir + "/xmrig"; -#endif - const auto* res = getEmbeddedResource(RESOURCE_XMRIG); - return resourceNeedsUpdate(res, xmrigPath); -#else - return false; -#endif -} - bool hasXmrigAvailable() { #ifdef HAS_EMBEDDED_XMRIG diff --git a/src/resources/embedded_resources.h b/src/resources/embedded_resources.h index ab7bce5..c7d041b 100644 --- a/src/resources/embedded_resources.h +++ b/src/resources/embedded_resources.h @@ -41,6 +41,9 @@ bool extractEmbeddedResources(ProvisionProgress* progress = nullptr, const Cance // Does `destPath` need (re)writing? Missing -> yes. Present: only when `refreshOnSizeMismatch` and the size // differs. embeddedSize == 0 -> never. (Pure apart from the stat; exposed for tests.) bool resourceNeedsWrite(std::uint64_t embeddedSize, bool refreshOnSizeMismatch, const std::string& destPath); +// The bundled miner is placed only when MISSING: a present xmrig is never replaced by the bundled copy, even when +// its size differs, so an "Update miner..." install survives a wallet restart or upgrade. +inline constexpr bool kXmrigRefreshOnSizeMismatch = false; // the in-app updater owns the miner once placed // Write `data` to `destPath` via `destPath + kPartialFileSuffix`, flush it to disk, then move it into place // (POSIX rename; Windows MoveFileEx with retry and move-aside of a running .exe to ".old"). POSIX: chmod 0755 // first when `executable`. Returns false (temp removed, original kept) on any failure or on cancel. @@ -152,9 +155,6 @@ bool hasDaemonAvailable(); // Get daemon executable path (extracts if needed) std::string getDaemonPath(); -// Check if xmrig needs to be extracted -bool needsXmrigExtraction(); - // Check if xmrig is available (embedded or in app directory) bool hasXmrigAvailable(); diff --git a/tests/test_phase4.cpp b/tests/test_phase4.cpp index 20e89f8..2d8588d 100644 --- a/tests/test_phase4.cpp +++ b/tests/test_phase4.cpp @@ -3559,6 +3559,22 @@ void testResourceNeedsWrite() removeTree(dir); } +// C120: the bundled miner is placed only when missing, so an "Update miner..." install of a different size is +// never overwritten by the bundled copy on the next start. +void testXmrigProvisionPolicy() +{ + using dragonx::resources::kXmrigRefreshOnSizeMismatch; + using dragonx::resources::resourceNeedsWrite; + EXPECT_TRUE(!kXmrigRefreshOnSizeMismatch); + const fs::path dir = makeTempDir(); + const std::string f = (dir / "xmrig.exe").string(); + const std::string missing = (dir / "missing-xmrig.exe").string(); + { std::ofstream(f, std::ios::binary) << "12345"; } + EXPECT_TRUE(!resourceNeedsWrite(10, kXmrigRefreshOnSizeMismatch, f)); // present, different size: kept + EXPECT_TRUE(resourceNeedsWrite(10, kXmrigRefreshOnSizeMismatch, missing)); // missing: placed + removeTree(dir); +} + // ── C222: bootstrap preflight (util/bootstrap.h) ── // Writes a zip with miniz. level 0 stores members uncompressed, so a test can corrupt member data in place. static bool writeBootstrapTestZip(const fs::path& zipPath, @@ -16982,6 +16998,7 @@ int main() testVerifySaplingParams(); testStartupProvisionState(); testResourceNeedsWrite(); + testXmrigProvisionPolicy(); testBootstrapSpaceSufficient(); testBootstrapPlanArchive(); #ifndef _WIN32