fix xmrig bundling issues

This commit is contained in:
dan_s
2026-03-11 21:14:03 -05:00
parent 06c80ef51c
commit 36b67e69d0
6 changed files with 86 additions and 12 deletions

View File

@@ -271,6 +271,9 @@ build_release_linux() {
[[ -f bin/asmap.dat ]] && cp bin/asmap.dat "$dist_dir/"
[[ -f bin/sapling-spend.params ]] && cp bin/sapling-spend.params "$dist_dir/"
[[ -f bin/sapling-output.params ]] && cp bin/sapling-output.params "$dist_dir/"
# Bundle xmrig for mining support
local XMRIG_LINUX="$SCRIPT_DIR/prebuilt-binaries/xmrig-hac/xmrig"
[[ -f "$XMRIG_LINUX" ]] && { cp "$XMRIG_LINUX" "$dist_dir/"; chmod +x "$dist_dir/xmrig"; info "Bundled xmrig"; } || warn "xmrig not found — mining unavailable in zip"
cp -r bin/res "$dist_dir/" 2>/dev/null || true
# ── Zip ──────────────────────────────────────────────────────────────────
@@ -294,9 +297,14 @@ build_release_linux() {
[[ -f bin/dragonxd ]] && cp bin/dragonxd "$APPDIR/usr/bin/"
[[ -f bin/dragonx-cli ]] && cp bin/dragonx-cli "$APPDIR/usr/bin/"
[[ -f bin/asmap.dat ]] && cp bin/asmap.dat "$APPDIR/usr/share/ObsidianDragon/"
[[ -f bin/sapling-spend.params ]] && cp bin/sapling-spend.params "$APPDIR/usr/share/ObsidianDragon/"
[[ -f bin/sapling-output.params ]] && cp bin/sapling-output.params "$APPDIR/usr/share/ObsidianDragon/"
# Daemon data files must be alongside the daemon binary (usr/bin/)
# because dragonxd searches relative to its own directory.
[[ -f bin/asmap.dat ]] && cp bin/asmap.dat "$APPDIR/usr/bin/"
[[ -f bin/sapling-spend.params ]] && cp bin/sapling-spend.params "$APPDIR/usr/bin/"
[[ -f bin/sapling-output.params ]] && cp bin/sapling-output.params "$APPDIR/usr/bin/"
# Bundle xmrig for mining support
local XMRIG_LINUX_AI="$SCRIPT_DIR/prebuilt-binaries/xmrig-hac/xmrig"
[[ -f "$XMRIG_LINUX_AI" ]] && { cp "$XMRIG_LINUX_AI" "$APPDIR/usr/bin/"; chmod +x "$APPDIR/usr/bin/xmrig"; }
# Desktop entry
cat > "$APPDIR/usr/share/applications/ObsidianDragon.desktop" <<'DESK'
@@ -602,6 +610,13 @@ HDR
[[ -f "$DD/$f" ]] && cp "$DD/$f" "$dist_dir/"
done
# Bundle Sapling params + asmap for the zip distribution
# (The single-file exe has these embedded via INCBIN, but the zip
# needs them on disk so the daemon can find them in its work dir.)
for f in sapling-spend.params sapling-output.params asmap.dat; do
[[ -f "$DD/$f" ]] && cp "$DD/$f" "$dist_dir/"
done
cp -r bin/res "$dist_dir/" 2>/dev/null || true
# ── Single-file exe (all resources embedded) ────────────────────────────

View File

@@ -627,8 +627,13 @@ XMRIG_SRC="$PROJECT_DIR/external/xmrig-hac"
XMRIG_PREBUILT="$PROJECT_DIR/prebuilt-binaries/xmrig-hac"
# Clean previous prebuilt xmrig binaries so we always rebuild
# Only clean the binary for the platform(s) we are actually building,
# otherwise a plain ./setup.sh deletes xmrig.exe without rebuilding it.
if ! $CHECK_ONLY; then
rm -f "$XMRIG_PREBUILT/xmrig" "$XMRIG_PREBUILT/xmrig.exe" 2>/dev/null || true
rm -f "$XMRIG_PREBUILT/xmrig" 2>/dev/null || true
if $SETUP_WIN; then
rm -f "$XMRIG_PREBUILT/xmrig.exe" 2>/dev/null || true
fi
fi
# Helper: clone xmrig-hac if not present

View File

@@ -1855,10 +1855,34 @@ bool App::startEmbeddedDaemon()
}
DEBUG_LOGF("Sapling params extracted successfully\n");
} else {
daemon_status_ = "Sapling parameters not found. They should be in: " + rpc::Connection::getSaplingParamsDir();
DEBUG_LOGF("Sapling params not found and no embedded resources available!\n");
DEBUG_LOGF("Expected location: %s\n", rpc::Connection::getSaplingParamsDir().c_str());
return false;
// Fallback: check for params bundled alongside the executable
// (zip distributions bundle sapling-*.params next to the binary)
namespace fs = std::filesystem;
std::string exe_dir = util::Platform::getExecutableDirectory();
std::string daemon_dir = resources::getDaemonDirectory();
const char* paramFiles[] = { "sapling-spend.params", "sapling-output.params", "asmap.dat" };
bool copied = false;
if (!exe_dir.empty()) {
std::error_code ec;
fs::create_directories(daemon_dir, ec);
for (const char* name : paramFiles) {
fs::path src = fs::path(exe_dir) / name;
fs::path dst = fs::path(daemon_dir) / name;
if (fs::exists(src) && !fs::exists(dst)) {
DEBUG_LOGF("Copying bundled %s from exe dir to %s\n", name, daemon_dir.c_str());
fs::copy_file(src, dst, ec);
if (!ec) copied = true;
}
}
}
if (copied && rpc::Connection::verifySaplingParams()) {
DEBUG_LOGF("Sapling params copied from exe directory successfully\n");
} else {
daemon_status_ = "Sapling parameters not found. They should be in: " + rpc::Connection::getSaplingParamsDir();
DEBUG_LOGF("Sapling params not found and no embedded resources available!\n");
DEBUG_LOGF("Expected location: %s\n", rpc::Connection::getSaplingParamsDir().c_str());
return false;
}
}
}

View File

@@ -466,6 +466,18 @@ bool XmrigManager::startProcess(const std::string& xmrigPath, const std::string&
dup2(pipefd[1], STDERR_FILENO);
close(pipefd[1]);
// Detach from controlling terminal's stdin to prevent SIGTTIN/SIGTTOU
// when running in a new process group (setpgid below).
int devnull = open("/dev/null", O_RDONLY);
if (devnull >= 0) {
dup2(devnull, STDIN_FILENO);
close(devnull);
}
// Ignore job-control signals that a background process group may receive
signal(SIGTTIN, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
// New process group so we can kill the whole group
setpgid(0, 0);

View File

@@ -509,6 +509,18 @@ std::string getXmrigPath()
return xmrigName;
}
// Check alongside the wallet executable (zip / AppImage distributions)
{
std::string exeDir = util::Platform::getExecutableDirectory();
if (!exeDir.empty()) {
std::string exeDirPath = exeDir + "/" + xmrigName;
if (std::filesystem::exists(exeDirPath)) {
DEBUG_LOGF("[INFO] getXmrigPath: found alongside wallet at %s\n", exeDirPath.c_str());
return exeDirPath;
}
}
}
// Check development paths
#ifdef _WIN32
// Not applicable for cross-compiled Windows builds

View File

@@ -153,10 +153,15 @@ void RenderMiningTab(App* app)
s_pool_mode = app->settings()->getPoolMode();
strncpy(s_pool_url, app->settings()->getPoolUrl().c_str(), sizeof(s_pool_url) - 1);
strncpy(s_pool_worker, app->settings()->getPoolWorker().c_str(), sizeof(s_pool_worker) - 1);
// If pool worker is empty or placeholder, default to user's first address
s_pool_state_loaded = true;
}
// Default pool worker to user's first shielded address once addresses are available
{
static bool s_pool_worker_defaulted = false;
std::string workerStr(s_pool_worker);
if (workerStr.empty() || workerStr == "x") {
if (!s_pool_worker_defaulted && !state.addresses.empty() &&
(workerStr.empty() || workerStr == "x")) {
std::string defaultAddr;
for (const auto& addr : state.addresses) {
if (addr.type == "shielded" && !addr.address.empty()) {
@@ -175,9 +180,10 @@ void RenderMiningTab(App* app)
if (!defaultAddr.empty()) {
strncpy(s_pool_worker, defaultAddr.c_str(), sizeof(s_pool_worker) - 1);
s_pool_worker[sizeof(s_pool_worker) - 1] = '\0';
s_pool_settings_dirty = true;
}
s_pool_worker_defaulted = true;
}
s_pool_state_loaded = true;
}
// Persist pool settings when dirty and no field is active