Merge pull request 'Cmake: Refactor executable embeds, embed XMRig, allow solo mining' (#89) from dsc/feather:refactor-feather-execs into master

Reviewed-on: https://git.wownero.com/feather/feather/pulls/89
This commit is contained in:
dsc 2020-10-18 20:47:53 +00:00
commit 44a2fc30dc
24 changed files with 548 additions and 268 deletions

View file

@ -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
... ...

View file

@ -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.

View file

@ -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")
set(TOR_DIR "${CMAKE_SOURCE_DIR}/contrib/tor")
if(BUILD_TOR AND APPLE)
execute_process(COMMAND bash -c "touch ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
ENDIF()
if(UNIX AND NOT APPLE)
set(TOR_LIB "libtorsocks.so")
elseif(APPLE)
set(TOR_LIB "libtorsocks.dylib")
endif()
if("$ENV{DRONE}" STREQUAL "true" AND APPLE)
message(STATUS "We are inside a static compile with Drone CI") message(STATUS "We are inside a static compile with Drone CI")
# @TODO: taken from Tor Browser official release for now
execute_process(COMMAND bash -c "cp ~/tor/libevent-2.1.7.dylib ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
execute_process(COMMAND bash -c "cp ~/tor/tor ${CMAKE_SOURCE_DIR}/src/tor/tor")
elseif("$ENV{DRONE}" STREQUAL "true" AND BUILD_TOR)
message(STATUS "We are inside a static compile with Drone CI")
if(MINGW)
execute_process(COMMAND bash -c "cp /mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe ${CMAKE_SOURCE_DIR}/src/tor/tor.exe")
elseif(UNIX AND NOT APPLE)
execute_process(COMMAND bash -c "cp /usr/local/tor/bin/tor ${CMAKE_SOURCE_DIR}/src/tor/tor")
execute_process(COMMAND bash -c "cp /usr/local/torsocks/lib/torsocks/* ${CMAKE_SOURCE_DIR}/src/tor/")
endif() endif()
# To build Feather with embedded (and static) Tor, pass CMake -DTOR=/path/to/tor
if(TOR)
if(APPLE)
execute_process(COMMAND bash -c "touch ${CMAKE_CURRENT_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
endif()
# on the buildbot Tor is baked into the image
# - linux: See `Dockerfile`
# - windows: https://github.com/mxe/mxe/blob/1024dc7d2db5eb7d5d3c64a2c12b5f592572f1ce/plugins/apps/tor.mk
# - 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() else()
if(BUILD_TOR) message(STATUS "Skipping Tor inclusion because -DTOR=Off")
if(UNIX OR APPLE) endif()
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) # To build Feather with embedded (and static) XMRig, pass CMake -DXMRIG=/path/to/xmrig
message(STATUS "${TOR_LIB} found, skipping Tor build") if(XMRIG)
# on the buildbot XMRig is baked into the image
# - linux: See `Dockerfile`
# - windows: See `Dockerfile_windows`
# - macos: manually downloaded an official release
set(XMRIG_COPY_CMD "cp ${XMRIG} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/xmrig")
message(STATUS "${XMRIG_COPY_CMD}")
execute_process(COMMAND bash -c "${XMRIG_COPY_CMD}" RESULT_VARIABLE ret)
if(ret EQUAL "1")
message(FATAL_ERROR "XMRig copy failure: ${XMRIG_COPY_CMD}")
endif()
message(STATUS "Embedding XMRig binary at ${XMRIG}")
else() else()
message(STATUS "${TOR_LIB} not found, building Tor") message(STATUS "Skipping XMRig inclusion because -DXMRIG=Off")
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)

View file

@ -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

View file

@ -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/

View file

@ -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:

View file

@ -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)

View file

@ -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")
elseif(MINGW AND BUILD_TOR)
set(ASSETS_OS "assets_windows_tor.qrc")
else() else()
message(STATUS "Building without embedded Tor") set(ASSETS_TOR "assets_tor.qrc")
endif()
endif()
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)

View file

@ -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))
throw std::runtime_error("Could not create directory " + config_dir_tordata.toStdString());
}
QString config_dir_torsocks = QString("%1%2").arg(dir).arg("torsocks"); QStringList createDirs({dir, config_dir_tor, config_dir_tordata, config_dir_xmrig});
if(!Utils::dirExists(config_dir_torsocks)) { for(const auto &d: createDirs) {
qDebug() << QString("Creating directory: %1").arg(config_dir_torsocks); if(!Utils::dirExists(d)) {
if (!QDir().mkpath(config_dir_torsocks)) qDebug() << QString("Creating directory: %1").arg(d);
throw std::runtime_error("Could not create directory " + config_dir_torsocks.toStdString()); if (!QDir().mkpath(d))
throw std::runtime_error("Could not create directory " + d.toStdString());
}
} }
} }

View file

@ -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;

View file

@ -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>

View file

@ -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>

View file

@ -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>

6
src/assets_tor_macos.qrc Normal file
View file

@ -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>

View file

@ -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_;

View file

@ -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");

View file

@ -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;
} }

View file

@ -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);
connect(&m_process, &QProcess::readyReadStandardOutput, this, &XMRig::handleProcessOutput);
connect(&m_process, &QProcess::errorOccurred, this, &XMRig::handleProcessError);
connect(&m_process, &QProcess::stateChanged, this, &XMRig::stateChanged);
} }
void XMRig::stop() { void XmRig::prepare() {
// unpack and set process signals
if(!this->unpackBins()) {
qCritical() << "failed to write XMRig to config directory";
return;
}
m_process.setProcessChannelMode(QProcess::MergedChannels);
connect(&m_process, &QProcess::readyReadStandardOutput, this, &XmRig::handleProcessOutput);
connect(&m_process, &QProcess::errorOccurred, this, &XmRig::handleProcessError);
connect(&m_process, &QProcess::stateChanged, this, &XmRig::stateChanged);
}
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,21 +53,21 @@ 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;
if(!password.isEmpty())
arguments << "-p" << password; arguments << "-p" << password;
arguments << "--no-color"; arguments << "--no-color";
arguments << "-t" << QString::number(threads); arguments << "-t" << QString::number(threads);
@ -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;
}

View file

@ -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);

View file

@ -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();
if(!path.isEmpty()) {
ui->pathFrame->show();
ui->check_custompath->setChecked(true);
ui->lineEdit_path->setText(path); ui->lineEdit_path->setText(path);
ui->label_status->hide(); }
if(path.isEmpty())
ui->tabWidget->setCurrentIndex(1);
// 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,6 +85,11 @@ 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));
if(m_ctx->isTails) {
ui->console->appendPlainText("Mining not available on Tails.");
ui->btn_start->setEnabled(false);
}
else
ui->console->appendPlainText("Ready to mine."); ui->console->appendPlainText("Ready to mine.");
// username/password // username/password
@ -88,11 +97,14 @@ XMRigWidget::XMRigWidget(AppContext *ctx, QWidget *parent) :
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());

View file

@ -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

View file

@ -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,8 @@
</item> </item>
</layout> </layout>
</item> </item>
</layout>
</item>
<item> <item>
<widget class="QLabel" name="label_5"> <spacer name="horizontalSpacer_8">
<property name="text">
<string>Pool worker name (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"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -256,6 +169,204 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QCheckBox" name="check_solo">
<property name="text">
<string>Solo mine</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="check_custompath">
<property name="text">
<string>Custom XMRig executable</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<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>
<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>

View file

@ -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"