- Embed XMRig executable (baked into buildbot image)

- Refactored CMake related to Tor/XMRig
- Move executables to `src/assets/exec`
- Embedding executables require passing definition to CMake, e.g:
  - `-DTOR=/path/to/tor`
  - `-DXMRIG=/path/to/xmrig`
- Allow solo mining for XMRig
- Redesign XMRig settings screen
master
dsc 4 years ago
parent 5d8700370b
commit aee60f33b7
Signed by untrusted user: dsc
GPG Key ID: 521F1E7991AA42DC

@ -14,11 +14,9 @@ steps:
commands: commands:
- git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/ - git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/
- git config --global url."http://gitea:3000/".insteadOf https://github.com/ - git config --global url."http://gitea:3000/".insteadOf https://github.com/
- git submodule update --init --depth 50 contrib/tor
- git submodule update --init --depth 50 contrib/torsocks
- git submodule update --init --depth 120 monero - git submodule update --init --depth 120 monero
- git submodule update --init --depth 120 --recursive monero - git submodule update --init --depth 120 --recursive monero
- make -j8 release-static - TOR="/usr/local/tor/bin/tor" XMRIG="/xmrig/xmrig" make -j6 release-static
environment: environment:
OPENSSL_ROOT_DIR: /usr/local/openssl/ OPENSSL_ROOT_DIR: /usr/local/openssl/
CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off
@ -44,7 +42,7 @@ volumes:
path: /var/drone/ccache_linux_release/ path: /var/drone/ccache_linux_release/
- name: files_linux_release - name: files_linux_release
host: host:
path: /mnt/storage1/feather_files/files/linux-release/ path: /build/feather_files/files/linux-release/
--- ---
@ -75,7 +73,7 @@ steps:
volumes: volumes:
- name: files_linux_appimage - name: files_linux_appimage
host: host:
path: /mnt/storage1/feather_files/files/linux-release-appimage/ path: /build/feather_files/files/linux-release-appimage/
--- ---
@ -94,11 +92,9 @@ steps:
commands: commands:
- git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/ - git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/
- git config --global url."http://gitea:3000/".insteadOf https://github.com/ - git config --global url."http://gitea:3000/".insteadOf https://github.com/
- git submodule update --init --depth 50 contrib/tor
- git submodule update --init --depth 50 contrib/torsocks
- git submodule update --init --depth 120 monero - git submodule update --init --depth 120 monero
- git submodule update --init --depth 120 --recursive monero - git submodule update --init --depth 120 --recursive monero
- PATH=/mxe/usr/bin/:$PATH make -j8 windows-mxe-release - PATH="/mxe/usr/bin/:$PATH" TOR="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" XMRIG="/xmrig/xmrig.exe" make -j6 windows-mxe-release
environment: environment:
CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off
- name: deploy - name: deploy
@ -122,7 +118,7 @@ volumes:
path: /var/drone/ccache_win_release/ path: /var/drone/ccache_win_release/
- name: files_win_release - name: files_win_release
host: host:
path: /mnt/storage1/feather_files/files/windows-mxe-release/ path: /build/feather_files/files/windows-mxe-release/
--- ---
@ -157,9 +153,9 @@ steps:
volumes: volumes:
- name: files_mac_release - name: files_mac_release
host: host:
path: /mnt/storage1/feather_files/files/mac-release/ path: /build/feather_files/files/mac-release/
--- ---
kind: signature kind: signature
hmac: 91e773a27d27f29ea62f5df500664b733df641b7c31202c8e5558174fd046fba hmac: 527d334190a8a824b3b781a05ae4c7d87f4fa2bc37ebc53a96db91f925fa4a52
... ...

@ -35,7 +35,7 @@ Note: You only need to build the base image once.
#### 3. Build #### 3. Build
```bash ```bash
docker run --rm -it -v /tmp/ccache:/root/.ccache -v /root/feather:/feather -w /feather feather:win /bin/bash -c 'PATH=/mxe/usr/bin/:$PATH make windows-mxe-release -j8' docker run --rm -it -v /tmp/ccache:/root/.ccache -v /root/feather:/feather -w /feather feather:win /bin/bash -c 'PATH="/mxe/usr/bin/:$PATH" TOR="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" XMRIG="/xmrig/xmrig.exe" make windows-mxe-release -j8'
``` ```
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally. Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
@ -68,7 +68,7 @@ Note: You only need to build the base image once.
#### 3. Build #### 3. Build
```bash ```bash
docker run --env OPENSSL_ROOT_DIR=/usr/local/openssl/ --rm -it -v /tmp/ccache:/root/.ccache -v PATH_TO_FEATHER:/feather -w /feather feather:linux sh -c 'make release-static -j8' docker run --env OPENSSL_ROOT_DIR=/usr/local/openssl/ --rm -it -v /tmp/ccache:/root/.ccache -v PATH_TO_FEATHER:/feather -w /feather feather:linux sh -c 'TOR="/usr/local/tor/bin/tor" XMRIG="/xmrig/xmrig" make release-static -j8'
``` ```
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally. Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
@ -98,4 +98,4 @@ Build Feather.
CMAKE_PREFIX_PATH=~/Qt5.15.1/5.15.1/clang_64 make mac-release CMAKE_PREFIX_PATH=~/Qt5.15.1/5.15.1/clang_64 make mac-release
``` ```
The resulting Mac OS application can be found `build/bin/feather.app`. The resulting Mac OS application can be found `build/bin/feather.app` and will **not** have Tor embedded.

@ -11,8 +11,9 @@ set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
option(FETCH_DEPS "Download dependencies if they are not found" ON) option(FETCH_DEPS "Download dependencies if they are not found" ON)
option(XMRTO "Include Xmr.To module" ON) option(XMRTO "Include Xmr.To module" ON)
option(XMRig "Include XMRig module" ON) option(XMRIG "Path to XMRig binary to embed inside Feather" OFF)
option(BUILD_TOR "Build Tor" OFF) option(TOR "Path to Tor binary to embed inside Feather" OFF)
option(TOR_VERSION "Optional git hash or tag of embedded Tor version" "tor-0.4.3.5")
option(STATIC "Link libraries statically, requires static Qt") option(STATIC "Link libraries statically, requires static Qt")
option(USE_DEVICE_TREZOR "Trezor support compilation" OFF) option(USE_DEVICE_TREZOR "Trezor support compilation" OFF)
option(DONATE_BEG "Prompt donation window every once in a while" ON) option(DONATE_BEG "Prompt donation window every once in a while" ON)
@ -175,47 +176,48 @@ if(UNIX AND NOT APPLE)
endif() endif()
endif() endif()
# Tor/torsocks if("$ENV{DRONE}" STREQUAL "true")
set(TOR_TAG "tor-0.4.3.5") message(STATUS "We are inside a static compile with Drone CI")
set(TOR_DIR "${CMAKE_SOURCE_DIR}/contrib/tor") endif()
if(BUILD_TOR AND APPLE) # To build Feather with embedded (and static) Tor, pass CMake -DTOR=/path/to/tor
execute_process(COMMAND bash -c "touch ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib") if(TOR)
ENDIF() if(APPLE)
execute_process(COMMAND bash -c "touch ${CMAKE_CURRENT_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
endif()
if(UNIX AND NOT APPLE) # on the buildbot Tor is baked into the image
set(TOR_LIB "libtorsocks.so") # - linux: See `Dockerfile`
elseif(APPLE) # - windows: https://github.com/mxe/mxe/blob/1024dc7d2db5eb7d5d3c64a2c12b5f592572f1ce/plugins/apps/tor.mk
set(TOR_LIB "libtorsocks.dylib") # - macos: taken from Tor Browser official release
set(TOR_COPY_CMD "cp ${TOR} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor")
message(STATUS "${TOR_COPY_CMD}")
execute_process(COMMAND bash -c "${TOR_COPY_CMD}" RESULT_VARIABLE ret)
if(ret EQUAL "1")
message(FATAL_ERROR "Tor copy failure: ${TOR_COPY_CMD}")
endif()
message(STATUS "Embedding Tor binary at ${TOR}")
else()
message(STATUS "Skipping Tor inclusion because -DTOR=Off")
endif() endif()
if("$ENV{DRONE}" STREQUAL "true" AND APPLE) # To build Feather with embedded (and static) XMRig, pass CMake -DXMRIG=/path/to/xmrig
message(STATUS "We are inside a static compile with Drone CI") if(XMRIG)
# @TODO: taken from Tor Browser official release for now # on the buildbot XMRig is baked into the image
execute_process(COMMAND bash -c "cp ~/tor/libevent-2.1.7.dylib ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib") # - linux: See `Dockerfile`
execute_process(COMMAND bash -c "cp ~/tor/tor ${CMAKE_SOURCE_DIR}/src/tor/tor") # - windows: See `Dockerfile_windows`
elseif("$ENV{DRONE}" STREQUAL "true" AND BUILD_TOR) # - macos: manually downloaded an official release
message(STATUS "We are inside a static compile with Drone CI") set(XMRIG_COPY_CMD "cp ${XMRIG} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/xmrig")
if(MINGW) message(STATUS "${XMRIG_COPY_CMD}")
execute_process(COMMAND bash -c "cp /mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe ${CMAKE_SOURCE_DIR}/src/tor/tor.exe") execute_process(COMMAND bash -c "${XMRIG_COPY_CMD}" RESULT_VARIABLE ret)
elseif(UNIX AND NOT APPLE) if(ret EQUAL "1")
execute_process(COMMAND bash -c "cp /usr/local/tor/bin/tor ${CMAKE_SOURCE_DIR}/src/tor/tor") message(FATAL_ERROR "XMRig copy failure: ${XMRIG_COPY_CMD}")
execute_process(COMMAND bash -c "cp /usr/local/torsocks/lib/torsocks/* ${CMAKE_SOURCE_DIR}/src/tor/")
endif() endif()
message(STATUS "Embedding XMRig binary at ${XMRIG}")
else() else()
if(BUILD_TOR) message(STATUS "Skipping XMRig inclusion because -DXMRIG=Off")
if(UNIX OR APPLE)
execute_process(COMMAND bash -c "ls -al src/tor/${TOR_LIB} 2>/dev/null" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE TOR_FOUND OUTPUT_STRIP_TRAILING_WHITESPACE)
if(TOR_FOUND)
message(STATUS "${TOR_LIB} found, skipping Tor build")
else()
message(STATUS "${TOR_LIB} not found, building Tor")
execute_process(COMMAND bash -c "bash build_tor.sh ${TOR_TAG} ${CMAKE_SOURCE_DIR} 'ON'" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/contrib)
endif()
endif()
else()
message(STATUS "Skipping Tor build because -DBUILD_TOR=OFF")
endif()
endif() endif()
if(MINGW) if(MINGW)

@ -305,3 +305,9 @@ RUN git clone https://git.wownero.com/feather/monero-seed.git && \
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \ cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
make -Cbuild -j$THREADS && \ make -Cbuild -j$THREADS && \
make -Cbuild install make -Cbuild install
RUN apt install -y curl && \
curl -LO "https://github.com/xmrig/xmrig/releases/download/v6.3.5/xmrig-6.3.5-linux-static-x64.tar.gz" && \
echo "24d4f07cf5850f00ab513b228f95769a5a5ed68d35808d98f9959b58d97985a0 xmrig-6.3.5-linux-static-x64.tar.gz" > hashsum.txt && \
sha256sum -c hashsum.txt && \
tar xvf xmrig-6.3.5-linux-static-x64.tar.gz --one-top-level=/xmrig --strip 1

@ -72,3 +72,10 @@ RUN git clone https://git.wownero.com/feather/monero-seed.git && \
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \ cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
make -Cbuild -j$THREADS && \ make -Cbuild -j$THREADS && \
make -Cbuild install make -Cbuild install
RUN apt install -y curl && \
curl -LO "https://github.com/xmrig/xmrig/releases/download/v6.3.5/xmrig-6.3.5-gcc-win64.zip" && \
echo "e45915ada7e6e30f6ab40abf33831056449d5914307d7706bb0ad439b6d64c12 xmrig-6.3.5-gcc-win64.zip" > hashsum.txt && \
sha256sum -c hashsum.txt && \
unzip -q xmrig-6.3.5-gcc-win64.zip -d /xmrig && \
mv /xmrig/xmrig-6.3.5/* /xmrig/

@ -42,7 +42,8 @@ via the `CMAKE_PREFIX_PATH` definition. For me this is:
There are some Monero/Feather related options/definitions that you may pass: There are some Monero/Feather related options/definitions that you may pass:
- `-DXMRTO=OFF` - disable Xmr.To feature - `-DXMRTO=OFF` - disable Xmr.To feature
- `-DBUILD_TOR=OFF` - disable embedded Tor - `-DTOR=/path/to/tor` - Embed a Tor executable inside Feather
- `-DXMRIG=/path/to/xmrig` - Embed a XMRig executable inside Feather
- `-DDONATE_BEG=OFF` - disable the dreaded donate requests - `-DDONATE_BEG=OFF` - disable the dreaded donate requests
And: And:

@ -31,6 +31,8 @@ CMAKEFLAGS = \
-DBUILD_64=On \ -DBUILD_64=On \
-DBUILD_TESTS=Off \ -DBUILD_TESTS=Off \
-DXMRTO=ON \ -DXMRTO=ON \
-DXMRIG=Off \
-DTOR=Off \
-DCMAKE_CXX_STANDARD=11 \ -DCMAKE_CXX_STANDARD=11 \
-DCMAKE_VERBOSE_MAKEFILE=On \ -DCMAKE_VERBOSE_MAKEFILE=On \
-DINSTALL_VENDORED_LIBUNBOUND=Off \ -DINSTALL_VENDORED_LIBUNBOUND=Off \
@ -40,29 +42,33 @@ CMAKEFLAGS = \
$(CMAKEFLAGS_EXTRA) $(CMAKEFLAGS_EXTRA)
release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64" release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64"
release-static: CMAKEFLAGS += -DBUILD_TOR=On release-static: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF)
release-static: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
release-static: release-static:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild $(MAKE) -Cbuild
windows-mxe-release: CMAKEFLAGS += -DBUILD_TAG="win-x64" windows-mxe-release: CMAKEFLAGS += -DBUILD_TAG="win-x64"
windows-mxe-release: CMAKEFLAGS += -DBUILD_TOR=On windows-mxe-release: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF)
windows-mxe-release: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
windows-mxe-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release windows-mxe-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
windows-mxe-release: windows-mxe-release:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild $(MAKE) -Cbuild
windows-mxe-debug: CMAKEFLAGS += -DBUILD_TAG="win-x64" windows-mxe-debug: CMAKEFLAGS += -DBUILD_TAG="win-x64"
windows-mxe-debug: CMAKEFLAGS += -DBUILD_TOR=Off windows-mxe-debug: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF)
windows-mxe-debug: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
windows-mxe-debug: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Debug windows-mxe-debug: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Debug
windows-mxe-debug: windows-mxe-debug:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild $(MAKE) -Cbuild
mac-release: CMAKEFLAGS += -DSTATIC=Off mac-release: CMAKEFLAGS += -DSTATIC=Off
mac-release: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF)
mac-release: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
mac-release: CMAKEFLAGS += -DBUILD_TAG="mac-x64" mac-release: CMAKEFLAGS += -DBUILD_TAG="mac-x64"
mac-release: CMAKEFLAGS += -DBUILD_TOR=Off
mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
mac-release: mac-release:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)

@ -42,14 +42,16 @@ file(GLOB SOURCE_FILES
"dialog/*.cpp" "dialog/*.cpp"
) )
if((APPLE AND BUILD_TOR) OR (APPLE AND "$ENV{DRONE}" STREQUAL "true")) if(TOR)
set(ASSETS_OS "assets_macos_tor.qrc") if(APPLE)
elseif(UNIX AND NOT APPLE AND BUILD_TOR) set(ASSETS_TOR "assets_tor_macos.qrc")
set(ASSETS_OS "assets_linux_tor.qrc") else()
elseif(MINGW AND BUILD_TOR) set(ASSETS_TOR "assets_tor.qrc")
set(ASSETS_OS "assets_windows_tor.qrc") endif()
else() endif()
message(STATUS "Building without embedded Tor")
if(XMRIG)
set(ASSETS_XMRIG "assets_mining.qrc")
endif() endif()
set(EXECUTABLE_FLAG) set(EXECUTABLE_FLAG)
@ -74,7 +76,8 @@ endif()
add_executable(feather ${EXECUTABLE_FLAG} main.cpp add_executable(feather ${EXECUTABLE_FLAG} main.cpp
${SOURCE_FILES} ${SOURCE_FILES}
${RESOURCES} ${RESOURCES}
${ASSETS_OS} ${ASSETS_TOR}
${ASSETS_XMRIG}
) )
# mac os bundle # mac os bundle
@ -122,16 +125,16 @@ if(DONATE_BEG)
target_compile_definitions(feather PRIVATE DONATE_BEG=1) target_compile_definitions(feather PRIVATE DONATE_BEG=1)
endif() endif()
if(BUILD_TOR)
target_compile_definitions(feather PRIVATE BUILD_TOR=1)
endif()
if(XMRTO) if(XMRTO)
target_compile_definitions(feather PRIVATE XMRTO=1) target_compile_definitions(feather PRIVATE XMRTO=1)
endif() endif()
if(XMRig) if(TOR)
target_compile_definitions(feather PRIVATE MINING=1) target_compile_definitions(feather PRIVATE HAS_TOR=1)
endif()
if(XMRIG)
target_compile_definitions(feather PRIVATE HAS_XMRIG=1)
endif() endif()
if(HAVE_SYS_PRCTL_H) if(HAVE_SYS_PRCTL_H)

@ -147,10 +147,17 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
AppContext::prices = new Prices(); AppContext::prices = new Prices();
// xmr.to // xmr.to
#if defined(XMRTO) #ifdef XMRTO
this->XMRTo = new XmrTo(this); this->XMRTo = new XmrTo(this);
#endif #endif
// XMRig
#ifdef HAS_XMRIG
this->XMRig = new XmRig(this->configDirectory, this);
if(!this->isTails)
this->XMRig->prepare();
#endif
this->walletManager = WalletManager::instance(); this->walletManager = WalletManager::instance();
QString logPath = QString("%1/daemon.log").arg(configDirectory); QString logPath = QString("%1/daemon.log").arg(configDirectory);
Monero::Utils::onStartup(); Monero::Utils::onStartup();
@ -393,7 +400,7 @@ void AppContext::onWSMessage(const QJsonObject &msg) {
else if(cmd == "nodes") { else if(cmd == "nodes") {
this->onWSNodes(msg.value("data").toArray()); this->onWSNodes(msg.value("data").toArray());
} }
#if defined(MINING) #if defined(HAS_XMRIG)
else if(cmd == "xmrig") { else if(cmd == "xmrig") {
this->XMRigDownloads(msg.value("data").toObject()); this->XMRigDownloads(msg.value("data").toObject());
} }
@ -511,31 +518,17 @@ void AppContext::onWSCCS(const QJsonArray &ccs_data) {
} }
void AppContext::createConfigDirectory(const QString &dir) { void AppContext::createConfigDirectory(const QString &dir) {
if(!Utils::dirExists(dir)) {
qDebug() << QString("Creating directory: %1").arg(dir);
if(!QDir().mkpath(dir))
throw std::runtime_error("Could not create directory " + dir.toStdString());
}
QString config_dir_tor = QString("%1%2").arg(dir).arg("tor"); QString config_dir_tor = QString("%1%2").arg(dir).arg("tor");
if(!Utils::dirExists(config_dir_tor)) {
qDebug() << QString("Creating directory: %1").arg(config_dir_tor);
if (!QDir().mkpath(config_dir_tor))
throw std::runtime_error("Could not create directory " + config_dir_tor.toStdString());
}
QString config_dir_tordata = QString("%1%2").arg(dir).arg("tor/data"); QString config_dir_tordata = QString("%1%2").arg(dir).arg("tor/data");
if(!Utils::dirExists(config_dir_tordata)) { QString config_dir_xmrig = QString("%1%2").arg(dir).arg("xmrig");
qDebug() << QString("Creating directory: %1").arg(config_dir_tordata);
if (!QDir().mkpath(config_dir_tordata)) QStringList createDirs({dir, config_dir_tor, config_dir_tordata, config_dir_xmrig});
throw std::runtime_error("Could not create directory " + config_dir_tordata.toStdString()); for(const auto &d: createDirs) {
} if(!Utils::dirExists(d)) {
qDebug() << QString("Creating directory: %1").arg(d);
QString config_dir_torsocks = QString("%1%2").arg(dir).arg("torsocks"); if (!QDir().mkpath(d))
if(!Utils::dirExists(config_dir_torsocks)) { throw std::runtime_error("Could not create directory " + d.toStdString());
qDebug() << QString("Creating directory: %1").arg(config_dir_torsocks); }
if (!QDir().mkpath(config_dir_torsocks))
throw std::runtime_error("Could not create directory " + config_dir_torsocks.toStdString());
} }
} }

@ -14,6 +14,7 @@
#include "utils/networking.h" #include "utils/networking.h"
#include "utils/tor.h" #include "utils/tor.h"
#include "utils/xmrto.h" #include "utils/xmrto.h"
#include "utils/xmrig.h"
#include "utils/wsclient.h" #include "utils/wsclient.h"
#include "utils/txfiathistory.h" #include "utils/txfiathistory.h"
#include "widgets/RedditPost.h" #include "widgets/RedditPost.h"
@ -78,6 +79,7 @@ public:
Tor *tor; Tor *tor;
WSClient *ws; WSClient *ws;
XmrTo *XMRTo; XmrTo *XMRTo;
XmRig *XMRig;
Nodes *nodes; Nodes *nodes;
static Prices *prices; static Prices *prices;
static WalletKeysFilesModel *wallets; static WalletKeysFilesModel *wallets;

@ -1,6 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>tor/tor</file>
<file>tor/libevent-2.1.7.dylib</file>
</qresource>
</RCC>

@ -1,5 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0"> <!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/"> <qresource prefix="/">
<file>tor/tor.exe</file> <file>assets/exec/xmrig</file>
</qresource> </qresource>
</RCC> </RCC>

@ -1,5 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0"> <!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/"> <qresource prefix="/">
<file>tor/tor</file> <file>assets/exec/tor</file>
</qresource> </qresource>
</RCC> </RCC>

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>assets/exec/tor</file>
<file>assets/exec/libevent-2.1.7.dylib</file>
</qresource>
</RCC>

@ -22,12 +22,14 @@ int main(int argc, char *argv[])
{ {
Q_INIT_RESOURCE(assets); Q_INIT_RESOURCE(assets);
#if defined(Q_OS_MAC) && defined(BUILD_TOR) #if defined(Q_OS_MAC) && defined(HAS_TOR)
Q_INIT_RESOURCE(assets_macos_tor); Q_INIT_RESOURCE(assets_tor_macos);
#elif defined(Q_OS_LINUX) && defined(BUILD_TOR) #elif defined(HAS_TOR)
Q_INIT_RESOURCE(assets_linux_tor); Q_INIT_RESOURCE(assets_tor);
#elif defined(Q_OS_WIN) && defined(BUILD_TOR) #endif
Q_INIT_RESOURCE(assets_windows_tor);
#if defined(HAS_XMRIG)
Q_INIT_RESOURCE(assets_mining);
#endif #endif
QStringList argv_; QStringList argv_;

@ -167,13 +167,20 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
connect(m_ctx->nodes, &Nodes::WSNodeExhausted, this, &MainWindow::showWSNodeExhaustedMessage); connect(m_ctx->nodes, &Nodes::WSNodeExhausted, this, &MainWindow::showWSNodeExhaustedMessage);
// XMRig // XMRig
#ifdef HAS_XMRIG
m_xmrig = new XMRigWidget(m_ctx, this); m_xmrig = new XMRigWidget(m_ctx, this);
ui->xmrRigLayout->addWidget(m_xmrig); ui->xmrRigLayout->addWidget(m_xmrig);
connect(m_ctx->XMRig, &XmRig::output, m_xmrig, &XMRigWidget::onProcessOutput);
connect(m_ctx->XMRig, &XmRig::error, m_xmrig, &XMRigWidget::onProcessError);
connect(m_ctx->XMRig, &XmRig::hashrate, m_xmrig, &XMRigWidget::onHashrate);
connect(m_ctx, &AppContext::walletClosed, m_xmrig, &XMRigWidget::onWalletClosed);
connect(m_ctx, &AppContext::walletOpened, m_xmrig, &XMRigWidget::onWalletOpened); connect(m_ctx, &AppContext::walletOpened, m_xmrig, &XMRigWidget::onWalletOpened);
connect(m_ctx, &AppContext::XMRigDownloads, m_xmrig, &XMRigWidget::onDownloads); connect(m_ctx, &AppContext::XMRigDownloads, m_xmrig, &XMRigWidget::onDownloads);
connect(m_ctx, &AppContext::walletClosed, m_xmrig, &XMRigWidget::onWalletClosed);
connect(m_xmrig, &XMRigWidget::miningStarted, [=]{ m_ctx->setWindowTitle(true); }); connect(m_xmrig, &XMRigWidget::miningStarted, [=]{ m_ctx->setWindowTitle(true); });
connect(m_xmrig, &XMRigWidget::miningEnded, [=]{ m_ctx->setWindowTitle(false); }); connect(m_xmrig, &XMRigWidget::miningEnded, [=]{ m_ctx->setWindowTitle(false); });
#endif
// CCS/Reddit widget // CCS/Reddit widget
m_ccsWidget = new CCSWidget(this); m_ccsWidget = new CCSWidget(this);
@ -388,7 +395,7 @@ void MainWindow::initMenu() {
ui->actionShow_xmr_to->setVisible(false); ui->actionShow_xmr_to->setVisible(false);
#endif #endif
#if defined(MINING) #if defined(HAS_XMRIG)
connect(ui->actionShow_XMRig, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->actionShow_XMRig, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
m_tabShowHideMapper["XMRig"] = new ToggleTab(ui->tabXmrRig, "XMRig", "XMRig", ui->actionShow_XMRig, Config::showTabXMRig); m_tabShowHideMapper["XMRig"] = new ToggleTab(ui->tabXmrRig, "XMRig", "XMRig", ui->actionShow_XMRig, Config::showTabXMRig);
m_tabShowHideSignalMapper->setMapping(ui->actionShow_XMRig, "XMRig"); m_tabShowHideSignalMapper->setMapping(ui->actionShow_XMRig, "XMRig");

@ -43,9 +43,15 @@ Tor::Tor(AppContext *ctx, QObject *parent)
return; return;
} }
#ifndef HAS_TOR
qCritical() << "Feather built without embedded Tor. Assuming --use-local-tor";
this->localTor = true;
return;
#endif
bool unpacked = this->unpackBins(); bool unpacked = this->unpackBins();
if (!unpacked) { if (!unpacked) {
qCritical() << "Feather built without embedded Tor. Assuming --use-local-tor"; qCritical() << "Error unpacking embedded Tor. Assuming --use-local-tor";
this->localTor = true; this->localTor = true;
return; return;
} }
@ -175,11 +181,9 @@ void Tor::handleProcessError(QProcess::ProcessError error) {
bool Tor::unpackBins() { bool Tor::unpackBins() {
QString torFile; QString torFile;
// @TODO: refactor for Mac OS - should compile Tor statically. // On MacOS write libevent to disk
#if defined(Q_OS_MAC) && defined(DRONE) #if defined(Q_OS_MAC)
// Tor on Mac requires libevent.dylib, borrowed the executable from QString libEvent = ":/assets/exec/libevent-2.1.7.dylib";
// the official Tor Browser release for now.
QString libEvent = ":/tor/libevent-2.1.7.dylib";
if (Utils::fileExists(libEvent)) { if (Utils::fileExists(libEvent)) {
QFile e(libEvent); QFile e(libEvent);
QFileInfo eventInfo(e); QFileInfo eventInfo(e);
@ -190,18 +194,15 @@ bool Tor::unpackBins() {
} }
#endif #endif
#if defined(Q_OS_MAC) || defined(Q_OS_LINUX) torFile = ":/assets/exec/tor";
torFile = ":/tor/tor";
#elif defined(Q_OS_WIN)
torFile = ":/tor/tor.exe";
#endif
if (!Utils::fileExists(torFile)) if (!Utils::fileExists(torFile))
return false; return false;
// write to disk
QFile f(torFile); QFile f(torFile);
QFileInfo fileInfo(f); QFileInfo fileInfo(f);
this->torPath = QDir(this->torDir).filePath(fileInfo.fileName()); this->torPath = QDir(this->torDir).filePath(fileInfo.fileName());
qDebug() << this->torPath; qDebug() << "Writing Tor executable to " << this->torPath;
f.copy(torPath); f.copy(torPath);
f.close(); f.close();
@ -209,7 +210,6 @@ bool Tor::unpackBins() {
QFile torBin(this->torPath); QFile torBin(this->torPath);
torBin.setPermissions(QFile::ExeGroup | QFile::ExeOther | QFile::ExeOther | QFile::ExeUser); torBin.setPermissions(QFile::ExeGroup | QFile::ExeOther | QFile::ExeOther | QFile::ExeUser);
#endif #endif
return true; return true;
} }

@ -13,28 +13,37 @@
#include "appcontext.h" #include "appcontext.h"
XMRig::XMRig(QObject *parent) : QObject(parent) XmRig::XmRig(const QString &configDir, QObject *parent) : QObject(parent) {
{ this->rigDir = QDir(configDir).filePath("xmrig");
qDebug() << "Using embedded tor instance"; }
m_process.setProcessChannelMode(QProcess::MergedChannels);
void XmRig::prepare() {
// unpack and set process signals
if(!this->unpackBins()) {
qCritical() << "failed to write XMRig to config directory";
return;
}
connect(&m_process, &QProcess::readyReadStandardOutput, this, &XMRig::handleProcessOutput); m_process.setProcessChannelMode(QProcess::MergedChannels);
connect(&m_process, &QProcess::errorOccurred, this, &XMRig::handleProcessError); connect(&m_process, &QProcess::readyReadStandardOutput, this, &XmRig::handleProcessOutput);
connect(&m_process, &QProcess::stateChanged, this, &XMRig::stateChanged); connect(&m_process, &QProcess::errorOccurred, this, &XmRig::handleProcessError);
connect(&m_process, &QProcess::stateChanged, this, &XmRig::stateChanged);
} }
void XMRig::stop() { void XmRig::stop() {
if(m_process.state() == QProcess::Running) if(m_process.state() == QProcess::Running)
m_process.kill(); m_process.kill();
} }
void XMRig::terminate() { void XmRig::terminate() {
if(m_process.state() == QProcess::Running) if(m_process.state() == QProcess::Running)
m_process.terminate(); m_process.terminate();
} }
void XMRig::start(unsigned int threads, void XmRig::start(const QString &path,
const QString &pool_name, unsigned int threads,
const QString &address,
const QString &username, const QString &username,
const QString &password, const QString &password,
bool tor, bool tls) { bool tor, bool tls) {
@ -44,22 +53,22 @@ void XMRig::start(unsigned int threads,
return; return;
} }
auto path = config()->get(Config::xmrigPath).toString();
if(path.isEmpty()) { if(path.isEmpty()) {
emit error("Please set path to XMRig binary before starting."); emit error("XmRig->Start path parameter missing.");
return; return;
} }
if(!Utils::fileExists(path)) { if(!Utils::fileExists(path)) {
emit error("Path to XMRig binary invalid; file does not exist."); emit error(QString("Path to XMRig binary invalid; file does not exist: %1").arg(path));
return; return;
} }
QStringList arguments; QStringList arguments;
arguments << "-o" << pool_name; arguments << "-o" << address;
arguments << "-a" << "rx/0"; arguments << "-a" << "rx/0";
arguments << "-u" << username; arguments << "-u" << username;
arguments << "-p" << password; if(!password.isEmpty())
arguments << "-p" << password;
arguments << "--no-color"; arguments << "--no-color";
arguments << "-t" << QString::number(threads); arguments << "-t" << QString::number(threads);
if(tor) if(tor)
@ -72,14 +81,14 @@ void XMRig::start(unsigned int threads,
m_process.start(path, arguments); m_process.start(path, arguments);
} }
void XMRig::stateChanged(QProcess::ProcessState state) { void XmRig::stateChanged(QProcess::ProcessState state) {
if(state == QProcess::ProcessState::Running) if(state == QProcess::ProcessState::Running)
emit output("XMRig started"); emit output("XMRig started");
else if (state == QProcess::ProcessState::NotRunning) else if (state == QProcess::ProcessState::NotRunning)
emit output("XMRig stopped"); emit output("XMRig stopped");
} }
void XMRig::handleProcessOutput() { void XmRig::handleProcessOutput() {
QByteArray _output = m_process.readAllStandardOutput(); QByteArray _output = m_process.readAllStandardOutput();
if(_output.contains("miner") && _output.contains("speed")) { if(_output.contains("miner") && _output.contains("speed")) {
// detect hashrate // detect hashrate
@ -93,7 +102,7 @@ void XMRig::handleProcessOutput() {
emit output(_output); emit output(_output);
} }
void XMRig::handleProcessError(QProcess::ProcessError err) { void XmRig::handleProcessError(QProcess::ProcessError err) {
if (err == QProcess::ProcessError::Crashed) if (err == QProcess::ProcessError::Crashed)
emit error("XMRig crashed or killed"); emit error("XMRig crashed or killed");
else if (err == QProcess::ProcessError::FailedToStart) { else if (err == QProcess::ProcessError::FailedToStart) {
@ -102,3 +111,24 @@ void XMRig::handleProcessError(QProcess::ProcessError err) {
} }
} }
bool XmRig::unpackBins() {
QString rigFile;
rigFile = ":/assets/exec/xmrig";
if (!Utils::fileExists(rigFile))
return false;
// write to disk
QFile f(rigFile);
QFileInfo fileInfo(f);
this->rigPath = QDir(this->rigDir).filePath(fileInfo.fileName());
qDebug() << "Writing XMRig executable to " << this->rigPath;
f.copy(rigPath);
f.close();
#if defined(Q_OS_UNIX)
QFile torBin(this->rigPath);
torBin.setPermissions(QFile::ExeGroup | QFile::ExeOther | QFile::ExeOther | QFile::ExeUser);
#endif
return true;
}

@ -15,16 +15,21 @@
#include "utils/childproc.h" #include "utils/childproc.h"
class XMRig : public QObject class XmRig : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit XMRig(QObject *parent = nullptr); explicit XmRig(const QString &configDir, QObject *parent = nullptr);
void prepare();
void start(unsigned int threads, const QString &pool_name, const QString &username, const QString &password, bool tor = false, bool tls = true); void start(const QString &path, unsigned int threads, const QString &address, const QString &username, const QString &password, bool tor = false, bool tls = true);
void stop(); void stop();
void terminate(); void terminate();
bool unpackBins();
QString rigDir;
QString rigPath;
signals: signals:
void error(const QString &msg); void error(const QString &msg);

@ -33,12 +33,6 @@ XMRigWidget::XMRigWidget(AppContext *ctx, QWidget *parent) :
connect(ui->tableView, &QHeaderView::customContextMenuRequested, this, &XMRigWidget::showContextMenu); connect(ui->tableView, &QHeaderView::customContextMenuRequested, this, &XMRigWidget::showContextMenu);
connect(ui->tableView, &QTableView::doubleClicked, this, &XMRigWidget::linkClicked); connect(ui->tableView, &QTableView::doubleClicked, this, &XMRigWidget::linkClicked);
// XMRig core
m_rig = new XMRig(this);
connect(m_rig, &XMRig::output, this, &XMRigWidget::onProcessOutput);
connect(m_rig, &XMRig::error, this, &XMRigWidget::onProcessError);
connect(m_rig, &XMRig::hashrate, this, &XMRigWidget::onHashrate);
// threads // threads
ui->threadSlider->setMinimum(1); ui->threadSlider->setMinimum(1);
int threads = QThread::idealThreadCount(); int threads = QThread::idealThreadCount();
@ -60,19 +54,29 @@ XMRigWidget::XMRigWidget(AppContext *ctx, QWidget *parent) :
ui->relayTor->setChecked(false); ui->relayTor->setChecked(false);
ui->check_tls->setChecked(true); ui->check_tls->setChecked(true);
ui->label_status->setTextInteractionFlags(Qt::TextSelectableByMouse); ui->label_status->setTextInteractionFlags(Qt::TextSelectableByMouse);
ui->label_status->hide();
ui->pathFrame->hide();
ui->soloFrame->hide();
ui->poolFrame->hide();
// XMRig binary // XMRig binary
auto path = config()->get(Config::xmrigPath).toString(); auto path = config()->get(Config::xmrigPath).toString();
ui->lineEdit_path->setText(path); if(!path.isEmpty()) {
ui->label_status->hide(); ui->pathFrame->show();
if(path.isEmpty()) ui->check_custompath->setChecked(true);
ui->tabWidget->setCurrentIndex(1); ui->lineEdit_path->setText(path);
}
// pools // pools
ui->poolFrame->show();
ui->combo_pools->insertItems(0, m_pools); ui->combo_pools->insertItems(0, m_pools);
auto preferredPool = config()->get(Config::xmrigPool).toString(); auto preferredPool = config()->get(Config::xmrigPool).toString();
if (m_pools.contains(preferredPool)) if (m_pools.contains(preferredPool))
ui->combo_pools->setCurrentIndex(m_pools.indexOf(preferredPool)); ui->combo_pools->setCurrentIndex(m_pools.indexOf(preferredPool));
else {
preferredPool = m_pools.at(0);
config()->set(Config::xmrigPool, preferredPool);
}
connect(ui->combo_pools, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XMRigWidget::onPoolChanged); connect(ui->combo_pools, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XMRigWidget::onPoolChanged);
// info // info
@ -81,18 +85,26 @@ XMRigWidget::XMRigWidget(AppContext *ctx, QWidget *parent) :
ui->console->appendPlainText("Invalid path to XMRig binary detected. Please reconfigure on the Settings tab."); ui->console->appendPlainText("Invalid path to XMRig binary detected. Please reconfigure on the Settings tab.");
else else
ui->console->appendPlainText(QString("XMRig path set to %1").arg(path)); ui->console->appendPlainText(QString("XMRig path set to %1").arg(path));
ui->console->appendPlainText("Ready to mine."); if(m_ctx->isTails) {
ui->console->appendPlainText("Mining not available on Tails.");
ui->btn_start->setEnabled(false);
}
else
ui->console->appendPlainText("Ready to mine.");
// username/password // username/password
connect(ui->lineEdit_password, &QLineEdit::editingFinished, [=]() { connect(ui->lineEdit_password, &QLineEdit::editingFinished, [=]() {
m_ctx->currentWallet->setCacheAttribute("feather.xmrig_password", ui->lineEdit_password->text()); m_ctx->currentWallet->setCacheAttribute("feather.xmrig_password", ui->lineEdit_password->text());
m_ctx->currentWallet->store(); m_ctx->currentWallet->store();
}); });
connect(ui->lineEdit_address, &QLineEdit::editingFinished, [=]() { connect(ui->lineEdit_address, &QLineEdit::editingFinished, [=]() {
m_ctx->currentWallet->setCacheAttribute("feather.xmrig_username", ui->lineEdit_address->text()); m_ctx->currentWallet->setCacheAttribute("feather.xmrig_username", ui->lineEdit_address->text());
m_ctx->currentWallet->store(); m_ctx->currentWallet->store();
}); });
// checkbox connects
connect(ui->check_custompath, &QCheckBox::stateChanged, this, &XMRigWidget::onCustomPathChecked);
connect(ui->check_solo, &QCheckBox::stateChanged, this, &XMRigWidget::onSoloChecked);
} }
void XMRigWidget::onWalletClosed() { void XMRigWidget::onWalletClosed() {
@ -140,30 +152,40 @@ void XMRigWidget::onClearClicked() {
} }
void XMRigWidget::onStartClicked() { void XMRigWidget::onStartClicked() {
auto pool_name = config()->get(Config::xmrigPool).toString(); QString xmrigPath;
bool solo = ui->check_solo->isChecked();
bool customBinary = ui->check_custompath->isChecked();
// fix error in config if(customBinary)
if(!m_pools.contains(pool_name)) { xmrigPath = config()->get(Config::xmrigPath).toString();
pool_name = m_pools.at(0); else
config()->set(Config::xmrigPool, pool_name); xmrigPath = m_ctx->XMRig->rigPath;
}
// username is receiving address usually
auto username = m_ctx->currentWallet->getCacheAttribute("feather.xmrig_username"); auto username = m_ctx->currentWallet->getCacheAttribute("feather.xmrig_username");
auto password = m_ctx->currentWallet->getCacheAttribute("feather.xmrig_password"); auto password = m_ctx->currentWallet->getCacheAttribute("feather.xmrig_password");
if(username.isEmpty()) { if(username.isEmpty()) {
Utils::showMessageBox("Error", "Please specify a receiving address on the Settings screen", true); QString err = "Please specify a receiving address on the Settings screen";
ui->console->appendPlainText(err);
Utils::showMessageBox("Error", err, true);
return; return;
} }
m_rig->start(m_threads, pool_name, username, password, ui->relayTor->isChecked(), ui->check_tls->isChecked()); QString address;
if(solo)
address = ui->lineEdit_solo->text().trimmed();
else
address = config()->get(Config::xmrigPool).toString();
m_ctx->XMRig->start(xmrigPath, m_threads, address, username, password, ui->relayTor->isChecked(), ui->check_tls->isChecked());
ui->btn_start->setEnabled(false); ui->btn_start->setEnabled(false);
ui->btn_stop->setEnabled(true); ui->btn_stop->setEnabled(true);
emit miningStarted(); emit miningStarted();
} }
void XMRigWidget::onStopClicked() { void XMRigWidget::onStopClicked() {
m_rig->terminate(); m_ctx->XMRig->terminate();
ui->btn_start->setEnabled(true); ui->btn_start->setEnabled(true);
ui->btn_stop->setEnabled(false); ui->btn_stop->setEnabled(false);
ui->label_status->hide(); ui->label_status->hide();
@ -257,6 +279,28 @@ void XMRigWidget::showContextMenu(const QPoint &pos) {
m_contextMenu->exec(ui->tableView->viewport()->mapToGlobal(pos)); m_contextMenu->exec(ui->tableView->viewport()->mapToGlobal(pos));
} }
void XMRigWidget::onCustomPathChecked(int state) {
if(state == 2) {
ui->pathFrame->show();
} else {
ui->lineEdit_path->setText("");
config()->set(Config::xmrigPath, "");
ui->pathFrame->hide();
}
}
void XMRigWidget::onSoloChecked(int state) {
if(state == 2) {
ui->poolFrame->hide();
ui->soloFrame->show();
ui->check_tls->setChecked(false);
}
else {
ui->poolFrame->show();
ui->soloFrame->hide();
}
}
void XMRigWidget::linkClicked() { void XMRigWidget::linkClicked() {
QModelIndex index = ui->tableView->currentIndex(); QModelIndex index = ui->tableView->currentIndex();
auto download_link = m_urls.at(index.row()); auto download_link = m_urls.at(index.row());

@ -33,14 +33,16 @@ public slots:
void onClearClicked(); void onClearClicked();
void onDownloads(const QJsonObject &data); void onDownloads(const QJsonObject &data);
void linkClicked(); void linkClicked();
void onProcessError(const QString &msg);
void onProcessOutput(const QByteArray &msg);
void onHashrate(const QString &hashrate);
void onCustomPathChecked(int state);
void onSoloChecked(int state);
private slots: private slots:
void onBrowseClicked(); void onBrowseClicked();
void onProcessError(const QString &msg);
void onProcessOutput(const QByteArray &msg);
void onThreadsValueChanged(int date); void onThreadsValueChanged(int date);
void onPoolChanged(int pos); void onPoolChanged(int pos);
void onHashrate(const QString &hashrate);
signals: signals:
void miningStarted(); void miningStarted();
@ -56,7 +58,6 @@ private:
unsigned int m_threads; unsigned int m_threads;
QStringList m_urls; QStringList m_urls;
QStringList m_pools{"pool.xmr.pt:9000", "pool.supportxmr.com:9000", "mine.xmrpool.net:443", "xmrpool.eu:9999", "xmr-eu1.nanopool.org:14433", "pool.minexmr.com:6666", "us-west.minexmr.com:6666", "monerohash.com:9999"}; QStringList m_pools{"pool.xmr.pt:9000", "pool.supportxmr.com:9000", "mine.xmrpool.net:443", "xmrpool.eu:9999", "xmr-eu1.nanopool.org:14433", "pool.minexmr.com:6666", "us-west.minexmr.com:6666", "monerohash.com:9999"};
XMRig *m_rig;
}; };
#endif // REDDITWIDGET_H #endif // REDDITWIDGET_H

@ -29,7 +29,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<attribute name="title"> <attribute name="title">
@ -125,86 +125,13 @@
<attribute name="title"> <attribute name="title">
<string>Settings</string> <string>Settings</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_7"> <layout class="QVBoxLayout" name="verticalLayout_9">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_6"> <layout class="QHBoxLayout" name="horizontalLayout_6">
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_6"> <layout class="QVBoxLayout" name="verticalLayout_6">
<item> <item>
<widget class="QLabel" name="label_3"> <layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="text">
<string>Path to XMRig executable</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLineEdit" name="lineEdit_path"/>
</item>
<item>
<widget class="QPushButton" name="btn_browse">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Pool</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QComboBox" name="combo_pools">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="check_tls">
<property name="text">
<string>TLS</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="relayTor">
<property name="text">
<string>Tor</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
@ -227,22 +154,39 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_5"> <layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="text"> <item>
<string>Pool worker name (optional)</string> <widget class="QCheckBox" name="check_solo">
</property> <property name="text">
</widget> <string>Solo mine</string>
</item> </property>
<item> </widget>
<layout class="QHBoxLayout" name="horizontalLayout_10"> </item>
<item> <item>
<widget class="QLineEdit" name="lineEdit_password"/> <widget class="QCheckBox" name="check_custompath">
<property name="text">
<string>Custom XMRig executable</string>
</property>
</widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer_6"> <spacer name="horizontalSpacer_7">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -256,6 +200,173 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QFrame" name="pathFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLineEdit" name="lineEdit_path">
<property name="placeholderText">
<string>/path/to/xmrig</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_browse">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QFrame" name="poolFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Pool</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QComboBox" name="combo_pools">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="soloFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Node address</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLineEdit" name="lineEdit_solo">
<property name="text">
<string>127.0.0.1:18081</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
@ -266,6 +377,71 @@
<item> <item>
<widget class="QLineEdit" name="lineEdit_address"/> <widget class="QLineEdit" name="lineEdit_address"/>
</item> </item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Password (optional)</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLineEdit" name="lineEdit_password"/>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QCheckBox" name="check_tls">
<property name="text">
<string>TLS</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="relayTor">
<property name="text">
<string>Tor</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout> </layout>
</item> </item>
<item> <item>

@ -10,12 +10,11 @@ rm ~/feather.zip 2>&1 >/dev/null
cd ~/feather cd ~/feather
git fetch --all git fetch --all
git reset --hard "$HASH" git reset --hard "$HASH"
git submodule update --init --depth 50 contrib/tor
git submodule update --init --depth 50 contrib/torsocks
git submodule update --init --depth 120 monero git submodule update --init --depth 120 monero
git submodule update --init --depth 120 --recursive monero git submodule update --init --depth 120 --recursive monero
CMAKE_PREFIX_PATH=~/Qt/5.15.1/clang_64 make -j3 mac-release cp "/Users/administrator/tor/libevent-2.1.7.dylib" "/Users/administrator/feather/src/assets/exec/libevent-2.1.7.dylib"
CMAKE_PREFIX_PATH="~/Qt/5.15.1/clang_64" TOR="/Users/administrator/tor/tor" XMRIG="/Users/administrator/xmrig/xmrig" make -j3 mac-release
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo "[+] Feather built OK" echo "[+] Feather built OK"

Loading…
Cancel
Save