diff --git a/CMakeLists.txt b/CMakeLists.txt index a9d3c5d..41a2402 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,9 @@ message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}") set(THREADS_PREFER_PTHREAD_FLAG ON) set(VERSION_MAJOR "3") -set(VERSION_MINOR "0") +set(VERSION_MINOR "1") set(VERSION_REVISION "0") -set(VERSION "beta-4") +set(VERSION "beta-5") option(FETCH_DEPS "Download dependencies if they are not found" ON) option(OPENVR "Include OpenVR support") @@ -16,7 +16,6 @@ option(ANDROID_DEBUG "View the Android app on desktop") option(TOR_BIN "Path to Tor binary to embed inside WOWlet") option(STATIC "Link libraries statically, requires static Qt") option(USE_DEVICE_TREZOR "Trezor support compilation") -option(DONATE_BEG "Prompt donation window every once in a while" ON) list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/cmake") include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) @@ -26,7 +25,7 @@ include(FindCcache) include(CheckIncludeFile) include(CheckSymbolExists) -set(WOWNERO_HEAD "f611d5c9e32bc62f1735f6571b0bdb95cc020531") +set(WOWNERO_HEAD "ff5182f7f2825263e93e88064931597b3c6cf928") set(BUILD_GUI_DEPS ON) set(BUILD_64 ON CACHE BOOL "Build 64-bit binaries") set(INSTALL_VENDORED_LIBUNBOUND ${STATIC}) @@ -85,16 +84,6 @@ function (add_linker_flag_if_supported flag var) endfunction() find_package(Git) -#if(GIT_FOUND) -# message(STATUS "Initializing submodules") -# execute_process(COMMAND git "submodule" "update" "--init" "--recursive") -# execute_process(COMMAND git rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/wownero OUTPUT_VARIABLE _WOWNERO_HEAD OUTPUT_STRIP_TRAILING_WHITESPACE) -# if(NOT _WOWNERO_HEAD STREQUAL WOWNERO_HEAD) -# message(FATAL_ERROR "[submodule] Wownero HEAD was at ${_WOWNERO_HEAD} but should be at ${WOWNERO_HEAD}") -# else() -# message(STATUS "[submodule] Wownero HEAD @ ${WOWNERO_HEAD}") -# endif() -#endif() add_subdirectory(wownero) get_directory_property(ARCH_WIDTH DIRECTORY "wownero" DEFINITION ARCH_WIDTH) @@ -153,10 +142,12 @@ endif() if(MINGW) set(Boost_THREADAPI win32) endif() + find_package(Boost 1.58 REQUIRED COMPONENTS system filesystem thread + atomic date_time chrono regex @@ -197,34 +188,57 @@ if(UNIX) endif() endif() -# To build WOWlet with embedded (and static) Tor, pass CMake -DTOR_BIN=/path/to/tor if(TOR_BIN) + # To build WOWlet with embedded & static Tor, pass CMake -DTOR_BIN=/path/to/tor_executable + # The CMake below will copy the Tor binary into src/assets/exec + # + # For release: + # ## Linux / Window + # on the buildbot(s) Tor is baked into the image + # - linux: See `Dockerfile` + # - windows: See `Dockerfile.windows` + # + # ## MacOS: + # we assume the following files are already present in src/assets/exec: + # - tor + # - libevent-2.1.7.dylib + # so copy them beforehand and set TOR_BIN to something random. + + # MacOS, check if required files are present if(APPLE) - execute_process(COMMAND bash -c "touch ${CMAKE_CURRENT_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib") + foreach(fn libevent-2.1.7.dylib tor) + set(tor_path "${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/${fn}") + if (EXISTS "${tor_path}") + message(STATUS "Tor found: ${tor_path}") + else() + message(FATAL_ERROR "TOR_BIN is set, so the following file needs to be present: '${fn}'") + endif() + set(TOR_BIN "${tor_path}") + endforeach() + else() + if(not EXISTS "${TOR_BIN}") + message(FATAL_ERROR "TOR_BIN is set, but file does not exist: '${TOR_BIN}'") + endif() + + # copy the Tor executable over + set(TOR_COPY_CMD "cp -u ${TOR_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor") + message(STATUS "Tor cmd: ${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() + endif() - execute_process(COMMAND bash -c "${TOR_BIN} --version --quiet" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE out RESULT_VARIABLE ret) + # get Tor version while we're at it + execute_process(COMMAND bash -c "${TOR_BIN} --version --quiet | head -n1" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE out RESULT_VARIABLE ret) if (ret EQUAL "0") set(TOR_VERSION "${out}") endif() - message(STATUS "${TOR_VERSION}") + message(STATUS "Tor version: ${TOR_VERSION}") configure_file("cmake/config-wowlet.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/src/config-wowlet.h") - # on the buildbot Tor is baked into the image - # - linux: See `Dockerfile` - # - windows: See `Dockerfile.windows` - # - macos: taken from Tor Browser official release - if(REPRODUCIBLE) # Always copy Tor when doing a reproducible build to prevent old versions from getting included - set(TOR_COPY_CMD "cp ${TOR_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor") - else() - set(TOR_COPY_CMD "cp -u ${TOR_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor") - endif() - 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_BIN}") else() message(STATUS "Skipping Tor inclusion because -DTOR_BIN=Off") @@ -278,16 +292,7 @@ if(APPLE) if(POLICY CMP0042) cmake_policy(SET CMP0042 NEW) endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default -std=c++11") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -DGTEST_HAS_TR1_TUPLE=0") -endif() - -if (APPLE AND NOT IOS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default -std=c++11") -endif() - -if(APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -DGTEST_HAS_TR1_TUPLE=0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -std=c++11 -DGTEST_HAS_TR1_TUPLE=0") endif() # warnings diff --git a/Makefile b/Makefile index 526ff1c..56370a0 100644 --- a/Makefile +++ b/Makefile @@ -30,8 +30,6 @@ CMAKEFLAGS = \ -DBUILD_64=On \ -DBUILD_TESTS=Off \ -DOPENVR=Off \ - -DQML=Off \ - -DXMRIG=Off \ -DTOR_BIN=Off \ -DCMAKE_CXX_STANDARD=11 \ -DCMAKE_VERBOSE_MAKEFILE=On \ @@ -75,10 +73,27 @@ windows-mxe-debug: cmake -Bbuild $(CMAKEFLAGS) $(MAKE) -Cbuild +mac: CMAKEFLAGS += -DSTATIC=Off +mac: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF) +mac: CMAKEFLAGS += -DBUILD_TAG="mac-x64" +mac: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release +mac: + cmake -Bbuild $(CMAKEFLAGS) + $(MAKE) -Cbuild + $(MAKE) -Cbuild deploy + +# used for release, covers both intel and M1 +# 1) assumes a *static* BOOST has been compiled at BOOST_ROOT, see docs/BUILDING.md +# 2) assumes a *static* Tor and libevent at src/assets/exec, see docs/BUILDING.md +mac-release: CMAKEFLAGS += -DARCH=default +mac-release: CMAKEFLAGS += -DCMAKE_OSX_ARCHITECTURES="x86_64" mac-release: CMAKEFLAGS += -DSTATIC=Off -mac-release: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF) +mac-release: CMAKEFLAGS += -DTOR_BIN="foo" mac-release: CMAKEFLAGS += -DBUILD_TAG="mac-x64" mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release +mac-release: CMAKEFLAGS += -DBoost_USE_STATIC_RUNTIME=ON +mac-release: CMAKEFLAGS += -DBoost_USE_STATIC_LIBS=ON +mac-release: CMAKEFLAGS += -DBOOST_ROOT=/Users/${USER}/build/boost mac-release: cmake -Bbuild $(CMAKEFLAGS) $(MAKE) -Cbuild diff --git a/cmake/Deploy.cmake b/cmake/Deploy.cmake index 86bbb06..f82d67e 100644 --- a/cmake/Deploy.cmake +++ b/cmake/Deploy.cmake @@ -7,7 +7,7 @@ if(APPLE OR (WIN32 AND NOT STATIC)) find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}") add_custom_command(TARGET deploy POST_BUILD - COMMAND "${MACDEPLOYQT_EXECUTABLE}" "$/../.." -always-overwrite + COMMAND "${MACDEPLOYQT_EXECUTABLE}" "$/../.." -always-overwrite -qmldir="${CMAKE_SOURCE_DIR}" COMMENT "Running macdeployqt..." ) @@ -17,12 +17,8 @@ if(APPLE OR (WIN32 AND NOT STATIC)) add_custom_command(TARGET deploy POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${_qt_svg_dylib} $/../PlugIns/imageformats/ - COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtGui.framework/Versions/5/QtGui" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $/../PlugIns/imageformats/libqsvg.dylib - COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtWidgets.framework/Versions/5/QtWidgets" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $/../PlugIns/imageformats/libqsvg.dylib - COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtSvg.framework/Versions/5/QtSvg" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $/../PlugIns/imageformats/libqsvg.dylib - COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtCore.framework/Versions/5/QtCore" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $/../PlugIns/imageformats/libqsvg.dylib - COMMENT "Copying libqsvg.dylib, running install_name_tool" + COMMENT "Copying libqsvg.dylib" ) endif() endif() -endif() \ No newline at end of file +endif() diff --git a/contrib/build-appimage.sh b/contrib/build-appimage.sh deleted file mode 100755 index 535069b..0000000 --- a/contrib/build-appimage.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -set -e -unset SOURCE_DATE_EPOCH - -APPDIR="$PWD/wowlet.AppDir" - -mkdir -p "$APPDIR" -mkdir -p "$APPDIR/usr/share/applications/" -mkdir -p "$APPDIR/usr/bin" - -cp "$PWD/src/assets/org.wowlet.wowlet.desktop" "$APPDIR/usr/share/applications/org.wowlet.wowlet.desktop" -cp "$PWD/src/assets/images/appicons/64x64.png" "$APPDIR/wowlet.png" -cp "$PWD/build/bin/wowlet" "$APPDIR/usr/bin/wowlet" - -LD_LIBRARY_PATH=/usr/local/lib /linuxdeployqt/squashfs-root/AppRun wowlet.AppDir/usr/share/applications/org.wowlet.wowlet.desktop -bundle-non-qt-libs - -find wowlet.AppDir/ -exec touch -h -a -m -t 202101010100.00 {} \; - -# Manually create AppImage (reproducibly) - -# download runtime -wget -nc https://github.com/AppImage/AppImageKit/releases/download/12/runtime-x86_64 -echo "24da8e0e149b7211cbfb00a545189a1101cb18d1f27d4cfc1895837d2c30bc30 runtime-x86_64" | sha256sum -c - -mksquashfs wowlet.AppDir wowlet.squashfs -info -root-owned -no-xattrs -noappend -fstime 0 -# mksquashfs writes a timestamp to the header -printf '\x00\x00\x00\x00' | dd conv=notrunc of=wowlet.squashfs bs=1 seek=$((0x8)) - -rm -f wowlet.AppImage -cat runtime-x86_64 >> wowlet.AppImage -cat wowlet.squashfs >> wowlet.AppImage -chmod a+x wowlet.AppImage diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 58360b2..bcab7f0 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -1,40 +1,37 @@ -## Buildbot builds +# Building WOWlet -The docker build bins can be found here: https://build.wownero.org/files/ - -## Docker static builds - -Static builds via Docker are done in 3 steps: +Building for Linux and Windows via Docker is done in 3 steps: 1. Cloning this repository (+submodules) 2. Creating a base Docker image 3. Using the base image to compile a build -### Linux (reproducible) +**important:** you only have to do step 2 (base docker image) once. + +For Mac OS, scroll down. + +# Linux -The docker image for reproducible Linux static builds uses Ubuntu 16.04 and compiles the required libraries statically -so that the resulting `wowlet` binary is static. For more information, check the Dockerfile: `Dockerfile`. +For more information, check the Dockerfile: `Dockerfile`. -#### 1. Clone +### 1. Clone ```bash git clone --branch master --recursive https://git.wownero.com/wowlet/wowlet.git cd wowlet ``` -Replace `master` with the desired version tag (e.g. `beta-4`) to build the release binary. +Replace `master` with the desired version tag (e.g. `v3.1.0`) to build the release binary. -#### 2. Base image +### 2. Base image ```bash docker build --tag wowlet:linux --build-arg THREADS=6 . ``` -Building the base image takes a while. You only need to build the base image once. +Building the base image takes a while. **You only need to build the base image once.** -#### 3. Build - -##### Standalone binary +### 3. Build ```bash docker run --rm -it -v $PWD:/wowlet -w /wowlet wowlet:linux sh -c 'make release-static -j6' @@ -44,35 +41,26 @@ If you're re-running a build make sure to `rm -rf build/` first. The resulting binary can be found in `build/bin/wowlet`. -##### AppImage +# Windows -First create the standalone binary using the Docker command in the previous step. - -```bash -docker run --rm -it -v $PWD:/wowlet -w /wowlet wowlet:linux contrib/build-appimage.sh -``` - -### Windows (reproducible) - -#### 1. Clone +### 1. Clone ```bash git clone --branch master --recursive https://git.wownero.com/wowlet/wowlet.git cd wowlet ``` -Replace `master` with the desired version tag (e.g. `beta-4`) to build the release binary. - -#### 2. Base image +Replace `master` with the desired version tag (e.g. `v3.1.0`) to build the release binary. +### 2. Base image ```bash docker build -f Dockerfile.windows --tag wowlet:win --build-arg THREADS=6 . ``` -Building the base image takes a while. You only need to build the base image once. +Building the base image takes a while. **You only need to build the base image once.** -#### 3. Build +### 3. Build ```bash docker run --rm -it -v $PWD:/wowlet -w /wowlet wowlet:win sh -c 'make windows root=/depends target=x86_64-w64-mingw32 tag=win-x64 -j6' @@ -82,42 +70,122 @@ If you're re-running a build make sure to `rm -rf build/` first. The resulting binary can be found in `build/x86_64-w64-mingw32/release/bin/wowlet.exe`. -## macOS +# Mac OS + +## method 1 (easiest) + +### 1. Get homebrew -For MacOS it's easiest to leverage [brew](https://brew.sh) to install the required dependencies. +Get [brew](https://brew.sh) to install the required dependencies. ```bash HOMEBREW_OPTFLAGS="-march=core2" HOMEBREW_OPTIMIZATION_LEVEL="O0" \ brew install boost zmq openssl libpgm miniupnpc libsodium expat libunwind-headers protobuf libgcrypt qrencode ccache cmake pkgconfig git ``` -Clone the repository. +### 2. Compile WOWlet ```bash -git clone --recursive https://git.wownero.com/wowlet/wowlet.git -``` -Download Qt5.15.1 from here: -https://download.qt.io/archive/qt/5.15/5.15.1/single/ -and build Qt 5.15.1: +CMAKE_PREFIX_PATH=/usr/local/opt/qt5/ make -j4 mac +``` -Qt build on Mac OS: +The resulting Mac OS application can be found `build/bin/wowlet.app` and will **not** have Tor embedded. +Since WOWlet needs Tor, install it, start it, and start at Mac OS boot: ```bash -cd ~/Downloads/qt-everywhere-src-5.15.1 -./configure -prefix $PWD/qtbase -release -nomake examples -nomake tests -skip qtwebchannel -skip qtpurchasing -skip webengine -skip qtwebview -make -j 4 +brew install tor +brew services start tor ``` -Build WOWlet: +## method 2 (advanced, intel/m1 release binaries) + +This assumes you have homebrew installed with the packages defined in the previous step ("Get homebrew"). + +### 1. Get Qt + +Install Qt `5.15.2` from [the open-source Qt installer](https://www.qt.io/download). + +### 2. Get static Boost + +We'll install boost under `/Users/$USER/build/boost/` ```bash -CMAKE_PREFIX_PATH=/Users/$username/Downloads/qt-everywhere-src-5.15.1/qtbase/ make mac-release +mkdir -p "/Users/$USER/build/boost" + +wget https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.gz && \ + echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" | sha256sum -c && \ + tar -xzf boost_1_73_0.tar.gz && \ + rm boost_1_73_0.tar.gz && \ + cd boost_1_73_0 + +./bootstrap.sh --without-icu +./b2 --disable-icu --with-atomic --with-system --with-filesystem --with-thread \ + --with-date_time --with-chrono --with-regex --with-serialization \ + --with-program_options --with-locale variant=release link=static \ + runtime-link=static cxxflags='-std=c++11' install -a --prefix="/Users/$USER/build/boost/" ``` -Install and start tor service for ticker/forums: +### 3. Get static Tor + +1. Download the official Tor Browser `.dmg` +2. Steal `tor.real` and `libevent-2.1.7.dylib` from the `.dmg` +3. Place them both in `src/assets/exec/` + - `src/assets/exec/tor` + - `src/assets/exec/libevent-2.1.7.dylib` + +### 4. Get static Tor + ```bash -brew install tor -brew services start tor +CMAKE_PREFIX_PATH=/Users/dsc/Qt5.15.2/5.15.2/clang_64 TOR_BIN="foo" make -j10 mac-release ``` -The resulting Mac OS application can be found `build/bin/wowlet.app` and will **not** have Tor embedded. +Resulting *static* Mac OS package: `build/bin/wowlet.app` + +## method 3 (from source, WIP, does not work yet) + +Download Qt `https://download.qt.io/archive/qt/5.15/5.15.3/single/`, unpack it somewhere. + +Patch Qt 5.15.3 source. + +- Context: [#1](https://github.com/microsoft/vcpkg/pull/21056) [#2](https://code.qt.io/cgit/qt/qtbase.git/diff/?id=dece6f5840463ae2ddf927d65eb1b3680e34a547) + +``` +diff --git a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h +index 5d4b6d6a71..cc7193d8b7 100644 +--- a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h ++++ b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h +@@ -43,6 +43,7 @@ + #include + #include + ++#include + #include + + QT_BEGIN_NAMESPACE +``` + +Build Qt: + +```bash +./configure -prefix $PWD/qtbase -release -opensource -confirm-license -ccache \ +-no-dbus -no-sql-sqlite -no-use-gold-linker -no-kms \ +-qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \ +-skip qt3d -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d \ +-skip qtdoc -skip qtquickcontrols -skip qtquickcontrols2 -skip qtspeech -skip qtgamepad \ +-skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing -optimize-size \ +-skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools \ +-skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebview \ +-skip qtwinextras -skip qtx11extras -skip gamepad -skip serialbus -skip location -skip webengine -skip qtdeclarative \ +-no-feature-cups -no-feature-ftp -no-feature-pdf -no-feature-animation -nomake examples -nomake tests -nomake tools + +./configure -prefix $PWD/qtbase -release -nomake examples -nomake tests -skip qtwebchannel -skip qtpurchasing -skip webengine -skip qtwebview +make -j 4 +``` + +Problem: QtQuick does not seem to be compiled, `Qt5QuickConfig.cmake` missing. + +Build: + +```bash +CMAKE_PREFIX_PATH=/Users/$USER/Downloads/qt-everywhere-src-5.15.3/qtbase/ make -j4 mac +``` diff --git a/docs/HACKING.md b/docs/HACKING.md index 2b7c08e..42a901c 100644 --- a/docs/HACKING.md +++ b/docs/HACKING.md @@ -22,6 +22,8 @@ by running this command: `pandoc wowlet.1.md -s -t man -o wowlet.1 && gzip wowle ## Requirements +(Possibly out-of-date) + ### Ubuntu/Debian ```bash @@ -40,29 +42,20 @@ protobuf libgcrypt qrencode ccache cmake pkgconfig git ## CMake -After installing Qt you might have a folder called `/home/$user/Qt/`. You need to pass this to CMake +After installing Qt you might have a folder called `/home/$USER/Qt/`. You need to pass this to CMake via the `CMAKE_PREFIX_PATH` definition. ``` --DCMAKE_PREFIX_PATH=/home/$user/QtNew/5.15.0/gcc_64 +-DCMAKE_PREFIX_PATH=/home/$USER/QtFooBar/5.15.0/gcc_64 ``` -There are some Wownero/WOWlet related options/definitions that you may pass: - -- `-DXMRIG=OFF` - disable XMRig feature -- `-DTOR_BIN=/path/to/tor` - Embed a Tor executable inside WOWlet -- `-DDONATE_BEG=OFF` - disable the dreaded donate requests +There are some Wownero/WOWlet related options/definitions that you may pass, see also `CMakeLists.txt`. -And: +At a bare minimum, recommended: -``` --DMANUAL_SUBMODULES=1 --DUSE_DEVICE_TREZOR=OFF --DUSE_SINGLE_BUILDDIR=ON --DDEV_MODE=ON -``` +`-DMANUAL_SUBMODULES=1 -DUSE_DEVICE_TREZOR=OFF -DUSE_SINGLE_BUILDDIR=ON -DDEV_MODE=ON` -If you have OpenSSL installed in a custom location, try: +If you have OpenSSL installed at a custom location, try: ``` -DOPENSSL_INCLUDE_DIR=/usr/local/lib/openssl-1.1.1g/include @@ -85,7 +78,7 @@ Enable debugging symbols: ## Wowlet It's best to install Tor locally as a service and start `wowlet` with `--use-local-tor`, this -prevents the child process from starting up and saves time. +prevents the child process from starting up each time you launch WOWlet and thus saves time. #### Ubuntu/Debian diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f1861d6..d4d6d68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -62,7 +62,6 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-deprecated-declarations add_subdirectory(libwalletqt) add_subdirectory(model) add_subdirectory(utils) -add_subdirectory(openpgp) if(WITH_SCANNER) add_subdirectory(QR-Code-scanner) @@ -140,6 +139,7 @@ target_include_directories(wowlet PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/tor ${CMAKE_CURRENT_SOURCE_DIR}/qrcode ${X11_INCLUDE_DIR} + ${QRENCODE_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${Qt5Core_INCLUDE_DIRS} @@ -155,10 +155,6 @@ if(OPENVR) target_include_directories(wowlet PUBLIC ${CMAKE_SOURCE_DIR}/contrib/) endif() -if(DONATE_BEG) - target_compile_definitions(wowlet PRIVATE DONATE_BEG=1) -endif() - if(TOR_BIN) target_compile_definitions(wowlet PRIVATE HAS_TOR_BIN=1) endif() @@ -288,8 +284,6 @@ endif() # Link random other stuff target_link_libraries(wowlet PUBLIC - ${ICU_LIBRARIES} - openpgp Threads::Threads ${QRENCODE_LIBRARY} ) @@ -356,15 +350,18 @@ install(TARGETS wowlet ) -message(STATUS "=============================================") -message(STATUS "VERSION_MAJOR: ${VERSION_MAJOR}") -message(STATUS "VERSION_MINOR: ${VERSION_MINOR}") -message(STATUS "VERSION_REVISION: ${VERSION_REVISION}") -message(STATUS "STATIC: ${STATIC}") -message(STATUS "VERSION: ${VERSION}") -message(STATUS "Include Valve's OpenVR library: ${OPENVR}") -message(STATUS "This build is for Android: ${ANDROID}") -message(STATUS "This build is for testing the Android app on desktop: ${ANDROID_DEBUG}") -message(STATUS "TOR_BIN: ${TOR_BIN}") -message(STATUS "DONATE_BEG: ${DONATE_BEG}") -message(STATUS "=============================================") \ No newline at end of file +message(STATUS "\n====================================== SUMMARY") +if(GIT_FOUND) + execute_process(COMMAND git rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/wownero OUTPUT_VARIABLE _WOWNERO_HEAD OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT _WOWNERO_HEAD STREQUAL WOWNERO_HEAD) + message(STATUS "[+] WOWNERO HEAD: ${_WOWNERO_HEAD} ... while CMake requested ${WOWNERO_HEAD}") + else() + message(STATUS "[+] WOWNERO HEAD: ${WOWNERO_HEAD}") + endif() +endif() +message(STATUS "[+] VERSION: ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}-${VERSION}") +message(STATUS "[+] STATIC: ${STATIC}") +message(STATUS "[+] Include Valve's OpenVR library: ${OPENVR}") +message(STATUS "[+] This build is for Android: ${ANDROID}") +message(STATUS "[+] This build is for testing the Android app on desktop: ${ANDROID_DEBUG}") +message(STATUS "[+] TOR_BIN: ${TOR_BIN}") diff --git a/src/appcontext.cpp b/src/appcontext.cpp index 4153ed7..694760a 100644 --- a/src/appcontext.cpp +++ b/src/appcontext.cpp @@ -395,10 +395,6 @@ void AppContext::onWalletOpened(Wallet *wallet) { this->nodes->connectToNode(); this->updateBalance(); -#ifdef DONATE_BEG - this->donateBeg(); -#endif - // force trigger preferredFiat signal for history model this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString()); this->setWindowTitle(); @@ -786,21 +782,6 @@ void AppContext::onOpenAliasResolve(const QString &openAlias) { emit openAliasResolveError(msg); } -void AppContext::donateBeg() { - if(this->currentWallet == nullptr) return; - if(this->networkType != NetworkType::Type::MAINNET) return; - if(this->currentWallet->viewOnly()) return; - - auto donationCounter = config()->get(Config::donateBeg).toInt(); - if(donationCounter == -1) - return; // previously donated - - donationCounter += 1; - if (donationCounter % m_donationBoundary == 0) - emit donationNag(); - config()->set(Config::donateBeg, donationCounter); -} - AppContext::~AppContext() {} // ############################################## LIBWALLET QT ######################################################### @@ -875,12 +856,6 @@ void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, q } void AppContext::onTransactionCreated(PendingTransaction *tx, const QVector &address) { - for (auto &addr : address) { - if (addr == this->donationAddress) { - this->donationSending = true; - } - } - // Let UI know that the transaction was constructed emit endTransaction(); @@ -970,12 +945,6 @@ void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, con this->updateBalance(); emit transactionCommitted(status, tx, txid); - - // this tx was a donation to WOWlet, stop our nagging - if(this->donationSending) { - this->donationSending = false; - config()->set(Config::donateBeg, -1); - } } void AppContext::storeWallet() { diff --git a/src/appcontext.h b/src/appcontext.h index 6d12de8..45fda0e 100644 --- a/src/appcontext.h +++ b/src/appcontext.h @@ -51,7 +51,6 @@ public: // Donation config const QString donationAddress = "Wo3MWeKwtA918DU4c69hVSNgejdWFCRCuWjShRY66mJkU2Hv58eygJWDJS1MNa2Ge5M1WjUkGHuLqHkweDxwZZU42d16v94mP"; const int donationAmount = 25; // euro - bool donationSending = false; QCommandLineParser *cmdargs; @@ -129,7 +128,6 @@ public: Q_INVOKABLE void initTor(); Q_INVOKABLE void initWS(); void initRestoreHeights(); - void donateBeg(); void refreshModels(); void setWindowTitle(bool mining = false); diff --git a/src/assets.qrc b/src/assets.qrc index efebcca..6b5d07c 100644 --- a/src/assets.qrc +++ b/src/assets.qrc @@ -232,6 +232,9 @@ assets/images/mining/bottom_center_console.png assets/images/mining/intel.png assets/images/mining/amd.png + assets/images/mining/overlay.png + assets/images/mining/mining_gradient.png + assets/images/mining/bg1.gif assets/images/mining/lowerleft_circle.png assets/images/mining/lowerleft.png assets/images/mining/lower_repeat.png diff --git a/src/assets/images/mining/bg1.gif b/src/assets/images/mining/bg1.gif new file mode 100644 index 0000000..356669c Binary files /dev/null and b/src/assets/images/mining/bg1.gif differ diff --git a/src/assets/images/mining/mining_gradient.png b/src/assets/images/mining/mining_gradient.png new file mode 100644 index 0000000..f7422fe Binary files /dev/null and b/src/assets/images/mining/mining_gradient.png differ diff --git a/src/assets/images/mining/overlay.png b/src/assets/images/mining/overlay.png new file mode 100644 index 0000000..be97146 Binary files /dev/null and b/src/assets/images/mining/overlay.png differ diff --git a/src/assets/images/mining/solo.png b/src/assets/images/mining/solo.png new file mode 100644 index 0000000..499e73b Binary files /dev/null and b/src/assets/images/mining/solo.png differ diff --git a/src/openpgp/CMakeLists.txt b/src/openpgp/CMakeLists.txt deleted file mode 100644 index 53e356b..0000000 --- a/src/openpgp/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -file(GLOB_RECURSE SOURCES *.cpp) -file(GLOB_RECURSE HEADERS *.h) - -find_library(GCRYPT_LIBRARY gcrypt) -find_library(GPG_ERROR_LIBRARY gpg-error) - -add_library(openpgp - ${SOURCES} - ${HEADERS}) - -find_package(GCrypt) -target_include_directories(openpgp PUBLIC - ${CMAKE_SOURCE_DIR}/monero/contrib/epee/include - ${GCRYPT_INCLUDE_DIRS} - ) - -target_link_libraries(openpgp - PUBLIC - epee - ${GCRYPT_LIBRARY} - ${GPG_ERROR_LIBRARY}) diff --git a/src/openpgp/hash.h b/src/openpgp/hash.h deleted file mode 100644 index 3b592c2..0000000 --- a/src/openpgp/hash.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2020-2021, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include - -#include -#include - -namespace openpgp -{ - -class hash -{ -public: - enum algorithm : uint8_t - { - sha256 = 8, - }; - - hash(const hash &) = delete; - hash &operator=(const hash &) = delete; - - hash(uint8_t algorithm) - : algo(algorithm) - , consumed(0) - { - if (gcry_md_open(&md, algo, 0) != GPG_ERR_NO_ERROR) - { - throw std::runtime_error("failed to create message digest object"); - } - } - - ~hash() - { - gcry_md_close(md); - } - - hash &operator<<(uint8_t byte) - { - gcry_md_putc(md, byte); - ++consumed; - return *this; - } - - hash &operator<<(const epee::span &bytes) - { - gcry_md_write(md, &bytes[0], bytes.size()); - consumed += bytes.size(); - return *this; - } - - hash &operator<<(const std::vector &bytes) - { - return *this << epee::to_span(bytes); - } - - std::vector finish() const - { - std::vector result(gcry_md_get_algo_dlen(algo)); - const void *digest = gcry_md_read(md, algo); - if (digest == nullptr) - { - throw std::runtime_error("failed to read the digest"); - } - memcpy(&result[0], digest, result.size()); - return result; - } - - size_t consumed_bytes() const - { - return consumed; - } - -private: - const uint8_t algo; - gcry_md_hd_t md; - size_t consumed; -}; - -} diff --git a/src/openpgp/mpi.h b/src/openpgp/mpi.h deleted file mode 100644 index f77a2b1..0000000 --- a/src/openpgp/mpi.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2020-2021, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include - -namespace openpgp -{ - -class mpi -{ -public: - mpi(const mpi &) = delete; - mpi &operator=(const mpi &) = delete; - - mpi(mpi &&other) - : data(other.data) - { - other.data = nullptr; - } - - template < - typename byte_container, - typename = typename std::enable_if<(sizeof(typename byte_container::value_type) == 1)>::type> - mpi(const byte_container &buffer, gcry_mpi_format format = GCRYMPI_FMT_USG) - : mpi(&buffer[0], buffer.size(), format) - { - } - - mpi(const void *buffer, size_t size, gcry_mpi_format format = GCRYMPI_FMT_USG) - { - if (gcry_mpi_scan(&data, format, buffer, size, nullptr) != GPG_ERR_NO_ERROR) - { - throw std::runtime_error("failed to read mpi from buffer"); - } - } - - ~mpi() - { - gcry_mpi_release(data); - } - - const gcry_mpi_t &get() const - { - return data; - } - -private: - gcry_mpi_t data; -}; - -} // namespace openpgp diff --git a/src/openpgp/openpgp.cpp b/src/openpgp/openpgp.cpp deleted file mode 100644 index fec702a..0000000 --- a/src/openpgp/openpgp.cpp +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright (c) 2020-2021, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "openpgp.h" - -#include - -#include - -#include "hash.h" -#include "mpi.h" -#include "packet_stream.h" - -namespace openpgp -{ -namespace -{ - -std::string::const_iterator find_next_line(std::string::const_iterator begin, const std::string::const_iterator &end) -{ - begin = std::find(begin, end, '\n'); - return begin != end ? ++begin : end; -} - -std::string::const_iterator find_line_starting_with( - std::string::const_iterator it, - const std::string::const_iterator &end, - const std::string &starts_with) -{ - for (std::string::const_iterator next_line; it != end; it = next_line) - { - next_line = find_next_line(it, end); - const size_t line_length = static_cast(std::distance(it, next_line)); - if (line_length >= starts_with.size() && std::equal(starts_with.begin(), starts_with.end(), it)) - { - return it; - } - } - return end; -} - -std::string::const_iterator find_empty_line(std::string::const_iterator it, const std::string::const_iterator &end) -{ - for (; it != end && *it != '\r' && *it != '\n'; it = find_next_line(it, end)) - { - } - return it; -} - -std::string get_armored_block_contents(const std::string &text, const std::string &block_name) -{ - static constexpr const char dashes[] = "-----"; - const std::string armor_header = dashes + block_name + dashes; - auto block_start = find_line_starting_with(text.begin(), text.end(), armor_header); - auto block_headers = find_next_line(block_start, text.end()); - auto block_end = find_line_starting_with(block_headers, text.end(), dashes); - auto contents_begin = find_next_line(find_empty_line(block_headers, block_end), block_end); - if (contents_begin == block_end) - { - throw std::runtime_error("armored block not found"); - } - return std::string(contents_begin, block_end); -} - -} // namespace - -public_key_rsa::public_key_rsa(s_expression expression, size_t bits) - : m_expression(std::move(expression)) - , m_bits(bits) -{ -} - -const gcry_sexp_t &public_key_rsa::get() const -{ - return m_expression.get(); -} - -size_t public_key_rsa::bits() const -{ - return m_bits; -} - -public_key_block::public_key_block(const std::string &armored) - : public_key_block(epee::to_byte_span(epee::to_span(epee::string_encoding::base64_decode( - strip_line_breaks(get_armored_block_contents(armored, "BEGIN PGP PUBLIC KEY BLOCK")))))) -{ -} - -// TODO: Public-Key expiration, User ID and Public-Key certification, Subkey binding checks -public_key_block::public_key_block(const epee::span buffer) -{ - packet_stream packets(buffer); - - const std::vector *data = packets.find_first(packet_tag::type::user_id); - if (data == nullptr) - { - throw std::runtime_error("user id is missing"); - } - m_user_id.assign(data->begin(), data->end()); - - const auto append_public_key = [this](const std::vector &data) { - deserializer> serialized(data); - - const auto version = serialized.read_big_endian(); - if (version != 4) - { - throw std::runtime_error("unsupported public key version"); - } - - /* const auto timestamp = */ serialized.read_big_endian(); - - const auto algorithm = serialized.read_big_endian(); - if (algorithm != openpgp::algorithm::rsa) - { - throw std::runtime_error("unsupported public key algorithm"); - } - - { - const mpi public_key_n = serialized.read_mpi(); - const mpi public_key_e = serialized.read_mpi(); - - emplace_back( - s_expression("(public-key (rsa (n %m) (e %m)))", public_key_n.get(), public_key_e.get()), - gcry_mpi_get_nbits(public_key_n.get())); - } - }; - - data = packets.find_first(packet_tag::type::public_key); - if (data == nullptr) - { - throw std::runtime_error("public key is missing"); - } - append_public_key(*data); - - packets.for_each(packet_tag::type::public_subkey, append_public_key); -} - -std::string public_key_block::user_id() const -{ - return m_user_id; -} - -// TODO: Signature expiration check -signature_rsa::signature_rsa( - uint8_t algorithm, - std::pair hash_leftmost_bytes, - uint8_t hash_algorithm, - const std::vector &hashed_data, - type type, - s_expression signature, - uint8_t version) - : m_hash_algorithm(hash_algorithm) - , m_hash_leftmost_bytes(hash_leftmost_bytes) - , m_hashed_appendix(format_hashed_appendix(algorithm, hash_algorithm, hashed_data, type, version)) - , m_signature(std::move(signature)) - , m_type(type) -{ -} - -signature_rsa signature_rsa::from_armored(const std::string &armored_signed_message) -{ - return from_base64(get_armored_block_contents(armored_signed_message, "BEGIN PGP SIGNATURE")); -} - -signature_rsa signature_rsa::from_base64(const std::string &base64) -{ - std::string decoded = epee::string_encoding::base64_decode(strip_line_breaks(base64)); - epee::span buffer(reinterpret_cast(&decoded[0]), decoded.size()); - return from_buffer(buffer); -} - -signature_rsa signature_rsa::from_buffer(const epee::span input) -{ - packet_stream packets(input); - - const std::vector *data = packets.find_first(packet_tag::type::signature); - if (data == nullptr) - { - throw std::runtime_error("signature is missing"); - } - - deserializer> buffer(*data); - - const auto version = buffer.read_big_endian(); - if (version != 4) - { - throw std::runtime_error("unsupported signature version"); - } - - const auto signature_type = static_cast(buffer.read_big_endian()); - - const auto algorithm = buffer.read_big_endian(); - if (algorithm != openpgp::algorithm::rsa) - { - throw std::runtime_error("unsupported signature algorithm"); - } - - const auto hash_algorithm = buffer.read_big_endian(); - - const auto hashed_data_length = buffer.read_big_endian(); - std::vector hashed_data = buffer.read(hashed_data_length); - - const auto unhashed_data_length = buffer.read_big_endian(); - buffer.read_span(unhashed_data_length); - - std::pair hash_leftmost_bytes{buffer.read_big_endian(), buffer.read_big_endian()}; - - const mpi signature = buffer.read_mpi(); - - return signature_rsa( - algorithm, - std::move(hash_leftmost_bytes), - hash_algorithm, - hashed_data, - signature_type, - s_expression("(sig-val (rsa (s %m)))", signature.get()), - version); -} - -bool signature_rsa::verify(const epee::span message, const public_key_rsa &public_key) const -{ - const s_expression signed_data = hash_message(message, public_key.bits()); - return gcry_pk_verify(m_signature.get(), signed_data.get(), public_key.get()) == 0; -} - -s_expression signature_rsa::hash_message(const epee::span message, size_t public_key_bits) const -{ - switch (m_type) - { - case type::binary_document: - return hash_bytes(message, public_key_bits); - case type::canonical_text_document: - { - std::vector crlf_formatted; - crlf_formatted.reserve(message.size()); - const size_t message_size = message.size(); - for (size_t offset = 0; offset < message_size; ++offset) - { - const auto &character = message[offset]; - if (character == '\r') - { - continue; - } - if (character == '\n') - { - const bool skip_last_crlf = offset + 1 == message_size; - if (skip_last_crlf) - { - break; - } - crlf_formatted.push_back('\r'); - } - crlf_formatted.push_back(character); - } - return hash_bytes(epee::to_span(crlf_formatted), public_key_bits); - } - default: - throw std::runtime_error("unsupported signature type"); - } -} - -std::vector signature_rsa::hash_asn_object_id() const -{ - size_t size; - if (gcry_md_algo_info(m_hash_algorithm, GCRYCTL_GET_ASNOID, nullptr, &size) != GPG_ERR_NO_ERROR) - { - throw std::runtime_error("failed to get ASN.1 Object Identifier (OID) size"); - } - - std::vector asn_object_id(size); - if (gcry_md_algo_info(m_hash_algorithm, GCRYCTL_GET_ASNOID, &asn_object_id[0], &size) != GPG_ERR_NO_ERROR) - { - throw std::runtime_error("failed to get ASN.1 Object Identifier (OID)"); - } - - return asn_object_id; -} - -s_expression signature_rsa::hash_bytes(const epee::span message, size_t public_key_bits) const -{ - const std::vector plain_hash = (hash(m_hash_algorithm) << message << m_hashed_appendix).finish(); - if (plain_hash.size() < 2) - { - throw std::runtime_error("insufficient message hash size"); - } - if (plain_hash[0] != m_hash_leftmost_bytes.first || plain_hash[1] != m_hash_leftmost_bytes.second) - { - throw std::runtime_error("signature checksum doesn't match the expected value"); - } - - std::vector asn_object_id = hash_asn_object_id(); - - const size_t public_key_bytes = bits_to_bytes(public_key_bits); - if (public_key_bytes < plain_hash.size() + asn_object_id.size() + 11) - { - throw std::runtime_error("insufficient public key bit length"); - } - - std::vector emsa_pkcs1_v1_5_encoded; - emsa_pkcs1_v1_5_encoded.reserve(public_key_bytes); - emsa_pkcs1_v1_5_encoded.push_back(0); - emsa_pkcs1_v1_5_encoded.push_back(1); - const size_t ps_size = public_key_bytes - plain_hash.size() - asn_object_id.size() - 3; - emsa_pkcs1_v1_5_encoded.insert(emsa_pkcs1_v1_5_encoded.end(), ps_size, 0xff); - emsa_pkcs1_v1_5_encoded.push_back(0); - emsa_pkcs1_v1_5_encoded.insert(emsa_pkcs1_v1_5_encoded.end(), asn_object_id.begin(), asn_object_id.end()); - emsa_pkcs1_v1_5_encoded.insert(emsa_pkcs1_v1_5_encoded.end(), plain_hash.begin(), plain_hash.end()); - - mpi value(emsa_pkcs1_v1_5_encoded); - return s_expression("(data (flags raw) (value %m))", value.get()); -} - -std::vector signature_rsa::format_hashed_appendix( - uint8_t algorithm, - uint8_t hash_algorithm, - const std::vector &hashed_data, - uint8_t type, - uint8_t version) -{ - const uint16_t hashed_data_size = static_cast(hashed_data.size()); - const uint32_t hashed_pefix_size = sizeof(version) + sizeof(type) + sizeof(algorithm) + sizeof(hash_algorithm) + - sizeof(hashed_data_size) + hashed_data.size(); - - std::vector appendix; - appendix.reserve(hashed_pefix_size + sizeof(version) + sizeof(uint8_t) + sizeof(hashed_pefix_size)); - appendix.push_back(version); - appendix.push_back(type); - appendix.push_back(algorithm); - appendix.push_back(hash_algorithm); - appendix.push_back(static_cast(hashed_data_size >> 8)); - appendix.push_back(static_cast(hashed_data_size)); - appendix.insert(appendix.end(), hashed_data.begin(), hashed_data.end()); - appendix.push_back(version); - appendix.push_back(0xff); - appendix.push_back(static_cast(hashed_pefix_size >> 24)); - appendix.push_back(static_cast(hashed_pefix_size >> 16)); - appendix.push_back(static_cast(hashed_pefix_size >> 8)); - appendix.push_back(static_cast(hashed_pefix_size)); - - return appendix; -} - -message_armored::message_armored(const std::string &message_armored) - : m_message(get_armored_block_contents(message_armored, "BEGIN PGP SIGNED MESSAGE")) -{ -} - -message_armored::operator epee::span() const -{ - return epee::to_byte_span(epee::to_span(m_message)); -} - -} // namespace openpgp diff --git a/src/openpgp/openpgp.h b/src/openpgp/openpgp.h deleted file mode 100644 index 4514156..0000000 --- a/src/openpgp/openpgp.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2020-2021, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include - -#include - -#include - -#include "s_expression.h" - -namespace openpgp -{ - -enum algorithm : uint8_t -{ - rsa = 1, -}; - -class public_key_rsa -{ -public: - public_key_rsa(s_expression expression, size_t bits); - - size_t bits() const; - const gcry_sexp_t &get() const; - -private: - s_expression m_expression; - size_t m_bits; -}; - -class public_key_block : public std::vector -{ -public: - public_key_block(const std::string &armored); - public_key_block(const epee::span buffer); - - std::string user_id() const; - -private: - std::string m_user_id; -}; - -class signature_rsa -{ -public: - enum type : uint8_t - { - binary_document = 0, - canonical_text_document = 1, - }; - - signature_rsa( - uint8_t algorithm, - std::pair hash_leftmost_bytes, - uint8_t hash_algorithm, - const std::vector &hashed_data, - type type, - s_expression signature, - uint8_t version); - - static signature_rsa from_armored(const std::string &armored_signed_message); - static signature_rsa from_base64(const std::string &base64); - static signature_rsa from_buffer(const epee::span input); - - bool verify(const epee::span message, const public_key_rsa &public_key) const; - -private: - s_expression hash_message(const epee::span message, size_t public_key_bits) const; - std::vector hash_asn_object_id() const; - s_expression hash_bytes(const epee::span message, size_t public_key_bits) const; - - static std::vector format_hashed_appendix( - uint8_t algorithm, - uint8_t hash_algorithm, - const std::vector &hashed_data, - uint8_t type, - uint8_t version); - -private: - uint8_t m_hash_algorithm; - std::pair m_hash_leftmost_bytes; - std::vector m_hashed_appendix; - s_expression m_signature; - type m_type; -}; - -class message_armored -{ -public: - message_armored(const std::string &message_armored); - - operator epee::span() const; - -private: - std::string m_message; -}; - -} // namespace openpgp diff --git a/src/openpgp/packet_stream.h b/src/openpgp/packet_stream.h deleted file mode 100644 index 3bfecec..0000000 --- a/src/openpgp/packet_stream.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2020-2021, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include - -#include - -#include "serialization.h" - -namespace openpgp -{ - -class packet_stream -{ -public: - packet_stream(const epee::span buffer) - : packet_stream(deserializer>(buffer)) - { - } - - template < - typename byte_container, - typename = typename std::enable_if<(sizeof(typename byte_container::value_type) == 1)>::type> - packet_stream(deserializer buffer) - { - while (!buffer.empty()) - { - packet_tag tag = buffer.read_packet_tag(); - packets.push_back({std::move(tag), buffer.read(tag.length)}); - } - } - - const std::vector *find_first(packet_tag::type type) const - { - for (const auto &packet : packets) - { - if (packet.first.packet_type == type) - { - return &packet.second; - } - } - return nullptr; - } - - template - void for_each(packet_tag::type type, Callback &callback) const - { - for (const auto &packet : packets) - { - if (packet.first.packet_type == type) - { - callback(packet.second); - } - } - } - -private: - std::vector>> packets; -}; - -} // namespace openpgp diff --git a/src/openpgp/s_expression.h b/src/openpgp/s_expression.h deleted file mode 100644 index ac60415..0000000 --- a/src/openpgp/s_expression.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2020-2021, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include -#include - -#include - -namespace openpgp -{ - -class s_expression -{ -public: - s_expression(const s_expression &) = delete; - s_expression &operator=(const s_expression &) = delete; - - template - s_expression(Args... args) - { - if (gcry_sexp_build(&data, nullptr, args...) != GPG_ERR_NO_ERROR) - { - throw std::runtime_error("failed to build S-expression"); - } - } - - s_expression(s_expression &&other) - { - std::swap(data, other.data); - } - - s_expression(gcry_sexp_t data) - : data(data) - { - } - - ~s_expression() - { - gcry_sexp_release(data); - } - - const gcry_sexp_t &get() const - { - return data; - } - -private: - gcry_sexp_t data = nullptr; -}; - -} // namespace openpgp diff --git a/src/openpgp/serialization.h b/src/openpgp/serialization.h deleted file mode 100644 index cbc1ee1..0000000 --- a/src/openpgp/serialization.h +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2020-2021, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "mpi.h" - -namespace openpgp -{ - -size_t bits_to_bytes(size_t bits) -{ - constexpr const uint16_t bits_in_byte = 8; - return (bits + bits_in_byte - 1) / bits_in_byte; -} - -std::string strip_line_breaks(const std::string &string) -{ - std::string result; - result.reserve(string.size()); - for (const auto &character : string) - { - if (character != '\r' && character != '\n') - { - result.push_back(character); - } - } - return result; -} - -struct packet_tag -{ - enum type : uint8_t - { - signature = 2, - public_key = 6, - user_id = 13, - public_subkey = 14, - }; - - const type packet_type; - const size_t length; -}; - -template < - typename byte_container, - typename = typename std::enable_if<(sizeof(typename byte_container::value_type) == 1)>::type> -class deserializer -{ -public: - deserializer(byte_container buffer) - : buffer(std::move(buffer)) - , cursor(0) - { - } - - bool empty() const - { - return buffer.size() - cursor == 0; - } - - packet_tag read_packet_tag() - { - const auto tag = read_big_endian(); - - constexpr const uint8_t format_mask = 0b11000000; - constexpr const uint8_t format_old_tag = 0b10000000; - if ((tag & format_mask) != format_old_tag) - { - throw std::runtime_error("invalid packet tag"); - } - - const packet_tag::type packet_type = static_cast((tag & 0b00111100) >> 2); - const uint8_t length_type = tag & 0b00000011; - - size_t length; - switch (length_type) - { - case 0: - length = read_big_endian(); - break; - case 1: - length = read_big_endian(); - break; - case 2: - length = read_big_endian(); - break; - default: - throw std::runtime_error("unsupported packet length type"); - } - - return {packet_type, length}; - } - - mpi read_mpi() - { - const size_t bit_length = read_big_endian(); - return mpi(read_span(bits_to_bytes(bit_length))); - } - - std::vector read(size_t size) - { - if (buffer.size() - cursor < size) - { - throw std::runtime_error("insufficient buffer size"); - } - - const size_t offset = cursor; - cursor += size; - - return {&buffer[offset], &buffer[cursor]}; - } - - template ::value>::type> - T read_big_endian() - { - if (buffer.size() - cursor < sizeof(T)) - { - throw std::runtime_error("insufficient buffer size"); - } - T result = 0; - for (size_t read = 0; read < sizeof(T); ++read) - { - result = (result << 8) | static_cast(buffer[cursor++]); - } - return result; - } - - epee::span read_span(size_t size) - { - if (buffer.size() - cursor < size) - { - throw std::runtime_error("insufficient buffer size"); - } - - const size_t offset = cursor; - cursor += size; - - return {reinterpret_cast(&buffer[offset]), size}; - } - -private: - byte_container buffer; - size_t cursor; -}; - -} // namespace openpgp diff --git a/src/qrcode/CMakeLists.txt b/src/qrcode/CMakeLists.txt index 9ffcf58..86b79c9 100644 --- a/src/qrcode/CMakeLists.txt +++ b/src/qrcode/CMakeLists.txt @@ -18,4 +18,5 @@ set(qrcode_SOURCES ) add_library(qrcode STATIC ${qrcode_SOURCES}) +target_include_directories(qrcode PUBLIC ${QRENCODE_INCLUDE_DIR}) target_link_libraries(qrcode Qt5::Core Qt5::Widgets Qt5::Svg ${QRENCODE_LIBRARY}) diff --git a/src/ui/qml/mining.qml b/src/ui/qml/mining.qml index d76fe23..46a195c 100644 --- a/src/ui/qml/mining.qml +++ b/src/ui/qml/mining.qml @@ -34,6 +34,55 @@ Rectangle { FontLoader { id: comicMonoBold; source: "qrc:/fonts/ComicMono-Bold.ttf" } } + AnimatedImage { + //visible: mining.daemonMiningState === 0 + source: "qrc:/mining/bg1.gif" + fillMode: Image.PreserveAspectCrop + + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.top: parent.top + anchors.bottomMargin: 92 + anchors.topMargin: 112 + } + + Image { + source: "qrc:/mining/overlay.png" + fillMode: Image.PreserveAspectCrop + + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.top: parent.top + anchors.bottomMargin: 92 + anchors.topMargin: 112 + smooth: false + } + + Image { + id: miningGradient + opacity: 0.0 + source: "qrc:/mining/mining_gradient.png" + fillMode: Image.PreserveAspectCrop + + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.top: parent.top + anchors.bottomMargin: 92 + anchors.topMargin: 112 + smooth: false + + states: [ + State { when: mining.daemonMiningState !== 0; + PropertyChanges { target: miningGradient; opacity: 1.0 }}, + State { when: mining.daemonMiningState === 0; + PropertyChanges { target: miningGradient; opacity: 0.0 }} + ] + transitions: [ Transition { NumberAnimation { property: "opacity"; duration: 750}} ] + } + ColumnLayout { width: parent.width height: parent.height @@ -343,8 +392,14 @@ Rectangle { id: cons anchors.margins: 4 anchors.fill: parent - text: "Miner is idle." - font.pointSize: 12 + text: { + if(mining.daemonMiningState === 0) { + return "Press the pick-axe to start mining!"; + } else { + return ""; + } + } + font.pointSize: 14 font.family: comicMono.name; wrapMode: Text.WordWrap color: "white" @@ -436,10 +491,7 @@ Rectangle { } Image { - source: { - var imgs = ["qrc:/mining/amd.png", "qrc:/mining/intel.png"]; - return imgs[Math.floor(Math.random()*imgs.length)]; - } + source: "qrc:/mining/intel.png" width: 100 height: 100 fillMode: Image.Pad @@ -447,7 +499,6 @@ Rectangle { anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter - } } diff --git a/src/utils/config.cpp b/src/utils/config.cpp index a73fd88..2e9b125 100644 --- a/src/utils/config.cpp +++ b/src/utils/config.cpp @@ -23,7 +23,6 @@ static const QHash configStrings = { {Config::warnOnTestnet,{QS("warnOnTestnet"), true}}, {Config::warnOnAlpha,{QS("warnOnAlpha"), true}}, {Config::homeWidget,{QS("homeWidget"), 0}}, - {Config::donateBeg,{QS("donateBeg"), 1}}, {Config::skin,{QS("skin"), "light"}}, {Config::openVRSkin,{QS("openVRSkin"), "default"}}, {Config::openVRStreamerMode,{QS("openVRStreamerMode"), false}}, diff --git a/src/utils/config.h b/src/utils/config.h index fa6ff29..7095696 100644 --- a/src/utils/config.h +++ b/src/utils/config.h @@ -25,7 +25,6 @@ public: warnOnTestnet, warnOnAlpha, homeWidget, - donateBeg, autoOpenWalletPath, skin, openVRSkin, diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 3071253..4156ccf 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -439,6 +439,18 @@ int Utils::maxLength(const QVector &array) { return maxLength; } +unsigned int Utils::countAlphaNum(const QByteArray &line) { + QRegularExpression re("([a-zA-Z0-9])"); + QRegularExpressionMatchIterator iterator = re.globalMatch(line); + + int count = 0; + while (iterator.hasNext()){ + QRegularExpressionMatch match = iterator.next(); + count += 1; + } + return count; +} + bool Utils::versionOutdated(const QString ¤t_version, const QString &newest_version) { // True when major or minor version changed auto cver = current_version.split('.'); diff --git a/src/utils/utils.h b/src/utils/utils.h index 4ccca15..fe12914 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -70,6 +70,7 @@ public: static bool xdgDesktopEntryWrite(const QString &path); static void xdgRefreshApplications(); static bool xdgDesktopEntryRegister(); + static unsigned int countAlphaNum(const QByteArray &line); static bool pixmapWrite(const QString &path, const QPixmap &pixmap); static QFont relativeFont(int delta); static double roundSignificant(double N, double n); diff --git a/src/utils/xmrig.cpp b/src/utils/xmrig.cpp index 93a40d9..b26fe89 100644 --- a/src/utils/xmrig.cpp +++ b/src/utils/xmrig.cpp @@ -50,7 +50,7 @@ bool XmRig::start(const QString &path, int threads) { } if(path.isEmpty()) { - emit error("wownerod path seems to be empty."); + emit error("wownerod path seems to be empty. Go to the mining settings tab and point towards the wownerod executable!"); return false; } @@ -114,6 +114,10 @@ void XmRig::onHandleProcessOutput() { auto lower = line.toLower(); if(lower.isEmpty() || lower.startsWith("status")) continue; + // skip ascii/ansi art + unsigned int printable_chars_pct = 100 * Utils::countAlphaNum(lower) / lower.length(); + if(printable_chars_pct < 60) continue; + if(lower.startsWith("the daemon will start synchronizing")) { changeDaemonState(DaemonMiningState::startup); } else if(lower.startsWith("synchronization started")) { diff --git a/src/widgets/xmrigwidget.cpp b/src/widgets/xmrigwidget.cpp index f461bcd..887eb03 100644 --- a/src/widgets/xmrigwidget.cpp +++ b/src/widgets/xmrigwidget.cpp @@ -362,12 +362,12 @@ void XMRigWidget::showContextWownerodMenu(const QPoint &pos) { QModelIndex index = ui->tableWownerod->indexAt(pos); if (!index.isValid()) return; - m_contextMenuRig->exec(ui->tableWownerod->viewport()->mapToGlobal(pos)); + m_contextMenuWownerod->exec(ui->tableWownerod->viewport()->mapToGlobal(pos)); } void XMRigWidget::wownerodLinkClicked() { - QModelIndex index = ui->tableRig->currentIndex(); - auto download_link = m_urlsRig.at(index.row()); + QModelIndex index = ui->tableWownerod->currentIndex(); + auto download_link = m_urlsWownerod.at(index.row()); Utils::externalLinkWarning(this, download_link); }