diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17bc8167a2..e91b96ab58 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,11 +30,11 @@ jobs: OS_NAME: linux steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: current time for cache run: echo "TIMESTAMP=$(date +%s)" >> $GITHUB_ENV - name: cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ./depends/built @@ -55,11 +55,11 @@ jobs: OS_NAME: macos steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: current time for cache run: echo "TIMESTAMP=$(date +%s)" >> $GITHUB_ENV - name: cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ./ci/scratch/.ccache @@ -87,11 +87,11 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: setup-python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: - python-version: 3.6 + python-version: 3.9 - name: lint run: | set -o errexit; source ./ci/lint/04_install.sh diff --git a/.tx/config b/.tx/config index 972366c2e5..75b58ff3ca 100644 --- a/.tx/config +++ b/.tx/config @@ -1,7 +1,7 @@ [main] host = https://www.transifex.com -[gridcoin.src-qt-locale-bitcoin-en-ts--development] +[o:gridcoin:p:gridcoin:r:src-qt-locale-bitcoin-en-ts--development] file_filter = src/qt/locale/bitcoin_.xlf source_file = src/qt/locale/bitcoin_en.xlf source_lang = en diff --git a/CHANGELOG.md b/CHANGELOG.md index e5cfebd322..62187547ef 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,61 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/) and this project adheres to [Semantic Versioning](https://semver.org/). +## [5.4.1.0] 2022-11-27, leisure + +### Added + - net: Add and document network messages in protocol.h (backport) #2533 (@Pythonix) + - Define MAX_DIGITS_BTC for magic number in BitcoinUnits::format #2555 (@barton2526) + - rpc: Implementation of getmrcinfo #2570 (@jamescowens) + - init: Add init error message if -printtoconsole and -daemon specified simultaneously #2571 (@jamescowens) + - rpc: getmrcinfo part 2 - add calculated minimum fees and fee boosting and by CPID reporting #2575 (@jamescowens) + - fs: fully initialize `_OVERLAPPED` for win32 #2587 (@div72) + - util: Diagnose Lib Version #1 #2573 (@MinaFarhan) + - util: Implement core diagnostics #2 (@jamescowens) + - util: modify Win32LockedPageAllocator to query windows for limit. #2536 (@div72) + - gui, voting: Implement information for wallet holder's votes on poll info cards #2605 (@jamescowens) + +### Changed + - scripted-diff: Drop Darwin version for better maintainability #2557 (@barton2526) + - build: Require gcc8 on Ubuntu Bionic to enable C++17 features #2579 (@barton2526) + - util: Replace use of locale dependent atoi(…) with locale-independent std::from_chars(…) (C++17) #2564 (@barton2526) + - translation: Translation updates #2581 (@jamescowens) + - depends: update urls for dmg tools #2583 (@div72) + - Use ReadLE64 in uint256::GetUint64 instead of duplicating logic #2586 (@div72) + - util: Make Parse{Int,UInt}{32,64} use locale independent std::from_chars(…) (C++17) instead of locale dependent strto{l,ll,ul,ull} #2592 (@barton2526) + - build: don't set PORT=no in config.site #2593 (@barton2526) + - build: Replace `which` command with `command -v` #2595 (@barton2526) + - build: update ax_cxx_compile_stdcxx to serial 14 #2596 (@barton2526) + - gui: Changed the unlocked for staking only icons to green #2598 (@delta1513) + - gui: Translation updates #2599 (@jamescowens) + - build: update CI for linter and actions version #2606 (@jamescowens) + - gui: Update translations #2608 (@jamescowens) + +### Removed + - refactor: remove unused c-string variant of atoi64() #2562 (@barton2526) + - refactor: Remove unused CDataStream::rdbuf method #2585 (@div72) + +### Fixed + - net: Fix some benign races (backport) #2532 (@Pythonix) + - rpc: fix invalid parameter error codes for {sign,verify}message RPCs #2556 (@barton2526) + - build: Fix x86_64 <-> arm64 cross-compiling for macOS #2560 (@barton2526) + - rpc, mrc: Fix field name and initialization of mrc_fees_to_staker #2567 (@jamescowens) + - gui: Add missing resizeTableColumns to fix send address book column widths #2569 (@jamescowens) + - accrual: rebuild snapshot registry on corruption instead of crashing #2577 (@div72) + - doc: Fix link to MurmurHash3.cpp (moved from Google Code to Github) #2584 (@div72) + - fix help text for `revokebeacon` command #2591 (@Pythonix) + - util: Fix spelling error in gridcoinresearchd.cpp #2590 (@jamescowens) + - depends: always use correct ar for win qt build #2588 (@div72) + - util: Fix some bugs due to new implementation and change in BOINC dir handling (@jamescowens) + - util: Diagnose lib - Implement changes to solve crash on some Boost 1.66 machines #2597 (@jamescowens) + - contrib: Check for `patch` command, Check for `wget` command #2594 (@barton2526) + - build: Check std::system for -[alert|block|wallet]notify #2582 (@barton2526) + - gui: Changed the wording on the tooltip for the address book #2602 (@delta1513) + - build: pass win32-dll to LT_INIT() #2601 (@barton2526) + - build: minor cleanups to native_clang package #2600 (@barton2526) + - util: restore translations to diagnostics #2603 (@jamescowens) + - refactor: Fix problems found by valgrind #2607 (@jamescowens) + ## [5.4.0.0] 2022-08-01, mandatory, "Kermit's Mom" ### Added @@ -1040,7 +1095,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/). Fork is set to trigger at block 1420000. - Raise coinstake output count limit to 8 #1261 (@tomasbrod). - Port of Bitcoin hash implementation #1208 (@jamescowens). - - Minor canges for the build documentation #1091 (@Lenni). + - Minor changes for the build documentation #1091 (@Lenni). - Allow sendmany to be used without an account specified #1158 (@Foggyx420). ### Fixed - Fix `cpids` and `validcpids` not returning the correct data #1233 @@ -1074,7 +1129,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/). - Compatibility with boost-1.67 (@denravonska) - Calculations to reduce network time offset (@jamescowens) - Feedback for addnode RPC command (@tomasbrod) - - Added data acquisiton commands (@tomasbrod): + - Added data acquisition commands (@tomasbrod): - getrecentblocks - exportstats1 - getsupervotes @@ -1409,7 +1464,7 @@ Internal test version used to sort out the forks. ### Fixed - High CPU usage #349 (@tomasbrod) - - Repetetive block signing #295 (@tomasbrod) + - Repetitive block signing #295 (@tomasbrod) - Staking creates 1 cent output #311 (@tomasbrod) - Client no longer has to be restarted for a beacon to activate #253 (@Foggyx420). diff --git a/build-aux/m4/ax_cxx_compile_stdcxx.m4 b/build-aux/m4/ax_cxx_compile_stdcxx.m4 index dc69e23463..51a35054d0 100644 --- a/build-aux/m4/ax_cxx_compile_stdcxx.m4 +++ b/build-aux/m4/ax_cxx_compile_stdcxx.m4 @@ -10,8 +10,8 @@ # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) -# or '14' (for the C++14 standard). +# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for +# the respective C++ standard version. # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. @@ -36,13 +36,14 @@ # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper # Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021 Jörn Heusipp # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 12 +#serial 14 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). @@ -51,6 +52,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [$1], [20], [ax_cxx_compile_alternatives="20"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], @@ -69,12 +71,12 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [ax_cv_cxx_compile_cxx$1=yes], [ax_cv_cxx_compile_cxx$1=no])]) - if test "$ax_cv_cxx_compile_cxx$1" = "yes"; then + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then ac_success=yes fi]) m4_if([$2], [noext], [], [dnl - if test "$ac_success" = "no"; then + if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) @@ -98,7 +100,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl fi]) m4_if([$2], [ext], [], [dnl - if test "$ac_success" = "no"; then + if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" @@ -122,18 +124,18 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl break fi done - if test "$ac_success" = "yes"; then + if test x$ac_success = xyes; then break fi done fi]) AC_LANG_POP([C++]) - if test "$ax_cxx_compile_cxx$1_required" = "true"; then - if test "$ac_success" = "no"; then + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi fi - if test "$ac_success" = "no"; then + if test x$ac_success = xno; then HAVE_CXX$1=0 AC_MSG_NOTICE([No compiler with C++$1 support was found]) else @@ -151,7 +153,6 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) - dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], @@ -159,12 +160,24 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) +dnl Test body for checking C++17 support + m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 +) + + dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ @@ -960,3 +973,33 @@ namespace cxx17 #endif // __cplusplus < 201703L ]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L + +]]) diff --git a/cd/00_setup_env_mac.sh b/cd/00_setup_env_mac.sh index 64beb8b0bb..68b002b0e4 100755 --- a/cd/00_setup_env_mac.sh +++ b/cd/00_setup_env_mac.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_macos_cross export DOCKER_NAME_TAG=ubuntu:20.04 -export HOST=x86_64-apple-darwin18 +export HOST=x86_64-apple-darwin export PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools libtinfo5 python3-dev python3-setuptools xorriso" export XCODE_VERSION=12.1 export XCODE_BUILD_ID=12A7403 diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh index 78d9bc676b..ad1856aedc 100755 --- a/ci/lint/04_install.sh +++ b/ci/lint/04_install.sh @@ -6,11 +6,11 @@ export LC_ALL=C -./ci/retry/retry sudo apt update && sudo apt install -y clang-format-9 -sudo update-alternatives --install /usr/bin/clang-format clang-format $(which clang-format-9 ) 100 -sudo update-alternatives --install /usr/bin/clang-format-diff clang-format-diff $(which clang-format-diff-9) 100 +./ci/retry/retry sudo apt update && sudo apt install -y clang-format-14 +sudo update-alternatives --install /usr/bin/clang-format clang-format $(which clang-format-14 ) 100 +sudo update-alternatives --install /usr/bin/clang-format-diff clang-format-diff $(which clang-format-diff-14) 100 -./ci/retry/retry pip3 install codespell==2.1.0 +./ci/retry/retry pip3 install codespell==2.2.2 ./ci/retry/retry pip3 install flake8==4.0.1 ./ci/retry/retry pip3 install mypy==0.942 ./ci/retry/retry pip3 install vulture==2.3 diff --git a/ci/test/00_setup_env_mac.sh b/ci/test/00_setup_env_mac.sh index deb273963e..237077efd1 100755 --- a/ci/test/00_setup_env_mac.sh +++ b/ci/test/00_setup_env_mac.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_macos_cross export DOCKER_NAME_TAG=ubuntu:20.04 # Check that Focal can cross-compile to macos -export HOST=x86_64-apple-darwin18 +export HOST=x86_64-apple-darwin export PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools libtinfo5 python3-dev python3-setuptools xorriso" export XCODE_VERSION=12.1 export XCODE_BUILD_ID=12A7403 diff --git a/ci/test/00_setup_env_mac_host.sh b/ci/test/00_setup_env_mac_host.sh index e3c7bbbeea..cc55ae79b4 100755 --- a/ci/test/00_setup_env_mac_host.sh +++ b/ci/test/00_setup_env_mac_host.sh @@ -6,7 +6,7 @@ export LC_ALL=C.UTF-8 -export HOST=x86_64-apple-darwin18 +export HOST=x86_64-apple-darwin export GOAL="install" # We run the contrib/install_db4.sh script rather than installing the # Homebrew berkeley-db4 formula to add the Berkeley DB 4.8 dependency diff --git a/ci/test/00_setup_env_native_old.sh b/ci/test/00_setup_env_native_old.sh index ff35aae8fd..44e1dd0315 100755 --- a/ci/test/00_setup_env_native_old.sh +++ b/ci/test/00_setup_env_native_old.sh @@ -8,11 +8,11 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_old export DOCKER_NAME_TAG=ubuntu:18.04 -export PACKAGES="libqt5gui5 libqt5core5a qtbase5-dev libqt5dbus5 qttools5-dev qttools5-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-iostreams-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libqrencode-dev libzip-dev zlib1g zlib1g-dev libcurl4-openssl-dev" +export PACKAGES="gcc-8 g++-8 libqt5gui5 libqt5core5a qtbase5-dev libqt5dbus5 qttools5-dev qttools5-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-iostreams-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libqrencode-dev libzip-dev zlib1g zlib1g-dev libcurl4-openssl-dev" export RUN_UNIT_TESTS=true # export RUN_FUNCTIONAL_TESTS=false # export RUN_SECURITY_TESTS="true" export GOAL="install" -export GRIDCOIN_CONFIG="--enable-reduce-exports --with-incompatible-bdb --with-gui=qt5" +export GRIDCOIN_CONFIG="--enable-reduce-exports --with-incompatible-bdb --with-gui=qt5 CC=gcc-8 CXX=g++-8" export NEED_XVFB="true" export NO_DEPENDS=1 diff --git a/configure.ac b/configure.ac index 4752a26c34..3c509a19a2 100755 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 4) -define(_CLIENT_VERSION_REVISION, 0) +define(_CLIENT_VERSION_REVISION, 1) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2022) @@ -75,7 +75,7 @@ AC_PROG_OBJCXX ]) dnl Libtool init checks. -LT_INIT([pic-only]) +LT_INIT([pic-only win32-dll]) dnl Check/return PATH for base programs. AC_PATH_TOOL(AR, ar) @@ -768,6 +768,31 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([ ] ) +have_any_system=no +AC_MSG_CHECKING([for std::system]) +AC_LINK_IFELSE( + [ AC_LANG_PROGRAM( + [[ #include ]], + [[ int nErr = std::system(""); ]] + )], + [ AC_MSG_RESULT(yes); have_any_system=yes], + [ AC_MSG_RESULT(no) ] +) + +AC_MSG_CHECKING([for ::_wsystem]) +AC_LINK_IFELSE( + [ AC_LANG_PROGRAM( + [[ ]], + [[ int nErr = ::_wsystem(""); ]] + )], + [ AC_MSG_RESULT(yes); have_any_system=yes], + [ AC_MSG_RESULT(no) ] +) + +if test "x$have_any_system" != "xno"; then + AC_DEFINE(HAVE_SYSTEM, 1, Define to 1 if std::system or ::wsystem is available.) +fi + dnl Our minimum supported glibc is 2.17, however support for thread_local dnl did not arrive in glibc until 2.18. if test "$use_thread_local" = "yes" || test "$use_thread_local" = "auto"; then diff --git a/contrib/install_db4.sh b/contrib/install_db4.sh index 6c6577de33..3d4f78b659 100755 --- a/contrib/install_db4.sh +++ b/contrib/install_db4.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright (c) 2017-2019 The Bitcoin Core developers +# Copyright (c) 2017-2021 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://opensource.org/licenses/mit-license.php. @@ -59,13 +59,22 @@ http_get() { echo "File ${2} already exists; not downloading again" elif check_exists curl; then curl --insecure --retry 5 "${1}" -o "${2}" - else + elif check_exists wget; then wget --no-check-certificate "${1}" -O "${2}" + else + echo "Simple transfer utilities 'curl' and 'wget' not found. Please install one of them and try again." + exit 1 fi sha256_check "${3}" "${2}" } +# Ensure the commands we use exist on the system +if ! check_exists patch; then + echo "Command-line tool 'patch' not found. Install patch and try again." + exit 1 +fi + mkdir -p "${BDB_PREFIX}" http_get "${BDB_URL}" "${BDB_VERSION}.tar.gz" "${BDB_HASH}" tar -xzvf ${BDB_VERSION}.tar.gz -C "$BDB_PREFIX" diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md index 0750e75547..602b120e56 100644 --- a/contrib/macdeploy/README.md +++ b/contrib/macdeploy/README.md @@ -57,10 +57,10 @@ the depends directory and deploy the .dmg: ```bash cd depends -make HOST=x86_64-apple-darwin18 +make HOST=x86_64-apple-darwin cd .. ./autogen.sh # not required when building from tarball -CONFIG_SITE=$PWD/depends/x86_64-apple-darwin18/share/config.site ./configure --prefix=/ +CONFIG_SITE=$PWD/depends/x86_64-apple-darwin/share/config.site ./configure --prefix=/ make make deploy ``` diff --git a/depends/README.md b/depends/README.md index 5681b288fe..64627b7abd 100644 --- a/depends/README.md +++ b/depends/README.md @@ -22,7 +22,7 @@ Common `host-platform-triplets` for cross compilation are: - `i686-w64-mingw32` for Win32 - `x86_64-w64-mingw32` for Win64 -- `x86_64-apple-darwin18` for macOS +- `x86_64-apple-darwin` for macOS - `arm-linux-gnueabihf` for Linux ARM 32 bit - `aarch64-linux-gnu` for Linux ARM 64 bit diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index a6978a91d3..4eda404621 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -20,3 +20,8 @@ darwin_OTOOL:=$(shell xcrun -f otool) darwin_NM:=$(shell xcrun -f nm) darwin_INSTALL_NAME_TOOL:=$(shell xcrun -f install_name_tool) darwin_native_toolchain= + +x86_64_darwin_CFLAGS += -arch x86_64 +x86_64_darwin_CXXFLAGS += -arch x86_64 +aarch64_darwin_CFLAGS += -arch arm64 +aarch64_darwin_CXXFLAGS += -arch arm64 diff --git a/depends/config.site.in b/depends/config.site.in index 5c3297e2ff..ef05bb1681 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -35,7 +35,6 @@ fi if test "@host_os@" = darwin; then BREW=no - PORT=no fi if test "@host_os@" = "mingw32"; then diff --git a/depends/hosts/mingw32.mk b/depends/hosts/mingw32.mk index 2080f80ce7..18045fcc25 100644 --- a/depends/hosts/mingw32.mk +++ b/depends/hosts/mingw32.mk @@ -1,4 +1,4 @@ -ifneq ($(shell which $(host)-g++-posix),) +ifneq ($(shell $(SHELL) $(.SHELLFLAGS) "command -v $(host)-g++-posix"),) mingw32_CXX := $(host)-g++-posix endif diff --git a/depends/packages/native_clang.mk b/depends/packages/native_clang.mk index 36adeb196d..943ecbda87 100644 --- a/depends/packages/native_clang.mk +++ b/depends/packages/native_clang.mk @@ -12,15 +12,10 @@ endef define $(package)_stage_cmds mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_version)/include && \ mkdir -p $($(package)_staging_prefix_dir)/bin && \ - mkdir -p $($(package)_staging_prefix_dir)/include && \ cp bin/clang $($(package)_staging_prefix_dir)/bin/ && \ cp -P bin/clang++ $($(package)_staging_prefix_dir)/bin/ && \ cp bin/dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil && \ cp bin/llvm-config $($(package)_staging_prefix_dir)/bin/ && \ cp lib/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \ - cp -rf lib/clang/$($(package)_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_version)/include/ -endef - -define $(package)_postprocess_cmds - rmdir include + cp -r lib/clang/$($(package)_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_version)/include/ endef diff --git a/depends/packages/native_ds_store.mk b/depends/packages/native_ds_store.mk index 44108925a4..51a95f48ef 100644 --- a/depends/packages/native_ds_store.mk +++ b/depends/packages/native_ds_store.mk @@ -1,6 +1,6 @@ package=native_ds_store $(package)_version=1.3.0 -$(package)_download_path=https://github.com/al45tair/ds_store/archive/ +$(package)_download_path=https://github.com/dmgbuild/ds_store/archive/ $(package)_file_name=v$($(package)_version).tar.gz $(package)_sha256_hash=76b3280cd4e19e5179defa23fb594a9dd32643b0c80d774bd3108361d94fb46d $(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages diff --git a/depends/packages/native_mac_alias.mk b/depends/packages/native_mac_alias.mk index 783f87ca7c..ddd631186e 100644 --- a/depends/packages/native_mac_alias.mk +++ b/depends/packages/native_mac_alias.mk @@ -1,6 +1,6 @@ package=native_mac_alias $(package)_version=2.2.0 -$(package)_download_path=https://github.com/al45tair/mac_alias/archive/ +$(package)_download_path=https://github.com/dmgbuild/mac_alias/archive/ $(package)_file_name=v$($(package)_version).tar.gz $(package)_sha256_hash=421e6d7586d1f155c7db3e7da01ca0dacc9649a509a253ad7077b70174426499 $(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 8639c90406..7e12066f22 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -174,6 +174,7 @@ $(package)_config_opts_mingw32 += "QMAKE_CFLAGS = '$($(package)_cflags) $($(pack $(package)_config_opts_mingw32 += "QMAKE_CXX = '$($(package)_cxx)'" $(package)_config_opts_mingw32 += "QMAKE_CXXFLAGS = '$($(package)_cxxflags) $($(package)_cppflags)'" $(package)_config_opts_mingw32 += "QMAKE_LFLAGS = '$($(package)_ldflags)'" +$(package)_config_opts_mingw32 += "QMAKE_LIB = '$($(package)_ar) rc'" $(package)_config_opts_mingw32 += -device-option CROSS_COMPILE="$(host)-" $(package)_config_opts_mingw32 += -pch $(package)_config_opts_mingw32 += -qt-freetype diff --git a/doc/build-unix.md b/doc/build-unix.md index bdac0dbc9c..a46bc35fbc 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -89,6 +89,10 @@ Build requirements: sudo apt-get install build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils libzip-dev libfreetype-dev +**For Ubuntu 18.04 gcc8 is also required** + + sudo apt-get install gcc-8 g++-8 + Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies: sudo apt-get install libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev libboost-iostreams-dev libcurl4-gnutls-dev diff --git a/src/Makefile.am b/src/Makefile.am index 78e30a2957..59d8e1cc09 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -207,7 +207,8 @@ GRIDCOIN_CORE_H = \ wallet/generated_type.h \ wallet/walletdb.h \ wallet/wallet.h \ - wallet/ismine.h + wallet/ismine.h \ + wallet/diagnose.h GRIDCOIN_CORE_CPP = addrdb.cpp \ addrman.cpp \ @@ -309,7 +310,8 @@ GRIDCOIN_CORE_CPP = addrdb.cpp \ wallet/rpcdump.cpp \ wallet/rpcwallet.cpp \ wallet/wallet.cpp \ - wallet/walletdb.cpp + wallet/walletdb.cpp \ + wallet/diagnose.cpp obj/build.h: FORCE diff --git a/src/addrman.h b/src/addrman.h index 8f2606cb38..45daafa02c 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -460,6 +460,7 @@ class CAddrMan //! Return the number of (unique) addresses in all tables. int size() { + LOCK(cs); // TODO: Cache this in an atomic to avoid this overhead return vRandom.size(); } @@ -476,57 +477,49 @@ class CAddrMan #endif } - // Add a single address. + //! Add a single address. bool Add(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty = 0) { + LOCK(cs); bool fRet = false; - { - LOCK(cs); - Check(); - fRet |= Add_(addr, source, nTimePenalty); - Check(); - } + Check(); + fRet |= Add_(addr, source, nTimePenalty); + Check(); if (fRet) LogPrint(BCLog::LogFlags::ADDRMAN,"Added %s from %s: %i tried, %i new", addr.ToStringIPPort(), source.ToString(), nTried, nNew); return fRet; } - // Add multiple addresses. + //! Add multiple addresses. bool Add(const std::vector &vAddr, const CNetAddr& source, int64_t nTimePenalty = 0) { + LOCK(cs); int nAdd = 0; - { - LOCK(cs); - Check(); - for (std::vector::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) - nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0; - Check(); - } + Check(); + for (std::vector::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) + nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0; + Check(); if (nAdd) LogPrint(BCLog::LogFlags::ADDRMAN,"Added %i addresses from %s: %i tried, %i new", nAdd, source.ToString(), nTried, nNew); return nAdd > 0; } - // Mark an entry as accessible. + //! Mark an entry as accessible. void Good(const CService &addr, int64_t nTime = GetAdjustedTime()) { - { - LOCK(cs); - Check(); - Good_(addr, nTime); - Check(); - } + LOCK(cs); + Check(); + Good_(addr, nTime); + Check(); } - // Mark an entry as connection attempted to. + //! Mark an entry as connection attempted to. void Attempt(const CService &addr, int64_t nTime = GetAdjustedTime()) { - { - LOCK(cs); - Check(); - Attempt_(addr, nTime); - Check(); - } + LOCK(cs); + Check(); + Attempt_(addr, nTime); + Check(); } //! Choose an address to connect to. @@ -555,15 +548,13 @@ class CAddrMan return vAddr; } - // Mark an entry as currently-connected-to. + //! Mark an entry as currently-connected-to. void Connected(const CService &addr, int64_t nTime = GetAdjustedTime()) { - { - LOCK(cs); - Check(); - Connected_(addr, nTime); - Check(); - } + LOCK(cs); + Check(); + Connected_(addr, nTime); + Check(); } }; diff --git a/src/alert.cpp b/src/alert.cpp index e8d4aaacc2..0ee441818a 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -137,7 +137,7 @@ bool CAlert::RelayTo(CNode* pnode) const AppliesToMe() || GetAdjustedTime() < nRelayUntil) { - pnode->PushMessage("alert", *this); + pnode->PushMessage(NetMsgType::ALERT, *this); return true; } } @@ -258,6 +258,7 @@ bool CAlert::ProcessAlert(bool fThread) if(AppliesToMe()) { uiInterface.NotifyAlertChanged(GetHash(), CT_NEW); + #if HAVE_SYSTEM std::string strCmd = gArgs.GetArg("-alertnotify", ""); if (!strCmd.empty()) { @@ -282,6 +283,7 @@ bool CAlert::ProcessAlert(bool fThread) else runCommand(strCmd); } + #endif } } diff --git a/src/fs.cpp b/src/fs.cpp index e592e3aef4..d75f0771c1 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -123,7 +123,7 @@ bool FileLock::TryLock() if (hFile == INVALID_HANDLE_VALUE) { return false; } - _OVERLAPPED overlapped = {0}; + _OVERLAPPED overlapped = {}; if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, std::numeric_limits::max(), std::numeric_limits::max(), &overlapped)) { reason = GetErrorReason(); return false; diff --git a/src/gridcoin/accrual/snapshot.h b/src/gridcoin/accrual/snapshot.h index e697fd2a57..5b7ad3fe4a 100644 --- a/src/gridcoin/accrual/snapshot.h +++ b/src/gridcoin/accrual/snapshot.h @@ -867,7 +867,15 @@ class AccrualSnapshotRegistry CURRENT_VERSION); if (!registry_file.IsNull()) { - Unserialize(registry_file); + try { + Unserialize(registry_file); + } catch (const std::ios_base::failure& e) { + if (feof(registry_file.Get())) { + throw SnapshotStateError("unexpected eof while loading the registry."); + } + + throw; + } } else { m_entries.clear(); } diff --git a/src/gridcoin/claim.h b/src/gridcoin/claim.h index 36021597f7..0c822fcdab 100644 --- a/src/gridcoin/claim.h +++ b/src/gridcoin/claim.h @@ -193,13 +193,6 @@ class Claim : public IContractPayload //! std::map m_mrc_tx_map; - //! - //! \brief This represents the fees taken from the MRC research subsidies that are awarded to the staker. - //! This must be tracked because this value is added to coinstake award for the staker and must be - //! included in the claim validation. - //! - CAmount m_mrc_fees_to_staker; - //! //! \brief Initialize an empty, invalid reward claim object. //! diff --git a/src/gridcoin/mrc.cpp b/src/gridcoin/mrc.cpp index bd82382aaa..8abf739e98 100644 --- a/src/gridcoin/mrc.cpp +++ b/src/gridcoin/mrc.cpp @@ -100,7 +100,7 @@ CAmount MRC::ComputeMRCFee() const if (!cpid) return fee; const ResearchAccount& account = Tally::GetAccount(*cpid); - const int64_t last_reward_time = account.LastRewardTime(); + int64_t last_reward_time = account.LastRewardTime(); // Get the block index of the head of the chain at the time the MRC was filled out. auto block_index_element = mapBlockIndex.find(m_last_block_hash); @@ -112,10 +112,61 @@ CAmount MRC::ComputeMRCFee() const int64_t payment_time = prev_block_pindex->nTime; + // This is for ComputeMRCFee computations on historical MRC contracts, where actual payments have already occurred, + // in which case the last_reward_time gotten from the accrual system above will not be the right context. In this + // case we need to go through the block index starting at prev_block_index backwards and manually search for the + // last reward. Unfortunately this is very expensive, but it is really only used in the getmrcinfo rpc call. + if (payment_time <= last_reward_time) { + Beacon_ptr beacon = GetBeaconRegistry().TryActive(*cpid, payment_time); + if (!beacon) return fee; + + CBlockIndex* last_payment_index = prev_block_pindex; + bool found_last_payment = false; + + // Find the last payment, whether normal stake or MRC. + for (; last_payment_index; last_payment_index = last_payment_index->pprev) { + + // Historical normal stake payment + if (last_payment_index->m_researcher && last_payment_index->m_researcher->m_cpid == *cpid) { + found_last_payment = true; + last_reward_time = last_payment_index->nTime; + break; + } + + // Historical MRC payment + for (const auto& mrc_context : last_payment_index->m_mrc_researchers) { + if (mrc_context->m_cpid == *cpid) { + found_last_payment = true; + last_reward_time = last_payment_index->pprev->nTime; + break; + } + } + + // Last normal or MRC payment found. We need this because we have to break out of two levels + // for historical MRC payments. + if (found_last_payment) break; + } + + // We have gone through the whole chain looking for past payments and none have been found, so + // the last_reward_time is set to the beacon time for the beacon that predates the mrc time. + if (!found_last_payment) { + // If the beacon was renewed and the time stamp of this beacon is greater than + // the time of the last_payment_index, then walk the beacon chain back to the previous beacon. + while (beacon->m_timestamp > prev_block_pindex->nTime && beacon->Renewed()) { + beacon = GetBeaconRegistry().GetBeaconDB().find(beacon->m_prev_beacon_hash)->second; + } + + last_reward_time = beacon->m_timestamp; + } + } + int64_t mrc_payment_interval = 0; - // If there is a last reward recorded in the accrual system, then the payment interval for the MRC request starts - // there and goes to the head of the chain for the MRC in the mempool. If not, we use the age of the beacon. + // If there is a last reward recorded in the accrual system, or, in the historical context, the history walk + // has determined a last payment or beacon root datetime, then the payment interval for the MRC request starts + // there and goes to the paytime time in context, which is for non-historical MRC's the head of the chain for + // the MRC in the mempool, and for historical MRC's the time of the prev_block_index. If the last_reward_time is + // zero, we use the age of the current beacon. if (!last_reward_time) { const BeaconOption beacon = GetBeaconRegistry().Try(*cpid);; diff --git a/src/gridcoin/scraper/scraper.cpp b/src/gridcoin/scraper/scraper.cpp index 50fdffd0ea..6ad6ddf9f3 100755 --- a/src/gridcoin/scraper/scraper.cpp +++ b/src/gridcoin/scraper/scraper.cpp @@ -1289,7 +1289,7 @@ void ApplyCache(const std::string& key, T& result) { unsigned int out = 0; - if (!ParseUInt(entry.value, &out)) + if (!ParseUInt32(entry.value, &out)) { throw std::invalid_argument("Argument is not parseable as an unsigned int."); } @@ -3354,10 +3354,10 @@ bool LoadScraperFileManifest(const fs::path& file) nhash.SetHex(vline[0].c_str()); LoadEntry.hash = nhash; - // We will use the ParseUInt from strencodings to avoid the locale specific stoi. + // We will use the ParseUInt32 from strencodings to avoid the locale specific stoi. unsigned int parsed_current = 0; - if (!ParseUInt(vline[1], &parsed_current)) + if (!ParseUInt32(vline[1], &parsed_current)) { _log(logattribute::ERR, __func__, "The \"current\" field not parsed correctly for a manifest entry. Skipping."); continue; @@ -3380,7 +3380,7 @@ bool LoadScraperFileManifest(const fs::path& file) // are to be maintained, such as team and host files. unsigned int parsed_exclude = 0; - if (!ParseUInt(vline[5], &parsed_exclude)) + if (!ParseUInt32(vline[5], &parsed_exclude)) { // This shouldn't happen given the conditional above, but to be thorough... _log(logattribute::ERR, __func__, "The \"excludefromcsmanifest\" field not parsed correctly for a manifest " diff --git a/src/gridcoin/scraper/scraper_net.cpp b/src/gridcoin/scraper/scraper_net.cpp index 7e06eef98b..43f5dd2df5 100644 --- a/src/gridcoin/scraper/scraper_net.cpp +++ b/src/gridcoin/scraper/scraper_net.cpp @@ -184,7 +184,7 @@ bool CSplitBlob::SendPartTo(CNode* pto, const uint256& hash) EXCLUSIVE_LOCKS_REQ { if (ipart->second.present()) { - pto->PushMessage("part",ipart->second.getReader()); + pto->PushMessage(NetMsgType::PART,ipart->second.getReader()); return true; } } @@ -275,7 +275,7 @@ EXCLUSIVE_LOCKS_REQUIRED(CSplitBlob::cs_mapParts) { LOCK(manifest->cs_manifest); - pto->PushMessage("scraperindex", *manifest); + pto->PushMessage(NetMsgType::SCRAPERINDEX, *manifest); return true; } diff --git a/src/gridcoin/staking/difficulty.h b/src/gridcoin/staking/difficulty.h index 231a3153fc..a002d8ed90 100644 --- a/src/gridcoin/staking/difficulty.h +++ b/src/gridcoin/staking/difficulty.h @@ -8,6 +8,7 @@ class CBlockIndex; class CWallet; +#include namespace GRC { // Note that dDiff cannot be = 0 normally. This is set as default because you can't specify the output of diff --git a/src/gridcoin/superblock.cpp b/src/gridcoin/superblock.cpp index eeda6f40db..5e557a08c0 100644 --- a/src/gridcoin/superblock.cpp +++ b/src/gridcoin/superblock.cpp @@ -352,7 +352,7 @@ class LegacySuperblockParser , m_averages(ExtractXML(packed, "", "")) , m_zero_mags(0) { - if (!ParseInt(ExtractXML(packed, "", ""), &m_zero_mags)) { + if (!ParseInt32(ExtractXML(packed, "", ""), &m_zero_mags)) { error("%s: Failed to parse zero mag CPIDs.", __func__); } } diff --git a/src/gridcoin/upgrade.cpp b/src/gridcoin/upgrade.cpp index ce70755902..5d706210ad 100644 --- a/src/gridcoin/upgrade.cpp +++ b/src/gridcoin/upgrade.cpp @@ -130,7 +130,7 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial { int github_version = 0; - if (!ParseInt(GithubVersion[x], &github_version)) + if (!ParseInt32(GithubVersion[x], &github_version)) { throw std::invalid_argument("Failed to parse GitHub version from official GitHub project repo."); } diff --git a/src/gridcoin/voting/result.cpp b/src/gridcoin/voting/result.cpp index 0f26b83c0f..d13afa3964 100644 --- a/src/gridcoin/voting/result.cpp +++ b/src/gridcoin/voting/result.cpp @@ -13,6 +13,8 @@ #include "gridcoin/researcher.h" #include "txdb.h" #include "util/reverse_iterator.h" +#include "wallet/wallet.h" +#include "init.h" #include #include @@ -100,6 +102,16 @@ class VoteCandidate return m_payload.As(); } + //! + //! \brief returns IsMine flag on transaction containing vote contract + //! + isminetype IsMine() const + { + LOCK(pwalletMain->cs_wallet); + + return pwalletMain->IsMine(m_tx); + } + //! //! \brief Serialize a vote for claim signing and verification. //! @@ -162,6 +174,7 @@ class VoteResolver VoteDetail detail; detail.m_amount = Resolve(vote.m_claim.m_balance_claim, message); + detail.m_ismine = candidate.IsMine(); if (m_poll.IncludesMagnitudeWeight()) { detail.m_mining_id = vote.m_claim.m_magnitude_claim.m_mining_id; @@ -1112,6 +1125,8 @@ PollResult::PollResult(Poll poll) , m_vote_percent_avw() , m_poll_results_validated() , m_finished(m_poll.Expired(GetAdjustedTime())) + , m_self_voted(false) + , m_self_vote_detail() { m_responses.resize(m_poll.Choices().size()); } @@ -1174,6 +1189,11 @@ void PollResult::TallyVote(VoteDetail detail) return; } + if (detail.m_ismine != ISMINE_NO) { + m_self_voted = true; + m_self_vote_detail = detail; + } + for (const auto& response_pair : detail.m_responses) { const uint8_t response_offset = response_pair.first; const Weight response_weight = response_pair.second; @@ -1198,7 +1218,7 @@ ResponseDetail::ResponseDetail() : m_weight(0), m_votes(0) // Class: PollResult::VoteDetail // ----------------------------------------------------------------------------- -VoteDetail::VoteDetail() : m_amount(0), m_magnitude(Magnitude::Zero()) +VoteDetail::VoteDetail() : m_amount(0), m_magnitude(Magnitude::Zero()), m_ismine(ISMINE_NO) { } @@ -1206,3 +1226,5 @@ bool VoteDetail::Empty() const { return m_amount == 0 && m_magnitude == 0; } + +VoteDetail& VoteDetail::operator=(const VoteDetail& b) = default; diff --git a/src/gridcoin/voting/result.h b/src/gridcoin/voting/result.h index 16705b10b5..758a7bbcf9 100644 --- a/src/gridcoin/voting/result.h +++ b/src/gridcoin/voting/result.h @@ -5,6 +5,7 @@ #ifndef GRIDCOIN_VOTING_RESULT_H #define GRIDCOIN_VOTING_RESULT_H +#include "wallet/ismine.h" #include "gridcoin/cpid.h" #include "gridcoin/magnitude.h" #include "gridcoin/voting/fwd.h" @@ -57,6 +58,7 @@ class PollResult Weight m_amount; //!< Total balance resolved for the vote. MiningId m_mining_id; //!< CPID for the vote, if any. Magnitude m_magnitude; //!< Magnitude resolved for the vote. + isminetype m_ismine; //!< True if the vote is from the wallet holder. //! //! \brief The selected poll choice offsets and the associated voting @@ -75,6 +77,8 @@ class PollResult //! \return \c true if the vote claims no balance or magnitude weight. //! bool Empty() const; + + VoteDetail& operator=(const VoteDetail& b); }; const Poll m_poll; //!< The poll associated with the result. @@ -85,6 +89,8 @@ class PollResult std::optional m_vote_percent_avw; //!< Vote weight percent of AVW. std::optional m_poll_results_validated; //!< Whether the poll's AVW is >= the minimum AVW for the poll. bool m_finished; //!< Whether the poll finished as of this result. + bool m_self_voted; //!< Whether the wallet holder voted. + VoteDetail m_self_vote_detail; //!< The vote detail from the wallet holder's (last) vote //! //! \brief The aggregated voting weight tallied for each poll choice. diff --git a/src/gridcoinresearchd.cpp b/src/gridcoinresearchd.cpp index 65ef60ce4f..7f33c73e48 100644 --- a/src/gridcoinresearchd.cpp +++ b/src/gridcoinresearchd.cpp @@ -196,6 +196,16 @@ bool AppInit(int argc, char* argv[]) return !CommandLineRPC(argc, argv); } + if (gArgs.GetBoolArg("-printtoconsole", false) && gArgs.GetBoolArg("-daemon", DEFAULT_DAEMON)) { + return InitError("-printtoconsole && -daemon cannot be specified at the same time,\n" + "because Gridcoin follows proper daemonization and disconnects the\n" + "console when the process is forked. This is consistent with Bitcoin\n" + "Core. Please see https://github.com/bitcoin/bitcoin/issues/10132.\n" + "If you are not specifying -daemon as a startup parameter, but only\n" + "-printtoconsole, and you are getting this error, please check the\n" + "gridcoinresearch.conf and comment out daemon=1, or use -nodaemon."); + } + // -server defaults to true for gridcoinresearchd but not for the GUI so do this here gArgs.SoftSetBoolArg("-server", true); // Initialize logging as early as possible. @@ -287,7 +297,7 @@ bool AppInit(int argc, char* argv[]) if (token) { // Success exit(EXIT_SUCCESS); } else { // fRet = false or token read error (premature exit). - tfm::format(std::cerr, "Error during initializaton - check debug.log for details\n"); + tfm::format(std::cerr, "Error during initialization - check debug.log for details\n"); exit(EXIT_FAILURE); } } diff --git a/src/hash.cpp b/src/hash.cpp index 822bd4c880..b05803efae 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -16,7 +16,7 @@ inline uint32_t ROTL32(uint32_t x, int8_t r) unsigned int MurmurHash3(unsigned int nHashSeed, Span vDataToHash) { - // The following is MurmurHash3 (x86_32), see https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp + // The following is MurmurHash3 (x86_32), see https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp uint32_t h1 = nHashSeed; const uint32_t c1 = 0xcc9e2d51; const uint32_t c2 = 0x1b873593; diff --git a/src/init.cpp b/src/init.cpp index 92d2c7a7e2..c8183fb929 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -337,17 +337,21 @@ void SetupServerArgs() argsman.AddArg("-mininput=", "When creating transactions, ignore inputs with value less than this (default: 0.01)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-testnet", "Use the test network", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); +#if HAVE_SYSTEM argsman.AddArg("-blocknotify=", "Execute command when the best block changes (%s in cmd is replaced by block hash)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-walletnotify=", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); +#endif argsman.AddArg("-confchange", "Require confirmations for change (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-enforcecanonical", "Enforce transaction scripts to use canonical PUSH operators (default: 1)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); +#if HAVE_SYSTEM argsman.AddArg("-alertnotify=", "Execute command when a relevant alert is received or we see a really long fork" " (%s in cmd is replaced by message)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); +#endif argsman.AddArg("-blockminsize=", "Set minimum block size in bytes (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-blockmaxsize=", strprintf("Set maximum block size in bytes (default: %u)", MAX_BLOCK_SIZE_GEN/2), @@ -575,8 +579,13 @@ void SetupServerArgs() ArgsManager::ALLOW_ANY, OptionsCategory::RPC); #if HAVE_DECL_FORK - argsman.AddArg("-daemon", strprintf("Run in the background as a daemon and accept commands (default: %d)", DEFAULT_DAEMON), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-daemonwait", strprintf("Wait for initialization to be finished before exiting. This implies -daemon (default: %d)", DEFAULT_DAEMONWAIT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + argsman.AddArg("-daemon", + strprintf("Run in the background as a daemon and accept commands (default: %d)", DEFAULT_DAEMON), + ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + argsman.AddArg("-daemonwait", + strprintf("Wait for initialization to be finished before exiting. " + "This implies -daemon (default: %d)", DEFAULT_DAEMONWAIT), + ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); #else hidden_args.emplace_back("-daemon"); hidden_args.emplace_back("-daemonwait"); diff --git a/src/keystore.h b/src/keystore.h index d7a102fb15..c360096078 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -124,7 +124,9 @@ class CCryptoKeyStore : public CBasicKeyStore bool Unlock(const CKeyingMaterial& vMasterKeyIn); public: - CCryptoKeyStore() : fUseCrypto(false) + CCryptoKeyStore() + : fUseCrypto(false) + , fDecryptionThoroughlyChecked(false) { } diff --git a/src/main.cpp b/src/main.cpp index daeaaaa4c8..abfdac9d13 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1277,12 +1277,14 @@ bool SetBestChain(CTxDB& txdb, CBlock &blockNew, CBlockIndex* pindexNew) EXCLUSI else LogPrintf("{SBC} new best {%s %d} ; ",hashBestChain.ToString(), nBestHeight); + #if HAVE_SYSTEM std::string strCmd = gArgs.GetArg("-blocknotify", ""); if (!fIsInitialDownload && !strCmd.empty()) { boost::replace_all(strCmd, "%s", hashBestChain.GetHex()); boost::thread t(runCommand, strCmd); // thread runs free } + #endif uiInterface.NotifyBlocksChanged( fIsInitialDownload, @@ -1945,7 +1947,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { LogPrint(BCLog::LogFlags::NOISY, "received: %s from %s (%" PRIszu " bytes)", strCommand, pfrom->addrName, vRecv.size()); - if (strCommand == "aries") + if (strCommand == NetMsgType::ARIES || strCommand == NetMsgType::VERSION) { // Each connection can only send one version message if (pfrom->nVersion != 0) @@ -2061,7 +2063,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, AddTimeData(pfrom->addr, nOffsetSample); // Change version - pfrom->PushMessage("verack"); + pfrom->PushMessage(NetMsgType::VERACK); pfrom->ssSend.SetVersion(min(pfrom->nVersion, PROTOCOL_VERSION)); @@ -2074,7 +2076,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // Get recent addresses - pfrom->PushMessage("getaddr"); + pfrom->PushMessage(NetMsgType::GETADDR); pfrom->fGetAddr = true; addrman.Good(pfrom->addr); } @@ -2118,13 +2120,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->fDisconnect=true; return false; } - else if (strCommand == "verack") + else if (strCommand == NetMsgType::VERACK) { pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION)); } - else if (strCommand == "gridaddr") + else if (strCommand == NetMsgType::GRIDADDR || strCommand == NetMsgType::ADDR) { - //addr->gridaddr vector vAddr; vRecv >> vAddr; @@ -2188,7 +2189,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->fDisconnect = true; } - else if (strCommand == "inv") + else if (strCommand == NetMsgType::INV) { vector vInv; vRecv >> vInv; @@ -2261,7 +2262,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } - else if (strCommand == "getdata") + else if (strCommand == NetMsgType::GETDATA) { vector vInv; vRecv >> vInv; @@ -2295,7 +2296,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBlock block; ReadBlockFromDisk(block, mi->second, Params().GetConsensus()); - pfrom->PushMessage("encrypt", block); + pfrom->PushMessage(NetMsgType::ENCRYPT, block); // Trigger them to send a getblocks request for the next batch of inventory if (inv.hash == pfrom->hashContinue) @@ -2305,7 +2306,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // wait for other stuff first. vector vInv; vInv.push_back(CInv(MSG_BLOCK, hashBestChain)); - pfrom->PushMessage("inv", vInv); + pfrom->PushMessage(NetMsgType::INV, vInv); pfrom->hashContinue.SetNull(); } } @@ -2328,7 +2329,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << tx; - pfrom->PushMessage("tx", ss); + pfrom->PushMessage(NetMsgType::TX, ss); } } else if(!pushed && inv.type == MSG_PART) { @@ -2393,7 +2394,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } - else if (strCommand == "getblocks") + else if (strCommand == NetMsgType::GETBLOCKS) { CBlockLocator locator; uint256 hashStop; @@ -2432,7 +2433,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } } - else if (strCommand == "getheaders") + else if (strCommand == NetMsgType::GETHEADERS) { CBlockLocator locator; uint256 hashStop; @@ -2466,9 +2467,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop) break; } - pfrom->PushMessage("headers", vHeaders); + pfrom->PushMessage(NetMsgType::HEADERS, vHeaders); } - else if (strCommand == "tx") + else if (strCommand == NetMsgType::TX) { vector vWorkQueue; vector vEraseQueue; @@ -2534,7 +2535,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } - else if (strCommand == "encrypt") + else if (strCommand == NetMsgType::ENCRYPT || strCommand == NetMsgType::BLOCK) { //Response from getblocks, message = block @@ -2565,7 +2566,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } - else if (strCommand == "getaddr") + else if (strCommand == NetMsgType::GETADDR) { // Don't return addresses older than nCutOff timestamp int64_t nCutOff = GetAdjustedTime() - (nNodeLifespan * 24 * 60 * 60); @@ -2577,7 +2578,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } - else if (strCommand == "mempool") + else if (strCommand == NetMsgType::MEMPOOL) { LOCK(cs_main); @@ -2591,9 +2592,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, break; } if (vInv.size() > 0) - pfrom->PushMessage("inv", vInv); + pfrom->PushMessage(NetMsgType::INV, vInv); } - else if (strCommand == "ping") + else if (strCommand == NetMsgType::PING) { uint64_t nonce = 0; vRecv >> nonce; @@ -2609,9 +2610,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // it, if the remote node sends a ping once per second and this node takes 5 // seconds to respond to each, the 5th ping the remote sends would appear to // return very quickly. - pfrom->PushMessage("pong", nonce); + pfrom->PushMessage(NetMsgType::PONG, nonce); } - else if (strCommand == "pong") + else if (strCommand == NetMsgType::PONG) { int64_t pingUsecEnd = GetTimeMicros(); uint64_t nonce = 0; @@ -2666,7 +2667,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->nPingNonceSent = 0; } } - else if (strCommand == "alert") + else if (strCommand == NetMsgType::ALERT) { CAlert alert; vRecv >> alert; @@ -2696,11 +2697,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } - else if (strCommand == "scraperindex") + else if (strCommand == NetMsgType::SCRAPERINDEX) { CScraperManifest::RecvManifest(pfrom, vRecv); } - else if (strCommand == "part") + else if (strCommand == NetMsgType::PART) { CSplitBlob::RecvPart(pfrom, vRecv); } @@ -2722,7 +2723,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Update the last seen time for this node's address if (pfrom->fNetworkNode) - if (strCommand == "aries" || strCommand == "gridaddr" || strCommand == "inv" || strCommand == "getdata" || strCommand == "ping") + if (strCommand == NetMsgType::ARIES || strCommand == NetMsgType::GRIDADDR || strCommand == NetMsgType::INV || strCommand == NetMsgType::GETDATA || strCommand == NetMsgType::PING || strCommand == NetMsgType::VERSION || strCommand == NetMsgType::ADDR) AddressCurrentlyConnected(pfrom->addr); return true; @@ -2890,7 +2891,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) pto->nPingUsecStart = GetTimeMicros(); pto->nPingNonceSent = nonce; - pto->PushMessage("ping", nonce); + pto->PushMessage(NetMsgType::PING, nonce); } // Resend wallet transactions that haven't gotten in a block yet @@ -2928,14 +2929,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // receiver rejects addr messages larger than 1000 if (vAddr.size() >= 1000) { - pto->PushMessage("gridaddr", vAddr); + pto->PushMessage(NetMsgType::GRIDADDR, vAddr); vAddr.clear(); } } } pto->vAddrToSend.clear(); if (!vAddr.empty()) - pto->PushMessage("gridaddr", vAddr); + pto->PushMessage(NetMsgType::GRIDADDR, vAddr); } @@ -2986,7 +2987,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) vInv.push_back(inv); if (vInv.size() >= 1000) { - pto->PushMessage("inv", vInv); + pto->PushMessage(NetMsgType::INV, vInv); vInv.clear(); } } @@ -2994,7 +2995,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) pto->vInventoryToSend = vInvWait; } if (!vInv.empty()) - pto->PushMessage("inv", vInv); + pto->PushMessage(NetMsgType::INV, vInv); // @@ -3034,7 +3035,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) vGetData.push_back(inv); if (vGetData.size() >= 1000) { - pto->PushMessage("getdata", vGetData); + pto->PushMessage(NetMsgType::GETDATA, vGetData); vGetData.clear(); } @@ -3043,7 +3044,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) pto->mapAskFor.erase(pto->mapAskFor.begin()); } if (!vGetData.empty()) - pto->PushMessage("getdata", vGetData); + pto->PushMessage(NetMsgType::GETDATA, vGetData); return true; } @@ -3096,3 +3097,45 @@ GRC::MintSummary CBlock::GetMint() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) return mint; } +GRC::MRCFees CBlock::GetMRCFees() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) +{ + GRC::MRCFees mrc_fees; + unsigned int mrc_output_limit = GetMRCOutputLimit(nVersion, false); + + // Return zeroes for mrc fees if MRC not allowed. (This could have also been done + // by block version check, but this is more correct.) + if (!mrc_output_limit) { + return mrc_fees; + } + + Fraction foundation_fee_fraction = FoundationSideStakeAllocation(); + + const GRC::Claim claim = GetClaim(); + + CAmount mrc_total_fees = 0; + + // This is similar to the code in CheckMRCRewards in the Validator class, but with the validation removed because + // the block has already been validated. We also only need the MRC fee calculation portion. + for (const auto& tx: vtx) { + for (const auto& mrc : claim.m_mrc_tx_map) { + if (mrc.second == tx.GetHash() && !tx.GetContracts().empty()) { + // An MRC contract must be the first and only contract on a transaction by protocol. + GRC::Contract contract = tx.GetContracts()[0]; + + if (contract.m_type != GRC::ContractType::MRC) continue; + + GRC::MRC mrc = contract.CopyPayloadAs(); + + mrc_fees.m_mrc_minimum_calc_fees += mrc.ComputeMRCFee(); + + mrc_total_fees += mrc.m_fee; + mrc_fees.m_mrc_foundation_fees += mrc.m_fee * foundation_fee_fraction.GetNumerator() + / foundation_fee_fraction.GetDenominator(); + } + } + } + + mrc_fees.m_mrc_staker_fees = mrc_total_fees - mrc_fees.m_mrc_foundation_fees; + + return mrc_fees; +} diff --git a/src/main.h b/src/main.h index 3f09326b9a..94ffc1ac55 100644 --- a/src/main.h +++ b/src/main.h @@ -310,6 +310,17 @@ class CBlockHeader }; namespace GRC { +//! +//! \brief A report that contains the mrc fees paid in a block. +//! +class MRCFees +{ +public: + CAmount m_mrc_foundation_fees = 0; //!< mrc fees to the foundation + CAmount m_mrc_staker_fees = 0; //!< mrc fees to the staker + CAmount m_mrc_minimum_calc_fees = 0; //!< minimum calculated mrc fees for validation +}; + //! //! \brief A report that contains the calculated subsidy claimed in a block. //! Produced by the CBlock::GetMint() method. @@ -393,6 +404,7 @@ class CBlock : public CBlockHeader GRC::SuperblockPtr GetSuperblock() const; GRC::SuperblockPtr GetSuperblock(const CBlockIndex* const pindex) const; GRC::MintSummary GetMint() const; + GRC::MRCFees GetMRCFees() const; // entropy bit for stake modifier if chosen by modifier unsigned int GetStakeEntropyBit() const diff --git a/src/miner.cpp b/src/miner.cpp index f7c1eaf0a1..118a968987 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -262,9 +262,6 @@ bool CreateMRCRewards(CBlock &blocknew, std::map #endif +namespace NetMsgType { + const char *VERSION="version"; + const char *VERACK="verack"; + const char *ADDR="addr"; + const char *INV="inv"; + const char *GETDATA="getdata"; + const char *GETBLOCKS="getblocks"; + const char *GETHEADERS="getheaders"; + const char *TX="tx"; + const char *HEADERS="headers"; + const char *BLOCK="block"; + const char *GETADDR="getaddr"; + const char *MEMPOOL="mempool"; + const char *PING="ping"; + const char *PONG="pong"; + const char *ALERT="alert"; + + // Gridcoin aliases (to be removed) + const char *ENCRYPT="encrypt"; + const char *GRIDADDR="gridaddr"; + const char *ARIES="aries"; + + // Gridcoin specific + const char *SCRAPERINDEX="scraperindex"; + const char *PART="part"; +} + static const char* ppszTypeName[] = { - "ERROR", - "tx", - "block", - "part", - "scraperindex", + "ERROR", // Should never occur + NetMsgType::TX, + NetMsgType::BLOCK, + NetMsgType::PART, + NetMsgType::SCRAPERINDEX, +}; + +/** All known message types. Keep this in the same order as the list of + * messages above and in protocol.h. + */ +const static std::string allNetMessageTypes[] = { + NetMsgType::VERSION, + NetMsgType::VERACK, + NetMsgType::ADDR, + NetMsgType::INV, + NetMsgType::GETDATA, + NetMsgType::GETBLOCKS, + NetMsgType::GETHEADERS, + NetMsgType::TX, + NetMsgType::HEADERS, + NetMsgType::BLOCK, + NetMsgType::GETADDR, + NetMsgType::MEMPOOL, + NetMsgType::PING, + NetMsgType::PONG, + NetMsgType::ALERT, + + // Gridcoin aliases (to be removed) + NetMsgType::ENCRYPT, + NetMsgType::GRIDADDR, + NetMsgType::ARIES, + + // Gridcoin specific + NetMsgType::SCRAPERINDEX, + NetMsgType::PART, }; +const static std::vector allNetMessageTypesVec(std::begin(allNetMessageTypes), std::end(allNetMessageTypes)); + CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn) { memcpy(pchMessageStart, Params().MessageStart(), CMessageHeader::MESSAGE_START_SIZE); @@ -122,3 +181,7 @@ void CInv::print() const LogPrintf("CInv(%s)", ToString()); } +const std::vector &getAllNetMessageTypes() +{ + return allNetMessageTypesVec; +} \ No newline at end of file diff --git a/src/protocol.h b/src/protocol.h index 00485c2955..b3fe809637 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -117,5 +117,146 @@ class CInv uint256 hash; }; +/** + * Bitcoin protocol message types. When adding new message types, don't forget + * to update allNetMessageTypes in protocol.cpp. + */ +namespace NetMsgType { + + /** + * The version message provides information about the transmitting node to the + * receiving node at the beginning of a connection. + * @see https://bitcoin.org/en/developer-reference#version + */ + extern const char *VERSION; + + /** + * The verack message acknowledges a previously-received version message, + * informing the connecting node that it can begin to send other messages. + * @see https://bitcoin.org/en/developer-reference#verack + */ + extern const char *VERACK; + + /** + * The addr (IP address) message relays connection information for peers on the + * network. + * @see https://bitcoin.org/en/developer-reference#addr + */ + extern const char *ADDR; + + /** + * The inv message (inventory message) transmits one or more inventories of + * objects known to the transmitting peer. + * @see https://bitcoin.org/en/developer-reference#inv + */ + extern const char *INV; + + /** + * The getdata message requests one or more data objects from another node. + * @see https://bitcoin.org/en/developer-reference#getdata + */ + extern const char *GETDATA; + + /** + * The getblocks message requests an inv message that provides block header + * hashes starting from a particular point in the block chain. + * @see https://bitcoin.org/en/developer-reference#getblocks + */ + extern const char *GETBLOCKS; + + /** + * The getheaders message requests a headers message that provides block + * headers starting from a particular point in the block chain. + * @since protocol version 31800. + * @see https://bitcoin.org/en/developer-reference#getheaders + */ + extern const char *GETHEADERS; + + /** + * The tx message transmits a single transaction. + * @see https://bitcoin.org/en/developer-reference#tx + */ + extern const char *TX; + + /** + * The headers message sends one or more block headers to a node which + * previously requested certain headers with a getheaders message. + * @since protocol version 31800. + * @see https://bitcoin.org/en/developer-reference#headers + */ + extern const char *HEADERS; + + /** + * The block message transmits a single serialized block. + * @see https://bitcoin.org/en/developer-reference#block + */ + extern const char *BLOCK; + + /** + * The ping message is sent periodically to help confirm that the receiving + * peer is still connected. + * @see https://bitcoin.org/en/developer-reference#ping + */ + extern const char *PING; + + /** + * The pong message replies to a ping message, proving to the pinging node that + * the ponging node is still alive. + * @since protocol version 60001 as described by BIP31. + * @see https://bitcoin.org/en/developer-reference#pong + */ + extern const char *PONG; + + /** + * The alert message warns nodes of problems that may affect them or the rest + * of the network. + * @since protocol version 311. + * @see https://bitcoin.org/en/developer-reference#alert + */ + extern const char *ALERT; + + /** + * The getaddr message requests an addr message from the receiving node, + * preferably one with lots of IP addresses of other receiving nodes. + * @see https://bitcoin.org/en/developer-reference#getaddr + */ + extern const char *GETADDR; + + /** + * The mempool message requests the TXIDs of transactions that the receiving + * node has verified as valid but which have not yet appeared in a block. + * @since protocol version 60002. + * @see https://bitcoin.org/en/developer-reference#mempool + */ + extern const char *MEMPOOL; + + /** + * Gridcoin alias for block message (will be removed) + */ + extern const char *ENCRYPT; + + /** + * Gridcoin alias for addr message (will be removed) + */ + extern const char *GRIDADDR; + + /** + * Gridcoin specific message + */ + extern const char *SCRAPERINDEX; + + /** + * Gridcoin specific message + */ + extern const char *PART; + + /** + * Gridcoin alias for version message (will be removed) + */ + extern const char *ARIES; +}; +/* Get a vector of all valid message types (see above) */ +const std::vector &getAllNetMessageTypes(); + #endif // BITCOIN_PROTOCOL_H diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 3dafa5e2cf..bb6d967c42 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -38,12 +38,17 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "Cannot obtain a lock on data directory %s. %s is probably already running."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Check that BOINC is installed and that you have the correct path in the " +"config file if you installed it to a nonstandard location."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Due to the failure to delete the blockchain data you will be required to " "manually delete the data before starting your wallet."), QT_TRANSLATE_NOOP("bitcoin-core", "" "Error initializing database environment %s! To recover, BACKUP THAT " "DIRECTORY, then remove everything from it except for wallet.dat."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Error: Clock skew is 5 minutes or greater. Please check your clock settings."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Error: The transaction was rejected. This might happen if some of the coins " "in your wallet were already spent, such as if you used a copy of wallet.dat " "and coins were spent in the copy but not marked as spent here."), @@ -66,15 +71,83 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Failure to do so will result in undefined behaviour or failure to start " "wallet."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"For initiatives related to the Gridcoin community not covered by other poll " +"types."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"For polls about community representation, public relations, and " +"communications."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Please check your network and also check the config file and ensure your " +"addnode entries are up-to-date. If you recently started the wallet, you may " +"want to wait another few minutes for connections to build up and test again. " +"Please see https://gridcoin.us/wiki/config-file.html and https://addnodes." +"cycy.me/."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Please ensure that you have followed the process to advertise and verify " +"your beacon. You can use the research wizard (the beacon button on the " +"overview screen)."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Poll additional field value \"%s\" for field name \"%s\" exceeds %s " +"characters."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Proposals related to Gridcoin management like poll requirements and funding."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Propose additions or removals of computing projects for research reward " +"eligibility."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"The IP for the port test site is unable to be resolved. This could mean your " +"DNS is not working correctly. The wallet may operate without DNS, but it " +"could be severely degraded, especially if the wallet is new and a database " +"of prior successful connections has not been built up. Please check your " +"computer and ensure name resolution is operating correctly."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"The connection to the port test site was refused. This could be a transient " +"problem with the port test site, but could also be an issue with your " +"firewall. If you are also failing the connection test, your firewall is most " +"likely blocking network communications from the Gridcoin client."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"The network has experienced a low-level error and this probably means your " +"IP address or other network connection parameters are not configured " +"correctly. Please check your network configuration on your computer."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"The network is reporting an unspecified socket error. If you also are " +"failing the connection test, then please check your computer's network " +"configuration."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"The port test site is closed on port. This could be a transient problem with " +"the port test site, but could also be an issue with your firewall. If you " +"are also failing the connection test, your firewall is most likely blocking " +"network communications from the Gridcoin client."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"The wallet has less than five connections to the network and is unable to " +"connect to an NTP server to check your computer clock. This is not " +"necessarily a problem. You can wait a few minutes and try the test again."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "The wallet will now shutdown. Please start your wallet to begin sync from " "zero"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"There is a new leisure version available and you should upgrade as soon as " +"practical."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"There is a new mandatory version available and you should upgrade as soon as " +"possible to ensure your wallet remains in consensus with the network."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Unable to bind to %s on this computer. Gridcoin is probably already running."), QT_TRANSLATE_NOOP("bitcoin-core", "" "Unable to download a snapshot, as the wallet has detected that a new " "mandatory version is available for install. The mandatory upgrade must be " "installed before the snapshot can be downloaded and applied."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Verify (1) that you have BOINC installed correctly, (2) that you have " +"attached at least one whitelisted project, (3) that you advertised your " +"beacon with the same email as you use for your BOINC project(s), and (4) " +"that the CPID on the overview screen matches the CPID when you login to your " +"BOINC project(s) online."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Verify that you have actually completed workunits for the projects you have " +"attached and that you have authorized the export of statistics. Please see " +"https://gridcoin.us/guides/whitelist.htm."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "WARNING: A mandatory release is available. Please upgrade as soon as " "possible."), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -93,6 +166,14 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Warning: -paytxfee is set very high! This is the transaction fee you will " "pay if you send a transaction."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Warning: Clock skew is between 3 and 5 minutes. Please check your clock " +"settings."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Warning: ETTS is > 90 days. It will take a very long time to receive your " +"research rewards by staking - increase balance or use MRC"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Warning: ETTS is infinite. No coins to stake - increase balance or use MRC"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Warning: Ending this process after Stage 2 will result in syncing from 0 or " "an incomplete/corrupted blockchain."), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -106,10 +187,82 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect " "you should restore from a backup."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"You have no balance and will be unable to retrieve your research rewards " +"when solo crunching by staking. You can use MRC to retrieve your rewards, or " +"you should acquire GRC to stake so you can retrieve your research rewards. " +"Please see https://gridcoin.us/guides/boinc-install.htm."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "You must set rpcpassword= in the configuration file:\n" "%s\n" "If the file does not exist, create it with owner-readable-only file " "permissions."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"You will not be able to stake because you have less than %1 connection(s). " +"Please check your network and also check the config file and ensure your " +"addnode entries are up-to-date. If you recently started the wallet, you may " +"want to wait another few minutes for connections to build up and then test " +"again. Please see https://gridcoin.us/wiki/config-file.html and https://" +"addnodes.cycy.me/."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your balance is low given the current network difficulty to stake in a " +"reasonable period of time to retrieve your research rewards when solo " +"crunching. You should consider acquiring more GRC to stake more often, or " +"else use MRC to retrieve your rewards."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your balance is too low given the current network difficulty to stake in a " +"reasonable period of time to retrieve your research rewards when solo " +"crunching. You can use MRC to retrieve your rewards, or you should acquire " +"more GRC to stake more often."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your clock in your computer is significantly off from UTC or network time " +"and this may seriously degrade the operation of the wallet, including " +"maintaining connection to the network. You should check your time and time " +"zone settings for your computer. A very common problem is the off by one " +"hour caused by a time zone issue or problems with daylight savings time."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your difficulty is extremely low and your wallet is almost certainly forked. " +"Please ensure you are running the latest version and try removing the " +"blockchain database and resyncing from genesis using the menu option. (Note " +"this will take 2-4 hours.)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your difficulty is low but your wallet is still in initial sync. Please " +"recheck it later to see if this passes."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your difficulty is very low and your wallet is probably forked. Please " +"ensure you are running the latest version and try removing the blockchain " +"database and resyncing from genesis using the menu option. (Note this will " +"take 2-4 hours.)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your outbound connection count is critically low. Please check your the " +"config file and ensure your addnode entries are up-to-date. If you recently " +"started the wallet, you may want to wait another few minutes for connections " +"to build up and then test again. Please see https://gridcoin.us/wiki/config-" +"file.html and https://addnodes.cycy.me/."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your outbound connection count is low. Please check your the config file and " +"ensure your addnode entries are up-to-date. If you recently started the " +"wallet, you may want to wait another few minutes for connections to build up " +"and then test again. Please see https://gridcoin.us/wiki/config-file.html " +"and https://addnodes.cycy.me/."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your wallet is not in sync and has not previously been in sync during this " +"run, please wait for the wallet to sync and retest. If there are other " +"failures preventing the wallet from syncing, please correct those items and " +"retest to see if this test passes."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your wallet is out of sync with the network but was in sync before. If this " +"fails there is likely a severe problem that is preventing the wallet from " +"syncing. If the lack of sync is due to network connection issues, you will " +"see failures on the network connection test(s). If the network connections " +"pass, but your wallet fails this test, and continues to fail this test on " +"repeated attempts with a few minutes in between, this could indicate a more " +"serious issue. In that case you should check the debug log to see if it " +"sheds light on the cause for no sync."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Your wallet is still in initial sync. If this is a sync from the beginning " +"(genesis), the sync process can take from 2 to 4 hours, or longer on a slow " +"computer. If you have synced your wallet before but you just started the " +"wallet up, then wait a few more minutes and retry the diagnostics again."), QT_TRANSLATE_NOOP("bitcoin-core", "A poll choice cannot be empty."), QT_TRANSLATE_NOOP("bitcoin-core", "Are you sure you want to cancel the snapshot operation?"), QT_TRANSLATE_NOOP("bitcoin-core", "Balance too low to create a contract."), @@ -133,12 +286,14 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write to data directory '%s'; check permissions."), QT_TRANSLATE_NOOP("bitcoin-core", "Click \"Show Details\" to view changes in latest update."), QT_TRANSLATE_NOOP("bitcoin-core", "Client Version"), +QT_TRANSLATE_NOOP("bitcoin-core", "Community"), QT_TRANSLATE_NOOP("bitcoin-core", "Could not create transaction. See debug.log."), QT_TRANSLATE_NOOP("bitcoin-core", "Datadir: "), QT_TRANSLATE_NOOP("bitcoin-core", "Difficulty"), QT_TRANSLATE_NOOP("bitcoin-core", "Directories:"), QT_TRANSLATE_NOOP("bitcoin-core", "Disabled by configuration"), QT_TRANSLATE_NOOP("bitcoin-core", "Done loading"), +QT_TRANSLATE_NOOP("bitcoin-core", "Duplicate poll additional field: %s"), QT_TRANSLATE_NOOP("bitcoin-core", "Duplicate poll choice: %s"), QT_TRANSLATE_NOOP("bitcoin-core", "Duplicate response for poll choice: %s"), QT_TRANSLATE_NOOP("bitcoin-core", "ERROR"), @@ -160,12 +315,16 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Exceeded the number of choices in the poll: % QT_TRANSLATE_NOOP("bitcoin-core", "Failed to download snapshot.zip; See debug.log"), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to rename bootstrap file to .old for backup purposes."), +QT_TRANSLATE_NOOP("bitcoin-core", "Failed: 80 block difficulty is less than"), +QT_TRANSLATE_NOOP("bitcoin-core", "Failed: Count ="), QT_TRANSLATE_NOOP("bitcoin-core", "Fees Collected"), QT_TRANSLATE_NOOP("bitcoin-core", "Files:"), +QT_TRANSLATE_NOOP("bitcoin-core", "For opinion or casual polls without any particular requirements."), QT_TRANSLATE_NOOP("bitcoin-core", "GB)"), QT_TRANSLATE_NOOP("bitcoin-core", "GB/"), QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"), QT_TRANSLATE_NOOP("bitcoin-core", "GitHub version: "), +QT_TRANSLATE_NOOP("bitcoin-core", "Governance"), QT_TRANSLATE_NOOP("bitcoin-core", "Gridcoin Update Available"), QT_TRANSLATE_NOOP("bitcoin-core", "Gridcoin version"), QT_TRANSLATE_NOOP("bitcoin-core", "Gridcoin"), @@ -204,6 +363,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Magnitude"), QT_TRANSLATE_NOOP("bitcoin-core", "Magnitude+Balance"), QT_TRANSLATE_NOOP("bitcoin-core", "Magnitude-only polls are not supported."), QT_TRANSLATE_NOOP("bitcoin-core", "Malformed CPID"), +QT_TRANSLATE_NOOP("bitcoin-core", "Marketing"), QT_TRANSLATE_NOOP("bitcoin-core", "Multiple Choice"), QT_TRANSLATE_NOOP("bitcoin-core", "N/A"), QT_TRANSLATE_NOOP("bitcoin-core", "No UTXOs available due to reserve balance"), @@ -215,12 +375,20 @@ QT_TRANSLATE_NOOP("bitcoin-core", "No mature coins"), QT_TRANSLATE_NOOP("bitcoin-core", "No wallet available."), QT_TRANSLATE_NOOP("bitcoin-core", "Offline"), QT_TRANSLATE_NOOP("bitcoin-core", "Organization"), +QT_TRANSLATE_NOOP("bitcoin-core", "Outbound communication to TCP port %1 appears to be blocked. "), +QT_TRANSLATE_NOOP("bitcoin-core", "Outbound communication to TCP port"), +QT_TRANSLATE_NOOP("bitcoin-core", "Outreach"), QT_TRANSLATE_NOOP("bitcoin-core", "Participant Count"), QT_TRANSLATE_NOOP("bitcoin-core", "Participant count polls are not supported."), +QT_TRANSLATE_NOOP("bitcoin-core", "Passed: 80 block difficulty is"), +QT_TRANSLATE_NOOP("bitcoin-core", "Passed: Count ="), +QT_TRANSLATE_NOOP("bitcoin-core", "Passed: ETTS ="), QT_TRANSLATE_NOOP("bitcoin-core", "Please enter a poll discussion website URL."), QT_TRANSLATE_NOOP("bitcoin-core", "Please enter a poll title."), QT_TRANSLATE_NOOP("bitcoin-core", "Please enter at least one response."), QT_TRANSLATE_NOOP("bitcoin-core", "Please enter at least two poll choices."), +QT_TRANSLATE_NOOP("bitcoin-core", "Poll additional field name \"%s\" exceeds %s characters."), +QT_TRANSLATE_NOOP("bitcoin-core", "Poll cannot contain more than %s additional fields"), QT_TRANSLATE_NOOP("bitcoin-core", "Poll cannot contain more than %s choices."), QT_TRANSLATE_NOOP("bitcoin-core", "Poll choice \"%s\" exceeds %s characters."), QT_TRANSLATE_NOOP("bitcoin-core", "Poll discussion URL cannot exceed %s characters."), @@ -233,7 +401,11 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Poll signature failed. See debug.log."), QT_TRANSLATE_NOOP("bitcoin-core", "Poll title cannot exceed %s characters."), QT_TRANSLATE_NOOP("bitcoin-core", "Poll with that title already exists. Please choose another title."), QT_TRANSLATE_NOOP("bitcoin-core", "Pool"), +QT_TRANSLATE_NOOP("bitcoin-core", "Project Listing"), QT_TRANSLATE_NOOP("bitcoin-core", "Project email mismatch"), +QT_TRANSLATE_NOOP("bitcoin-core", "Propose a change to Gridcoin at the protocol level."), +QT_TRANSLATE_NOOP("bitcoin-core", "Propose marketing initiatives like ad campaigns."), +QT_TRANSLATE_NOOP("bitcoin-core", "Protocol Development"), QT_TRANSLATE_NOOP("bitcoin-core", "Quorum Hash"), QT_TRANSLATE_NOOP("bitcoin-core", "Reindexing blockchain from on disk block data files..."), QT_TRANSLATE_NOOP("bitcoin-core", "Replaying contracts..."), @@ -263,15 +435,22 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Staking Only - No Eligible Research Projects" QT_TRANSLATE_NOOP("bitcoin-core", "Staking Only - No active beacon"), QT_TRANSLATE_NOOP("bitcoin-core", "Staking Only - Pool Detected"), QT_TRANSLATE_NOOP("bitcoin-core", "Superblock Binary Size"), +QT_TRANSLATE_NOOP("bitcoin-core", "Survey"), QT_TRANSLATE_NOOP("bitcoin-core", "Testnet-only version"), +QT_TRANSLATE_NOOP("bitcoin-core", "The field is not well-formed."), +QT_TRANSLATE_NOOP("bitcoin-core", "The field list is not well-formed."), QT_TRANSLATE_NOOP("bitcoin-core", "The wallet is now shutting down. Please restart your wallet."), QT_TRANSLATE_NOOP("bitcoin-core", "The wallet will now shutdown."), QT_TRANSLATE_NOOP("bitcoin-core", "This update is "), +QT_TRANSLATE_NOOP("bitcoin-core", "This wallet is almost certainly forked."), +QT_TRANSLATE_NOOP("bitcoin-core", "This wallet is probably forked."), QT_TRANSLATE_NOOP("bitcoin-core", "To use the %s option"), QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %d, %s)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Unable to create the PID file '%s': %s"), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown error"), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown poll response type."), +QT_TRANSLATE_NOOP("bitcoin-core", "Unknown poll type. This should never happen."), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown poll type."), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown poll weight type."), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown"), @@ -282,10 +461,17 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Vote signature failed. See debug.log."), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside data directory %s."), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet locked"), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Gridcoin to complete"), +QT_TRANSLATE_NOOP("bitcoin-core", "Warning: 45 days < ETTS ="), +QT_TRANSLATE_NOOP("bitcoin-core", "Warning: 80 block difficulty is less than"), +QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Cannot connect to NTP server"), +QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Count ="), QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Disk space is low!"), +QT_TRANSLATE_NOOP("bitcoin-core", "Wrong Payload version specified for current block height."), QT_TRANSLATE_NOOP("bitcoin-core", "Yes/No/Abstain"), +QT_TRANSLATE_NOOP("bitcoin-core", "You should check your time and time zone settings for your computer."), QT_TRANSLATE_NOOP("bitcoin-core", "You will need to delete the following."), QT_TRANSLATE_NOOP("bitcoin-core", "\"%s\" is not a valid poll choice."), +QT_TRANSLATE_NOOP("bitcoin-core", "appears to be blocked."), QT_TRANSLATE_NOOP("bitcoin-core", "leisure"), QT_TRANSLATE_NOOP("bitcoin-core", "mandatory"), QT_TRANSLATE_NOOP("bitcoin-core", "unknown"), diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index fd713fcd7e..baf3a6cd30 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -3,6 +3,8 @@ #include +static constexpr auto MAX_DIGITS_BTC = 16; + BitcoinUnits::BitcoinUnits(QObject *parent): QAbstractListModel(parent), unitlist(availableUnits()) @@ -99,7 +101,9 @@ QString BitcoinUnits::format(int unit, qint64 n, bool fPlus, bool justify) qint64 remainder = n_abs % coin; QString quotient_str = QString::number(quotient); - if (justify) quotient_str = quotient_str.rightJustified(16 - num_decimals, ' '); + if (justify) { + quotient_str = quotient_str.rightJustified(MAX_DIGITS_BTC - num_decimals, ' '); + } QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0'); diff --git a/src/qt/diagnosticsdialog.cpp b/src/qt/diagnosticsdialog.cpp index 31f5dc839b..e1c342203f 100644 --- a/src/qt/diagnosticsdialog.cpp +++ b/src/qt/diagnosticsdialog.cpp @@ -1,24 +1,17 @@ -// Copyright (c) 2014-2021 The Gridcoin developers +// Copyright (c) 2014-2022 The Gridcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include "fs.h" -#include "main.h" -#include "util.h" - #include #include #include "diagnosticsdialog.h" -#include "ui_diagnosticsdialog.h" -#include "gridcoin/boinc.h" -#include "gridcoin/researcher.h" -#include "gridcoin/staking/difficulty.h" -#include "gridcoin/upgrade.h" +#include "qt/forms/ui_diagnosticsdialog.h" #include "qt/decoration.h" #include "qt/researcher/researchermodel.h" #include +#include extern std::atomic g_nTimeBestReceived; @@ -34,6 +27,34 @@ DiagnosticsDialog::DiagnosticsDialog(QWidget *parent, ResearcherModel* researche GRC::ScaleFontPointSize(ui->diagnosticsLabel, 14); GRC::ScaleFontPointSize(ui->overallResultLabel, 12); GRC::ScaleFontPointSize(ui->overallResultResultLabel, 12); + + // Construct the tests needed. + // If need to add a test m just add it to the below set. + // Check Diagnose.h for the base class to create tests. + diagnoseTestInsertInSet(ui->checkConnectionCountResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->checkOutboundConnectionCountResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->verifyWalletIsSyncedResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->verifyClockResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->checkClientVersionResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->verifyBoincPathResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->verifyCPIDValidResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->verifyCPIDHasRACResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->verifyCPIDIsActiveResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->verifyTCPPortResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->checkDifficultyResultLabel, + std::make_unique()); + diagnoseTestInsertInSet(ui->checkETTSResultLabel, + std::make_unique()); } DiagnosticsDialog::~DiagnosticsDialog() @@ -100,7 +121,7 @@ unsigned int DiagnosticsDialog::GetNumberOfTestsPending() return pending_count; } -DiagnosticsDialog::DiagnosticTestStatus DiagnosticsDialog::GetTestStatus(std::string test_name) +DiagnosticsDialog::DiagnosticTestStatus DiagnosticsDialog::GetTestStatus(DiagnoseLib::Diagnose::TestNames test_name) { LOCK(cs_diagnostictests); @@ -116,7 +137,7 @@ DiagnosticsDialog::DiagnosticTestStatus DiagnosticsDialog::GetTestStatus(std::st } } -unsigned int DiagnosticsDialog::UpdateTestStatus(std::string test_name, QLabel *label, +unsigned int DiagnosticsDialog::UpdateTestStatus(DiagnoseLib::Diagnose::TestNames test_name, QLabel *label, DiagnosticTestStatus test_status, DiagnosticResult test_result, QString override_text, QString tooltip_text) { @@ -133,14 +154,14 @@ unsigned int DiagnosticsDialog::UpdateTestStatus(std::string test_name, QLabel * return m_test_status_map.size(); } -void DiagnosticsDialog::UpdateTestResult(std::string test_name, DiagnosticResult test_result) +void DiagnosticsDialog::UpdateTestResult(DiagnoseLib::Diagnose::TestNames test_name, DiagnosticResult test_result) { LOCK(cs_diagnostictests); m_test_result_map[test_name] = test_result; } -DiagnosticsDialog::DiagnosticResult DiagnosticsDialog::GetTestResult(std::string test_name) +DiagnosticsDialog::DiagnosticResult DiagnosticsDialog::GetTestResult(DiagnoseLib::Diagnose::TestNames test_name) { LOCK(cs_diagnostictests); @@ -262,765 +283,35 @@ void DiagnosticsDialog::on_testButton_clicked() ResetOverallDiagnosticResult(); DisplayOverallDiagnosticResult(); - m_researcher_mode = !(m_researcher_model->configuredForInvestorMode() || m_researcher_model->detectedPoolMode()); - - VerifyWalletIsSynced(); - - unsigned int connections = CheckConnectionCount(); - - CheckOutboundConnectionCount(); - - VerifyClock(connections); - - VerifyTCPPort(); - - double diff = CheckDifficulty(); - - CheckClientVersion(); - - VerifyBoincPath(); - - VerifyCPIDValid(); - - VerifyCPIDHasRAC(); - - VerifyCPIDIsActive(); - - CheckETTS(diff); - - DisplayOverallDiagnosticResult(); -} - -void DiagnosticsDialog::VerifyWalletIsSynced() -{ - UpdateTestStatus(__func__, ui->verifyWalletIsSyncedResultLabel, pending, NA); - - if (g_nTimeBestReceived == 0 && OutOfSyncByAge()) - { - QString tooltip = tr("Your wallet is still in initial sync. If this is a sync from the beginning (genesis), the " - "sync process can take from 2 to 4 hours, or longer on a slow computer. If you have synced " - "your wallet before but you just started the wallet up, then wait a few more minutes and " - "retry the diagnostics again."); - - UpdateTestStatus(__func__, ui->verifyWalletIsSyncedResultLabel, completed, warning, QString(), tooltip); - } - else if (g_nTimeBestReceived > 0 && OutOfSyncByAge()) - { - QString tooltip = tr("Your wallet is out of sync with the network but was in sync before. If this fails there is " - "likely a severe problem that is preventing the wallet from syncing. If the lack of sync " - "is due to network connection issues, you will see failures on the network connection " - "test(s). If the network connections pass, but your wallet fails this test, and continues to " - "fail this test on repeated attempts with a few minutes in between, this could indicate a " - "more serious issue. In that case you should check the debug log to see if it sheds light " - "on the cause for no sync."); - - UpdateTestStatus(__func__, ui->verifyWalletIsSyncedResultLabel, completed, failed, QString(), tooltip); - - } - else - { - UpdateTestStatus(__func__, ui->verifyWalletIsSyncedResultLabel, completed, passed); - } -} - -int DiagnosticsDialog::CheckConnectionCount() -{ - UpdateTestStatus(__func__, ui->checkConnectionCountResultLabel, pending, NA); - - int connections = 0; - int minimum_connections_to_stake = fTestNet ? 1 : 3; - { - LOCK(cs_vNodes); - - connections = vNodes.size(); - } - - if (connections <= 7 && connections >= minimum_connections_to_stake) - { - QString tooltip = tr("Please check your network and also check the config file and ensure your addnode entries " - "are up-to-date. If you recently started the wallet, you may want to wait another few " - "minutes for connections to build up and test again. Please see " - "https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/."); - - UpdateTestStatus(__func__, ui->checkConnectionCountResultLabel, completed, warning, - tr("Warning: Count = %1 (Pass = 8+)").arg(QString::number(connections)), tooltip); - } - else if (connections >= 8) - { - UpdateTestStatus(__func__, ui->checkConnectionCountResultLabel, completed, passed, - tr("Passed: Count = %1").arg(QString::number(connections))); - } - else - { - QString tooltip = tr("You will not be able to stake because you have less than %1 connection(s). Please check " - "your network and also check the config file and ensure your addnode entries are up-to-date. " - "If you recently started the wallet, you may want to wait another few minutes for connections " - "to build up and then test again. Please see https://gridcoin.us/wiki/config-file.html and " - "https://addnodes.cycy.me/.").arg(QString::number(minimum_connections_to_stake)); - - UpdateTestStatus(__func__, ui->checkConnectionCountResultLabel, completed, failed, - tr("Failed: Count = %1").arg(QString::number(connections)), tooltip); - } - - return connections; -} - -void DiagnosticsDialog::CheckOutboundConnectionCount() -{ - UpdateTestStatus(__func__, ui->checkOutboundConnectionCountResultLabel, pending, NA); - - LOCK(cs_vNodes); - - int outbound_connections = 0; - - for (const auto& vnodes : vNodes) - { - if (!vnodes->fInbound) ++outbound_connections; - } - - if (outbound_connections < 1) - { - QString tooltip = tr("Your outbound connection count is critically low. Please check your the config file and " - "ensure your addnode entries are up-to-date. If you recently started the wallet, you may " - "want to wait another few minutes for connections to build up and then test again. Please see " - "https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/."); - - UpdateTestStatus(__func__, ui->checkOutboundConnectionCountResultLabel, completed, failed, - tr("Failed: Count = %1").arg(QString::number(outbound_connections)), tooltip); - } - else if (outbound_connections < 3) - { - QString tooltip = tr("Your outbound connection count is low. Please check your the config file and " - "ensure your addnode entries are up-to-date. If you recently started the wallet, you may " - "want to wait another few minutes for connections to build up and then test again. Please see " - "https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/."); - - UpdateTestStatus(__func__, ui->checkOutboundConnectionCountResultLabel, completed, warning, - tr("Warning: Count = %1 (Pass = 3+)").arg(QString::number(outbound_connections)), tooltip); - - } - else - { - UpdateTestStatus(__func__, ui->checkOutboundConnectionCountResultLabel, completed, passed, - tr("Passed: Count = %1").arg(QString::number(outbound_connections))); - } -} - -void DiagnosticsDialog::VerifyClock(unsigned int connections) -{ - UpdateTestStatus(__func__, ui->verifyClockResultLabel, pending, NA); - - // This is aligned to the minimum sample size in AddTimeData to compute a nTimeOffset from the sampling of - // connected nodes. If a sufficient sample exists, use the existing time offset from the node rather than - // going through the ntp connection code. The ntp connection code is retained to help people resolve no connection - // situations where their node is so far off they are banned and disconnected from the network. - if (connections >= 5) - { - int64_t time_offset = 0; - - { - LOCK(cs_main); - - time_offset = GetTimeOffset(); + DiagnoseLib::Diagnose::setResearcherModel(); + + for (auto& i : m_diagnostic_tests) { + auto& diagnose_test = i.second; + auto diagnoselabel = i.first; + UpdateTestStatus(i.second->getTestName(), diagnoselabel, pending, NA); + diagnose_test->runCheck(); + QString tooltip = tr(diagnose_test->getResultsTip().c_str()); + QString resultString = tr(diagnose_test->getResultsString().c_str()); + for (auto& j : diagnose_test->getStringArgs()) { + resultString = resultString.arg(QString::fromStdString(j)); } - - clkReportResults(time_offset); - - return; - } - - QTimer *timerVerifyClock = new QTimer(); - - // Set up a timeout clock of 10 seconds as a fail-safe. - connect(timerVerifyClock, &QTimer::timeout, this, &DiagnosticsDialog::clkFinished); - timerVerifyClock->start(10 * 1000); - - QHostInfo NTPHost = QHostInfo::fromName("pool.ntp.org"); - m_udpSocket = new QUdpSocket(this); - - connect(m_udpSocket, &QUdpSocket::stateChanged, this, &DiagnosticsDialog::clkStateChanged); - - // For Qt 5.15 and above QAbstractSocket::error has been deprecated in favor of errorOccurred. -#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) - connect(m_udpSocket, static_cast(&QUdpSocket::error), - this, static_cast(&DiagnosticsDialog::clkSocketError)); -#else - connect(m_udpSocket, &QUdpSocket::errorOccurred, this, &DiagnosticsDialog::clkSocketError); -#endif - - if (!NTPHost.addresses().empty()) - { - m_udpSocket->connectToHost(QHostAddress(NTPHost.addresses().first()), 123, QIODevice::ReadWrite); - } - else - { - clkSocketError(); - } -} - -void DiagnosticsDialog::clkStateChanged(QAbstractSocket::SocketState state) -{ - if (state == QAbstractSocket::ConnectedState) - { - connect(m_udpSocket, &QUdpSocket::readyRead, this, &DiagnosticsDialog::clkFinished); - - char NTPMessage[48] = {0x1b, 0, 0, 0 ,0, 0, 0, 0, 0}; - - m_udpSocket->write(NTPMessage, sizeof(NTPMessage)); - } -} - -void DiagnosticsDialog::clkSocketError() -{ - m_udpSocket->close(); - - clkReportResults(0, true); -} - -void DiagnosticsDialog::clkFinished() -{ - if (m_udpSocket->waitForReadyRead(10 * 1000)) - { - int64_t start_time = GetAdjustedTime(); - - // Only allow this loop to run for 5 seconds maximum. - while (m_udpSocket->hasPendingDatagrams() && GetAdjustedTime() - start_time <= 5) - { - QByteArray BufferSocket = m_udpSocket->readAll(); - - if (BufferSocket.size() == 48) - { - int nNTPCount = 40; - uint32_t DateTimeIn = uchar(BufferSocket.at(nNTPCount)) - + (uchar(BufferSocket.at(nNTPCount + 1)) << 8) - + (uchar(BufferSocket.at(nNTPCount + 2)) << 16) - + (uchar(BufferSocket.at(nNTPCount + 3)) << 24); - time_t tmit = ntohl(DateTimeIn) - 2208988800U; - - m_udpSocket->close(); - - boost::posix_time::ptime localTime = boost::posix_time::microsec_clock::universal_time(); - boost::posix_time::ptime networkTime = boost::posix_time::from_time_t(tmit); - boost::posix_time::time_duration timeDiff = networkTime - localTime; - - clkReportResults(timeDiff.total_seconds()); - - return; - } - } - } - else // The other state here is a socket or other indeterminate error such as a timeout (coming from clkSocketError). - { - // This is needed to "cancel" the timeout timer. Essentially if the test was marked completed via the normal exits - // above, then when the timer calls clkFinished again, it will hit this conditional and be a no-op. - if (GetTestStatus("VerifyClock") != completed) - { - clkReportResults(0, true); + for (auto& j : diagnose_test->getTipArgs()) { + tooltip = tooltip.arg(QString::fromStdString(j)); } - return; - } -} - -void DiagnosticsDialog::clkReportResults(const int64_t& time_offset, const bool& timeout_during_check) -{ - if (!timeout_during_check) - { - if (abs64(time_offset) < 3 * 60) - { - UpdateTestStatus("VerifyClock", ui->verifyClockResultLabel, completed, passed); + if (diagnose_test->getResults() == DiagnoseLib::Diagnose::NONE) { + UpdateTestStatus(i.second->getTestName(), diagnoselabel, completed, NA); + } else if (diagnose_test->getResults() == DiagnoseLib::Diagnose::FAIL) { + UpdateTestStatus(i.second->getTestName(), diagnoselabel, completed, failed, + resultString, tooltip); + } else if (diagnose_test->getResults() == DiagnoseLib::Diagnose::WARNING) { + UpdateTestStatus(i.second->getTestName(), diagnoselabel, completed, warning, + resultString, tooltip); + } else { + UpdateTestStatus(i.second->getTestName(), diagnoselabel, completed, passed, + resultString); } - else if (abs64(time_offset) < 5 * 60) - { - QString tooltip = tr("You should check your time and time zone settings for your computer."); - - UpdateTestStatus("VerifyClock", ui->verifyClockResultLabel, completed, warning, - tr("Warning: Clock skew is between 3 and 5 minutes. Please check your clock settings."), - tooltip); - } - else - { - QString tooltip = tr("Your clock in your computer is significantly off from UTC or network time and " - "this may seriously degrade the operation of the wallet, including maintaining " - "connection to the network. You should check your time and time zone settings " - "for your computer. A very common problem is the off by one hour caused by a time " - "zone issue or problems with daylight savings time."); - - UpdateTestStatus("VerifyClock", ui->verifyClockResultLabel, completed, failed, - tr("Error: Clock skew is 5 minutes or greater. Please check your clock settings."), - tooltip); - } - } - else - { - QString tooltip = tr("The wallet has less than five connections to the network and is unable to connect " - "to an NTP server to check your computer clock. This is not necessarily a problem. " - "You can wait a few minutes and try the test again."); - - UpdateTestStatus("VerifyClock", ui->verifyClockResultLabel, completed, warning, - tr("Warning: Cannot connect to NTP server"), tooltip); } DisplayOverallDiagnosticResult(); } - -void DiagnosticsDialog::VerifyTCPPort() -{ - UpdateTestStatus(__func__, ui->verifyTCPPortResultLabel, pending, NA); - - // Note that if the CheckConnectionCount test has been run already (which it must given the order the tests are - // run above), then the test result cannot be NA. So if it did not fail, it must be either warning or passed, - // which is sufficient in and of itself to mark VerifyTCPPort() successful without further testing, since - // to get valid outbound connections, the port must be working. - if (GetTestStatus("CheckConnectionCount") == completed - && GetTestResult("CheckConnectionCount") != failed) { - UpdateTestStatus("VerifyTCPPort", ui->verifyTCPPortResultLabel, completed, passed); - - return; - } - - m_tcpSocket = new QTcpSocket(this); - - connect(m_tcpSocket, &QTcpSocket::connected, this, &DiagnosticsDialog::TCPFinished); - - // For Qt 5.15 and above QAbstractSocket::error has been deprecated in favor of errorOccurred. -#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) - connect(m_tcpSocket, static_cast(&QTcpSocket::error), - this, static_cast(&DiagnosticsDialog::TCPFailed)); -#else - connect(m_tcpSocket, static_cast(&QTcpSocket::errorOccurred), - this, static_cast(&DiagnosticsDialog::TCPFailed)); -#endif - - m_tcpSocket->connectToHost("portquiz.net", GetListenPort()); -} - -void DiagnosticsDialog::TCPFinished() -{ - m_tcpSocket->close(); - UpdateTestStatus("VerifyTCPPort", ui->verifyTCPPortResultLabel, completed, passed); - - DisplayOverallDiagnosticResult(); - - return; -} - -void DiagnosticsDialog::TCPFailed(QAbstractSocket::SocketError socket_error) -{ - DiagnosticResult test_result = warning; - QString tooltip = tr("Outbound communication to TCP port %1 appears to be blocked. ").arg(GetListenPort()); - - switch (socket_error) - { - case QAbstractSocket::SocketError::ConnectionRefusedError: - tooltip += tr("The connection to the port test site was refused. This could be a transient problem with the " - "port test site, but could also be an issue with your firewall. If you are also failing the " - "connection test, your firewall is most likely blocking network communications from the " - "Gridcoin client."); - - break; - - case QAbstractSocket::SocketError::RemoteHostClosedError: - tooltip += tr("The port test site is closed on port. This could be a transient problem with the " - "port test site, but could also be an issue with your firewall. If you are also failing the " - "connection test, your firewall is most likely blocking network communications from the " - "Gridcoin client."); - - break; - - case QAbstractSocket::SocketError::HostNotFoundError: - // This does not include the common text above on purpose. - tooltip = tr("The IP for the port test site is unable to be resolved. This could mean your DNS is not working " - "correctly. The wallet may operate without DNS, but it could be severely degraded, especially if " - "the wallet is new and a database of prior successful connections has not been built up. Please " - "check your computer and ensure name resolution is operating correctly."); - - break; - - case QAbstractSocket::SocketError::SocketAccessError: - case QAbstractSocket::SocketError::SocketResourceError: - case QAbstractSocket::SocketError::SocketTimeoutError: - case QAbstractSocket::SocketError::DatagramTooLargeError: - case QAbstractSocket::SocketError::NetworkError: - case QAbstractSocket::SocketError::AddressInUseError: - case QAbstractSocket::SocketError::SocketAddressNotAvailableError: - case QAbstractSocket::SocketError::UnsupportedSocketOperationError: - case QAbstractSocket::SocketError::UnfinishedSocketOperationError: - case QAbstractSocket::SocketError::OperationError: - test_result = failed; - - // This does not include the common text above on purpose. - tooltip = tr("The network has experienced a low-level error and this probably means your IP address or other " - "network connection parameters are not configured correctly. Please check your network configuration " - "on your computer."); - - break; - - case QAbstractSocket::SocketError::ProxyAuthenticationRequiredError: - case QAbstractSocket::SocketError::ProxyConnectionRefusedError: - case QAbstractSocket::SocketError::ProxyConnectionClosedError: - case QAbstractSocket::SocketError::ProxyConnectionTimeoutError: - case QAbstractSocket::SocketError::ProxyNotFoundError: - case QAbstractSocket::SocketError::ProxyProtocolError: - test_result = failed; - - tooltip += tr("Your network may be using a proxy server to communicate to public IP addresses on the Internet, and " - "the wallet is not configured properly to use it. Please check the proxy settings under Options -> " - "Network -> Connect through SOCKS5 proxy."); - - break; - - // SSL errors will NOT be triggered unless we implement a test and site to actually do an SSL connection test. This - // is put here for completeness. - case QAbstractSocket::SocketError::SslHandshakeFailedError: - case QAbstractSocket::SocketError::SslInternalError: - case QAbstractSocket::SocketError::SslInvalidUserDataError: - test_result = failed; - - // This does not include the common text above on purpose. - tooltip = tr("The network is reporting an SSL error. If you also failed or got a warning on your clock test, you " - "should check your clock settings, including your time and time zone. If your clock is ok, please " - "check your computer's network configuration."); - - break; - - case QAbstractSocket::SocketError::TemporaryError: - case QAbstractSocket::SocketError::UnknownSocketError: - test_result = failed; - - // This does not include the common text above on purpose. - tooltip = tr("The network is reporting an unspecified socket error. If you also are failing the connection test, " - "then please check your computer's network configuration."); - } - - UpdateTestStatus("VerifyTCPPort", ui->verifyTCPPortResultLabel, completed, test_result, - QString(), tooltip); - - DisplayOverallDiagnosticResult(); - - return; -} - -double DiagnosticsDialog::CheckDifficulty() -{ - UpdateTestStatus(__func__, ui->checkDifficultyResultLabel, pending, NA); - - double diff = 0; - double scale_factor = 1.0; - - { - LOCK(cs_main); - - scale_factor = fTestNet ? 0.1 : 1.0; - - diff = GRC::GetAverageDifficulty(80); - } - - double fail_diff = scale_factor; - double warn_diff = scale_factor * 5.0; - - // If g_nTimeBestReceived == 0, the wallet is still in the initial sync process. In that case use the failure - // standard and just warn, with a different explanation. - if (g_nTimeBestReceived == 0 && OutOfSyncByAge() && diff < fail_diff) - { - QString override_text = tr("Warning: 80 block difficulty is less than %1.") - .arg(QString::number(fail_diff, 'f', 1)); - - QString tooltip = tr("Your difficulty is low but your wallet is still in initial sync. Please recheck it later " - "to see if this passes."); - - UpdateTestStatus(__func__, ui->checkDifficultyResultLabel, completed, warning, - override_text, tooltip); - } - // If the wallet has been in sync in the past in this run, then apply the normal standards, whether the wallet is - // in sync or not right now. - else if (g_nTimeBestReceived > 0 && diff < fail_diff) - { - QString override_text = tr("Failed: 80 block difficulty is less than %1. This wallet is almost certainly forked.") - .arg(QString::number(fail_diff, 'f', 1)); - - QString tooltip = tr("Your difficulty is extremely low and your wallet is almost certainly forked. Please ensure " - "you are running the latest version and try removing the blockchain database and resyncing " - "from genesis using the menu option. (Note this will take 2-4 hours.)"); - - UpdateTestStatus(__func__, ui->checkDifficultyResultLabel, completed, failed, - override_text, tooltip); - } - else if (g_nTimeBestReceived > 0 && diff < warn_diff) - { - QString override_text = tr("Warning: 80 block difficulty is less than %1. This wallet is probably forked.") - .arg(QString::number(warn_diff, 'f', 1)); - - QString tooltip = tr("Your difficulty is very low and your wallet is probably forked. Please ensure you are " - "running the latest version and try removing the blockchain database and resyncing from " - "genesis using the menu option. (Note this will take 2-4 hours.)"); - - UpdateTestStatus(__func__, ui->checkDifficultyResultLabel, completed, warning, - override_text, tooltip); - } - else - { - QString override_text = tr("Passed: 80 block difficulty is %1.") - .arg(QString::number(diff, 'f', 1)); - - UpdateTestStatus(__func__, ui->checkDifficultyResultLabel, completed, passed, override_text); - } - - return diff; -} - -void DiagnosticsDialog::CheckClientVersion() -{ - UpdateTestStatus(__func__, ui->checkClientVersionResultLabel, pending, NA); - - std::string client_message; - - if (g_UpdateChecker->CheckForLatestUpdate(client_message, false) - && client_message.find("mandatory") != std::string::npos) - { - QString tooltip = tr("There is a new mandatory version available and you should upgrade as soon as possible to " - "ensure your wallet remains in consensus with the network."); - - UpdateTestStatus(__func__, ui->checkClientVersionResultLabel, completed, failed, - tr("Warning: New Client version available:\n %1").arg(QString(client_message.c_str()))); - } - else if (g_UpdateChecker->CheckForLatestUpdate(client_message, false) - && client_message.find("mandatory") == std::string::npos) - { - QString tooltip = tr("There is a new leisure version available and you should upgrade as soon as practical."); - - UpdateTestStatus(__func__, ui->checkClientVersionResultLabel, completed, warning, - tr("Warning: New Client version available:\n %1").arg(QString(client_message.c_str()))); - } - else - { - UpdateTestStatus(__func__, ui->checkClientVersionResultLabel, completed, passed); - } -} - -void DiagnosticsDialog::VerifyBoincPath() -{ - // This test is only applicable if the wallet is in researcher mode. - if (!m_researcher_mode) - { - UpdateTestStatus(__func__, ui->verifyBoincPathResultLabel, completed, NA); - - return; - } - - UpdateTestStatus(__func__, ui->verifyBoincPathResultLabel, pending, NA); - - fs::path boincPath = (fs::path) GRC::GetBoincDataDir(); - - if (boincPath.empty()) - boincPath = (fs::path) gArgs.GetArg("-boincdatadir", ""); - - boincPath = boincPath / "client_state.xml"; - - if (fs::exists(boincPath)) - { - UpdateTestStatus(__func__, ui->verifyBoincPathResultLabel, completed, passed); - } - else - { - QString tooltip = tr("Check that BOINC is installed and that you have the correct path in the config file " - "if you installed it to a nonstandard location."); - - UpdateTestStatus(__func__, ui->verifyBoincPathResultLabel, completed, failed, QString(), tooltip); - } -} - -void DiagnosticsDialog::VerifyCPIDValid() -{ - // This test is only applicable if the wallet is in researcher mode. - if (!m_researcher_mode) - { - UpdateTestStatus(__func__, ui->verifyCPIDValidResultLabel, completed, NA); - - return; - } - - UpdateTestStatus(__func__, ui->verifyCPIDValidResultLabel, pending, NA); - - if (m_researcher_model->hasEligibleProjects()) - { - UpdateTestStatus(__func__, ui->verifyCPIDValidResultLabel, completed, passed); - } - else - { - if (g_nTimeBestReceived == 0 && OutOfSyncByAge()) - { - QString tooltip = tr("Your wallet is not in sync and has not previously been in sync during this run, please " - "wait for the wallet to sync and retest. If there are other failures preventing the " - "wallet from syncing, please correct those items and retest to see if this test passes."); - - UpdateTestStatus(__func__, ui->verifyCPIDValidResultLabel, completed, warning, QString(), tooltip); - } - else - { - QString tooltip = tr("Verify (1) that you have BOINC installed correctly, (2) that you have attached at least " - "one whitelisted project, (3) that you advertised your beacon with the same email as you " - "use for your BOINC project(s), and (4) that the CPID on the overview screen matches the " - "CPID when you login to your BOINC project(s) online."); - - UpdateTestStatus(__func__, ui->verifyCPIDValidResultLabel, completed, failed, QString(), tooltip); - } - } -} - -void DiagnosticsDialog::VerifyCPIDHasRAC() -{ - // This test is only applicable if the wallet is in researcher mode. - if (!m_researcher_mode) - { - UpdateTestStatus(__func__, ui->verifyCPIDHasRACResultLabel, completed, NA); - - return; - } - - UpdateTestStatus(__func__, ui->verifyCPIDHasRACResultLabel, pending, NA); - - if (m_researcher_model->hasRAC()) - { - UpdateTestStatus(__func__, ui->verifyCPIDHasRACResultLabel, completed, passed); - } - else - { - if (g_nTimeBestReceived == 0 && OutOfSyncByAge()) - { - QString tooltip = tr("Your wallet is not in sync and has not previously been in sync during this run, please " - "wait for the wallet to sync and retest. If there are other failures preventing the " - "wallet from syncing, please correct those items and retest to see if this test passes."); - - UpdateTestStatus(__func__, ui->verifyCPIDHasRACResultLabel, completed, warning, QString(), tooltip); - } - else - { - QString tooltip = tr("Verify that you have actually completed workunits for the projects you have attached and " - "that you have authorized the export of statistics. Please see " - "https://gridcoin.us/guides/whitelist.htm."); - - UpdateTestStatus(__func__, ui->verifyCPIDHasRACResultLabel, completed, failed, QString(), tooltip); - } - } -} - -void DiagnosticsDialog::VerifyCPIDIsActive() -{ - // This test is only applicable if the wallet is in researcher mode. - if (!m_researcher_mode) - { - UpdateTestStatus(__func__, ui->verifyCPIDIsActiveResultLabel, completed, NA); - - return; - } - - UpdateTestStatus(__func__, ui->verifyCPIDIsActiveResultLabel, pending, NA); - - if (m_researcher_model->hasActiveBeacon()) - { - UpdateTestStatus(__func__, ui->verifyCPIDIsActiveResultLabel, completed, passed); - } - else - { - if (g_nTimeBestReceived == 0 && OutOfSyncByAge()) - { - QString tooltip = tr("Your wallet is not in sync and has not previously been in sync during this run, please " - "wait for the wallet to sync and retest. If there are other failures preventing the " - "wallet from syncing, please correct those items and retest to see if this test passes."); - - UpdateTestStatus(__func__, ui->verifyCPIDIsActiveResultLabel, completed, warning, QString(), tooltip); - } - else - { - QString tooltip = tr("Please ensure that you have followed the process to advertise and verify your beacon. " - "You can use the research wizard (the beacon button on the overview screen)."); - - UpdateTestStatus(__func__, ui->verifyCPIDIsActiveResultLabel, completed, failed, QString(), tooltip); - } - } -} - -// check ETTS -// This is only checked if wallet is a researcher wallet because the purpose is to -// alert the owner that his stake time is too long and therefore there is a chance -// of research rewards loss between stakes due to the 180 day limit. -void DiagnosticsDialog::CheckETTS(const double& diff) -{ - // This test is only applicable if the wallet is in researcher mode. - if (!m_researcher_mode) - { - UpdateTestStatus(__func__, ui->checkETTSResultLabel, completed, NA); - - return; - } - - UpdateTestStatus(__func__, ui->checkETTSResultLabel, pending, NA); - - double ETTS = GRC::GetEstimatedTimetoStake(true, diff) / (24.0 * 60.0 * 60.0); - - std::string rounded_ETTS; - - //round appropriately for display. - if (ETTS >= 100) - { - rounded_ETTS = RoundToString(ETTS, 0); - } - else if (ETTS >= 10) - { - rounded_ETTS = RoundToString(ETTS, 1); - } - else - { - rounded_ETTS = RoundToString(ETTS, 2); - } - - if (g_nTimeBestReceived == 0 && OutOfSyncByAge()) - { - QString tooltip = tr("Your wallet is not in sync and has not previously been in sync during this run, please " - "wait for the wallet to sync and retest. If there are other failures preventing the " - "wallet from syncing, please correct those items and retest to see if this test passes."); - - UpdateTestStatus(__func__, ui->checkETTSResultLabel, completed, warning, QString(), tooltip); - } - else - { - // ETTS of zero actually means no coins, i.e. infinite. - if (ETTS == 0.0) - { - QString tooltip = tr("You have no balance and will be unable to retrieve your research rewards when solo " - "crunching. You should acquire GRC to stake so you can retrieve your research rewards. " - "Please see https://gridcoin.us/guides/boinc-install.htm."); - - UpdateTestStatus(__func__, ui->checkETTSResultLabel, completed, failed, - tr("Failed: ETTS is infinite. No coins to stake."), tooltip); - } - else if (ETTS > 90.0) - { - QString tooltip = tr("Your balance is too low given the current network difficulty to stake in a reasonable " - "period of time to retrieve your research rewards when solo crunching. You should acquire " - "more GRC to stake more often."); - - UpdateTestStatus(__func__, ui->checkETTSResultLabel, completed, failed, - tr("Failed: ETTS is > 90 days. It will take a very long time to receive your research " - "rewards."), - tooltip); - } - else if (ETTS > 45.0 && ETTS <= 90.0) - { - QString tooltip = tr("Your balance is low given the current network difficulty to stake in a reasonable " - "period of time to retrieve your research rewards when solo crunching. You should consider " - "acquiring more GRC to stake more often."); - - UpdateTestStatus(__func__, ui->checkETTSResultLabel, completed, warning, - tr("Warning: 45 days < ETTS = %1 <= 90 days").arg(QString(rounded_ETTS.c_str())), - tooltip); - } - else - { - UpdateTestStatus(__func__, ui->checkETTSResultLabel, completed, passed, - tr("Passed: ETTS = %1 <= 45 days").arg(QString(rounded_ETTS.c_str()))); - } - } -} - diff --git a/src/qt/diagnosticsdialog.h b/src/qt/diagnosticsdialog.h index adea82eb26..cfd31e7aaf 100644 --- a/src/qt/diagnosticsdialog.h +++ b/src/qt/diagnosticsdialog.h @@ -13,6 +13,10 @@ #include #include "sync.h" +#include +#include +#include +#include "wallet/diagnose.h" class ResearcherModel; @@ -46,18 +50,10 @@ class DiagnosticsDialog : public QDialog private: Ui::DiagnosticsDialog *ui; void GetData(); - void VerifyWalletIsSynced(); - int CheckConnectionCount(); - void CheckOutboundConnectionCount(); - void VerifyClock(unsigned int connections); - void VerifyTCPPort(); - double CheckDifficulty(); - void CheckClientVersion(); - void VerifyBoincPath(); - void VerifyCPIDValid(); - void VerifyCPIDHasRAC(); - void VerifyCPIDIsActive(); - void CheckETTS(const double& diff); + + typedef std::set>> DiagnoseLabelTestPtr_set; + //Set the contains a pair