diff options
48 files changed, 690 insertions, 352 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8bc1d6498..806c8a0fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,8 +9,8 @@ jobs: - uses: actions/checkout@v1 with: submodules: recursive - - name: update brew and install dependencies - run: brew update && brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf + - name: install dependencies + run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf - name: build run: make -j3 @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v1 with: submodules: recursive - - uses: eine/setup-msys2@v1 + - uses: eine/setup-msys2@v2 with: update: true install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb git diff --git a/CMakeLists.txt b/CMakeLists.txt index 316fd7ed8..0920b34f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,20 @@ else() message(STATUS "ccache deselected") endif() +if (${CMAKE_VERSION} VERSION_GREATER "3.0.0" AND CMAKE_MAKE_PROGRAM MATCHES "ninja") + set(MONERO_PARALLEL_COMPILE_JOBS "" CACHE STRING "The maximum number of concurrent compilation jobs.") + if (MONERO_PARALLEL_COMPILE_JOBS) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS compile_job_pool=${MONERO_PARALLEL_COMPILE_JOBS}) + set(CMAKE_JOB_POOL_COMPILE compile_job_pool) + endif () + + set(MONERO_PARALLEL_LINK_JOBS "" CACHE STRING "The maximum number of concurrent link jobs.") + if (MONERO_PARALLEL_LINK_JOBS) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${MONERO_PARALLEL_LINK_JOBS}) + set(CMAKE_JOB_POOL_LINK link_job_pool) + endif () +endif() + enable_language(C ASM) function (die msg) @@ -95,15 +95,13 @@ The Monero donation address is: `888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnj The Bitcoin donation address is: `1KTexdemPdxSBcG55heUuTjDRYqbC5ZL8H` -Core development funding and/or some supporting services are also graciously provided by sponsors: +Core development funding and/or some supporting services are also graciously provided by [sponsors](https://www.getmonero.org/community/sponsorships/): -[<img width="80" src="https://static.getmonero.org/images/sponsors/mymonero.png"/>](https://mymonero.com) -[<img width="150" src="https://static.getmonero.org/images/sponsors/kitware.png?1"/>](https://kitware.com) -[<img width="100" src="https://static.getmonero.org/images/sponsors/dome9.png"/>](https://dome9.com) -[<img width="150" src="https://static.getmonero.org/images/sponsors/araxis.png"/>](https://araxis.com) -[<img width="150" src="https://static.getmonero.org/images/sponsors/jetbrains.png"/>](https://www.jetbrains.com/) -[<img width="150" src="https://static.getmonero.org/images/sponsors/navicat.png"/>](https://www.navicat.com/) -[<img width="150" src="https://static.getmonero.org/images/sponsors/symas.png"/>](https://www.symas.com/) +[<img width="150" src="https://www.getmonero.org/img/sponsors/tarilabs.png"/>](https://tarilabs.com/) +[<img width="150" src="https://www.getmonero.org/img/sponsors/globee.png"/>](https://globee.com/) +[<img width="150" src="https://www.getmonero.org/img/sponsors/symas.png"/>](https://symas.com/) +[<img width="150" src="https://www.getmonero.org/img/sponsors/forked_logo.png"/>](http://www.forked.net/) +[<img width="150" src="https://www.getmonero.org/img/sponsors/macstadium.png"/>](https://www.macstadium.com/) There are also several mining pools that kindly donate a portion of their fees, [a list of them can be found on our Bitcointalk post](https://bitcointalk.org/index.php?topic=583449.0). @@ -113,7 +111,7 @@ See [LICENSE](LICENSE). ## Contributing -If you want to help out, see [CONTRIBUTING](CONTRIBUTING.md) for a set of guidelines. +If you want to help out, see [CONTRIBUTING](docs/CONTRIBUTING.md) for a set of guidelines. ## Scheduled software upgrades @@ -134,8 +132,8 @@ Dates are provided in the format YYYY-MM-DD. | 1788000 | 2019-03-09 | v10 | v0.14.0.0 | v0.14.1.2 | New PoW based on Cryptonight-R, new block weight algorithm, slightly more efficient RingCT format | 1788720 | 2019-03-10 | v11 | v0.14.0.0 | v0.14.1.2 | forbid old RingCT transaction format | 1978433 | 2019-11-30* | v12 | v0.15.0.0 | v0.16.0.0 | New PoW based on RandomX, only allow >= 2 outputs, change to the block median used to calculate penalty, v1 coinbases are forbidden, rct sigs in coinbase forbidden, 10 block lock time for incoming outputs -| 2210000 | 2020-10-17 | v13 | v0.17.0.0 | v0.17.0.0 | New CLSAG transaction format -| 2210720 | 2020-10-18 | v14 | v0.17.0.0 | v0.17.0.0 | forbid old MLSAG transaction format +| 2210000 | 2020-10-17 | v13 | v0.17.0.0 | v0.17.1.1 | New CLSAG transaction format +| 2210720 | 2020-10-18 | v14 | v0.17.1.1 | v0.17.1.1 | forbid old MLSAG transaction format | XXXXXXX | XXX-XX-XX | XXX | vX.XX.X.X | vX.XX.X.X | XXX | X's indicate that these details have not been determined as of commit date. @@ -295,7 +293,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch ( ```bash git clone https://github.com/monero-project/monero.git cd monero - git checkout tags/v0.17.0.0 + git checkout tags/v0.17.1.0 ``` * Build: @@ -412,10 +410,10 @@ application. cd monero ``` -* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.17.0.0'. If you don't care about the version and just want binaries from master, skip this step: +* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.17.1.0'. If you don't care about the version and just want binaries from master, skip this step: ```bash - git checkout v0.17.0.0 + git checkout v0.17.1.0 ``` * If you are on a 64-bit system, run: @@ -650,11 +648,11 @@ monero-wallet-cli, and possibly monerod, if you get crashes refreshing. ## Internationalization -See [README.i18n.md](README.i18n.md). +See [README.i18n.md](docs/README.i18n.md). ## Using Tor -> There is a new, still experimental, [integration with Tor](ANONYMITY_NETWORKS.md). The +> There is a new, still experimental, [integration with Tor](docs/ANONYMITY_NETWORKS.md). The > feature allows connecting over IPv4 and Tor simultaneously - IPv4 is used for > relaying blocks and relaying transactions received by peers whereas Tor is > used solely for relaying transactions received over local RPC. This provides diff --git a/cmake/CheckTrezor.cmake b/cmake/CheckTrezor.cmake index d2fe60d92..f600cc0bb 100644 --- a/cmake/CheckTrezor.cmake +++ b/cmake/CheckTrezor.cmake @@ -91,7 +91,7 @@ endif() # Protobuf compilation test if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON) - execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} -I "${CMAKE_SOURCE_DIR}/cmake" -I "${Protobuf_INCLUDE_DIR}" "${CMAKE_SOURCE_DIR}/cmake/test-protobuf.proto" --cpp_out ${CMAKE_BINARY_DIR} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR) + execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} -I "${CMAKE_CURRENT_LIST_DIR}" -I "${Protobuf_INCLUDE_DIR}" "${CMAKE_CURRENT_LIST_DIR}/test-protobuf.proto" --cpp_out ${CMAKE_BINARY_DIR} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR) if(RET) message(STATUS "Protobuf test generation failed: ${OUT} ${ERR}") endif() @@ -100,7 +100,7 @@ if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON) "${CMAKE_BINARY_DIR}" SOURCES "${CMAKE_BINARY_DIR}/test-protobuf.pb.cc" - "${CMAKE_SOURCE_DIR}/cmake/test-protobuf.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test-protobuf.cpp" CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${Protobuf_INCLUDE_DIR};${CMAKE_BINARY_DIR}" "-DCMAKE_CXX_STANDARD=11" diff --git a/cmake/Version.cmake b/cmake/Version.cmake index a6c13ab6c..707d72639 100644 --- a/cmake/Version.cmake +++ b/cmake/Version.cmake @@ -28,7 +28,7 @@ function (write_version tag) set(VERSIONTAG "${tag}" CACHE STRING "The tag portion of the Monero software version" FORCE) - configure_file("${CMAKE_SOURCE_DIR}/src/version.cpp.in" "${CMAKE_BINARY_DIR}/version.cpp") + configure_file("${CMAKE_CURRENT_LIST_DIR}/../src/version.cpp.in" "${CMAKE_BINARY_DIR}/version.cpp") endfunction () find_package(Git QUIET) diff --git a/contrib/depends/packages/qt.mk b/contrib/depends/packages/qt.mk index 98cef4631..76c50f3fd 100644 --- a/contrib/depends/packages/qt.mk +++ b/contrib/depends/packages/qt.mk @@ -1,18 +1,18 @@ PACKAGE=qt -$(package)_version=5.7.1 -$(package)_download_path=http://linorg.usp.br/Qt/archive/qt/5.7/5.7.1/submodules -$(package)_suffix=opensource-src-$($(package)_version).tar.gz +$(package)_version=5.15.1 +$(package)_download_path=https://download.qt.io/official_releases/qt/5.15/$($(package)_version)/submodules +$(package)_suffix=everywhere-src-$($(package)_version).tar.xz $(package)_file_name=qtbase-$($(package)_suffix) -$(package)_sha256_hash=95f83e532d23b3ddbde7973f380ecae1bac13230340557276f75f2e37984e410 +$(package)_sha256_hash=33960404d579675b7210de103ed06a72613bfc4305443e278e2d32a3eb1f3d8c $(package)_build_subdir=qtbase $(package)_qt_libs=corelib -$(package)_patches=pidlist_absolute.patch fix_qt_pkgconfig.patch qfixed-coretext.patch +$(package)_patches=fix_qt_pkgconfig.patch fix_no_printer.patch fix_rcc_determinism.patch no-xlib.patch $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) -$(package)_qttranslations_sha256_hash=3a15aebd523c6d89fb97b2d3df866c94149653a26d27a00aac9b6d3020bc5a1d +$(package)_qttranslations_sha256_hash=46e0c0e3a511fbcc803a4146204062e47f6ed43b34d98a3c27372a03b8746bd8 $(package)_qttools_file_name=qttools-$($(package)_suffix) -$(package)_qttools_sha256_hash=22d67de915cb8cd93e16fdd38fa006224ad9170bd217c2be1e53045a8dd02f0f +$(package)_qttools_sha256_hash=c98ee5f0f980bf68cbf0c94d62434816a92441733de50bd9adbe9b9055f03498 $(package)_extra_sources = $($(package)_qttranslations_file_name) $(package)_extra_sources += $($(package)_qttools_file_name) @@ -24,28 +24,26 @@ $(package)_config_opts += -bindir $(build_prefix)/bin $(package)_config_opts += -c++std c++11 $(package)_config_opts += -confirm-license $(package)_config_opts += -dbus-runtime -$(package)_config_opts += -no-alsa -$(package)_config_opts += -no-audio-backend +$(package)_config_opts += -hostprefix $(build_prefix) +$(package)_config_opts += -no-compile-examples $(package)_config_opts += -no-cups $(package)_config_opts += -no-egl $(package)_config_opts += -no-eglfs -$(package)_config_opts += -no-feature-style-windowsmobile -$(package)_config_opts += -no-feature-style-windowsce +$(package)_config_opts += -no-evdev +$(package)_config_opts += -no-gui $(package)_config_opts += -no-freetype $(package)_config_opts += -no-gif $(package)_config_opts += -no-glib -$(package)_config_opts += -no-gstreamer $(package)_config_opts += -no-icu +$(package)_config_opts += -no-ico $(package)_config_opts += -no-iconv $(package)_config_opts += -no-kms $(package)_config_opts += -no-linuxfb +$(package)_config_opts += -no-libjpeg $(package)_config_opts += -no-libudev -$(package)_config_opts += -no-mitshm $(package)_config_opts += -no-mtdev -$(package)_config_opts += -no-pulseaudio $(package)_config_opts += -no-openvg $(package)_config_opts += -no-reduce-relocations -$(package)_config_opts += -no-qml-debug $(package)_config_opts += -no-sql-db2 $(package)_config_opts += -no-sql-ibase $(package)_config_opts += -no-sql-oci @@ -56,8 +54,6 @@ $(package)_config_opts += -no-sql-psql $(package)_config_opts += -no-sql-sqlite $(package)_config_opts += -no-sql-sqlite2 $(package)_config_opts += -no-use-gold-linker -$(package)_config_opts += -no-xinput2 -$(package)_config_opts += -no-xrender $(package)_config_opts += -nomake examples $(package)_config_opts += -nomake tests $(package)_config_opts += -opensource @@ -65,25 +61,46 @@ $(package)_config_opts += -no-openssl $(package)_config_opts += -optimized-qmake $(package)_config_opts += -pch $(package)_config_opts += -pkg-config +$(package)_config_opts += -prefix $(host_prefix) $(package)_config_opts += -no-libpng -$(package)_config_opts += -no-libjpeg $(package)_config_opts += -qt-pcre +$(package)_config_opts += -qt-harfbuzz $(package)_config_opts += -no-zlib -$(package)_config_opts += -reduce-exports $(package)_config_opts += -static $(package)_config_opts += -silent $(package)_config_opts += -v -$(package)_config_opts += -no-feature-printer +$(package)_config_opts += -no-feature-bearermanagement +$(package)_config_opts += -no-feature-colordialog +$(package)_config_opts += -no-feature-dial +$(package)_config_opts += -no-feature-filesystemwatcher +$(package)_config_opts += -no-feature-fontcombobox +$(package)_config_opts += -no-feature-ftp +$(package)_config_opts += -no-feature-image_heuristic_mask +$(package)_config_opts += -no-feature-keysequenceedit +$(package)_config_opts += -no-feature-lcdnumber +$(package)_config_opts += -no-feature-pdf $(package)_config_opts += -no-feature-printdialog -$(package)_config_opts += -no-gui -$(package)_config_opts += -no-freetype -$(package)_config_opts += -no-sm -$(package)_config_opts += -no-fontconfig -$(package)_config_opts += -no-opengl -$(package)_config_opts += -no-xkb -$(package)_config_opts += -no-xcb -$(package)_config_opts += -no-xshape -$(package)_build_env = QT_RCC_TEST=1 +$(package)_config_opts += -no-feature-printer +$(package)_config_opts += -no-feature-printpreviewdialog +$(package)_config_opts += -no-feature-printpreviewwidget +$(package)_config_opts += -no-feature-sessionmanager +$(package)_config_opts += -no-feature-sql +$(package)_config_opts += -no-feature-statemachine +$(package)_config_opts += -no-feature-syntaxhighlighter +$(package)_config_opts += -no-feature-textbrowser +$(package)_config_opts += -no-feature-textodfwriter +$(package)_config_opts += -no-feature-topleveldomain +$(package)_config_opts += -no-feature-udpsocket +$(package)_config_opts += -no-feature-undocommand +$(package)_config_opts += -no-feature-undogroup +$(package)_config_opts += -no-feature-undostack +$(package)_config_opts += -no-feature-undoview +$(package)_config_opts += -no-feature-vnc +$(package)_config_opts += -no-feature-wizard +$(package)_config_opts_linux = -no-fontconfig +$(package)_config_opts_linux += -no-opengl +$(package)_config_opts_linux += -no-xcb +$(package)_config_opts_linux += -no-feature-xlib endef define $(package)_fetch_cmds @@ -108,14 +125,24 @@ endef define $(package)_preprocess_cmds + sed -i.old "s|FT_Get_Font_Format|FT_Get_X11_Font_Format|" qtbase/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp && \ sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \ sed -i.old "/updateqm.depends =/d" qttranslations/translations/translations.pro && \ - patch -p1 < $($(package)_patch_dir)/pidlist_absolute.patch && \ - patch -p1 < $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \ - patch -p1 < $($(package)_patch_dir)/qfixed-coretext.patch && \ + sed -i.old "s/src_plugins.depends = src_sql src_network/src_plugins.depends = src_network/" qtbase/src/src.pro && \ + cp -r qtbase/mkspecs/linux-arm-gnueabi-g++ qtbase/mkspecs/bitcoin-linux-g++ && \ + sed -i.old "s/arm-linux-gnueabi-/$(host)-/g" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \ + patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch && \ echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ - echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf + echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ + patch -p1 -i $($(package)_patch_dir)/no-xlib.patch && \ + echo "QMAKE_LINK_OBJECT_MAX = 10" >> qtbase/mkspecs/win32-g++/qmake.conf && \ + echo "QMAKE_LINK_OBJECT_SCRIPT = object_script" >> qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s|QMAKE_CFLAGS += |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s|QMAKE_CXXFLAGS += |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "0,/^QMAKE_LFLAGS_/s|^QMAKE_LFLAGS_|!host_build: QMAKE_LFLAGS = $($(package)_ldflags)\n&|" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s/LIBRARY_PATH/(CROSS_)?\0/g" qtbase/mkspecs/features/toolchain.prf endef define $(package)_config_cmds diff --git a/contrib/depends/patches/qt/fix_no_printer.patch b/contrib/depends/patches/qt/fix_no_printer.patch new file mode 100644 index 000000000..137235613 --- /dev/null +++ b/contrib/depends/patches/qt/fix_no_printer.patch @@ -0,0 +1,19 @@ +--- x/qtbase/src/plugins/platforms/cocoa/qprintengine_mac_p.h ++++ y/qtbase/src/plugins/platforms/cocoa/qprintengine_mac_p.h +@@ -52,6 +52,7 @@ + // + + #include <QtCore/qglobal.h> ++#include <qpa/qplatformprintdevice.h> + + #ifndef QT_NO_PRINTER + +--- x/qtbase/src/plugins/plugins.pro ++++ y/qtbase/src/plugins/plugins.pro +@@ -9,6 +9,3 @@ qtHaveModule(gui) { + !android:qtConfig(library): SUBDIRS *= generic + } + qtHaveModule(widgets): SUBDIRS += styles +- +-!winrt:qtHaveModule(printsupport): \ +- SUBDIRS += printsupport diff --git a/contrib/depends/patches/qt/fix_qt_pkgconfig.patch b/contrib/depends/patches/qt/fix_qt_pkgconfig.patch index 34302a9f2..73f4d89f7 100644 --- a/contrib/depends/patches/qt/fix_qt_pkgconfig.patch +++ b/contrib/depends/patches/qt/fix_qt_pkgconfig.patch @@ -1,11 +1,11 @@ --- old/qtbase/mkspecs/features/qt_module.prf +++ new/qtbase/mkspecs/features/qt_module.prf -@@ -245,7 +245,7 @@ +@@ -269,7 +269,7 @@ load(qt_installs) load(qt_targets) # this builds on top of qt_common --!internal_module:!lib_bundle:if(unix|mingw) { -+unix|mingw { +-!internal_module:if(unix|mingw):!if(darwin:debug_and_release:CONFIG(debug, debug|release)) { ++if(unix|mingw):!if(darwin:debug_and_release:CONFIG(debug, debug|release)) { CONFIG += create_pc QMAKE_PKGCONFIG_DESTDIR = pkgconfig host_build: \ diff --git a/contrib/depends/patches/qt/fix_rcc_determinism.patch b/contrib/depends/patches/qt/fix_rcc_determinism.patch new file mode 100644 index 000000000..c1b07fe23 --- /dev/null +++ b/contrib/depends/patches/qt/fix_rcc_determinism.patch @@ -0,0 +1,15 @@ +--- old/qtbase/src/tools/rcc/rcc.cpp ++++ new/qtbase/src/tools/rcc/rcc.cpp +@@ -207,7 +207,11 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib) + if (lib.formatVersion() >= 2) { + // last modified time stamp + const QDateTime lastModified = m_fileInfo.lastModified(); +- lib.writeNumber8(quint64(lastModified.isValid() ? lastModified.toMSecsSinceEpoch() : 0)); ++ quint64 lastmod = quint64(lastModified.isValid() ? lastModified.toMSecsSinceEpoch() : 0); ++ static const quint64 sourceDate = 1000 * qgetenv("QT_RCC_SOURCE_DATE_OVERRIDE").toULongLong(); ++ if (sourceDate != 0) ++ lastmod = sourceDate; ++ lib.writeNumber8(lastmod); + if (text || pass1) + lib.writeChar('\n'); + } diff --git a/contrib/depends/patches/qt/no-xlib.patch b/contrib/depends/patches/qt/no-xlib.patch new file mode 100644 index 000000000..6800d398c --- /dev/null +++ b/contrib/depends/patches/qt/no-xlib.patch @@ -0,0 +1,69 @@ +From 9563cef873ae82e06f60708d706d054717e801ce Mon Sep 17 00:00:00 2001 +From: Carl Dong <contact@carldong.me> +Date: Thu, 18 Jul 2019 17:22:05 -0400 +Subject: [PATCH] Wrap xlib related code blocks in #if's + +They are not necessary to compile QT. +--- + qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp +index 7c62c2e2b3..c05c6c0a07 100644 +--- a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp ++++ b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp +@@ -49,7 +49,9 @@ + #include <QtGui/QWindow> + #include <QtGui/QBitmap> + #include <QtGui/private/qguiapplication_p.h> ++#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library) + #include <X11/cursorfont.h> ++#endif + #include <xcb/xfixes.h> + #include <xcb/xcb_image.h> + +@@ -391,6 +393,7 @@ void QXcbCursor::changeCursor(QCursor *cursor, QWindow *window) + xcb_flush(xcb_connection()); + } + ++#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library) + static int cursorIdForShape(int cshape) + { + int cursorId = 0; +@@ -444,6 +447,7 @@ static int cursorIdForShape(int cshape) + } + return cursorId; + } ++#endif + + xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape) + { +@@ -556,7 +560,9 @@ static xcb_cursor_t loadCursor(void *dpy, int cshape) + xcb_cursor_t QXcbCursor::createFontCursor(int cshape) + { + xcb_connection_t *conn = xcb_connection(); ++#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library) + int cursorId = cursorIdForShape(cshape); ++#endif + xcb_cursor_t cursor = XCB_NONE; + + // Try Xcursor first +@@ -586,6 +592,7 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape) + // Non-standard X11 cursors are created from bitmaps + cursor = createNonStandardCursor(cshape); + ++#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library) + // Create a glpyh cursor if everything else failed + if (!cursor && cursorId) { + cursor = xcb_generate_id(conn); +@@ -593,6 +600,7 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape) + cursorId, cursorId + 1, + 0xFFFF, 0xFFFF, 0xFFFF, 0, 0, 0); + } ++#endif + + if (cursor && cshape >= 0 && cshape < Qt::LastCursor && connection()->hasXFixes()) { + const char *name = cursorNames[cshape].front(); +--- +2.22.0 + diff --git a/contrib/depends/patches/qt/pidlist_absolute.patch b/contrib/depends/patches/qt/pidlist_absolute.patch deleted file mode 100644 index c79282417..000000000 --- a/contrib/depends/patches/qt/pidlist_absolute.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff -dur old/qtbase/src/plugins/platforms/windows/qwindowscontext.h new/qtbase/src/plugins/platforms/windows/qwindowscontext.h ---- old/qtbase/src/plugins/platforms/windows/qwindowscontext.h -+++ new/qtbase/src/plugins/platforms/windows/qwindowscontext.h -@@ -136,10 +136,18 @@ - inline void init(); - - typedef HRESULT (WINAPI *SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **); -+#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3) -+ typedef HRESULT (WINAPI *SHGetKnownFolderIDList)(const GUID &, DWORD, HANDLE, ITEMIDLIST **); -+#else - typedef HRESULT (WINAPI *SHGetKnownFolderIDList)(const GUID &, DWORD, HANDLE, PIDLIST_ABSOLUTE *); -+#endif - typedef HRESULT (WINAPI *SHGetStockIconInfo)(int , int , _SHSTOCKICONINFO *); - typedef HRESULT (WINAPI *SHGetImageList)(int, REFIID , void **); -+#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3) -+ typedef HRESULT (WINAPI *SHCreateItemFromIDList)(const ITEMIDLIST *, REFIID, void **); -+#else - typedef HRESULT (WINAPI *SHCreateItemFromIDList)(PCIDLIST_ABSOLUTE, REFIID, void **); -+#endif - - SHCreateItemFromParsingName sHCreateItemFromParsingName; - SHGetKnownFolderIDList sHGetKnownFolderIDList; -diff -dur old/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp new/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp ---- old/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp -+++ new/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp -@@ -1016,7 +1016,11 @@ - qWarning() << __FUNCTION__ << ": Invalid CLSID: " << url.path(); - return Q_NULLPTR; - } -+#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3) -+ ITEMIDLIST *idList; -+#else - PIDLIST_ABSOLUTE idList; -+#endif - HRESULT hr = QWindowsContext::shell32dll.sHGetKnownFolderIDList(uuid, 0, 0, &idList); - if (FAILED(hr)) { - qErrnoWarning("%s: SHGetKnownFolderIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString())); diff --git a/contrib/depends/patches/qt/qfixed-coretext.patch b/contrib/depends/patches/qt/qfixed-coretext.patch deleted file mode 100644 index aa56f1e1d..000000000 --- a/contrib/depends/patches/qt/qfixed-coretext.patch +++ /dev/null @@ -1,34 +0,0 @@ -From dbdd5f0ffbce52c8b789ed09f1aa3f1da6c02e23 Mon Sep 17 00:00:00 2001 -From: Gabriel de Dietrich <gabriel.dedietrich@qt.io> -Date: Fri, 30 Mar 2018 11:58:16 -0700 -Subject: [PATCH] QCoreTextFontEngine: Fix build with Xcode 9.3 - -Apple LLVM version 9.1.0 (clang-902.0.39.1) - -Error message: - -.../qfontengine_coretext.mm:827:20: error: qualified reference to - 'QFixed' is a constructor name rather than a type in this context - return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont))); - -Change-Id: Iebe26b3b087a16b10664208fc8851cbddb47f043 -Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> ---- - src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git old/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm new/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm -index 25ff69d877d..98b753eff96 100644 ---- old/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm -+++ new/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm -@@ -824,7 +824,7 @@ void QCoreTextFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, gl - - QFixed QCoreTextFontEngine::emSquareSize() const - { -- return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont))); -+ return QFixed(int(CTFontGetUnitsPerEm(ctfont))); - } - - QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const --- -2.16.3
\ No newline at end of file diff --git a/contrib/gitian/gitian-freebsd.yml b/contrib/gitian/gitian-freebsd.yml index c104bfd02..36b81c641 100644 --- a/contrib/gitian/gitian-freebsd.yml +++ b/contrib/gitian/gitian-freebsd.yml @@ -119,7 +119,7 @@ script: | for i in ${HOSTS}; do export PATH=${WRAP_DIR}:${BASEPREFIX}/${i}/native/bin:${ORIGPATH} mkdir build && cd build - cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DCMAKE_BUILD_TYPE=Release + cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_SKIP_RPATH=ON make ${MAKEOPTS} chmod 755 bin/* cp ../LICENSE bin diff --git a/contrib/gitian/gitian-linux.yml b/contrib/gitian/gitian-linux.yml index 4a2f3798a..0aac983cc 100644 --- a/contrib/gitian/gitian-linux.yml +++ b/contrib/gitian/gitian-linux.yml @@ -111,6 +111,11 @@ script: | rm -f $WRAP_DIR/extra_includes/i686-linux-gnu/asm ln -s /usr/include/x86_64-linux-gnu/asm $EXTRA_INCLUDES_BASE/i686-linux-gnu/asm + # glibc 2.23 breaks compatibility with <=2.19 use of lgamma function. + # Hack the math header to restore the old behavior. + mkdir $EXTRA_INCLUDES_BASE/bits + sed -e '/__REDIRFROM .lgamma,/,+3s/_USE_/_DONTUSE_/g' /usr/include/x86_64-linux-gnu/bits/math-finite.h > $EXTRA_INCLUDES_BASE/bits/math-finite.h + # gcc 7+ honors SOURCE_DATE_EPOCH, no faketime needed export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s` @@ -127,14 +132,14 @@ script: | # Build dependencies for each host export TAR_OPTIONS=--mtime=2000-01-01T12:00:00 for i in $HOSTS; do - EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i" - if [ -d "$EXTRA_INCLUDES" ]; then - export C_INCLUDE_PATH="$EXTRA_INCLUDES" - export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES" + ARCH_INCLUDES="$EXTRA_INCLUDES_BASE/$i" + if [ -d "$ARCH_INCLUDES" ]; then + EXTRA_INCLUDES="${EXTRA_INCLUDES_BASE}:${ARCH_INCLUDES}" else - unset C_INCLUDE_PATH - unset CPLUS_INCLUDE_PATH + EXTRA_INCLUDES="${EXTRA_INCLUDES_BASE}" fi + export C_INCLUDE_PATH="$EXTRA_INCLUDES" + export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES" make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" V=1 done @@ -151,15 +156,15 @@ script: | for i in ${HOSTS}; do export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} mkdir build && cd build - EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i" - if [ -d "$EXTRA_INCLUDES" ]; then - export C_INCLUDE_PATH="$EXTRA_INCLUDES" - export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES" + ARCH_INCLUDES="$EXTRA_INCLUDES_BASE/$i" + if [ -d "$ARCH_INCLUDES" ]; then + EXTRA_INCLUDES="${EXTRA_INCLUDES_BASE}:${ARCH_INCLUDES}" else - unset C_INCLUDE_PATH - unset CPLUS_INCLUDE_PATH + EXTRA_INCLUDES="${EXTRA_INCLUDES_BASE}" fi - cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=ON + export C_INCLUDE_PATH="$EXTRA_INCLUDES" + export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES" + cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=ON -DCMAKE_SKIP_RPATH=ON make ${MAKEOPTS} chmod 755 bin/* cp ../LICENSE bin diff --git a/ANONYMITY_NETWORKS.md b/docs/ANONYMITY_NETWORKS.md index 3337b5fc3..3337b5fc3 100644 --- a/ANONYMITY_NETWORKS.md +++ b/docs/ANONYMITY_NETWORKS.md diff --git a/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 7b184c00a..7b184c00a 100644 --- a/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md diff --git a/LEVIN_PROTOCOL.md b/docs/LEVIN_PROTOCOL.md index 207509146..43500fd06 100644 --- a/LEVIN_PROTOCOL.md +++ b/docs/LEVIN_PROTOCOL.md @@ -10,7 +10,7 @@ extensibility. One of the goals of this document is to clearly indicate what is being sent "on the wire" to identify metadata that could de-anonymize users over I2P/Tor. These issues will be addressed as they are found. See `ANONMITY_NETWORKS.md` in -the top-level folder for any outstanding issues. +the `docs` folder for any outstanding issues. > This document does not currently list all data being sent by the monero > protocol, that portion is a work-in-progress. Please take the time to do it diff --git a/README.i18n.md b/docs/README.i18n.md index 5df277624..5df277624 100644 --- a/README.i18n.md +++ b/docs/README.i18n.md diff --git a/docs/RELEASE_CHECKLIST.md b/docs/RELEASE_CHECKLIST.md new file mode 100644 index 000000000..632366985 --- /dev/null +++ b/docs/RELEASE_CHECKLIST.md @@ -0,0 +1,68 @@ +- [ ] Security audit +- [ ] Code audit +- [ ] Ledger integration + - [ ] Implemented in Monero codebase (if needed) + - [ ] Ledger app integration coded by Ledger + - [ ] Ledger Monero app update available +- [ ] Trezor integration + - [ ] Implemented in Monero codebase (if needed) + - [ ] Trezor app integration coded by Trezor + - [ ] Trezor firmware update available (if needed) +- [ ] Fork height set + - [ ] Monero-announce mailer notice + - [ ] Twitter announcement + - [ ] Reddit announcement + - [ ] Getmonero.org announcement +- [ ] Notify wallets + - [ ] MyMonero + - [ ] Coinomi + - [ ] Exa Wallet + - [ ] Wookey Wallet + - [ ] X Wallet + - [ ] Guarda + - [ ] ZelCore + - [ ] Cake Wallet + - [ ] Monerujo + - [ ] Edge Wallet + - [ ] Exodus + - [ ] XMRWallet +- [ ] Notify exchanges + - [ ] https://web.getmonero.org/community/merchants/#exchanges +- [ ] Notify 3rd party payment processors + - [ ] https://web.getmonero.org/community/merchants/#payment-gateways +- [ ] Notify mining pools + - [ ] https://miningpoolstats.stream/monero +- [ ] Release tagged + - [ ] Update src/version.cpp.in with new version AND new name (if necessary) + - [ ] Update Gitian YML files in contrib/gitian/ to the new version number + - [ ] Update README.md with new fork table entry (or at least update the Recommended Monero version) + - [ ] Update contrib/gitian/README.md so that the instructions reflect the current version + - [ ] Update src/checkpoints/checkpoints.cpp with a recent hardcoded checkpoint + - [ ] Update src/blocks/checkpoints.dat with ./monero-blockchain-export --output-file checkpoints.dat --block-stop <recent block height> --blocksdat + - [ ] Update expected_block_hashes_hash in src/cryptonote_core/blockchain.cpp with checkpoints.dat sha256 hash +- [ ] Testnet forked +- [ ] Testnet testing/verification + - [ ] Ledger + - [ ] Trezor + - [ ] Release-specific testing + - [ ] RPC testing/update RPC documentation +- [ ] CLI reproducible builds validated +- [ ] CLI released + - [ ] https://web.getmonero.org/downloads/ updated + - [ ] Update hashes.txt on website + - [ ] Update downloads.yml on website + - [ ] Update auto-update DNS records + - [ ] Update redirects on downloads box + - [ ] Update seed nodes +- [ ] GUI released + - [ ] https://web.getmonero.org/downloads/ updated + - [ ] Update hashes.txt on website + - [ ] Update hashes.txt.sig on website + - [ ] Update downloads.yml on website + - [ ] Update auto-update DNS records + - [ ] Update redirects on downloads box +- [ ] Release Announcements + - [ ] Monero-announce mailer notice + - [ ] Twitter announcement + - [ ] Reddit announcement + - [ ] Getmonero.org announcement diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 93e3ef3bc..f91b3d6c1 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3068,9 +3068,21 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context if (tx.version >= 2) { if (tx.rct_signatures.type <= rct::RCTTypeBulletproof2) { - MERROR_VER("Ringct type " << (unsigned)tx.rct_signatures.type << " is not allowed from v" << (HF_VERSION_CLSAG + 1)); - tvc.m_invalid_output = true; - return false; + // two MLSAG txes went in due to a bug with txes that went into the txpool before the fork, grandfather them in + static const char * grandfathered[2] = { "c5151944f0583097ba0c88cd0f43e7fabb3881278aa2f73b3b0a007c5d34e910", "6f2f117cde6fbcf8d4a6ef8974fcac744726574ac38cf25d3322c996b21edd4c" }; + crypto::hash h0, h1; + epee::string_tools::hex_to_pod(grandfathered[0], h0); + epee::string_tools::hex_to_pod(grandfathered[1], h1); + if (cryptonote::get_transaction_hash(tx) == h0 || cryptonote::get_transaction_hash(tx) == h1) + { + MDEBUG("Grandfathering cryptonote::get_transaction_hash(tx) in"); + } + else + { + MERROR_VER("Ringct type " << (unsigned)tx.rct_signatures.type << " is not allowed from v" << (HF_VERSION_CLSAG + 1)); + tvc.m_invalid_output = true; + return false; + } } } } diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index c9d26e0ed..7c578ac51 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -663,7 +663,7 @@ namespace cryptonote * * @param target_blockchain_height the target height */ - uint64_t get_target_blockchain_height() const; + virtual uint64_t get_target_blockchain_height() const override; /** * @brief returns the newest hardfork version known to the blockchain diff --git a/src/cryptonote_core/i_core_events.h b/src/cryptonote_core/i_core_events.h index 03394d785..addb659ab 100644 --- a/src/cryptonote_core/i_core_events.h +++ b/src/cryptonote_core/i_core_events.h @@ -39,6 +39,7 @@ namespace cryptonote virtual ~i_core_events() noexcept {} + virtual uint64_t get_target_blockchain_height() const = 0; virtual void on_transactions_relayed(epee::span<const cryptonote::blobdata> tx_blobs, relay_method tx_relay) = 0; }; } diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 85bcf2246..28721ee36 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1391,7 +1391,10 @@ namespace cryptonote txpool_tx_meta_t meta; if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta)) { - MERROR(" failed to find tx meta"); + static bool warned = false; + if (!warned) + MERROR(" failed to find tx meta: " << sorted_it->second << " (will only print once)"); + warned = true; continue; } LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase) << ", relay method " << (unsigned)meta.get_relay_method()); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 337885509..a8073e091 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -2538,7 +2538,7 @@ skip: local mempool before doing the relay. The code was already updating the DB twice on received transactions - it is difficult to workaround this due to the internal design. */ - return m_p2p->send_txs(std::move(arg.txs), zone, source, m_core, tx_relay) != epee::net_utils::zone::invalid; + return m_p2p->send_txs(std::move(arg.txs), zone, source, tx_relay) != epee::net_utils::zone::invalid; } //------------------------------------------------------------------------------------------------------------------------ template<class t_core> diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp index 7c482156f..634750cab 100644 --- a/src/cryptonote_protocol/levin_notify.cpp +++ b/src/cryptonote_protocol/levin_notify.cpp @@ -105,8 +105,8 @@ namespace levin return std::chrono::steady_clock::duration{crypto::rand_range(rep(0), range.count())}; } - //! \return All outgoing connections supporting fragments in `connections`. - std::vector<boost::uuids::uuid> get_out_connections(connections& p2p) + //! \return Outgoing connections supporting fragments in `connections` filtered by remote blockchain height. + std::vector<boost::uuids::uuid> get_out_connections(connections& p2p, uint64_t min_blockchain_height) { std::vector<boost::uuids::uuid> outs; outs.reserve(connection_id_reserve_size); @@ -115,8 +115,8 @@ namespace levin the reserve call so a strand is not used. Investigate if there is lots of waiting in here. */ - p2p.foreach_connection([&outs] (detail::p2p_context& context) { - if (!context.m_is_income) + p2p.foreach_connection([&outs, min_blockchain_height] (detail::p2p_context& context) { + if (!context.m_is_income && context.m_remote_blockchain_height >= min_blockchain_height) outs.emplace_back(context.m_connection_id); return true; }); @@ -233,7 +233,7 @@ namespace levin { struct zone { - explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, bool is_public, bool pad_txs) + explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, epee::net_utils::zone zone, bool pad_txs) : p2p(std::move(p2p)), noise(std::move(noise_in)), next_epoch(io_service), @@ -243,7 +243,7 @@ namespace levin channels(), flush_time(std::chrono::steady_clock::time_point::max()), connection_count(0), - is_public(is_public), + nzone(zone), pad_txs(pad_txs), fluffing(false) { @@ -260,7 +260,7 @@ namespace levin std::deque<noise_channel> channels; //!< Never touch after init; only update elements on `noise_channel.strand` std::chrono::steady_clock::time_point flush_time; //!< Next expected Dandelion++ fluff flush std::atomic<std::size_t> connection_count; //!< Only update in strand, can be read at any time - const bool is_public; //!< Zone is public ipv4/ipv6 connections + const epee::net_utils::zone nzone; //!< Zone is public ipv4/ipv6 connections, or i2p or tor const bool pad_txs; //!< Pad txs to the next boundary for privacy bool fluffing; //!< Zone is in Dandelion++ fluff epoch }; @@ -297,7 +297,8 @@ namespace levin if (!channel.connection.is_nil()) channel.queue.push_back(std::move(message_)); else if (destination_ == 0 && zone_->connection_count == 0) - MWARNING("Unable to send transaction(s) over anonymity network - no available outbound connections"); + MWARNING("Unable to send transaction(s) to " << epee::net_utils::zone_to_string(zone_->nzone) << + " - no available outbound connections"); } }; @@ -410,7 +411,7 @@ namespace levin zone->p2p->foreach_connection([txs, now, &zone, &source, &in_duration, &out_duration, &next_flush, &available] (detail::p2p_context& context) { // When i2p/tor, only fluff to outbound connections - if (source != context.m_connection_id && (zone->is_public || !context.m_is_income)) + if (source != context.m_connection_id && (zone->nzone == epee::net_utils::zone::public_ || !context.m_is_income)) { available = true; if (context.fluff_txs.empty()) @@ -544,7 +545,7 @@ namespace levin } // connection list may be outdated, try again - update_channels::run(zone_, get_out_connections(*zone_->p2p)); + update_channels::run(zone_, get_out_connections(*zone_->p2p, core_->get_target_blockchain_height())); } MERROR("Unable to send transaction(s) via Dandelion++ stem"); @@ -577,7 +578,7 @@ namespace levin assert(zone_->strand.running_in_this_thread()); - if (zone_->is_public) + if (zone_->nzone == epee::net_utils::zone::public_) MDEBUG("Starting new Dandelion++ epoch: " << (fluffing_ ? "fluff" : "stem")); zone_->map = std::move(map_); @@ -591,8 +592,9 @@ namespace levin { std::shared_ptr<detail::zone> zone_; const std::size_t channel_; + const i_core_events* core_; - static void wait(const std::chrono::steady_clock::time_point start, std::shared_ptr<detail::zone> zone, const std::size_t index) + static void wait(const std::chrono::steady_clock::time_point start, std::shared_ptr<detail::zone> zone, const std::size_t index, const i_core_events* core) { if (!zone) return; @@ -600,7 +602,7 @@ namespace levin noise_channel& channel = zone->channels.at(index); channel.next_noise.expires_at(start + noise_min_delay + random_duration(noise_delay_range)); channel.next_noise.async_wait( - channel.strand.wrap(send_noise{std::move(zone), index}) + channel.strand.wrap(send_noise{std::move(zone), index, core}) ); } @@ -644,16 +646,18 @@ namespace levin { channel.active = nullptr; channel.connection = boost::uuids::nil_uuid(); + auto height = core_->get_target_blockchain_height(); - auto connections = get_out_connections(*zone_->p2p); + auto connections = get_out_connections(*zone_->p2p, height); if (connections.empty()) - MWARNING("Lost all outbound connections to anonymity network - currently unable to send transaction(s)"); + MWARNING("Unable to send transaction(s) to " << epee::net_utils::zone_to_string(zone_->nzone) << + " - no suitable outbound connections at height " << height); zone_->strand.post(update_channels{zone_, std::move(connections)}); } } - wait(start, std::move(zone_), channel_); + wait(start, std::move(zone_), channel_, core_); } }; @@ -665,6 +669,7 @@ namespace levin std::chrono::seconds min_epoch_; std::chrono::seconds epoch_range_; std::size_t count_; + const i_core_events* core_; //! \pre Should not be invoked within any strand to prevent blocking. void operator()(const boost::system::error_code error = {}) @@ -677,8 +682,9 @@ namespace levin const bool fluffing = crypto::rand_idx(unsigned(100)) < CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY; const auto start = std::chrono::steady_clock::now(); + auto connections = get_out_connections(*(zone_->p2p), core_->get_target_blockchain_height()); zone_->strand.dispatch( - change_channels{zone_, net::dandelionpp::connection_map{get_out_connections(*(zone_->p2p)), count_}, fluffing} + change_channels{zone_, net::dandelionpp::connection_map{std::move(connections), count_}, fluffing} ); detail::zone& alias = *zone_; @@ -688,24 +694,25 @@ namespace levin }; } // anonymous - notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, const bool is_public, const bool pad_txs) - : zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), is_public, pad_txs)) + notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, const bool pad_txs, i_core_events& core) + : zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), zone, pad_txs)) + , core_(std::addressof(core)) { if (!zone_->p2p) throw std::logic_error{"cryptonote::levin::notify cannot have nullptr p2p argument"}; const bool noise_enabled = !zone_->noise.empty(); - if (noise_enabled || is_public) + if (noise_enabled || zone == epee::net_utils::zone::public_) { const auto now = std::chrono::steady_clock::now(); const auto min_epoch = noise_enabled ? noise_min_epoch : dandelionpp_min_epoch; const auto epoch_range = noise_enabled ? noise_epoch_range : dandelionpp_epoch_range; const std::size_t out_count = noise_enabled ? CRYPTONOTE_NOISE_CHANNELS : CRYPTONOTE_DANDELIONPP_STEMS; - start_epoch{zone_, min_epoch, epoch_range, out_count}(); + start_epoch{zone_, min_epoch, epoch_range, out_count, core_}(); for (std::size_t channel = 0; channel < zone_->channels.size(); ++channel) - send_noise::wait(now, zone_, channel); + send_noise::wait(now, zone_, channel, core_); } } @@ -726,7 +733,7 @@ namespace levin return; zone_->strand.dispatch( - update_channels{zone_, get_out_connections(*(zone_->p2p))} + update_channels{zone_, get_out_connections(*(zone_->p2p), core_->get_target_blockchain_height())} ); } @@ -753,7 +760,7 @@ namespace levin zone_->flush_txs.cancel(); } - bool notify::send_txs(std::vector<blobdata> txs, const boost::uuids::uuid& source, i_core_events& core, relay_method tx_relay) + bool notify::send_txs(std::vector<blobdata> txs, const boost::uuids::uuid& source, relay_method tx_relay) { if (txs.empty()) return true; @@ -785,7 +792,7 @@ namespace levin tx_relay = relay_method::local; // do not put into stempool embargo (hopefully not there already!). } - core.on_transactions_relayed(epee::to_span(txs), tx_relay); + core_->on_transactions_relayed(epee::to_span(txs), tx_relay); // Padding is not useful when using noise mode. Send as stem so receiver // forwards in Dandelion++ mode. @@ -817,11 +824,11 @@ namespace levin case relay_method::stem: case relay_method::forward: case relay_method::local: - if (zone_->is_public) + if (zone_->nzone == epee::net_utils::zone::public_) { // this will change a local/forward tx to stem or fluff ... zone_->strand.dispatch( - dandelionpp_notify{zone_, std::addressof(core), std::move(txs), source} + dandelionpp_notify{zone_, core_, std::move(txs), source} ); break; } @@ -832,7 +839,7 @@ namespace levin routine. A "fluff" over i2p/tor is not the same as a "fluff" over ipv4/6. Marking it as "fluff" here will make the tx immediately visible externally from this node, which is not desired. */ - core.on_transactions_relayed(epee::to_span(txs), tx_relay); + core_->on_transactions_relayed(epee::to_span(txs), tx_relay); zone_->strand.dispatch(fluff_notify{zone_, std::move(txs), source}); break; } diff --git a/src/cryptonote_protocol/levin_notify.h b/src/cryptonote_protocol/levin_notify.h index 957794b12..abbf9d461 100644 --- a/src/cryptonote_protocol/levin_notify.h +++ b/src/cryptonote_protocol/levin_notify.h @@ -69,6 +69,7 @@ namespace levin class notify { std::shared_ptr<detail::zone> zone_; + i_core_events* core_; public: struct status @@ -80,10 +81,11 @@ namespace levin //! Construct an instance that cannot notify. notify() noexcept : zone_(nullptr) + , core_(nullptr) {} //! Construct an instance with available notification `zones`. - explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, bool is_public, bool pad_txs); + explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, bool pad_txs, i_core_events& core); notify(const notify&) = delete; notify(notify&&) = default; @@ -123,7 +125,7 @@ namespace levin particular stem. \return True iff the notification is queued for sending. */ - bool send_txs(std::vector<blobdata> txs, const boost::uuids::uuid& source, i_core_events& core, relay_method tx_relay); + bool send_txs(std::vector<blobdata> txs, const boost::uuids::uuid& source, relay_method tx_relay); }; } // levin } // net diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 504b104b0..aac891c4a 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -50,7 +50,7 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>& { if (args.size() > 3) { - std::cout << "use: print_pl [white] [gray] [<limit>] [pruned] [publicrpc]" << std::endl; + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; return true; } @@ -79,7 +79,7 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>& } else if (!epee::string_tools::get_xtype_from_string(limit, args[i])) { - std::cout << "unexpected argument: " << args[i] << std::endl; + std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl; return true; } } @@ -90,56 +90,79 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>& bool t_command_parser_executor::print_peer_list_stats(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.print_peer_list_stats(); } bool t_command_parser_executor::save_blockchain(const std::vector<std::string>& args) { - if (!args.empty()) return false; - + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.save_blockchain(); } bool t_command_parser_executor::show_hash_rate(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.show_hash_rate(); } bool t_command_parser_executor::hide_hash_rate(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.hide_hash_rate(); } bool t_command_parser_executor::show_difficulty(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.show_difficulty(); } bool t_command_parser_executor::show_status(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.show_status(); } bool t_command_parser_executor::print_connections(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.print_connections(); } bool t_command_parser_executor::print_net_stats(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.print_net_stats(); } @@ -148,8 +171,8 @@ bool t_command_parser_executor::print_blockchain_info(const std::vector<std::str { if(!args.size()) { - std::cout << "need block index parameter" << std::endl; - return false; + std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl; + return true; } uint64_t start_index = 0; uint64_t end_index = 0; @@ -158,20 +181,20 @@ bool t_command_parser_executor::print_blockchain_info(const std::vector<std::str int64_t nblocks; if(!epee::string_tools::get_xtype_from_string(nblocks, args[0])) { - std::cout << "wrong number of blocks" << std::endl; - return false; + std::cout << "Invalid syntax: Wrong number of blocks. For more details, use the help command." << std::endl; + return true; } return m_executor.print_blockchain_info(nblocks, (uint64_t)-nblocks); } if(!epee::string_tools::get_xtype_from_string(start_index, args[0])) { - std::cout << "wrong starter block index parameter" << std::endl; - return false; + std::cout << "Invalid syntax: Wrong starter block index parameter. For more details, use the help command." << std::endl; + return true; } if(args.size() >1 && !epee::string_tools::get_xtype_from_string(end_index, args[1])) { - std::cout << "wrong end block index parameter" << std::endl; - return false; + std::cout << "Invalid syntax: Wrong end block index parameter. For more details, use the help command." << std::endl; + return true; } return m_executor.print_blockchain_info(start_index, end_index); @@ -181,7 +204,7 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar { if(args.size() > 1) { - std::cout << "use: set_log [<log_level_number_0-4> | <categories>]" << std::endl; + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; return true; } @@ -195,7 +218,7 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar { if(4 < l) { - std::cout << "wrong number range, use: set_log <log_level_number_0-4>" << std::endl; + std::cout << "Invalid syntax: Wrong number range, use: set_log <log_level_number_0-4>. For more details, use the help command." << std::endl; return true; } return m_executor.set_log_level(l); @@ -208,7 +231,10 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar bool t_command_parser_executor::print_height(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.print_height(); } @@ -223,14 +249,14 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args include_hex = true; else { - std::cout << "unexpected argument: " << args[i] << std::endl; + std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl; return true; } } if (args.empty()) { - std::cout << "expected: print_block (<block_hash> | <block_height>) [+hex]" << std::endl; - return false; + std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl; + return true; } const std::string& arg = args.front(); @@ -248,7 +274,7 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args } } - return false; + return true; } bool t_command_parser_executor::print_transaction(const std::vector<std::string>& args) @@ -267,13 +293,13 @@ bool t_command_parser_executor::print_transaction(const std::vector<std::string> include_json = true; else { - std::cout << "unexpected argument: " << args[i] << std::endl; + std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl; return true; } } if (args.empty()) { - std::cout << "expected: print_tx <transaction_hash> [+meta] [+hex] [+json]" << std::endl; + std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl; return true; } @@ -291,7 +317,7 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector<std::string { if (args.empty()) { - std::cout << "expected: is_key_image_spent <key_image>" << std::endl; + std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl; return true; } @@ -309,21 +335,30 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector<std::string bool t_command_parser_executor::print_transaction_pool_long(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.print_transaction_pool_long(); } bool t_command_parser_executor::print_transaction_pool_short(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.print_transaction_pool_short(); } bool t_command_parser_executor::print_transaction_pool_stats(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.print_transaction_pool_stats(); } @@ -332,7 +367,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg { if(!args.size()) { - std::cout << "Please specify a wallet address to mine for: start_mining <addr> [<threads>|auto]" << std::endl; + std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl; return true; } @@ -353,7 +388,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg { if(!cryptonote::get_account_address_from_str(info, cryptonote::STAGENET, address_str)) { - std::cout << "target account address has wrong format" << std::endl; + std::cout << "Invalid syntax: Target account address has wrong format. For more details, use the help command." << std::endl; return true; } else @@ -389,9 +424,10 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg bool ignore_battery = false; if(args.size() > 4) { - return false; + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; + return true; } - + if(args.size() == 4) { if(args[3] == "true" || command_line::is_yes(args[3]) || args[3] == "1") @@ -400,10 +436,11 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg } else if(args[3] != "false" && !command_line::is_no(args[3]) && args[3] != "0") { - return false; + std::cout << "Invalid syntax: Invalid combination of parameters. For more details, use the help command." << std::endl; + return true; } - } - + } + if(args.size() >= 3) { if(args[2] == "true" || command_line::is_yes(args[2]) || args[2] == "1") @@ -412,10 +449,11 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg } else if(args[2] != "false" && !command_line::is_no(args[2]) && args[2] != "0") { - return false; + std::cout << "Invalid syntax: Invalid combination of parameters. For more details, use the help command." << std::endl; + return true; } } - + if(args.size() >= 2) { if (args[1] == "auto" || args[1] == "autodetect") @@ -436,7 +474,10 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg bool t_command_parser_executor::stop_mining(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.stop_mining(); } @@ -448,21 +489,31 @@ bool t_command_parser_executor::mining_status(const std::vector<std::string>& ar bool t_command_parser_executor::stop_daemon(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.stop_daemon(); } bool t_command_parser_executor::print_status(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.print_status(); } bool t_command_parser_executor::set_limit(const std::vector<std::string>& args) { - if(args.size()>1) return false; + if(args.size()>1) { + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; + return true; + } + if(args.size()==0) { return m_executor.get_limit(); } @@ -471,8 +522,8 @@ bool t_command_parser_executor::set_limit(const std::vector<std::string>& args) limit = std::stoll(args[0]); } catch(const std::exception& ex) { - std::cout << "failed to parse argument" << std::endl; - return false; + std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl; + return true; } return m_executor.set_limit(limit, limit); @@ -480,7 +531,11 @@ bool t_command_parser_executor::set_limit(const std::vector<std::string>& args) bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& args) { - if(args.size()>1) return false; + if(args.size()>1) { + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; + return true; + } + if(args.size()==0) { return m_executor.get_limit_up(); } @@ -489,8 +544,8 @@ bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& arg limit = std::stoll(args[0]); } catch(const std::exception& ex) { - std::cout << "failed to parse argument" << std::endl; - return false; + std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl; + return true; } return m_executor.set_limit(0, limit); @@ -498,7 +553,11 @@ bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& arg bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& args) { - if(args.size()>1) return false; + if(args.size()>1) { + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; + return true; + } + if(args.size()==0) { return m_executor.get_limit_down(); } @@ -507,8 +566,8 @@ bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& a limit = std::stoll(args[0]); } catch(const std::exception& ex) { - std::cout << "failed to parse argument" << std::endl; - return false; + std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl; + return true; } return m_executor.set_limit(limit, 0); @@ -525,12 +584,13 @@ bool t_command_parser_executor::out_peers(const std::vector<std::string>& args) set = true; } } - + catch(const std::exception& ex) { _erro("stoi exception"); - return false; + std::cout << "Invalid syntax: Failed to parse number. For more details, use the help command." << std::endl; + return true; } - + return m_executor.out_peers(set, limit); } @@ -548,7 +608,8 @@ bool t_command_parser_executor::in_peers(const std::vector<std::string>& args) catch(const std::exception& ex) { _erro("stoi exception"); - return false; + std::cout << "Invalid syntax: Failed to parse number." << std::endl; + return true; } return m_executor.in_peers(set, limit); @@ -565,26 +626,37 @@ bool t_command_parser_executor::hard_fork_info(const std::vector<std::string>& a version = std::stoi(args[0]); } catch(const std::exception& ex) { - return false; + std::cout << "Invalid syntax: Failed to parse version number. For more details, use the help command." << std::endl; + return true; + } + if (version <= 0 || version > 255) { + std::cout << "Invalid syntax: Unknown version number. Must be between 0 and 255. For more details, use the help command." << std::endl; + return true; } - if (version <= 0 || version > 255) - return false; } else { - return false; + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; + return true; } return m_executor.hard_fork_info(version); } bool t_command_parser_executor::show_bans(const std::vector<std::string>& args) { - if (!args.empty()) return false; + if (!args.empty()) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } + return m_executor.print_bans(); } bool t_command_parser_executor::ban(const std::vector<std::string>& args) { - if (args.size() != 1 && args.size() != 2) return false; + if (args.size() != 1 && args.size() != 2) { + std::cout << "Invalid syntax: Expects one or two parameters. For more details, use the help command." << std::endl; + return true; + } std::string ip = args[0]; time_t seconds = P2P_IP_BLOCKTIME; if (args.size() > 1) @@ -595,11 +667,13 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args) } catch (const std::exception &e) { - return false; + std::cout << "Invalid syntax: Failed to parse seconds. For more details, use the help command." << std::endl; + return true; } if (seconds == 0) { - return false; + std::cout << "Seconds must be greater than 0." << std::endl; + return true; } } return m_executor.ban(ip, seconds); @@ -607,21 +681,31 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args) bool t_command_parser_executor::unban(const std::vector<std::string>& args) { - if (args.size() != 1) return false; + if (args.size() != 1) { + std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl; + return true; + } + std::string ip = args[0]; return m_executor.unban(ip); } bool t_command_parser_executor::banned(const std::vector<std::string>& args) { - if (args.size() != 1) return false; + if (args.size() != 1) { + std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl; + return true; + } std::string address = args[0]; return m_executor.banned(address); } bool t_command_parser_executor::flush_txpool(const std::vector<std::string>& args) { - if (args.size() > 1) return false; + if (args.size() > 1) { + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; + return true; + } std::string txid; if (args.size() == 1) @@ -629,7 +713,7 @@ bool t_command_parser_executor::flush_txpool(const std::vector<std::string>& arg crypto::hash hash; if (!parse_hash256(args[0], hash)) { - std::cout << "failed to parse tx id" << std::endl; + std::cout << "Invalid syntax: Failed to parse tx id. For more details, use the help command." << std::endl; return true; } txid = args[0]; @@ -662,7 +746,7 @@ bool t_command_parser_executor::output_histogram(const std::vector<std::string>& } else { - std::cout << "Invalid syntax: more than two non-amount parameters" << std::endl; + std::cout << "Invalid syntax: More than two non-amount parameters. For more details, use the help command." << std::endl; return true; } } @@ -673,20 +757,21 @@ bool t_command_parser_executor::print_coinbase_tx_sum(const std::vector<std::str { if(!args.size()) { - std::cout << "need block height parameter" << std::endl; - return false; + std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl; + return true; } + uint64_t height = 0; uint64_t count = 0; if(!epee::string_tools::get_xtype_from_string(height, args[0])) { - std::cout << "wrong starter block height parameter" << std::endl; - return false; + std::cout << "Invalid syntax: Wrong starter block height parameter. For more details, use the help command." << std::endl; + return true; } if(args.size() >1 && !epee::string_tools::get_xtype_from_string(count, args[1])) { std::cout << "wrong count parameter" << std::endl; - return false; + return true; } return m_executor.print_coinbase_tx_sum(height, count); @@ -696,8 +781,8 @@ bool t_command_parser_executor::alt_chain_info(const std::vector<std::string>& a { if(args.size() > 1) { - std::cout << "usage: alt_chain_info [block_hash|>N|-N]" << std::endl; - return false; + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; + return true; } std::string tip; @@ -709,16 +794,16 @@ bool t_command_parser_executor::alt_chain_info(const std::vector<std::string>& a { if (!epee::string_tools::get_xtype_from_string(above, args[0].c_str() + 1)) { - std::cout << "invalid above parameter" << std::endl; - return false; + std::cout << "Invalid syntax: Invalid above parameter. For more details, use the help command." << std::endl; + return true; } } else if (args[0].size() > 0 && args[0][0] == '-') { if (!epee::string_tools::get_xtype_from_string(last_blocks, args[0].c_str() + 1)) { - std::cout << "invalid last_blocks parameter" << std::endl; - return false; + std::cout << "Invalid syntax: Invalid last_blocks parameter. For more details, use the help command." << std::endl; + return true; } } else @@ -734,15 +819,15 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector { if(args.size() != 1) { - std::cout << "Exactly one parameter is needed" << std::endl; - return false; + std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl; + return true; } uint64_t nblocks = 0; if(!epee::string_tools::get_xtype_from_string(nblocks, args[0]) || nblocks == 0) { - std::cout << "wrong number of blocks" << std::endl; - return false; + std::cout << "Invalid syntax: Wrong number of blocks. For more details, use the help command." << std::endl; + return true; } return m_executor.print_blockchain_dynamic_stats(nblocks); @@ -750,10 +835,10 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector bool t_command_parser_executor::update(const std::vector<std::string>& args) { - if(args.size() != 1) + if (args.size() != 1) { - std::cout << "Exactly one parameter is needed: check, download, or update" << std::endl; - return false; + std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl; + return true; } return m_executor.update(args.front()); @@ -761,13 +846,17 @@ bool t_command_parser_executor::update(const std::vector<std::string>& args) bool t_command_parser_executor::relay_tx(const std::vector<std::string>& args) { - if (args.size() != 1) return false; + if (args.size() != 1) + { + std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl; + return true; + } std::string txid; crypto::hash hash; if (!parse_hash256(args[0], hash)) { - std::cout << "failed to parse tx id" << std::endl; + std::cout << "Invalid syntax: Failed to parse tx id. For more details, use the help command." << std::endl; return true; } txid = args[0]; @@ -776,7 +865,10 @@ bool t_command_parser_executor::relay_tx(const std::vector<std::string>& args) bool t_command_parser_executor::sync_info(const std::vector<std::string>& args) { - if (args.size() != 0) return false; + if (args.size() != 0) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.sync_info(); } @@ -785,8 +877,8 @@ bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args) { if (args.size() != 1) { - std::cout << "Exactly one parameter is needed" << std::endl; - return false; + std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl; + return true; } try @@ -794,21 +886,24 @@ bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args) uint64_t nblocks = boost::lexical_cast<uint64_t>(args[0]); if (nblocks < 1) { - std::cout << "number of blocks must be greater than 0" << std::endl; - return false; + std::cout << "Invalid syntax: Number of blocks must be greater than 0. For more details, use the help command." << std::endl; + return true; } return m_executor.pop_blocks(nblocks); } catch (const boost::bad_lexical_cast&) { - std::cout << "number of blocks must be a number greater than 0" << std::endl; + std::cout << "Invalid syntax: Number of blocks must be a number greater than 0. For more details, use the help command." << std::endl; } - return false; + return true; } bool t_command_parser_executor::rpc_payments(const std::vector<std::string>& args) { - if (args.size() != 0) return false; + if (args.size() != 0) { + std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl; + return true; + } return m_executor.rpc_payments(); } @@ -820,7 +915,11 @@ bool t_command_parser_executor::version(const std::vector<std::string>& args) bool t_command_parser_executor::prune_blockchain(const std::vector<std::string>& args) { - if (args.size() > 1) return false; + if (args.size() > 1) + { + std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl; + return true; + } if (args.empty() || args[0] != "confirm") { @@ -846,7 +945,8 @@ bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::stri const size_t args_count = args.size(); if (args_count < 1 || args_count > 3) { - return false; + std::cout << "Invalid syntax: Wrong number of parameters. For more details, use the help command." << std::endl; + return true; } return m_executor.set_bootstrap_daemon( diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index ac4c30726..dd5f76188 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -223,7 +223,8 @@ t_command_server::t_command_server( m_command_lookup.set_handler( "hard_fork_info" , std::bind(&t_command_parser_executor::hard_fork_info, &m_parser, p::_1) - , "Print the hard fork voting information." + , "hard_fork_info <version>" + , "Print the hard fork voting information. If given a version, prints whether is this version enabled." ); m_command_lookup.set_handler( "bans" @@ -314,6 +315,7 @@ t_command_server::t_command_server( m_command_lookup.set_handler( "prune_blockchain" , std::bind(&t_command_parser_executor::prune_blockchain, &m_parser, p::_1) + , "prune_blockchain [confirm]" , "Prune the blockchain." ); m_command_lookup.set_handler( diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index e81371783..97835edd4 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -334,7 +334,7 @@ namespace nodetool virtual void callback(p2p_connection_context& context); //----------------- i_p2p_endpoint ------------------------------------------------------------- virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections); - virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::i_core_events& core, cryptonote::relay_method tx_relay); + virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::relay_method tx_relay); virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context); virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context); virtual bool drop_connection(const epee::net_utils::connection_context_base& context); diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 175741146..9aa188146 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -386,7 +386,7 @@ namespace nodetool m_use_ipv6 = command_line::get_arg(vm, arg_p2p_use_ipv6); m_require_ipv4 = !command_line::get_arg(vm, arg_p2p_ignore_ipv4); public_zone.m_notifier = cryptonote::levin::notify{ - public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, true, pad_txs + public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, epee::net_utils::zone::public_, pad_txs, m_payload_handler.get_core() }; if (command_line::has_arg(vm, arg_p2p_add_peer)) @@ -499,7 +499,7 @@ namespace nodetool } zone.m_notifier = cryptonote::levin::notify{ - zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), false, pad_txs + zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), proxy.zone, pad_txs, m_payload_handler.get_core() }; } @@ -1994,13 +1994,13 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - epee::net_utils::zone node_server<t_payload_net_handler>::send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::i_core_events& core, const cryptonote::relay_method tx_relay) + epee::net_utils::zone node_server<t_payload_net_handler>::send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, const cryptonote::relay_method tx_relay) { namespace enet = epee::net_utils; - const auto send = [&txs, &source, &core, tx_relay] (std::pair<const enet::zone, network_zone>& network) + const auto send = [&txs, &source, tx_relay] (std::pair<const enet::zone, network_zone>& network) { - if (network.second.m_notifier.send_txs(std::move(txs), source, core, tx_relay)) + if (network.second.m_notifier.send_txs(std::move(txs), source, tx_relay)) return network.first; return enet::zone::invalid; }; diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h index 393d38e0a..2ace5987f 100644 --- a/src/p2p/net_node_common.h +++ b/src/p2p/net_node_common.h @@ -50,7 +50,7 @@ namespace nodetool struct i_p2p_endpoint { virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)=0; - virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::i_core_events& core, cryptonote::relay_method tx_relay)=0; + virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::relay_method tx_relay)=0; virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)=0; virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context)=0; virtual bool drop_connection(const epee::net_utils::connection_context_base& context)=0; @@ -75,7 +75,7 @@ namespace nodetool { return false; } - virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::i_core_events& core, cryptonote::relay_method tx_relay) + virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::relay_method tx_relay) { return epee::net_utils::zone::invalid; } diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 19298c969..aa4102481 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -66,7 +66,7 @@ set(rpc_pub_headers zmq_pub.h) set(daemon_rpc_server_headers) -set(rpc_daemon_private_headers +set(rpc_private_headers bootstrap_daemon.h core_rpc_server.h rpc_payment.h diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a50c70418..382b5815f 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -521,9 +521,17 @@ namespace cryptonote bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res, const connection_context *ctx) { RPC_TRACKER(get_blocks); - bool r; - if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCKS_FAST>(invoke_http_mode::BIN, "/getblocks.bin", req, res, r)) - return r; + + bool use_bootstrap_daemon; + { + boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex); + use_bootstrap_daemon = m_should_use_bootstrap_daemon; + } + if (use_bootstrap_daemon) + { + bool r; + return use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCKS_FAST>(invoke_http_mode::BIN, "/getblocks.bin", req, res, r); + } CHECK_PAYMENT(req, res, 1); diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp index f69a69ca3..96090d9f5 100644 --- a/src/wallet/api/address_book.cpp +++ b/src/wallet/api/address_book.cpp @@ -70,6 +70,25 @@ bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &pa return r; } +bool AddressBookImpl::setDescription(std::size_t index, const std::string &description) +{ + clearStatus(); + + const auto ab = m_wallet->m_wallet->get_address_book(); + if (index >= ab.size()){ + return false; + } + + tools::wallet2::address_book_row entry = ab[index]; + entry.m_description = description; + bool r = m_wallet->m_wallet->set_address_book_row(index, entry.m_address, NULL, entry.m_description, entry.m_is_subaddress); + if (r) + refresh(); + else + m_errorCode = General_Error; + return r; +} + void AddressBookImpl::refresh() { LOG_PRINT_L2("Refreshing addressbook"); diff --git a/src/wallet/api/address_book.h b/src/wallet/api/address_book.h index f287969f3..e22f474fb 100644 --- a/src/wallet/api/address_book.h +++ b/src/wallet/api/address_book.h @@ -45,6 +45,7 @@ public: void refresh() override; std::vector<AddressBookRow*> getAll() const override; bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) override; + bool setDescription(std::size_t index, const std::string &description) override; bool deleteRow(std::size_t rowId) override; // Error codes. See AddressBook:ErrorCode enum in wallet2_api.h diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index bcb300889..3a8532db8 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -92,6 +92,17 @@ std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const return m_history; } +void TransactionHistoryImpl::setTxNote(const std::string &txid, const std::string ¬e) +{ + cryptonote::blobdata txid_data; + if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash)) + return; + const crypto::hash htxid = *reinterpret_cast<const crypto::hash*>(txid_data.data()); + + m_wallet->m_wallet->set_tx_note(htxid, note); + refresh(); +} + void TransactionHistoryImpl::refresh() { // multithreaded access: @@ -126,10 +137,12 @@ void TransactionHistoryImpl::refresh() payment_id = payment_id.substr(0,16); TransactionInfoImpl * ti = new TransactionInfoImpl(); ti->m_paymentid = payment_id; + ti->m_coinbase = pd.m_coinbase; ti->m_amount = pd.m_amount; ti->m_direction = TransactionInfo::Direction_In; ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash); ti->m_blockheight = pd.m_block_height; + ti->m_description = m_wallet->m_wallet->get_tx_note(pd.m_tx_hash); ti->m_subaddrIndex = { pd.m_subaddr_index.minor }; ti->m_subaddrAccount = pd.m_subaddr_index.major; ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index); @@ -173,6 +186,7 @@ void TransactionHistoryImpl::refresh() ti->m_direction = TransactionInfo::Direction_Out; ti->m_hash = string_tools::pod_to_hex(hash); ti->m_blockheight = pd.m_block_height; + ti->m_description = m_wallet->m_wallet->get_tx_note(hash); ti->m_subaddrIndex = pd.m_subaddr_indices; ti->m_subaddrAccount = pd.m_subaddr_account; ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : ""; @@ -183,6 +197,7 @@ void TransactionHistoryImpl::refresh() for (const auto &d: pd.m_dests) { ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)}); } + m_history.push_back(ti); } @@ -207,6 +222,7 @@ void TransactionHistoryImpl::refresh() ti->m_failed = is_failed; ti->m_pending = true; ti->m_hash = string_tools::pod_to_hex(hash); + ti->m_description = m_wallet->m_wallet->get_tx_note(hash); ti->m_subaddrIndex = pd.m_subaddr_indices; ti->m_subaddrAccount = pd.m_subaddr_account; ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : ""; @@ -230,6 +246,7 @@ void TransactionHistoryImpl::refresh() ti->m_direction = TransactionInfo::Direction_In; ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash); ti->m_blockheight = pd.m_block_height; + ti->m_description = m_wallet->m_wallet->get_tx_note(pd.m_tx_hash); ti->m_pending = true; ti->m_subaddrIndex = { pd.m_subaddr_index.minor }; ti->m_subaddrAccount = pd.m_subaddr_index.major; diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h index 8f3805788..60f12d771 100644 --- a/src/wallet/api/transaction_history.h +++ b/src/wallet/api/transaction_history.h @@ -45,6 +45,7 @@ public: virtual TransactionInfo * transaction(const std::string &id) const; virtual std::vector<TransactionInfo*> getAll() const; virtual void refresh(); + virtual void setTxNote(const std::string &txid, const std::string ¬e); private: diff --git a/src/wallet/api/transaction_info.cpp b/src/wallet/api/transaction_info.cpp index 5ae3a6937..33e7856db 100644 --- a/src/wallet/api/transaction_info.cpp +++ b/src/wallet/api/transaction_info.cpp @@ -45,6 +45,7 @@ TransactionInfoImpl::TransactionInfoImpl() : m_direction(Direction_Out) , m_pending(false) , m_failed(false) + , m_coinbase(false) , m_amount(0) , m_fee(0) , m_blockheight(0) @@ -77,6 +78,11 @@ bool TransactionInfoImpl::isFailed() const return m_failed; } +bool TransactionInfoImpl::isCoinbase() const +{ + return m_coinbase; +} + uint64_t TransactionInfoImpl::amount() const { return m_amount; @@ -92,6 +98,11 @@ uint64_t TransactionInfoImpl::blockHeight() const return m_blockheight; } +std::string TransactionInfoImpl::description() const +{ + return m_description; +} + std::set<uint32_t> TransactionInfoImpl::subaddrIndex() const { return m_subaddrIndex; diff --git a/src/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h index 73bb7689d..8bc36a8e9 100644 --- a/src/wallet/api/transaction_info.h +++ b/src/wallet/api/transaction_info.h @@ -46,10 +46,12 @@ public: //! true if hold virtual bool isPending() const override; virtual bool isFailed() const override; + virtual bool isCoinbase() const override; virtual uint64_t amount() const override; //! always 0 for incoming txes virtual uint64_t fee() const override; virtual uint64_t blockHeight() const override; + virtual std::string description() const override; virtual std::set<uint32_t> subaddrIndex() const override; virtual uint32_t subaddrAccount() const override; virtual std::string label() const override; @@ -65,9 +67,11 @@ private: int m_direction; bool m_pending; bool m_failed; + bool m_coinbase; uint64_t m_amount; uint64_t m_fee; uint64_t m_blockheight; + std::string m_description; std::set<uint32_t> m_subaddrIndex; // always unique index for incoming transfers; can be multiple indices for outgoing transfers uint32_t m_subaddrAccount; std::string m_label; diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 152a7dcd7..9acc8484c 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -910,6 +910,11 @@ std::string WalletImpl::path() const return m_wallet->path(); } +void WalletImpl::stop() +{ + m_wallet->stop(); +} + bool WalletImpl::store(const std::string &path) { clearStatus(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index caf1e9ed4..3bf3e759b 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -99,6 +99,7 @@ public: std::string publicSpendKey() const override; std::string publicMultisigSignerKey() const override; std::string path() const override; + void stop() override; bool store(const std::string &path) override; std::string filename() const override; std::string keysFilename() const override; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index 50df7e5dd..44928a422 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -182,9 +182,11 @@ struct TransactionInfo virtual int direction() const = 0; virtual bool isPending() const = 0; virtual bool isFailed() const = 0; + virtual bool isCoinbase() const = 0; virtual uint64_t amount() const = 0; virtual uint64_t fee() const = 0; virtual uint64_t blockHeight() const = 0; + virtual std::string description() const = 0; virtual std::set<uint32_t> subaddrIndex() const = 0; virtual uint32_t subaddrAccount() const = 0; virtual std::string label() const = 0; @@ -208,6 +210,7 @@ struct TransactionHistory virtual TransactionInfo * transaction(const std::string &id) const = 0; virtual std::vector<TransactionInfo*> getAll() const = 0; virtual void refresh() = 0; + virtual void setTxNote(const std::string &txid, const std::string ¬e) = 0; }; /** @@ -250,6 +253,7 @@ struct AddressBook virtual std::vector<AddressBookRow*> getAll() const = 0; virtual bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) = 0; virtual bool deleteRow(std::size_t rowId) = 0; + virtual bool setDescription(std::size_t index, const std::string &description) = 0; virtual void refresh() = 0; virtual std::string errorString() const = 0; virtual int errorCode() const = 0; @@ -507,6 +511,11 @@ struct Wallet virtual std::string publicMultisigSignerKey() const = 0; /*! + * \brief stop - interrupts wallet refresh() loop once (doesn't stop background refresh thread) + */ + virtual void stop() = 0; + + /*! * \brief store - stores wallet to file. * \param path - main filename to store wallet to. additionally stores address file and keys file. * to store to the same file - just pass empty string; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index eac99185c..fed7d745c 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -434,7 +434,7 @@ private: std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> m_rings; // relative BEGIN_SERIALIZE_OBJECT() - VERSION_FIELD(0) + VERSION_FIELD(1) FIELD(m_tx) VARINT_FIELD(m_amount_in) VARINT_FIELD(m_amount_out) @@ -442,6 +442,8 @@ private: VARINT_FIELD(m_sent_time) FIELD(m_dests) FIELD(m_payment_id) + if (version >= 1) + VARINT_FIELD(m_state) VARINT_FIELD(m_timestamp) VARINT_FIELD(m_subaddr_account) FIELD(m_subaddr_indices) diff --git a/tests/functional_tests/mining.py b/tests/functional_tests/mining.py index 34b4aceab..1eb6b0ba7 100755 --- a/tests/functional_tests/mining.py +++ b/tests/functional_tests/mining.py @@ -107,7 +107,7 @@ class MiningTest(): break else: assert False, 'Failed to mine successor to block %d (initial block = %d)' % (seen_height, prev_height) - timeout = 5 + timeout = 10 if via_daemon: res = daemon.stop_mining() diff --git a/tests/unit_tests/block_reward.cpp b/tests/unit_tests/block_reward.cpp index 5f3335981..2f0ea92f3 100644 --- a/tests/unit_tests/block_reward.cpp +++ b/tests/unit_tests/block_reward.cpp @@ -138,24 +138,6 @@ namespace ASSERT_FALSE(m_block_not_too_big); } -#ifdef __x86_64__ // For 64-bit systems only, because block size is limited to size_t. - TEST_F(block_reward_and_current_block_weight, fails_on_huge_median_size) - { -#if !defined(NDEBUG) - size_t huge_size = std::numeric_limits<uint32_t>::max() + UINT64_C(2); - ASSERT_DEATH(do_test(huge_size, huge_size + 1), ""); -#endif - } - - TEST_F(block_reward_and_current_block_weight, fails_on_huge_block_weight) - { -#if !defined(NDEBUG) - size_t huge_size = std::numeric_limits<uint32_t>::max() + UINT64_C(2); - ASSERT_DEATH(do_test(huge_size - 2, huge_size), ""); -#endif - } -#endif // __x86_64__ - //-------------------------------------------------------------------------------------------------------------------- class block_reward_and_last_block_weights : public ::testing::Test { diff --git a/tests/unit_tests/levin.cpp b/tests/unit_tests/levin.cpp index 15563e764..9ff68d927 100644 --- a/tests/unit_tests/levin.cpp +++ b/tests/unit_tests/levin.cpp @@ -120,6 +120,11 @@ namespace { std::map<cryptonote::relay_method, std::vector<cryptonote::blobdata>> relayed_; + uint64_t get_target_blockchain_height() const override + { + return 0; + } + virtual void on_transactions_relayed(epee::span<const cryptonote::blobdata> txes, cryptonote::relay_method relay) override final { std::vector<cryptonote::blobdata>& cached = relayed_[relay]; @@ -324,7 +329,8 @@ namespace epee::byte_slice noise = nullptr; if (noise_size) noise = epee::levin::make_noise_notify(noise_size); - return cryptonote::levin::notify{io_service_, connections_, std::move(noise), is_public, pad_txs}; + epee::net_utils::zone zone = is_public ? epee::net_utils::zone::public_ : epee::net_utils::zone::i2p; + return cryptonote::levin::notify{io_service_, connections_, std::move(noise), zone, pad_txs, events_}; } boost::uuids::random_generator random_generator_; @@ -483,11 +489,11 @@ TEST_F(levin_notify, defaulted) EXPECT_FALSE(status.has_noise); EXPECT_FALSE(status.connections_filled); } - EXPECT_TRUE(notifier.send_txs({}, random_generator_(), events_, cryptonote::relay_method::local)); + EXPECT_TRUE(notifier.send_txs({}, random_generator_(), cryptonote::relay_method::local)); std::vector<cryptonote::blobdata> txs(2); txs[0].resize(100, 'e'); - EXPECT_FALSE(notifier.send_txs(std::move(txs), random_generator_(), events_, cryptonote::relay_method::local)); + EXPECT_FALSE(notifier.send_txs(std::move(txs), random_generator_(), cryptonote::relay_method::local)); } TEST_F(levin_notify, fluff_without_padding) @@ -512,7 +518,7 @@ TEST_F(levin_notify, fluff_without_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::fluff)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::fluff)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -564,7 +570,7 @@ TEST_F(levin_notify, stem_without_padding) while (!has_stemmed || !has_fluffed) { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::stem)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::stem)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -636,7 +642,7 @@ TEST_F(levin_notify, local_without_padding) while (!has_stemmed || !has_fluffed) { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::local)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::local)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -708,7 +714,7 @@ TEST_F(levin_notify, forward_without_padding) while (!has_stemmed || !has_fluffed) { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::forward)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::forward)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -727,7 +733,9 @@ TEST_F(levin_notify, forward_without_padding) { const std::size_t sent = context->process_send_queue(); if (sent && is_stem) + { EXPECT_EQ(1u, (context - contexts_.begin()) % 2); + } send_count += sent; } @@ -772,7 +780,7 @@ TEST_F(levin_notify, block_without_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::block)); + EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::block)); io_service_.reset(); ASSERT_EQ(0u, io_service_.poll()); @@ -801,7 +809,7 @@ TEST_F(levin_notify, none_without_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::none)); + EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::none)); io_service_.reset(); ASSERT_EQ(0u, io_service_.poll()); @@ -830,7 +838,7 @@ TEST_F(levin_notify, fluff_with_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::fluff)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::fluff)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -879,7 +887,7 @@ TEST_F(levin_notify, stem_with_padding) while (!has_stemmed || !has_fluffed) { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::stem)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::stem)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -946,7 +954,7 @@ TEST_F(levin_notify, local_with_padding) while (!has_stemmed || !has_fluffed) { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::local)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::local)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1013,7 +1021,7 @@ TEST_F(levin_notify, forward_with_padding) while (!has_stemmed || !has_fluffed) { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::forward)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::forward)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1077,7 +1085,7 @@ TEST_F(levin_notify, block_with_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::block)); + EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::block)); io_service_.reset(); ASSERT_EQ(0u, io_service_.poll()); @@ -1106,7 +1114,7 @@ TEST_F(levin_notify, none_with_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::none)); + EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::none)); io_service_.reset(); ASSERT_EQ(0u, io_service_.poll()); @@ -1135,7 +1143,7 @@ TEST_F(levin_notify, private_fluff_without_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::fluff)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::fluff)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1186,7 +1194,7 @@ TEST_F(levin_notify, private_stem_without_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::stem)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::stem)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1237,7 +1245,7 @@ TEST_F(levin_notify, private_local_without_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::local)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::local)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1288,7 +1296,7 @@ TEST_F(levin_notify, private_forward_without_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::forward)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::forward)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1339,7 +1347,7 @@ TEST_F(levin_notify, private_block_without_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::block)); + EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::block)); io_service_.reset(); ASSERT_EQ(0u, io_service_.poll()); @@ -1369,7 +1377,7 @@ TEST_F(levin_notify, private_none_without_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::none)); + EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::none)); io_service_.reset(); ASSERT_EQ(0u, io_service_.poll()); @@ -1398,7 +1406,7 @@ TEST_F(levin_notify, private_fluff_with_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::fluff)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::fluff)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1448,7 +1456,7 @@ TEST_F(levin_notify, private_stem_with_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::stem)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::stem)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1498,7 +1506,7 @@ TEST_F(levin_notify, private_local_with_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::local)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::local)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1548,7 +1556,7 @@ TEST_F(levin_notify, private_forward_with_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::forward)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::forward)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1598,7 +1606,7 @@ TEST_F(levin_notify, private_block_with_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::block)); + EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::block)); io_service_.reset(); ASSERT_EQ(0u, io_service_.poll()); @@ -1627,7 +1635,7 @@ TEST_F(levin_notify, private_none_with_padding) ASSERT_EQ(10u, contexts_.size()); { auto context = contexts_.begin(); - EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::none)); + EXPECT_FALSE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::none)); io_service_.reset(); ASSERT_EQ(0u, io_service_.poll()); @@ -1659,7 +1667,7 @@ TEST_F(levin_notify, stem_mappings) for (;;) { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::stem)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::stem)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1721,7 +1729,7 @@ TEST_F(levin_notify, stem_mappings) for (unsigned i = 0; i < contexts_.size() * 2; i += 2) { auto& incoming = contexts_[i % contexts_.size()]; - EXPECT_TRUE(notifier.send_txs(txs, incoming.get_id(), events_, cryptonote::relay_method::stem)); + EXPECT_TRUE(notifier.send_txs(txs, incoming.get_id(), cryptonote::relay_method::stem)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1782,7 +1790,7 @@ TEST_F(levin_notify, fluff_multiple) for (;;) { auto context = contexts_.begin(); - EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), events_, cryptonote::relay_method::stem)); + EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::stem)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1841,7 +1849,7 @@ TEST_F(levin_notify, fluff_multiple) for (unsigned i = 0; i < contexts_.size() * 2; i += 2) { auto& incoming = contexts_[i % contexts_.size()]; - EXPECT_TRUE(notifier.send_txs(txs, incoming.get_id(), events_, cryptonote::relay_method::stem)); + EXPECT_TRUE(notifier.send_txs(txs, incoming.get_id(), cryptonote::relay_method::stem)); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1905,7 +1913,7 @@ TEST_F(levin_notify, noise) EXPECT_EQ(0u, receiver_.notified_size()); } - EXPECT_TRUE(notifier.send_txs(txs, incoming_id, events_, cryptonote::relay_method::local)); + EXPECT_TRUE(notifier.send_txs(txs, incoming_id, cryptonote::relay_method::local)); notifier.run_stems(); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1927,7 +1935,7 @@ TEST_F(levin_notify, noise) } txs[0].resize(3000, 'r'); - EXPECT_TRUE(notifier.send_txs(txs, incoming_id, events_, cryptonote::relay_method::fluff)); + EXPECT_TRUE(notifier.send_txs(txs, incoming_id, cryptonote::relay_method::fluff)); notifier.run_stems(); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); @@ -1996,7 +2004,7 @@ TEST_F(levin_notify, noise_stem) EXPECT_EQ(0u, receiver_.notified_size()); } - EXPECT_TRUE(notifier.send_txs(txs, incoming_id, events_, cryptonote::relay_method::stem)); + EXPECT_TRUE(notifier.send_txs(txs, incoming_id, cryptonote::relay_method::stem)); notifier.run_stems(); io_service_.reset(); ASSERT_LT(0u, io_service_.poll()); diff --git a/utils/systemd/monerod.service b/utils/systemd/monerod.service index dbb9e8aaa..c89e31f8c 100644 --- a/utils/systemd/monerod.service +++ b/utils/systemd/monerod.service @@ -6,16 +6,15 @@ After=network.target User=monero Group=monero WorkingDirectory=~ -RuntimeDirectory=monero StateDirectory=monero LogsDirectory=monero # Clearnet config # -Type=forking -PIDFile=/run/monero/monerod.pid -ExecStart=/usr/bin/monerod --config-file /etc/monerod.conf \ - --detach --pidfile /run/monero/monerod.pid +Type=simple +ExecStart=/usr/bin/monerod --config-file /etc/monerod.conf --non-interactive +StandardOutput=null +StandardError=null # Tor config # |