diff options
806 files changed, 6006 insertions, 12238 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bd2e26484..69040d0af 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ on: env: REMOVE_BUNDLED_BOOST : rm -rf /usr/local/share/boost BUILD_DEFAULT_LINUX: | - cmake -S . -B build -D ARCH="default" -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=release && cmake --build build -j3 + cmake -S . -B build -D ARCH="default" -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=Release && cmake --build build -j3 APT_INSTALL_LINUX: 'sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler ccache' APT_SET_CONF: | echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom diff --git a/.gitignore b/.gitignore index 049fc2562..a39168ac5 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,8 @@ cmake-build-debug/ # KDE directory preferences .directory +### VSCode ### +.vscode/ ### Eclipse ### *.pydevproject @@ -110,3 +112,5 @@ nbproject /testnet __pycache__/ +*.pyc +*.log diff --git a/CMakeLists.txt b/CMakeLists.txt index e21fbb65b..a0f11608c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/CMakeLists_IOS.txt b/CMakeLists_IOS.txt index 951286cb0..21aa92094 100644 --- a/CMakeLists_IOS.txt +++ b/CMakeLists_IOS.txt @@ -1,4 +1,4 @@ -# Portions Copyright (c) 2017-2020, The Monero Project +# Portions Copyright (c) 2017-2022, The Monero Project # This file is based off of the https://code.google.com/archive/p/ios-cmake/ # It has been altered for Monero iOS development # @@ -96,15 +96,15 @@ release: cmake-release release-test: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=release $(topdir) && $(MAKE) && $(MAKE) test + cd $(builddir)/release && cmake -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE) && $(MAKE) test release-all: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=release $(topdir) && $(MAKE) + cd $(builddir)/release && cmake -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE) release-static: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release $(topdir) && $(MAKE) + cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE) coverage: mkdir -p $(builddir)/debug @@ -114,41 +114,41 @@ coverage: release-static-linux-armv6: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D ARCH="armv6zk" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="linux-armv6" $(topdir) && $(MAKE) + cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D ARCH="armv6zk" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="linux-armv6" $(topdir) && $(MAKE) release-static-linux-armv7: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="linux-armv7" $(topdir) && $(MAKE) + cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="linux-armv7" $(topdir) && $(MAKE) release-static-android-armv7: mkdir -p $(builddir)/release/translations cd $(builddir)/release/translations && cmake ../../../translations && $(MAKE) - cd $(builddir)/release && CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D BUILD_TAG="android-armv7" -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARM_MODE=ON -D CMAKE_ANDROID_ARCH_ABI="armeabi-v7a" ../.. && $(MAKE) + cd $(builddir)/release && CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=Release -D ANDROID=true -D BUILD_TAG="android-armv7" -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARM_MODE=ON -D CMAKE_ANDROID_ARCH_ABI="armeabi-v7a" ../.. && $(MAKE) release-static-android-armv8: mkdir -p $(builddir)/release/translations cd $(builddir)/release/translations && cmake ../../../translations && $(MAKE) - cd $(builddir)/release && CC=aarch64-linux-android-clang CXX=aarch64-linux-android-clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv8-a" -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D BUILD_TAG="android-armv8" -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARCH_ABI="arm64-v8a" ../.. && $(MAKE) + cd $(builddir)/release && CC=aarch64-linux-android-clang CXX=aarch64-linux-android-clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv8-a" -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D ANDROID=true -D BUILD_TAG="android-armv8" -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARCH_ABI="arm64-v8a" ../.. && $(MAKE) release-static-linux-armv8: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D ARCH="armv8-a" -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="linux-armv8" $(topdir) && $(MAKE) + cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D ARCH="armv8-a" -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="linux-armv8" $(topdir) && $(MAKE) release-static-linux-x86_64: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="linux-x64" $(topdir) && $(MAKE) + cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="linux-x64" $(topdir) && $(MAKE) release-static-freebsd-x86_64: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="freebsd-x64" $(topdir) && $(MAKE) + cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="freebsd-x64" $(topdir) && $(MAKE) release-static-mac-x86_64: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="mac-x64" $(topdir) && $(MAKE) + cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="mac-x64" $(topdir) && $(MAKE) release-static-linux-i686: mkdir -p $(builddir)/release - cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="i686" -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="linux-x86" $(topdir) && $(MAKE) + cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="i686" -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="linux-x86" $(topdir) && $(MAKE) release-static-win64: mkdir -p $(builddir)/release @@ -1,6 +1,6 @@ # Monero -Copyright (c) 2014-2022 The Monero Project. +Copyright (c) 2014-2022 The Monero Project. Portions Copyright (c) 2012-2013 The Cryptonote developers. ## Table of Contents @@ -33,7 +33,7 @@ Portions Copyright (c) 2012-2013 The Cryptonote developers. - Mail: [dev@getmonero.org](mailto:dev@getmonero.org) - GitHub: [https://github.com/monero-project/monero](https://github.com/monero-project/monero) - IRC: [#monero-dev on Libera](https://web.libera.chat/#monero-dev) -- It is HIGHLY recommended that you join the #monero-dev IRC channel if you are developing software that uses Monero. Due to the nature of this open source software project, joining this channel and idling is the best way to stay updated on best practices and new developments in the Monero ecosystem. All you need to do is join the IRC channel and idle to stay updated with the latest in Monero development. If you do not, you risk wasting resources on developing integrations that are not compatible with the Monero network. The Monero core team and community continuously make efforts to communicate updates, developments, and documentation via other platforms – but for the best information, you need to talk to other Monero developers, and they are on IRC. #monero-dev is about Monero development, not getting help about using Monero, or help about development of other software, including yours, unless it also pertains to Monero code itself. For these cases, checkout #monero. +- It is HIGHLY recommended that you join the #monero-dev IRC channel if you are developing software that uses Monero. Due to the nature of this open source software project, joining this channel and idling is the best way to stay updated on best practices and new developments in the Monero ecosystem. All you need to do is join the IRC channel and idle to stay updated with the latest in Monero development. If you do not, you risk wasting resources on developing integrations that are not compatible with the Monero network. The Monero core team and community continuously make efforts to communicate updates, developments, and documentation via other platforms – but for the best information, you need to talk to other Monero developers, and they are on IRC. #monero-dev is about Monero development, not getting help about using Monero, or help about development of other software, including yours, unless it also pertains to Monero code itself. For these cases, checkout #monero. ## Vulnerability response @@ -75,7 +75,7 @@ Monero is a private, secure, untraceable, decentralised digital currency. You ar **Untraceability:** By taking advantage of ring signatures, a special property of a certain type of cryptography, Monero is able to ensure that transactions are not only untraceable but have an optional measure of ambiguity that ensures that transactions cannot easily be tied back to an individual user or computer. -**Decentralization:** The utility of Monero depends on its decentralised peer-to-peer consensus network - anyone should be able to run the monero software, validate the integrity of the blockchain, and participate in all aspects of the monero network using consumer-grade commodity hardware. Decentralization of the monero network is maintained by software development that minimizes the costs of running the monero software and inhibits the proliferation of specialized, non-commodity hardware. +**Decentralization:** The utility of Monero depends on its decentralised peer-to-peer consensus network - anyone should be able to run the monero software, validate the integrity of the blockchain, and participate in all aspects of the monero network using consumer-grade commodity hardware. Decentralization of the monero network is maintained by software development that minimizes the costs of running the monero software and inhibits the proliferation of specialized, non-commodity hardware. ## About this project @@ -117,7 +117,7 @@ Monero uses a fixed-schedule software upgrade (hard fork) mechanism to implement Dates are provided in the format YYYY-MM-DD. -| Software upgrade block height | Date | Fork version | Minimum Monero version | Recommended Monero version | Details | +| Software upgrade block height | Date | Fork version | Minimum Monero version | Recommended Monero version | Details | | ------------------------------ | -----------| ----------------- | ---------------------- | -------------------------- | ---------------------------------------------------------------------------------- | | 1009827 | 2016-03-22 | v2 | v0.9.4 | v0.9.4 | Allow only >= ringsize 3, blocktime = 120 seconds, fee-free blocksize 60 kb | | 1141317 | 2016-09-21 | v3 | v0.9.4 | v0.10.0 | Splits coinbase into denominations | @@ -196,30 +196,44 @@ then: Install all dependencies at once on Debian/Ubuntu: -``` sudo apt update && sudo apt install build-essential cmake pkg-config libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev libpgm-dev qttools5-dev-tools libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-locale-dev libboost-program-options-dev libboost-regex-dev libboost-serialization-dev libboost-system-dev libboost-thread-dev ccache doxygen graphviz ``` +``` +sudo apt update && sudo apt install build-essential cmake pkg-config libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev libpgm-dev qttools5-dev-tools libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-locale-dev libboost-program-options-dev libboost-regex-dev libboost-serialization-dev libboost-system-dev libboost-thread-dev ccache doxygen graphviz +``` Install all dependencies at once on openSUSE: -``` sudo zypper ref && sudo zypper in cppzmq-devel ldns-devel libboost_chrono-devel libboost_date_time-devel libboost_filesystem-devel libboost_locale-devel libboost_program_options-devel libboost_regex-devel libboost_serialization-devel libboost_system-devel libboost_thread-devel libexpat-devel libminiupnpc-devel libsodium-devel libunwind-devel unbound-devel cmake doxygen ccache fdupes gcc-c++ libevent-devel libopenssl-devel pkgconf-pkg-config readline-devel xz-devel libqt5-qttools-devel patterns-devel-C-C++-devel_C_C++``` +``` +sudo zypper ref && sudo zypper in cppzmq-devel ldns-devel libboost_chrono-devel libboost_date_time-devel libboost_filesystem-devel libboost_locale-devel libboost_program_options-devel libboost_regex-devel libboost_serialization-devel libboost_system-devel libboost_thread-devel libexpat-devel libminiupnpc-devel libsodium-devel libunwind-devel unbound-devel cmake doxygen ccache fdupes gcc-c++ libevent-devel libopenssl-devel pkgconf-pkg-config readline-devel xz-devel libqt5-qttools-devel patterns-devel-C-C++-devel_C_C++ +``` Install all dependencies at once on macOS with the provided Brewfile: -``` brew update && brew bundle --file=contrib/brew/Brewfile ``` + +``` +brew update && brew bundle --file=contrib/brew/Brewfile +``` FreeBSD 12.1 one-liner required to build dependencies: -```pkg install git gmake cmake pkgconf boost-libs libzmq4 libsodium unbound``` + +``` +pkg install git gmake cmake pkgconf boost-libs libzmq4 libsodium unbound +``` ### Cloning the repository Clone recursively to pull-in needed submodule(s): -`$ git clone --recursive https://github.com/monero-project/monero` +``` +git clone --recursive https://github.com/monero-project/monero +``` If you already have a repo cloned, initialize and update: -`$ cd monero && git submodule init && git submodule update` +``` +cd monero && git submodule init && git submodule update +``` *Note*: If there are submodule differences between branches, you may need -to use ```git submodule sync && git submodule update``` after changing branches +to use `git submodule sync && git submodule update` after changing branches to build successfully. ### Build instructions @@ -383,15 +397,15 @@ application. * Download and install the [MSYS2 installer](https://www.msys2.org), either the 64-bit or the 32-bit package, depending on your system. * Open the MSYS shell via the `MSYS2 Shell` shortcut -* Update packages using pacman: +* Update packages using pacman: ```bash pacman -Syu ``` -* Exit the MSYS shell using Alt+F4 +* Exit the MSYS shell using Alt+F4 * Edit the properties for the `MSYS2 Shell` shortcut changing "msys2_shell.bat" to "msys2_shell.cmd -mingw64" for 64-bit builds or "msys2_shell.cmd -mingw32" for 32-bit builds -* Restart MSYS shell via modified shortcut and update packages again using pacman: +* Restart MSYS shell via modified shortcut and update packages again using pacman: ```bash pacman -Syu @@ -471,7 +485,7 @@ application. The project can be built from scratch by following instructions for Linux above(but use `gmake` instead of `make`). If you are running Monero in a jail, you need to add `sysvsem="new"` to your jail configuration, otherwise lmdb will throw the error message: `Failed to open lmdb environment: Function not implemented`. -Monero is also available as a port or package as 'monero-cli`. +Monero is also available as a port or package as `monero-cli`. ### On OpenBSD: diff --git a/cmake/32-bit-toolchain.cmake b/cmake/32-bit-toolchain.cmake index 6bee56482..eb28953a4 100644 --- a/cmake/32-bit-toolchain.cmake +++ b/cmake/32-bit-toolchain.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/cmake/64-bit-toolchain.cmake b/cmake/64-bit-toolchain.cmake index 5eaa17596..2ec22b8e5 100644 --- a/cmake/64-bit-toolchain.cmake +++ b/cmake/64-bit-toolchain.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/cmake/FindCcache.cmake b/cmake/FindCcache.cmake index d98518134..d3f5f829b 100644 --- a/cmake/FindCcache.cmake +++ b/cmake/FindCcache.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/cmake/FindUnbound.cmake b/cmake/FindUnbound.cmake index 65c6725c6..611b047ab 100644 --- a/cmake/FindUnbound.cmake +++ b/cmake/FindUnbound.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are diff --git a/cmake/GitVersion.cmake b/cmake/GitVersion.cmake index 2839d549f..80f6b506d 100644 --- a/cmake/GitVersion.cmake +++ b/cmake/GitVersion.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/cmake/SetClangTidy.cmake b/cmake/SetClangTidy.cmake index ce66286e2..88dfe4be2 100644 --- a/cmake/SetClangTidy.cmake +++ b/cmake/SetClangTidy.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/cmake/Version.cmake b/cmake/Version.cmake index 707d72639..e9ed9fba1 100644 --- a/cmake/Version.cmake +++ b/cmake/Version.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/cmake/test-libusb-version.c b/cmake/test-libusb-version.c index bd8f90c03..9f22416b8 100644 --- a/cmake/test-libusb-version.c +++ b/cmake/test-libusb-version.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/cmake/test-protobuf.cpp b/cmake/test-protobuf.cpp index 4b2e19725..f1665969e 100644 --- a/cmake/test-protobuf.cpp +++ b/cmake/test-protobuf.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/cmake/test-static-assert.c b/cmake/test-static-assert.c index 520939c6f..1697bfeb9 100644 --- a/cmake/test-static-assert.c +++ b/cmake/test-static-assert.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/cmake/test-static-assert.cpp b/cmake/test-static-assert.cpp index 520939c6f..1697bfeb9 100644 --- a/cmake/test-static-assert.cpp +++ b/cmake/test-static-assert.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 046115bd3..10296514c 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/contrib/epee/CMakeLists.txt b/contrib/epee/CMakeLists.txt index 6e303eb0b..a61e50445 100644 --- a/contrib/epee/CMakeLists.txt +++ b/contrib/epee/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/contrib/epee/demo/.gitignore b/contrib/epee/demo/.gitignore deleted file mode 100644 index d9b4f015d..000000000 --- a/contrib/epee/demo/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build/* diff --git a/contrib/epee/demo/CMakeLists.txt b/contrib/epee/demo/CMakeLists.txt deleted file mode 100644 index d2ae0ed55..000000000 --- a/contrib/epee/demo/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -set(Boost_USE_MULTITHREADED ON) -#set(Boost_DEBUG 1) -find_package(Boost COMPONENTS system filesystem thread date_time chrono regex ) - -include_directories( ${Boost_INCLUDE_DIRS} ) - - -IF (MSVC) - add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /nologo /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /bigobj" ) -ELSE() - # set stuff for other systems - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder -D_GNU_SOURCE") -ENDIF() - - -include_directories(.) -include_directories(../include) -include_directories(iface) - - -# Add folders to filters -file(GLOB_RECURSE LEVIN_GENERAL_SECTION RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/demo_levin_server/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/demo_levin_server/*.inl - ${CMAKE_CURRENT_SOURCE_DIR}/demo_levin_server/*.cpp) - -file(GLOB_RECURSE HTTP_GENERAL_SECTION RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/demo_http_server/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/demo_http_server/*.inl - ${CMAKE_CURRENT_SOURCE_DIR}/demo_http_server/*.cpp) - - - -source_group(general FILES ${LEVIN_GENERAL_SECTION} FILES ${HTTP_GENERAL_SECTION}) -#source_group(general FILES ${HTTP_GENERAL_SECTION}) - -add_executable(demo_http_server ${HTTP_GENERAL_SECTION} ) -add_executable(demo_levin_server ${LEVIN_GENERAL_SECTION} ) - -target_link_libraries( demo_http_server ${Boost_LIBRARIES} ) -target_link_libraries( demo_levin_server ${Boost_LIBRARIES} ) - -IF (NOT WIN32) - target_link_libraries (demo_http_server rt) - target_link_libraries (demo_levin_server rt) -ENDIF() - - diff --git a/contrib/epee/demo/README.txt b/contrib/epee/demo/README.txt deleted file mode 100644 index e69de29bb..000000000 --- a/contrib/epee/demo/README.txt +++ /dev/null diff --git a/contrib/epee/demo/demo_http_server/stdafx.cpp b/contrib/epee/demo/demo_http_server/stdafx.cpp deleted file mode 100644 index ecec24657..000000000 --- a/contrib/epee/demo/demo_http_server/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// demo_http_server.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/contrib/epee/demo/demo_http_server/stdafx.h b/contrib/epee/demo/demo_http_server/stdafx.h deleted file mode 100644 index e28883202..000000000 --- a/contrib/epee/demo/demo_http_server/stdafx.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "targetver.h" - - -#include <stdio.h> - - -#define BOOST_FILESYSTEM_VERSION 3 -#define ENABLE_RELEASE_LOGGING -#include "misc_log_ex.h" - - diff --git a/contrib/epee/demo/demo_http_server/targetver.h b/contrib/epee/demo/demo_http_server/targetver.h deleted file mode 100644 index 6fe8eb79e..000000000 --- a/contrib/epee/demo/demo_http_server/targetver.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -// The following macros define the minimum required platform. The minimum required platform -// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run -// your application. The macros work by enabling all features available on platform versions up to and -// including the version specified. - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. -#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. -#endif - diff --git a/contrib/epee/demo/demo_levin_server/stdafx.cpp b/contrib/epee/demo/demo_levin_server/stdafx.cpp deleted file mode 100644 index d6ea1c6f2..000000000 --- a/contrib/epee/demo/demo_levin_server/stdafx.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "stdafx.h" - diff --git a/contrib/epee/demo/demo_levin_server/stdafx.h b/contrib/epee/demo/demo_levin_server/stdafx.h deleted file mode 100644 index f69d5922b..000000000 --- a/contrib/epee/demo/demo_levin_server/stdafx.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "targetver.h" - - -#include <stdio.h> - - -#define BOOST_FILESYSTEM_VERSION 3 -#define ENABLE_RELEASE_LOGGING -#include "log_opt_defs.h" -#include "misc_log_ex.h" - - diff --git a/contrib/epee/demo/demo_levin_server/targetver.h b/contrib/epee/demo/demo_levin_server/targetver.h deleted file mode 100644 index 6fe8eb79e..000000000 --- a/contrib/epee/demo/demo_levin_server/targetver.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -// The following macros define the minimum required platform. The minimum required platform -// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run -// your application. The macros work by enabling all features available on platform versions up to and -// including the version specified. - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. -#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. -#endif - diff --git a/contrib/epee/demo/generate_gcc.sh b/contrib/epee/demo/generate_gcc.sh deleted file mode 100644 index fcd0a8a7e..000000000 --- a/contrib/epee/demo/generate_gcc.sh +++ /dev/null @@ -1,4 +0,0 @@ -mkdir build -cd build -cmake .. -#cmake -DBOOST_ROOT=/usr/local/proj/boost_1_49_0 -DBOOST_LIBRARYDIR=/usr/local/proj/boost_1_49_0/stage/lib .. diff --git a/contrib/epee/demo/generate_vc_proj.bat b/contrib/epee/demo/generate_vc_proj.bat deleted file mode 100644 index 7d83ced6f..000000000 --- a/contrib/epee/demo/generate_vc_proj.bat +++ /dev/null @@ -1,7 +0,0 @@ -mkdir build - -cd build - -cmake "-DBoost_USE_STATIC_LIBS=TRUE" -G "Visual Studio 11 Win64" .. -cd .. -pause diff --git a/contrib/epee/demo/iface/transport_defs.h b/contrib/epee/demo/iface/transport_defs.h deleted file mode 100644 index 61968ed71..000000000 --- a/contrib/epee/demo/iface/transport_defs.h +++ /dev/null @@ -1,225 +0,0 @@ -#pragma once - -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_base.h" - -namespace demo -{ - - struct some_test_subdata - { - std::string m_str; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_str) - END_KV_SERIALIZE_MAP() - }; - - struct some_test_data - { - std::string m_str; - uint64_t m_uint64; - uint32_t m_uint32; - uint16_t m_uint16; - uint8_t m_uint8; - int64_t m_int64; - int32_t m_int32; - int16_t m_int16; - int8_t m_int8; - double m_double; - bool m_bool; - std::list<std::string> m_list_of_str; - std::list<uint64_t> m_list_of_uint64_t; - std::list<uint32_t> m_list_of_uint32_t; - std::list<uint16_t> m_list_of_uint16_t; - std::list<uint8_t> m_list_of_uint8_t; - std::list<int64_t> m_list_of_int64_t; - std::list<int32_t> m_list_of_int32_t; - std::list<int16_t> m_list_of_int16_t; - std::list<int8_t> m_list_of_int8_t; - std::list<double> m_list_of_double; - std::list<bool> m_list_of_bool; - some_test_subdata m_subobj; - std::list<some_test_data> m_list_of_self; - epee::serialization::storage_entry m_storage_entry_int; - epee::serialization::storage_entry m_storage_entry_string; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_str) - KV_SERIALIZE(m_uint64) - KV_SERIALIZE(m_uint32) - KV_SERIALIZE(m_uint16) - KV_SERIALIZE(m_uint8) - KV_SERIALIZE(m_int64) - KV_SERIALIZE(m_int32) - KV_SERIALIZE(m_int16) - KV_SERIALIZE(m_int8) - KV_SERIALIZE(m_double) - KV_SERIALIZE(m_bool) - KV_SERIALIZE(m_subobj) - KV_SERIALIZE(m_list_of_str) - KV_SERIALIZE(m_list_of_uint64_t) - KV_SERIALIZE(m_list_of_uint32_t) - KV_SERIALIZE(m_list_of_uint16_t) - KV_SERIALIZE(m_list_of_uint8_t) - KV_SERIALIZE(m_list_of_int64_t) - KV_SERIALIZE(m_list_of_int32_t) - KV_SERIALIZE(m_list_of_int16_t) - KV_SERIALIZE(m_list_of_int8_t) - KV_SERIALIZE(m_list_of_double) - KV_SERIALIZE(m_list_of_bool) - KV_SERIALIZE(m_list_of_self) - KV_SERIALIZE(m_storage_entry_int) - KV_SERIALIZE(m_storage_entry_string) - END_KV_SERIALIZE_MAP() - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_EXAMPLE_1 - { - const static int ID = 1000; - - struct request_t - { - std::string example_string_data; - some_test_data sub; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(example_string_data) - KV_SERIALIZE(sub) - END_KV_SERIALIZE_MAP() - }; - typedef epee::misc_utils::struct_init<request_t> request; - - - struct response_t - { - bool m_success; - std::list<some_test_data> subs; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_success) - KV_SERIALIZE(subs) - END_KV_SERIALIZE_MAP() - }; - }; - typedef epee::misc_utils::struct_init<response_t> response; - - - - struct COMMAND_EXAMPLE_2 - { - const static int ID = 1001; - - struct request_t - { - std::string example_string_data2; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(example_string_data2) - END_KV_SERIALIZE_MAP() - }; - typedef epee::misc_utils::struct_init<request_t> request; - - struct response_t - { - bool m_success; - - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_success) - END_KV_SERIALIZE_MAP() - }; - typedef epee::misc_utils::struct_init<response_t> response; - }; - - - //------------------------------------------------------------------------------------- - //------------------------------------------------------------------------------------- - //in debug purpose - bool operator != (const some_test_subdata& a, const some_test_subdata& b) - { - return b.m_str != a.m_str; - } - - bool operator == (const some_test_data& a, const some_test_data& b) - { - if( b.m_str != a.m_str - || b.m_uint64 != a.m_uint64 - || b.m_uint32 != a.m_uint32 - || b.m_uint16 != a.m_uint16 - || b.m_uint8 != a.m_uint8 - || b.m_int64 != a.m_int64 - || b.m_int32 != a.m_int32 - || b.m_int16 != a.m_int16 - || b.m_int8 != a.m_int8 - || b.m_double != a.m_double - || b.m_bool != a.m_bool - || b.m_list_of_str != a.m_list_of_str - || b.m_list_of_uint64_t != a.m_list_of_uint64_t - || b.m_list_of_uint32_t != a.m_list_of_uint32_t - || b.m_list_of_uint16_t != a.m_list_of_uint16_t - || b.m_list_of_uint8_t != a.m_list_of_uint8_t - || b.m_list_of_int64_t != a.m_list_of_int64_t - || b.m_list_of_int32_t != a.m_list_of_int32_t - || b.m_list_of_int16_t != a.m_list_of_int16_t - || b.m_list_of_int8_t != a.m_list_of_int8_t - || b.m_list_of_double != a.m_list_of_double - || b.m_list_of_bool != a.m_list_of_bool - || b.m_subobj != a.m_subobj - || b.m_list_of_self != a.m_list_of_self - || b.m_storage_entry_int.which() != a.m_storage_entry_int.which() - || b.m_storage_entry_string.which() != a.m_storage_entry_string.which() - ) - return false; - return true; - } - - inline some_test_data get_test_data() - { - some_test_data s; - s.m_str = "zuzuzuzuzuz"; - s.m_uint64 = 111111111111111; - s.m_uint32 = 2222222; - s.m_uint16 = 2222; - s.m_uint8 = 22; - s.m_int64 = -111111111111111; - s.m_int32 = -2222222; - s.m_int16 = -2222; - s.m_int8 = -24; - s.m_double = 0.11111; - s.m_bool = true; - s.m_list_of_str.push_back("1112121"); - s.m_list_of_uint64_t.push_back(1111111111); - s.m_list_of_uint64_t.push_back(2222222222); - s.m_list_of_uint32_t.push_back(1111111); - s.m_list_of_uint32_t.push_back(2222222); - s.m_list_of_uint16_t.push_back(1111); - s.m_list_of_uint16_t.push_back(2222); - s.m_list_of_uint8_t.push_back(11); - s.m_list_of_uint8_t.push_back(22); - - - s.m_list_of_int64_t.push_back(-1111111111); - s.m_list_of_int64_t.push_back(-222222222); - s.m_list_of_int32_t.push_back(-1111111); - s.m_list_of_int32_t.push_back(-2222222); - s.m_list_of_int16_t.push_back(-1111); - s.m_list_of_int16_t.push_back(-2222); - s.m_list_of_int8_t.push_back(-11); - s.m_list_of_int8_t.push_back(-22); - - s.m_list_of_double.push_back(0.11111); - s.m_list_of_double.push_back(0.22222); - s.m_list_of_bool.push_back(true); - s.m_list_of_bool.push_back(false); - - s.m_subobj.m_str = "subszzzzzzzz"; - s.m_list_of_self.push_back(s); - s.m_storage_entry_int = epee::serialization::storage_entry(uint64_t(22222)); - s.m_storage_entry_string = epee::serialization::storage_entry(std::string("sdsvsdvs")); - return s; - } -} diff --git a/contrib/epee/include/ado_db_helper.h b/contrib/epee/include/ado_db_helper.h deleted file mode 100644 index ed4e5b30f..000000000 --- a/contrib/epee/include/ado_db_helper.h +++ /dev/null @@ -1,1095 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _DB_ADO_HELPER_H_ -#define _DB_ADO_HELPER_H_ - -#include <vector> -#include <comutil.h> -#include "string_coding.h" -#include "math_helper.h" -#include "file_io_utils.h" -#include "global_stream_operators.h" - - - -#define BEGIN_TRY_SECTION() try { - -#define CATCH_TRY_SECTION(ret_val) CATCH_TRY_SECTION_MESS(ret_val, "") - -#define CATCH_TRY_SECTION_MESS(ret_val, mess_where) }\ - catch(const std::exception&ex)\ - {\ - LOG_PRINT_J("DB_ERROR: " << ex.what(), LOG_LEVEL_0);\ - return ret_val;\ - }\ - catch(const _com_error& comm_err)\ - {\ - const TCHAR* pstr = comm_err.Description();\ - std::string descr = string_encoding::convert_to_ansii(pstr?pstr:TEXT(""));\ - const TCHAR* pmessage = comm_err.ErrorMessage();\ - pstr = comm_err.Source();\ - std::string source = string_encoding::convert_to_ansii(pstr?pstr:TEXT(""));\ - LOG_PRINT_J("COM_ERROR " << mess_where << ":\n\tDescriprion:" << descr << ", \n\t Message: " << string_encoding::convert_to_ansii(pmessage) << "\n\t Source: " << source, LOG_LEVEL_0);\ - return ret_val;\ - }\ - catch(...)\ - {\ - LOG_PRINT_J("..._ERROR: Unknown error.", LOG_LEVEL_0);\ - return ret_val;\ - }\ - -namespace epee -{ -namespace ado_db_helper -{ - - struct profile_entry - { - profile_entry():m_call_count(0), m_max_time(0), m_min_time(0) - {} - //std::string m_sql; - math_helper::average<DWORD, 10> m_avrg; - size_t m_call_count; - DWORD m_max_time; - DWORD m_min_time; - }; - - class profiler_manager - { - public: - typedef std::map<std::string, profile_entry> sqls_map; - profiler_manager(){} - - static bool sort_by_timing(const sqls_map::iterator& a, const sqls_map::iterator& b) - { - return a->second.m_avrg.get_avg() > b->second.m_avrg.get_avg(); - } - - bool flush_log(const std::string& path) - { - CRITICAL_REGION_BEGIN(m_sqls_lock); - std::stringstream strm; - strm << "SQL PROFILE:\r\nStatements: " << m_sqls.size() << "\r\n"; - std::list<sqls_map::iterator> m_sorted_by_time_sqls; - for(std::map<std::string, profile_entry>::iterator it = m_sqls.begin();it!=m_sqls.end();it++) - m_sorted_by_time_sqls.push_back(it); - - m_sorted_by_time_sqls.sort(sort_by_timing); - - for(std::list<sqls_map::iterator>::iterator it = m_sorted_by_time_sqls.begin();it!=m_sorted_by_time_sqls.end();it++) - { - strm << "---------------------------------------------------------------------------------------------------------\r\nSQL: " << (*it)->first << "\r\n"; - strm << "\tavrg: " << (*it)->second.m_avrg.get_avg() << "\r\n\tmax: " << (*it)->second.m_max_time << "\r\n\tmin: " << (*it)->second.m_min_time << "\r\n\tcount: " << (*it)->second.m_call_count << "\r\n"; - } - - return file_io_utils::save_string_to_file(path.c_str(), strm.str()); - CRITICAL_REGION_END(); - } - - bool push_entry(const std::string sql, DWORD time) - { - CRITICAL_REGION_BEGIN(m_sqls_lock); - profile_entry& entry_ref = m_sqls[sql]; - entry_ref.m_avrg.push(time); - entry_ref.m_call_count++; - if(time > entry_ref.m_max_time) entry_ref.m_max_time = time; - if(time < entry_ref.m_min_time || entry_ref.m_min_time == 0) entry_ref.m_min_time = time; - CRITICAL_REGION_END(); - return true; - } - - bool get_entry_avarege(const std::string sql, DWORD& time) - { - CRITICAL_REGION_BEGIN(m_sqls_lock); - sqls_map::iterator it = m_sqls.find(sql); - if(it==m_sqls.end()) - return false; - - time = static_cast<DWORD>(it->second.m_avrg.get_avg()); - CRITICAL_REGION_END(); - return true; - } - - private: - - sqls_map m_sqls; - critical_section m_sqls_lock; - }; -inline - profiler_manager* get_set_profiler(bool need_to_set = false, profiler_manager** pprofiler = NULL) - { - static profiler_manager* pmanager = NULL; - if(need_to_set) - pmanager = *pprofiler; - //else - // *pprofiler = pmanager; - - return pmanager; - } -inline - bool init() // INIT and DEINIT are NOT THREAD SAFE operations, CALL it BEFOR u start using this wrapper. - { - profiler_manager* pmanager = new profiler_manager(); - get_set_profiler(true, &pmanager); - return true; - } -inline - bool deinit() - { - profiler_manager* pmanager = get_set_profiler(); - //get_set_profiler(false, &pmanager); - if(pmanager) - delete pmanager; - return true; - } - inline bool push_timing(const std::string sql, DWORD time) - { - profiler_manager* pmanager = get_set_profiler(); - //get_set_profiler(false, &pmanager); - if(pmanager) - return pmanager->push_entry(sql, time); - return true; - } - - inline bool flush_profiler(const std::string path) - { - profiler_manager* pmanager = get_set_profiler(); - //get_set_profiler(false, &pmanager); - if(pmanager) - return pmanager->flush_log(path); - return true; - } - - class timing_guard - { - DWORD m_start_time; - std::string m_sql; - - public: - timing_guard(const std::string& sql) - { - m_start_time = ::GetTickCount(); - m_sql = sql; - } - - ~timing_guard() - { - DWORD timing = ::GetTickCount() - m_start_time; - push_timing(m_sql, timing); - } - }; -#define PROFILE_SQL(sql) timing_guard local_timing(sql) - - - typedef std::vector<std::vector<_variant_t> > table; - - inline bool add_parametr(ADODB::_CommandPtr cmd, const std::string& parametr) - { - _variant_t param(parametr.c_str()); - ADODB::ADO_LONGPTR size = sizeof(parametr); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("", ADODB::adVarChar, ADODB::adParamInput, static_cast<long>(parametr.size()+1), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const std::wstring& parametr) - { - _variant_t param(parametr.c_str()); - ADODB::ADO_LONGPTR size = sizeof(parametr); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("", ADODB::adVarWChar, ADODB::adParamInput, static_cast<long>(parametr.size()+2), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const __int64 parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast<long>(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adBigInt, ADODB::adParamInput, static_cast<long>(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const unsigned __int64 parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast<long>(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adUnsignedBigInt, ADODB::adParamInput, static_cast<long>(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - - inline bool add_parametr(ADODB::_CommandPtr cmd, const int parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast<long>(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adInteger, ADODB::adParamInput, static_cast<long>(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const unsigned int parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast<long>(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adUnsignedInt, ADODB::adParamInput, static_cast<long>(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, float parametr) - { - _variant_t param; - param.ChangeType(VT_R4); - param.fltVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adSingle, ADODB::adParamInput, static_cast<long>(sizeof(float)), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, bool parametr) - { - _variant_t param; - param = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adBoolean, ADODB::adParamInput, sizeof(parametr), param); - cmd->Parameters->Append(param_obj); - return true; - } - - - inline bool add_parametr(ADODB::_CommandPtr cmd, _variant_t parametr) - { - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDBTimeStamp, ADODB::adParamInput, sizeof(parametr), parametr); - cmd->Parameters->Append(param_obj); - return true; - } - - - inline bool add_parametr_as_double(ADODB::_CommandPtr cmd, const DATE parametr) - { - _variant_t param; - param.ChangeType(VT_R8); - param.dblVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDouble, ADODB::adParamInput, sizeof(float), param); - cmd->Parameters->Append(param_obj); - return true; - } - - template<typename TParam> - inline bool add_parametr(ADODB::_CommandPtr cmd, const std::list<TParam> params) - { - for(std::list<TParam>::const_iterator it = params.begin(); it!=params.end(); it++) - if(!add_parametr(cmd, *it)) - return false; - return true; - } - - /* - inline bool add_parametr(ADODB::_CommandPtr cmd, const size_t parametr) - { - _variant_t param; - param.ChangeType(VT_I4); - param.intVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adInteger, ADODB::adParamInput, sizeof(parametr), param); - cmd->Parameters->Append(param_obj); - return true; - }*/ - - - inline bool add_parametr(ADODB::_CommandPtr cmd, const DATE parametr) - { - /*_variant_t param; - param.ChangeType(VT_R8); - param.dblVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDouble, ADODB::adParamInput, sizeof(float), param); - cmd->Parameters->Append(param_obj);*/ - - _variant_t param; - param.ChangeType(VT_DATE); - param.date = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDBDate, ADODB::adParamInput, sizeof(parametr), param); - cmd->Parameters->Append(param_obj); - - return true; - } - - - inline bool execute_helper(ADODB::_CommandPtr cmd, _variant_t* pcount_processed = NULL) - { - //BEGIN_TRY_SECTION(); - - cmd->Execute(pcount_processed, NULL, ADODB::adExecuteNoRecords); - - - //CATCH_TRY_SECTION(false); - - return true; - } - - - inline bool select_helper(ADODB::_CommandPtr cmd, table& result_vector) - { - result_vector.clear(); - //BEGIN_TRY_SECTION(); - - ADODB::_RecordsetPtr precordset = cmd->Execute(NULL, NULL, NULL); - if(!precordset) - { - LOG_ERROR("DB_ERROR: cmd->Execute returned NULL!!!"); - return false; - } - - //if(precordset->EndOfFile == EOF) - //{ - // return true; - //} - /*try - { - if(precordset->MoveFirst()!= S_OK) - { - LOG_ERROR("DB_ERROR: Filed to move first!!!"); - return false; - } - } - catch (...) - { - return true; - }*/ - - size_t current_record_index = 0; - while(precordset->EndOfFile != EOF) - { - result_vector.push_back(table::value_type()); - size_t fields_count = precordset->Fields->Count; - result_vector[current_record_index].resize(fields_count); - for(size_t current_field_index = 0; current_field_index < fields_count; current_field_index++) - { - _variant_t var; - var.ChangeType(VT_I2); - var.intVal = static_cast<INT>(current_field_index); - result_vector[current_record_index][current_field_index] = precordset->Fields->GetItem(var)->Value; - } - precordset->MoveNext(); - current_record_index++; - } - //CATCH_TRY_SECTION(false); - return true; - } - - - template<typename TParam1> - struct adapter_zero - { - - }; - - template<typename TParam1> - struct adapter_single - { - TParam1 tparam1; - }; - template<typename TParam1, typename TParam2> - struct adapter_double - { - TParam1 tparam1; - TParam2 tparam2; - }; - - - template<typename TParam1, typename TParam2, typename TParam3> - struct adapter_triple - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - }; - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4> - struct adapter_quad - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - }; - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5> - struct adapter_quanto - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - }; - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6> - struct adapter_sixto - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - TParam6 tparam6; - }; - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6, typename TParam7> - struct adapter_sevento - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - TParam6 tparam6; - TParam7 tparam7; - }; - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6, typename TParam7, typename TParam8, typename TParam9> - struct adapter_nine - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - TParam6 tparam6; - TParam7 tparam7; - TParam8 tparam8; - TParam9 tparam9; - }; - - template<typename TParam1> - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_zero<TParam1>& params) - { - return true; - } - - template<typename TParam1> - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_single<TParam1>& params) - { - return add_parametr(cmd, params.tparam1); - } - - template<typename TParam1, typename TParam2> - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_double<TParam1, TParam2>& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - return add_parametr(cmd, params.tparam2); - } - - template<typename TParam1, typename TParam2, typename TParam3> - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_triple<TParam1, TParam2, TParam3>& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - return add_parametr(cmd, params.tparam3); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4> - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_quad<TParam1, TParam2, TParam3, TParam4>& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - return add_parametr(cmd, params.tparam4); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5> - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_quanto<TParam1, TParam2, TParam3, TParam4, TParam5>& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - return add_parametr(cmd, params.tparam5); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6> - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_sixto<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6>& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - if(!add_parametr(cmd, params.tparam5)) return false; - return add_parametr(cmd, params.tparam6); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6, typename TParam7> - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_sevento<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6, TParam7>& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - if(!add_parametr(cmd, params.tparam5)) return false; - if(!add_parametr(cmd, params.tparam6)) return false; - return add_parametr(cmd, params.tparam7); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6, typename TParam7, typename TParam8, typename TParam9> - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_nine<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6, TParam7, TParam8, TParam9>& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - if(!add_parametr(cmd, params.tparam5)) return false; - if(!add_parametr(cmd, params.tparam6)) return false; - if(!add_parametr(cmd, params.tparam7)) return false; - if(!add_parametr(cmd, params.tparam8)) return false; - return add_parametr(cmd, params.tparam9); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6, typename TParam7> - std::string print_parameters_multi(const adapter_sevento<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6, TParam7>& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5 << ", " << params.tparam6 << ", " << params.tparam7; - return strm.str(); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6, typename TParam7, typename TParam8, typename TParam9> - std::string print_parameters_multi(const adapter_nine<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6, TParam7, TParam8, TParam9>& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5 << ", " << params.tparam6 << ", " << params.tparam7 << ", " << params.tparam8 << ", " << params.tparam9; - return strm.str(); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6> - std::string print_parameters_multi(const adapter_sixto<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6>& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5 << ", " << params.tparam6; - return strm.str(); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5> - std::string print_parameters_multi(const adapter_quanto<TParam1, TParam2, TParam3, TParam4, TParam5>& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5; - return strm.str(); - } - - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4> - std::string print_parameters_multi(const adapter_quad<TParam1, TParam2, TParam3, TParam4>& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4; - return strm.str(); - } - - template<typename TParam1, typename TParam2, typename TParam3> - std::string print_parameters_multi(const adapter_triple<TParam1, TParam2, TParam3>& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3; - return strm.str(); - } - - template<typename TParam> - std::string get_str_param(const TParam& prm) - { - std::stringstream strm; - strm << prm; - return strm.str(); - } - - template<typename TParam> - std::string get_str_param(const std::list<TParam>& prm_lst) - { - std::stringstream strm; - for(std::list<TParam>::const_iterator it = prm_lst.begin();it!=prm_lst.end();it++) - strm << get_str_param(*it) << ", "; - return strm.str(); - } - - - template<typename TParam1, typename TParam2> - std::string print_parameters_multi(const adapter_double<TParam1, TParam2>& params) - { - std::stringstream strm; - strm << get_str_param(params.tparam1) << ", " << get_str_param(params.tparam2); - return strm.str(); - } - - template<typename TParam1> - std::string print_parameters_multi(const adapter_single<TParam1>& params) - { - std::stringstream strm; - strm << get_str_param(params.tparam1); - return strm.str(); - } - - template<typename TParam1> - std::string print_parameters_multi(const adapter_zero<TParam1>& params) - { - std::stringstream strm; - strm << "(no parametrs)"; - return strm.str(); - } - - - template<typename TParams> - bool execute_helper_multiparam(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParams& parametrs, _variant_t* pcount_processed = NULL) - { - PROFILE_SQL(sql_statment); - bool res = false; - BEGIN_TRY_SECTION(); - - ADODB::_CommandPtr cmd; - cmd.CreateInstance(__uuidof(ADODB::Command)); - cmd->CommandText = _bstr_t(sql_statment.c_str()); - - if(!add_parametrs_multi(cmd, parametrs)) - return false; - - cmd->ActiveConnection = pconnection; - res = execute_helper(cmd, pcount_processed); - - CATCH_TRY_SECTION_MESS(false, "while statment: " << sql_statment << " [params]: " << print_parameters_multi(parametrs)); - return res; - } - - - template<typename TParams> - inline - bool select_helper_multiparam(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParams& parametrs, table& result_vector) - { - PROFILE_SQL(sql_statment); - bool res = false; - BEGIN_TRY_SECTION(); - ADODB::_CommandPtr cmd; - cmd.CreateInstance(__uuidof(ADODB::Command)); - cmd->CommandText = _bstr_t(sql_statment.c_str()); - - - if(!add_parametrs_multi(cmd, parametrs)) - return false; - - cmd->ActiveConnection = pconnection; - res = select_helper(cmd, result_vector); - CATCH_TRY_SECTION_MESS(false, "while statment: " << sql_statment << " [params]: " << print_parameters_multi(parametrs)); - return res; - } - - - template<typename TParams> - inline - bool select_helper_param_container(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParams& parametrs, table& result_vector) - { - PROFILE_SQL(sql_statment); - bool res = false; - BEGIN_TRY_SECTION(); - ADODB::_CommandPtr cmd; - cmd.CreateInstance(__uuidof(ADODB::Command)); - cmd->CommandText = _bstr_t(sql_statment.c_str()); - - - for(TParams::const_iterator it = parametrs.begin(); it!=parametrs.end(); it++) - { - add_parametr(cmd, *it); - } - - cmd->ActiveConnection = pconnection; - res = select_helper(cmd, result_vector); - - CATCH_TRY_SECTION(false); - return res; - } - - - inline - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, _variant_t* pvt = NULL) - { - adapter_zero<int> params; - return execute_helper_multiparam(pconnection, sql_statment, params, pvt); - } - - template<typename TParam> - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam& parametr) - { - adapter_single<TParam> params; - params.tparam1 = parametr; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - - template<typename TParam1, typename TParam2> - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2) - { - adapter_double<TParam1, TParam2> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - return execute_helper_multiparam(pconnection, sql_statment, params); - - } - - template<typename TParam1, typename TParam2, typename TParam3> - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3) - { - adapter_triple<TParam1, TParam2, typename TParam3> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4> - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4) - { - adapter_quad<TParam1, TParam2, TParam3, TParam4> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5> - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4, const TParam5& parametr5) - { - adapter_quanto<TParam1, TParam2, TParam3, TParam4, TParam5> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6> - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4, const TParam5& parametr5, const TParam6& parametr6) - { - adapter_sixto<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6, typename TParam7> - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4, const TParam5& parametr5, const TParam6& parametr6, const TParam7& parametr7) - { - adapter_sevento<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6, TParam7> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - params.tparam7 = parametr7; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - inline - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, table& result_vector) - { - adapter_zero<int> params; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - - template<typename TParam> - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam& parametr, table& result_vector) - { - adapter_single<TParam> params; - params.tparam1 = parametr; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template<typename TParam1, typename TParam2> - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, table& result_vector) - { - adapter_double<TParam1, TParam2> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - - } - - template<typename TParam1, typename TParam2, typename TParam3> - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, table& result_vector) - { - adapter_triple<TParam1, TParam2, typename TParam3> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4> - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, table& result_vector) - { - adapter_quad<TParam1, TParam2, TParam3, TParam4> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5> - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, table& result_vector) - { - adapter_quanto<TParam1, TParam2, TParam3, TParam4, TParam5> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6> - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, const TParam6 parametr6, table& result_vector) - { - adapter_sixto<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6, typename TParam7> - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, const TParam6 parametr6, const TParam7 parametr7, table& result_vector) - { - adapter_sevento<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6, TParam7> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - params.tparam7 = parametr7; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename TParam5, typename TParam6, typename TParam7, typename TParam8, typename TParam9> - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, const TParam6 parametr6, const TParam7 parametr7,const TParam8 parametr8,const TParam9 parametr9, table& result_vector) - { - adapter_nine<TParam1, TParam2, TParam3, TParam4, TParam5, TParam6, TParam7, TParam8, TParam9> params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - params.tparam7 = parametr7; - params.tparam8 = parametr8; - params.tparam9 = parametr9; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - - - - /************************************************************************/ - /* */ - /************************************************************************/ - - class per_thread_connection_pool - { - public: - bool init(const std::string& connection_string, const std::string& login, const std::string& pass) - { - m_connection_string = connection_string; - m_login = login; - m_password = pass; - if(!get_db_connection().GetInterfacePtr()) - return false; - - return true; - } - - ADODB::_ConnectionPtr& get_db_connection() - { - - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr<ADODB::_ConnectionPtr>& conn_ptr = m_db_connections[::GetCurrentThreadId()]; - m_db_connections_lock.unlock(); - if(!conn_ptr.get()) - { - conn_ptr.reset(new ADODB::_ConnectionPtr()); - ADODB::_ConnectionPtr& conn = *conn_ptr.get(); - //init new connection - - BEGIN_TRY_SECTION(); - //_bstr_t str = _bstr_t("Provider=SQLOLEDB;Data Source=SRV1;Integrated Security=SSPI;Initial Catalog=dispatcher;"); - - if(S_OK != conn.CreateInstance(__uuidof(ADODB::Connection))) - { - LOG_ERROR("Failed to Create, instance, was CoInitialize called ???!"); - return conn; - } - - HRESULT res = conn->Open(_bstr_t(m_connection_string.c_str()), _bstr_t(m_login.c_str()), _bstr_t(m_password.c_str()), NULL); - if(res != S_OK) - { - LOG_ERROR("Failed to connect do DB, connection str:" << m_connection_string); - return conn; - } - CATCH_TRY_SECTION_MESS(conn, "while creating another connection"); - LOG_PRINT("New DB Connection added for threadid=" << ::GetCurrentThreadId(), LOG_LEVEL_0); - ado_db_helper::execute_helper(conn, "set enable_seqscan=false;"); - return conn; - } - - return *conn_ptr.get(); - } - - //---------------------------------------------------------------------------------------------- - bool check_status() - { - ADODB::_ConnectionPtr& rconn = get_db_connection(); - if(!ado_db_helper::execute_helper(rconn, "SET CLIENT_ENCODING TO 'SQL_ASCII'")) - { - - try{ - HRESULT res = rconn->Close(); - } - catch(...) - { - - }; - BEGIN_TRY_SECTION(); - - HRESULT res = rconn->Open(_bstr_t(m_connection_string.c_str()), _bstr_t(m_login.c_str()), _bstr_t(m_password.c_str()), NULL); - if(res != S_OK) - { - LOG_PRINT("Failed to restore connection to local AI DB", LOG_LEVEL_1); - return false; - } - CATCH_TRY_SECTION(false); - } - - return true; - } - - protected: - private: - std::map<DWORD, boost::shared_ptr<ADODB::_ConnectionPtr> > m_db_connections; - critical_section m_db_connections_lock; - std::string m_connection_string; - std::string m_login; - std::string m_password; - }; - - - template<typename TParam1, typename default_id_type, typename t_conn> - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, t_conn& c) - { - ado_db_helper::adapter_single<TParam1> params; - params.tparam1 = parametr_1; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - - template<typename TParam1, typename TParam2, typename default_id_type, typename t_conn> - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, TParam2 parametr_2, t_conn& c) - { - ado_db_helper::adapter_double<TParam1, TParam2> params; - params.tparam1 = parametr_1; - params.tparam2 = parametr_2; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - - template<typename TParam1, typename TParam2, typename TParam3, typename default_id_type, typename t_conn> - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, TParam2 parametr_2, TParam3 parametr_3, t_conn& c) - { - ado_db_helper::adapter_triple<TParam1, TParam2, TParam3> params; - params.tparam1 = parametr_1; - params.tparam2 = parametr_2; - params.tparam3 = parametr_3; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - template<typename TParam1, typename TParam2, typename TParam3, typename TParam4, typename default_id_type, typename t_conn> - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, TParam2 parametr_2, TParam3 parametr_3, TParam4 parametr_4, t_conn& c) - { - ado_db_helper::adapter_quad<TParam1, TParam2, TParam3, TParam4> params; - params.tparam1 = parametr_1; - params.tparam2 = parametr_2; - params.tparam3 = parametr_3; - params.tparam4 = parametr_4; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - template<typename TParams, typename default_id_type, typename t_conn> - bool find_or_add_t_multiparametred(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParams params, t_conn& c) - { - - //CHECK_CONNECTION(false); - - new_object_added = false; - ado_db_helper::table result_table; - - bool res = select_helper_multiparam(c.get_db_connection(), sql_select_statment, params, result_table); - if(!result_table.size()) - { - res = select_helper_multiparam(c.get_db_connection(), sql_insert_statment, params, result_table); - if(!res || !result_table.size()) - { - //last time try to select - res = select_helper_multiparam(c.get_db_connection(), sql_select_statment, params, result_table); - CHECK_AND_ASSERT_MES(res, false, "Failed to execute statment: " << sql_select_statment); - CHECK_AND_ASSERT_MES(result_table.size(), false, "No records returned from statment: " << sql_select_statment); - }else - { - new_object_added = true; - } - } - - BEGIN_TRY_SECTION() - id = result_table[0][0]; - CATCH_TRY_SECTION_MESS(false, "while converting returned value [find_or_add_t_multiparametred()]"); - - return true; - } - -} -} -#endif //!_DB_HELPER_H_ diff --git a/contrib/epee/include/byte_slice.h b/contrib/epee/include/byte_slice.h index 18d60e088..57f6c410a 100644 --- a/contrib/epee/include/byte_slice.h +++ b/contrib/epee/include/byte_slice.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/byte_stream.h b/contrib/epee/include/byte_stream.h index 93f9ac85c..e7993133a 100644 --- a/contrib/epee/include/byte_stream.h +++ b/contrib/epee/include/byte_stream.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/contrib/epee/include/copyable_atomic.h b/contrib/epee/include/copyable_atomic.h deleted file mode 100644 index 00a5f484b..000000000 --- a/contrib/epee/include/copyable_atomic.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include <atomic> - -namespace epee -{ - class copyable_atomic: public std::atomic<uint32_t> - { - public: - copyable_atomic() - {}; - copyable_atomic(uint32_t value) - { store(value); } - copyable_atomic(const copyable_atomic& a):std::atomic<uint32_t>(a.load()) - {} - copyable_atomic& operator= (const copyable_atomic& a) - { - store(a.load()); - return *this; - } - uint32_t operator++() - { - return std::atomic<uint32_t>::operator++(); - } - uint32_t operator++(int fake) - { - return std::atomic<uint32_t>::operator++(fake); - } - }; -} diff --git a/contrib/epee/include/file_io_utils.h b/contrib/epee/include/file_io_utils.h index 84dc79266..da05520c1 100644 --- a/contrib/epee/include/file_io_utils.h +++ b/contrib/epee/include/file_io_utils.h @@ -36,10 +36,7 @@ namespace file_io_utils { bool is_file_exist(const std::string& path); bool save_string_to_file(const std::string& path_to_file, const std::string& str); - bool get_file_time(const std::string& path_to_file, time_t& ft); - bool set_file_time(const std::string& path_to_file, const time_t& ft); bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000); - bool append_string_to_file(const std::string& path_to_file, const std::string& str); bool get_file_size(const std::string& path_to_file, uint64_t &size); } } diff --git a/contrib/epee/include/fnv1.h b/contrib/epee/include/fnv1.h index c04389bca..6a699f4d8 100644 --- a/contrib/epee/include/fnv1.h +++ b/contrib/epee/include/fnv1.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/contrib/epee/include/global_stream_operators.h b/contrib/epee/include/global_stream_operators.h deleted file mode 100644 index 6fbdbc2ed..000000000 --- a/contrib/epee/include/global_stream_operators.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -std::stringstream& operator<<(std::stringstream& out, const std::wstring& ws) -{ - std::string as = string_encoding::convert_to_ansii(ws); - out << as; - return out; -} diff --git a/contrib/epee/include/hex.h b/contrib/epee/include/hex.h index 8443cb92f..af0a581a9 100644 --- a/contrib/epee/include/hex.h +++ b/contrib/epee/include/hex.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/int-util.h b/contrib/epee/include/int-util.h index bc422d841..3789076e8 100644 --- a/contrib/epee/include/int-util.h +++ b/contrib/epee/include/int-util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/math_helper.h b/contrib/epee/include/math_helper.h index 29acffaea..6a759b515 100644 --- a/contrib/epee/include/math_helper.h +++ b/contrib/epee/include/math_helper.h @@ -37,8 +37,8 @@ #include <boost/uuid/uuid.hpp> #include <boost/uuid/random_generator.hpp> -#include "misc_os_dependent.h" #include "syncobj.h" +#include "time_helper.h" namespace epee { diff --git a/contrib/epee/include/memwipe.h b/contrib/epee/include/memwipe.h index c6f247913..ebb9373c9 100644 --- a/contrib/epee/include/memwipe.h +++ b/contrib/epee/include/memwipe.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h index 5ccfe6fcc..ee07bbe8f 100644 --- a/contrib/epee/include/misc_language.h +++ b/contrib/epee/include/misc_language.h @@ -30,74 +30,14 @@ #include <boost/utility/value_init.hpp> #include <boost/shared_ptr.hpp> -#include <limits> -#include <functional> #include <vector> namespace epee { -#define STD_TRY_BEGIN() try { - -#define STD_TRY_CATCH(where_, ret_val) \ - } \ - catch (const std::exception &e) \ - { \ - LOG_ERROR("EXCEPTION: " << where_ << ", mes: "<< e.what()); \ - return ret_val; \ - } \ - catch (...) \ - { \ - LOG_ERROR("EXCEPTION: " << where_ ); \ - return ret_val; \ - } - - - #define AUTO_VAL_INIT(v) boost::value_initialized<decltype(v)>() namespace misc_utils { - template<typename t_type> - t_type get_max_t_val(t_type t) - { - return (std::numeric_limits<t_type>::max)(); - } - - - template<typename t_iterator> - t_iterator move_it_forward(t_iterator it, size_t count) - { - while(count--) - it++; - return it; - } - - template<typename t_iterator> - t_iterator move_it_backward(t_iterator it, size_t count) - { - while(count--) - it--; - return it; - } - - - // TEMPLATE STRUCT less - template<class _Ty> - struct less_as_pod - : public std::binary_function<_Ty, _Ty, bool> - { // functor for operator< - bool operator()(const _Ty& _Left, const _Ty& _Right) const - { // apply operator< to operands - return memcmp(&_Left, &_Right, sizeof(_Left)) < 0; - } - }; - - template<class _Ty> - bool is_less_as_pod(const _Ty& _Left, const _Ty& _Right) - { // apply operator< to operands - return memcmp(&_Left, &_Right, sizeof(_Left)) < 0; - } - - bool sleep_no_w(long ms ); + bool sleep_no_w(long ms); template <typename T> T get_mid(const T &a, const T &b) diff --git a/contrib/epee/include/misc_os_dependent.h b/contrib/epee/include/misc_os_dependent.h deleted file mode 100644 index 522cdf263..000000000 --- a/contrib/epee/include/misc_os_dependent.h +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#ifdef _WIN32 -#include <winsock2.h> -#endif - -#ifdef WIN32 - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - - //#ifdef _WIN32_WINNT - // #undef _WIN32_WINNT - // #define _WIN32_WINNT 0x0600 - //#endif - - -#include <windows.h> -#endif - -#ifdef __MACH__ -#include <mach/clock.h> -#include <mach/mach.h> -#endif - -#include <iostream> -#include <ctime> - -#pragma once -namespace epee -{ -namespace misc_utils -{ - - inline uint64_t get_ns_count() - { -#if defined(_MSC_VER) - return ::GetTickCount64() * 1000000; -#elif defined(WIN32) - static LARGE_INTEGER pcfreq = {0}; - LARGE_INTEGER ticks; - if (!pcfreq.QuadPart) - QueryPerformanceFrequency(&pcfreq); - QueryPerformanceCounter(&ticks); - ticks.QuadPart *= 1000000000; /* we want nsec */ - return ticks.QuadPart / pcfreq.QuadPart; -#elif defined(__MACH__) - clock_serv_t cclock; - mach_timespec_t mts; - - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - - return ((uint64_t)mts.tv_sec * 1000000000) + (mts.tv_nsec); -#else - struct timespec ts; - if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - return 0; - } - return ((uint64_t)ts.tv_sec * 1000000000) + (ts.tv_nsec); -#endif - } - - inline uint64_t get_tick_count() - { - return get_ns_count() / 1000000; - } - - - inline int call_sys_cmd(const std::string& cmd) - { - std::cout << "# " << cmd << std::endl; - - FILE * fp ; - //char tstCommand[] ="ls *"; - char path[1000] = {0}; -#if !defined(__GNUC__) - fp = _popen(cmd.c_str(), "r"); -#else - fp = popen(cmd.c_str(), "r"); -#endif - while ( fgets( path, 1000, fp ) != NULL ) - std::cout << path; - -#if !defined(__GNUC__) - _pclose(fp); -#else - pclose(fp); -#endif - return 0; - - } - - std::string get_thread_string_id(); - - inline bool get_gmt_time(time_t t, struct tm &tm) - { -#ifdef _WIN32 - return gmtime_s(&tm, &t); -#else - return gmtime_r(&t, &tm); -#endif - } -} -} diff --git a/contrib/epee/include/mlocker.h b/contrib/epee/include/mlocker.h index a6d94b3d2..47ca0032a 100644 --- a/contrib/epee/include/mlocker.h +++ b/contrib/epee/include/mlocker.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/contrib/epee/include/net/abstract_tcp_server.h b/contrib/epee/include/net/abstract_tcp_server.h deleted file mode 100644 index cbad1717c..000000000 --- a/contrib/epee/include/net/abstract_tcp_server.h +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _ABSTRACT_TCP_SERVER_H_ -#define _ABSTRACT_TCP_SERVER_H_ - -#include <process.h> -#include <list> -#include <winsock2.h> -#include "winobj.h" -//#include "threads_helper.h" -#include "net_utils_base.h" - -#pragma comment(lib, "Ws2_32.lib") - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace net_utils -{ - /************************************************************************/ - /* */ - /************************************************************************/ - class soket_sender: public i_service_endpoint - { - public: - soket_sender(SOCKET sock):m_sock(sock){} - private: - virtual bool handle_send(const void* ptr, size_t cb) - { - if(cb != send(m_sock, (char*)ptr, (int)cb, 0)) - { - int sock_err = WSAGetLastError(); - LOG_ERROR("soket_sender: Failed to send " << cb << " bytes, Error=" << sock_err); - return false; - } - return true; - - } - - SOCKET m_sock; - }; - - - - /************************************************************************/ - /* */ - /************************************************************************/ - template<class THandler> - class abstract_tcp_server - { - public: - abstract_tcp_server(); - - bool init_server(int port_no); - bool deinit_server(); - bool run_server(); - bool send_stop_signal(); - - typename THandler::config_type& get_config_object(){return m_config;} - - private: - bool invoke_connection(SOCKET hnew_sock, long ip_from, int post_from); - static unsigned __stdcall ConnectionHandlerProc(void* lpParameter); - - class thread_context; - typedef std::list<thread_context> connections_container; - typedef typename connections_container::iterator connections_iterator; - - struct thread_context - { - HANDLE m_htread; - SOCKET m_socket; - abstract_tcp_server* powner; - connection_context m_context; - typename connections_iterator m_self_it; - }; - - SOCKET m_listen_socket; - int m_port; - bool m_initialized; - volatile LONG m_stop_server; - volatile LONG m_threads_count; - typename THandler::config_type m_config; - connections_container m_connections; - critical_section m_connections_lock; - }; - - template<class THandler> - unsigned __stdcall abstract_tcp_server<THandler>::ConnectionHandlerProc(void* lpParameter) - { - - thread_context* pthread_context = (thread_context*)lpParameter; - if(!pthread_context) - return 0; - abstract_tcp_server<THandler>* pthis = pthread_context->powner; - - ::InterlockedIncrement(&pthis->m_threads_count); - - ::CoInitialize(NULL); - - - LOG_PRINT("Handler thread STARTED with socket=" << pthread_context->m_socket, LOG_LEVEL_2); - int res = 0; - - soket_sender sndr(pthread_context->m_socket); - THandler srv(&sndr, pthread_context->powner->m_config, pthread_context->m_context); - - - srv.after_init_connection(); - - char buff[1000] = {0}; - std::string ansver; - while ( (res = recv(pthread_context->m_socket, (char*)buff, 1000, 0)) > 0) - { - LOG_PRINT("Data in, " << res << " bytes", LOG_LEVEL_3); - if(!srv.handle_recv(buff, res)) - break; - } - shutdown(pthread_context->m_socket, SD_BOTH); - closesocket(pthread_context->m_socket); - - abstract_tcp_server* powner = pthread_context->powner; - LOG_PRINT("Handler thread with socket=" << pthread_context->m_socket << " STOPPED", LOG_LEVEL_2); - powner->m_connections_lock.lock(); - ::CloseHandle(pthread_context->m_htread); - pthread_context->powner->m_connections.erase(pthread_context->m_self_it); - powner->m_connections_lock.unlock(); - CoUninitialize(); - ::InterlockedDecrement(&pthis->m_threads_count); - return 1; - } - //---------------------------------------------------------------------------------------- - template<class THandler> - abstract_tcp_server<THandler>::abstract_tcp_server():m_listen_socket(INVALID_SOCKET), - m_initialized(false), - m_stop_server(0), m_port(0), m_threads_count(0) - { - - } - - //---------------------------------------------------------------------------------------- - template<class THandler> - bool abstract_tcp_server<THandler>::init_server(int port_no) - { - m_port = port_no; - WSADATA wsad = {0}; - int err = ::WSAStartup(MAKEWORD(2,2), &wsad); - if ( err != 0 || LOBYTE( wsad.wVersion ) != 2 || HIBYTE( wsad.wVersion ) != 2 ) - { - LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - m_initialized = true; - - m_listen_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0); - if(INVALID_SOCKET == m_listen_socket) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - int opt = 1; - setsockopt (m_listen_socket, SOL_SOCKET,SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(int)); - - sockaddr_in adr = {0}; - adr.sin_family = AF_INET; - adr.sin_addr.s_addr = htonl(INADDR_ANY); - adr.sin_port = (u_short)htons(port_no); - - err = bind(m_listen_socket, (const sockaddr*)&adr, sizeof(adr )); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); - deinit_server(); - return false; - } - - ::InterlockedExchange(&m_stop_server, 0); - - return true; - } - //---------------------------------------------------------------------------------------- - template<class THandler> - bool abstract_tcp_server<THandler>::deinit_server() - { - - if(!m_initialized) - return true; - - if(INVALID_SOCKET != m_listen_socket) - { - shutdown(m_listen_socket, SD_BOTH); - int res = closesocket(m_listen_socket); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_listen_socket = INVALID_SOCKET; - } - - int res = ::WSACleanup(); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_initialized = false; - - return true; - } - //---------------------------------------------------------------------------------------- - template<class THandler> - bool abstract_tcp_server<THandler>::send_stop_signal() - { - InterlockedExchange(&m_stop_server, 1); - return true; - } - //---------------------------------------------------------------------------------------- - template<class THandler> - bool abstract_tcp_server<THandler>::run_server() - { - int err = listen(m_listen_socket, 10000); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - LOG_PRINT("Listening port "<< m_port << "...." , LOG_LEVEL_2); - - while(!m_stop_server) - { - sockaddr_in adr_from = {0}; - int adr_len = sizeof(adr_from); - fd_set read_fs = {0}; - read_fs.fd_count = 1; - read_fs.fd_array[0] = m_listen_socket; - TIMEVAL tv = {0}; - tv.tv_usec = 100; - int select_res = select(0, &read_fs, NULL, NULL, &tv); - if(!select_res) - continue; - SOCKET new_sock = WSAAccept(m_listen_socket, (sockaddr *)&adr_from, &adr_len, NULL, NULL); - LOG_PRINT("Accepted connection on socket=" << new_sock, LOG_LEVEL_2); - invoke_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port); - } - - deinit_server(); - -#define ABSTR_TCP_SRV_WAIT_COUNT_MAX 5000 -#define ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL 1000 - - int wait_count = 0; - - while(m_threads_count && wait_count*1000 < ABSTR_TCP_SRV_WAIT_COUNT_MAX) - { - ::Sleep(ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL); - wait_count++; - } - LOG_PRINT("abstract_tcp_server exit with wait count=" << wait_count*ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL << "(max=" << ABSTR_TCP_SRV_WAIT_COUNT_MAX <<")", LOG_LEVEL_0); - - return true; - } - //---------------------------------------------------------------------------------------- - template<class THandler> - bool abstract_tcp_server<THandler>::invoke_connection(SOCKET hnew_sock, const network_address &remote_address) - { - m_connections_lock.lock(); - m_connections.push_back(thread_context()); - m_connections_lock.unlock(); - m_connections.back().m_socket = hnew_sock; - m_connections.back().powner = this; - m_connections.back().m_self_it = --m_connections.end(); - m_connections.back().m_context.m_remote_address = remote_address; - m_connections.back().m_htread = threads_helper::create_thread(ConnectionHandlerProc, &m_connections.back()); // ugh, seems very risky - - return true; - } - //---------------------------------------------------------------------------------------- - - //---------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------- -} -} -#endif //_ABSTRACT_TCP_SERVER_H_ diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index f40cd108a..51aa9f275 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -49,7 +49,6 @@ #include <boost/asio/ssl.hpp> #include <boost/array.hpp> #include <boost/enable_shared_from_this.hpp> -#include <boost/interprocess/detail/atomic.hpp> #include <boost/thread/thread.hpp> #include "byte_slice.h" #include "net_utils_base.h" @@ -393,7 +392,7 @@ namespace net_utils std::vector<boost::shared_ptr<boost::thread> > m_threads; boost::thread::id m_main_thread_id; critical_section m_threads_lock; - volatile uint32_t m_thread_index; // TODO change to std::atomic + std::atomic<uint32_t> m_thread_index; t_connection_type m_connection_type; diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 89971bea2..0c3b457bc 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -44,8 +44,6 @@ #include "warnings.h" #include "string_tools_lexical.h" #include "misc_language.h" -#include "net/local_ip.h" -#include "pragma_comp_defs.h" #include <sstream> #include <iomanip> @@ -64,7 +62,6 @@ #define TIMEOUT_EXTRA_MS_PER_BYTE 0.2 -PRAGMA_WARNING_PUSH namespace epee { namespace net_utils @@ -79,8 +76,6 @@ namespace net_utils /************************************************************************/ /* */ /************************************************************************/ -PRAGMA_WARNING_DISABLE_VS(4355) - template<class t_protocol_handler> connection<t_protocol_handler>::connection( boost::asio::io_service& io_service, std::shared_ptr<shared_state> state, @@ -111,7 +106,6 @@ PRAGMA_WARNING_DISABLE_VS(4355) MDEBUG("test, connection constructor set m_connection_type="<<m_connection_type); } -PRAGMA_WARNING_DISABLE_VS(4355) //--------------------------------------------------------------------------------- template<class t_protocol_handler> connection<t_protocol_handler>::~connection() noexcept(false) @@ -384,7 +378,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) { //_info("[sock " << socket().native_handle() << "] protocol_want_close"); //some error in protocol, protocol handler ask to close connection - boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); + m_want_close_connection = true; bool do_shutdown = false; CRITICAL_REGION_BEGIN(m_send_que_lock); if(!m_send_que.size()) @@ -478,7 +472,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) if (!handshake(boost::asio::ssl::stream_base::server, boost::asio::const_buffer(buffer_.data(), buffer_ssl_init_fill))) { MERROR("SSL handshake failed"); - boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); + m_want_close_connection = true; m_ready_to_close = true; bool do_shutdown = false; CRITICAL_REGION_BEGIN(m_send_que_lock); @@ -834,7 +828,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) CRITICAL_REGION_BEGIN(m_send_que_lock); send_que_size = m_send_que.size(); CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); + m_want_close_connection = true; if(!send_que_size) { shutdown(); @@ -889,7 +883,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_send_que.pop_front(); if(m_send_que.empty()) { - if(boost::interprocess::ipcdetail::atomic_read32(&m_want_close_connection)) + if(m_want_close_connection) { do_shutdown = true; } @@ -1092,8 +1086,6 @@ PRAGMA_WARNING_DISABLE_VS(4355) } } //----------------------------------------------------------------------------- -PUSH_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) template<class t_protocol_handler> bool boosted_tcp_server<t_protocol_handler>::init_server(const std::string port, const std::string& address, const std::string port_ipv6, const std::string address_ipv6, bool use_ipv6, bool require_ipv4, @@ -1113,13 +1105,12 @@ DISABLE_GCC_WARNING(maybe-uninitialized) } return this->init_server(p, address, p_ipv6, address_ipv6, use_ipv6, require_ipv4, std::move(ssl_options)); } -POP_WARNINGS //--------------------------------------------------------------------------------- template<class t_protocol_handler> bool boosted_tcp_server<t_protocol_handler>::worker_thread() { TRY_ENTRY(); - uint32_t local_thr_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); + const uint32_t local_thr_index = m_thread_index++; // atomically increment, getting value before increment std::string thread_name = std::string("[") + m_thread_name_prefix; thread_name += boost::to_string(local_thr_index) + "]"; MLOG_SET_THREAD_NAME(thread_name); @@ -1734,4 +1725,3 @@ POP_WARNINGS } // namespace } // namespace -PRAGMA_WARNING_POP diff --git a/contrib/epee/include/net/abstract_tcp_server_cp.h b/contrib/epee/include/net/abstract_tcp_server_cp.h deleted file mode 100644 index f10f4203f..000000000 --- a/contrib/epee/include/net/abstract_tcp_server_cp.h +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _LEVIN_CP_SERVER_H_ -#define _LEVIN_CP_SERVER_H_ - -#include <winsock2.h> -#include <rpc.h> -#include <string> -#include <map> -#include <boost/shared_ptr.hpp> - -#include "misc_log_ex.h" -//#include "threads_helper.h" -#include "syncobj.h" -#define ENABLE_PROFILING -#include "profile_tools.h" -#include "net_utils_base.h" -#include "pragma_comp_defs.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -#define LEVIN_DEFAULT_DATA_BUFF_SIZE 2000 - -namespace epee -{ -namespace net_utils -{ - - template<class TProtocol> - class cp_server_impl//: public abstract_handler - { - public: - cp_server_impl(/*abstract_handler* phandler = NULL*/); - virtual ~cp_server_impl(); - - bool init_server(int port_no); - bool deinit_server(); - bool run_server(int threads_count = 0); - bool send_stop_signal(); - bool is_stop_signal(); - virtual bool on_net_idle(){return true;} - size_t get_active_connections_num(); - typename TProtocol::config_type& get_config_object(){return m_config;} - private: - enum overlapped_operation_type - { - op_type_recv, - op_type_send, - op_type_stop - }; - - struct io_data_base - { - OVERLAPPED m_overlapped; - WSABUF DataBuf; - overlapped_operation_type m_op_type; - DWORD TotalBuffBytes; - volatile LONG m_is_in_use; - char Buffer[1]; - }; - -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4355) - template<class TProtocol> - struct connection: public net_utils::i_service_endpoint - { - connection(typename TProtocol::config_type& ref_config):m_sock(INVALID_SOCKET), m_tprotocol_handler(this, ref_config, context), m_psend_data(NULL), m_precv_data(NULL), m_asked_to_shutdown(0), m_connection_shutwoned(0) - { - } - - //connection():m_sock(INVALID_SOCKET), m_tprotocol_handler(this, m_dummy_config, context), m_psend_data(NULL), m_precv_data(NULL), m_asked_to_shutdown(0), m_connection_shutwoned(0) - //{ - //} - - connection<TProtocol>& operator=(const connection<TProtocol>& obj) - { - return *this; - } - - bool init_buffers() - { - m_psend_data = (io_data_base*)new char[sizeof(io_data_base) + LEVIN_DEFAULT_DATA_BUFF_SIZE-1]; - m_psend_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE; - m_precv_data = (io_data_base*)new char[sizeof(io_data_base) + LEVIN_DEFAULT_DATA_BUFF_SIZE-1]; - m_precv_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE; - return true; - } - - bool query_shutdown() - { - if(!::InterlockedCompareExchange(&m_asked_to_shutdown, 1, 0)) - { - m_psend_data->m_op_type = op_type_stop; - ::PostQueuedCompletionStatus(m_completion_port, 0, (ULONG_PTR)this, &m_psend_data->m_overlapped); - } - return true; - } - - //bool set_config(typename TProtocol::config_type& config) - //{ - // this->~connection(); - // new(this) connection<TProtocol>(config); - // return true; - //} - ~connection() - { - if(m_psend_data) - delete m_psend_data; - - if(m_precv_data) - delete m_precv_data; - } - virtual bool handle_send(const void* ptr, size_t cb) - { - PROFILE_FUNC("[handle_send]"); - if(m_psend_data->TotalBuffBytes < cb) - resize_send_buff((DWORD)cb); - - ZeroMemory(&m_psend_data->m_overlapped, sizeof(OVERLAPPED)); - m_psend_data->DataBuf.len = (u_long)cb;//m_psend_data->TotalBuffBytes; - m_psend_data->DataBuf.buf = m_psend_data->Buffer; - memcpy(m_psend_data->DataBuf.buf, ptr, cb); - m_psend_data->m_op_type = op_type_send; - InterlockedExchange(&m_psend_data->m_is_in_use, 1); - DWORD bytes_sent = 0; - DWORD flags = 0; - int res = 0; - { - PROFILE_FUNC("[handle_send] ::WSASend"); - res = ::WSASend(m_sock, &(m_psend_data->DataBuf), 1, &bytes_sent, flags, &(m_psend_data->m_overlapped), NULL); - } - - if(res == SOCKET_ERROR ) - { - int err = ::WSAGetLastError(); - if(WSA_IO_PENDING == err ) - return true; - } - LOG_ERROR("BIG FAIL: WSASend error code not correct, res=" << res << " last_err=" << err); - ::InterlockedExchange(&m_psend_data->m_is_in_use, 0); - query_shutdown(); - //closesocket(m_psend_data); - return false; - }else if(0 == res) - { - ::InterlockedExchange(&m_psend_data->m_is_in_use, 0); - if(!bytes_sent || bytes_sent != cb) - { - int err = ::WSAGetLastError(); - LOG_ERROR("BIG FAIL: WSASend immediatly complete? but bad results, res=" << res << " last_err=" << err); - query_shutdown(); - return false; - }else - { - return true; - } - } - - return true; - } - bool resize_send_buff(DWORD new_size) - { - if(m_psend_data->TotalBuffBytes >= new_size) - return true; - - delete m_psend_data; - m_psend_data = (io_data_base*)new char[sizeof(io_data_base) + new_size-1]; - m_psend_data->TotalBuffBytes = new_size; - LOG_PRINT("Connection buffer resized up to " << new_size, LOG_LEVEL_3); - return true; - } - - - SOCKET m_sock; - net_utils::connection_context_base context; - TProtocol m_tprotocol_handler; - typename TProtocol::config_type m_dummy_config; - io_data_base* m_precv_data; - io_data_base* m_psend_data; - HANDLE m_completion_port; - volatile LONG m_asked_to_shutdown; - volatile LONG m_connection_shutwoned; - }; -PRAGMA_WARNING_POP - - bool worker_thread_member(); - static unsigned CALLBACK worker_thread(void* param); - - bool add_new_connection(SOCKET new_sock, long ip_from, int port_from); - bool shutdown_connection(connection<TProtocol>* pconn); - - - typedef std::map<SOCKET, boost::shared_ptr<connection<TProtocol> > > connections_container; - SOCKET m_listen_socket; - HANDLE m_completion_port; - connections_container m_connections; - critical_section m_connections_lock; - int m_port; - volatile LONG m_stop; - //abstract_handler* m_phandler; - bool m_initialized; - volatile LONG m_worker_thread_counter; - typename TProtocol::config_type m_config; - }; -} -} -#include "abstract_tcp_server_cp.inl" - - -#endif //_LEVIN_SERVER_H_ diff --git a/contrib/epee/include/net/abstract_tcp_server_cp.inl b/contrib/epee/include/net/abstract_tcp_server_cp.inl deleted file mode 100644 index e0ef6470e..000000000 --- a/contrib/epee/include/net/abstract_tcp_server_cp.inl +++ /dev/null @@ -1,607 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma comment(lib, "Ws2_32.lib") - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace net_utils -{ -template<class TProtocol> -cp_server_impl<TProtocol>::cp_server_impl(): - m_port(0), m_stop(false), - m_worker_thread_counter(0), m_listen_socket(INVALID_SOCKET) -{ -} -//------------------------------------------------------------- -template<class TProtocol> -cp_server_impl<TProtocol>::~cp_server_impl() -{ - deinit_server(); -} -//------------------------------------------------------------- -template<class TProtocol> -bool cp_server_impl<TProtocol>::init_server(int port_no) -{ - m_port = port_no; - - WSADATA wsad = {0}; - int err = ::WSAStartup(MAKEWORD(2,2), &wsad); - if ( err != 0 || LOBYTE( wsad.wVersion ) != 2 || HIBYTE( wsad.wVersion ) != 2 ) - { - LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - m_initialized = true; - - m_listen_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); - if(INVALID_SOCKET == m_listen_socket) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - - int opt = 1; - err = setsockopt (m_listen_socket, SOL_SOCKET,SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(int)); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to setsockopt(SO_REUSEADDR), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1); - deinit_server(); - return false; - } - - - sockaddr_in adr = {0}; - adr.sin_family = AF_INET; - adr.sin_addr.s_addr = htonl(INADDR_ANY); - adr.sin_port = (u_short)htons(m_port); - - //binding - err = bind(m_listen_socket, (const sockaddr*)&adr, sizeof(adr )); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1); - deinit_server(); - return false; - } - - - m_completion_port = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); - if(INVALID_HANDLE_VALUE == m_completion_port) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to CreateIoCompletionPort, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1); - deinit_server(); - return false; - } - - - return true; -} -//------------------------------------------------------------- - -//------------------------------------------------------------- -static int CALLBACK CPConditionFunc( - IN LPWSABUF lpCallerId, - IN LPWSABUF lpCallerData, - IN OUT LPQOS lpSQOS, - IN OUT LPQOS lpGQOS, - IN LPWSABUF lpCalleeId, - OUT LPWSABUF lpCalleeData, - OUT GROUP FAR *g, - IN DWORD_PTR dwCallbackData - ) -{ - - /*cp_server_impl* pthis = (cp_server_impl*)dwCallbackData; - if(!pthis) - return CF_REJECT;*/ - /*if(pthis->get_active_connections_num()>=FD_SETSIZE-1) - { - LOG_PRINT("Maximum connections count overfull.", LOG_LEVEL_2); - return CF_REJECT; - }*/ - - return CF_ACCEPT; -} -//------------------------------------------------------------- -template<class TProtocol> -size_t cp_server_impl<TProtocol>::get_active_connections_num() -{ - return m_connections.size(); -} -//------------------------------------------------------------- -template<class TProtocol> -unsigned CALLBACK cp_server_impl<TProtocol>::worker_thread(void* param) -{ - if(!param) - return 0; - - cp_server_impl<TProtocol>* pthis = (cp_server_impl<TProtocol>*)param; - pthis->worker_thread_member(); - return 1; -} -//------------------------------------------------------------- -template<class TProtocol> -bool cp_server_impl<TProtocol>::worker_thread_member() -{ - LOG_PRINT("Worker thread STARTED", LOG_LEVEL_1); - bool stop_handling = false; - while(!stop_handling) - { - PROFILE_FUNC("[worker_thread]Worker Loop"); - DWORD bytes_transfered = 0; - connection<TProtocol>* pconnection = 0; - io_data_base* pio_data = 0; - - { - PROFILE_FUNC("[worker_thread]GetQueuedCompletionStatus"); - BOOL res = ::GetQueuedCompletionStatus (m_completion_port, &bytes_transfered , (PULONG_PTR)&pconnection, (LPOVERLAPPED *)&pio_data, INFINITE); - if (res == 0) - { - // check return code for error - int err = GetLastError(); - LOG_PRINT("GetQueuedCompletionStatus failed with error " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_1); - - if(pio_data) - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - - - continue; - } - } - - if(pio_data) - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - - - - if(!bytes_transfered && !pconnection && !pio_data) - { - //signal to stop - break; - } - if(!pconnection || !pio_data) - { - LOG_PRINT("BIG FAIL: pconnection or pio_data is empty: pconnection=" << pconnection << " pio_data=" << pio_data, LOG_LEVEL_0); - break; - } - - - - if(::InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)) - { - LOG_ERROR("InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)"); - //DebugBreak(); - } - - if(pio_data->m_op_type == op_type_stop) - { - if(!pconnection) - { - LOG_ERROR("op_type=op_type_stop, but pconnection is empty!!!"); - continue; - } - shutdown_connection(pconnection); - continue;// - } - else if(pio_data->m_op_type == op_type_send) - { - continue; - //do nothing, just queuing request - }else if(pio_data->m_op_type == op_type_recv) - { - PROFILE_FUNC("[worker_thread]m_tprotocol_handler.handle_recv"); - if(bytes_transfered) - { - bool res = pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_transfered); - if(!res) - pconnection->query_shutdown(); - } - else - { - pconnection->query_shutdown(); - continue; - } - - } - - //preparing new request, - - { - PROFILE_FUNC("[worker_thread]RECV Request small loop"); - int res = 0; - while(true) - { - LOG_PRINT("Prepearing data for WSARecv....", LOG_LEVEL_3); - ZeroMemory(&pio_data->m_overlapped, sizeof(OVERLAPPED)); - pio_data->DataBuf.len = pio_data->TotalBuffBytes; - pio_data->DataBuf.buf = pio_data->Buffer; - pio_data->m_op_type = op_type_recv; - //calling WSARecv() and go to completion waiting - DWORD bytes_recvd = 0; - DWORD flags = 0; - - LOG_PRINT("Calling WSARecv....", LOG_LEVEL_3); - ::InterlockedExchange(&pio_data->m_is_in_use, 1); - res = WSARecv(pconnection->m_sock, &(pio_data->DataBuf), 1, &bytes_recvd , &flags, &(pio_data->m_overlapped), NULL); - if(res == SOCKET_ERROR ) - { - int err = ::WSAGetLastError(); - if(WSA_IO_PENDING == err ) - {//go pending, ok - LOG_PRINT("WSARecv return WSA_IO_PENDING", LOG_LEVEL_3); - break; - } - LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err); - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - pconnection->query_shutdown(); - break; - } - break; - /*else if(0 == res) - { - if(!bytes_recvd) - { - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - LOG_PRINT("WSARecv return 0, bytes_recvd=0, graceful close.", LOG_LEVEL_3); - int err = ::WSAGetLastError(); - //LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err); - //pconnection->query_shutdown(); - break; - }else - { - LOG_PRINT("WSARecv return immediatily 0, bytes_recvd=" << bytes_recvd, LOG_LEVEL_3); - //pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_recvd); - } - }*/ - } - } - } - - - LOG_PRINT("Worker thread STOPED", LOG_LEVEL_1); - ::InterlockedDecrement(&m_worker_thread_counter); - return true; -} -//------------------------------------------------------------- -template<class TProtocol> -bool cp_server_impl<TProtocol>::shutdown_connection(connection<TProtocol>* pconn) -{ - PROFILE_FUNC("[shutdown_connection]"); - - if(!pconn) - { - LOG_ERROR("Attempt to remove null pptr connection!"); - return false; - } - else - { - LOG_PRINT("Shutting down connection ("<< pconn << ")", LOG_LEVEL_3); - } - m_connections_lock.lock(); - connections_container::iterator it = m_connections.find(pconn->m_sock); - m_connections_lock.unlock(); - if(it == m_connections.end()) - { - LOG_ERROR("Failed to find closing socket=" << pconn->m_sock); - return false; - } - SOCKET sock = it->second->m_sock; - { - PROFILE_FUNC("[shutdown_connection] shutdown, close"); - ::shutdown(it->second->m_sock, SD_SEND ); - } - size_t close_sock_wait_count = 0; - { - LOG_PRINT("Entered to 'in_use wait zone'", LOG_LEVEL_3); - PROFILE_FUNC("[shutdown_connection] wait for in_use"); - while(::InterlockedCompareExchange(&it->second->m_precv_data->m_is_in_use, 1, 1)) - { - - Sleep(100); - close_sock_wait_count++; - } - LOG_PRINT("First step to 'in_use wait zone'", LOG_LEVEL_3); - - - while(::InterlockedCompareExchange(&it->second->m_psend_data->m_is_in_use, 1, 1)) - { - Sleep(100); - close_sock_wait_count++; - } - LOG_PRINT("Leaved 'in_use wait zone'", LOG_LEVEL_3); - } - - ::closesocket(it->second->m_sock); - - ::InterlockedExchange(&it->second->m_connection_shutwoned, 1); - m_connections_lock.lock(); - m_connections.erase(it); - m_connections_lock.unlock(); - LOG_PRINT("Socked " << sock << " closed, wait_count=" << close_sock_wait_count, LOG_LEVEL_2); - return true; -} -//------------------------------------------------------------- -template<class TProtocol> -bool cp_server_impl<TProtocol>::run_server(int threads_count = 0) -{ - int err = listen(m_listen_socket, 100); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - if(!threads_count) - { - SYSTEM_INFO si = {0}; - ::GetSystemInfo(&si); - threads_count = si.dwNumberOfProcessors + 2; - } - for(int i = 0; i != threads_count; i++) - { - boost::thread(boost::bind(&cp_server_impl::worker_thread_member, this)); - //HANDLE h_thread = threads_helper::create_thread(worker_thread, this); - InterlockedIncrement(&m_worker_thread_counter); - //::CloseHandle(h_thread); - } - - LOG_PRINT("Numbers of worker threads started: " << threads_count, LOG_LEVEL_1); - - m_stop = false; - while(!m_stop) - { - PROFILE_FUNC("[run_server] main_loop"); - TIMEVAL tv = {0}; - tv.tv_sec = 0; - tv.tv_usec = 100; - fd_set sock_set; - sock_set.fd_count = 1; - sock_set.fd_array[0] = m_listen_socket; - int select_res = 0; - { - PROFILE_FUNC("[run_server] select"); - select_res = select(0, &sock_set, &sock_set, NULL, &tv); - } - - if(SOCKET_ERROR == select_res) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to select, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - if(!select_res) - { - on_net_idle(); - continue; - } - else - { - sockaddr_in adr_from = {0}; - int adr_len = sizeof(adr_from); - SOCKET new_sock = INVALID_SOCKET; - { - PROFILE_FUNC("[run_server] WSAAccept"); - new_sock = ::WSAAccept(m_listen_socket, (sockaddr *)&adr_from, &adr_len, CPConditionFunc, (DWORD_PTR)this); - } - - if(INVALID_SOCKET == new_sock) - { - if(m_stop) - break; - int err = ::WSAGetLastError(); - LOG_PRINT("Failed to WSAAccept, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); - continue; - } - LOG_PRINT("Accepted connection (new socket=" << new_sock << ")", LOG_LEVEL_2); - { - PROFILE_FUNC("[run_server] Add new connection"); - add_new_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port); - } - - } - - } - LOG_PRINT("Closing connections("<< m_connections.size() << ") and waiting...", LOG_LEVEL_2); - m_connections_lock.lock(); - for(connections_container::iterator it = m_connections.begin(); it != m_connections.end(); it++) - { - ::shutdown(it->second->m_sock, SD_BOTH); - ::closesocket(it->second->m_sock); - } - m_connections_lock.unlock(); - size_t wait_count = 0; - while(m_connections.size() && wait_count < 100) - { - ::Sleep(100); - wait_count++; - } - LOG_PRINT("Connections closed OK (wait_count=" << wait_count << ")", LOG_LEVEL_2); - - - LOG_PRINT("Stopping worker threads("<< m_worker_thread_counter << ").", LOG_LEVEL_2); - for(int i = 0; i<m_worker_thread_counter; i++) - { - ::PostQueuedCompletionStatus(m_completion_port, 0, 0, 0); - } - - wait_count = 0; - while(InterlockedCompareExchange(&m_worker_thread_counter, 0, 0) && wait_count < 100) - { - Sleep(100); - wait_count++; - } - - LOG_PRINT("Net Server STOPPED, wait_count = " << wait_count, LOG_LEVEL_1); - return true; -} -//------------------------------------------------------------- -template<class TProtocol> -bool cp_server_impl<TProtocol>::add_new_connection(SOCKET new_sock, const network_address &address_from) -{ - PROFILE_FUNC("[add_new_connection]"); - - LOG_PRINT("Add new connection zone: entering lock", LOG_LEVEL_3); - m_connections_lock.lock(); - - boost::shared_ptr<connection<TProtocol> > ptr; - ptr.reset(new connection<TProtocol>(m_config)); - - connection<TProtocol>& conn = *ptr.get(); - m_connections[new_sock] = ptr; - LOG_PRINT("Add new connection zone: leaving lock", LOG_LEVEL_3); - m_connections_lock.unlock(); - conn.init_buffers(); - conn.m_sock = new_sock; - conn.context.m_remote_address = address_from; - conn.m_completion_port = m_completion_port; - { - PROFILE_FUNC("[add_new_connection] CreateIoCompletionPort"); - ::CreateIoCompletionPort((HANDLE)new_sock, m_completion_port, (ULONG_PTR)&conn, 0); - } - - //if(NULL == ::CreateIoCompletionPort((HANDLE)new_sock, m_completion_port, (ULONG_PTR)&conn, 0)) - //{ - // int err = ::GetLastError(); - // LOG_PRINT("Failed to CreateIoCompletionPort(associate socket and completion port), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); - // return false; - //} - - conn.m_tprotocol_handler.after_init_connection(); - { - PROFILE_FUNC("[add_new_connection] starting loop"); - int res = 0; - while(true)//res!=SOCKET_ERROR) - { - PROFILE_FUNC("[add_new_connection] in loop time"); - conn.m_precv_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE; - ZeroMemory(&conn.m_precv_data->m_overlapped, sizeof(OVERLAPPED)); - conn.m_precv_data->DataBuf.len = conn.m_precv_data->TotalBuffBytes; - conn.m_precv_data->DataBuf.buf = conn.m_precv_data->Buffer; - conn.m_precv_data->m_op_type = op_type_recv; - InterlockedExchange(&conn.m_precv_data->m_is_in_use, 1); - DWORD bytes_recvd = 0; - DWORD flags = 0; - - ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 1); - { - PROFILE_FUNC("[add_new_connection] ::WSARecv"); - res = ::WSARecv(conn.m_sock, &(conn.m_precv_data->DataBuf), 1, &bytes_recvd , &flags, &(conn.m_precv_data->m_overlapped), NULL); - } - if(res == SOCKET_ERROR ) - { - int err = ::WSAGetLastError(); - if(WSA_IO_PENDING == err ) - { - break; - } - LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err << " " << log_space::get_win32_err_descr(err)); - ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 0); - conn.query_shutdown(); - //shutdown_connection(&conn); - break; - } - - - break; - /*else if(0 == res) - { - if(!bytes_recvd) - { - PROFILE_FUNC("[add_new_connection] shutdown_connection"); - ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 0); - conn.query_shutdown(); - //shutdown_connection(&conn); - break; - }else - { - PROFILE_FUNC("[add_new_connection] handle_recv"); - } - }*/ - } - } - - - - return true; -} -//------------------------------------------------------------- -template<class TProtocol> -bool cp_server_impl<TProtocol>::deinit_server() -{ - if(!m_initialized) - return true; - - if(INVALID_SOCKET != m_listen_socket) - { - shutdown(m_listen_socket, SD_BOTH); - int res = closesocket(m_listen_socket); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_listen_socket = INVALID_SOCKET; - } - - int res = ::WSACleanup(); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_initialized = false; - - return true; -} - -//------------------------------------------------------------- -template<class TProtocol> -bool cp_server_impl<TProtocol>::send_stop_signal() -{ - ::InterlockedExchange(&m_stop, 1); - return true; -} -//------------------------------------------------------------- -template<class TProtocol> -bool cp_server_impl<TProtocol>::is_stop_signal() -{ - return m_stop?true:false; -} -//------------------------------------------------------------- -} -} diff --git a/contrib/epee/include/net/buffer.h b/contrib/epee/include/net/buffer.h index 56c67f6bf..c5305a8b7 100644 --- a/contrib/epee/include/net/buffer.h +++ b/contrib/epee/include/net/buffer.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp index 23873f65b..a26d538cd 100644 --- a/contrib/epee/include/net/connection_basic.hpp +++ b/contrib/epee/include/net/connection_basic.hpp @@ -8,7 +8,7 @@ // ! (how ever if in some wonderful juristdictions that is not the case, then why not make another sub-class withat that members and licence it as epee part) // ! Working on above premise, IF this is valid in your juristdictions, then consider this code as released as: -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -106,7 +106,7 @@ class connection_basic { // not-templated base class for rapid developmet of som std::unique_ptr< connection_basic_pimpl > mI; // my Implementation // moved here from orginal connecton<> - common member variables that do not depend on template in connection<> - volatile uint32_t m_want_close_connection; + std::atomic<bool> m_want_close_connection; std::atomic<bool> m_was_shutdown; critical_section m_send_que_lock; std::deque<byte_slice> m_send_que; diff --git a/contrib/epee/include/net/enums.h b/contrib/epee/include/net/enums.h index 2f27d07f9..8c402da20 100644 --- a/contrib/epee/include/net/enums.h +++ b/contrib/epee/include/net/enums.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/contrib/epee/include/net/http_auth.h b/contrib/epee/include/net/http_auth.h index b7105bf8a..97407ae2c 100644 --- a/contrib/epee/include/net/http_auth.h +++ b/contrib/epee/include/net/http_auth.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index 29ef82fb1..056b50fe6 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -50,7 +50,6 @@ #include "abstract_http_client.h" #include "http_base.h" #include "http_auth.h" -#include "to_nonconst_iterator.h" #include "net_parse_helpers.h" #include "syncobj.h" diff --git a/contrib/epee/include/net/http_client_via_api_helper.h b/contrib/epee/include/net/http_client_via_api_helper.h deleted file mode 100644 index 3242e4162..000000000 --- a/contrib/epee/include/net/http_client_via_api_helper.h +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include <wininet.h> -#include <atlutil.h> -#pragma comment(lib, "Wininet.lib") - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ -namespace net_utils -{ - inline - bool http_ssl_invoke(const std::string& url, const std::string usr, const std::string psw, std::string& http_response_body, bool use_post = false) - { - bool final_res = false; - - ATL::CUrl url_obj; - BOOL crack_rss = url_obj.CrackUrl(string_encoding::convert_to_t<std::basic_string<TCHAR> >(url).c_str()); - - HINTERNET hinet = ::InternetOpenA(SHARED_JOBSCOMMON_HTTP_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); - if(!hinet) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenA, \nError: " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - return false; - } - - DWORD dwFlags = 0; - DWORD dwBuffLen = sizeof(dwFlags); - - if(usr.size()) - { - dwFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID| - INTERNET_FLAG_PRAGMA_NOCACHE | SECURITY_FLAG_IGNORE_UNKNOWN_CA|INTERNET_FLAG_SECURE; - }else - { - dwFlags |= INTERNET_FLAG_PRAGMA_NOCACHE; - } - - - int port = url_obj.GetPortNumber(); - BOOL res = FALSE; - - HINTERNET hsession = ::InternetConnectA(hinet, string_encoding::convert_to_ansii(url_obj.GetHostName()).c_str(), port/*INTERNET_DEFAULT_HTTPS_PORT*/, usr.c_str(), psw.c_str(), INTERNET_SERVICE_HTTP, dwFlags, NULL); - if(hsession) - { - const std::string uri = string_encoding::convert_to_ansii(url_obj.GetUrlPath()) + string_encoding::convert_to_ansii(url_obj.GetExtraInfo()); - - HINTERNET hrequest = ::HttpOpenRequestA(hsession, use_post?"POST":NULL, uri.c_str(), NULL, NULL,NULL, dwFlags, NULL); - if(hrequest) - { - while(true) - { - res = ::HttpSendRequestA(hrequest, NULL, 0, NULL, 0); - if(!res) - { - //ERROR_INTERNET_INVALID_CA 45 - //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) - int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpSendRequestA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - - DWORD code = 0; - DWORD buf_len = sizeof(code); - DWORD index = 0; - res = ::HttpQueryInfo(hrequest, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &code, &buf_len, &index); - if(!res) - { - //ERROR_INTERNET_INVALID_CA 45 - //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) - int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpQueryInfo, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - if(code < 200 || code > 299) - { - LOG_PRINT("Wrong server response, HttpQueryInfo returned statuse code" << code , LOG_LEVEL_0); - break; - } - - - char buff[100000] = {0}; - DWORD readed = 0; - while(true) - { - res = ::InternetReadFile(hrequest, buff, sizeof(buff), &readed); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetReadFile, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - if(readed) - { - http_response_body.append(buff, readed); - } - else - break; - } - - if(!res) - break; - - - //we success - final_res = true; - - res = ::InternetCloseHandle(hrequest); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - - break; - } - } - else - { - //ERROR_INTERNET_INVALID_CA - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenUrlA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - return false; - } - - res = ::InternetCloseHandle(hsession); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - }else - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetConnectA(" << string_encoding::convert_to_ansii(url_obj.GetHostName()) << ", port " << port << " \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - - - - res = ::InternetCloseHandle(hinet); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - return final_res; - } -} -} diff --git a/contrib/epee/include/net/http_protocol_handler.h b/contrib/epee/include/net/http_protocol_handler.h index a29f141e8..258b07e2c 100644 --- a/contrib/epee/include/net/http_protocol_handler.h +++ b/contrib/epee/include/net/http_protocol_handler.h @@ -33,7 +33,6 @@ #include <boost/optional/optional.hpp> #include <string> #include "net_utils_base.h" -#include "to_nonconst_iterator.h" #include "http_auth.h" #include "http_base.h" @@ -56,6 +55,7 @@ namespace net_utils std::string m_folder; std::vector<std::string> m_access_control_origins; boost::optional<login> m_user; + size_t m_max_content_length{std::numeric_limits<size_t>::max()}; critical_section m_lock; }; @@ -142,6 +142,7 @@ namespace net_utils config_type& m_config; bool m_want_close; size_t m_newlines; + size_t m_bytes_read; protected: i_service_endpoint* m_psnd_hndlr; t_connection_context& m_conn_context; diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl index 0f4a28c99..f7d2074b2 100644 --- a/contrib/epee/include/net/http_protocol_handler.inl +++ b/contrib/epee/include/net/http_protocol_handler.inl @@ -206,6 +206,7 @@ namespace net_utils m_config(config), m_want_close(false), m_newlines(0), + m_bytes_read(0), m_psnd_hndlr(psnd_hndlr), m_conn_context(conn_context) { @@ -221,6 +222,7 @@ namespace net_utils m_query_info.clear(); m_len_summary = 0; m_newlines = 0; + m_bytes_read = 0; return true; } //-------------------------------------------------------------------------------------------- @@ -243,6 +245,14 @@ namespace net_utils size_t ndel; + m_bytes_read += buf.size(); + if (m_bytes_read > m_config.m_max_content_length) + { + LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too much data: got " << m_bytes_read); + m_state = http_state_error; + return false; + } + if(m_cache.size()) m_cache += buf; else @@ -376,7 +386,7 @@ namespace net_utils m_query_info.m_http_method_str = result[2]; m_query_info.m_full_request_str = result[0]; - m_cache.erase(m_cache.begin(), to_nonsonst_iterator(m_cache, result[0].second)); + m_cache.erase(m_cache.begin(), result[0].second); m_state = http_state_retriving_header; diff --git a/contrib/epee/include/net/http_server_cp.h b/contrib/epee/include/net/http_server_cp.h deleted file mode 100644 index 1ac2223c7..000000000 --- a/contrib/epee/include/net/http_server_cp.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server_cp.h" -#include "http_server.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ -namespace net_utils -{ - typedef cp_server_impl<http::simple_http_connection_handler> cp_http_server_file_system; - typedef cp_server_impl<http::http_custom_handler> cp_http_server_custum_handling; -} -} - - - -#endif - - diff --git a/contrib/epee/include/net/http_server_cp2.h b/contrib/epee/include/net/http_server_cp2.h deleted file mode 100644 index 8dfd43a16..000000000 --- a/contrib/epee/include/net/http_server_cp2.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP2_H_ -#define _HTTP_SERVER_CP2_H_ - -#include "abstract_tcp_server2.h" -#include "http_protocol_handler.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ -namespace net_utils -{ - typedef boosted_tcp_server<http::simple_http_connection_handler<> > boosted_http_server_file_system; - typedef boosted_tcp_server<http::http_custom_handler<> > boosted_http_server_custum_handling; -} -} - - -#endif - - diff --git a/contrib/epee/include/net/http_server_thread_per_connect.h b/contrib/epee/include/net/http_server_thread_per_connect.h deleted file mode 100644 index bec43b726..000000000 --- a/contrib/epee/include/net/http_server_thread_per_connect.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server.h" -#include "http_server.h" - -namespace epee -{ -namespace net_utils -{ - typedef abstract_tcp_server<http::simple_http_connection_handler> mt_http_server_file_system; - typedef abstract_tcp_server<http::http_custom_handler> mt_http_server_custum_handling; - -} -} - - -#endif - - diff --git a/contrib/epee/include/net/jsonrpc_protocol_handler.h b/contrib/epee/include/net/jsonrpc_protocol_handler.h deleted file mode 100644 index b224c3429..000000000 --- a/contrib/epee/include/net/jsonrpc_protocol_handler.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef JSONRPC_PROTOCOL_HANDLER_H -#define JSONRPC_PROTOCOL_HANDLER_H - -#include <cstdint> -#include <string> - -#include "net/net_utils_base.h" -#include "jsonrpc_structs.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_template_helper.h" - -namespace epee -{ -namespace net_utils -{ - namespace jsonrpc2 - { - inline - std::string& make_error_resp_json(int64_t code, const std::string& message, - std::string& response_data, - const epee::serialization::storage_entry& id = nullptr) - { - epee::json_rpc::error_response rsp; - rsp.id = id; - rsp.jsonrpc = "2.0"; - rsp.error.code = code; - rsp.error.message = message; - epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_data, 0, false); - response_data += "\n"; - return response_data; - } - - template<class t_connection_context> - struct i_jsonrpc2_server_handler - { - virtual ~i_jsonrpc2_server_handler() - {} - virtual bool handle_rpc_request(const std::string& req_data, - std::string& resp_data, - t_connection_context& conn_context) = 0; - virtual bool init_server_thread() - { return true; } - virtual bool deinit_server_thread() - { return true; } - }; - - template<class t_connection_context> - struct jsonrpc2_server_config - { - i_jsonrpc2_server_handler<t_connection_context>* m_phandler; - critical_section m_lock; - }; - - template<class t_connection_context = net_utils::connection_context_base> - class jsonrpc2_connection_handler - { - public: - typedef t_connection_context connection_context; - typedef jsonrpc2_server_config<t_connection_context> config_type; - - jsonrpc2_connection_handler(i_service_endpoint* psnd_hndlr, - config_type& config, - t_connection_context& conn_context) - : m_psnd_hndlr(psnd_hndlr), - m_config(config), - m_conn_context(conn_context), - m_is_stop_handling(false) - {} - virtual ~jsonrpc2_connection_handler() - {} - - bool release_protocol() - { - return true; - } - virtual bool thread_init() - { - return true; - } - virtual bool thread_deinit() - { - return true; - } - void handle_qued_callback() - {} - bool after_init_connection() - { - return true; - } - virtual bool handle_recv(const void* ptr, size_t cb) - { - std::string buf((const char*)ptr, cb); - LOG_PRINT_L0("JSONRPC2_RECV: " << ptr << "\r\n" << buf); - - bool res = handle_buff_in(buf); - return res; - } - private: - bool handle_buff_in(std::string& buf) - { - if(m_cache.size()) - m_cache += buf; - else - m_cache.swap(buf); - - m_is_stop_handling = false; - while (!m_is_stop_handling) { - std::string::size_type pos = match_end_of_request(m_cache); - if (std::string::npos == pos) { - m_is_stop_handling = true; - if (m_cache.size() > 4096) { - LOG_ERROR("jsonrpc2_connection_handler::handle_buff_in: Too long request"); - return false; - } - break; - } else { - extract_cached_request_and_handle(pos); - } - - if (!m_cache.size()) { - m_is_stop_handling = true; - } - } - - return true; - } - bool extract_cached_request_and_handle(std::string::size_type pos) - { - std::string request_data(m_cache.begin(), m_cache.begin() + pos); - m_cache.erase(0, pos); - return handle_request_and_send_response(request_data); - } - bool handle_request_and_send_response(const std::string& request_data) - { - CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!"); - std::string response_data; - - LOG_PRINT_L3("JSONRPC2_REQUEST: >> \r\n" << request_data); - bool rpc_result = m_config.m_phandler->handle_rpc_request(request_data, response_data, m_conn_context); - LOG_PRINT_L3("JSONRPC2_RESPONSE: << \r\n" << response_data); - - m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size()); - return rpc_result; - } - std::string::size_type match_end_of_request(const std::string& buf) - { - std::string::size_type res = buf.find("\n"); - if(std::string::npos != res) { - return res + 2; - } - return res; - } - - protected: - i_service_endpoint* m_psnd_hndlr; - - private: - config_type& m_config; - t_connection_context& m_conn_context; - std::string m_cache; - bool m_is_stop_handling; - }; - } -} -} - -#endif /* JSONRPC_PROTOCOL_HANDLER_H */ diff --git a/contrib/epee/include/net/jsonrpc_server_handlers_map.h b/contrib/epee/include/net/jsonrpc_server_handlers_map.h deleted file mode 100644 index 8c747d1af..000000000 --- a/contrib/epee/include/net/jsonrpc_server_handlers_map.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef JSONRPC_SERVER_HANDLERS_MAP_H -#define JSONRPC_SERVER_HANDLERS_MAP_H - -#include <string> -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_template_helper.h" -#include "storages/portable_storage_base.h" -#include "jsonrpc_structs.h" -#include "jsonrpc_protocol_handler.h" - -#define BEGIN_JSONRPC2_MAP(t_connection_context) \ -bool handle_rpc_request(const std::string& req_data, \ - std::string& resp_data, \ - t_connection_context& m_conn_context) \ -{ \ - bool handled = false; \ - uint64_t ticks = epee::misc_utils::get_tick_count(); \ - epee::serialization::portable_storage ps; \ - if (!ps.load_from_json(req_data)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32700, "Parse error", resp_data); \ - return true; \ - } \ - epee::serialization::storage_entry id_; \ - id_ = epee::serialization::storage_entry(std::string()); \ - if (!ps.get_value("id", id_, nullptr)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data); \ - return true; \ - } \ - std::string callback_name; \ - if (!ps.get_value("method", callback_name, nullptr)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data, id_); \ - return true; \ - } \ - if (false) return true; //just a stub to have "else if" - - - -#define PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \ - handled = true; \ - boost::value_initialized<epee::json_rpc::request<command_type::request> > req_; \ - epee::json_rpc::request<command_type::request>& req = static_cast<epee::json_rpc::request<command_type::request>&>(req_);\ - if(!req.load(ps)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32602, "Invalid params", resp_data, req.id); \ - return true; \ - } \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> > resp_; \ - epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error>& resp = static_cast<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> &>(resp_); \ - resp.jsonrpc = "2.0"; \ - resp.id = req.id; - -#define FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_json(resp, resp_data, 0, false); \ - resp_data += "\n"; \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - LOG_PRINT("[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); - - -#define MAP_JSONRPC2_WE(method_name, callback_f, command_type) \ - else if (callback_name == method_name) \ - { \ - PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context)) \ - { \ - epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), resp_data, 0, false); \ - resp_data += "\n"; \ - return true; \ - } \ - FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \ - return true; \ - } - -#define END_JSONRPC2_MAP() \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32601, "Method not found", resp_data, id_); \ - return true; \ -} - -#endif /* JSONRPC_SERVER_HANDLERS_MAP_H */ diff --git a/contrib/epee/include/net/jsonrpc_server_impl_base.h b/contrib/epee/include/net/jsonrpc_server_impl_base.h deleted file mode 100644 index 8a5a9a5b6..000000000 --- a/contrib/epee/include/net/jsonrpc_server_impl_base.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef JSONRPC_SERVER_IMPL_BASE_H -#define JSONRPC_SERVER_IMPL_BASE_H - -#include <boost/thread.hpp> -#include <boost/bind.hpp> - -#include "net/jsonrpc_protocol_handler.h" -#include "net/jsonrpc_server_handlers_map.h" -#include "net/abstract_tcp_server2.h" - -namespace epee -{ - -template<class t_child_class, class t_connection_context = epee::net_utils::connection_context_base> - class jsonrpc_server_impl_base: public net_utils::jsonrpc2::i_jsonrpc2_server_handler<t_connection_context> - { - - public: - jsonrpc_server_impl_base() - : m_net_server() - {} - - explicit jsonrpc_server_impl_base(boost::asio::io_service& external_io_service) - : m_net_server(external_io_service) - {} - - bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0") - { - //set self as callback handler - m_net_server.get_config_object().m_phandler = static_cast<t_child_class*>(this); - - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - bool res = m_net_server.init_server(bind_port, bind_ip); - if (!res) - { - LOG_ERROR("Failed to bind server"); - return false; - } - return true; - } - - bool run(size_t threads_count, bool wait = true) - { - //go to loop - LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(threads_count, wait)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - if(wait) - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool deinit() - { - return m_net_server.deinit_server(); - } - - bool timed_wait_server_stop(uint64_t ms) - { - return m_net_server.timed_wait_server_stop(ms); - } - - bool send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - - int get_binded_port() - { - return m_net_server.get_binded_port(); - } - - protected: - net_utils::boosted_tcp_server<net_utils::jsonrpc2::jsonrpc2_connection_handler<t_connection_context> > m_net_server; - }; - -} - -#endif /* JSONRPC_SERVER_IMPL_BASE_H */ - diff --git a/contrib/epee/include/net/levin_client.h b/contrib/epee/include/net/levin_client.h deleted file mode 100644 index 76d528234..000000000 --- a/contrib/epee/include/net/levin_client.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - - -#ifndef _LEVIN_CLIENT_H_ -#define _LEVIN_CLIENT_H_ - -#include "net_helper.h" -#include "levin_base.h" - - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - -namespace epee -{ -namespace levin -{ - /************************************************************************/ - /* */ - /************************************************************************/ - class levin_client_impl - { - public: - levin_client_impl(); - virtual ~levin_client_impl(); - - bool connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0"); - bool connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0"); - bool is_connected(); - bool disconnect(); - - virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out); - virtual int notify(int command, const std::string& in_buff); - - protected: - net_utils::blocked_mode_client m_transport; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - class levin_client_impl2: public levin_client_impl - { - public: - - int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out); - int notify(int command, const std::string& in_buff); - }; - -} -namespace net_utils -{ - typedef levin::levin_client_impl levin_client; - typedef levin::levin_client_impl2 levin_client2; -} -} - -#include "levin_client.inl" - -#endif //_LEVIN_CLIENT_H_ diff --git a/contrib/epee/include/net/levin_client.inl b/contrib/epee/include/net/levin_client.inl deleted file mode 100644 index 177dd8967..000000000 --- a/contrib/epee/include/net/levin_client.inl +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -#include "string_tools.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace levin -{ -inline -bool levin_client_impl::connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip) -{ - return m_transport.connect(string_tools::get_ip_string_from_int32(ip), port, timeout, timeout, bind_ip); -} -//------------------------------------------------------------------------------ -inline - bool levin_client_impl::connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip) -{ - return m_transport.connect(addr, port, timeout, timeout, bind_ip); -} -//------------------------------------------------------------------------------ -inline -bool levin_client_impl::is_connected() -{ - return m_transport.is_connected(); -} -//------------------------------------------------------------------------------ -inline -bool levin_client_impl::disconnect() -{ - return m_transport.disconnect(); -} -//------------------------------------------------------------------------------ -inline -levin_client_impl::levin_client_impl() -{ -} -//------------------------------------------------------------------------------ -inline -levin_client_impl::~levin_client_impl() -{ - disconnect(); -} -//------------------------------------------------------------------------------ -inline -int levin_client_impl::invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head head = {0}; - head.m_signature = SWAP64LE(LEVIN_SIGNATURE); - head.m_cb = SWAP64LE(in_buff.size()); - head.m_have_to_return_data = 1; - head.m_command = SWAP32LE(command); - if(!m_transport.send(&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - std::string local_buff; - if(!m_transport.recv_n(local_buff, sizeof(bucket_head))) - return -1; - - head = *(bucket_head*)local_buff.data(); - - - if(head.m_signature!=SWAP64LE(LEVIN_SIGNATURE)) - { - LOG_PRINT_L1("Signature mismatch in response"); - return -1; - } - - if(!m_transport.recv_n(buff_out, head.m_cb)) - return -1; - - return head.m_return_code; -} -//------------------------------------------------------------------------------ -inline -int levin_client_impl::notify(int command, const std::string& in_buff) -{ - if(!is_connected()) - return -1; - - bucket_head head = {0}; - head.m_signature = SWAP64LE(LEVIN_SIGNATURE); - head.m_cb = SWAP64LE(in_buff.size()); - head.m_have_to_return_data = 0; - head.m_command = SWAP32LE(command); - - if(!m_transport.send((const char*)&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - return 1; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -inline - int levin_client_impl2::invoke(int command, epee::span<const uint8_t>string& in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head2 head = {0}; - head.m_signature = SWAP64LE(LEVIN_SIGNATURE); - head.m_cb = SWAP64LE(in_buff.size()); - head.m_have_to_return_data = 1; - head.m_command = SWAP32LE(command); - head.m_return_code = SWAP32LE(0); - head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); - head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); - if(!m_transport.send(&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - std::string local_buff; - if(!m_transport.recv_n(local_buff, sizeof(bucket_head2))) - return -1; - - head = *(bucket_head2*)local_buff.data(); - - if(head.m_signature != SWAP64LE(LEVIN_SIGNATURE)) - { - LOG_PRINT_L1("Signature mismatch in response"); - return -1; - } - - if(!m_transport.recv_n(buff_out, SWAP64LE(head.m_cb))) - return -1; - - return head.m_return_code; -} -//------------------------------------------------------------------------------ -inline - int levin_client_impl2::notify(int command, const std::string& in_buff) -{ - if(!is_connected()) - return -1; - - bucket_head2 head = {0}; - head.m_signature = SWAP64LE(LEVIN_SIGNATURE); - head.m_cb = SWAP64LE(in_buff.size()); - head.m_have_to_return_data = 0; - head.m_command = SWAP32LE(command); - head.m_return_code = SWAP32LE(0); - head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); - head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); - - if(!m_transport.send((const char*)&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - return 1; -} - -} -} -//------------------------------------------------------------------------------ diff --git a/contrib/epee/include/net/levin_client_async.h b/contrib/epee/include/net/levin_client_async.h deleted file mode 100644 index 067707edf..000000000 --- a/contrib/epee/include/net/levin_client_async.h +++ /dev/null @@ -1,585 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "" -#include "net_helper.h" -#include "levin_base.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - - -namespace epee -{ -namespace levin -{ - - /************************************************************************ - * levin_client_async - probably it is not really fast implementation, - * each handler thread could make up to 30 ms latency. - * But, handling events in reader thread will cause dead locks in - * case of recursive call (call invoke() to the same connection - * on reader thread on remote invoke() handler) - ***********************************************************************/ - - - class levin_client_async - { - levin_commands_handler* m_pcommands_handler; - void (*commands_handler_destroy)(levin_commands_handler*); - volatile uint32_t m_is_stop; - volatile uint32_t m_threads_count; - ::critical_section m_send_lock; - - std::string m_local_invoke_buff; - ::critical_section m_local_invoke_buff_lock; - volatile int m_invoke_res; - - volatile uint32_t m_invoke_data_ready; - volatile uint32_t m_invoke_is_active; - - boost::mutex m_invoke_event; - boost::condition_variable m_invoke_cond; - size_t m_timeout; - - ::critical_section m_recieved_packets_lock; - struct packet_entry - { - bucket_head m_hd; - std::string m_body; - uint32_t m_connection_index; - }; - std::list<packet_entry> m_recieved_packets; - /* - m_current_connection_index needed when some connection was broken and reconnected - in this - case we could have some received packets in que, which shoud not be handled - */ - volatile uint32_t m_current_connection_index; - ::critical_section m_invoke_lock; - ::critical_section m_reciev_packet_lock; - ::critical_section m_connection_lock; - net_utils::blocked_mode_client m_transport; - public: - levin_client_async():m_pcommands_handler(NULL), commands_handler_destroy(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0) - {} - levin_client_async(const levin_client_async& /*v*/):m_pcommands_handler(NULL), commands_handler_destroy(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0) - {} - ~levin_client_async() - { - boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1); - disconnect(); - - - while(boost::interprocess::ipcdetail::atomic_read32(&m_threads_count)) - ::Sleep(100); - - set_handler(NULL); - } - - void set_handler(levin_commands_handler* phandler, void (*destroy)(levin_commands_handler*) = NULL) - { - if (commands_handler_destroy && m_pcommands_handler) - (*commands_handler_destroy)(m_pcommands_handler); - m_pcommands_handler = phandler; - m_pcommands_handler_destroy = destroy; - } - - bool connect(uint32_t ip, uint32_t port, uint32_t timeout) - { - loop_call_guard(); - critical_region cr(m_connection_lock); - - m_timeout = timeout; - bool res = false; - CRITICAL_REGION_BEGIN(m_reciev_packet_lock); - CRITICAL_REGION_BEGIN(m_send_lock); - res = levin_client_impl::connect(ip, port, timeout); - boost::interprocess::ipcdetail::atomic_inc32(&m_current_connection_index); - CRITICAL_REGION_END(); - CRITICAL_REGION_END(); - if(res && !boost::interprocess::ipcdetail::atomic_read32(&m_threads_count) ) - { - //boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 0);//m_is_stop = false; - boost::thread( boost::bind(&levin_duplex_client::reciever_thread, this) ); - boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) ); - boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) ); - } - - return res; - } - bool is_connected() - { - loop_call_guard(); - critical_region cr(m_cs); - return levin_client_impl::is_connected(); - } - - inline - bool check_connection() - { - loop_call_guard(); - critical_region cr(m_cs); - - if(!is_connected()) - { - if( !reconnect() ) - { - LOG_ERROR("Reconnect Failed. Failed to invoke() because not connected!"); - return false; - } - } - return true; - } - - //------------------------------------------------------------------------------ - inline - bool recv_n(SOCKET s, char* pbuff, size_t cb) - { - while(cb) - { - int res = ::recv(m_socket, pbuff, (int)cb, 0); - - if(SOCKET_ERROR == res) - { - if(!m_connected) - return false; - - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to recv(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - //reconnect(); - return false; - }else if(res == 0) - { - disconnect(); - //reconnect(); - return false; - } - LOG_PRINT_L4("[" << m_socket <<"] RECV " << res); - cb -= res; - pbuff += res; - } - - return true; - } - - //------------------------------------------------------------------------------ - inline - bool recv_n(SOCKET s, std::string& buff) - { - size_t cb_remain = buff.size(); - char* m_current_ptr = (char*)buff.data(); - return recv_n(s, m_current_ptr, cb_remain); - } - - bool disconnect() - { - //boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1);//m_is_stop = true; - loop_call_guard(); - critical_region cr(m_cs); - levin_client_impl::disconnect(); - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - m_local_invoke_buff.clear(); - m_invoke_res = LEVIN_ERROR_CONNECTION_DESTROYED; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true; - m_invoke_cond.notify_all(); - return true; - } - - void loop_call_guard() - { - - } - - void on_leave_invoke() - { - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 0); - } - - int invoke(const GUID& target, int command, const std::string& in_buff, std::string& buff_out) - { - - critical_region cr_invoke(m_invoke_lock); - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 1); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 0); - misc_utils::destr_ptr hdlr = misc_utils::add_exit_scope_handler(boost::bind(&levin_duplex_client::on_leave_invoke, this)); - - loop_call_guard(); - - if(!check_connection()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = 1; - head.m_id = target; -#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS - ::UuidCreate(&head.m_id); -#endif - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - LOG_PRINT("[" << m_socket <<"] Sending invoke data", LOG_LEVEL_4); - - CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head)); - int res = ::send(m_socket, (const char*)&head, sizeof(head), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size()); - res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - //hard coded timeout in 10 minutes for maximum invoke period. if it happens, it could mean only some real troubles. - boost::system_time timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100); - size_t timeout_count = 0; - boost::unique_lock<boost::mutex> lock(m_invoke_event); - - while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_data_ready)) - { - if(!m_invoke_cond.timed_wait(lock, timeout)) - { - if(timeout_count < 10) - { - //workaround to avoid freezing at timed_wait called after notify_all. - timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100); - ++timeout_count; - continue; - }else if(timeout_count == 10) - { - //workaround to avoid freezing at timed_wait called after notify_all. - timeout = boost::get_system_time()+ boost::posix_time::minutes(10); - ++timeout_count; - continue; - }else - { - LOG_PRINT("[" << m_socket <<"] Timeout on waiting invoke result. ", LOG_LEVEL_0); - //disconnect(); - return LEVIN_ERROR_CONNECTION_TIMEDOUT; - } - } - } - - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - buff_out.swap(m_local_invoke_buff); - m_local_invoke_buff.clear(); - CRITICAL_REGION_END(); - return m_invoke_res; - } - - int notify(const GUID& target, int command, const std::string& in_buff) - { - if(!check_connection()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = 0; - head.m_id = target; -#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS - ::UuidCreate(&head.m_id); -#endif - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head)); - int res = ::send(m_socket, (const char*)&head, sizeof(head), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size()); - res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - return 1; - } - - - private: - bool have_some_data(SOCKET sock, int interval = 1) - { - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - fd_set fdse; - FD_ZERO(&fdse); - FD_SET(sock, &fdse); - - - timeval tv; - tv.tv_sec = interval; - tv.tv_usec = 0; - - int sel_res = select(0, &fds, 0, &fdse, &tv); - if(0 == sel_res) - return false; - else if(sel_res == SOCKET_ERROR) - { - if(m_is_stop) - return false; - int err_code = ::WSAGetLastError(); - LOG_ERROR("Filed to call select, err code = " << err_code); - disconnect(); - }else - { - if(fds.fd_array[0]) - {//some read operations was performed - return true; - }else if(fdse.fd_array[0]) - {//some error was at the socket - return true; - } - } - return false; - } - - - bool reciev_and_process_incoming_data() - { - bucket_head head = {0}; - uint32_t conn_index = 0; - bool is_request = false; - std::string local_buff; - CRITICAL_REGION_BEGIN(m_reciev_packet_lock);//to protect from socket reconnect between head and body - - if(!recv_n(m_socket, (char*)&head, sizeof(head))) - { - if(m_is_stop) - return false; - LOG_ERROR("Failed to recv_n"); - return false; - } - - conn_index = boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index); - - if(head.m_signature!=LEVIN_SIGNATURE) - { - LOG_ERROR("Signature mismatch in response"); - return false; - } - - is_request = (head.m_protocol_version == LEVIN_PROTOCOL_VER_1 && head.m_flags&LEVIN_PACKET_REQUEST); - - - local_buff.resize((size_t)head.m_cb); - if(!recv_n(m_socket, local_buff)) - { - if(m_is_stop) - return false; - LOG_ERROR("Filed to reciev"); - return false; - } - CRITICAL_REGION_END(); - - LOG_PRINT_L4("LEVIN_PACKET_RECEIVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - if(is_request) - { - CRITICAL_REGION_BEGIN(m_recieved_packets_lock); - m_recieved_packets.resize(m_recieved_packets.size() + 1); - m_recieved_packets.back().m_hd = head; - m_recieved_packets.back().m_body.swap(local_buff); - m_recieved_packets.back().m_connection_index = conn_index; - CRITICAL_REGION_END(); - /* - - */ - }else - {//this is some response - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - m_local_invoke_buff.swap(local_buff); - m_invoke_res = head.m_return_code; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true; - m_invoke_cond.notify_all(); - - } - return true; - } - - bool reciever_thread() - { - LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread started.[m_threads_count=" << m_threads_count << "]"); - log_space::log_singletone::set_thread_log_prefix("RECIEVER_WORKER"); - boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); - - while(!m_is_stop) - { - if(!m_connected) - { - Sleep(100); - continue; - } - - if(have_some_data(m_socket, 1)) - { - if(!reciev_and_process_incoming_data()) - { - if(m_is_stop) - { - break;//boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - //return true; - } - LOG_ERROR("Failed to reciev_and_process_incoming_data. shutting down"); - //boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - //disconnect_no_wait(); - //break; - } - } - } - - boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread stopped.[m_threads_count=" << m_threads_count << "]"); - return true; - } - - bool process_recieved_packet(bucket_head& head, const std::string& local_buff, uint32_t conn_index) - { - - net_utils::connection_context_base conn_context; - conn_context.m_remote_address = m_address; - if(head.m_have_to_return_data) - { - std::string return_buff; - if(m_pcommands_handler) - head.m_return_code = m_pcommands_handler->invoke(head.m_id, head.m_command, local_buff, return_buff, conn_context); - else - head.m_return_code = LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; - - - - head.m_cb = return_buff.size(); - head.m_have_to_return_data = 0; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_RESPONSE; - - std::string send_buff((const char*)&head, sizeof(head)); - send_buff += return_buff; - CRITICAL_REGION_BEGIN(m_send_lock); - if(conn_index != boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index)) - {//there was reconnect, send response back is not allowed - return true; - } - int res = ::send(m_socket, (const char*)send_buff.data(), send_buff.size(), 0); - if(res == SOCKET_ERROR) - { - int err_code = ::WSAGetLastError(); - LOG_ERROR("Failed to send, err = " << err_code); - return false; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - } - else - { - if(m_pcommands_handler) - m_pcommands_handler->notify(head.m_id, head.m_command, local_buff, conn_context); - } - - return true; - } - - bool handler_thread() - { - LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread started.[m_threads_count=" << m_threads_count << "]"); - log_space::log_singletone::set_thread_log_prefix("HANDLER_WORKER"); - boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); - - while(!m_is_stop) - { - bool have_some_work = false; - std::string local_buff; - bucket_head bh = {0}; - uint32_t conn_index = 0; - - CRITICAL_REGION_BEGIN(m_recieved_packets_lock); - if(m_recieved_packets.size()) - { - bh = m_recieved_packets.begin()->m_hd; - conn_index = m_recieved_packets.begin()->m_connection_index; - local_buff.swap(m_recieved_packets.begin()->m_body); - have_some_work = true; - m_recieved_packets.pop_front(); - } - CRITICAL_REGION_END(); - - if(have_some_work) - { - process_recieved_packet(bh, local_buff, conn_index); - }else - { - //Idle when no work - Sleep(30); - } - } - - boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread stopped.[m_threads_count=" << m_threads_count << "]"); - return true; - } - }; - -} -} diff --git a/contrib/epee/include/net/levin_client_async.inl b/contrib/epee/include/net/levin_client_async.inl deleted file mode 100644 index e69de29bb..000000000 --- a/contrib/epee/include/net/levin_client_async.inl +++ /dev/null diff --git a/contrib/epee/include/net/levin_helper.h b/contrib/epee/include/net/levin_helper.h deleted file mode 100644 index 541e0948d..000000000 --- a/contrib/epee/include/net/levin_helper.h +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "levin_base.h" -#include "serializeble_struct_helper.h" -#include "int-util.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace levin -{ - template<class t_struct> - bool pack_struct_to_levin_message(const t_struct& t, std::string& buff, int command_id) - { - buff.resize(sizeof(levin::bucket_head)); - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = SWAP64LE(LEVIN_SIGNATURE); - head.m_cb = 0; - head.m_have_to_return_data = 1; - head.m_command = SWAP32LE(command_id); - head.m_return_code = SWAP32LE(1); - head.m_reservedA = rand(); //probably some flags in future - head.m_reservedB = rand(); //probably some check summ in future - - std::string buff_strg; - if(!StorageNamed::save_struct_as_storage_to_buff_t<t_struct, StorageNamed::DefaultStorageType>(t, buff_strg)) - return false; - - head.m_cb = SWAP64LE(buff_strg.size()); - buff.append(buff_strg); - return true; - } - - - bool pack_data_to_levin_message(const std::string& data, std::string& buff, int command_id) - { - buff.resize(sizeof(levin::bucket_head)); - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = SWAP64LE(LEVIN_SIGNATURE); - head.m_cb = 0; - head.m_have_to_return_data = 1; - head.m_command = SWAP32LE(command_id); - head.m_return_code = SWAP32LE(1); - head.m_reservedA = rand(); //probably some flags in future - head.m_reservedB = rand(); //probably some check summ in future - - head.m_cb = SWAP64LE(data.size()); - buff.append(data); - return true; - } - - bool load_levin_data_from_levin_message(std::string& levin_data, const std::string& buff, int& command) - { - if(buff.size() < sizeof(levin::bucket_head) ) - { - LOG_PRINT_L3("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); - return false; - } - -#if BYTE_ORDER == LITTLE_ENDIAN - levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]); -#else - levin::bucket_head head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = SWAP64LE(head.m_signature); - head.m_cb = SWAP64LE(head.m_cb); - head.m_command = SWAP32LE(head.m_command); - head.m_return_code = SWAP32LE(head.m_return_code); - head.m_reservedA = SWAP32LE(head.m_reservedA); - head.m_reservedB = SWAP32LE(head.m_reservedB); -#endif - if(head.m_signature != LEVIN_SIGNATURE) - { - LOG_PRINT_L3("Failed to read signature in levin message, at load_struct_from_levin_message"); - return false; - } - if(head.m_cb != buff.size()-sizeof(levin::bucket_head)) - { - LOG_PRINT_L3("sizes mismatch, at load_struct_from_levin_message"); - return false; - } - - //std::string buff_strg; - levin_data.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head)); - command = head.m_command; - return true; - } - - template<class t_struct> - bool load_struct_from_levin_message(t_struct& t, const std::string& buff, int& command) - { - if(buff.size() < sizeof(levin::bucket_head) ) - { - LOG_ERROR("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); - return false; - } - -#if BYTE_ORDER == LITTLE_ENDIAN - levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]); -#else - levin::bucket_head head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = SWAP64LE(head.m_signature); - head.m_cb = SWAP64LE(head.m_cb); - head.m_command = SWAP32LE(head.m_command); - head.m_return_code = SWAP32LE(head.m_return_code); - head.m_reservedA = SWAP32LE(head.m_reservedA); - head.m_reservedB = SWAP32LE(head.m_reservedB); -#endif - if(head.m_signature != LEVIN_SIGNATURE) - { - LOG_ERROR("Failed to read signature in levin message, at load_struct_from_levin_message"); - return false; - } - if(head.m_cb != buff.size()-sizeof(levin::bucket_head)) - { - LOG_ERROR("sizes mismatch, at load_struct_from_levin_message"); - return false; - } - - std::string buff_strg; - buff_strg.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head)); - - if(!StorageNamed::load_struct_from_storage_buff_t<t_struct, StorageNamed::DefaultStorageType>(t, buff_strg)) - { - LOG_ERROR("Failed to read storage, at load_struct_from_levin_message"); - return false; - } - command = head.m_command; - return true; - } -} -} diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index a6816cafc..bd6ffe930 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -28,7 +28,6 @@ #include <boost/asio/deadline_timer.hpp> #include <boost/uuid/uuid_generators.hpp> #include <boost/unordered_map.hpp> -#include <boost/interprocess/detail/atomic.hpp> #include <boost/smart_ptr/make_shared.hpp> #include <atomic> @@ -38,7 +37,7 @@ #include "buffer.h" #include "misc_language.h" #include "syncobj.h" -#include "misc_os_dependent.h" +#include "time_helper.h" #include "int-util.h" #include <random> @@ -166,7 +165,7 @@ public: }; std::atomic<bool> m_protocol_released; - volatile uint32_t m_invoke_buf_ready; + std::atomic<bool> m_invoke_buf_ready; volatile int m_invoke_result_code; @@ -175,8 +174,8 @@ public: critical_section m_call_lock; - volatile uint32_t m_wait_count; - volatile uint32_t m_close_called; + std::atomic<uint32_t> m_wait_count; + std::atomic<uint32_t> m_close_called; bucket_head2 m_current_head; net_utils::i_service_endpoint* m_pservice_endpoint; config_type& m_config; @@ -319,7 +318,7 @@ public: m_wait_count = 0; m_oponent_protocol_ver = 0; m_connection_initialized = false; - m_invoke_buf_ready = 0; + m_invoke_buf_ready = false; m_invoke_result_code = LEVIN_ERROR_CONNECTION; } virtual ~async_protocol_handler() @@ -332,11 +331,11 @@ public: m_config.del_connection(this); } - for (size_t i = 0; i < 60 * 1000 / 100 && 0 != boost::interprocess::ipcdetail::atomic_read32(&m_wait_count); ++i) + for (size_t i = 0; i < 60 * 1000 / 100 && 0 != m_wait_count; ++i) { misc_utils::sleep_no_w(100); } - CHECK_AND_ASSERT_MES_NO_RET(0 == boost::interprocess::ipcdetail::atomic_read32(&m_wait_count), "Failed to wait for operation completion. m_wait_count = " << m_wait_count); + CHECK_AND_ASSERT_MES_NO_RET(0 == m_wait_count, "Failed to wait for operation completion. m_wait_count = " << m_wait_count.load()); MTRACE(m_connection_context << "~async_protocol_handler()"); @@ -352,13 +351,13 @@ public: MERROR(m_connection_context << "[levin_protocol] -->> start_outer_call failed"); return false; } - boost::interprocess::ipcdetail::atomic_inc32(&m_wait_count); + ++m_wait_count; return true; } bool finish_outer_call() { MTRACE(m_connection_context << "[levin_protocol] <<-- finish_outer_call"); - boost::interprocess::ipcdetail::atomic_dec32(&m_wait_count); + --m_wait_count; m_pservice_endpoint->release(); return true; } @@ -382,7 +381,7 @@ public: bool close() { - boost::interprocess::ipcdetail::atomic_inc32(&m_close_called); + ++m_close_called; m_pservice_endpoint->close(); return true; @@ -408,7 +407,7 @@ public: virtual bool handle_recv(const void* ptr, size_t cb) { - if(boost::interprocess::ipcdetail::atomic_read32(&m_close_called)) + if(m_close_called) return false; //closing connections if(!m_config.m_pcommands_handler) @@ -524,7 +523,7 @@ public: { invoke_response_handlers_guard.unlock(); //use sync call scenario - if(!boost::interprocess::ipcdetail::atomic_read32(&m_wait_count) && !boost::interprocess::ipcdetail::atomic_read32(&m_close_called)) + if(!m_wait_count && !m_close_called) { MERROR(m_connection_context << "no active invoke when response came, wtf?"); return false; @@ -535,7 +534,7 @@ public: buff_to_invoke = epee::span<const uint8_t>((const uint8_t*)NULL, 0); m_invoke_result_code = m_current_head.m_return_code; CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 1); + m_invoke_buf_ready = true; } } }else @@ -642,7 +641,7 @@ public: { CRITICAL_REGION_LOCAL(m_call_lock); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); + m_invoke_buf_ready = false; CRITICAL_REGION_BEGIN(m_invoke_response_handlers_lock); if (command == m_connection_context.handshake_command()) @@ -681,7 +680,7 @@ public: CRITICAL_REGION_LOCAL(m_call_lock); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); + m_invoke_buf_ready = false; if (command == m_connection_context.handshake_command()) m_max_packet_size = m_config.m_max_packet_size; @@ -695,7 +694,7 @@ public: uint64_t ticks_start = misc_utils::get_tick_count(); size_t prev_size = 0; - while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_buf_ready) && !m_protocol_released) + while(!m_invoke_buf_ready && !m_protocol_released) { if(m_cache_in_buffer.size() - prev_size >= MIN_BYTES_WANTED) { diff --git a/contrib/epee/include/net/levin_server_cp.h b/contrib/epee/include/net/levin_server_cp.h deleted file mode 100644 index 8ece35059..000000000 --- a/contrib/epee/include/net/levin_server_cp.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server_cp.h" -#include "levin_protocol_handler.h" -namespace epee -{ -namespace net_utils -{ - typedef cp_server_impl<levin::protocol_handler> cp_levin_server; -} -} - - - -#endif - - diff --git a/contrib/epee/include/net/levin_server_cp2.h b/contrib/epee/include/net/levin_server_cp2.h deleted file mode 100644 index b29d49bf8..000000000 --- a/contrib/epee/include/net/levin_server_cp2.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server2.h" -#include "levin_protocol_handler.h" -#include "levin_protocol_handler_async.h" - -namespace epee -{ -namespace net_utils -{ - typedef boosted_tcp_server<levin::protocol_handler<> > boosted_levin_server; - typedef boosted_tcp_server<levin::async_protocol_handler<> > boosted_levin_async_server; -} -} - - - -#endif - - diff --git a/contrib/epee/include/net/local_ip.h b/contrib/epee/include/net/local_ip.h index 1eeab2dc5..6dfa19e6e 100644 --- a/contrib/epee/include/net/local_ip.h +++ b/contrib/epee/include/net/local_ip.h @@ -27,7 +27,6 @@ #pragma once -#include <string> #include "int-util.h" // IP addresses are kept in network byte order @@ -44,9 +43,9 @@ namespace epee ip = SWAP32LE(ip); /* local ip area - 10.0.0.0 10.255.255.255 - 172.16.0.0 172.31.255.255 - 192.168.0.0 192.168.255.255 + 10.0.0.0 ... 10.255.255.255 + 172.16.0.0 ... 172.31.255.255 + 192.168.0.0 ... 192.168.255.255 */ if( (ip | 0xffffff00) == 0xffffff0a) return true; @@ -71,7 +70,7 @@ namespace epee //MAKE_IP /* loopback ip - 127.0.0.0 127.255.255.255 + 127.0.0.0 ... 127.255.255.255 */ return false; } diff --git a/contrib/epee/include/net/multiprotocols_server.h b/contrib/epee/include/net/multiprotocols_server.h deleted file mode 100644 index 4807a4421..000000000 --- a/contrib/epee/include/net/multiprotocols_server.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MULTIPROTOCOLS_SERVER_H_ -#define _MULTIPROTOCOLS_SERVER_H_ - -//#include "abstract_tcp_server_cp.h" -#include "protocol_switcher.h" -#include "abstract_tcp_server2.h" - -namespace epee -{ -namespace net_utils -{ - //typedef cp_server_impl<net_utils::protocol_switcher> multiprotocol_server; - typedef boosted_tcp_server<net_utils::protocol_switcher> boosted_multiprotocol_server; -} -} - - -#endif //_MULTIPROTOCOLS_SERVER_H_ - diff --git a/contrib/epee/include/net/munin_connection_handler.h b/contrib/epee/include/net/munin_connection_handler.h deleted file mode 100644 index 20dc38507..000000000 --- a/contrib/epee/include/net/munin_connection_handler.h +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MUNIN_CONNECTION_HANDLER_H_ -#define _MUNIN_CONNECTION_HANDLER_H_ - -#include <string> -#include "net_utils_base.h" -#include "to_nonconst_iterator.h" -#include "http_base.h" -#include "reg_exp_definer.h" - -#define MUNIN_ARGS_DEFAULT(vertial_lable_str) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " \n" -#define MUNIN_ARGS_FORCE_AUPPER_LIMIT(vertial_lable_str, limit) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " --rigid --upper-limit " limit " \n" -#define MUNIN_TITLE(title_str) "graph_title " title_str "\n" -#define MUNIN_CATEGORY(category_str) "graph_category " category_str "\n" -#define MUNIN_INFO(info_str) "graph_info " info_str "\n" -#define MUNIN_ENTRY(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" -#define MUNIN_ENTRY_AREA(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" #var_name".draw AREASTACK\n" -#define MUNIN_ENTRY_ALIAS(var_name, alias) #var_name".label " #alias"\n" #var_name".info "#alias".\n" -#define BEGIN_MUNIN_SERVICE(servivece_name_str) if(servivece_name_str == pservice->m_service_name) { -#define END_MUNIN_SERVICE() } -#define MUNIN_SERVICE_PARAM(munin_var_name_str, variable) paramters_text += std::string() + munin_var_name_str ".value " + boost::lexical_cast<std::string>(variable) + "\n" - - - - -namespace epee -{ -namespace net_utils -{ - namespace munin - { - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct munin_service; - - struct munin_service_data_provider - { - virtual bool update_service_data(munin_service* pservice, std::string& paramters_text)=0; - }; - - struct munin_service - { - std::string m_service_name; - std::string m_service_config_string; - munin_service_data_provider* m_pdata_provider; - }; - - struct node_server_config - { - std::list<munin_service> m_services; - //TODO: - }; - - struct fake_send_handler: public i_service_endpoint - { - virtual bool do_send(const void* ptr, size_t cb) - { - m_cache += std::string((const char*)ptr, cb); - return true; - } - public: - - std::string m_cache; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class munin_node_server_connection_handler - { - public: - typedef node_server_config config_type; - typedef connection_context_base connection_context; - - munin_node_server_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config, const connection_context_base& context):m_psnd_hndlr(psnd_hndlr), - m_machine_state(http_state_retriving_comand_line), - m_config(config) - { - init(); - } - virtual ~munin_node_server_connection_handler() - { - - } - - bool release_protocol() - { - return true; - } - bool after_init_connection() - { - std::string hello_str = "# munin node at "; - hello_str += m_host_name + "\n"; - send_hook(hello_str); - return true; - } - - virtual bool thread_init() - { - return true; - } - - virtual bool thread_deinit() - { - return true; - } - - void handle_qued_callback() - { - - } - - virtual bool handle_recv(const void* ptr, size_t cb) - { - - const char* pbuff = (const char*)ptr; - std::string recvd_buff(pbuff, cb); - LOG_PRINT("munin_recv: \n" << recvd_buff, LOG_LEVEL_3); - - m_cache += recvd_buff; - - bool stop_handling = false; - while(!stop_handling) - { - switch(m_machine_state) - { - case http_state_retriving_comand_line: - { - - std::string::size_type fpos = m_cache.find('\n'); - if(std::string::npos != fpos ) - { - bool res = handle_command(m_cache); - if(!res) - return false; - m_cache.erase(0, fpos+1); - continue; - } - stop_handling = true; - } - break; - case http_state_error: - stop_handling = true; - return false; - default: - LOG_ERROR("Error in munin state machine! Unknown state=" << m_machine_state); - stop_handling = true; - m_machine_state = http_state_error; - return false; - } - - } - - return true; - } - - private: - - - bool init() - { - char hostname[64] = {0}; - int res = gethostname(hostname, 64); - hostname[63] = 0;//be happy - m_host_name = hostname; - return true; - } - bool handle_command(const std::string& command) - { - // list, nodes, config, fetch, version or quit - STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^((list)|(nodes)|(config)|(fetch)|(version)|(quit))(\\s+(\\S+))?", boost::regex::icase | boost::regex::normal); - // 12 3 4 5 6 7 8 9 - size_t match_len = 0; - boost::smatch result; - if(boost::regex_search(command, result, rexp_match_command_line, boost::match_default) && result[0].matched) - { - if(result[2].matched) - {//list command - return handle_list_command(); - }else if(result[3].matched) - {//nodes command - return handle_nodes_command(); - }else if(result[4].matched) - {//config command - if(result[9].matched) - return handle_config_command(result[9]); - else - { - send_hook("Unknown service\n"); - } - }else if(result[5].matched) - {//fetch command - if(result[9].matched) - return handle_fetch_command(result[9]); - else - { - send_hook("Unknown service\n"); - } - }else if(result[6].matched) - {//version command - return handle_version_command(); - }else if(result[7].matched) - {//quit command - return handle_quit_command(); - } - else - return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n"); - } - - return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n"); - } - - bool handle_list_command() - { - std::string buff_to_send; - for(std::list<munin_service>::const_iterator it = m_config.m_services.begin(); it!=m_config.m_services.end();it++) - { - buff_to_send += it->m_service_name + " "; - } - buff_to_send+='\n'; - return send_hook(buff_to_send); - } - bool handle_nodes_command() - { - //supports only one node - host name - send_hook(m_host_name + "\n.\n"); - return true; - } - bool handle_config_command(const std::string& service_name) - { - munin_service* psrv = get_service_by_name(service_name); - if(!psrv) - return send_hook(std::string() + "Unknown service\n"); - - - return send_hook(psrv->m_service_config_string + ".\n"); - } - - bool handle_fetch_command(const std::string& service_name) - { - munin_service* psrv = get_service_by_name(service_name); - if(!psrv) - return send_hook(std::string() + "Unknown service\n"); - - std::string buff; - psrv->m_pdata_provider->update_service_data(psrv, buff); - - buff += ".\n"; - return send_hook(buff); - } - bool handle_version_command() - { - return send_hook("Munin node component by Andrey Sabelnikov\n"); - } - bool handle_quit_command() - { - return false; - } - - bool send_hook(const std::string& buff) - { - LOG_PRINT("munin_send: \n" << buff, LOG_LEVEL_3); - - if(m_psnd_hndlr) - return m_psnd_hndlr->do_send(buff.data(), buff.size()); - else - return false; - } - - - munin_service* get_service_by_name(const std::string& srv_name) - { - std::list<munin_service>::iterator it = m_config.m_services.begin(); - for(; it!=m_config.m_services.end(); it++) - if(it->m_service_name == srv_name) - break; - - if(it==m_config.m_services.end()) - return NULL; - - return &(*it); - } - - enum machine_state{ - http_state_retriving_comand_line, - http_state_error - }; - - - config_type& m_config; - machine_state m_machine_state; - std::string m_cache; - std::string m_host_name; - protected: - i_service_endpoint* m_psnd_hndlr; - }; - - - inline bool test_self() - { - /*WSADATA w; - ::WSAStartup(MAKEWORD(1, 1), &w); - node_server_config sc; - sc.m_services.push_back(munin_service()); - sc.m_services.back().m_service_name = "test_service"; - - sc.m_services.back().m_service_config_string = - "graph_args --base 1000 -l 0 --vertical-label N --upper-limit 329342976\n" - "graph_title REPORTS STATICTICS\n" - "graph_category bind\n" - "graph_info This graph shows how many reports came in fixed time period.\n" - "graph_order apps free swap\n" - "apps.label apps\n" - "apps.draw AREA\n" - "apps.info Memory used by user-space applications.\n" - "swap.label swap\n" - "swap.draw STACK\n" - "swap.info Swap space used.\n" - "free.label unused\n" - "free.draw STACK\n" - "free.info Wasted memory. Memory that is not used for anything at all.\n" - "committed.label committed\n" - "committed.draw LINE2\n" - "committed.warn 625410048\n" - "committed.info The amount of memory that would be used if all the memory that's been allocated were to be used.\n"; - - - sc.m_services.push_back(munin_service()); - sc.m_services.back().m_service_name = "test_service1"; - fake_send_handler fh; - munin_node_server_connection_handler mh(&fh, sc); - - std::string buff = "list\n"; - mh.handle_recv(buff.data(), buff.size()); - - - buff = "nodes\n"; - mh.handle_recv(buff.data(), buff.size()); -*/ - return true; - } - - } -} -} -#endif//!_MUNIN_CONNECTION_HANDLER_H_ diff --git a/contrib/epee/include/net/munin_node_server.h b/contrib/epee/include/net/munin_node_server.h deleted file mode 100644 index e6df390cb..000000000 --- a/contrib/epee/include/net/munin_node_server.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MUNIN_NODE_SERVER_H_ -#define _MUNIN_NODE_SERVER_H_ - -#include <string> -//#include "net_utils_base.h" -#include "munin_connection_handler.h" -//#include "abstract_tcp_server.h" -//#include "abstract_tcp_server_cp.h" -#include "abstract_tcp_server2.h" -namespace epee -{ -namespace net_utils -{ - namespace munin - { - typedef boosted_tcp_server<munin_node_server_connection_handler> munin_node_server; - //typedef cp_server_impl<munin_node_server_connection_handler> munin_node_cp_server; - } -} -} -#endif//!_MUNIN_NODE_SERVER_H_ diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index a1f44cab0..0a35797fd 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -42,7 +42,6 @@ #include <boost/thread/future.hpp> #include <boost/lambda/bind.hpp> #include <boost/lambda/lambda.hpp> -#include <boost/interprocess/detail/atomic.hpp> #include <boost/system/error_code.hpp> #include <boost/utility/string_ref.hpp> #include <functional> @@ -110,7 +109,7 @@ namespace net_utils m_initialized(true), m_connected(false), m_deadline(m_io_service, std::chrono::steady_clock::time_point::max()), - m_shutdowned(0), + m_shutdowned(false), m_bytes_sent(0), m_bytes_received(0) { @@ -435,7 +434,7 @@ namespace net_utils async_read(&buff[0], max_size, boost::asio::transfer_at_least(1), hndlr); // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) + while (ec == boost::asio::error::would_block && !m_shutdowned) { m_io_service.reset(); m_io_service.run_one(); @@ -519,7 +518,7 @@ namespace net_utils async_read((char*)buff.data(), buff.size(), boost::asio::transfer_at_least(buff.size()), hndlr); // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) + while (ec == boost::asio::error::would_block && !m_shutdowned) { m_io_service.run_one(); } @@ -576,7 +575,7 @@ namespace net_utils m_ssl_socket->next_layer().close(ec); if(ec) MDEBUG("Problems at close: " << ec.message()); - boost::interprocess::ipcdetail::atomic_write32(&m_shutdowned, 1); + m_shutdowned = true; m_connected = false; return true; } @@ -685,7 +684,7 @@ namespace net_utils bool m_initialized; bool m_connected; boost::asio::steady_timer m_deadline; - volatile uint32_t m_shutdowned; + std::atomic<bool> m_shutdowned; std::atomic<uint64_t> m_bytes_sent; std::atomic<uint64_t> m_bytes_received; }; diff --git a/contrib/epee/include/net/network_throttle-detail.hpp b/contrib/epee/include/net/network_throttle-detail.hpp index 0bab4fe9e..0a6dc4a20 100644 --- a/contrib/epee/include/net/network_throttle-detail.hpp +++ b/contrib/epee/include/net/network_throttle-detail.hpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief implementaion for throttling of connection (count and rate-limit speed etc) -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/net/network_throttle.hpp b/contrib/epee/include/net/network_throttle.hpp index b6f7592c2..750231610 100644 --- a/contrib/epee/include/net/network_throttle.hpp +++ b/contrib/epee/include/net/network_throttle.hpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief interface for throttling of connection (count and rate-limit speed etc) -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -42,11 +42,9 @@ #include <vector> #include <boost/noncopyable.hpp> #include <boost/shared_ptr.hpp> -#include <atomic> #include <boost/array.hpp> #include <boost/enable_shared_from_this.hpp> -#include <boost/interprocess/detail/atomic.hpp> #include <boost/thread/thread.hpp> #include "syncobj.h" @@ -61,7 +59,6 @@ #include <boost/asio/deadline_timer.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include "misc_language.h" -#include "pragma_comp_defs.h" #include <sstream> #include <iomanip> #include <algorithm> diff --git a/contrib/epee/include/net/protocol_switcher.h b/contrib/epee/include/net/protocol_switcher.h deleted file mode 100644 index 3b153d19c..000000000 --- a/contrib/epee/include/net/protocol_switcher.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _PROTOCOL_SWITCHER_H_ -#define _PROTOCOL_SWITCHER_H_ - -#include "levin_base.h" -#include "http_server.h" -#include "levin_protocol_handler.h" -//#include "abstract_tcp_server.h" - -namespace epee -{ -namespace net_utils -{ - struct protocl_switcher_config - { - http::http_custom_handler::config_type m_http_config; - levin::protocol_handler::config_type m_levin_config; - }; - - - struct i_protocol_handler - { - virtual bool handle_recv(const void* ptr, size_t cb)=0; - }; - - template<class t> - class t_protocol_handler: public i_protocol_handler - { - public: - typedef t t_type; - t_protocol_handler(i_service_endpoint* psnd_hndlr, typename t_type::config_type& config, const connection_context& conn_context):m_hadler(psnd_hndlr, config, conn_context) - {} - private: - bool handle_recv(const void* ptr, size_t cb) - { - return m_hadler.handle_recv(ptr, cb); - } - t_type m_hadler; - }; - - - class protocol_switcher - { - public: - typedef protocl_switcher_config config_type; - - protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context); - virtual ~protocol_switcher(){} - - virtual bool handle_recv(const void* ptr, size_t cb); - - bool after_init_connection(){return true;} - private: - t_protocol_handler<http::http_custom_handler> m_http_handler; - t_protocol_handler<levin::protocol_handler> m_levin_handler; - i_protocol_handler* pcurrent_handler; - - std::string m_cached_buff; - }; - - protocol_switcher::protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context):m_http_handler(psnd_hndlr, config.m_http_config, conn_context), m_levin_handler(psnd_hndlr, config.m_levin_config, conn_context), pcurrent_handler(NULL) - {} - - bool protocol_switcher::handle_recv(const void* ptr, size_t cb) - { - if(pcurrent_handler) - return pcurrent_handler->handle_recv(ptr, cb); - else - { - m_cached_buff.append((const char*)ptr, cb); - if(m_cached_buff.size() < sizeof(uint64_t)) - return true; - - if(*((uint64_t*)&m_cached_buff[0]) == LEVIN_SIGNATURE) - { - pcurrent_handler = &m_levin_handler; - return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size()); - } - if(m_cached_buff.substr(0, 4) == "GET " || m_cached_buff.substr(0, 4) == "POST") - { - pcurrent_handler = &m_http_handler; - return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size()); - }else - { - LOG_ERROR("Wrong protocol accepted on port..."); - return false; - } - } - - return true; - } -} -} -#endif //_PROTOCOL_SWITCHER_H_ diff --git a/contrib/epee/include/net/rpc_method_name.h b/contrib/epee/include/net/rpc_method_name.h deleted file mode 100644 index 1c327bc31..000000000 --- a/contrib/epee/include/net/rpc_method_name.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - - -#define RPC_METHOD_NAME(name) static inline const char* methodname(){return name;} diff --git a/contrib/epee/include/net/smtp.h b/contrib/epee/include/net/smtp.h deleted file mode 100644 index 5f2b842d5..000000000 --- a/contrib/epee/include/net/smtp.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include <iostream> -#include <istream> -#include <ostream> -#include <string> -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/archive/iterators/base64_from_binary.hpp> -#include <boost/archive/iterators/transform_width.hpp> -#include <boost/archive/iterators/ostream_iterator.hpp> - - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - using boost::asio::ip::tcp; - using namespace boost::archive::iterators; - typedef base64_from_binary<transform_width<const char *,6,8> > base64_text; - - /************************************************************************/ - /* */ - /************************************************************************/ - class smtp_client - { - public: - smtp_client(std::string pServer,unsigned int pPort,std::string pUser,std::string pPassword): - mServer(pServer),mPort(pPort),mUserName(pUser),mPassword(pPassword),mSocket(mIOService),mResolver(mIOService) - { - tcp::resolver::query qry(mServer,boost::lexical_cast<std::string>( mPort )); - mResolver.async_resolve(qry,boost::bind(&smtp_client::handleResolve,this,boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); - } - bool Send(std::string pFrom,std::string pTo,std::string pSubject,std::string pMessage) - { - mHasError = true; - mFrom=pFrom; - mTo=pTo; - mSubject=pSubject; - mMessage=pMessage; - mIOService.run(); - return !mHasError; - } - private: - std::string encodeBase64(std::string pData) - { - std::stringstream os; - size_t sz=pData.size(); - std::copy(base64_text(pData.c_str()),base64_text(pData.c_str()+sz),std::ostream_iterator<char>(os)); - return os.str(); - } - void handleResolve(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) - { - if(!err) - { - tcp::endpoint endpoint=*endpoint_iterator; - mSocket.async_connect(endpoint, - boost::bind(&smtp_client::handleConnect,this,boost::asio::placeholders::error,++endpoint_iterator)); - } - else - { - mHasError=true; - mErrorMsg= err.message(); - } - } - void writeLine(std::string pData) - { - std::ostream req_strm(&mRequest); - req_strm << pData << "\r\n"; - boost::asio::write(mSocket,mRequest); - req_strm.clear(); - } - void readLine(std::string& pData) - { - boost::asio::streambuf response; - boost::asio::read_until(mSocket, response, "\r\n"); - std::istream response_stream(&response); - response_stream >> pData; - } - void handleConnect(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) - { - if (!err) - { - std::string read_buff; - // The connection was successful. Send the request. - std::ostream req_strm(&mRequest); - writeLine("EHLO "+mServer); - readLine(read_buff);//220 - writeLine("AUTH LOGIN"); - readLine(read_buff);// - writeLine(encodeBase64(mUserName)); - readLine(read_buff); - writeLine(encodeBase64(mPassword)); - readLine(read_buff); - writeLine( "MAIL FROM:<"+mFrom+">"); - writeLine( "RCPT TO:<"+mTo+">"); - writeLine( "DATA"); - writeLine( "SUBJECT:"+mSubject); - writeLine( "From:"+mFrom); - writeLine( "To:"+mTo); - writeLine( ""); - writeLine( mMessage ); - writeLine( "\r\n.\r\n"); - readLine(read_buff); - if(read_buff == "250") - mHasError = false; - writeLine( "QUIT"); - } - else - { - mHasError=true; - mErrorMsg= err.message(); - } - } - std::string mServer; - std::string mUserName; - std::string mPassword; - std::string mFrom; - std::string mTo; - std::string mSubject; - std::string mMessage; - unsigned int mPort; - boost::asio::io_service mIOService; - tcp::resolver mResolver; - tcp::socket mSocket; - boost::asio::streambuf mRequest; - boost::asio::streambuf mResponse; - bool mHasError; - std::string mErrorMsg; - }; - - - bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_email, /*"STIL CRAWLER",*/ - const std::string& maillist, const std::string& subject, const std::string& body) - { - STD_TRY_BEGIN(); - //smtp_client mailc("yoursmtpserver.com",25,"user@yourdomain.com","password"); - //mailc.Send("from@yourdomain.com","to@somewhere.com","subject","Hello from C++ SMTP Client!"); - smtp_client mailc(server,port,login,pass); - return mailc.Send(from_email,maillist,subject,body); - STD_TRY_CATCH("at send_mail", false); - } - - } -} -} - -//#include "smtp.inl" diff --git a/contrib/epee/include/net/smtp.inl b/contrib/epee/include/net/smtp.inl deleted file mode 100644 index c16372c88..000000000 --- a/contrib/epee/include/net/smtp.inl +++ /dev/null @@ -1,1569 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "md5.h" - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - - ////////////////////////////////////////////////////////////////////////// - inline char * convert_hex( unsigned char *in, int len ) - { - static char hex[] = "0123456789abcdef"; - char * out; - int i; - - out = (char *) malloc(len * 2 + 1); - if (out == NULL) - return NULL; - - for (i = 0; i < len; i++) { - out[i * 2] = hex[in[i] >> 4]; - out[i * 2 + 1] = hex[in[i] & 15]; - } - - out[i*2] = 0; - - return out; - } - - ////////////////////////////////////////////////////////////////////////// - inline char * hash_md5(const char * sec_key, const char * data, int len) - { - char key[65], digest[24]; - char * hash_hex; - - int sec_len, i; - - sec_len = strlen(sec_key); - - if (sec_len < 64) { - memcpy(key, sec_key, sec_len); - for (i = sec_len; i < 64; i++) { - key[i] = 0; - } - } else { - memcpy(key, sec_key, 64); - } - - md5::hmac_md5( (const unsigned char*)data, len, (const unsigned char*)key, 64, (unsigned char*)digest ); - hash_hex = convert_hex( (unsigned char*)digest, 16 ); - - return hash_hex; - } - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - inline CSMTPClient::CSMTPClient(void) - { - m_dwSupportedAuthModesCount = 0; - m_bConnected = FALSE; - m_hSocket = INVALID_SOCKET; - m_pErrorText = NULL; - - // Initialize WinSock - WORD wVer = MAKEWORD( 2, 2 ); - if ( WSAStartup( wVer, &m_wsaData ) != NO_ERROR ) - { - SetErrorText( "WSAStartup.", WSAGetLastError() ); - throw; - } - if ( LOBYTE( m_wsaData.wVersion ) != 2 || HIBYTE( m_wsaData.wVersion ) != 2 ) - { - SetErrorText( "Can't find a useable WinSock DLL." ); - WSACleanup(); - throw; - } - } - - ////////////////////////////////////////////////////////////////////////// - inline CSMTPClient::~CSMTPClient(void) - { - if ( m_pErrorText ) - { - free( m_pErrorText ); - m_pErrorText = NULL; - } - - if ( m_bConnected ) - ServerDisconnect(); - - // Cleanup - WSACleanup(); - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::SetErrorText( LPCSTR szErrorText, DWORD dwErrorCode ) - { - if ( m_pErrorText ) - { - free( m_pErrorText ); - m_pErrorText = NULL; - } - - LPVOID lpMsgBuf = NULL; - if ( dwErrorCode ) - { - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dwErrorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR) &lpMsgBuf, - 0, NULL ); - } - - if ( szErrorText && strlen( szErrorText ) ) - { - m_pErrorText = (LPBYTE)malloc( strlen( szErrorText ) + 1 ); - strcpy( (char*)m_pErrorText, szErrorText ); - - if ( lpMsgBuf ) - { - strcat( (char*)m_pErrorText, " " ); - strcpy( (char*)m_pErrorText, (char*)lpMsgBuf ); - - LocalFree( lpMsgBuf ); - } - } - } - - inline void CSMTPClient::SetErrorText( PBYTE szErrorText, DWORD dwErrorCode ) - { - SetErrorText( (LPCSTR)szErrorText, dwErrorCode ); - } - - ////////////////////////////////////////////////////////////////////////// - inline char* CSMTPClient::GetLastErrorText() - { - return (char*)m_pErrorText; - } - - ////////////////////////////////////////////////////////////////////////// - inline DWORD CSMTPClient::ReceiveData( SOCKET hSocket, PBYTE pReceiveBuffer, DWORD dwReceiveBufferSize ) - { - DWORD dwReceivedDataSize = 0; - - if ( hSocket != INVALID_SOCKET && pReceiveBuffer && dwReceiveBufferSize ) - { - int iReceived = 0; - int iLength = 0; - - iLength = recv( hSocket, (LPSTR)pReceiveBuffer + iReceived, dwReceiveBufferSize - iReceived, - NO_FLAGS ); - - if ( iLength != 0 && iLength != SOCKET_ERROR ) - iReceived += iLength; - - dwReceivedDataSize = iReceived; - - pReceiveBuffer[ iReceived ] = 0; - } - - return dwReceivedDataSize; - } - - inline ////////////////////////////////////////////////////////////////////////// - DWORD CSMTPClient::SendData( SOCKET hSocket, PBYTE pSendBuffer, DWORD dwSendBufferSize ) - { - DWORD dwSended = 0; - - if ( hSocket != INVALID_SOCKET && pSendBuffer && dwSendBufferSize ) - { - int iSended = 0; - int iLength = 0; - - while ( iLength != SOCKET_ERROR && dwSendBufferSize - iSended > 0 ) - { - iLength = send( hSocket, (LPSTR)pSendBuffer + iSended, dwSendBufferSize - iSended, - NO_FLAGS ); - - if ( iLength != 0 && iLength != SOCKET_ERROR ) - iSended += iLength; - } - - dwSended = iSended; - } - - //if ( dwSended ) - // printf( "C: %s", pSendBuffer ); - - return dwSended; - } - - ////////////////////////////////////////////////////////////////////////// - inline unsigned short CSMTPClient::GetResponseCode( LPBYTE pBuffer, DWORD dwBufferSize ) - { - unsigned short iCode = 0; - - if ( dwBufferSize >= 3 ) - { - CHAR szResponseCode[ 4 ] = { 0 }; - memcpy( szResponseCode, pBuffer, 3 ); - szResponseCode[ 3 ] = 0; - iCode = atoi( szResponseCode ); - } - - return iCode; - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::ParseESMTPExtensions( LPBYTE pBuffer, DWORD dwBufferSize ) - { - const char *szSubstring = strstr( (const char*)pBuffer, "250-AUTH " ); - if ( !szSubstring ) - { - szSubstring = strstr( (const char*)pBuffer, "250 AUTH " ); - } - - if ( szSubstring ) - { - const char *szSubstringEnd = strstr( (const char*)szSubstring, "\r\n" ); - if ( szSubstringEnd ) - { - szSubstring += 9; - char szAuthMode[ 256 ] = { 0 }; - for ( ; szSubstring < szSubstringEnd + 1 ; szSubstring++ ) - { - if ( *szSubstring == ' ' || *szSubstring == '\r' ) - { - if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_PLAIN ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_PLAIN; - m_dwSupportedAuthModesCount++; - } - else if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_LOGIN ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_LOGIN; - m_dwSupportedAuthModesCount++; - } - else if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_CRAM_MD5 ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_CRAM_MD5; - m_dwSupportedAuthModesCount++; - } - - szAuthMode[ 0 ] = 0; - - if ( m_dwSupportedAuthModesCount == MAX_AUTH_MODES_COUND ) - break; - } - else - { - szAuthMode[ strlen( szAuthMode ) + 1 ] = 0; - szAuthMode[ strlen( szAuthMode ) ] = *szSubstring; - } - } - } - } - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerConnect( LPCSTR szServerAddress, const unsigned short iPortNumber ) - { - if ( m_bConnected ) - ServerDisconnect(); - - m_bConnected = FALSE; - m_hSocket = INVALID_SOCKET; - - m_hSocket = _connectServerSocket( szServerAddress, iPortNumber ); - - if ( m_hSocket != INVALID_SOCKET ) - { - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - // Check 220 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 220 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error. ", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - // EHLO / HELO - BYTE szHelloBuffer[ 256 ]; - sprintf( (char*)szHelloBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_EHLO, (char*)szServerAddress ); - if ( SendData( m_hSocket, (PBYTE)szHelloBuffer, strlen( (const char*)szHelloBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 500 ) - { - SetErrorText( pReceiveBuffer ); - - sprintf( (char*)szHelloBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_HELO, (char*)szServerAddress ); - if ( SendData( m_hSocket, (PBYTE)szHelloBuffer, strlen( (const char*)szHelloBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 250 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - } - else if ( iResponseCode != 250 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - // Parse AUTH supported modes - ParseESMTPExtensions( pReceiveBuffer, iReceived ); - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - free( pReceiveBuffer ); - } - } - else - { - return FALSE; - } - - m_bConnected = TRUE; - - return TRUE; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerConnect( LPCSTR szServerAddress, const unsigned short iPortNumber, LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - bSuccess = ServerConnect( szServerAddress, iPortNumber ); - if ( bSuccess ) - { - if ( GetAuthModeIsSupported( AUTH_MODE_CRAM_MD5 ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_CRAM_MD5 ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_PLAIN ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_PLAIN ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_LOGIN ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_LOGIN ); - } - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline SOCKET CSMTPClient::_connectServerSocket( LPCSTR szServerAddress, const unsigned short iPortNumber ) - { - int nConnect; - short nProtocolPort = iPortNumber; - LPHOSTENT lpHostEnt; - SOCKADDR_IN sockAddr; - - SOCKET hServerSocket = INVALID_SOCKET; - - lpHostEnt = gethostbyname( szServerAddress ); - if (lpHostEnt) - { - hServerSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if (hServerSocket != INVALID_SOCKET) - { - sockAddr.sin_family = AF_INET; - sockAddr.sin_port = htons( nProtocolPort ); - sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list); - - nConnect = connect( hServerSocket, (PSOCKADDR)&sockAddr, - sizeof(sockAddr) ); - - if ( nConnect != 0 ) - { - SetErrorText( "connect error.", WSAGetLastError() ); - hServerSocket = INVALID_SOCKET; - } - } - else - { - SetErrorText( "Invalid socket." ); - throw; - } - } - else - { - SetErrorText( "Error retrieving host by name.", WSAGetLastError() ); - } - - return hServerSocket ; - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::ServerDisconnect() - { - if ( m_hSocket != INVALID_SOCKET ) - { - if ( SendData( m_hSocket, (PBYTE)SMTP_COMMAND_QUIT, strlen( SMTP_COMMAND_QUIT ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - - if ( iReceived ) - SetErrorText( pReceiveBuffer ); - - free( pReceiveBuffer ); - } - - m_hSocket = INVALID_SOCKET; - } - - m_bConnected = FALSE; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::GetAuthModeIsSupported( int iMode ) - { - BOOL bSupported = FALSE; - - for ( int i = 0 ; i < m_dwSupportedAuthModesCount ; i++ ) - { - if ( m_aSupportedAuthModes[ i ] == iMode ) - { - bSupported = TRUE; - break; - } - } - - return bSupported; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLogin( LPCSTR szUsername, LPCSTR szPassword, int iAuthMode ) - { - BOOL bSuccess = FALSE; - - if ( iAuthMode == AUTH_MODE_PLAIN ) - { - bSuccess = ServerLoginMethodPlain( szUsername, szPassword ); - } - else if ( iAuthMode == AUTH_MODE_LOGIN ) - { - bSuccess = ServerLoginMethodLogin( szUsername, szPassword ); - } - else if ( iAuthMode == AUTH_MODE_CRAM_MD5 ) - { - bSuccess = ServerLoginMethodCramMD5( szUsername, szPassword ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLogin( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - if ( GetAuthModeIsSupported( AUTH_MODE_CRAM_MD5 ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_CRAM_MD5 ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_PLAIN ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_PLAIN ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_LOGIN ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_LOGIN ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodPlain( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_PLAIN ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - // Encode. - DWORD dwLoginBuffer = strlen( szUsername ) + strlen( szPassword ) + 3; - char *pLoginBuffer = (char*)malloc( dwLoginBuffer ); - if ( pLoginBuffer ) - { - ZeroMemory( pLoginBuffer, dwLoginBuffer ); - strcpy( pLoginBuffer + 1, szUsername ); - strcpy( pLoginBuffer + 1 + strlen( szUsername ) + 1, szPassword ); - - Base64Coder coder; - coder.Encode( (const PBYTE)pLoginBuffer, dwLoginBuffer - 1 ); - LPCSTR szLoginBufferEncoded = coder.EncodedMessage(); - - if ( szLoginBufferEncoded && strlen( szLoginBufferEncoded ) > 0 ) - { - DWORD dwSendBufferSize = strlen( szLoginBufferEncoded ) + 4; - char* pSendBuffer = (char*)malloc( dwSendBufferSize ); - if ( pSendBuffer ) - { - strcpy( pSendBuffer, szLoginBufferEncoded ); - strcat( pSendBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)pSendBuffer, strlen( (const char*)pSendBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pSendBuffer ); - free( pLoginBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pSendBuffer ); - } - } - - free( pLoginBuffer ); - - // check result - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - } - - free( pReceiveBuffer ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodLogin( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_LOGIN ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - Base64Coder coder; - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szRequest = coder.DecodedMessage(); - if ( szRequest && strlen( szRequest ) > 0 ) - { - if ( strcmpi( szRequest, "Username:" ) == 0 ) - { - coder.Encode( (const PBYTE)szUsername, strlen( szUsername ) ); - LPCSTR szUsernameEncoded = coder.EncodedMessage(); - - char* szLoginUsernameBuffer = (char*)malloc( strlen( szUsernameEncoded ) + 4 ); - if ( szLoginUsernameBuffer ) - { - strcpy( szLoginUsernameBuffer, szUsernameEncoded ); - strcat( szLoginUsernameBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)szLoginUsernameBuffer, strlen( (const char*)szLoginUsernameBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szLoginUsernameBuffer ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szRequest2 = coder.DecodedMessage(); - if ( szRequest2 && strlen( szRequest2 ) > 0 ) - { - if ( strcmpi( szRequest2, "Password:" ) == 0 ) - { - coder.Encode( (const PBYTE)szPassword, strlen( szPassword ) ); - LPCSTR szPasswordEncoded = coder.EncodedMessage(); - - char* szLoginPasswordBuffer = (char*)malloc( strlen( szPasswordEncoded ) + 4 ); - if ( szLoginPasswordBuffer ) - { - strcpy( szLoginPasswordBuffer, szPasswordEncoded ); - strcat( szLoginPasswordBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)szLoginPasswordBuffer, strlen( (const char*)szLoginPasswordBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szLoginPasswordBuffer ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - } - } - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pReceiveBuffer ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodCramMD5( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_CRAM_MD5 ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - Base64Coder coder; - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szResponse = coder.DecodedMessage(); - if ( szResponse && strlen( szResponse ) > 0 ) - { - char *auth_hex = hash_md5( szPassword, szResponse, strlen(szResponse) ); - if ( !auth_hex ) - { - free( pReceiveBuffer ); - return FALSE; - } - - char *szCommand = (char*)malloc( strlen( szUsername ) + strlen( auth_hex ) + 5 ); - if ( szCommand ) - { - sprintf( szCommand, "%s %s", szUsername, auth_hex ); - - free( auth_hex ); - - coder.Encode( (const PBYTE)szCommand, strlen( szCommand ) ); - - free( szCommand ); - - LPCSTR szAuthEncoded = coder.EncodedMessage(); - if ( szAuthEncoded == NULL ) - { - free( pReceiveBuffer ); - return FALSE; - } - - char *szAuthCommand = (char*)malloc( strlen( szAuthEncoded ) + 4 ); - if ( szAuthCommand ) - { - strcpy( szAuthCommand, szAuthEncoded ); - strcat( szAuthCommand, "\r\n" ); - - // Send auth data - if ( SendData( m_hSocket, (PBYTE)szAuthCommand, strlen( (const char*)szAuthCommand ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szAuthCommand ); - free( pReceiveBuffer ); - return FALSE; - } - - // Check response - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szAuthCommand ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( auth_hex ); - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pReceiveBuffer ); - } - else - { - SetErrorText( "malloc() failed.", GetLastError() ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::SendMessage( LPCSTR szFromAddress, LPCSTR szFromName, LPCSTR szToAddresses, LPCSTR szSubject, LPCSTR szXMailer, LPBYTE pBodyBuffer, DWORD dwBodySize ) - { - BOOL bSuccess = FALSE; - - // Format Header - if ( !szFromAddress ) - { - SetErrorText( "SendMessage. Invalid Parameters!" ); - return NULL; - } - - char *szHeaderBuffer = (char*)malloc( 1024 * 16 ); - if ( szHeaderBuffer ) - { - // get the current date and time - char szDate[ 500 ]; - char sztTime[ 500 ]; - - SYSTEMTIME st = { 0 }; - ::GetSystemTime(&st); - - ::GetDateFormatA( MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), 0, &st, "ddd',' dd MMM yyyy", szDate , sizeof( szDate ) ); - ::GetTimeFormatA( MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), TIME_FORCE24HOURFORMAT, &st, "HH':'mm':'ss", sztTime, sizeof( sztTime ) ); - - sprintf( szHeaderBuffer, "DATE: %s %s\r\n", szDate, sztTime ); - - // X-Mailer Field - if ( szXMailer && strlen( szXMailer ) ) - { - strcat( szHeaderBuffer, "X-Mailer: " ); - strcat( szHeaderBuffer, szXMailer ); - strcat( szHeaderBuffer, "\r\n" ); - } - - // From: - strcat( szHeaderBuffer, "From: " ); - if ( szFromName ) - { - strcat( szHeaderBuffer, "\"" ); - strcat( szHeaderBuffer, szFromName ); - strcat( szHeaderBuffer, "\" <" ); - strcat( szHeaderBuffer, szFromAddress ); - strcat( szHeaderBuffer, ">\r\n" ); - } - else - { - strcat( szHeaderBuffer, "<" ); - strcat( szHeaderBuffer, szFromAddress ); - strcat( szHeaderBuffer, ">\r\n" ); - } - - // Subject: - if ( szSubject && strlen( szSubject ) ) - { - strcat( szHeaderBuffer, "Subject: " ); - strcat( szHeaderBuffer, szSubject ); - strcat( szHeaderBuffer, "\r\n" ); - } - - // To Fields - strcat( szHeaderBuffer, "To: " ); - strcat( szHeaderBuffer, szToAddresses ); - strcat( szHeaderBuffer, "\r\n" ); - - // MIME - strcat( szHeaderBuffer, "MIME-Version: 1.0\r\nContent-type: text/plain; charset=US-ASCII\r\n" ); - - // End Header - strcat( szHeaderBuffer, "\r\n" ); - } - else - { - SetErrorText( "malloc error.", GetLastError() ); - return FALSE; - } - - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "MAIL FROM:<%s> SIZE=%u\r\n", (char*)szFromAddress, strlen( szHeaderBuffer ) + dwBodySize + 2 ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szHeaderBuffer ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 250 ) - { - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - // Post "RCTP TO:" - char *szCurrentAddr = (char*)malloc( strlen( szToAddresses ) + 1 ); - if ( !szCurrentAddr ) - { - SetErrorText( "malloc error.", GetLastError() ); - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - const char* szToOffset = szToAddresses; - char* szZap = NULL; - - BOOL bRCPTAccepted = FALSE; - do - { - strcpy( szCurrentAddr, szToOffset ); - char *szExtractedAdress = szCurrentAddr; - szZap = strchr( szCurrentAddr, ',' ); - - if ( szZap ) - { - *szZap = 0; - szToOffset = szZap + 1; - } - - char *pSkobka1 = strchr( szCurrentAddr, '<' ); - char *pSkobka2 = strchr( szCurrentAddr, '>' ); - - if ( pSkobka1 && pSkobka2 && pSkobka2 > pSkobka1 ) - { - szExtractedAdress = pSkobka1 + 1; - *pSkobka2 = NULL; - } - - if ( szExtractedAdress && strlen( szExtractedAdress ) > 0 ) - { - sprintf( (char*)szCommandBuffer, "RCPT TO:<%s>\r\n", (char*)szExtractedAdress ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szCurrentAddr ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 250 ) - { - bRCPTAccepted = TRUE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( szCurrentAddr ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - } - - } while( szZap ); - - free( szCurrentAddr ); - - if ( bRCPTAccepted ) - { - sprintf( (char*)szCommandBuffer, "DATA\r\n" ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 354 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 354 ) - { - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - // Send message data (header + body + .) - if ( SendData( m_hSocket, (PBYTE)szHeaderBuffer, strlen( (const char*)szHeaderBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - if ( SendData( m_hSocket, (PBYTE)pBodyBuffer, dwBodySize ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - if ( SendData( m_hSocket, (PBYTE)"\r\n.\r\n", 5 ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 250 ) - { - bSuccess = TRUE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - } - } - - free( pReceiveBuffer ); - } - else - { - SetErrorText( "malloc error.", GetLastError() ); - } - - if ( szHeaderBuffer ) - free( szHeaderBuffer ); - - return bSuccess; - } - - - - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - - -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif - -#ifndef ROUNDTOPAGE -#define ROUNDTOPAGE(a) (((a/4096)+1)*4096) -#endif - - ////////////////////////////////////////////////////////////////////// - // Construction/Destruction - ////////////////////////////////////////////////////////////////////// - - inline Base64Coder::Base64Coder() - : m_pDBuffer(NULL), - m_pEBuffer(NULL), - m_nDBufLen(0), - m_nEBufLen(0) - { - - } - - inline Base64Coder::~Base64Coder() - { - if(m_pDBuffer != NULL) - delete [] m_pDBuffer; - - if(m_pEBuffer != NULL) - delete [] m_pEBuffer; - } - - inline LPCSTR Base64Coder::DecodedMessage() const - { - return (LPCSTR) m_pDBuffer; - } - - inline LPCSTR Base64Coder::EncodedMessage() const - { - return (LPCSTR) m_pEBuffer; - } - - inline void Base64Coder::AllocEncode(DWORD nSize) - { - if(m_nEBufLen < nSize) - { - if(m_pEBuffer != NULL) - delete [] m_pEBuffer; - - m_nEBufLen = ROUNDTOPAGE(nSize); - m_pEBuffer = new BYTE[m_nEBufLen]; - } - - ::ZeroMemory(m_pEBuffer, m_nEBufLen); - m_nEDataLen = 0; - } - - inline void Base64Coder::AllocDecode(DWORD nSize) - { - if(m_nDBufLen < nSize) - { - if(m_pDBuffer != NULL) - delete [] m_pDBuffer; - - m_nDBufLen = ROUNDTOPAGE(nSize); - m_pDBuffer = new BYTE[m_nDBufLen]; - } - - ::ZeroMemory(m_pDBuffer, m_nDBufLen); - m_nDDataLen = 0; - } - - inline void Base64Coder::SetEncodeBuffer(const PBYTE pBuffer, DWORD nBufLen) - { - DWORD i = 0; - - AllocEncode(nBufLen); - while(i < nBufLen) - { - if(!_IsBadMimeChar(pBuffer[i])) - { - m_pEBuffer[m_nEDataLen] = pBuffer[i]; - m_nEDataLen++; - } - - i++; - } - } - - inline void Base64Coder::SetDecodeBuffer(const PBYTE pBuffer, DWORD nBufLen) - { - AllocDecode(nBufLen); - ::CopyMemory(m_pDBuffer, pBuffer, nBufLen); - m_nDDataLen = nBufLen; - } - - inline void Base64Coder::Encode(const PBYTE pBuffer, DWORD nBufLen) - { - SetDecodeBuffer(pBuffer, nBufLen); - AllocEncode(nBufLen * 2); - - TempBucket Raw; - DWORD nIndex = 0; - - while((nIndex + 3) <= nBufLen) - { - Raw.Clear(); - ::CopyMemory(&Raw, m_pDBuffer + nIndex, 3); - Raw.nSize = 3; - _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen); - nIndex += 3; - m_nEDataLen += 4; - } - - if(nBufLen > nIndex) - { - Raw.Clear(); - Raw.nSize = (BYTE) (nBufLen - nIndex); - ::CopyMemory(&Raw, m_pDBuffer + nIndex, nBufLen - nIndex); - _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen); - m_nEDataLen += 4; - } - } - - inline void Base64Coder::Encode(LPCSTR szMessage) - { - if(szMessage != NULL) - Base64Coder::Encode((const PBYTE)szMessage, strlen( (const char*)szMessage)); - } - - inline void Base64Coder::Decode(const PBYTE pBuffer, DWORD dwBufLen) - { - if(is_init()) - _Init(); - - SetEncodeBuffer(pBuffer, dwBufLen); - - AllocDecode(dwBufLen); - - TempBucket Raw; - - DWORD nIndex = 0; - - while((nIndex + 4) <= m_nEDataLen) - { - Raw.Clear(); - Raw.nData[0] = DecodeTable()[m_pEBuffer[nIndex]]; - Raw.nData[1] = DecodeTable()[m_pEBuffer[nIndex + 1]]; - Raw.nData[2] = DecodeTable()[m_pEBuffer[nIndex + 2]]; - Raw.nData[3] = DecodeTable()[m_pEBuffer[nIndex + 3]]; - - if(Raw.nData[2] == 255) - Raw.nData[2] = 0; - if(Raw.nData[3] == 255) - Raw.nData[3] = 0; - - Raw.nSize = 4; - _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen); - nIndex += 4; - m_nDDataLen += 3; - } - - // If nIndex < m_nEDataLen, then we got a decode message without padding. - // We may want to throw some kind of warning here, but we are still required - // to handle the decoding as if it was properly padded. - if(nIndex < m_nEDataLen) - { - Raw.Clear(); - for(DWORD i = nIndex; i < m_nEDataLen; i++) - { - Raw.nData[i - nIndex] = DecodeTable()[m_pEBuffer[i]]; - Raw.nSize++; - if(Raw.nData[i - nIndex] == 255) - Raw.nData[i - nIndex] = 0; - } - - _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen); - m_nDDataLen += (m_nEDataLen - nIndex); - } - } - - inline void Base64Coder::Decode(LPCSTR szMessage) - { - if(szMessage != NULL) - Base64Coder::Decode((const PBYTE)szMessage, strlen((const char*)szMessage)); - } - - inline DWORD Base64Coder::_DecodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) - { - TempBucket Data; - DWORD nCount = 0; - - _DecodeRaw(Data, Decode); - - for(int i = 0; i < 3; i++) - { - pBuffer[i] = Data.nData[i]; - if(pBuffer[i] != 255) - nCount++; - } - - return nCount; - } - - - inline void Base64Coder::_EncodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) - { - TempBucket Data; - - _EncodeRaw(Data, Decode); - - for(int i = 0; i < 4; i++) - pBuffer[i] = Base64Digits()[Data.nData[i]]; - - switch(Decode.nSize) - { - case 1: - pBuffer[2] = '='; - case 2: - pBuffer[3] = '='; - } - } - - inline void Base64Coder::_DecodeRaw(TempBucket &Data, const TempBucket &Decode) - { - BYTE nTemp; - - Data.nData[0] = Decode.nData[0]; - Data.nData[0] <<= 2; - - nTemp = Decode.nData[1]; - nTemp >>= 4; - nTemp &= 0x03; - Data.nData[0] |= nTemp; - - Data.nData[1] = Decode.nData[1]; - Data.nData[1] <<= 4; - - nTemp = Decode.nData[2]; - nTemp >>= 2; - nTemp &= 0x0F; - Data.nData[1] |= nTemp; - - Data.nData[2] = Decode.nData[2]; - Data.nData[2] <<= 6; - nTemp = Decode.nData[3]; - nTemp &= 0x3F; - Data.nData[2] |= nTemp; - } - - inline void Base64Coder::_EncodeRaw(TempBucket &Data, const TempBucket &Decode) - { - BYTE nTemp; - - Data.nData[0] = Decode.nData[0]; - Data.nData[0] >>= 2; - - Data.nData[1] = Decode.nData[0]; - Data.nData[1] <<= 4; - nTemp = Decode.nData[1]; - nTemp >>= 4; - Data.nData[1] |= nTemp; - Data.nData[1] &= 0x3F; - - Data.nData[2] = Decode.nData[1]; - Data.nData[2] <<= 2; - - nTemp = Decode.nData[2]; - nTemp >>= 6; - - Data.nData[2] |= nTemp; - Data.nData[2] &= 0x3F; - - Data.nData[3] = Decode.nData[2]; - Data.nData[3] &= 0x3F; - } - - inline BOOL Base64Coder::_IsBadMimeChar(BYTE nData) - { - switch(nData) - { - case '\r': case '\n': case '\t': case ' ' : - case '\b': case '\a': case '\f': case '\v': - return TRUE; - default: - return FALSE; - } - } - - inline void Base64Coder::_Init() - { // Initialize Decoding table. - - int i; - - for(i = 0; i < 256; i++) - DecodeTable()[i] = -2; - - for(i = 0; i < 64; i++) - { - DecodeTable()[Base64Digits()[i]] = i; - DecodeTable()[Base64Digits()[i]|0x80] = i; - } - - DecodeTable()['='] = -1; - DecodeTable()['='|0x80] = -1; - - is_init() = TRUE; - } - - - } -} -} diff --git a/contrib/epee/include/net/smtp_helper.h b/contrib/epee/include/net/smtp_helper.h deleted file mode 100644 index 7827315a2..000000000 --- a/contrib/epee/include/net/smtp_helper.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include "smtp.h" - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - inline bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_addres, const std::string& from_name, const std::string& maillist, const std::string& subject, const std::string& mail_body) - { - net_utils::smtp::CSMTPClient smtp; - - if ( !smtp.ServerConnect( server.c_str(), port ) ) - { - LOG_PRINT("Reporting: Failed to connect to server " << server <<":"<< port, LOG_LEVEL_0); - return false; - } - - if(login.size() && pass.size()) - { - if ( !smtp.ServerLogin( login.c_str(), pass.c_str()) ) - { - LOG_PRINT("Reporting: Failed to auth on server " << server <<":"<< port, LOG_LEVEL_0); - return false; - - } - } - - if ( !smtp.SendMessage( from_addres.c_str(), - from_name.c_str(), - maillist.c_str(), - subject.c_str(), - "bicycle-client", - (LPBYTE)mail_body.data(), - mail_body.size())) - { - char *szErrorText = smtp.GetLastErrorText(); - if ( szErrorText ) - { - LOG_PRINT("Failed to send message, error text: " << szErrorText, LOG_LEVEL_0); - } - else - { - LOG_PRINT("Failed to send message, error text: null", LOG_LEVEL_0); - } - return false; - } - - smtp.ServerDisconnect(); - - return true; - - - } - } -} -} diff --git a/contrib/epee/include/pragma_comp_defs.h b/contrib/epee/include/pragma_comp_defs.h deleted file mode 100644 index f4ef7057e..000000000 --- a/contrib/epee/include/pragma_comp_defs.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#if defined(__GNUC__) - #define PRAGMA_WARNING_PUSH _Pragma("GCC diagnostic push") - #define PRAGMA_WARNING_POP _Pragma("GCC diagnostic pop") - #define PRAGMA_WARNING_DISABLE_VS(w) - #define PRAGMA_GCC(w) _Pragma(w) -#elif defined(_MSC_VER) - #define PRAGMA_WARNING_PUSH __pragma(warning( push )) - #define PRAGMA_WARNING_POP __pragma(warning( pop )) - #define PRAGMA_WARNING_DISABLE_VS(w) __pragma( warning ( disable: w )) - //#define PRAGMA_WARNING_DISABLE_GCC(w) - #define PRAGMA_GCC(w) -#endif diff --git a/contrib/epee/include/profile_tools.h b/contrib/epee/include/profile_tools.h index a0b5f77f4..76f794a36 100644 --- a/contrib/epee/include/profile_tools.h +++ b/contrib/epee/include/profile_tools.h @@ -28,7 +28,7 @@ #ifndef _PROFILE_TOOLS_H_ #define _PROFILE_TOOLS_H_ -#include "misc_os_dependent.h" +#include "time_helper.h" namespace epee { diff --git a/contrib/epee/include/reg_exp_definer.h b/contrib/epee/include/reg_exp_definer.h index 386a45f9a..d1b800a32 100644 --- a/contrib/epee/include/reg_exp_definer.h +++ b/contrib/epee/include/reg_exp_definer.h @@ -28,7 +28,7 @@ #ifndef _REG_EXP_DEFINER_H_ #define _REG_EXP_DEFINER_H_ -#include <boost/interprocess/detail/atomic.hpp> +#include <atomic> #include <boost/regex.hpp> #include "syncobj.h" @@ -46,38 +46,38 @@ namespace epee const static global_regexp_critical_section gregexplock; #define STATIC_REGEXP_EXPR_1(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_1 = 0;\ + static std::atomic<bool> regexp_initialized_1(false);\ volatile uint32_t local_is_initialized_1 = regexp_initialized_1;\ if(!local_is_initialized_1)\ gregexplock.get_lock().lock();\ static const boost::regex var_name(xpr_text , reg_exp_flags);\ if(!local_is_initialized_1)\ {\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_1, 1);\ + regexp_initialized_1 = true;\ gregexplock.get_lock().unlock();\ } #define STATIC_REGEXP_EXPR_2(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_2 = 0;\ + static std::atomic<bool> regexp_initialized_2(false);\ volatile uint32_t local_is_initialized_2 = regexp_initialized_2;\ if(!local_is_initialized_2)\ gregexplock.get_lock().lock().lock();\ static const boost::regex var_name(xpr_text , reg_exp_flags);\ if(!local_is_initialized_2)\ {\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_2, 1);\ + regexp_initialized_2 = true;\ gregexplock.get_lock().lock().unlock();\ } #define STATIC_REGEXP_EXPR_3(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_3 = 0;\ + static std::atomic<bool> regexp_initialized_3(false);\ volatile uint32_t local_is_initialized_3 = regexp_initialized_3;\ if(!local_is_initialized_3)\ gregexplock.get_lock().lock().lock();\ static const boost::regex var_name(xpr_text , reg_exp_flags);\ if(!local_is_initialized_3)\ {\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_3, 1);\ + regexp_initialized_3 = true;\ gregexplock.get_lock().lock().unlock();\ } } diff --git a/contrib/epee/include/reg_utils.h b/contrib/epee/include/reg_utils.h deleted file mode 100644 index 22227a9b2..000000000 --- a/contrib/epee/include/reg_utils.h +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _MUSC_UTILS_EX_H_ -#define _MUSC_UTILS_EX_H_ - -namespace epee -{ -namespace reg_utils -{ - //----------------------------------------------------------------------------------------------------------------------------------- - template<class T> - bool RegSetPODValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const T& valToSave, bool force_create = true) - { - HKEY hRegKey = 0; - DWORD dw = 0; - - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - if(force_create && (::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS) ) - return false; - - - DWORD val_type = (sizeof(valToSave) == sizeof(DWORD)) ? REG_DWORD:REG_BINARY; - - BOOL res = ::RegSetValueExA( hRegKey, pValName, 0, val_type, (LPBYTE)&valToSave, sizeof(valToSave)) == ERROR_SUCCESS; - - ::RegCloseKey(hRegKey); - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template<class T> - bool RegGetPODValue(HKEY hParentKey, const char* pSubKey, const char* pValName, T& valToSave) - { - HKEY hRegKey = 0; - LONG res = 0; - - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - DWORD dwType, lSize = 0; - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || (sizeof(valToSave) < lSize) ) - { - ::RegCloseKey(hRegKey); - return false; - } - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, (LPBYTE)&valToSave, &lSize); - } - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegSetANSIString(HKEY hParentKey, const char* pSubKey, const char* pValName, const std::string& strToSave) - { - HKEY hRegKey = 0; - DWORD dw = 0; - DWORD res_ = 0; - if( (res_ = ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw)) != ERROR_SUCCESS ) - if( (res_= ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey)) != ERROR_SUCCESS ) - return false; - - DWORD valType = REG_SZ; - const char* pStr = strToSave.c_str(); - DWORD sizeOfStr = (DWORD)strToSave.size()+1; - LSTATUS res = ::RegSetValueExA(hRegKey, pValName, 0, valType, (LPBYTE)pStr, sizeOfStr); - - ::RegCloseKey(hRegKey); - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegGetANSIString(HKEY hParentKey, const char* pSubKey, const char* pValName, std::string& strToSave) - { - HKEY hRegKey = 0; - LONG res = 0; - - - if((res = ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey)) == ERROR_SUCCESS ) - { - DWORD dwType, lSize = 0; - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res) - { - - ::RegCloseKey(hRegKey); - return false; - } - char* pTmpStr = new char[lSize+2]; - memset(pTmpStr, 0, lSize+2); - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, (LPBYTE)pTmpStr, &lSize); - pTmpStr[lSize+1] = 0; //be happy ;) - strToSave = pTmpStr; - delete [] pTmpStr; - ::RegCloseKey(hRegKey); - } - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template<class TMemoryObject> - bool RegSetRAWValue(HKEY hKey, const char* pValName, const TMemoryObject& valToSave, DWORD valType = REG_BINARY) - { - LONG res = ::RegSetValueExA( hKey, pValName, 0, valType, (CONST BYTE*)valToSave.get(0), (DWORD)valToSave.get_size()); - - return ERROR_SUCCESS==res ? true:false; - } - //---------------------------------------------------------------------------------------------------------------------------------- - bool RegSetRAWValue(HKEY hKey, const char* pValName, const std::string & valToSave, DWORD valType = REG_BINARY) - { - LONG res = ::RegSetValueExA( hKey, pValName, 0, valType, (CONST BYTE*)valToSave.data(), (DWORD)valToSave.size()); - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template<class TMemoryObject> - bool RegGetRAWValue(HKEY hKey, const char* pValName, TMemoryObject& valToSave, DWORD* pRegType) - { - DWORD dwType, lSize = 0; - LONG res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || 0 >= lSize) - { - valToSave.release(); - return false; - } - if(valToSave.get_size() < lSize) - valToSave.alloc_buff(lSize); - res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, (LPBYTE)valToSave.get(0), &lSize); - if(pRegType) *pRegType = dwType; - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - bool RegGetRAWValue(HKEY hKey, const char* pValName, std::string& valToSave, DWORD* pRegType) - { - DWORD dwType, lSize = 0; - LONG res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || 0 >= lSize) - { - return false; - } - - valToSave.resize(lSize); - res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, (LPBYTE)valToSave.data(), &lSize); - if(pRegType) *pRegType = dwType; - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template<class TMemoryObject> - bool RegSetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const TMemoryObject& valToSave, DWORD valType = REG_BINARY) - { - HKEY hRegKey = 0; - DWORD dw = 0; - bool res = false; - - if( ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS ) - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - return false; - - res = RegSetRAWValue(hRegKey, pValName, valToSave, valType); - - ::RegCloseKey(hRegKey); - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - bool RegSetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const std::string& valToSave, DWORD valType = REG_BINARY) - { - HKEY hRegKey = 0; - DWORD dw = 0; - bool res = false; - - if( ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS ) - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - return false; - - res = RegSetRAWValue(hRegKey, pValName, valToSave, valType); - - ::RegCloseKey(hRegKey); - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template<class TMemoryObject> - bool RegGetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, TMemoryObject& valToSave, DWORD* pRegType) - { - HKEY hRegKey = 0; - bool res = false; - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - res = RegGetRAWValue(hRegKey, pValName, valToSave, pRegType); - ::RegCloseKey(hRegKey); - } - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegGetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, std::string& valToSave, DWORD* pRegType) - { - HKEY hRegKey = 0; - bool res = false; - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - res = RegGetRAWValue(hRegKey, pValName, valToSave, pRegType); - ::RegCloseKey(hRegKey); - } - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegRemoveValue(HKEY hParentKey, const char* pValName) - { - //CHECK_AND_ASSERT(hParentKey&&pValName, false); - return ::RegDeleteValueA(hParentKey, pValName)==ERROR_SUCCESS ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegRemoveKey(HKEY hParentKey, const char* pKeyName) - { - //CHECK_AND_ASSERT(hParentKey&&pKeyName, false); - return ::RegDeleteKeyA(hParentKey, pKeyName)==ERROR_SUCCESS ? true:false; - } - -} -} -#endif //_MUSC_UTILS_EX_H_ diff --git a/contrib/epee/include/rolling_median.h b/contrib/epee/include/rolling_median.h index 877814e57..e230fd974 100644 --- a/contrib/epee/include/rolling_median.h +++ b/contrib/epee/include/rolling_median.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // @@ -126,7 +126,6 @@ private: protected: rolling_median_t &operator=(const rolling_median_t&) = delete; - rolling_median_t(const rolling_median_t&) = delete; public: //creates new rolling_median_t: to calculate `nItems` running median. @@ -139,6 +138,20 @@ public: clear(); } + rolling_median_t(const rolling_median_t &other) + { + N = other.N; + int size = N * (sizeof(Item) + sizeof(int) * 2); + data = (Item*)malloc(size); + memcpy(data, other.data, size); + pos = (int*) (data + N); + heap = pos + N + (N / 2); //points to middle of storage. + idx = other.idx; + minCt = other.minCt; + maxCt = other.maxCt; + sz = other.sz; + } + rolling_median_t(rolling_median_t &&m) { memcpy(this, &m, sizeof(rolling_median_t)); diff --git a/contrib/epee/include/serialization/enableable.h b/contrib/epee/include/serialization/enableable.h deleted file mode 100644 index e1be2a774..000000000 --- a/contrib/epee/include/serialization/enableable.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -namespace epee -{ - - template<class t_obj> - struct enableable - { - t_obj v; - bool enabled; - - enableable() - : v(t_obj()), enabled(true) - { // construct from defaults - } - - enableable(const t_obj& _v) - : v(_v), enabled(true) - { // construct from specified values - } - - enableable(const enableable<t_obj>& _v) - : v(_v.v), enabled(_v.enabled) - { // construct from specified values - } - }; -} diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h index 2e4a0faad..06d74329f 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/contrib/epee/include/serialization/keyvalue_serialization.h @@ -30,7 +30,6 @@ #include <boost/utility/value_init.hpp> #include <boost/foreach.hpp> #include "misc_log_ex.h" -#include "enableable.h" #include "keyvalue_serialization_overloads.h" #undef MONERO_DEFAULT_LOG_CATEGORY diff --git a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h index 1f9d6b6d7..b637df5b0 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h @@ -81,24 +81,6 @@ namespace epee return obj._load(stg, hchild_section); } //------------------------------------------------------------------------------------------------------------------- - template<class serializible_type, class t_storage> - static bool serialize_t_obj(enableable<serializible_type>& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - if(!obj.enabled) - return true; - return serialize_t_obj(obj.v, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template<class serializible_type, class t_storage> - static bool unserialize_t_obj(enableable<serializible_type>& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - obj.enabled = false; - typename t_storage::hsection hchild_section = stg.open_section(pname, hparent_section, false); - if(!hchild_section) return false; - obj.enabled = true; - return obj.v._load(stg, hchild_section); - } - //------------------------------------------------------------------------------------------------------------------- template<class stl_container, class t_storage> static bool serialize_stl_container_t_val (const stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) { diff --git a/contrib/epee/include/serialization/serialize_base.h b/contrib/epee/include/serialization/serialize_base.h deleted file mode 100644 index 84a1624cb..000000000 --- a/contrib/epee/include/serialization/serialize_base.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once - diff --git a/contrib/epee/include/service_impl_base.h b/contrib/epee/include/service_impl_base.h deleted file mode 100644 index 6e9aefc46..000000000 --- a/contrib/epee/include/service_impl_base.h +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _SERVICE_IMPL_BASE_H_ -#define _SERVICE_IMPL_BASE_H_ - -#pragma comment(lib, "advapi32.lib") - - -namespace epee -{ -class service_impl_base { - public: - service_impl_base(); - virtual ~service_impl_base(); - - virtual const char *get_name() = 0; - virtual const char *get_caption() = 0; - virtual const char *get_description() = 0; - - bool run_service(); - virtual bool install(); - virtual bool remove(); - virtual bool init(); - void set_control_accepted(unsigned controls); - void set_status(unsigned state, unsigned pending = 0); - unsigned get_control_accepted(); - - private: - virtual void service_main() = 0; - virtual unsigned service_handler(unsigned control, unsigned event_code, - void *pdata) = 0; - //------------------------------------------------------------------------- - static service_impl_base*& instance(); - //------------------------------------------------------------------------- - static DWORD __stdcall _service_handler(DWORD control, DWORD event, - void *pdata, void *pcontext); - static void __stdcall service_entry(DWORD argc, char **pargs); - virtual SERVICE_FAILURE_ACTIONSA* get_failure_actions(); - - private: - SC_HANDLE m_manager; - SC_HANDLE m_service; - SERVICE_STATUS_HANDLE m_status_handle; - DWORD m_accepted_control; -}; - -inline service_impl_base::service_impl_base() { - m_manager = 0; - m_service = 0; - m_status_handle = 0; - m_accepted_control = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN - | SERVICE_ACCEPT_PAUSE_CONTINUE; - - instance() = this; -} -//----------------------------------------------------------------------------- -inline service_impl_base::~service_impl_base() { - if (m_service) { - ::CloseServiceHandle(m_service); - } - m_service = 0; - if (m_manager) { - ::CloseServiceHandle(m_manager); - } - m_manager = 0; - instance() = 0; -} -//----------------------------------------------------------------------------- -inline service_impl_base*& service_impl_base::instance() { - static service_impl_base *pservice = NULL; - return pservice; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::install() { - CHECK_AND_ASSERT(!m_service, false); - const char *psz_descr = get_description(); - SERVICE_FAILURE_ACTIONSA* fail_acts = get_failure_actions(); - - char sz_path[MAX_PATH]; - ::GetModuleFileNameA(0, sz_path, sizeof(sz_path)); - ::GetShortPathNameA(sz_path, sz_path, sizeof(sz_path)); - - while (TRUE) { - if (!m_manager) { - m_manager = ::OpenSCManager(NULL, NULL, GENERIC_ALL); - if (!m_manager) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - m_service = ::CreateServiceA(m_manager, get_name(), get_caption(), - SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, - SERVICE_ERROR_IGNORE, sz_path, 0, 0, 0, 0, 0); - if (!m_service) { - int err = GetLastError(); - LOG_ERROR( - "Failed to CreateService(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - - if (psz_descr) { - SERVICE_DESCRIPTIONA sd = { (char*) psz_descr }; - if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_DESCRIPTION, - &sd)) { - int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_DESCRIPTION), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (fail_acts) { - if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_FAILURE_ACTIONS, - fail_acts)) { - int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_FAILURE_ACTIONS), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - LOG_PRINT("Installed succesfully.", LOG_LEVEL_0); - return true; - } - LOG_PRINT("Failed to install.", LOG_LEVEL_0); - return false; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::remove() { - CHECK_AND_ASSERT(!m_service, false); - - while (TRUE) { - if (!m_manager) { - m_manager = ::OpenSCManager(0, 0, GENERIC_ALL); - if (!m_manager) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (!m_service) { - m_service = ::OpenServiceA(m_manager, get_name(), SERVICE_STOP | DELETE); - if (!m_service) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenService(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - SERVICE_STATUS status = { }; - if (!::ControlService(m_service, SERVICE_CONTROL_STOP, &status)) { - int err = ::GetLastError(); - if (err == ERROR_SHUTDOWN_IN_PROGRESS) - continue; - else if (err != ERROR_SERVICE_NOT_ACTIVE) { - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (!::DeleteService(m_service)) { - int err = ::GetLastError(); - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - - LOG_PRINT("Removed successfully.", LOG_LEVEL_0); - break; - } - - return true; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::init() { - return true; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::run_service() { - CHECK_AND_ASSERT(!m_service, false); - - long error_code = 0; - - SERVICE_TABLE_ENTRYA service_table[2]; - ZeroMemory(&service_table, sizeof(service_table)); - - service_table->lpServiceName = (char*) get_name(); - service_table->lpServiceProc = service_entry; - - LOG_PRINT("[+] Start service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); - - error_code = 1; - BOOL res = ::StartServiceCtrlDispatcherA(service_table); - if (!res) { - int err = GetLastError(); - LOG_PRINT( - "[+] Error starting service control dispatcher, err=" - << log_space::get_win32_err_descr(err), LOG_LEVEL_1); - return false; - } else { - LOG_PRINT("[+] End service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); - } - return true; -} -//----------------------------------------------------------------------------- -inline DWORD __stdcall service_impl_base::_service_handler(DWORD control, - DWORD event, void *pdata, void *pcontext) { - CHECK_AND_ASSERT(pcontext, ERROR_CALL_NOT_IMPLEMENTED); - - service_impl_base *pservice = (service_impl_base*) pcontext; - return pservice->service_handler(control, event, pdata); -} -//----------------------------------------------------------------------------- -inline -void __stdcall service_impl_base::service_entry(DWORD argc, char **pargs) { - service_impl_base *pme = instance(); - LOG_PRINT("instance: " << pme, LOG_LEVEL_4); - if (!pme) { - LOG_ERROR("Error: at service_entry() pme = NULL"); - return; - } - pme->m_status_handle = ::RegisterServiceCtrlHandlerExA(pme->get_name(), - _service_handler, pme); - - pme->set_status(SERVICE_RUNNING); - pme->service_main(); - pme->set_status(SERVICE_STOPPED); -} -//----------------------------------------------------------------------------- -inline -void service_impl_base::set_status(unsigned state, unsigned pending) { - if (!m_status_handle) - return; - - SERVICE_STATUS status = { 0 }; - status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - status.dwCurrentState = state; - status.dwControlsAccepted = m_accepted_control; - /*status.dwWin32ExitCode = NO_ERROR; - status.dwServiceSpecificExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - status.dwCheckPoint = 0; - status.dwWaitHint = 0; - - status.dwCurrentState = state;*/ - - if (state == SERVICE_START_PENDING || state == SERVICE_STOP_PENDING - || state == SERVICE_CONTINUE_PENDING || state == SERVICE_PAUSE_PENDING) { - status.dwWaitHint = 2000; - status.dwCheckPoint = pending; - } - ::SetServiceStatus(m_status_handle, &status); -} -//----------------------------------------------------------------------------------------- -inline -void service_impl_base::set_control_accepted(unsigned controls) { - m_accepted_control = controls; -} -//----------------------------------------------------------------------------------------- -inline -unsigned service_impl_base::get_control_accepted() { - return m_accepted_control; -} -//----------------------------------------------------------------------------------------- -inline SERVICE_FAILURE_ACTIONSA* service_impl_base::get_failure_actions() { - // first 3 failures in 30 minutes. Service will be restarted. - // do nothing for next failures - static SC_ACTION sa[] = { { SC_ACTION_RESTART, 3 * 1000 }, { - SC_ACTION_RESTART, 3 * 1000 }, { SC_ACTION_RESTART, 3 * 1000 }, { - SC_ACTION_NONE, 0 } }; - - static SERVICE_FAILURE_ACTIONSA sfa = { 1800, // interval for failures counter - 30 min - "", NULL, 4, (SC_ACTION*) &sa }; - - // TODO: refactor this code, really unsafe! - return &sfa; -} -} - -#endif //_SERVICE_IMPL_BASE_H_ diff --git a/contrib/epee/include/sha1.h b/contrib/epee/include/sha1.h deleted file mode 100644 index ce42082f8..000000000 --- a/contrib/epee/include/sha1.h +++ /dev/null @@ -1,51 +0,0 @@ - -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SHA1_DEFINED -#define SHA1_DEFINED - -namespace sha1 { - - /** - @param src points to any kind of data to be hashed. - @param bytelength the number of bytes to hash from the src pointer. - @param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in. - */ - void calc(const void* src, const int bytelength, unsigned char* hash); - - /** - @param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function. - @param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string. - */ - void toHexString(const unsigned char* hash, char* hexstring); - -} // namespace sha1 - -#include "sha1.inl" - -#endif // SHA1_DEFINED diff --git a/contrib/epee/include/sha1.inl b/contrib/epee/include/sha1.inl deleted file mode 100644 index d33202724..000000000 --- a/contrib/epee/include/sha1.inl +++ /dev/null @@ -1,179 +0,0 @@ - -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - Contributors: - Gustav - Several members in the gamedev.se forum. - Gregory Petrosyan - */ - -#include "sha1.h" - -namespace sha1 { -namespace {// local -// Rotate an integer value to left. -inline const unsigned int rol(const unsigned int value, - const unsigned int steps) { - return ((value << steps) | (value >> (32 - steps))); -} - -// Sets the first 16 integers in the buffert to zero. -// Used for clearing the W buffert. -inline void clearWBuffert(unsigned int* buffert) { - for (int pos = 16; --pos >= 0;) - { - buffert[pos] = 0; - } -} - -inline -void innerHash(unsigned int* result, unsigned int* w) { - unsigned int a = result[0]; - unsigned int b = result[1]; - unsigned int c = result[2]; - unsigned int d = result[3]; - unsigned int e = result[4]; - - int round = 0; - -#define sha1macro(func,val) \ - { \ - const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \ - e = d; \ - d = c; \ - c = rol(b, 30); \ - b = a; \ - a = t; \ - } - - while (round < 16) { - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 20) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 40) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0x6ed9eba1) - ++round; - } - while (round < 60) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc) - ++round; - } - while (round < 80) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0xca62c1d6) - ++round; - } - -#undef sha1macro - - result[0] += a; - result[1] += b; - result[2] += c; - result[3] += d; - result[4] += e; -} -} // namespace - -inline -void calc(const void* src, const int bytelength, unsigned char* hash) { - // Init the result array. - unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, - 0xc3d2e1f0 }; - - // Cast the void src pointer to be the byte array we can work with. - const unsigned char* sarray = (const unsigned char*) src; - - // The reusable round buffer - unsigned int w[80]; - - // Loop through all complete 64byte blocks. - const int endOfFullBlocks = bytelength - 64; - int endCurrentBlock; - int currentBlock(0); - - while (currentBlock <= endOfFullBlocks) { - endCurrentBlock = currentBlock + 64; - - // Init the round buffer with the 64 byte block data. - for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4) - { - // This line will swap endian on big endian and keep endian on little endian. - w[roundPos++] = (unsigned int) sarray[currentBlock + 3] - | (((unsigned int) sarray[currentBlock + 2]) << 8) - | (((unsigned int) sarray[currentBlock + 1]) << 16) - | (((unsigned int) sarray[currentBlock]) << 24); - } - innerHash(result, w); - } - - // Handle the last and not full 64 byte block if existing. - endCurrentBlock = bytelength - currentBlock; - clearWBuffert(w); - int lastBlockBytes = 0; - for (; lastBlockBytes < endCurrentBlock; ++lastBlockBytes) { - w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes - + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3); - } - w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3); - if (endCurrentBlock >= 56) { - innerHash(result, w); - clearWBuffert(w); - } - w[15] = bytelength << 3; - innerHash(result, w); - - // Store hash in result pointer, and make sure we get in in the correct order on both endian models. - for (int hashByte = 20; --hashByte >= 0;) { - hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) - & 0xff; - } -} -inline -void toHexString(const unsigned char* hash, char* hexstring) { - const char hexDigits[] = { "0123456789abcdef" }; - - for (int hashByte = 20; --hashByte >= 0;) - { - hexstring[hashByte << 1] = hexDigits[(hash[hashByte] >> 4) & 0xf]; - hexstring[(hashByte << 1) + 1] = hexDigits[hash[hashByte] & 0xf]; - } - hexstring[40] = 0; -} -} // namespace sha1 diff --git a/contrib/epee/include/soci_helper.h b/contrib/epee/include/soci_helper.h deleted file mode 100644 index 1da5aa7e2..000000000 --- a/contrib/epee/include/soci_helper.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -#include "soci.h" -#include "soci-postgresql.h" - -using namespace epee; -namespace soci -{ - - template <> - struct type_conversion<uint64_t> - { - typedef long long base_type; - - static void from_base(base_type a_, indicator ind, uint64_t & mi) - { - if (ind == i_null) - { - mi = 0; - //throw soci_error("Null value not allowed for this type"); - } - mi = (uint64_t)a_; - //mi.set(i); - } - - static void to_base(const uint64_t & mi, base_type & i, indicator & ind) - { - i = (base_type)mi; - ind = i_ok; - } - }; - - - - template <> - struct type_conversion<bool> - { - typedef int base_type; - - static void from_base(base_type a_, indicator ind, bool& mi) - { - if (ind == i_null) - { - mi = false; - //throw soci_error("Null value not allowed for this type"); - } - mi = a_? true:false; - //mi.set(i); - } - - static void to_base(const bool & mi, base_type & i, indicator & ind) - { - i = mi? 1:0; - ind = i_ok; - } - }; - - - - class per_thread_session - { - public: - bool init(const std::string& connection_string) - { - m_connection_string = connection_string; - - return true; - } - - soci::session& get() - { - - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr<soci::session>& conn_ptr = m_db_connections[epee::misc_utils::get_thread_string_id()]; - m_db_connections_lock.unlock(); - if(!conn_ptr.get()) - { - conn_ptr.reset(new soci::session(soci::postgresql, m_connection_string)); - } - //init new connection - return *conn_ptr.get(); - } - - bool reopen() - { - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr<soci::session>& conn_ptr = m_db_connections[misc_utils::get_thread_string_id()]; - m_db_connections_lock.unlock(); - if(conn_ptr.get()) - { - conn_ptr->close(); - conn_ptr.reset(new soci::session(soci::postgresql, m_connection_string)); - } - - //init new connection - return true; - } - - //---------------------------------------------------------------------------------------------- - bool check_status() - { - return true; - } - - protected: - private: - std::map<std::string, boost::shared_ptr<soci::session> > m_db_connections; - epee::critical_section m_db_connections_lock; - std::string m_connection_string; - }; -} -/*}*/ diff --git a/contrib/epee/include/span.h b/contrib/epee/include/span.h index 26861f994..99c2ebb4f 100644 --- a/contrib/epee/include/span.h +++ b/contrib/epee/include/span.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/static_initializer.h b/contrib/epee/include/static_initializer.h deleted file mode 100644 index 3463a5607..000000000 --- a/contrib/epee/include/static_initializer.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _STATIC_INITIALIZER_H_ -#define _STATIC_INITIALIZER_H_ - - -namespace epee -{ -/*********************************************************************** -class initializer - useful to initialize some static classes - which have init() and un_init() static members -************************************************************************/ - -template<class to_initialize> -class initializer -{ -public: - initializer() - { - to_initialize::init(); - //get_set_is_initialized(true, true); - } - ~initializer() - { - to_initialize::un_init(); - //get_set_is_uninitialized(true, true); - } - - /*static inline bool is_initialized() - { - return get_set_is_initialized(); - } - static inline bool is_uninitialized() - { - return get_set_is_uninitialized(); - } - -private: - static inline bool get_set_is_initialized(bool need_to_set = false, bool val_to_set= false) - { - static bool val_is_initialized = false; - if(need_to_set) - val_is_initialized = val_to_set; - return val_is_initialized; - } - static inline bool get_set_is_uninitialized(bool need_to_set = false, bool val_to_set = false) - { - static bool val_is_uninitialized = false; - if(need_to_set) - val_is_uninitialized = val_to_set; - return val_is_uninitialized; - }*/ -}; - -} -#endif //_STATIC_INITIALIZER_H_ diff --git a/contrib/epee/include/storages/crypted_storage.h b/contrib/epee/include/storages/crypted_storage.h deleted file mode 100644 index 163728cfc..000000000 --- a/contrib/epee/include/storages/crypted_storage.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _CRYPTED_STORAGE_H_ -#define _CRYPTED_STORAGE_H_ - -#include "cryptopp_helper.h" - -namespace epee -{ -template<class t_base_storage, class crypt_provider, class t_key_provider> -class crypted_storage: public t_base_storage -{ -public: - size_t PackToSolidBuffer(std::string& targetObj) - { - size_t res = t_base_storage::PackToSolidBuffer(targetObj); - if(res <= 0) - return res; - - if(!crypt_provider::encrypt(targetObj, t_key_provider::get_storage_default_key())) - return 0; - - return targetObj.size(); - } - - size_t LoadFromSolidBuffer(const std::string& pTargetObj) - { - std::string buff_to_decrypt = pTargetObj; - if(crypt_provider::decrypt(buff_to_decrypt, t_key_provider::get_storage_default_key())) - return t_base_storage::LoadFromSolidBuffer(buff_to_decrypt); - - return 0; - } -}; -} - -#endif //_CRYPTED_STORAGE_H_ diff --git a/contrib/epee/include/storages/gzipped_inmemstorage.h b/contrib/epee/include/storages/gzipped_inmemstorage.h deleted file mode 100644 index 229a56da6..000000000 --- a/contrib/epee/include/storages/gzipped_inmemstorage.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _GZIPPED_INMEMSTORAGE_H_ -#define _GZIPPED_INMEMSTORAGE_H_ - -#include "zlib_helper.h" -namespace epee -{ -namespace StorageNamed -{ - - template<class t_base_storage> - class gziped_storage: public t_base_storage - { - public: - size_t PackToSolidBuffer(std::string& targetObj) - { - size_t res = t_base_storage::PackToSolidBuffer(targetObj); - if(res <= 0) - return res; - - if(!zlib_helper::pack(targetObj)) - return 0; - - return targetObj.size(); - } - - size_t LoadFromSolidBuffer(const std::string& pTargetObj) - { - std::string buff_to_ungzip = pTargetObj; - if(zlib_helper::unpack(buff_to_ungzip)) - return t_base_storage::LoadFromSolidBuffer(buff_to_ungzip); - - return 0; - } - - private: - }; - -} -} - -#endif diff --git a/contrib/epee/include/storages/levin_abstract_invoke2.h b/contrib/epee/include/storages/levin_abstract_invoke2.h index 383d67cc2..7fd786a53 100644 --- a/contrib/epee/include/storages/levin_abstract_invoke2.h +++ b/contrib/epee/include/storages/levin_abstract_invoke2.h @@ -56,54 +56,6 @@ namespace epee { namespace net_utils { -#if 0 - template<class t_arg, class t_result, class t_transport> - bool invoke_remote_command2(int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) - { - if(!transport.is_connected()) - return false; - - serialization::portable_storage stg; - out_struct.store(stg); - std::string buff_to_send, buff_to_recv; - stg.store_to_binary(buff_to_send); - - int res = transport.invoke(command, buff_to_send, buff_to_recv); - if( res <=0 ) - { - MERROR("Failed to invoke command " << command << " return code " << res); - return false; - } - serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff_to_recv, &default_levin_limits)) - { - LOG_ERROR("Failed to load_from_binary on command " << command); - return false; - } - return result_struct.load(stg_ret); - } - - template<class t_arg, class t_transport> - bool notify_remote_command2(int command, const t_arg& out_struct, t_transport& transport) - { - if(!transport.is_connected()) - return false; - - serialization::portable_storage stg; - out_struct.store(&stg); - std::string buff_to_send; - stg.store_to_binary(buff_to_send); - - int res = transport.notify(command, buff_to_send); - if(res <=0 ) - { - LOG_ERROR("Failed to notify command " << command << " return code " << res); - return false; - } - return true; - } -#endif - template<class t_arg, class t_result, class t_transport> bool invoke_remote_command2(const epee::net_utils::connection_context_base context, int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) { diff --git a/contrib/epee/include/storages/parserse_base_utils.h b/contrib/epee/include/storages/parserse_base_utils.h index e59cbcf5f..898813ff9 100644 --- a/contrib/epee/include/storages/parserse_base_utils.h +++ b/contrib/epee/include/storages/parserse_base_utils.h @@ -107,48 +107,10 @@ namespace misc_utils */ void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val); - inline bool match_string(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - try - { - match_string2(star_end_string, buf_end, val); - return true; - } - catch(...) - { - return false; - } - } void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val, bool& is_float_val, bool& is_signed_val); - inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) - { - try - { - bool is_v_float = false;bool is_signed_val = false; - match_number2(star_end_string, buf_end, val, is_v_float, is_signed_val); - return !is_v_float; - } - catch(...) - { - return false; - } - } + void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val); - inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) - { - try - { - match_word2(star_end_string, buf_end, val); - return true; - } - catch(...) - { - return false; - } - } - bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val); - bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end); } } } diff --git a/contrib/epee/include/storages/portable_storage_bin_utils.h b/contrib/epee/include/storages/portable_storage_bin_utils.h index b2b4bc56c..476c81ea1 100644 --- a/contrib/epee/include/storages/portable_storage_bin_utils.h +++ b/contrib/epee/include/storages/portable_storage_bin_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/storages/portable_storage_to_bin.h b/contrib/epee/include/storages/portable_storage_to_bin.h index a68a08f69..70757607e 100644 --- a/contrib/epee/include/storages/portable_storage_to_bin.h +++ b/contrib/epee/include/storages/portable_storage_to_bin.h @@ -28,7 +28,6 @@ #pragma once -#include "pragma_comp_defs.h" #include "misc_language.h" #include "portable_storage_base.h" #include "portable_storage_bin_utils.h" @@ -49,12 +48,7 @@ namespace epee return sizeof(pack_value); } - PRAGMA_WARNING_PUSH - PRAGMA_GCC("GCC diagnostic ignored \"-Wstrict-aliasing\"") -#ifdef __clang__ - PRAGMA_GCC("GCC diagnostic ignored \"-Wtautological-constant-out-of-range-compare\"") -#endif - template<class t_stream> + template<class t_stream> size_t pack_varint(t_stream& strm, size_t val) { //the first two bits always reserved for size information @@ -70,13 +64,13 @@ namespace epee return pack_varint_t<uint32_t>(strm, PORTABLE_RAW_SIZE_MARK_DWORD, val); }else { - CHECK_AND_ASSERT_THROW_MES(val <= 4611686018427387903, "failed to pack varint - too big amount = " << val); + // Same as checking val <= 4611686018427387903 except that it's portable for 32-bit size_t + CHECK_AND_ASSERT_THROW_MES(!(val >> 31 >> 31), "failed to pack varint - too big amount = " << val); return pack_varint_t<uint64_t>(strm, PORTABLE_RAW_SIZE_MARK_INT64, val); } } - PRAGMA_WARNING_POP - template<class t_stream> + template<class t_stream> bool put_string(t_stream& strm, const std::string& v) { pack_varint(strm, v.size()); diff --git a/contrib/epee/include/time_helper.h b/contrib/epee/include/time_helper.h index 244b35800..b306880d9 100644 --- a/contrib/epee/include/time_helper.h +++ b/contrib/epee/include/time_helper.h @@ -28,132 +28,60 @@ #pragma once -//#include <atltime.h> -//#include <sqlext.h> -#include <boost/date_time/posix_time/posix_time.hpp> -#include <boost/date_time/local_time/local_time.hpp> -#include "pragma_comp_defs.h" +#include <chrono> +#include <cstdio> +#include <ctime> +#include <string> namespace epee { namespace misc_utils { - -#ifdef __ATLTIME_H__ - - inline - bool get_time_t_from_ole_date(DATE src, time_t& res) + inline bool get_gmt_time(time_t t, struct tm &tm) { - SYSTEMTIME st = {0}; - if(TRUE != ::VariantTimeToSystemTime(src, &st)) - return false; - ATL::CTime ss(st); - res = ss.GetTime(); - return true; - } +#ifdef _WIN32 + return gmtime_s(&tm, &t); +#else + return gmtime_r(&t, &tm); #endif - inline - std::string get_time_str(const time_t& time_) - { - - - char tmpbuf[200] = {0}; - tm* pt = NULL; -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4996) - pt = localtime(&time_); -PRAGMA_WARNING_POP - - if(pt) - strftime( tmpbuf, 199, "%d.%m.%Y %H:%M:%S", pt ); - else - { - std::stringstream strs; - strs << "[wrong_time: " << std::hex << time_ << "]"; - return strs.str(); - } - return tmpbuf; } - inline - std::string get_time_str_v2(const time_t& time_) - { - - char tmpbuf[200] = {0}; - tm* pt = NULL; -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4996) - pt = localtime(&time_); -PRAGMA_WARNING_POP - - if(pt) - strftime( tmpbuf, 199, "%Y_%m_%d %H_%M_%S", pt ); - else - { - std::stringstream strs; - strs << "[wrong_time: " << std::hex << time_ << "]"; - return strs.str(); - } - return tmpbuf; - } - - inline - std::string get_time_str_v3(const boost::posix_time::ptime& time_) - { - return boost::posix_time::to_simple_string(time_); - } - - - inline std::string get_internet_time_str(const time_t& time_) { char tmpbuf[200] = {0}; - tm* pt = NULL; -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4996) - pt = gmtime(&time_); -PRAGMA_WARNING_POP - strftime( tmpbuf, 199, "%a, %d %b %Y %H:%M:%S GMT", pt ); + struct tm pt; + get_gmt_time(time_, pt); + strftime(tmpbuf, 199, "%a, %d %b %Y %H:%M:%S GMT", &pt); return tmpbuf; } inline std::string get_time_interval_string(const time_t& time_) { - std::string res; time_t tail = time_; -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4244) - int days = tail/(60*60*24); + const int days = static_cast<int>(tail/(60*60*24)); tail = tail%(60*60*24); - int hours = tail/(60*60); + const int hours = static_cast<int>(tail/(60*60)); tail = tail%(60*60); - int minutes = tail/(60); + const int minutes = static_cast<int>(tail/60); tail = tail%(60); - int seconds = tail; -PRAGMA_WARNING_POP - res = std::string() + "d" + boost::lexical_cast<std::string>(days) + ".h" + boost::lexical_cast<std::string>(hours) + ".m" + boost::lexical_cast<std::string>(minutes) + ".s" + boost::lexical_cast<std::string>(seconds); - return res; + const int seconds = static_cast<int>(tail); + + char tmpbuf[64] = {0}; + snprintf(tmpbuf, sizeof(tmpbuf) - 1, "d%d.h%d.m%d.s%d", days, hours, minutes, seconds); + + return tmpbuf; } -#ifdef __SQLEXT - inline - bool odbc_time_to_oledb_taime(const SQL_TIMESTAMP_STRUCT& odbc_timestamp, DATE& oledb_date) + inline uint64_t get_ns_count() { - - SYSTEMTIME st = {0}; - st.wYear = odbc_timestamp.year; - st.wDay = odbc_timestamp.day; - st.wHour = odbc_timestamp.hour ; - st.wMilliseconds = (WORD)odbc_timestamp.fraction ; - st.wMinute = odbc_timestamp.minute ; - st.wMonth = odbc_timestamp.month ; - st.wSecond = odbc_timestamp.second ; - - if(TRUE != ::SystemTimeToVariantTime(&st, &oledb_date)) - return false; - return true; + typedef std::chrono::duration<uint64_t, std::nano> ns_duration; + const ns_duration ns_since_epoch = std::chrono::steady_clock::now().time_since_epoch(); + return ns_since_epoch.count(); } -#endif + inline uint64_t get_tick_count() + { + return get_ns_count() / 1000000; + } } } diff --git a/contrib/epee/include/tiny_ini.h b/contrib/epee/include/tiny_ini.h deleted file mode 100644 index 6ced548eb..000000000 --- a/contrib/epee/include/tiny_ini.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _TINY_INI_H_ -#define _TINY_INI_H_ - -#include "string_tools.h" - -namespace epee -{ -namespace tiny_ini -{ - - bool get_param_value(const std::string& param_name, const std::string& ini_entry, std::string& res); - inline std::string get_param_value(const std::string& param_name, const std::string& ini_entry) - { - std::string buff; - get_param_value(param_name, ini_entry, buff); - return buff; - } - - template<class T> - bool get_param_value_as_t(const std::string& param_name, const std::string& ini_entry, T& res) - { - std::string str_res = get_param_value(param_name, ini_entry); - - string_tools::trim(str_res); - if(!str_res.size()) - return false; - - return string_tools::get_xtype_from_string(res, str_res); - } - -} -} - -#endif //_TINY_INI_H_ diff --git a/contrib/epee/include/to_nonconst_iterator.h b/contrib/epee/include/to_nonconst_iterator.h deleted file mode 100644 index 729b0e8b2..000000000 --- a/contrib/epee/include/to_nonconst_iterator.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _TO_NONCONST_ITERATOR_H_ -#define _TO_NONCONST_ITERATOR_H_ - -namespace epee -{ - -template<class Type> -typename Type::iterator to_nonsonst_iterator(Type& obj, typename Type::const_iterator it) -{ - typename Type::difference_type dist = std::distance(static_cast<typename Type::const_iterator>(obj.begin()), it); - typename Type::iterator res_it = obj.begin()+dist; - return res_it; -} - - -template<class Type> -typename Type::iterator to_nonsonst_iterator(typename Type::iterator base_it, typename Type::const_iterator it) -{ - typename Type::difference_type dist = std::distance(static_cast<typename Type::const_iterator>(base_it), it); - typename Type::iterator res_it = base_it+dist; - return res_it; -} -}//namespace epee -#endif //_TO_NONCONST_ITERATOR_H_ diff --git a/contrib/epee/include/winobj.h b/contrib/epee/include/winobj.h deleted file mode 100644 index 3279cdac6..000000000 --- a/contrib/epee/include/winobj.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef __WINH_OBJ_H__ -#define __WINH_OBJ_H__ - -#include <boost/thread/locks.hpp> - -namespace epee -{ -class critical_region; - -class critical_section { - - boost::mutex m_section; - -public: - - critical_section( const critical_section& section ) { - InitializeCriticalSection( &m_section ); - } - - critical_section() { - InitializeCriticalSection( &m_section ); - } - - ~critical_section() { - DeleteCriticalSection( &m_section ); - } - - void lock() { - EnterCriticalSection( &m_section ); - } - - void unlock() { - LeaveCriticalSection( &m_section ); - } - - bool tryLock() { - return TryEnterCriticalSection( &m_section )? true:false; - } - - critical_section& operator=( const critical_section& section ) - { - return *this; - } - - -}; - -class critical_region { - - ::critical_section *m_locker; - - critical_region( const critical_region& ){} - -public: - - critical_region(critical_section &cs ) { - m_locker = &cs; - cs.lock(); - } - - ~critical_region() - { - m_locker->unlock(); - } -}; - - -class shared_critical_section -{ -public: - shared_critical_section() - { - ::InitializeSRWLock(&m_srw_lock); - } - ~shared_critical_section() - {} - - bool lock_shared() - { - AcquireSRWLockShared(&m_srw_lock); - return true; - } - bool unlock_shared() - { - ReleaseSRWLockShared(&m_srw_lock); - return true; - } - bool lock_exclusive() - { - ::AcquireSRWLockExclusive(&m_srw_lock); - return true; - } - bool unlock_exclusive() - { - ::ReleaseSRWLockExclusive(&m_srw_lock); - return true; - } -private: - SRWLOCK m_srw_lock; - -}; - - -class shared_guard -{ -public: - shared_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_shared(); - } - - ~shared_guard() - { - m_ref_sec.unlock_shared(); - } - -private: - shared_critical_section& m_ref_sec; -}; - - -class exclusive_guard -{ -public: - exclusive_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_exclusive(); - } - - ~exclusive_guard() - { - m_ref_sec.unlock_exclusive(); - } - -private: - shared_critical_section& m_ref_sec; -}; - - -class event -{ -public: - event() - { - m_hevent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - } - ~event() - { - ::CloseHandle(m_hevent); - - } - - bool set() - { - return ::SetEvent(m_hevent) ? true:false; - } - - bool reset() - { - return ::ResetEvent(m_hevent) ? true:false; - } - - HANDLE get_handle() - { - return m_hevent; - } -private: - HANDLE m_hevent; - -}; - - -#define SHARED_CRITICAL_REGION_BEGIN(x) { shared_guard critical_region_var(x) -#define EXCLUSIVE_CRITICAL_REGION_BEGIN(x) { exclusive_guard critical_region_var(x) - - - -#define CRITICAL_REGION_LOCAL(x) critical_region critical_region_var(x) -#define CRITICAL_REGION_BEGIN(x) { critical_region critical_region_var(x) -#define CRITICAL_REGION_END() } - - - inline const char* get_wait_for_result_as_text(DWORD res) - { - switch(res) - { - case WAIT_ABANDONED: return "WAIT_ABANDONED"; - case WAIT_TIMEOUT: return "WAIT_TIMEOUT"; - case WAIT_OBJECT_0: return "WAIT_OBJECT_0"; - case WAIT_OBJECT_0+1: return "WAIT_OBJECT_1"; - case WAIT_OBJECT_0+2: return "WAIT_OBJECT_2"; - default: - return "UNKNOWN CODE"; - } - - } - -}// namespace epee - -#endif diff --git a/contrib/epee/include/wipeable_string.h b/contrib/epee/include/wipeable_string.h index 22c30855f..65977cd97 100644 --- a/contrib/epee/include/wipeable_string.h +++ b/contrib/epee/include/wipeable_string.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/zlib_helper.h b/contrib/epee/include/zlib_helper.h deleted file mode 100644 index 46c7f48e6..000000000 --- a/contrib/epee/include/zlib_helper.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -extern "C" { -#include "zlib/zlib.h" -} -#pragma comment(lib, "zlibstat.lib") - -namespace epee -{ -namespace zlib_helper -{ - inline - bool pack(std::string& target){ - std::string result_packed_buff; - - z_stream zstream = {0}; - int ret = deflateInit(&zstream, Z_DEFAULT_COMPRESSION); - if(target.size()) - { - - - result_packed_buff.resize(target.size()*2, 'X'); - - zstream.next_in = (Bytef*)target.data(); - zstream.avail_in = (uInt)target.size(); - zstream.next_out = (Bytef*)result_packed_buff.data(); - zstream.avail_out = (uInt)result_packed_buff.size(); - - ret = deflate(&zstream, Z_FINISH); - CHECK_AND_ASSERT_MES(ret>=0, false, "Failed to deflate. err = " << ret); - - if(result_packed_buff.size() != zstream.avail_out) - result_packed_buff.resize(result_packed_buff.size()-zstream.avail_out); - - - result_packed_buff.erase(0, 2); - target.swap(result_packed_buff); - } - - deflateEnd(& zstream ); - return true; - } - - inline bool unpack(std::string& target) - { - z_stream zstream = {0}; - int ret = inflateInit(&zstream);// - - std::string decode_summary_buff; - size_t ungzip_buff_size = target.size() * 0x30; - std::string current_decode_buff(ungzip_buff_size, 'X'); - - while(target.size()) - { - - - zstream.next_out = (Bytef*)current_decode_buff.data(); - zstream.avail_out = (uInt)ungzip_buff_size; - - int flag = Z_SYNC_FLUSH; - - static char dummy_head[2] = - { - 0x8 + 0x7 * 0x10, - (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, - }; - zstream.next_in = (Bytef*) dummy_head; - zstream.avail_in = sizeof(dummy_head); - ret = inflate(&zstream, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - return false; - } - - zstream.next_in = (Bytef*)target.data(); - zstream.avail_in = (uInt)target.size(); - - ret = inflate(&zstream, Z_SYNC_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - LOCAL_ASSERT(0); - return false; - } - - - target.erase(0, target.size()-zstream.avail_in); - - - if(ungzip_buff_size == zstream.avail_out) - { - LOG_ERROR("Can't unpack buffer"); - return false; - } - - - current_decode_buff.resize(ungzip_buff_size - zstream.avail_out); - if(decode_summary_buff.size()) - decode_summary_buff += current_decode_buff; - else - current_decode_buff.swap(decode_summary_buff); - - current_decode_buff.resize(ungzip_buff_size); - } - - inflateEnd(&zstream ); - - decode_summary_buff.swap(target); - return 1; - } - -}; -}//namespace epee diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index 3fa2f7fb4..808b9f09e 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -35,11 +35,9 @@ monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_cli wipeable_string.cpp levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp int-util.cpp portable_storage.cpp misc_language.cpp - misc_os_dependent.cpp file_io_utils.cpp net_parse_helpers.cpp http_base.cpp - tiny_ini.cpp ${EPEE_HEADERS_PUBLIC} ) diff --git a/contrib/epee/src/buffer.cpp b/contrib/epee/src/buffer.cpp index cf94fb5d5..dd6619074 100644 --- a/contrib/epee/src/buffer.cpp +++ b/contrib/epee/src/buffer.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/contrib/epee/src/byte_slice.cpp b/contrib/epee/src/byte_slice.cpp index 430853c64..72aa39768 100644 --- a/contrib/epee/src/byte_slice.cpp +++ b/contrib/epee/src/byte_slice.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/byte_stream.cpp b/contrib/epee/src/byte_stream.cpp index 73bba92f2..b674b5fe0 100644 --- a/contrib/epee/src/byte_stream.cpp +++ b/contrib/epee/src/byte_stream.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index 30efbf2fc..b0a30f47f 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief base for connection, contains e.g. the ratelimit hooks -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -39,7 +39,6 @@ #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/thread/thread.hpp> #include "misc_language.h" -#include "pragma_comp_defs.h" #include <iomanip> #include <boost/asio/basic_socket.hpp> diff --git a/contrib/epee/src/file_io_utils.cpp b/contrib/epee/src/file_io_utils.cpp index 5072adcbc..a8348431c 100644 --- a/contrib/epee/src/file_io_utils.cpp +++ b/contrib/epee/src/file_io_utils.cpp @@ -102,29 +102,6 @@ namespace file_io_utils } - bool get_file_time(const std::string& path_to_file, time_t& ft) - { - boost::system::error_code ec; - ft = boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ec); - if(!ec) - return true; - else - return false; - } - - - bool set_file_time(const std::string& path_to_file, const time_t& ft) - { - boost::system::error_code ec; - boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ft, ec); - if(!ec) - return true; - else - return false; - } - - - bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size) { #ifdef WIN32 @@ -174,26 +151,6 @@ namespace file_io_utils } - bool append_string_to_file(const std::string& path_to_file, const std::string& str) - { - // No special Windows implementation because so far not used in Monero code - try - { - std::ofstream fstream; - fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - fstream.open(path_to_file.c_str(), std::ios_base::binary | std::ios_base::out | std::ios_base::app); - fstream << str; - fstream.close(); - return true; - } - - catch(...) - { - return false; - } - } - - bool get_file_size(const std::string& path_to_file, uint64_t &size) { #ifdef WIN32 diff --git a/contrib/epee/src/hex.cpp b/contrib/epee/src/hex.cpp index b53efe6b8..c62406c39 100644 --- a/contrib/epee/src/hex.cpp +++ b/contrib/epee/src/hex.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/http_auth.cpp b/contrib/epee/src/http_auth.cpp index 9f30e1975..98278cdfb 100644 --- a/contrib/epee/src/http_auth.cpp +++ b/contrib/epee/src/http_auth.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/int-util.cpp b/contrib/epee/src/int-util.cpp index 061c90b4e..3a2924c5a 100644 --- a/contrib/epee/src/int-util.cpp +++ b/contrib/epee/src/int-util.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/levin_base.cpp b/contrib/epee/src/levin_base.cpp index 7c5cd5a78..a64f2aa17 100644 --- a/contrib/epee/src/levin_base.cpp +++ b/contrib/epee/src/levin_base.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/memwipe.c b/contrib/epee/src/memwipe.c index 41a6b36ac..e96b94598 100644 --- a/contrib/epee/src/memwipe.c +++ b/contrib/epee/src/memwipe.c @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/misc_os_dependent.cpp b/contrib/epee/src/misc_os_dependent.cpp deleted file mode 100644 index cd4967131..000000000 --- a/contrib/epee/src/misc_os_dependent.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "misc_os_dependent.h" -#include <boost/lexical_cast.hpp> - -namespace epee -{ -namespace misc_utils -{ - // TODO: (vtnerd) This function is weird since boost::this_thread::get_id() exists but returns a different value. - std::string get_thread_string_id() - { -#if defined(_WIN32) - return boost::lexical_cast<std::string>(GetCurrentThreadId()); -#elif defined(__GNUC__) - return boost::lexical_cast<std::string>(pthread_self()); -#endif - } -} -} diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp index 446fa3315..ed71e386c 100644 --- a/contrib/epee/src/mlocker.cpp +++ b/contrib/epee/src/mlocker.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index bcde215be..092d41777 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -40,7 +40,7 @@ #include <boost/filesystem.hpp> #include <boost/algorithm/string.hpp> #include "string_tools.h" -#include "misc_os_dependent.h" +#include "time_helper.h" #include "misc_log_ex.h" #undef MONERO_DEFAULT_LOG_CATEGORY diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp index 70cd0d0ad..3a5db8187 100644 --- a/contrib/epee/src/net_ssl.cpp +++ b/contrib/epee/src/net_ssl.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp index f4ebeabf0..978572120 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief implementaion for throttling of connection (count and rate-limit speed etc) -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -46,7 +46,6 @@ #include "misc_log_ex.h" #include <boost/chrono.hpp> #include "misc_language.h" -#include "pragma_comp_defs.h" #include <sstream> #include <iomanip> #include <algorithm> diff --git a/contrib/epee/src/network_throttle.cpp b/contrib/epee/src/network_throttle.cpp index b2c861e30..3f250a542 100644 --- a/contrib/epee/src/network_throttle.cpp +++ b/contrib/epee/src/network_throttle.cpp @@ -26,7 +26,7 @@ Throttling work by: */ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/parserse_base_utils.cpp b/contrib/epee/src/parserse_base_utils.cpp index e96c2dede..e154a75f8 100644 --- a/contrib/epee/src/parserse_base_utils.cpp +++ b/contrib/epee/src/parserse_base_utils.cpp @@ -239,44 +239,6 @@ namespace misc_utils } ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); } - bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - val.clear(); - - for(std::string::const_iterator it = star_end_string;it != buf_end;++it) - { - if(!isalnum(*it) && *it != '-' && *it != '_') - { - val.assign(star_end_string, it); - if(val.size()) - { - star_end_string = --it; - return true; - }else - return false; - } - } - return false; - } - bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end) - { - word_end = star_end_string; - - for(std::string::const_iterator it = star_end_string;it != buf_end;++it) - { - if(isspace(*it)) - { - - continue; - }else if( *it == '=' ) - { - star_end_string = it; - word_end = it; - return true; - } - } - return false; - } } } } diff --git a/contrib/epee/src/tiny_ini.cpp b/contrib/epee/src/tiny_ini.cpp deleted file mode 100644 index 577ebf7c6..000000000 --- a/contrib/epee/src/tiny_ini.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "string_tools.h" -#include <boost/regex.hpp> - -namespace epee -{ -namespace tiny_ini -{ - bool get_param_value(const std::string& param_name, const std::string& ini_entry, std::string& res) - { - std::string expr_str = std::string() + "^("+ param_name +") *=(.*?)$"; - const boost::regex match_ini_entry( expr_str, boost::regex::icase | boost::regex::normal); - boost::smatch result; - if(!boost::regex_search(ini_entry, result, match_ini_entry, boost::match_default)) - return false; - res = result[2]; - string_tools::trim(res); - return true; - } -} -} diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp index 03cb05232..b016f2f48 100644 --- a/contrib/epee/src/wipeable_string.cpp +++ b/contrib/epee/src/wipeable_string.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/tests/.gitignore b/contrib/epee/tests/.gitignore deleted file mode 100644 index d9b4f015d..000000000 --- a/contrib/epee/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build/* diff --git a/contrib/epee/tests/data/storages/invalid_storage_1.bin b/contrib/epee/tests/data/storages/invalid_storage_1.bin Binary files differdeleted file mode 100644 index f64bef38e..000000000 --- a/contrib/epee/tests/data/storages/invalid_storage_1.bin +++ /dev/null diff --git a/contrib/epee/tests/data/storages/invalid_storage_2.bin b/contrib/epee/tests/data/storages/invalid_storage_2.bin Binary files differdeleted file mode 100644 index a8c29f155..000000000 --- a/contrib/epee/tests/data/storages/invalid_storage_2.bin +++ /dev/null diff --git a/contrib/epee/tests/data/storages/invalid_storage_3.bin b/contrib/epee/tests/data/storages/invalid_storage_3.bin deleted file mode 100644 index 4233bf25c..000000000 --- a/contrib/epee/tests/data/storages/invalid_storage_3.bin +++ /dev/null @@ -1 +0,0 @@ -IMm_bo diff --git a/contrib/epee/tests/data/storages/invalid_storage_4.bin b/contrib/epee/tests/data/storages/invalid_storage_4.bin Binary files differdeleted file mode 100644 index 69017244a..000000000 --- a/contrib/epee/tests/data/storages/invalid_storage_4.bin +++ /dev/null diff --git a/contrib/epee/tests/data/storages/valid_storage.bin b/contrib/epee/tests/data/storages/valid_storage.bin Binary files differdeleted file mode 100644 index 2af0abf50..000000000 --- a/contrib/epee/tests/data/storages/valid_storage.bin +++ /dev/null diff --git a/contrib/epee/tests/generate_vc_proj.bat b/contrib/epee/tests/generate_vc_proj.bat deleted file mode 100644 index 2b3fee953..000000000 --- a/contrib/epee/tests/generate_vc_proj.bat +++ /dev/null @@ -1,5 +0,0 @@ -mkdir build -cd build -cmake "-DBoost_USE_STATIC_LIBS=TRUE" -G "Visual Studio 11 Win64" ../src -cd .. -pause diff --git a/contrib/epee/tests/src/CMakeLists.txt b/contrib/epee/tests/src/CMakeLists.txt deleted file mode 100644 index e724b53f4..000000000 --- a/contrib/epee/tests/src/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ - -cmake_minimum_required(VERSION 3.5) - -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS OFF) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -set(Boost_USE_MULTITHREADED ON) - -include_directories(.) -include_directories(../../include) - -find_package(Boost COMPONENTS system filesystem thread date_time chrono regex) -include_directories( ${Boost_INCLUDE_DIRS} ) - -IF (MSVC) - add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /nologo /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /bigobj" ) - include_directories(SYSTEM platform/msvc) -ELSE() - # set stuff for other systems - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-reorder") -ENDIF() - - -# Add folders to filters -file(GLOB_RECURSE SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/*.inl - ${CMAKE_CURRENT_SOURCE_DIR}/*.h) - -source_group(general FILES ${SRC}) - - -add_executable(tests ${SRC} ) -target_link_libraries( tests ${Boost_LIBRARIES} ) - diff --git a/contrib/epee/tests/src/misc/test_math.h b/contrib/epee/tests/src/misc/test_math.h deleted file mode 100644 index 8b3064c2a..000000000 --- a/contrib/epee/tests/src/misc/test_math.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" - -namespace epee -{ - namespace tests - { - bool test_median() - { - LOG_PRINT_L0("Testing median"); - std::vector<size_t> sz; - size_t m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 0, false, "test failed"); - sz.push_back(1); - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 1, false, "test failed"); - sz.push_back(10); - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 5, false, "test failed"); - - sz.clear(); - sz.resize(3); - sz[0] = 0; - sz[1] = 9; - sz[2] = 3; - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 3, false, "test failed"); - - sz.clear(); - sz.resize(4); - sz[0] = 77; - sz[1] = 9; - sz[2] = 22; - sz[3] = 60; - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 41, false, "test failed"); - - - - sz.clear(); - sz.resize(5); - sz[0] = 77; - sz[1] = 9; - sz[2] = 22; - sz[3] = 60; - sz[4] = 11; - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 22, false, "test failed"); - return true; - } - } -} - diff --git a/contrib/epee/tests/src/net/test_net.h b/contrib/epee/tests/src/net/test_net.h deleted file mode 100644 index f99639afc..000000000 --- a/contrib/epee/tests/src/net/test_net.h +++ /dev/null @@ -1,408 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include <boost/thread.hpp> -#include <boost/bind.hpp> - -#include "net/abstract_tcp_server2.h" -#include "net/levin_protocol_handler.h" -#include "net/levin_protocol_handler_async.h" -#include "storages/abstract_invoke.h" - -namespace epee -{ -namespace StorageNamed -{ - typedef CInMemStorage DefaultStorageType; -} -namespace tests -{ - struct some_subdata - { - - std::string str1; - std::list<uint64_t> array_of_id; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_STL_ANSI_STRING(str1) - SERIALIZE_STL_CONTAINER_POD(array_of_id) - END_NAMED_SERIALIZE_MAP() - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_EXAMPLE_1 - { - const static int ID = 1000; - - struct request_t - { - - std::string example_string_data; - uint64_t example_id_data; - some_subdata sub; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_STL_ANSI_STRING(example_string_data) - SERIALIZE_POD(example_id_data) - SERIALIZE_T(sub) - END_NAMED_SERIALIZE_MAP() - }; - typedef epee::misc_utils::struct_init<request_t> request; - - struct response_t - { - bool m_success; - uint64_t example_id_data; - std::list<some_subdata> subs; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_POD(m_success) - SERIALIZE_POD(example_id_data) - SERIALIZE_STL_CONTAINER_T(subs) - END_NAMED_SERIALIZE_MAP() - }; - typedef epee::misc_utils::struct_init<response_t> response; - }; - - struct COMMAND_EXAMPLE_2 - { - const static int ID = 1001; - - struct request_t - { - std::string example_string_data2; - uint64_t example_id_data; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_POD(example_id_data) - SERIALIZE_STL_ANSI_STRING(example_string_data2) - END_NAMED_SERIALIZE_MAP() - }; - typedef epee::misc_utils::struct_init<request_t> request; - - struct response_t - { - bool m_success; - uint64_t example_id_data; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_POD(example_id_data) - SERIALIZE_POD(m_success) - END_NAMED_SERIALIZE_MAP() - }; - typedef epee::misc_utils::struct_init<response_t> response; - }; - typedef boost::uuids::uuid uuid; - - class test_levin_server: public levin::levin_commands_handler<> - { - test_levin_server(const test_levin_server&){} - public: - test_levin_server(){} - void set_thread_prefix(const std::string& pref) - { - m_net_server.set_threads_prefix(pref); - } - template<class calback_t> - bool connect_async(const std::string adr, const std::string& port, uint32_t conn_timeot, calback_t cb, const std::string& bind_ip = "0.0.0.0") - { - return m_net_server.connect_async(adr, port, conn_timeot, cb, bind_ip); - } - - bool connect(const std::string adr, const std::string& port, uint32_t conn_timeot, net_utils::connection_context_base& cn, const std::string& bind_ip = "0.0.0.0") - { - return m_net_server.connect(adr, port, conn_timeot, cn, bind_ip); - } - void close(net_utils::connection_context_base& cn) - { - m_net_server.get_config_object().close(cn.m_connection_id); - } - - template<class t_request, class t_response> - bool invoke(uuid con_id, int command, t_request& req, t_response& resp) - { - return invoke_remote_command(con_id, command, req, resp, m_net_server.get_config_object()); - } - - template< class t_response, class t_request, class callback_t> - bool invoke_async(uuid con_id, int command, t_request& req, callback_t cb) - { - return async_invoke_remote_command<t_response>(con_id, command, req, m_net_server.get_config_object(), cb); - } - - bool init(const std::string& bind_port = "", const std::string& bind_ip = "0.0.0.0") - { - m_net_server.get_config_object().set_handler(this); - m_net_server.get_config_object().m_invoke_timeout = 1000; - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - return m_net_server.init_server(bind_port, bind_ip); - } - - bool run() - { - //here you can set worker threads count - int thrds_count = 4; - - //go to loop - LOG_PRINT("Run net_service loop( " << thrds_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(thrds_count)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool deinit() - { - return m_net_server.deinit_server(); - } - - bool send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - - uint32_t get_binded_port() - { - return m_net_server.get_binded_port(); - } - private: - - - CHAIN_LEVIN_INVOKE_TO_MAP(); //move levin_commands_handler interface invoke(...) callbacks into invoke map - CHAIN_LEVIN_NOTIFY_TO_STUB(); //move levin_commands_handler interface notify(...) callbacks into nothing - - BEGIN_INVOKE_MAP(test_levin_server) - HANDLE_INVOKE_T(COMMAND_EXAMPLE_1, &test_levin_server::handle_1) - HANDLE_INVOKE_T(COMMAND_EXAMPLE_2, &test_levin_server::handle_2) - END_INVOKE_MAP() - - //----------------- commands handlers ---------------------------------------------- - int handle_1(int command, COMMAND_EXAMPLE_1::request& arg, COMMAND_EXAMPLE_1::response& rsp, const net_utils::connection_context_base& context) - { - LOG_PRINT_L0("on_command_1: id " << arg.example_id_data << "---->>"); - COMMAND_EXAMPLE_2::request arg_ = AUTO_VAL_INIT(arg_); - arg_.example_id_data = arg.example_id_data; - COMMAND_EXAMPLE_2::response rsp_ = AUTO_VAL_INIT(rsp_); - invoke_async<COMMAND_EXAMPLE_2::response>(context.m_connection_id, COMMAND_EXAMPLE_2::ID, arg_, [](int code, const COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context) - { - if(code < 0) - {LOG_PRINT_RED_L0("on_command_1: command_2 failed to invoke");} - else - {LOG_PRINT_L0("on_command_1: command_2 response " << rsp.example_id_data);} - }); - rsp.example_id_data = arg.example_id_data; - LOG_PRINT_L0("on_command_1: id " << arg.example_id_data << "<<----"); - return true; - } - int handle_2(int command, COMMAND_EXAMPLE_2::request& arg, COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context) - { - LOG_PRINT_L0("on_command_2: id "<< arg.example_id_data); - rsp.example_id_data = arg.example_id_data; - //misc_utils::sleep_no_w(6000); - return true; - } - //---------------------------------------------------------------------------------- - net_utils::boosted_levin_async_server m_net_server; - }; - - - inline - bool do_run_test_server() - { - - test_levin_server srv1, srv2; - - - std::string bind_param = "0.0.0.0"; - std::string port = ""; - - if(!srv1.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - if(!srv2.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - srv1.set_thread_prefix("SRV_A"); - srv2.set_thread_prefix("SRV_B"); - - boost::thread th1( boost::bind(&test_levin_server::run, &srv1)); - boost::thread th2( boost::bind(&test_levin_server::run, &srv2)); - - LOG_PRINT_L0("Initialized servers, waiting for worker threads started..."); - misc_utils::sleep_no_w(1000); - - - LOG_PRINT_L0("Connecting to each other..."); - uint32_t port1 = srv1.get_binded_port(); - uint32_t port2 = srv2.get_binded_port(); - - COMMAND_EXAMPLE_1::request arg; - COMMAND_EXAMPLE_1::request resp; - - net_utils::connection_context_base cntxt_1; - bool r = srv1.connect("127.0.0.1", string_tools::num_to_string_fast(port2), 5000, cntxt_1); - CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); - - net_utils::connection_context_base cntxt_2; - r = srv2.connect("127.0.0.1", string_tools::num_to_string_fast(port1), 5000, cntxt_2); - CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); - - while(true) - { - LOG_PRINT_L0("Invoking from A to B..."); - int r = srv1.invoke(cntxt_1.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, resp); - if(r<=0) - { - LOG_ERROR("Failed tp invoke A to B"); - break; - } - - LOG_PRINT_L0("Invoking from B to A..."); - r = srv2.invoke(cntxt_2.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, resp); - if(r<=0) - { - LOG_ERROR("Failed tp invoke B to A"); - break; - } - } - srv1.send_stop_signal(); - srv2.send_stop_signal(); - th1.join(); - th1.join(); - - return true; - } - - - - inline bool do_test2_work_with_srv(test_levin_server& srv, int port) - { - uint64_t i = 0; - boost::mutex wait_event; - wait_event.lock(); - while(true) - { - net_utils::connection_context_base cntxt_local = AUTO_VAL_INIT(cntxt_local); - bool r = srv.connect_async("127.0.0.1", string_tools::num_to_string_fast(port), 5000, [&srv, &port, &wait_event, &i, &cntxt_local](const net_utils::connection_context_base& cntxt, const boost::system::error_code& ec) - { - CHECK_AND_ASSERT_MES(!ec, void(), "Some problems at connect, message: " << ec.message() ); - cntxt_local = cntxt; - LOG_PRINT_L0("Invoking command 1 to " << port); - COMMAND_EXAMPLE_1::request arg = AUTO_VAL_INIT(arg); - arg.example_id_data = i; - /*vc2010 workaround*/ - int port_ = port; - boost::mutex& wait_event_ = wait_event; - int r = srv.invoke_async<COMMAND_EXAMPLE_1::request>(cntxt.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, [port_, &wait_event_](int code, const COMMAND_EXAMPLE_1::request& rsp, const net_utils::connection_context_base& cntxt) - { - CHECK_AND_ASSERT_MES(code > 0, void(), "Failed to invoke"); - LOG_PRINT_L0("command 1 invoke to " << port_ << " OK."); - wait_event_.unlock(); - }); - }); - wait_event.lock(); - srv.close(cntxt_local); - ++i; - } - return true; - } - - inline - bool do_run_test_server_async_connect() - { - test_levin_server srv1, srv2; - - - std::string bind_param = "0.0.0.0"; - std::string port = ""; - - if(!srv1.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - if(!srv2.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - srv1.set_thread_prefix("SRV_A"); - srv2.set_thread_prefix("SRV_B"); - - boost::thread thmain1( boost::bind(&test_levin_server::run, &srv1)); - boost::thread thmain2( boost::bind(&test_levin_server::run, &srv2)); - - LOG_PRINT_L0("Initalized servers, waiting for worker threads started..."); - misc_utils::sleep_no_w(1000); - - - LOG_PRINT_L0("Connecting to each other..."); - uint32_t port1 = srv1.get_binded_port(); - uint32_t port2 = srv2.get_binded_port(); - - COMMAND_EXAMPLE_1::request arg; - COMMAND_EXAMPLE_1::request resp; - - - boost::thread work_1( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_2( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - boost::thread work_3( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_4( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - boost::thread work_5( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_6( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - boost::thread work_7( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_8( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - - - work_1.join(); - work_2.join(); - srv1.send_stop_signal(); - srv2.send_stop_signal(); - thmain1.join(); - thmain2.join(); - - return true; - } - -} -} diff --git a/contrib/epee/tests/src/storages/portable_storages_test.h b/contrib/epee/tests/src/storages/portable_storages_test.h deleted file mode 100644 index 89f217d95..000000000 --- a/contrib/epee/tests/src/storages/portable_storages_test.h +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include <list> -#include <string> -#include "storages/serializeble_struct_helper.h" -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_template_helper.h" - -namespace epee -{ - namespace tests - { - - struct port_test_struct_sub - { - std::string m_str; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL(m_str) - END_KV_SERIALIZE_MAP() - }; - -#pragma pack (push, 1) - struct some_pod_struct - { - uint64_t a; - int32_t b; - }; -#pragma pack(pop) - - struct port_test_struct - { - std::string m_str; - uint64_t m_uint64; - uint32_t m_uint32; - uint16_t m_uint16; - uint8_t m_uint8; - int64_t m_int64; - int32_t m_int32; - int16_t m_int16; - int8_t m_int8; - double m_double; - bool m_bool; - some_pod_struct m_pod; - std::list<std::string> m_list_of_str; - std::list<uint64_t> m_list_of_uint64_t; - std::list<uint32_t> m_list_of_uint32_t; - std::list<uint16_t> m_list_of_uint16_t; - std::list<uint8_t> m_list_of_uint8_t; - std::list<int64_t> m_list_of_int64_t; - std::list<int32_t> m_list_of_int32_t; - std::list<int16_t> m_list_of_int16_t; - std::list<int8_t> m_list_of_int8_t; - std::list<double> m_list_of_double; - std::list<bool> m_list_of_bool; - port_test_struct_sub m_subobj; - std::list<port_test_struct> m_list_of_self; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL(m_str) - KV_SERIALIZE_VAL(m_uint64) - KV_SERIALIZE_VAL(m_uint32) - KV_SERIALIZE_VAL(m_uint16) - KV_SERIALIZE_VAL(m_uint8) - KV_SERIALIZE_VAL(m_int64) - KV_SERIALIZE_VAL(m_int32) - KV_SERIALIZE_VAL(m_int16) - KV_SERIALIZE_VAL(m_int8) - KV_SERIALIZE_VAL(m_double) - KV_SERIALIZE_VAL(m_bool) - KV_SERIALIZE_VAL_POD_AS_BLOB(m_pod) - KV_SERIALIZE_OBJ(m_subobj) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_str) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint64_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint32_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint16_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint8_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int64_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int32_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int16_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int8_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_double) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_bool) - KV_SERIALIZE_CONTAINER_OBJ(m_list_of_self) - END_KV_SERIALIZE_MAP() - }; - - bool operator != (const port_test_struct_sub& a, const port_test_struct_sub& b) - { - return b.m_str != a.m_str; - } - - bool operator == (const port_test_struct& a, const port_test_struct& b) - { - if( b.m_str != a.m_str - || b.m_uint64 != a.m_uint64 - || b.m_uint32 != a.m_uint32 - || b.m_uint16 != a.m_uint16 - || b.m_uint8 != a.m_uint8 - || b.m_int64 != a.m_int64 - || b.m_int32 != a.m_int32 - || b.m_int16 != a.m_int16 - || b.m_int8 != a.m_int8 - || b.m_double != a.m_double - || b.m_bool != a.m_bool - || b.m_pod.a != a.m_pod.a - || b.m_pod.b != a.m_pod.b - || b.m_list_of_str != a.m_list_of_str - || b.m_list_of_uint64_t != a.m_list_of_uint64_t - || b.m_list_of_uint32_t != a.m_list_of_uint32_t - || b.m_list_of_uint16_t != a.m_list_of_uint16_t - || b.m_list_of_uint8_t != a.m_list_of_uint8_t - || b.m_list_of_int64_t != a.m_list_of_int64_t - || b.m_list_of_int32_t != a.m_list_of_int32_t - || b.m_list_of_int16_t != a.m_list_of_int16_t - || b.m_list_of_int8_t != a.m_list_of_int8_t - || b.m_list_of_double != a.m_list_of_double - || b.m_list_of_bool != a.m_list_of_bool - || b.m_subobj != a.m_subobj - || b.m_list_of_self != a.m_list_of_self - ) - return false; - return true; - } - - void fill_struct_with_test_values(port_test_struct& s) - { - s.m_str = "zuzuzuzuzuz"; - s.m_uint64 = 111111111111111; - s.m_uint32 = 2222222; - s.m_uint16 = 2222; - s.m_uint8 = 22; - s.m_int64 = -111111111111111; - s.m_int32 = -2222222; - s.m_int16 = -2222; - s.m_int8 = -24; - s.m_double = 0.11111; - s.m_bool = true; - s.m_pod.a = 32342342342342; - s.m_pod.b = -342342; - s.m_list_of_str.push_back("1112121"); - s.m_list_of_uint64_t.push_back(1111111111); - s.m_list_of_uint64_t.push_back(2222222222); - s.m_list_of_uint32_t.push_back(1111111); - s.m_list_of_uint32_t.push_back(2222222); - s.m_list_of_uint16_t.push_back(1111); - s.m_list_of_uint16_t.push_back(2222); - s.m_list_of_uint8_t.push_back(11); - s.m_list_of_uint8_t.push_back(22); - - - s.m_list_of_int64_t.push_back(-1111111111); - s.m_list_of_int64_t.push_back(-222222222); - s.m_list_of_int32_t.push_back(-1111111); - s.m_list_of_int32_t.push_back(-2222222); - s.m_list_of_int16_t.push_back(-1111); - s.m_list_of_int16_t.push_back(-2222); - s.m_list_of_int8_t.push_back(-11); - s.m_list_of_int8_t.push_back(-22); - - s.m_list_of_double.push_back(0.11111); - s.m_list_of_double.push_back(0.22222); - s.m_list_of_bool.push_back(true); - s.m_list_of_bool.push_back(false); - - s.m_subobj.m_str = "subszzzzzzzz"; - s.m_list_of_self.push_back(s); - } - - bool test_portable_storages(const std::string& tests_folder) - { - serialization::portable_storage ps, ps2; - port_test_struct s1, s2; - fill_struct_with_test_values(s1); - - s1.store(ps); - std::string binbuf; - bool r = ps.store_to_binary(binbuf); - - ps2.load_from_binary(binbuf); - s2.load(ps2); - if(!(s1 == s2)) - { - LOG_ERROR("Portable storage test failed!"); - return false; - } - - - port_test_struct ss1, ss2; - fill_struct_with_test_values(ss1); - std::string json_buff = epee::serialization::store_t_to_json(ss1); - epee::serialization::load_t_from_json(ss2, json_buff); - if(!(ss1 == ss2)) - { - LOG_ERROR("Portable storage test failed!"); - return false; - } - - return true; - } - - } -} diff --git a/contrib/epee/tests/src/storages/storage_tests.h b/contrib/epee/tests/src/storages/storage_tests.h deleted file mode 100644 index 522e589c4..000000000 --- a/contrib/epee/tests/src/storages/storage_tests.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "storages/serializeble_struct_helper.h" -#include "storages/portable_storage.h" - -namespace epee -{ - namespace tests - { - - - struct test_struct - { - - std::string m_str; - unsigned int m_uint; - bool m_bool; - std::list<std::string> m_list_of_str; - std::list<int> m_list_of_int; - std::list<test_struct> m_list_of_self; - - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_STL_ANSI_STRING(m_str) - SERIALIZE_POD(m_uint) - SERIALIZE_POD(m_bool) - SERIALIZE_STL_CONTAINER_ANSII_STRING(m_list_of_str) - SERIALIZE_STL_CONTAINER_POD(m_list_of_int) - SERIALIZE_STL_CONTAINER_T(m_list_of_self) - END_NAMED_SERIALIZE_MAP() - - }; - - - bool operator == (const test_struct& a, const test_struct& b) - { - if( b.m_str != a.m_str - || b.m_uint != a.m_uint - || b.m_bool != a.m_bool - || b.m_list_of_str != a.m_list_of_str - || b.m_list_of_int != a.m_list_of_int - || b.m_list_of_self != a.m_list_of_self - ) - return false; - return true; - } - - inline test_struct get_test_struct() - { - test_struct t = boost::value_initialized<test_struct>(); - t.m_bool = true; - t.m_str = "ackamdc'kmecemcececmacmecmcm[aicm[oeicm[oeicm[qaicm[qoe"; - t.m_uint = 233242; - for(int i = 0; i!=500; i++) - t.m_list_of_int.push_back(i); - - for(int i = 0; i!=500; i++) - t.m_list_of_str.push_back("ssccd"); - - for(int i = 0; i!=5; i++) - { - t.m_list_of_self.push_back(t); - } - return t; - } - - bool test_storages(const std::string& tests_folder) - { - - epee::serialization::portable_storage ps; - auto s = ps.open_section("zzz", nullptr); - uint64_t i = 0; - ps.get_value("afdsdf", i, s); - - - LOG_PRINT_L0("Generating test struct..."); - boost::filesystem::path storage_folder = tests_folder; - storage_folder /= "storages"; - - - test_struct t = get_test_struct(); - - LOG_PRINT_L0("Loading test struct from storage..."); - test_struct t2; - bool res = epee::StorageNamed::load_struct_from_storage_file(t2, (storage_folder /+ "valid_storage.bin").string()); - CHECK_AND_ASSERT_MES(res, false, "Failed to load valid_storage.bin"); - - LOG_PRINT_L0("Comparing generated and loaded test struct..."); - if(!(t == t2)) - return false; - - LOG_PRINT_L0("Loading broken archive 1..."); - test_struct t3; - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_1.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_1.bin loaded, but should not "); - - - LOG_PRINT_L0("Loading broken archive 2..."); - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_2.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_2.bin loaded, but should not "); - - LOG_PRINT_L0("Loading broken archive 3..."); - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_3.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); - - LOG_PRINT_L0("Loading broken archive 4..."); - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_4.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); - - return true; - } - } -} - diff --git a/contrib/epee/tests/src/tests.cpp b/contrib/epee/tests/src/tests.cpp deleted file mode 100644 index 8d61334cc..000000000 --- a/contrib/epee/tests/src/tests.cpp +++ /dev/null @@ -1,59 +0,0 @@ - -#include "include_base_utils.h" -#include "storages/storage_tests.h" -#include "misc/test_math.h" -#include "storages/portable_storages_test.h" -#include "net/test_net.h" - -using namespace epee; - -int main(int argc, char* argv[]) -{ - - string_tools::set_module_name_and_folder(argv[0]); - - //set up logging options - log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); - log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); - log_space::log_singletone::add_logger(LOGGER_FILE, - log_space::log_singletone::get_default_log_file().c_str(), - log_space::log_singletone::get_default_log_folder().c_str()); - - - string_tools::command_line_params_a start_params; - string_tools::parse_commandline(start_params, argc, argv); - std::string tests_data_path; - string_tools::get_xparam_from_command_line(start_params, std::string("/tests_folder"), tests_data_path); - - if(string_tools::have_in_command_line(start_params, std::string("/run_net_tests"))) - { - if(!tests::do_run_test_server()) - { - LOG_ERROR("net tests failed"); - return 1; - } - if(!tests::do_run_test_server_async_connect() ) - { - LOG_ERROR("net tests failed"); - return 1; - } - }else if(string_tools::have_in_command_line(start_params, std::string("/run_unit_tests"))) - { - if(!tests::test_median()) - { - LOG_ERROR("median test failed"); - return 1; - } - - - if(!tests::test_storages(tests_data_path)) - { - LOG_ERROR("storage test failed"); - return 1; - } - }else if(string_tools::have_in_command_line(start_params, std::string("/run_portable_storage_test"))) - { - tests::test_portable_storages(tests_data_path); - } - return 1; -} diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index d60edc6a6..14b52a2af 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -56,7 +56,7 @@ the previous paragraph is here. ## License Copyright (c) 2009-2015 Pieter Hintjens. -Copyright (c) 2017-2018 The Monero Project. +Copyright (c) 2017-2022, The Monero Project This Specification is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. diff --git a/external/randomx b/external/randomx -Subproject 9efc398c196ef1c50d8e6f5e1f2c5ac02f1f6ce +Subproject ae8e98b681766f31d49ac562dd6974906156e07 diff --git a/include/IWallet.h b/include/IWallet.h deleted file mode 100644 index 74260ce35..000000000 --- a/include/IWallet.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2014-2020, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include <array> -#include <cstdint> -#include <istream> -#include <limits> -#include <ostream> -#include <string> -#include <system_error> -#include <vector> - -namespace CryptoNote { - -typedef size_t TransactionId; -typedef size_t TransferId; -typedef std::array<uint8_t, 32> TransacitonHash; - -struct Transfer { - std::string address; - int64_t amount; -}; - -const TransactionId INVALID_TRANSACTION_ID = std::numeric_limits<TransactionId>::max(); -const TransferId INVALID_TRANSFER_ID = std::numeric_limits<TransferId>::max(); -const uint64_t UNCONFIRMED_TRANSACTION_HEIGHT = std::numeric_limits<uint64_t>::max(); - -struct Transaction { - TransferId firstTransferId; - size_t transferCount; - int64_t totalAmount; - uint64_t fee; - TransacitonHash hash; - bool isCoinbase; - uint64_t blockHeight; - uint64_t timestamp; - std::string extra; -}; - -class IWalletObserver { -public: - virtual void initCompleted(std::error_code result) {} - virtual void saveCompleted(std::error_code result) {} - virtual void synchronizationProgressUpdated(uint64_t current, uint64_t total) {} - virtual void actualBalanceUpdated(uint64_t actualBalance) {} - virtual void pendingBalanceUpdated(uint64_t pendingBalance) {} - virtual void externalTransactionCreated(TransactionId transactionId) {} - virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) {} - virtual void transactionUpdated(TransactionId transactionId) {} -}; - -class IWallet { -public: - virtual ~IWallet() = 0; - virtual void addObserver(IWalletObserver* observer) = 0; - virtual void removeObserver(IWalletObserver* observer) = 0; - - virtual void initAndGenerate(const std::string& password) = 0; - virtual void initAndLoad(std::istream& source, const std::string& password) = 0; - virtual void shutdown() = 0; - - virtual void save(std::ostream& destination, bool saveDetailed = true, bool saveCache = true) = 0; - - virtual std::error_code changePassword(const std::string& oldPassword, const std::string& newPassword) = 0; - - virtual std::string getAddress() = 0; - - virtual uint64_t actualBalance() = 0; - virtual uint64_t pendingBalance() = 0; - - virtual size_t getTransactionCount() = 0; - virtual size_t getTransferCount() = 0; - - virtual TransactionId findTransactionByTransferId(TransferId transferId) = 0; - - virtual bool getTransaction(TransactionId transactionId, Transaction& transaction) = 0; - virtual bool getTransfer(TransferId transferId, Transfer& transfer) = 0; - - virtual TransactionId sendTransaction(const Transfer& transfer, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) = 0; - virtual TransactionId sendTransaction(const std::vector<Transfer>& transfers, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) = 0; - virtual std::error_code cancelTransaction(size_t transferId) = 0; -}; - -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aaaae3a09..3335d3c21 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/blockchain_db/CMakeLists.txt b/src/blockchain_db/CMakeLists.txt index 77faade17..14ed76295 100644 --- a/src/blockchain_db/CMakeLists.txt +++ b/src/blockchain_db/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -33,10 +33,7 @@ set(blockchain_db_sources set(blockchain_db_headers) -set(blockchain_db_private_headers - blockchain_db.h - lmdb/db_lmdb.h - ) +monero_find_all_headers(blockchain_db_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(blockchain_db ${crypto_private_headers}) diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index a84a4148d..44be08003 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -241,8 +241,15 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair } else { + rct::key commitment; + if (tx.version > 1) + { + commitment = tx.rct_signatures.outPk[i].mask; + if (rct::is_rct_bulletproof_plus(tx.rct_signatures.type)) + commitment = rct::scalarmult8(commitment); + } amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time, - tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL); + tx.version > 1 ? &commitment : NULL); } } add_tx_amount_output_indices(tx_id, amount_output_indices); diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 74bd72332..263948fa2 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index de2700ad0..e2ac9df0b 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are @@ -1045,8 +1045,9 @@ uint64_t BlockchainLMDB::add_output(const crypto::hash& tx_hash, CURSOR(output_txs) CURSOR(output_amounts) - if (tx_output.target.type() != typeid(txout_to_key)) - throw0(DB_ERROR("Wrong output type: expected txout_to_key")); + crypto::public_key output_public_key; + if (!get_output_public_key(tx_output, output_public_key)) + throw0(DB_ERROR("Could not get an output public key from a tx output.")); if (tx_output.amount == 0 && !commitment) throw0(DB_ERROR("RCT output without commitment")); @@ -1074,7 +1075,7 @@ uint64_t BlockchainLMDB::add_output(const crypto::hash& tx_hash, else ok.amount_index = 0; ok.output_id = m_num_outputs; - ok.data.pubkey = boost::get < txout_to_key > (tx_output.target).key; + ok.data.pubkey = output_public_key; ok.data.unlock_time = unlock_time; ok.data.height = m_height; if (tx_output.amount == 0) diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index d87bc6e49..20edab2e9 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/blockchain_db/locked_txn.h b/src/blockchain_db/locked_txn.h index 1834f56fb..beab8af21 100644 --- a/src/blockchain_db/locked_txn.h +++ b/src/blockchain_db/locked_txn.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_db/testdb.h b/src/blockchain_db/testdb.h index e36026e07..fe8078d5e 100644 --- a/src/blockchain_db/testdb.h +++ b/src/blockchain_db/testdb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index ac533596a..8122d9034 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/blockchain_utilities/README.md b/src/blockchain_utilities/README.md index 4a233bcf5..a7d47e233 100644 --- a/src/blockchain_utilities/README.md +++ b/src/blockchain_utilities/README.md @@ -1,6 +1,6 @@ # Monero Blockchain Utilities -Copyright (c) 2014-2020, The Monero Project +Copyright (c) 2014-2022, The Monero Project ## Introduction diff --git a/src/blockchain_utilities/blockchain_ancestry.cpp b/src/blockchain_utilities/blockchain_ancestry.cpp index 99a84606d..b0964e4a3 100644 --- a/src/blockchain_utilities/blockchain_ancestry.cpp +++ b/src/blockchain_utilities/blockchain_ancestry.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index d53251fd3..dee0f7f2a 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blockchain_depth.cpp b/src/blockchain_utilities/blockchain_depth.cpp index 8c3c3a009..b98a1f8e2 100644 --- a/src/blockchain_utilities/blockchain_depth.cpp +++ b/src/blockchain_utilities/blockchain_depth.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp index 87cd7945c..82fe524de 100644 --- a/src/blockchain_utilities/blockchain_export.cpp +++ b/src/blockchain_utilities/blockchain_export.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 8d81ef54d..f8cca638d 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blockchain_prune.cpp b/src/blockchain_utilities/blockchain_prune.cpp index b1c599f3a..4a91cf7cc 100644 --- a/src/blockchain_utilities/blockchain_prune.cpp +++ b/src/blockchain_utilities/blockchain_prune.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp index 78a662134..05aaf42ee 100644 --- a/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp +++ b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blockchain_stats.cpp b/src/blockchain_utilities/blockchain_stats.cpp index 5f5ca6abf..3009b5024 100644 --- a/src/blockchain_utilities/blockchain_stats.cpp +++ b/src/blockchain_utilities/blockchain_stats.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blockchain_usage.cpp b/src/blockchain_utilities/blockchain_usage.cpp index 8356ef420..129a9be21 100644 --- a/src/blockchain_utilities/blockchain_usage.cpp +++ b/src/blockchain_utilities/blockchain_usage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blockchain_utilities.h b/src/blockchain_utilities/blockchain_utilities.h index 035e2397f..47bbb0faf 100644 --- a/src/blockchain_utilities/blockchain_utilities.h +++ b/src/blockchain_utilities/blockchain_utilities.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blocksdat_file.cpp b/src/blockchain_utilities/blocksdat_file.cpp index b9ef1de7d..606805a08 100644 --- a/src/blockchain_utilities/blocksdat_file.cpp +++ b/src/blockchain_utilities/blocksdat_file.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/blocksdat_file.h b/src/blockchain_utilities/blocksdat_file.h index 567505ac1..ce224baa6 100644 --- a/src/blockchain_utilities/blocksdat_file.h +++ b/src/blockchain_utilities/blocksdat_file.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/bootstrap_file.cpp b/src/blockchain_utilities/bootstrap_file.cpp index 7050b9ab1..71477912a 100644 --- a/src/blockchain_utilities/bootstrap_file.cpp +++ b/src/blockchain_utilities/bootstrap_file.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/bootstrap_file.h b/src/blockchain_utilities/bootstrap_file.h index ff2875a61..0f2776172 100644 --- a/src/blockchain_utilities/bootstrap_file.h +++ b/src/blockchain_utilities/bootstrap_file.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_utilities/bootstrap_serialization.h b/src/blockchain_utilities/bootstrap_serialization.h index bcc8c7e15..261810a6b 100644 --- a/src/blockchain_utilities/bootstrap_serialization.h +++ b/src/blockchain_utilities/bootstrap_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index d2003316d..db8fe5f94 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/checkpoints/CMakeLists.txt b/src/checkpoints/CMakeLists.txt index 46d6fedf1..665441f62 100644 --- a/src/checkpoints/CMakeLists.txt +++ b/src/checkpoints/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -41,8 +41,7 @@ set(checkpoints_sources set(checkpoints_headers) -set(checkpoints_private_headers - checkpoints.h) +monero_find_all_headers(checkpoints_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(checkpoints ${checkpoints_private_headers}) diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp index 6b48d8723..27e77cae8 100644 --- a/src/checkpoints/checkpoints.cpp +++ b/src/checkpoints/checkpoints.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/checkpoints/checkpoints.h b/src/checkpoints/checkpoints.h index 029c50548..07daeb4c0 100644 --- a/src/checkpoints/checkpoints.h +++ b/src/checkpoints/checkpoints.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 99d9bd8bf..b712ee6b1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -58,36 +58,7 @@ endif() set(common_headers) -set(common_private_headers - apply_permutation.h - base58.h - boost_serialization_helper.h - command_line.h - common_fwd.h - dns_utils.h - download.h - error.h - expect.h - http_connection.h - notify.h - pod-class.h - pruning.h - rpc_client.h - scoped_message_writer.h - unordered_containers_boost_serialization.h - util.h - varint.h - i18n.h - password.h - perf_timer.h - spawn.h - stack_trace.h - threadpool.h - updates.h - aligned.h - timings.h - combinator.h - utf8.h) +monero_find_all_headers(common_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(common ${common_private_headers}) diff --git a/src/common/aligned.c b/src/common/aligned.c index e3a607f66..3e33bfa80 100644 --- a/src/common/aligned.c +++ b/src/common/aligned.c @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/aligned.h b/src/common/aligned.h index fed3ccb36..33242a151 100644 --- a/src/common/aligned.h +++ b/src/common/aligned.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/apply_permutation.h b/src/common/apply_permutation.h index 03effc50e..ceccdfe96 100644 --- a/src/common/apply_permutation.h +++ b/src/common/apply_permutation.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/base58.cpp b/src/common/base58.cpp index 77b6a642c..f50bd10fb 100644 --- a/src/common/base58.cpp +++ b/src/common/base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/base58.h b/src/common/base58.h index 4a7b02cbc..fa97ab98c 100644 --- a/src/common/base58.h +++ b/src/common/base58.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/boost_serialization_helper.h b/src/common/boost_serialization_helper.h index 4f9cf0518..4a903107f 100644 --- a/src/common/boost_serialization_helper.h +++ b/src/common/boost_serialization_helper.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/combinator.cpp b/src/common/combinator.cpp index cb4fbc908..72b139737 100644 --- a/src/common/combinator.cpp +++ b/src/common/combinator.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/combinator.h b/src/common/combinator.h index ba851bd81..0d35e4786 100644 --- a/src/common/combinator.h +++ b/src/common/combinator.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index 42370f543..30ded6f33 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/command_line.h b/src/common/command_line.h index b4619905b..d80a1b0df 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/common_fwd.h b/src/common/common_fwd.h index ac8894ba4..4853c23c9 100644 --- a/src/common/common_fwd.h +++ b/src/common/common_fwd.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index f0b617798..6ab6ff4fe 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h index 99e91bc54..f9507b42a 100644 --- a/src/common/dns_utils.h +++ b/src/common/dns_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/download.cpp b/src/common/download.cpp index c3dfa43d5..01d4a9aab 100644 --- a/src/common/download.cpp +++ b/src/common/download.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/download.h b/src/common/download.h index 19a52a786..52af4dc6a 100644 --- a/src/common/download.h +++ b/src/common/download.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/error.cpp b/src/common/error.cpp index e091e4478..f5e402ef4 100644 --- a/src/common/error.cpp +++ b/src/common/error.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/common/error.h b/src/common/error.h index 6fef3eb4b..d271517f4 100644 --- a/src/common/error.h +++ b/src/common/error.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/common/expect.h b/src/common/expect.h index 72e4060a7..6f2d8e291 100644 --- a/src/common/expect.h +++ b/src/common/expect.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/http_connection.h b/src/common/http_connection.h index 5ee39cdbb..f8281fe1e 100644 --- a/src/common/http_connection.h +++ b/src/common/http_connection.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/i18n.cpp b/src/common/i18n.cpp index 051220ee1..6d904a2e3 100644 --- a/src/common/i18n.cpp +++ b/src/common/i18n.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/i18n.h b/src/common/i18n.h index 3bf2f8260..1ed78bf8f 100644 --- a/src/common/i18n.h +++ b/src/common/i18n.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/json_util.h b/src/common/json_util.h index 38464f7f1..6d2cfedb4 100644 --- a/src/common/json_util.h +++ b/src/common/json_util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/notify.cpp b/src/common/notify.cpp index f31100214..28f38d8c3 100644 --- a/src/common/notify.cpp +++ b/src/common/notify.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/notify.h b/src/common/notify.h index 65d4e1072..7ff721c8a 100644 --- a/src/common/notify.h +++ b/src/common/notify.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/password.cpp b/src/common/password.cpp index 019f04c95..e6dff95ea 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/password.h b/src/common/password.h index 54d97e565..26b6616ab 100644 --- a/src/common/password.h +++ b/src/common/password.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/perf_timer.cpp b/src/common/perf_timer.cpp index 898701b2f..30164a557 100644 --- a/src/common/perf_timer.cpp +++ b/src/common/perf_timer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // @@ -27,7 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <vector> -#include "misc_os_dependent.h" +#include "time_helper.h" #include "perf_timer.h" #undef MONERO_DEFAULT_LOG_CATEGORY diff --git a/src/common/perf_timer.h b/src/common/perf_timer.h index fb89b78c0..c6120b06d 100644 --- a/src/common/perf_timer.h +++ b/src/common/perf_timer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/pod-class.h b/src/common/pod-class.h index 38eae8948..c6fce75e6 100644 --- a/src/common/pod-class.h +++ b/src/common/pod-class.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/pruning.cpp b/src/common/pruning.cpp index 442b24e4e..5cae238ae 100644 --- a/src/common/pruning.cpp +++ b/src/common/pruning.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/pruning.h b/src/common/pruning.h index 3fac3c0fa..6530dcf2e 100644 --- a/src/common/pruning.h +++ b/src/common/pruning.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/rpc_client.h b/src/common/rpc_client.h index 26bcea751..a603a7baf 100644 --- a/src/common/rpc_client.h +++ b/src/common/rpc_client.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/scoped_message_writer.h b/src/common/scoped_message_writer.h index 0a5ebe1c9..cf4e6855f 100644 --- a/src/common/scoped_message_writer.h +++ b/src/common/scoped_message_writer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/sfinae_helpers.h b/src/common/sfinae_helpers.h index e0778b10f..c5974fe82 100644 --- a/src/common/sfinae_helpers.h +++ b/src/common/sfinae_helpers.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/spawn.cpp b/src/common/spawn.cpp index 9a7e75d41..22e840407 100644 --- a/src/common/spawn.cpp +++ b/src/common/spawn.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/spawn.h b/src/common/spawn.h index c90a0f790..f3c8dbb6e 100644 --- a/src/common/spawn.h +++ b/src/common/spawn.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/stack_trace.cpp b/src/common/stack_trace.cpp index 828b8f1c8..130ba4d81 100644 --- a/src/common/stack_trace.cpp +++ b/src/common/stack_trace.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/stack_trace.h b/src/common/stack_trace.h index 57f939b2d..dc8182154 100644 --- a/src/common/stack_trace.h +++ b/src/common/stack_trace.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp index edc87fc48..5d2acc0a6 100644 --- a/src/common/threadpool.cpp +++ b/src/common/threadpool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/threadpool.h b/src/common/threadpool.h index 66b08fece..ce1bc5799 100644 --- a/src/common/threadpool.h +++ b/src/common/threadpool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/unordered_containers_boost_serialization.h b/src/common/unordered_containers_boost_serialization.h index 67bde676c..bc6dd8e7a 100644 --- a/src/common/unordered_containers_boost_serialization.h +++ b/src/common/unordered_containers_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/updates.cpp b/src/common/updates.cpp index af38d7a54..654ad068c 100644 --- a/src/common/updates.cpp +++ b/src/common/updates.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/updates.h b/src/common/updates.h index 0bfe26c3f..64e4eea50 100644 --- a/src/common/updates.h +++ b/src/common/updates.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/utf8.h b/src/common/utf8.h index 60247f1b2..434de15e7 100644 --- a/src/common/utf8.h +++ b/src/common/utf8.h @@ -1,4 +1,5 @@ -// Copyright (c) 2019, The Monero Project +// Copyright (c) 2019-2022, The Monero Project + // // All rights reserved. // diff --git a/src/common/util.cpp b/src/common/util.cpp index af9843b95..89dcf4fef 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -59,7 +59,7 @@ #include "include_base_utils.h" #include "file_io_utils.h" #include "wipeable_string.h" -#include "misc_os_dependent.h" +#include "time_helper.h" using namespace epee; #include "crypto/crypto.h" diff --git a/src/common/util.h b/src/common/util.h index 6366e5cb4..25f5ceb47 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/common/varint.h b/src/common/varint.h index 133622a67..9f8b9a4ab 100644 --- a/src/common/varint.h +++ b/src/common/varint.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index 3f0f7d34b..595c7f966 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -58,27 +58,7 @@ include_directories(${RANDOMX_INCLUDE}) set(crypto_headers) -set(crypto_private_headers - blake256.h - chacha.h - crypto-ops.h - crypto.h - generic-ops.h - groestl.h - groestl_tables.h - hash-ops.h - hash.h - hmac-keccak.h - initializer.h - jh.h - keccak.h - oaes_config.h - oaes_lib.h - random.h - skein.h - skein_port.h - CryptonightR_JIT.h - CryptonightR_template.h) +monero_find_all_headers(crypto_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(cncrypto ${crypto_private_headers}) diff --git a/src/crypto/blake256.c b/src/crypto/blake256.c index 831a90302..7e302bcad 100644 --- a/src/crypto/blake256.c +++ b/src/crypto/blake256.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/blake256.h b/src/crypto/blake256.h index 5abdb79b9..f727bddee 100644 --- a/src/crypto/blake256.h +++ b/src/crypto/blake256.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/c_threads.h b/src/crypto/c_threads.h index 5b2fcddd3..c5431cb8d 100644 --- a/src/crypto/c_threads.h +++ b/src/crypto/c_threads.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h index a1158be7e..74f05cbe8 100644 --- a/src/crypto/chacha.h +++ b/src/crypto/chacha.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/crypto-ops-data.c b/src/crypto/crypto-ops-data.c index d16fd9429..1a85de60d 100644 --- a/src/crypto/crypto-ops-data.c +++ b/src/crypto/crypto-ops-data.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/crypto-ops.c b/src/crypto/crypto-ops.c index 54ca39775..4b392d472 100644 --- a/src/crypto/crypto-ops.c +++ b/src/crypto/crypto-ops.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/crypto-ops.h b/src/crypto/crypto-ops.h index 96da16cbd..e4901e080 100644 --- a/src/crypto/crypto-ops.h +++ b/src/crypto/crypto-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 0059dd7f5..77a36069a 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -749,4 +749,28 @@ POP_WARNINGS sc_sub(&h, &h, &sum); return sc_isnonzero(&h) == 0; } + + void crypto_ops::derive_view_tag(const key_derivation &derivation, size_t output_index, view_tag &view_tag) { + #pragma pack(push, 1) + struct { + char salt[8]; // view tag domain-separator + key_derivation derivation; + char output_index[(sizeof(size_t) * 8 + 6) / 7]; + } buf; + #pragma pack(pop) + + char *end = buf.output_index; + memcpy(buf.salt, "view_tag", 8); // leave off null terminator + buf.derivation = derivation; + tools::write_varint(end, output_index); + assert(end <= buf.output_index + sizeof buf.output_index); + + // view_tag_full = H[salt|derivation|output_index] + hash view_tag_full; + cn_fast_hash(&buf, end - reinterpret_cast<char *>(&buf), view_tag_full); + + // only need a slice of view_tag_full to realize optimal perf/space efficiency + static_assert(sizeof(crypto::view_tag) <= sizeof(view_tag_full), "view tag should not be larger than hash result"); + memcpy(&view_tag, &view_tag_full, sizeof(crypto::view_tag)); + } } diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 599ae4f91..d8cd6c6a0 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -99,6 +99,10 @@ namespace crypto { ec_scalar c, r; friend class crypto_ops; }; + + POD_CLASS view_tag { + char data; + }; #pragma pack(pop) void hash_to_scalar(const void *data, size_t length, ec_scalar &res); @@ -107,7 +111,7 @@ namespace crypto { static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 && sizeof(public_key) == 32 && sizeof(public_key_memsafe) == 32 && sizeof(secret_key) == 32 && sizeof(key_derivation) == 32 && sizeof(key_image) == 32 && - sizeof(signature) == 64, "Invalid structure size"); + sizeof(signature) == 64 && sizeof(view_tag) == 1, "Invalid structure size"); class crypto_ops { crypto_ops(); @@ -151,6 +155,8 @@ namespace crypto { const public_key *const *, std::size_t, const signature *); friend bool check_ring_signature(const hash &, const key_image &, const public_key *const *, std::size_t, const signature *); + static void derive_view_tag(const key_derivation &, std::size_t, view_tag &); + friend void derive_view_tag(const key_derivation &, std::size_t, view_tag &); }; void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes); @@ -297,6 +303,14 @@ namespace crypto { return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig); } + /* Derive a 1-byte view tag from the sender-receiver shared secret to reduce scanning time. + * When scanning outputs that were not sent to the user, checking the view tag for a match removes the need to proceed with expensive EC operations + * for an expected 99.6% of outputs (expected false positive rate = 1/2^8 = 1/256 = 0.4% = 100% - 99.6%). + */ + inline void derive_view_tag(const key_derivation &derivation, std::size_t output_index, view_tag &vt) { + crypto_ops::derive_view_tag(derivation, output_index, vt); + } + inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; } @@ -312,6 +326,9 @@ namespace crypto { inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; } + inline std::ostream &operator <<(std::ostream &o, const crypto::view_tag &v) { + epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; + } const extern crypto::public_key null_pkey; const extern crypto::secret_key null_skey; @@ -325,3 +342,4 @@ CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(secret_key) CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(public_key_memsafe) CRYPTO_MAKE_HASHABLE(key_image) CRYPTO_MAKE_COMPARABLE(signature) +CRYPTO_MAKE_COMPARABLE(view_tag) diff --git a/src/crypto/crypto_ops_builder/README.md b/src/crypto/crypto_ops_builder/README.md index a3acb11e8..831c6a63c 100644 --- a/src/crypto/crypto_ops_builder/README.md +++ b/src/crypto/crypto_ops_builder/README.md @@ -1,6 +1,6 @@ # Monero -Copyright (c) 2014-2020, The Monero Project +Copyright (c) 2014-2022, The Monero Project ## Crypto Ops Builder diff --git a/src/crypto/crypto_ops_builder/crypto-ops-data.c b/src/crypto/crypto_ops_builder/crypto-ops-data.c index 64fd15070..4785f975f 100644 --- a/src/crypto/crypto_ops_builder/crypto-ops-data.c +++ b/src/crypto/crypto_ops_builder/crypto-ops-data.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/crypto_ops_builder/crypto-ops-old.c b/src/crypto/crypto_ops_builder/crypto-ops-old.c index da85ee534..5d632809e 100644 --- a/src/crypto/crypto_ops_builder/crypto-ops-old.c +++ b/src/crypto/crypto_ops_builder/crypto-ops-old.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/crypto_ops_builder/crypto-ops.h b/src/crypto/crypto_ops_builder/crypto-ops.h index d719743c4..568bf2a37 100644 --- a/src/crypto/crypto_ops_builder/crypto-ops.h +++ b/src/crypto/crypto_ops_builder/crypto-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/crypto_ops_builder/ref10CommentedCombined/MakeCryptoOps.py b/src/crypto/crypto_ops_builder/ref10CommentedCombined/MakeCryptoOps.py index 08cead175..16b6c0ba9 100644 --- a/src/crypto/crypto_ops_builder/ref10CommentedCombined/MakeCryptoOps.py +++ b/src/crypto/crypto_ops_builder/ref10CommentedCombined/MakeCryptoOps.py @@ -15,7 +15,7 @@ print("maybe someone smart can replace the sed with perl..") a = "" license = textwrap.dedent("""\ - // Copyright (c) 2014-2020, The Monero Project + // Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/crypto_ops_builder/ref10CommentedCombined/crypto-ops.h b/src/crypto/crypto_ops_builder/ref10CommentedCombined/crypto-ops.h index 613b718f5..8c0cbcda1 100644 --- a/src/crypto/crypto_ops_builder/ref10CommentedCombined/crypto-ops.h +++ b/src/crypto/crypto_ops_builder/ref10CommentedCombined/crypto-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/duration.h b/src/crypto/duration.h index 493874288..25d1c0b8c 100644 --- a/src/crypto/duration.h +++ b/src/crypto/duration.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/crypto/generic-ops.h b/src/crypto/generic-ops.h index 9aa7b065a..5a5e09f9b 100644 --- a/src/crypto/generic-ops.h +++ b/src/crypto/generic-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/groestl.h b/src/crypto/groestl.h index 7483db9b6..899660cb1 100644 --- a/src/crypto/groestl.h +++ b/src/crypto/groestl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/groestl_tables.h b/src/crypto/groestl_tables.h index 7bf03afd7..556354c47 100644 --- a/src/crypto/groestl_tables.h +++ b/src/crypto/groestl_tables.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/hash-extra-blake.c b/src/crypto/hash-extra-blake.c index 4cc915cdd..1557269e6 100644 --- a/src/crypto/hash-extra-blake.c +++ b/src/crypto/hash-extra-blake.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/hash-extra-groestl.c b/src/crypto/hash-extra-groestl.c index dec21310d..96230aed7 100644 --- a/src/crypto/hash-extra-groestl.c +++ b/src/crypto/hash-extra-groestl.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/hash-extra-jh.c b/src/crypto/hash-extra-jh.c index 0604003bd..4d7481c07 100644 --- a/src/crypto/hash-extra-jh.c +++ b/src/crypto/hash-extra-jh.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/hash-extra-skein.c b/src/crypto/hash-extra-skein.c index 55bd4ddec..9ea9c4faa 100644 --- a/src/crypto/hash-extra-skein.c +++ b/src/crypto/hash-extra-skein.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index 1cd502994..b7ec80d7c 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/hash.c b/src/crypto/hash.c index a917115fe..7c761a1b9 100644 --- a/src/crypto/hash.c +++ b/src/crypto/hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/hash.h b/src/crypto/hash.h index 4b99bebaa..2812422e0 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/hmac-keccak.c b/src/crypto/hmac-keccak.c index edcb2065e..771fcc27e 100644 --- a/src/crypto/hmac-keccak.c +++ b/src/crypto/hmac-keccak.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/hmac-keccak.h b/src/crypto/hmac-keccak.h index c450860d4..6b3633617 100644 --- a/src/crypto/hmac-keccak.h +++ b/src/crypto/hmac-keccak.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/initializer.h b/src/crypto/initializer.h index e9a7d97e2..90c09a087 100644 --- a/src/crypto/initializer.h +++ b/src/crypto/initializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/random.c b/src/crypto/random.c index 1e3d9beff..cfb637fb4 100644 --- a/src/crypto/random.c +++ b/src/crypto/random.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/random.h b/src/crypto/random.h index 8b81e7a66..d50f29430 100644 --- a/src/crypto/random.h +++ b/src/crypto/random.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/rx-slow-hash.c b/src/crypto/rx-slow-hash.c index 247c9032f..40ef96ac9 100644 --- a/src/crypto/rx-slow-hash.c +++ b/src/crypto/rx-slow-hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/skein_port.h b/src/crypto/skein_port.h index 94fd44035..2b701e8cc 100644 --- a/src/crypto/skein_port.h +++ b/src/crypto/skein_port.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 38aeeee54..0de7db505 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/tree-hash.c b/src/crypto/tree-hash.c index 8f3ea3339..93a1bce4d 100644 --- a/src/crypto/tree-hash.c +++ b/src/crypto/tree-hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/crypto/wallet/CMakeLists.txt b/src/crypto/wallet/CMakeLists.txt index 4ed986dce..ac1bdf7fd 100644 --- a/src/crypto/wallet/CMakeLists.txt +++ b/src/crypto/wallet/CMakeLists.txt @@ -1,4 +1,5 @@ -# Copyright (c) 2020, The Monero Project +# Copyright (c) 2020-2022, The Monero Project + # # All rights reserved. # diff --git a/src/crypto/wallet/crypto.h b/src/crypto/wallet/crypto.h index a4c5d5a07..cee0ca18e 100644 --- a/src/crypto/wallet/crypto.h +++ b/src/crypto/wallet/crypto.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/crypto/wallet/empty.h.in b/src/crypto/wallet/empty.h.in index ac252e1bd..b884a57b5 100644 --- a/src/crypto/wallet/empty.h.in +++ b/src/crypto/wallet/empty.h.in @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt index e386ec4ea..1414be1b2 100644 --- a/src/cryptonote_basic/CMakeLists.txt +++ b/src/cryptonote_basic/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -56,20 +56,7 @@ set(cryptonote_basic_sources set(cryptonote_basic_headers) -set(cryptonote_basic_private_headers - account.h - account_boost_serialization.h - connection_context.h - cryptonote_basic.h - cryptonote_basic_impl.h - cryptonote_boost_serialization.h - cryptonote_format_utils.h - difficulty.h - hardfork.h - merge_mining.h - miner.h - tx_extra.h - verification_context.h) +monero_find_all_headers(cryptonote_basic_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(cryptonote_basic ${cryptonote_basic_private_headers}) diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index 9927351a9..2ac455fda 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h index 96b024c3c..6e887db6d 100644 --- a/src/cryptonote_basic/account.h +++ b/src/cryptonote_basic/account.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/account_boost_serialization.h b/src/cryptonote_basic/account_boost_serialization.h index d97a5a854..ce0e4501a 100644 --- a/src/cryptonote_basic/account_boost_serialization.h +++ b/src/cryptonote_basic/account_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/blobdatatype.h b/src/cryptonote_basic/blobdatatype.h index 7f899993b..49735c034 100644 --- a/src/cryptonote_basic/blobdatatype.h +++ b/src/cryptonote_basic/blobdatatype.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/connection_context.cpp b/src/cryptonote_basic/connection_context.cpp index a0b8ca1f1..4395bad9f 100644 --- a/src/cryptonote_basic/connection_context.cpp +++ b/src/cryptonote_basic/connection_context.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/cryptonote_basic/connection_context.h b/src/cryptonote_basic/connection_context.h index ee26a0c07..818999a60 100644 --- a/src/cryptonote_basic/connection_context.h +++ b/src/cryptonote_basic/connection_context.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Parts of this file are originally copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net #pragma once #include <unordered_set> @@ -34,7 +35,6 @@ #include <algorithm> #include <boost/date_time/posix_time/posix_time.hpp> #include "net/net_utils_base.h" -#include "copyable_atomic.h" #include "crypto/hash.h" namespace cryptonote @@ -55,6 +55,37 @@ namespace cryptonote state_normal }; + /* + This class was originally from the EPEE module. It is identical in function to std::atomic<uint32_t> except + that it has copy-construction and copy-assignment defined, which means that earliers devs didn't have to write + custom copy-contructors and copy-assingment operators for the outer class, cryptonote_connection_context. + cryptonote_connection_context should probably be refactored because it is both trying to be POD-like while + also (very loosely) controlling access to its atomic members. + */ + class copyable_atomic: public std::atomic<uint32_t> + { + public: + copyable_atomic() + {}; + copyable_atomic(uint32_t value) + { store(value); } + copyable_atomic(const copyable_atomic& a):std::atomic<uint32_t>(a.load()) + {} + copyable_atomic& operator= (const copyable_atomic& a) + { + store(a.load()); + return *this; + } + uint32_t operator++() + { + return std::atomic<uint32_t>::operator++(); + } + uint32_t operator++(int fake) + { + return std::atomic<uint32_t>::operator++(fake); + } + }; + static constexpr int handshake_command() noexcept { return 1001; } bool handshake_complete() const noexcept { return m_state != state_before_handshake; } @@ -67,7 +98,7 @@ namespace cryptonote uint64_t m_remote_blockchain_height; uint64_t m_last_response_height; boost::posix_time::ptime m_last_request_time; - epee::copyable_atomic m_callback_request_count; //in debug purpose: problem with double callback rise + copyable_atomic m_callback_request_count; //in debug purpose: problem with double callback rise crypto::hash m_last_known_hash; uint32_t m_pruning_seed; uint16_t m_rpc_port; @@ -77,8 +108,8 @@ namespace cryptonote int m_expect_response; uint64_t m_expect_height; size_t m_num_requested; - epee::copyable_atomic m_new_stripe_notification{0}; - epee::copyable_atomic m_idle_peer_notification{0}; + copyable_atomic m_new_stripe_notification{0}; + copyable_atomic m_idle_peer_notification{0}; }; inline std::string get_protocol_state_string(cryptonote_connection_context::state s) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index d111f6f32..127958796 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -74,6 +74,7 @@ namespace cryptonote crypto::hash hash; }; + // outputs <= HF_VERSION_VIEW_TAGS struct txout_to_key { txout_to_key() { } @@ -81,6 +82,19 @@ namespace cryptonote crypto::public_key key; }; + // outputs >= HF_VERSION_VIEW_TAGS + struct txout_to_tagged_key + { + txout_to_tagged_key() { } + txout_to_tagged_key(const crypto::public_key &_key, const crypto::view_tag &_view_tag) : key(_key), view_tag(_view_tag) { } + crypto::public_key key; + crypto::view_tag view_tag; // optimization to reduce scanning time + + BEGIN_SERIALIZE_OBJECT() + FIELD(key) + FIELD(view_tag) + END_SERIALIZE() + }; /* inputs */ @@ -137,7 +151,7 @@ namespace cryptonote typedef boost::variant<txin_gen, txin_to_script, txin_to_scripthash, txin_to_key> txin_v; - typedef boost::variant<txout_to_script, txout_to_scripthash, txout_to_key> txout_target_v; + typedef boost::variant<txout_to_script, txout_to_scripthash, txout_to_key, txout_to_tagged_key> txout_target_v; //typedef std::pair<uint64_t, txout> out_t; struct tx_out @@ -562,6 +576,7 @@ VARIANT_TAG(binary_archive, cryptonote::txin_to_key, 0x2); VARIANT_TAG(binary_archive, cryptonote::txout_to_script, 0x0); VARIANT_TAG(binary_archive, cryptonote::txout_to_scripthash, 0x1); VARIANT_TAG(binary_archive, cryptonote::txout_to_key, 0x2); +VARIANT_TAG(binary_archive, cryptonote::txout_to_tagged_key, 0x3); VARIANT_TAG(binary_archive, cryptonote::transaction, 0xcc); VARIANT_TAG(binary_archive, cryptonote::block, 0xbb); @@ -572,6 +587,7 @@ VARIANT_TAG(json_archive, cryptonote::txin_to_key, "key"); VARIANT_TAG(json_archive, cryptonote::txout_to_script, "script"); VARIANT_TAG(json_archive, cryptonote::txout_to_scripthash, "scripthash"); VARIANT_TAG(json_archive, cryptonote::txout_to_key, "key"); +VARIANT_TAG(json_archive, cryptonote::txout_to_tagged_key, "tagged_key"); VARIANT_TAG(json_archive, cryptonote::transaction, "tx"); VARIANT_TAG(json_archive, cryptonote::block, "block"); @@ -582,5 +598,6 @@ VARIANT_TAG(debug_archive, cryptonote::txin_to_key, "key"); VARIANT_TAG(debug_archive, cryptonote::txout_to_script, "script"); VARIANT_TAG(debug_archive, cryptonote::txout_to_scripthash, "scripthash"); VARIANT_TAG(debug_archive, cryptonote::txout_to_key, "key"); +VARIANT_TAG(debug_archive, cryptonote::txout_to_tagged_key, "tagged_key"); VARIANT_TAG(debug_archive, cryptonote::transaction, "tx"); VARIANT_TAG(debug_archive, cryptonote::block, "block"); diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index 2600854a9..c60a62689 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h index 1303670d2..b423573c5 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.h +++ b/src/cryptonote_basic/cryptonote_basic_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index c6b81b094..493c9d91d 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -71,7 +71,11 @@ namespace boost { a & reinterpret_cast<char (&)[sizeof(crypto::key_image)]>(x); } - + template <class Archive> + inline void serialize(Archive &a, crypto::view_tag &x, const boost::serialization::version_type ver) + { + a & reinterpret_cast<char (&)[sizeof(crypto::view_tag)]>(x); + } template <class Archive> inline void serialize(Archive &a, crypto::signature &x, const boost::serialization::version_type ver) { @@ -103,6 +107,13 @@ namespace boost } template <class Archive> + inline void serialize(Archive &a, cryptonote::txout_to_tagged_key &x, const boost::serialization::version_type ver) + { + a & x.key; + a & x.view_tag; + } + + template <class Archive> inline void serialize(Archive &a, cryptonote::txout_to_scripthash &x, const boost::serialization::version_type ver) { a & x.hash; @@ -228,6 +239,20 @@ namespace boost } template <class Archive> + inline void serialize(Archive &a, rct::BulletproofPlus &x, const boost::serialization::version_type ver) + { + a & x.V; + a & x.A; + a & x.A1; + a & x.B; + a & x.r1; + a & x.s1; + a & x.d1; + a & x.L; + a & x.R; + } + + template <class Archive> inline void serialize(Archive &a, rct::boroSig &x, const boost::serialization::version_type ver) { a & x.s0; @@ -305,7 +330,7 @@ namespace boost a & x.type; if (x.type == rct::RCTTypeNull) return; - if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG) + if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus) throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); // a & x.message; message is not serialized, as it can be reconstructed from the tx data // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets @@ -321,7 +346,11 @@ namespace boost { a & x.rangeSigs; if (x.rangeSigs.empty()) + { a & x.bulletproofs; + if (ver >= 2u) + a & x.bulletproofs_plus; + } a & x.MGs; if (ver >= 1u) a & x.CLSAGs; @@ -335,7 +364,7 @@ namespace boost a & x.type; if (x.type == rct::RCTTypeNull) return; - if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG) + if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus) throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); // a & x.message; message is not serialized, as it can be reconstructed from the tx data // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets @@ -347,11 +376,15 @@ namespace boost //-------------- a & x.p.rangeSigs; if (x.p.rangeSigs.empty()) + { a & x.p.bulletproofs; + if (ver >= 2u) + a & x.p.bulletproofs_plus; + } a & x.p.MGs; if (ver >= 1u) a & x.p.CLSAGs; - if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG) + if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus) a & x.p.pseudoOuts; } @@ -392,6 +425,6 @@ namespace boost } } -BOOST_CLASS_VERSION(rct::rctSigPrunable, 1) -BOOST_CLASS_VERSION(rct::rctSig, 1) +BOOST_CLASS_VERSION(rct::rctSigPrunable, 2) +BOOST_CLASS_VERSION(rct::rctSig, 2) BOOST_CLASS_VERSION(rct::multisig_out, 1) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 835f59d69..432617a4f 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -105,7 +105,9 @@ namespace cryptonote uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs) { - const uint64_t bp_base = 368; + const rct::rctSig &rv = tx.rct_signatures; + const bool plus = rv.type == rct::RCTTypeBulletproofPlus; + const uint64_t bp_base = (32 * ((plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2) const size_t n_outputs = tx.vout.size(); if (n_padded_outputs <= 2) return 0; @@ -113,7 +115,7 @@ namespace cryptonote while ((1u << nlr) < n_padded_outputs) ++nlr; nlr += 6; - const size_t bp_size = 32 * (9 + 2 * nlr); + const size_t bp_size = 32 * ((plus ? 6 : 9) + 2 * nlr); CHECK_AND_ASSERT_THROW_MES_L1(n_outputs <= BULLETPROOF_MAX_OUTPUTS, "maximum number of outputs is " + std::to_string(BULLETPROOF_MAX_OUTPUTS) + " per transaction"); CHECK_AND_ASSERT_THROW_MES_L1(bp_base * n_padded_outputs >= bp_size, "Invalid bulletproof clawback: bp_base " + std::to_string(bp_base) + ", n_padded_outputs " + std::to_string(n_padded_outputs) + ", bp_size " + std::to_string(bp_size)); @@ -153,18 +155,44 @@ namespace cryptonote } for (size_t n = 0; n < tx.rct_signatures.outPk.size(); ++n) { - if (tx.vout[n].target.type() != typeid(txout_to_key)) + crypto::public_key output_public_key; + if (!get_output_public_key(tx.vout[n], output_public_key)) { - LOG_PRINT_L1("Unsupported output type in tx " << get_transaction_hash(tx)); + LOG_PRINT_L1("Failed to get output public key for output " << n << " in tx " << get_transaction_hash(tx)); return false; } - rv.outPk[n].dest = rct::pk2rct(boost::get<txout_to_key>(tx.vout[n].target).key); + rv.outPk[n].dest = rct::pk2rct(output_public_key); } if (!base_only) { const bool bulletproof = rct::is_rct_bulletproof(rv.type); - if (bulletproof) + const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type); + if (bulletproof_plus) + { + if (rv.p.bulletproofs_plus.size() != 1) + { + LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs_plus size in tx " << get_transaction_hash(tx)); + return false; + } + if (rv.p.bulletproofs_plus[0].L.size() < 6) + { + LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs_plus L size in tx " << get_transaction_hash(tx)); + return false; + } + const size_t max_outputs = rct::n_bulletproof_plus_max_amounts(rv.p.bulletproofs_plus[0]); + if (max_outputs < tx.vout.size()) + { + LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs_plus max outputs in tx " << get_transaction_hash(tx)); + return false; + } + const size_t n_amounts = tx.vout.size(); + CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V"); + rv.p.bulletproofs_plus[0].V.resize(n_amounts); + for (size_t i = 0; i < n_amounts; ++i) + rv.p.bulletproofs_plus[0].V[i] = rv.outPk[i].mask; + } + else if (bulletproof) { if (rv.p.bulletproofs.size() != 1) { @@ -419,9 +447,11 @@ namespace cryptonote if (tx.version < 2) return blob_size; const rct::rctSig &rv = tx.rct_signatures; - if (!rct::is_rct_bulletproof(rv.type)) + const bool bulletproof = rct::is_rct_bulletproof(rv.type); + const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type); + if (!bulletproof && !bulletproof_plus) return blob_size; - const size_t n_padded_outputs = rct::n_bulletproof_max_amounts(rv.p.bulletproofs); + const size_t n_padded_outputs = bulletproof_plus ? rct::n_bulletproof_plus_max_amounts(rv.p.bulletproofs_plus) : rct::n_bulletproof_max_amounts(rv.p.bulletproofs); uint64_t bp_clawback = get_transaction_weight_clawback(tx, n_padded_outputs); CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - blob_size, "Weight overflow"); return blob_size + bp_clawback; @@ -431,8 +461,8 @@ namespace cryptonote { CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support non pruned txes"); CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support v1 txes"); - CHECK_AND_ASSERT_MES(tx.rct_signatures.type >= rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG, - std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support older range proof types"); + CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus, + std::numeric_limits<uint64_t>::max(), "Unsupported rct_signatures type in get_pruned_transaction_weight"); CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits<uint64_t>::max(), "empty vin"); CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits<uint64_t>::max(), "empty vin"); @@ -450,12 +480,12 @@ namespace cryptonote while ((n_padded_outputs = (1u << nrl)) < tx.vout.size()) ++nrl; nrl += 6; - extra = 32 * (9 + 2 * nrl) + 2; + extra = 32 * ((rct::is_rct_bulletproof_plus(tx.rct_signatures.type) ? 6 : 9) + 2 * nrl) + 2; weight += extra; // calculate deterministic CLSAG/MLSAG data size const size_t ring_size = boost::get<cryptonote::txin_to_key>(tx.vin[0]).key_offsets.size(); - if (tx.rct_signatures.type == rct::RCTTypeCLSAG) + if (rct::is_rct_clsag(tx.rct_signatures.type)) extra = tx.vin.size() * (ring_size + 2) * 32; else extra = tx.vin.size() * (ring_size * (1 + 1) * 32 + 32 /* cc */); @@ -823,16 +853,16 @@ namespace cryptonote { for(const tx_out& out: tx.vout) { - CHECK_AND_ASSERT_MES(out.target.type() == typeid(txout_to_key), false, "wrong variant type: " - << out.target.type().name() << ", expected " << typeid(txout_to_key).name() - << ", in transaction id=" << get_transaction_hash(tx)); + crypto::public_key output_public_key; + CHECK_AND_ASSERT_MES(get_output_public_key(out, output_public_key), false, "Failed to get output public key (output type: " + << out.target.type().name() << "), in transaction id=" << get_transaction_hash(tx)); if (tx.version == 1) { CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx)); } - if(!check_key(boost::get<txout_to_key>(out.target).key)) + if(!check_key(output_public_key)) return false; } return true; @@ -876,6 +906,30 @@ namespace cryptonote return outputs_amount; } //--------------------------------------------------------------- + bool get_output_public_key(const cryptonote::tx_out& out, crypto::public_key& output_public_key) + { + // before HF_VERSION_VIEW_TAGS, outputs with public keys are of type txout_to_key + // after HF_VERSION_VIEW_TAGS, outputs with public keys are of type txout_to_tagged_key + if (out.target.type() == typeid(txout_to_key)) + output_public_key = boost::get< txout_to_key >(out.target).key; + else if (out.target.type() == typeid(txout_to_tagged_key)) + output_public_key = boost::get< txout_to_tagged_key >(out.target).key; + else + { + LOG_ERROR("Unexpected output target type found: " << out.target.type().name()); + return false; + } + + return true; + } + //--------------------------------------------------------------- + boost::optional<crypto::view_tag> get_output_view_tag(const cryptonote::tx_out& out) + { + return out.target.type() == typeid(txout_to_tagged_key) + ? boost::optional<crypto::view_tag>(boost::get< txout_to_tagged_key >(out.target).view_tag) + : boost::optional<crypto::view_tag>(); + } + //--------------------------------------------------------------- std::string short_hash_str(const crypto::hash& h) { std::string res = string_tools::pod_to_hex(h); @@ -885,45 +939,126 @@ namespace cryptonote return res; } //--------------------------------------------------------------- - bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, size_t output_index) + void set_tx_out(const uint64_t amount, const crypto::public_key& output_public_key, const bool use_view_tags, const crypto::view_tag& view_tag, tx_out& out) + { + out.amount = amount; + if (use_view_tags) + { + txout_to_tagged_key ttk; + ttk.key = output_public_key; + ttk.view_tag = view_tag; + out.target = ttk; + } + else + { + txout_to_key tk; + tk.key = output_public_key; + out.target = tk; + } + } + //--------------------------------------------------------------- + bool check_output_types(const transaction& tx, const uint8_t hf_version) + { + for (const auto &o: tx.vout) + { + if (hf_version > HF_VERSION_VIEW_TAGS) + { + // from v15, require outputs have view tags + CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_tagged_key), false, "wrong variant type: " + << o.target.type().name() << ", expected txout_to_tagged_key in transaction id=" << get_transaction_hash(tx)); + } + else if (hf_version < HF_VERSION_VIEW_TAGS) + { + // require outputs to be of type txout_to_key + CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "wrong variant type: " + << o.target.type().name() << ", expected txout_to_key in transaction id=" << get_transaction_hash(tx)); + } + else //(hf_version == HF_VERSION_VIEW_TAGS) + { + // require outputs be of type txout_to_key OR txout_to_tagged_key + // to allow grace period before requiring all to be txout_to_tagged_key + CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_to_tagged_key), false, "wrong variant type: " + << o.target.type().name() << ", expected txout_to_key or txout_to_tagged_key in transaction id=" << get_transaction_hash(tx)); + + // require all outputs in a tx be of the same type + CHECK_AND_ASSERT_MES(o.target.type() == tx.vout[0].target.type(), false, "non-matching variant types: " + << o.target.type().name() << " and " << tx.vout[0].target.type().name() << ", " + << "expected matching variant types in transaction id=" << get_transaction_hash(tx)); + } + } + return true; + } + //--------------------------------------------------------------- + bool out_can_be_to_acc(const boost::optional<crypto::view_tag>& view_tag_opt, const crypto::key_derivation& derivation, const size_t output_index) + { + // If there is no view tag to check, the output can possibly belong to the account. + // Will need to derive the output pub key to be certain whether or not the output belongs to the account. + if (!view_tag_opt) + return true; + + crypto::view_tag view_tag = *view_tag_opt; + + // If the output's view tag does *not* match the derived view tag, the output should not belong to the account. + // Therefore can fail out early to avoid expensive crypto ops needlessly deriving output public key to + // determine if output belongs to the account. + crypto::view_tag derived_view_tag; + crypto::derive_view_tag(derivation, output_index, derived_view_tag); + return view_tag == derived_view_tag; + } + //--------------------------------------------------------------- + bool is_out_to_acc(const account_keys& acc, const crypto::public_key& output_public_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, size_t output_index, const boost::optional<crypto::view_tag>& view_tag_opt) { crypto::key_derivation derivation; bool r = acc.get_device().generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation); CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); crypto::public_key pk; - r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk); - CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); - if (pk == out_key.key) - return true; + if (out_can_be_to_acc(view_tag_opt, derivation, output_index)) + { + r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk); + CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); + if (pk == output_public_key) + return true; + } + // try additional tx pubkeys if available if (!additional_tx_pub_keys.empty()) { CHECK_AND_ASSERT_MES(output_index < additional_tx_pub_keys.size(), false, "wrong number of additional tx pubkeys"); r = acc.get_device().generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation); CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); - r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk); - CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); - return pk == out_key.key; + if (out_can_be_to_acc(view_tag_opt, derivation, output_index)) + { + r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk); + CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); + return pk == output_public_key; + } } return false; } //--------------------------------------------------------------- - boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, hw::device &hwdev) + boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt) { // try the shared tx pubkey crypto::public_key subaddress_spendkey; - hwdev.derive_subaddress_public_key(out_key, derivation, output_index, subaddress_spendkey); - auto found = subaddresses.find(subaddress_spendkey); - if (found != subaddresses.end()) - return subaddress_receive_info{ found->second, derivation }; + if (out_can_be_to_acc(view_tag_opt, derivation, output_index)) + { + hwdev.derive_subaddress_public_key(out_key, derivation, output_index, subaddress_spendkey); + auto found = subaddresses.find(subaddress_spendkey); + if (found != subaddresses.end()) + return subaddress_receive_info{ found->second, derivation }; + } + // try additional tx pubkeys if available if (!additional_derivations.empty()) { CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations"); - hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey); - found = subaddresses.find(subaddress_spendkey); - if (found != subaddresses.end()) - return subaddress_receive_info{ found->second, additional_derivations[output_index] }; + if (out_can_be_to_acc(view_tag_opt, additional_derivations[output_index], output_index)) + { + hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey); + auto found = subaddresses.find(subaddress_spendkey); + if (found != subaddresses.end()) + return subaddress_receive_info{ found->second, additional_derivations[output_index] }; + } } return boost::none; } @@ -944,8 +1079,9 @@ namespace cryptonote size_t i = 0; for(const tx_out& o: tx.vout) { - CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "wrong type id in transaction out" ); - if(is_out_to_acc(acc, boost::get<txout_to_key>(o.target), tx_pub_key, additional_tx_pub_keys, i)) + crypto::public_key output_public_key; + CHECK_AND_ASSERT_MES(get_output_public_key(o, output_public_key), false, "unable to get output public key from transaction out" ); + if(is_out_to_acc(acc, output_public_key, tx_pub_key, additional_tx_pub_keys, i, get_output_view_tag(o))) { outs.push_back(i); money_transfered += o.amount; @@ -1035,6 +1171,69 @@ namespace cryptonote return s; } //--------------------------------------------------------------- + uint64_t round_money_up(uint64_t amount, unsigned significant_digits) + { + // round monetary amount up with the requested amount of significant digits + + CHECK_AND_ASSERT_THROW_MES(significant_digits > 0, "significant_digits must not be 0"); + static_assert(sizeof(unsigned long long) == sizeof(uint64_t), "Unexpected unsigned long long size"); + + // we don't need speed, so we do it via text, as it's easier to get right + char buf[32]; + snprintf(buf, sizeof(buf), "%llu", (unsigned long long)amount); + const size_t len = strlen(buf); + if (len > significant_digits) + { + bool bump = false; + char *ptr; + for (ptr = buf + significant_digits; *ptr; ++ptr) + { + // bump digits by one if the following digits past significant digits were to be 5 or more + if (*ptr != '0') + { + bump = true; + *ptr = '0'; + } + } + ptr = buf + significant_digits; + while (bump && ptr > buf) + { + --ptr; + // bumping a nine overflows + if (*ptr == '9') + *ptr = '0'; + else + { + // bumping another digit means we can stop bumping (no carry) + ++*ptr; + bump = false; + } + } + if (bump) + { + // carry reached the highest digit, we need to add a 1 in front + size_t offset = strlen(buf); + for (size_t i = offset + 1; i > 0; --i) + buf[i] = buf[i - 1]; + buf[0] = '1'; + } + } + char *end = NULL; + errno = 0; + const unsigned long long ull = strtoull(buf, &end, 10); + CHECK_AND_ASSERT_THROW_MES(ull != ULONG_MAX || errno == 0, "Failed to parse rounded amount: " << buf); + CHECK_AND_ASSERT_THROW_MES(ull != 0 || amount == 0, "Overflow in rounding"); + return ull; + } + //--------------------------------------------------------------- + std::string round_money_up(const std::string &s, unsigned significant_digits) + { + uint64_t amount; + CHECK_AND_ASSERT_THROW_MES(parse_amount(amount, s), "Failed to parse amount: " << s); + amount = round_money_up(amount, significant_digits); + return print_money(amount); + } + //--------------------------------------------------------------- crypto::hash get_blob_hash(const blobdata& blob) { crypto::hash h = null_hash; diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index 3fe4c44e7..8f5459ca7 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -89,13 +89,16 @@ namespace cryptonote void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id); bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id); bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id); - bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t output_index); + void set_tx_out(const uint64_t amount, const crypto::public_key& output_public_key, const bool use_view_tags, const crypto::view_tag& view_tag, tx_out& out); + bool check_output_types(const transaction& tx, const uint8_t hf_version); + bool out_can_be_to_acc(const boost::optional<crypto::view_tag>& view_tag_opt, const crypto::key_derivation& derivation, const size_t output_index); + bool is_out_to_acc(const account_keys& acc, const crypto::public_key& output_public_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t output_index, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>()); struct subaddress_receive_info { subaddress_index index; crypto::key_derivation derivation; }; - boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, hw::device &hwdev); + boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>()); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, std::vector<size_t>& outs, uint64_t& money_transfered); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered); bool get_tx_fee(const transaction& tx, uint64_t & fee); @@ -126,6 +129,8 @@ namespace cryptonote bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash &block_hash); bool get_inputs_money_amount(const transaction& tx, uint64_t& money); uint64_t get_outs_money_amount(const transaction& tx); + bool get_output_public_key(const cryptonote::tx_out& out, crypto::public_key& output_public_key); + boost::optional<crypto::view_tag> get_output_view_tag(const cryptonote::tx_out& out); bool check_inputs_types_supported(const transaction& tx); bool check_outs_valid(const transaction& tx); bool parse_amount(uint64_t& amount, const std::string& str_amount); @@ -144,6 +149,8 @@ namespace cryptonote std::string get_unit(unsigned int decimal_point = -1); std::string print_money(uint64_t amount, unsigned int decimal_point = -1); std::string print_money(const boost::multiprecision::uint128_t &amount, unsigned int decimal_point = -1); + uint64_t round_money_up(uint64_t amount, unsigned significant_digits); + std::string round_money_up(const std::string &amount, unsigned significant_digits); //--------------------------------------------------------------- template<class t_object> bool t_serializable_object_from_blob(t_object& to, const blobdata& b_blob) diff --git a/src/cryptonote_basic/cryptonote_format_utils_basic.cpp b/src/cryptonote_basic/cryptonote_format_utils_basic.cpp index 29130ce46..7431a1beb 100644 --- a/src/cryptonote_basic/cryptonote_format_utils_basic.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils_basic.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2021, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index dbc2e534a..165c1936e 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/difficulty.h b/src/cryptonote_basic/difficulty.h index 7f5ea4597..ee9378eb9 100644 --- a/src/cryptonote_basic/difficulty.h +++ b/src/cryptonote_basic/difficulty.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/events.h b/src/cryptonote_basic/events.h index 3417ece8c..18ea99800 100644 --- a/src/cryptonote_basic/events.h +++ b/src/cryptonote_basic/events.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/cryptonote_basic/fwd.h b/src/cryptonote_basic/fwd.h index 901ad151b..54f3c0184 100644 --- a/src/cryptonote_basic/fwd.h +++ b/src/cryptonote_basic/fwd.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/cryptonote_basic/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp index 7a5161bc8..a0ea3633f 100644 --- a/src/cryptonote_basic/hardfork.cpp +++ b/src/cryptonote_basic/hardfork.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/hardfork.h b/src/cryptonote_basic/hardfork.h index 5800c31b5..32f669c71 100644 --- a/src/cryptonote_basic/hardfork.h +++ b/src/cryptonote_basic/hardfork.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/merge_mining.cpp b/src/cryptonote_basic/merge_mining.cpp index fcc74859f..b8d16aade 100644 --- a/src/cryptonote_basic/merge_mining.cpp +++ b/src/cryptonote_basic/merge_mining.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/cryptonote_basic/merge_mining.h b/src/cryptonote_basic/merge_mining.h index 378438f7c..8fe282a76 100644 --- a/src/cryptonote_basic/merge_mining.h +++ b/src/cryptonote_basic/merge_mining.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index ae514aac6..5b0db9518 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -30,7 +30,6 @@ #include <sstream> #include <numeric> -#include <boost/interprocess/detail/atomic.hpp> #include <boost/algorithm/string.hpp> #include "misc_language.h" #include "syncobj.h" @@ -271,13 +270,13 @@ namespace cryptonote // restart all threads { CRITICAL_REGION_LOCAL(m_threads_lock); - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1); + m_stop = true; while (m_threads_active > 0) misc_utils::sleep_no_w(100); m_threads.clear(); } - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0); - boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0); + m_stop = false; + m_thread_index = 0; for(size_t i = 0; i != m_threads_total; i++) m_threads.push_back(boost::thread(m_attrs, boost::bind(&miner::worker_thread, this))); } @@ -394,8 +393,8 @@ namespace cryptonote request_block_template();//lets update block template - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0); - boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0); + m_stop = false; + m_thread_index = 0; set_is_background_mining_enabled(do_background); set_ignore_battery(ignore_battery); @@ -435,7 +434,7 @@ namespace cryptonote //----------------------------------------------------------------------------------------------------- void miner::send_stop_signal() { - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1); + m_stop = true; } extern "C" void rx_stop_mining(void); //----------------------------------------------------------------------------------------------------- @@ -524,7 +523,7 @@ namespace cryptonote //----------------------------------------------------------------------------------------------------- bool miner::worker_thread() { - uint32_t th_local_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); + const uint32_t th_local_index = m_thread_index++; // atomically increment, getting value before increment MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]"); MGINFO("Miner thread was started ["<< th_local_index << "]"); uint32_t nonce = m_starter_nonce + th_local_index; diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h index df3f56f68..72dc12762 100644 --- a/src/cryptonote_basic/miner.h +++ b/src/cryptonote_basic/miner.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -118,14 +118,14 @@ namespace cryptonote }; - volatile uint32_t m_stop; + std::atomic<bool> m_stop; epee::critical_section m_template_lock; block m_template; std::atomic<uint32_t> m_template_no; std::atomic<uint32_t> m_starter_nonce; difficulty_type m_diffic; uint64_t m_height; - volatile uint32_t m_thread_index; + std::atomic<uint32_t> m_thread_index; volatile uint32_t m_threads_total; std::atomic<uint32_t> m_threads_active; std::atomic<int32_t> m_pausers_count; diff --git a/src/cryptonote_basic/subaddress_index.h b/src/cryptonote_basic/subaddress_index.h index 3f5f120d9..612d1e8a5 100644 --- a/src/cryptonote_basic/subaddress_index.h +++ b/src/cryptonote_basic/subaddress_index.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/tx_extra.h b/src/cryptonote_basic/tx_extra.h index 76efc22d3..141f72352 100644 --- a/src/cryptonote_basic/tx_extra.h +++ b/src/cryptonote_basic/tx_extra.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_basic/verification_context.h b/src/cryptonote_basic/verification_context.h index 2535cba95..34157218f 100644 --- a/src/cryptonote_basic/verification_context.h +++ b/src/cryptonote_basic/verification_context.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index b738960a3..f2a8e9b79 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -126,6 +126,7 @@ #define COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT 1000 #define COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT 20000 +#define MAX_RPC_CONTENT_LENGTH 1048576 // 1 MB #define P2P_LOCAL_WHITE_PEERLIST_LIMIT 1000 #define P2P_LOCAL_GRAY_PEERLIST_LIMIT 5000 @@ -169,6 +170,7 @@ #define HF_VERSION_MIN_MIXIN_4 6 #define HF_VERSION_MIN_MIXIN_6 7 #define HF_VERSION_MIN_MIXIN_10 8 +#define HF_VERSION_MIN_MIXIN_15 15 #define HF_VERSION_ENFORCE_RCT 6 #define HF_VERSION_PER_BYTE_FEE 8 #define HF_VERSION_SMALLER_BP 10 @@ -182,14 +184,19 @@ #define HF_VERSION_EXACT_COINBASE 13 #define HF_VERSION_CLSAG 13 #define HF_VERSION_DETERMINISTIC_UNLOCK_TIME 13 +#define HF_VERSION_BULLETPROOF_PLUS 15 +#define HF_VERSION_VIEW_TAGS 15 +#define HF_VERSION_2021_SCALING 15 #define PER_KB_FEE_QUANTIZATION_DECIMALS 8 +#define CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES 2 #define HASH_OF_HASHES_STEP 512 #define DEFAULT_TXPOOL_MAX_WEIGHT 648000000ull // 3 days at 300000, in bytes #define BULLETPROOF_MAX_OUTPUTS 16 +#define BULLETPROOF_PLUS_MAX_OUTPUTS 16 #define CRYPTONOTE_PRUNING_STRIPE_SIZE 4096 // the smaller, the smoother the increase #define CRYPTONOTE_PRUNING_LOG_STRIPES 3 // the higher, the more space saved @@ -221,6 +228,8 @@ namespace config // Hash domain separators const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof"; + const char HASH_KEY_BULLETPROOF_PLUS_EXPONENT[] = "bulletproof_plus"; + const char HASH_KEY_BULLETPROOF_PLUS_TRANSCRIPT[] = "bulletproof_plus_transcript"; const char HASH_KEY_RINGDB[] = "ringdsb"; const char HASH_KEY_SUBADDRESS[] = "SubAddr"; const unsigned char HASH_KEY_ENCRYPTED_PAYMENT_ID = 0x8d; diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 0be8b544e..e272b94f0 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -35,13 +35,7 @@ set(cryptonote_core_sources set(cryptonote_core_headers) -set(cryptonote_core_private_headers - blockchain_storage_boost_serialization.h - blockchain.h - cryptonote_core.h - tx_pool.h - tx_sanity_check.h - cryptonote_tx_utils.h) +monero_find_all_headers(cryptonote_core_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(cryptonote_core ${cryptonote_core_private_headers}) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 34031fb7c..5b7b4353d 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -1341,6 +1341,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: // one input, of type txin_gen, with height set to the block's height // correct miner tx unlock time // a non-overflowing tx amount (dubious necessity on this check) +// valid output types bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, uint8_t hf_version) { LOG_PRINT_L3("Blockchain::" << __func__); @@ -1363,15 +1364,14 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW); //check outs overflow - //NOTE: not entirely sure this is necessary, given that this function is - // designed simply to make sure the total amount for a transaction - // does not overflow a uint64_t, and this transaction *is* a uint64_t... if(!check_outs_overflow(b.miner_tx)) { MERROR("miner transaction has money overflow in block " << get_block_hash(b)); return false; } + CHECK_AND_ASSERT_MES(check_output_types(b.miner_tx, hf_version), false, "miner transaction has invalid output type(s) in block " << get_block_hash(b)); + return true; } //------------------------------------------------------------------ @@ -3047,12 +3047,14 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context // from v4, forbid invalid pubkeys if (hf_version >= 4) { for (const auto &o: tx.vout) { - if (o.target.type() == typeid(txout_to_key)) { - const txout_to_key& out_to_key = boost::get<txout_to_key>(o.target); - if (!crypto::check_key(out_to_key.key)) { - tvc.m_invalid_output = true; - return false; - } + crypto::public_key output_public_key; + if (!get_output_public_key(o, output_public_key)) { + tvc.m_invalid_output = true; + return false; + } + if (!crypto::check_key(output_public_key)) { + tvc.m_invalid_output = true; + return false; } } } @@ -3143,6 +3145,39 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context } } + // from v15, allow bulletproofs plus + if (hf_version < HF_VERSION_BULLETPROOF_PLUS) { + if (tx.version >= 2) { + const bool bulletproof_plus = rct::is_rct_bulletproof_plus(tx.rct_signatures.type); + if (bulletproof_plus || !tx.rct_signatures.p.bulletproofs_plus.empty()) + { + MERROR_VER("Bulletproofs plus are not allowed before v" << std::to_string(HF_VERSION_BULLETPROOF_PLUS)); + tvc.m_invalid_output = true; + return false; + } + } + } + + // from v16, forbid bulletproofs + if (hf_version > HF_VERSION_BULLETPROOF_PLUS) { + if (tx.version >= 2) { + const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type); + if (bulletproof) + { + MERROR_VER("Bulletproof range proofs are not allowed after v" + std::to_string(HF_VERSION_BULLETPROOF_PLUS)); + tvc.m_invalid_output = true; + return false; + } + } + } + + // from v15, require view tags on outputs + if (!check_output_types(tx, hf_version)) + { + tvc.m_invalid_output = true; + return false; + } + return true; } //------------------------------------------------------------------ @@ -3183,7 +3218,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr } } } - else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeCLSAG) + else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus) { CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys"); rv.mixRing.resize(pubkeys.size()); @@ -3224,7 +3259,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr } } } - else if (rv.type == rct::RCTTypeCLSAG) + else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus) { if (!tx.pruned) { @@ -3286,7 +3321,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, size_t n_unmixable = 0, n_mixable = 0; size_t min_actual_mixin = std::numeric_limits<size_t>::max(); size_t max_actual_mixin = 0; - const size_t min_mixin = hf_version >= HF_VERSION_MIN_MIXIN_10 ? 10 : hf_version >= HF_VERSION_MIN_MIXIN_6 ? 6 : hf_version >= HF_VERSION_MIN_MIXIN_4 ? 4 : 2; + const size_t min_mixin = hf_version >= HF_VERSION_MIN_MIXIN_15 ? 15 : hf_version >= HF_VERSION_MIN_MIXIN_10 ? 10 : hf_version >= HF_VERSION_MIN_MIXIN_6 ? 6 : hf_version >= HF_VERSION_MIN_MIXIN_4 ? 4 : 2; for (const auto& txin : tx.vin) { // non txin_to_key inputs will be rejected below @@ -3329,14 +3364,11 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, } } - if (((hf_version == HF_VERSION_MIN_MIXIN_10 || hf_version == HF_VERSION_MIN_MIXIN_10+1) && min_actual_mixin != 10) || (hf_version >= HF_VERSION_MIN_MIXIN_10+2 && min_actual_mixin > 10)) - { - MERROR_VER("Tx " << get_transaction_hash(tx) << " has invalid ring size (" << (min_actual_mixin + 1) << "), it should be 11"); - tvc.m_low_mixin = true; - return false; - } - - if (min_actual_mixin < min_mixin) + // The only circumstance where ring sizes less than expected are + // allowed is when spending unmixable non-RCT outputs in the chain. + // Caveat: at HF_VERSION_MIN_MIXIN_15, temporarily allow ring sizes + // of 11 to allow a grace period in the transition to larger ring size. + if (min_actual_mixin < min_mixin && !(hf_version == HF_VERSION_MIN_MIXIN_15 && min_actual_mixin == 10)) { if (n_unmixable == 0) { @@ -3350,6 +3382,15 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, tvc.m_low_mixin = true; return false; } + } else if ((hf_version > HF_VERSION_MIN_MIXIN_15 && min_actual_mixin > 15) + || (hf_version == HF_VERSION_MIN_MIXIN_15 && min_actual_mixin != 15 && min_actual_mixin != 10) // grace period to allow either 15 or 10 + || (hf_version < HF_VERSION_MIN_MIXIN_15 && hf_version >= HF_VERSION_MIN_MIXIN_10+2 && min_actual_mixin > 10) + || ((hf_version == HF_VERSION_MIN_MIXIN_10 || hf_version == HF_VERSION_MIN_MIXIN_10+1) && min_actual_mixin != 10) + ) + { + MERROR_VER("Tx " << get_transaction_hash(tx) << " has invalid ring size (" << (min_actual_mixin + 1) << "), it should be " << (min_mixin + 1)); + tvc.m_low_mixin = true; + return false; } // min/max tx version based on HF, and we accept v1 txes if having a non mixable @@ -3516,6 +3557,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, case rct::RCTTypeBulletproof: case rct::RCTTypeBulletproof2: case rct::RCTTypeCLSAG: + case rct::RCTTypeBulletproofPlus: { // check all this, either reconstructed (so should really pass), or not { @@ -3551,7 +3593,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, } } - const size_t n_sigs = rv.type == rct::RCTTypeCLSAG ? rv.p.CLSAGs.size() : rv.p.MGs.size(); + const size_t n_sigs = rct::is_rct_clsag(rv.type) ? rv.p.CLSAGs.size() : rv.p.MGs.size(); if (n_sigs != tx.vin.size()) { MERROR_VER("Failed to check ringct signatures: mismatched MGs/vin sizes"); @@ -3560,7 +3602,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, for (size_t n = 0; n < tx.vin.size(); ++n) { bool error; - if (rv.type == rct::RCTTypeCLSAG) + if (rct::is_rct_clsag(rv.type)) error = memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.CLSAGs[n].I, 32); else error = rv.p.MGs[n].II.empty() || memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32); @@ -3686,11 +3728,24 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b if (version >= HF_VERSION_PER_BYTE_FEE) { lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi); - div128_64(hi, lo, min_block_weight, &hi, &lo, NULL, NULL); div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL); - assert(hi == 0); - lo /= 5; - return lo; + if (version >= HF_VERSION_2021_SCALING) + { + // min_fee_per_byte = round_up( 0.95 * block_reward * ref_weight / (fee_median^2) ) + // note: since hardfork HF_VERSION_2021_SCALING, fee_median (a.k.a. median_block_weight) equals effective long term median + div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL); + assert(hi == 0); + lo -= lo / 20; + return lo; + } + else + { + // min_fee_per_byte = 0.2 * block_reward * ref_weight / (min_penalty_free_zone * fee_median) + div128_64(hi, lo, min_block_weight, &hi, &lo, NULL, NULL); + assert(hi == 0); + lo /= 5; + return lo; + } } const uint64_t fee_base = version >= 5 ? DYNAMIC_FEE_PER_KB_BASE_FEE_V5 : DYNAMIC_FEE_PER_KB_BASE_FEE; @@ -3763,6 +3818,81 @@ bool Blockchain::check_fee(size_t tx_weight, uint64_t fee) const } //------------------------------------------------------------------ +void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, uint64_t base_reward, uint64_t Mnw, uint64_t Mlw, std::vector<uint64_t> &fees) const +{ + // variable names and calculations as per https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf + // from (earlier than) this fork, the base fee is per byte + const uint64_t Mfw = std::min(Mnw, Mlw); + + // 3 kB divided by something ? It's going to be either 0 or *very* quantized, so fold it into integer steps below + //const uint64_t Brlw = DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / Mfw; + + // constant.... equal to 0, unless floating point, so fold it into integer steps below + //const uint64_t Br = DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 + + //const uint64_t Fl = base_reward * Brlw / Mfw; fold Brlw from above + const uint64_t Fl = base_reward * /*Brlw*/ DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / (Mfw * Mfw); + + // fold Fl into this for better precision (and to match the test cases in the PDF) + // const uint64_t Fn = 4 * Fl; + const uint64_t Fn = 4 * base_reward * /*Brlw*/ DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / (Mfw * Mfw); + + // const uint64_t Fm = 16 * base_reward * Br / Mfw; fold Br from above + const uint64_t Fm = 16 * base_reward * DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT / (CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 * Mfw); + + // const uint64_t Fp = 2 * base_reward / Mnw; + + // fold Br from above, move 4Fm in the max to decrease quantization effect + //const uint64_t Fh = 4 * Fm * std::max<uint64_t>(1, Mfw / (32 * DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT * Mnw / CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5)); + const uint64_t Fh = std::max<uint64_t>(4 * Fm, 4 * Fm * Mfw / (32 * DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT * Mnw / CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5)); + + fees.resize(4); + fees[0] = cryptonote::round_money_up(Fl, CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES); + fees[1] = cryptonote::round_money_up(Fn, CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES); + fees[2] = cryptonote::round_money_up(Fm, CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES); + fees[3] = cryptonote::round_money_up(Fh, CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES); +} + +void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, std::vector<uint64_t> &fees) const +{ + const uint8_t version = get_current_hard_fork_version(); + const uint64_t db_height = m_db->height(); + + // we want Mlw = median of max((min(Mbw, 1.7 * Ml), Zm), Ml / 1.7) + // Mbw: block weight for the last 99990 blocks, 0 for the next 10 + // Ml: penalty free zone (dynamic), aka long_term_median, aka median of max((min(Mb, 1.7 * Ml), Zm), Ml / 1.7) + // Zm: 300000 (minimum penalty free zone) + // + // So we copy the current rolling median state, add 10 (grace_blocks) zeroes to it, and get back Mlw + + epee::misc_utils::rolling_median_t<uint64_t> rm = m_long_term_block_weights_cache_rolling_median; + for (size_t i = 0; i < grace_blocks; ++i) + rm.insert(0); + const uint64_t Mlw_penalty_free_zone_for_wallet = std::max<uint64_t>(rm.median(), CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5); + + // Msw: median over [100 - grace blocks] past + [grace blocks] future blocks + CHECK_AND_ASSERT_THROW_MES(grace_blocks <= 100, "Grace blocks invalid In 2021 fee scaling estimate."); + std::vector<uint64_t> weights; + get_last_n_blocks_weights(weights, 100 - grace_blocks); + weights.reserve(100); + for (size_t i = 0; i < grace_blocks; ++i) + weights.push_back(0); + const uint64_t Msw_effective_short_term_median = std::max(epee::misc_utils::median(weights), Mlw_penalty_free_zone_for_wallet); + + const uint64_t Mnw = std::min(Msw_effective_short_term_median, 50 * Mlw_penalty_free_zone_for_wallet); + + uint64_t already_generated_coins = db_height ? m_db->get_block_already_generated_coins(db_height - 1) : 0; + uint64_t base_reward; + if (!get_block_reward(m_current_block_cumul_weight_limit / 2, 1, already_generated_coins, base_reward, version)) + { + MERROR("Failed to determine block reward, using placeholder " << print_money(BLOCK_REWARD_OVERESTIMATE) << " as a high bound"); + base_reward = BLOCK_REWARD_OVERESTIMATE; + } + + get_dynamic_base_fee_estimate_2021_scaling(grace_blocks, base_reward, Mnw, Mlw_penalty_free_zone_for_wallet, fees); +} + +//------------------------------------------------------------------ uint64_t Blockchain::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const { const uint8_t version = get_current_hard_fork_version(); @@ -3774,6 +3904,13 @@ uint64_t Blockchain::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const if (grace_blocks >= CRYPTONOTE_REWARD_BLOCKS_WINDOW) grace_blocks = CRYPTONOTE_REWARD_BLOCKS_WINDOW - 1; + if (version >= HF_VERSION_2021_SCALING) + { + std::vector<uint64_t> fees; + get_dynamic_base_fee_estimate_2021_scaling(grace_blocks, fees); + return fees[0]; + } + const uint64_t min_block_weight = get_min_block_weight(version); std::vector<uint64_t> weights; get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW - grace_blocks); @@ -3858,9 +3995,11 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key& txin, cons } // The original code includes a check for the output corresponding to this input - // to be a txout_to_key. This is removed, as the database does not store this info, - // but only txout_to_key outputs are stored in the DB in the first place, done in - // Blockchain*::add_output + // to be a txout_to_key. This is removed, as the database does not store this info. + // Only txout_to_key (and since HF_VERSION_VIEW_TAGS, txout_to_tagged_key) + // outputs are stored in the DB in the first place, done in Blockchain*::add_output. + // Additional type checks on outputs were also added via cryptonote::check_output_types + // and cryptonote::get_output_public_key (see Blockchain::check_tx_outputs). m_output_keys.push_back(rct::ctkey({rct::pk2rct(pubkey), commitment})); return true; @@ -4448,6 +4587,7 @@ bool Blockchain::check_blockchain_pruning() return m_db->check_pruning(); } //------------------------------------------------------------------ +// returns min(Mb, 1.7*Ml) as per https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf from HF_VERSION_LONG_TERM_BLOCK_WEIGHT uint64_t Blockchain::get_next_long_term_block_weight(uint64_t block_weight) const { PERF_TIMER(get_next_long_term_block_weight); @@ -4462,7 +4602,18 @@ uint64_t Blockchain::get_next_long_term_block_weight(uint64_t block_weight) cons uint64_t long_term_median = get_long_term_block_weight_median(db_height - nblocks, nblocks); uint64_t long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median); - uint64_t short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5; + uint64_t short_term_constraint; + if (hf_version >= HF_VERSION_2021_SCALING) + { + // long_term_block_weight = block_weight bounded to range [long-term-median/1.7, long-term-median*1.7] + block_weight = std::max<uint64_t>(block_weight, long_term_effective_median_block_weight * 10 / 17); + short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 7 / 10; + } + else + { + // long_term_block_weight = block_weight bounded to range [0, long-term-median*1.4] + short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5; + } uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint); return long_term_block_weight; @@ -4504,7 +4655,11 @@ bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effecti m_long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median); - uint64_t short_term_constraint = m_long_term_effective_median_block_weight + m_long_term_effective_median_block_weight * 2 / 5; + uint64_t short_term_constraint = m_long_term_effective_median_block_weight; + if (hf_version >= HF_VERSION_2021_SCALING) + short_term_constraint += m_long_term_effective_median_block_weight * 7 / 10; + else + short_term_constraint += m_long_term_effective_median_block_weight * 2 / 5; uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint); if (db_height == 1) @@ -4523,7 +4678,19 @@ bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effecti get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW); uint64_t short_term_median = epee::misc_utils::median(weights); - uint64_t effective_median_block_weight = std::min<uint64_t>(std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, short_term_median), CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR * m_long_term_effective_median_block_weight); + uint64_t effective_median_block_weight; + if (hf_version >= HF_VERSION_2021_SCALING) + { + // effective median = short_term_median bounded to range [long_term_median, 50*long_term_median], but it can't be smaller than the + // minimum penalty free zone (a.k.a. 'full reward zone') + effective_median_block_weight = std::min<uint64_t>(std::max<uint64_t>(m_long_term_effective_median_block_weight, short_term_median), CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR * m_long_term_effective_median_block_weight); + } + else + { + // effective median = short_term_median bounded to range [0, 50*long_term_median], but it can't be smaller than the + // minimum penalty free zone (a.k.a. 'full reward zone') + effective_median_block_weight = std::min<uint64_t>(std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, short_term_median), CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR * m_long_term_effective_median_block_weight); + } m_current_block_cumul_weight_median = effective_median_block_weight; } diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 9afbfbc2d..7a94f6358 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -648,6 +648,22 @@ namespace cryptonote * @return the fee estimate */ uint64_t get_dynamic_base_fee_estimate(uint64_t grace_blocks) const; + void get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, uint64_t base_reward, uint64_t Mnw, uint64_t Mlw, std::vector<uint64_t> &fees) const; + + /** + * @brief get four levels of dynamic per byte fee estimate for the next few blocks + * + * The dynamic fee is based on the block weight in a past window, and + * the current block reward. It is expressed per byte, and is based on + * https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf + * This function calculates an estimate for a dynamic fee which will be + * valid for the next grace_blocks + * + * @param grace_blocks number of blocks we want the fee to be valid for + * + * @return the fee estimates (4 of them) + */ + void get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, std::vector<uint64_t> &fees) const; /** * @brief validate a transaction's fee diff --git a/src/cryptonote_core/blockchain_storage_boost_serialization.h b/src/cryptonote_core/blockchain_storage_boost_serialization.h index b5c14d53c..d166caf76 100644 --- a/src/cryptonote_core/blockchain_storage_boost_serialization.h +++ b/src/cryptonote_core/blockchain_storage_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 4c6536318..a78f5d673 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -879,6 +879,16 @@ namespace cryptonote return true; } //----------------------------------------------------------------------------------------------- + static bool is_canonical_bulletproof_plus_layout(const std::vector<rct::BulletproofPlus> &proofs) + { + if (proofs.size() != 1) + return false; + const size_t sz = proofs[0].V.size(); + if (sz == 0 || sz > BULLETPROOF_PLUS_MAX_OUTPUTS) + return false; + return true; + } + //----------------------------------------------------------------------------------------------- bool core::handle_incoming_tx_accumulated_batch(std::vector<tx_verification_batch_info> &tx_info, bool keeped_by_block) { bool ret = true; @@ -943,6 +953,17 @@ namespace cryptonote } rvv.push_back(&rv); // delayed batch verification break; + case rct::RCTTypeBulletproofPlus: + if (!is_canonical_bulletproof_plus_layout(rv.p.bulletproofs_plus)) + { + MERROR_VER("Bulletproof_plus does not have canonical form"); + set_semantics_failed(tx_info[n].tx_hash); + tx_info[n].tvc.m_verifivation_failed = true; + tx_info[n].result = false; + break; + } + rvv.push_back(&rv); // delayed batch verification + break; default: MERROR_VER("Unknown rct type: " << rv.type); set_semantics_failed(tx_info[n].tx_hash); @@ -960,7 +981,7 @@ namespace cryptonote { if (!tx_info[n].result) continue; - if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG) + if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproofPlus) continue; if (assumed_bad || !rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures)) { @@ -1156,7 +1177,8 @@ namespace cryptonote return false; } - if (!check_tx_inputs_ring_members_diff(tx)) + const uint8_t hf_version = m_blockchain_storage.get_current_hard_fork_version(); + if (!check_tx_inputs_ring_members_diff(tx, hf_version)) { MERROR_VER("tx uses duplicate ring members"); return false; @@ -1168,6 +1190,12 @@ namespace cryptonote return false; } + if (!check_output_types(tx, hf_version)) + { + MERROR_VER("tx does not use valid output type(s)"); + return false; + } + return true; } //----------------------------------------------------------------------------------------------- @@ -1274,10 +1302,9 @@ namespace cryptonote return true; } //----------------------------------------------------------------------------------------------- - bool core::check_tx_inputs_ring_members_diff(const transaction& tx) const + bool core::check_tx_inputs_ring_members_diff(const transaction& tx, const uint8_t hf_version) const { - const uint8_t version = m_blockchain_storage.get_current_hard_fork_version(); - if (version >= 6) + if (hf_version >= 6) { for(const auto& in: tx.vin) { diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index d2bffdaee..0b36730b6 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -40,7 +40,6 @@ #include "cryptonote_core/i_core_events.h" #include "cryptonote_protocol/cryptonote_protocol_handler_common.h" #include "cryptonote_protocol/enums.h" -#include "storages/portable_storage_template_helper.h" #include "common/download.h" #include "common/command_line.h" #include "tx_pool.h" @@ -1013,10 +1012,11 @@ namespace cryptonote * @brief verify that each ring uses distinct members * * @param tx the transaction to check + * @param hf_version the hard fork version rules to use * * @return false if any ring uses duplicate members, true otherwise */ - bool check_tx_inputs_ring_members_diff(const transaction& tx) const; + bool check_tx_inputs_ring_members_diff(const transaction& tx, const uint8_t hf_version) const; /** * @brief verify that each input key image in a transaction is in diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index a50ebb550..1d2024a05 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -149,12 +149,17 @@ namespace cryptonote r = crypto::derive_public_key(derivation, no, miner_address.m_spend_public_key, out_eph_public_key); CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << no << ", "<< miner_address.m_spend_public_key << ")"); - txout_to_key tk; - tk.key = out_eph_public_key; + uint64_t amount = out_amounts[no]; + summary_amounts += amount; + + bool use_view_tags = hard_fork_version >= HF_VERSION_VIEW_TAGS; + crypto::view_tag view_tag; + if (use_view_tags) + crypto::derive_view_tag(derivation, no, view_tag); tx_out out; - summary_amounts += out.amount = out_amounts[no]; - out.target = tk; + cryptonote::set_tx_out(amount, out_eph_public_key, use_view_tags, view_tag, out); + tx.vout.push_back(out); } @@ -198,7 +203,7 @@ namespace cryptonote return addr.m_view_public_key; } //--------------------------------------------------------------- - bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, bool shuffle_outs) + bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, bool shuffle_outs, bool use_view_tags) { hw::device &hwdev = sender_account_keys.get_device(); @@ -406,17 +411,16 @@ namespace cryptonote { CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount); crypto::public_key out_eph_public_key; + crypto::view_tag view_tag; hwdev.generate_output_ephemeral_keys(tx.version,sender_account_keys, txkey_pub, tx_key, dst_entr, change_addr, output_index, need_additional_txkeys, additional_tx_keys, - additional_tx_public_keys, amount_keys, out_eph_public_key); + additional_tx_public_keys, amount_keys, out_eph_public_key, + use_view_tags, view_tag); tx_out out; - out.amount = dst_entr.amount; - txout_to_key tk; - tk.key = out_eph_public_key; - out.target = tk; + cryptonote::set_tx_out(dst_entr.amount, out_eph_public_key, use_view_tags, view_tag, out); tx.vout.push_back(out); output_index++; summary_outs_money += dst_entr.amount; @@ -546,7 +550,9 @@ namespace cryptonote } for (size_t i = 0; i < tx.vout.size(); ++i) { - destinations.push_back(rct::pk2rct(boost::get<txout_to_key>(tx.vout[i].target).key)); + crypto::public_key output_public_key; + get_output_public_key(tx.vout[i], output_public_key); + destinations.push_back(rct::pk2rct(output_public_key)); outamounts.push_back(tx.vout[i].amount); amount_out += tx.vout[i].amount; } @@ -607,7 +613,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout) + bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, bool use_view_tags) { hw::device &hwdev = sender_account_keys.get_device(); hwdev.open_tx(tx_key); @@ -627,7 +633,8 @@ namespace cryptonote } } - bool r = construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, rct, rct_config, msout); + bool shuffle_outs = true; + bool r = construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, rct, rct_config, msout, shuffle_outs, use_view_tags); hwdev.close_tx(); return r; } catch(...) { @@ -643,7 +650,7 @@ namespace cryptonote crypto::secret_key tx_key; std::vector<crypto::secret_key> additional_tx_keys; std::vector<tx_destination_entry> destinations_copy = destinations; - return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations_copy, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, { rct::RangeProofBorromean, 0}, NULL); + return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations_copy, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, { rct::RangeProofBorromean, 0}, NULL, false); } //--------------------------------------------------------------- bool generate_genesis_block( diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index cea4aad17..f4ffb98ff 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -119,21 +119,23 @@ namespace cryptonote //--------------------------------------------------------------- crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::account_public_address>& change_addr); bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time); - bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL, bool shuffle_outs = true); - bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL); + bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL, bool shuffle_outs = true, bool use_view_tags = false); + bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, rct::multisig_out *msout = NULL, bool use_view_tags = false); bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key, const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index, const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys, std::vector<crypto::public_key> &additional_tx_public_keys, std::vector<rct::key> &amount_keys, - crypto::public_key &out_eph_public_key) ; + crypto::public_key &out_eph_public_key, + const bool use_view_tags, crypto::view_tag &view_tag) ; bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key, const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index, const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys, std::vector<crypto::public_key> &additional_tx_public_keys, std::vector<rct::key> &amount_keys, - crypto::public_key &out_eph_public_key) ; + crypto::public_key &out_eph_public_key, + const bool use_view_tags, crypto::view_tag &view_tag) ; bool generate_genesis_block( block& bl diff --git a/src/cryptonote_core/i_core_events.h b/src/cryptonote_core/i_core_events.h index 5d00858b5..629194543 100644 --- a/src/cryptonote_core/i_core_events.h +++ b/src/cryptonote_core/i_core_events.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 6fe5a54ac..c27261860 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 80b38c51d..62bef6c06 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_core/tx_sanity_check.cpp b/src/cryptonote_core/tx_sanity_check.cpp index ca870779e..f46ec3bbc 100644 --- a/src/cryptonote_core/tx_sanity_check.cpp +++ b/src/cryptonote_core/tx_sanity_check.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_core/tx_sanity_check.h b/src/cryptonote_core/tx_sanity_check.h index 15c5476ee..9779a8e79 100644 --- a/src/cryptonote_core/tx_sanity_check.h +++ b/src/cryptonote_core/tx_sanity_check.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_protocol/CMakeLists.txt b/src/cryptonote_protocol/CMakeLists.txt index 85c25546f..b516e17e9 100644 --- a/src/cryptonote_protocol/CMakeLists.txt +++ b/src/cryptonote_protocol/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/cryptonote_protocol/block_queue.cpp b/src/cryptonote_protocol/block_queue.cpp index 2f5b693dd..4e65eafa4 100644 --- a/src/cryptonote_protocol/block_queue.cpp +++ b/src/cryptonote_protocol/block_queue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_protocol/block_queue.h b/src/cryptonote_protocol/block_queue.h index 30fb5bc21..64ff106a3 100644 --- a/src/cryptonote_protocol/block_queue.h +++ b/src/cryptonote_protocol/block_queue.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h index 8c511e824..0b860f1a8 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_defs.h +++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp index 42774f2cb..92ee08054 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp +++ b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief This is the place to implement our handlers for protocol network actions, e.g. for ratelimit for download-requests -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -43,7 +43,6 @@ #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/thread/thread.hpp> #include "misc_language.h" -#include "pragma_comp_defs.h" #include <algorithm> diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index 80dd2bc39..a1e4df563 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -2,7 +2,7 @@ /// @author rfree (current maintainer/user in monero.cc project - most of code is from CryptoNote) /// @brief This is the original cryptonote protocol network-events handler, modified by us -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 39d562fd1..891ee109d 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -2,7 +2,7 @@ /// @author rfree (current maintainer/user in monero.cc project - most of code is from CryptoNote) /// @brief This is the original cryptonote protocol network-events handler, modified by us -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -35,7 +35,6 @@ // (may contain code and/or modifications by other developers) // developer rfree: this code is caller of our new network code, and is modded; e.g. for rate limiting -#include <boost/interprocess/detail/atomic.hpp> #include <list> #include <ctime> diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h index 57b1d049c..3b2ca5e37 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_protocol/enums.h b/src/cryptonote_protocol/enums.h index c0c495837..aeb66ed5c 100644 --- a/src/cryptonote_protocol/enums.h +++ b/src/cryptonote_protocol/enums.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_protocol/fwd.h b/src/cryptonote_protocol/fwd.h index e7722c2f4..f036f41cb 100644 --- a/src/cryptonote_protocol/fwd.h +++ b/src/cryptonote_protocol/fwd.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp index 53de407b6..83f37015f 100644 --- a/src/cryptonote_protocol/levin_notify.cpp +++ b/src/cryptonote_protocol/levin_notify.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/cryptonote_protocol/levin_notify.h b/src/cryptonote_protocol/levin_notify.h index 12704746a..2927eea86 100644 --- a/src/cryptonote_protocol/levin_notify.h +++ b/src/cryptonote_protocol/levin_notify.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index b95c0ac88..455f72472 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -37,30 +37,7 @@ set(daemon_sources set(daemon_headers) -set(daemon_private_headers - command_parser_executor.h - command_server.h - core.h - daemon.h - executor.h - p2p.h - protocol.h - rpc.h - rpc_command_executor.h - - # cryptonote_protocol - ../cryptonote_protocol/cryptonote_protocol_defs.h - ../cryptonote_protocol/cryptonote_protocol_handler.h - ../cryptonote_protocol/cryptonote_protocol_handler.inl - ../cryptonote_protocol/cryptonote_protocol_handler_common.h - - # p2p - ../p2p/net_node.h - ../p2p/net_node_common.h - ../p2p/net_peerlist.h - ../p2p/net_peerlist_boost_serialization.h - ../p2p/p2p_protocol_defs.h - ../p2p/stdafx.h) +monero_find_all_headers(daemon_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(daemon ${daemon_private_headers}) diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h index a988fe25f..96fddc02d 100644 --- a/src/daemon/command_line_args.h +++ b/src/daemon/command_line_args.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 14233bf29..20c906141 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h index 64e4c301b..cd9e6544e 100644 --- a/src/daemon/command_parser_executor.h +++ b/src/daemon/command_parser_executor.h @@ -6,7 +6,7 @@ */ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -40,7 +40,6 @@ #include "daemon/rpc_command_executor.h" #include "common/common_fwd.h" -#include "net/net_fwd.h" #include "rpc/core_rpc_server.h" namespace daemonize { diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index 63f44c4cd..fc5f1b3d7 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/command_server.h b/src/daemon/command_server.h index df7198d04..babb8e85a 100644 --- a/src/daemon/command_server.h +++ b/src/daemon/command_server.h @@ -9,7 +9,7 @@ Passing RPC commands: */ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -43,7 +43,6 @@ Passing RPC commands: #include "common/common_fwd.h" #include "console_handler.h" #include "daemon/command_parser_executor.h" -#include "net/net_fwd.h" namespace daemonize { diff --git a/src/daemon/core.h b/src/daemon/core.h index 0811cf420..fde0d6bab 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 3f1885423..286c02b50 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h index 2eb2019ce..529b42d20 100644 --- a/src/daemon/daemon.h +++ b/src/daemon/daemon.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/executor.cpp b/src/daemon/executor.cpp index f9ba3b493..d67bd6141 100644 --- a/src/daemon/executor.cpp +++ b/src/daemon/executor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/executor.h b/src/daemon/executor.h index a7235711c..d59ef22fb 100644 --- a/src/daemon/executor.h +++ b/src/daemon/executor.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index 70aec5538..73d9ebce1 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/p2p.h b/src/daemon/p2p.h index 38862c017..799dc3d25 100644 --- a/src/daemon/p2p.h +++ b/src/daemon/p2p.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/protocol.h b/src/daemon/protocol.h index 6b03c169a..733bacfc9 100644 --- a/src/daemon/protocol.h +++ b/src/daemon/protocol.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/rpc.h b/src/daemon/rpc.h index bff7dc449..7b059ebd3 100644 --- a/src/daemon/rpc.h +++ b/src/daemon/rpc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 16e6a304c..b6364ff77 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h index 118f04731..ebd7eda85 100644 --- a/src/daemon/rpc_command_executor.h +++ b/src/daemon/rpc_command_executor.h @@ -6,7 +6,7 @@ */ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -43,7 +43,6 @@ #include "common/common_fwd.h" #include "common/rpc_client.h" #include "cryptonote_basic/cryptonote_basic.h" -#include "net/net_fwd.h" #include "rpc/core_rpc_server.h" #undef MONERO_DEFAULT_LOG_CATEGORY diff --git a/src/daemonizer/CMakeLists.txt b/src/daemonizer/CMakeLists.txt index 462d40531..61999b3a5 100644 --- a/src/daemonizer/CMakeLists.txt +++ b/src/daemonizer/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/daemonizer/daemonizer.h b/src/daemonizer/daemonizer.h index 442861cdb..fa19c28b0 100644 --- a/src/daemonizer/daemonizer.h +++ b/src/daemonizer/daemonizer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemonizer/posix_daemonizer.inl b/src/daemonizer/posix_daemonizer.inl index 76ef467ca..bd2741039 100644 --- a/src/daemonizer/posix_daemonizer.inl +++ b/src/daemonizer/posix_daemonizer.inl @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemonizer/posix_fork.h b/src/daemonizer/posix_fork.h index d841df0fc..b1d82ff43 100644 --- a/src/daemonizer/posix_fork.h +++ b/src/daemonizer/posix_fork.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemonizer/windows_daemonizer.inl b/src/daemonizer/windows_daemonizer.inl index 67c8a2855..a0086408f 100644 --- a/src/daemonizer/windows_daemonizer.inl +++ b/src/daemonizer/windows_daemonizer.inl @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemonizer/windows_service.cpp b/src/daemonizer/windows_service.cpp index 01be6b247..846f6c071 100644 --- a/src/daemonizer/windows_service.cpp +++ b/src/daemonizer/windows_service.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemonizer/windows_service.h b/src/daemonizer/windows_service.h index 091041391..a96674d19 100644 --- a/src/daemonizer/windows_service.h +++ b/src/daemonizer/windows_service.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/daemonizer/windows_service_runner.h b/src/daemonizer/windows_service_runner.h index eb72df66d..a8e4d3b0e 100644 --- a/src/daemonizer/windows_service_runner.h +++ b/src/daemonizer/windows_service_runner.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/debug_utilities/CMakeLists.txt b/src/debug_utilities/CMakeLists.txt index 7b21123f6..ecb0f0229 100644 --- a/src/debug_utilities/CMakeLists.txt +++ b/src/debug_utilities/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/debug_utilities/cn_deserialize.cpp b/src/debug_utilities/cn_deserialize.cpp index c039b93c5..41c397bd8 100644 --- a/src/debug_utilities/cn_deserialize.cpp +++ b/src/debug_utilities/cn_deserialize.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/debug_utilities/dns_checks.cpp b/src/debug_utilities/dns_checks.cpp index 138cd4fc1..caa0421e9 100644 --- a/src/debug_utilities/dns_checks.cpp +++ b/src/debug_utilities/dns_checks.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/debug_utilities/object_sizes.cpp b/src/debug_utilities/object_sizes.cpp index bffff0882..40b651ab3 100644 --- a/src/debug_utilities/object_sizes.cpp +++ b/src/debug_utilities/object_sizes.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 3597ab336..e4f1159b5 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/device/device.cpp b/src/device/device.cpp index 4821abdcf..e6cd358b6 100644 --- a/src/device/device.cpp +++ b/src/device/device.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device/device.hpp b/src/device/device.hpp index 6005e157d..eca91006f 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -222,7 +222,8 @@ namespace hw { const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys, std::vector<crypto::public_key> &additional_tx_public_keys, std::vector<rct::key> &amount_keys, - crypto::public_key &out_eph_public_key) = 0; + crypto::public_key &out_eph_public_key, + const bool use_view_tags, crypto::view_tag &view_tag) = 0; virtual bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) = 0; virtual bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) = 0; diff --git a/src/device/device_cold.hpp b/src/device/device_cold.hpp index 07009b9d2..ba4d6d8ae 100644 --- a/src/device/device_cold.hpp +++ b/src/device/device_cold.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index 145197212..d70ece229 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -263,6 +263,11 @@ namespace hw { return true; } + bool device_default::derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag) { + crypto::derive_view_tag(derivation, output_index, view_tag); + return true; + } + bool device_default::conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations){ return true; } @@ -291,7 +296,8 @@ namespace hw { const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index, const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys, std::vector<crypto::public_key> &additional_tx_public_keys, - std::vector<rct::key> &amount_keys, crypto::public_key &out_eph_public_key) { + std::vector<rct::key> &amount_keys, crypto::public_key &out_eph_public_key, + const bool use_view_tags, crypto::view_tag &view_tag) { crypto::key_derivation derivation; @@ -331,6 +337,12 @@ namespace hw { derivation_to_scalar(derivation, output_index, scalar1); amount_keys.push_back(rct::sk2rct(scalar1)); } + + if (use_view_tags) + { + derive_view_tag(derivation, output_index, view_tag); + } + r = derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key); CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")"); diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp index 2493bd67d..7d3543652 100644 --- a/src/device/device_default.hpp +++ b/src/device/device_default.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -101,6 +101,7 @@ namespace hw { bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override; bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) override; bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) override; + bool derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag); /* ======================================================================= */ @@ -126,7 +127,8 @@ namespace hw { const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys, std::vector<crypto::public_key> &additional_tx_public_keys, std::vector<rct::key> &amount_keys, - crypto::public_key &out_eph_public_key) override; + crypto::public_key &out_eph_public_key, + bool use_view_tags, crypto::view_tag &view_tag) override; bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) override; bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override; diff --git a/src/device/device_io.hpp b/src/device/device_io.hpp index 6a7744c11..b333caa13 100644 --- a/src/device/device_io.hpp +++ b/src/device/device_io.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device/device_io_hid.cpp b/src/device/device_io_hid.cpp index 7aa5b39bf..3116a8713 100644 --- a/src/device/device_io_hid.cpp +++ b/src/device/device_io_hid.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device/device_io_hid.hpp b/src/device/device_io_hid.hpp index e6d76f276..fd2ec8515 100644 --- a/src/device/device_io_hid.hpp +++ b/src/device/device_io_hid.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index c082544e8..51e65dfa5 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -524,6 +524,7 @@ namespace hw { static const std::vector<hw::io::hid_conn_params> known_devices { {0x2c97, 0x0001, 0, 0xffa0}, {0x2c97, 0x0004, 0, 0xffa0}, + {0x2c97, 0x0005, 0, 0xffa0}, }; bool device_ledger::connect(void) { @@ -1527,7 +1528,8 @@ namespace hw { const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys, std::vector<crypto::public_key> &additional_tx_public_keys, std::vector<rct::key> &amount_keys, - crypto::public_key &out_eph_public_key) { + crypto::public_key &out_eph_public_key, + bool use_view_tags, crypto::view_tag &view_tag) { AUTO_LOCK_CMD(); #ifdef DEBUG_HWDEVICE @@ -1541,6 +1543,8 @@ namespace hw { const boost::optional<cryptonote::account_public_address> change_addr_x = change_addr; const size_t output_index_x = output_index; const bool need_additional_txkeys_x = need_additional_txkeys; + const bool use_view_tags_x = use_view_tags; + const crypto::view_tag view_tag_x = view_tag; std::vector<crypto::secret_key> additional_tx_keys_x; for (const auto &k: additional_tx_keys) { @@ -1568,7 +1572,7 @@ namespace hw { log_hexbuffer("generate_output_ephemeral_keys: [[IN]] additional_tx_keys[oi]", additional_tx_keys_x[output_index].data, 32); } this->controle_device->generate_output_ephemeral_keys(tx_version_x, sender_account_keys_x, txkey_pub_x, tx_key_x, dst_entr_x, change_addr_x, output_index_x, need_additional_txkeys_x, additional_tx_keys_x, - additional_tx_public_keys_x, amount_keys_x, out_eph_public_key_x); + additional_tx_public_keys_x, amount_keys_x, out_eph_public_key_x, use_view_tags_x, view_tag_x); if(need_additional_txkeys_x) { log_hexbuffer("additional_tx_public_keys_x: [[OUT]] additional_tx_public_keys_x", additional_tx_public_keys_x.back().data, 32); } diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index 590ae41b5..074bfaa8d 100644 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -273,7 +273,8 @@ namespace hw { const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys, std::vector<crypto::public_key> &additional_tx_public_keys, std::vector<rct::key> &amount_keys, - crypto::public_key &out_eph_public_key) override; + crypto::public_key &out_eph_public_key, + const bool use_view_tags, crypto::view_tag &view_tag) override; bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) override; bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override; diff --git a/src/device/log.cpp b/src/device/log.cpp index 6e62f1dee..9b882b784 100644 --- a/src/device/log.cpp +++ b/src/device/log.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device/log.hpp b/src/device/log.hpp index 66c3e06db..660adc63e 100644 --- a/src/device/log.hpp +++ b/src/device/log.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/CMakeLists.txt b/src/device_trezor/CMakeLists.txt index f105f68b7..6688a317b 100644 --- a/src/device_trezor/CMakeLists.txt +++ b/src/device_trezor/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp index 0545f3f26..6f7ae9a6b 100644 --- a/src/device_trezor/device_trezor.cpp +++ b/src/device_trezor/device_trezor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/device_trezor.hpp b/src/device_trezor/device_trezor.hpp index 15337d2b4..38aeaf6b5 100644 --- a/src/device_trezor/device_trezor.hpp +++ b/src/device_trezor/device_trezor.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp index 016eb2816..56f3784a7 100644 --- a/src/device_trezor/device_trezor_base.cpp +++ b/src/device_trezor/device_trezor_base.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp index de49397d5..5b6920313 100644 --- a/src/device_trezor/device_trezor_base.hpp +++ b/src/device_trezor/device_trezor_base.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor.hpp b/src/device_trezor/trezor.hpp index b3f85f6a8..f2a352f58 100644 --- a/src/device_trezor/trezor.hpp +++ b/src/device_trezor/trezor.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor/debug_link.cpp b/src/device_trezor/trezor/debug_link.cpp index 102d1f966..1eed0a53e 100644 --- a/src/device_trezor/trezor/debug_link.cpp +++ b/src/device_trezor/trezor/debug_link.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor/debug_link.hpp b/src/device_trezor/trezor/debug_link.hpp index a5f05ea94..b7a252833 100644 --- a/src/device_trezor/trezor/debug_link.hpp +++ b/src/device_trezor/trezor/debug_link.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor/exceptions.hpp b/src/device_trezor/trezor/exceptions.hpp index 9d63329e4..818b2cb6c 100644 --- a/src/device_trezor/trezor/exceptions.hpp +++ b/src/device_trezor/trezor/exceptions.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor/messages_map.cpp b/src/device_trezor/trezor/messages_map.cpp index 02869f760..313fd6820 100644 --- a/src/device_trezor/trezor/messages_map.cpp +++ b/src/device_trezor/trezor/messages_map.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor/messages_map.hpp b/src/device_trezor/trezor/messages_map.hpp index a903eaf92..b1ea65e6e 100644 --- a/src/device_trezor/trezor/messages_map.hpp +++ b/src/device_trezor/trezor/messages_map.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor/protocol.cpp b/src/device_trezor/trezor/protocol.cpp index 92150b579..a400e82c7 100644 --- a/src/device_trezor/trezor/protocol.cpp +++ b/src/device_trezor/trezor/protocol.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -154,8 +154,7 @@ namespace ki { res.emplace_back(); auto & cres = res.back(); - - cres.set_out_key(key_to_string(boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key)); + cres.set_out_key(key_to_string(td.get_public_key())); cres.set_tx_pub_key(key_to_string(tx_pub_key)); cres.set_internal_output_index(td.m_internal_output_index); cres.set_sub_addr_major(td.m_subaddr_index.major); diff --git a/src/device_trezor/trezor/protocol.hpp b/src/device_trezor/trezor/protocol.hpp index 0fdd36a51..858db1520 100644 --- a/src/device_trezor/trezor/protocol.hpp +++ b/src/device_trezor/trezor/protocol.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp index 881848a80..53b35a37a 100644 --- a/src/device_trezor/trezor/transport.cpp +++ b/src/device_trezor/trezor/transport.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor/transport.hpp b/src/device_trezor/trezor/transport.hpp index ff843f06b..a452724da 100644 --- a/src/device_trezor/trezor/transport.hpp +++ b/src/device_trezor/trezor/transport.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/device_trezor/trezor/trezor_defs.hpp b/src/device_trezor/trezor/trezor_defs.hpp index 9882d6d4b..53bf2b03c 100644 --- a/src/device_trezor/trezor/trezor_defs.hpp +++ b/src/device_trezor/trezor/trezor_defs.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/gen_multisig/CMakeLists.txt b/src/gen_multisig/CMakeLists.txt index 6d8bdfb5c..e8aaec62c 100644 --- a/src/gen_multisig/CMakeLists.txt +++ b/src/gen_multisig/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2020, The Monero Project +# Copyright (c) 2017-2022, The Monero Project # # All rights reserved. # diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp index 87de3c351..f13e74b0f 100644 --- a/src/gen_multisig/gen_multisig.cpp +++ b/src/gen_multisig/gen_multisig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/gen_ssl_cert/CMakeLists.txt b/src/gen_ssl_cert/CMakeLists.txt index 6203feb21..efadc7c31 100644 --- a/src/gen_ssl_cert/CMakeLists.txt +++ b/src/gen_ssl_cert/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2020, The Monero Project +# Copyright (c) 2017-2022, The Monero Project # # All rights reserved. # diff --git a/src/gen_ssl_cert/gen_ssl_cert.cpp b/src/gen_ssl_cert/gen_ssl_cert.cpp index 1a048e9e8..cd810ed20 100644 --- a/src/gen_ssl_cert/gen_ssl_cert.cpp +++ b/src/gen_ssl_cert/gen_ssl_cert.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/hardforks/CMakeLists.txt b/src/hardforks/CMakeLists.txt index 46f51e09d..81a3d694b 100644 --- a/src/hardforks/CMakeLists.txt +++ b/src/hardforks/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -29,8 +29,7 @@ set(hardforks_sources hardforks.cpp) -set(hardforks_headers - hardforks.h) +monero_find_all_headers(hardforks_headers "${CMAKE_CURRENT_SOURCE_DIR}") set(hardforks_private_headers) diff --git a/src/hardforks/hardforks.cpp b/src/hardforks/hardforks.cpp index 9055b92e3..c055f49d2 100644 --- a/src/hardforks/hardforks.cpp +++ b/src/hardforks/hardforks.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -70,6 +70,9 @@ const hardfork_t mainnet_hard_forks[] = { { 13, 2210000, 0, 1598180817 }, { 14, 2210720, 0, 1598180818 }, + + { 15, 8000000, 0, 1608223241 }, // temp so tests test with these consensus rules + { 16, 8000001, 0, 1608223242 }, // temp so tests test with these consensus rules }; const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]); const uint64_t mainnet_hard_fork_version_1_till = 1009826; diff --git a/src/hardforks/hardforks.h b/src/hardforks/hardforks.h index 039f18176..53f14b8eb 100644 --- a/src/hardforks/hardforks.h +++ b/src/hardforks/hardforks.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/lmdb/CMakeLists.txt b/src/lmdb/CMakeLists.txt index 1f369f114..a26c48ad5 100644 --- a/src/lmdb/CMakeLists.txt +++ b/src/lmdb/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2018, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -27,7 +27,7 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set(lmdb_sources database.cpp error.cpp table.cpp value_stream.cpp) -set(lmdb_headers database.h error.h key_stream.h table.h transaction.h util.h value_stream.h) +monero_find_all_headers(lmdb_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_add_library(lmdb_lib ${lmdb_sources} ${lmdb_headers}) target_link_libraries(lmdb_lib common ${LMDB_LIBRARY}) diff --git a/src/lmdb/database.cpp b/src/lmdb/database.cpp index ccab1902a..544197d57 100644 --- a/src/lmdb/database.cpp +++ b/src/lmdb/database.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/lmdb/database.h b/src/lmdb/database.h index 269f8c8a1..0c2390652 100644 --- a/src/lmdb/database.h +++ b/src/lmdb/database.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/lmdb/error.cpp b/src/lmdb/error.cpp index 91479521e..62fdb83c3 100644 --- a/src/lmdb/error.cpp +++ b/src/lmdb/error.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/lmdb/error.h b/src/lmdb/error.h index 2944adf78..f4134359b 100644 --- a/src/lmdb/error.h +++ b/src/lmdb/error.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/lmdb/key_stream.h b/src/lmdb/key_stream.h index 40434d3a1..11fa284dd 100644 --- a/src/lmdb/key_stream.h +++ b/src/lmdb/key_stream.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/lmdb/table.cpp b/src/lmdb/table.cpp index 0818b74e6..725a1a0b7 100644 --- a/src/lmdb/table.cpp +++ b/src/lmdb/table.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/lmdb/transaction.h b/src/lmdb/transaction.h index cdd80696c..f358290ec 100644 --- a/src/lmdb/transaction.h +++ b/src/lmdb/transaction.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/lmdb/util.h b/src/lmdb/util.h index 50162b7c8..c6c75bc00 100644 --- a/src/lmdb/util.h +++ b/src/lmdb/util.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/lmdb/value_stream.cpp b/src/lmdb/value_stream.cpp index 604140e47..6a1e054c1 100644 --- a/src/lmdb/value_stream.cpp +++ b/src/lmdb/value_stream.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/lmdb/value_stream.h b/src/lmdb/value_stream.h index 01090aa67..bd2814ef4 100644 --- a/src/lmdb/value_stream.h +++ b/src/lmdb/value_stream.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are diff --git a/src/mnemonics/CMakeLists.txt b/src/mnemonics/CMakeLists.txt index ed53a41f6..738633ef5 100644 --- a/src/mnemonics/CMakeLists.txt +++ b/src/mnemonics/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -31,23 +31,7 @@ set(mnemonics_sources set(mnemonics_headers) -set(mnemonics_private_headers - electrum-words.h - chinese_simplified.h - english.h - dutch.h - french.h - german.h - italian.h - japanese.h - language_base.h - english_old.h - portuguese.h - russian.h - singleton.h - spanish.h - esperanto.h - lojban.h) +monero_find_all_headers(mnemonics_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(mnemonics ${mnemonics_private_headers}) diff --git a/src/mnemonics/chinese_simplified.h b/src/mnemonics/chinese_simplified.h index 7a211bc34..2661b5820 100644 --- a/src/mnemonics/chinese_simplified.h +++ b/src/mnemonics/chinese_simplified.h @@ -21,7 +21,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// Code surrounding the word list is Copyright (c) 2014-2020, The Monero Project
+// Code surrounding the word list is Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/dutch.h b/src/mnemonics/dutch.h index 29c346d42..ace2e1b3d 100644 --- a/src/mnemonics/dutch.h +++ b/src/mnemonics/dutch.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index 8c79a53ca..b53f3acd3 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/mnemonics/electrum-words.h b/src/mnemonics/electrum-words.h index eb0c99e0b..becd6bb4e 100644 --- a/src/mnemonics/electrum-words.h +++ b/src/mnemonics/electrum-words.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/mnemonics/english.h b/src/mnemonics/english.h index b7eb3d643..1715445d8 100644 --- a/src/mnemonics/english.h +++ b/src/mnemonics/english.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/english_old.h b/src/mnemonics/english_old.h index f408b2a6c..c609dff2d 100644 --- a/src/mnemonics/english_old.h +++ b/src/mnemonics/english_old.h @@ -1,6 +1,6 @@ // Word list originally created as part of the Electrum project, Copyright (C) 2014 Thomas Voegtlin
//
-// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/esperanto.h b/src/mnemonics/esperanto.h index 4897fe0b3..1d3437fad 100644 --- a/src/mnemonics/esperanto.h +++ b/src/mnemonics/esperanto.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/french.h b/src/mnemonics/french.h index d5a7b6cb6..be2f8957c 100644 --- a/src/mnemonics/french.h +++ b/src/mnemonics/french.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/mnemonics/german.h b/src/mnemonics/german.h index c38a1fb83..4f5265888 100644 --- a/src/mnemonics/german.h +++ b/src/mnemonics/german.h @@ -1,6 +1,6 @@ // Word list created by Monero contributor Shrikez
//
-// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/italian.h b/src/mnemonics/italian.h index f202e23e2..dbd39984b 100644 --- a/src/mnemonics/italian.h +++ b/src/mnemonics/italian.h @@ -1,6 +1,6 @@ // Word list created by Monero contributor Shrikez
//
-// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/japanese.h b/src/mnemonics/japanese.h index 899d78f48..5831b1995 100644 --- a/src/mnemonics/japanese.h +++ b/src/mnemonics/japanese.h @@ -21,7 +21,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// Code surrounding the word list is Copyright (c) 2014-2020, The Monero Project
+// Code surrounding the word list is Copyright (c) 2014-2022, The Monero Project
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
diff --git a/src/mnemonics/language_base.h b/src/mnemonics/language_base.h index 1aa869e45..92eb09f0d 100644 --- a/src/mnemonics/language_base.h +++ b/src/mnemonics/language_base.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/lojban.h b/src/mnemonics/lojban.h index 95d8b4633..68aefd5fd 100644 --- a/src/mnemonics/lojban.h +++ b/src/mnemonics/lojban.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/portuguese.h b/src/mnemonics/portuguese.h index 090278f27..9ddac09bb 100644 --- a/src/mnemonics/portuguese.h +++ b/src/mnemonics/portuguese.h @@ -21,7 +21,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// Code surrounding the word list is Copyright (c) 2014-2020, The Monero Project
+// Code surrounding the word list is Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/russian.h b/src/mnemonics/russian.h index ca2629c1a..8922b1ed9 100644 --- a/src/mnemonics/russian.h +++ b/src/mnemonics/russian.h @@ -1,6 +1,6 @@ // Word list created by Monero contributor sammy007
//
-// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/singleton.h b/src/mnemonics/singleton.h index 10d220b65..91faad92c 100644 --- a/src/mnemonics/singleton.h +++ b/src/mnemonics/singleton.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project
+// Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/mnemonics/spanish.h b/src/mnemonics/spanish.h index f3adaaf42..1bdb6b934 100644 --- a/src/mnemonics/spanish.h +++ b/src/mnemonics/spanish.h @@ -21,7 +21,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// Code surrounding the word list is Copyright (c) 2014-2020, The Monero Project
+// Code surrounding the word list is Copyright (c) 2014-2022, The Monero Project
//
// All rights reserved.
//
diff --git a/src/multisig/CMakeLists.txt b/src/multisig/CMakeLists.txt index 14099e64a..294a1721f 100644 --- a/src/multisig/CMakeLists.txt +++ b/src/multisig/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2020, The Monero Project +# Copyright (c) 2017-2022, The Monero Project # # All rights reserved. # @@ -34,10 +34,7 @@ set(multisig_sources set(multisig_headers) -set(multisig_private_headers - multisig.h - multisig_account.h - multisig_kex_msg.h) +monero_find_all_headers(multisig_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(multisig ${multisig_private_headers}) diff --git a/src/multisig/multisig.cpp b/src/multisig/multisig.cpp index 85c45bc31..fabffdd02 100644 --- a/src/multisig/multisig.cpp +++ b/src/multisig/multisig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/multisig/multisig.h b/src/multisig/multisig.h index e041ea670..16dbbc544 100644 --- a/src/multisig/multisig.h +++ b/src/multisig/multisig.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/multisig/multisig_account.cpp b/src/multisig/multisig_account.cpp index b7298c4b6..8bd97cf21 100644 --- a/src/multisig/multisig_account.cpp +++ b/src/multisig/multisig_account.cpp @@ -73,7 +73,7 @@ namespace multisig const crypto::public_key &multisig_pubkey, const crypto::public_key &common_pubkey, const std::uint32_t kex_rounds_complete, - kex_origins_map_t kex_origins_map, + multisig_keyset_map_memsafe_t kex_origins_map, std::string next_round_kex_message) : m_base_privkey{base_privkey}, m_base_common_privkey{base_common_privkey}, @@ -89,6 +89,20 @@ namespace multisig CHECK_AND_ASSERT_THROW_MES(crypto::secret_key_to_public_key(m_base_privkey, m_base_pubkey), "Failed to derive public key"); set_multisig_config(threshold, std::move(signers)); + + // kex rounds should not exceed post-kex verification round + const std::uint32_t kex_rounds_required{multisig_kex_rounds_required(m_signers.size(), m_threshold)}; + CHECK_AND_ASSERT_THROW_MES(m_kex_rounds_complete <= kex_rounds_required + 1, + "multisig account: tried to reconstruct account, but kex rounds complete counter is invalid."); + + // once an account is done with kex, the 'next kex msg' is always the post-kex verification message + // i.e. the multisig account pubkey signed by the signer's privkey AND the common pubkey + if (main_kex_rounds_done()) + { + m_next_round_kex_message = multisig_kex_msg{kex_rounds_required + 1, + m_base_privkey, + std::vector<crypto::public_key>{m_multisig_pubkey, m_common_pubkey}}.get_msg(); + } } //---------------------------------------------------------------------------------------------------------------------- // multisig_account: EXTERNAL @@ -100,14 +114,24 @@ namespace multisig //---------------------------------------------------------------------------------------------------------------------- // multisig_account: EXTERNAL //---------------------------------------------------------------------------------------------------------------------- - bool multisig_account::multisig_is_ready() const + bool multisig_account::main_kex_rounds_done() const { if (account_is_active()) - return multisig_kex_rounds_required(m_signers.size(), m_threshold) == m_kex_rounds_complete; + return m_kex_rounds_complete >= multisig_kex_rounds_required(m_signers.size(), m_threshold); + else + return false; + } + //---------------------------------------------------------------------------------------------------------------------- + // multisig_account: EXTERNAL + //---------------------------------------------------------------------------------------------------------------------- + bool multisig_account::multisig_is_ready() const + { + if (main_kex_rounds_done()) + return m_kex_rounds_complete >= multisig_kex_rounds_required(m_signers.size(), m_threshold) + 1; else return false; } - //---------------------------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------------------------- // multisig_account: INTERNAL //---------------------------------------------------------------------------------------------------------------------- void multisig_account::set_multisig_config(const std::size_t threshold, std::vector<crypto::public_key> signers) @@ -119,10 +143,6 @@ namespace multisig for (auto signer_it = signers.begin(); signer_it != signers.end(); ++signer_it) { - // signers should all be unique - CHECK_AND_ASSERT_THROW_MES(std::find(signers.begin(), signer_it, *signer_it) == signer_it, - "multisig account: tried to set signers, but found a duplicate signer unexpectedly."); - // signer pubkeys must be in main subgroup, and not identity CHECK_AND_ASSERT_THROW_MES(rct::isInMainSubgroup(rct::pk2rct(*signer_it)) && !(*signer_it == rct::rct2pk(rct::identity())), "multisig account: tried to set signers, but a signer pubkey is invalid."); @@ -133,12 +153,11 @@ namespace multisig "multisig account: tried to set signers, but did not find the account's base pubkey in signer list."); // sort signers - std::sort(signers.begin(), signers.end(), - [](const crypto::public_key &key1, const crypto::public_key &key2) -> bool - { - return memcmp(&key1, &key2, sizeof(crypto::public_key)) < 0; - } - ); + std::sort(signers.begin(), signers.end()); + + // signers should all be unique + CHECK_AND_ASSERT_THROW_MES(std::adjacent_find(signers.begin(), signers.end()) == signers.end(), + "multisig account: tried to set signers, but there are duplicate signers unexpectedly."); // set m_threshold = threshold; diff --git a/src/multisig/multisig_account.h b/src/multisig/multisig_account.h index b01ae6c88..bb853246a 100644 --- a/src/multisig/multisig_account.h +++ b/src/multisig/multisig_account.h @@ -75,12 +75,12 @@ namespace multisig * - ZtM2: https://web.getmonero.org/library/Zero-to-Monero-2-0-0.pdf Ch. 9, especially Section 9.6.3 * - FROST: https://eprint.iacr.org/2018/417 */ + using multisig_keyset_map_memsafe_t = + std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>>; + class multisig_account final { public: - //member types - using kex_origins_map_t = std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>>; - //constructors // default constructor multisig_account() = default; @@ -105,7 +105,7 @@ namespace multisig const crypto::public_key &multisig_pubkey, const crypto::public_key &common_pubkey, const std::uint32_t kex_rounds_complete, - kex_origins_map_t kex_origins_map, + multisig_keyset_map_memsafe_t kex_origins_map, std::string next_round_kex_message); // copy constructor: default @@ -137,13 +137,15 @@ namespace multisig // get kex rounds complete std::uint32_t get_kex_rounds_complete() const { return m_kex_rounds_complete; } // get kex keys to origins map - const kex_origins_map_t& get_kex_keys_to_origins_map() const { return m_kex_keys_to_origins_map; } + const multisig_keyset_map_memsafe_t& get_kex_keys_to_origins_map() const { return m_kex_keys_to_origins_map; } // get the kex msg for the next round const std::string& get_next_kex_round_msg() const { return m_next_round_kex_message; } //account status functions // account has been intialized, and the account holder can use the 'common' key bool account_is_active() const; + // account has gone through main kex rounds, only remaining step is to verify all other participants are ready + bool main_kex_rounds_done() const; // account is ready to make multisig signatures bool multisig_is_ready() const; @@ -178,21 +180,21 @@ namespace multisig * - Collect the local signer's shared keys to ignore in incoming messages, build the aggregate ancillary key * if appropriate. * param: expanded_msgs - set of multisig kex messages to process - * param: rounds_required - number of rounds required for kex + * param: kex_rounds_required - number of rounds required for kex (not including post-kex verification round) * outparam: exclude_pubkeys_out - keys held by the local account corresponding to round 'current_round' * - If 'current_round' is the final round, these are the local account's shares of the final aggregate key. */ void initialize_kex_update(const std::vector<multisig_kex_msg> &expanded_msgs, - const std::uint32_t rounds_required, + const std::uint32_t kex_rounds_required, std::vector<crypto::public_key> &exclude_pubkeys_out); /** * brief: finalize_kex_update - Helper for kex_update_impl() - * param: rounds_required - number of rounds required for kex + * param: kex_rounds_required - number of rounds required for kex (not including post-kex verification round) * param: result_keys_to_origins_map - map between keys for the next round and the other participants they correspond to * inoutparam: temp_account_inout - account to perform last update steps on */ - void finalize_kex_update(const std::uint32_t rounds_required, - kex_origins_map_t result_keys_to_origins_map); + void finalize_kex_update(const std::uint32_t kex_rounds_required, + multisig_keyset_map_memsafe_t result_keys_to_origins_map); //member variables private: @@ -226,7 +228,7 @@ namespace multisig std::uint32_t m_kex_rounds_complete{0}; // this account's pubkeys for the in-progress key exchange round // - either DH derivations (intermediate rounds), H(derivation)*G (final round), empty (when kex is done) - kex_origins_map_t m_kex_keys_to_origins_map; + multisig_keyset_map_memsafe_t m_kex_keys_to_origins_map; // the account's message for the in-progress key exchange round std::string m_next_round_kex_message; }; diff --git a/src/multisig/multisig_account_kex_impl.cpp b/src/multisig/multisig_account_kex_impl.cpp index 0a0ca7bdc..2127ee04a 100644 --- a/src/multisig/multisig_account_kex_impl.cpp +++ b/src/multisig/multisig_account_kex_impl.cpp @@ -57,6 +57,30 @@ namespace multisig /** * INTERNAL * + * brief: check_multisig_config - validate multisig configuration details + * param: round - the round of the message that should be produced + * param: threshold - threshold for multisig (M in M-of-N) + * param: num_signers - number of participants in multisig (N) + */ + //---------------------------------------------------------------------------------------------------------------------- + static void check_multisig_config(const std::uint32_t round, + const std::uint32_t threshold, + const std::uint32_t num_signers) + { + CHECK_AND_ASSERT_THROW_MES(num_signers > 1, "Must be at least one other multisig signer."); + CHECK_AND_ASSERT_THROW_MES(num_signers <= config::MULTISIG_MAX_SIGNERS, + "Too many multisig signers specified (limit = 16 to prevent dangerous combinatorial explosion during key exchange)."); + CHECK_AND_ASSERT_THROW_MES(num_signers >= threshold, + "Multisig threshold may not be larger than number of signers."); + CHECK_AND_ASSERT_THROW_MES(threshold > 0, "Multisig threshold must be > 0."); + CHECK_AND_ASSERT_THROW_MES(round > 0, "Multisig kex round must be > 0."); + CHECK_AND_ASSERT_THROW_MES(round <= multisig_kex_rounds_required(num_signers, threshold) + 1, + "Trying to process multisig kex for an invalid round."); + } + //---------------------------------------------------------------------------------------------------------------------- + /** + * INTERNAL + * * brief: calculate_multisig_keypair_from_derivation - wrapper on calculate_multisig_keypair() for an input public key * Converts an input public key into a crypto private key (type cast, does not change serialization), * then passes it to get_multisig_blinded_secret_key(). @@ -224,50 +248,23 @@ namespace multisig /** * INTERNAL * - * brief: multisig_kex_make_next_msg - Construct a kex msg for any round > 1 of multisig key construction. + * brief: multisig_kex_make_round_keys - Makes a kex round's keys. * - Involves DH exchanges with pubkeys provided by other participants. * - Conserves mapping [pubkey -> DH derivation] : [origin keys of participants that share this secret with you]. * param: base_privkey - account's base private key, for performing DH exchanges and signing messages - * param: round - the round of the message that should be produced - * param: threshold - threshold for multisig (M in M-of-N) - * param: num_signers - number of participants in multisig (N) * param: pubkey_origins_map - map between pubkeys to produce DH derivations with and identity keys of * participants who will share each derivation with you * outparam: derivation_origins_map_out - map between DH derivations (shared secrets) and identity keys - * - If msg is not for the last round, then these derivations are also stored in the output message - * so they can be sent to other participants, who will make more DH derivations for the next kex round. - * - If msg is for the last round, then these derivations won't be sent to other participants. - * Instead, they are converted to share secrets (i.e. s = H(derivation)) and multiplied by G. - * The keys s*G are sent to other participants in the message, so they can be used to produce the final - * multisig key via generate_multisig_spend_public_key(). - * - The values s are the local account's shares of the final multisig key's private key. The caller can - * compute those values with calculate_multisig_keypair_from_derivation() (or compute them directly). - * return: multisig kex message for the specified round */ //---------------------------------------------------------------------------------------------------------------------- - static multisig_kex_msg multisig_kex_make_next_msg(const crypto::secret_key &base_privkey, - const std::uint32_t round, - const std::uint32_t threshold, - const std::uint32_t num_signers, - const std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>> &pubkey_origins_map, - std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>> &derivation_origins_map_out) + static void multisig_kex_make_round_keys(const crypto::secret_key &base_privkey, + multisig_keyset_map_memsafe_t pubkey_origins_map, + multisig_keyset_map_memsafe_t &derivation_origins_map_out) { - CHECK_AND_ASSERT_THROW_MES(num_signers > 1, "Must be at least one other multisig signer."); - CHECK_AND_ASSERT_THROW_MES(num_signers <= config::MULTISIG_MAX_SIGNERS, - "Too many multisig signers specified (limit = 16 to prevent dangerous combinatorial explosion during key exchange)."); - CHECK_AND_ASSERT_THROW_MES(num_signers >= threshold, - "Multisig threshold may not be larger than number of signers."); - CHECK_AND_ASSERT_THROW_MES(threshold > 0, "Multisig threshold must be > 0."); - CHECK_AND_ASSERT_THROW_MES(round > 1, "Round for next msg must be > 1."); - CHECK_AND_ASSERT_THROW_MES(round <= multisig_kex_rounds_required(num_signers, threshold), - "Trying to make key exchange message for an invalid round."); - // make shared secrets with input pubkeys - std::vector<crypto::public_key> msg_pubkeys; - msg_pubkeys.reserve(pubkey_origins_map.size()); derivation_origins_map_out.clear(); - for (const auto &pubkey_and_origins : pubkey_origins_map) + for (auto &pubkey_and_origins : pubkey_origins_map) { // D = 8 * k_base * K_pubkey // note: must be mul8 (cofactor), otherwise it is possible to leak to a malicious participant if the local @@ -281,27 +278,29 @@ namespace multisig rct::scalarmultKey(derivation_rct, rct::pk2rct(pubkey_and_origins.first), rct::sk2rct(base_privkey)); rct::scalarmultKey(derivation_rct, derivation_rct, rct::EIGHT); - crypto::public_key_memsafe derivation{rct::rct2pk(derivation_rct)}; - // retain mapping between pubkey's origins and the DH derivation - // note: if msg for last round, then caller must know how to handle these derivations properly - derivation_origins_map_out[derivation] = pubkey_and_origins.second; - - // if the last round, convert derivations to public keys for the output message - if (round == multisig_kex_rounds_required(num_signers, threshold)) - { - // derived_pubkey = H(derivation)*G - crypto::public_key derived_pubkey; - calculate_multisig_keypair_from_derivation(derivation, derived_pubkey); - msg_pubkeys.push_back(derived_pubkey); - } - // otherwise, put derivations in message directly, so other signers can in turn create derivations (shared secrets) - // with them for the next round - else - msg_pubkeys.push_back(derivation); + // note: if working on last kex round, then caller must know how to handle these derivations properly + derivation_origins_map_out[rct::rct2pk(derivation_rct)] = std::move(pubkey_and_origins.second); } + } + //---------------------------------------------------------------------------------------------------------------------- + /** + * INTERNAL + * + * brief: check_messages_round - Check that a set of messages have an expected round number. + * param: expanded_msgs - set of multisig kex messages to process + * param: expected_round - round number the kex messages should have + */ + //---------------------------------------------------------------------------------------------------------------------- + static void check_messages_round(const std::vector<multisig_kex_msg> &expanded_msgs, + const std::uint32_t expected_round) + { + CHECK_AND_ASSERT_THROW_MES(expanded_msgs.size() > 0, "At least one input message expected."); + const std::uint32_t round{expanded_msgs[0].get_round()}; + CHECK_AND_ASSERT_THROW_MES(round == expected_round, "Messages don't have the expected kex round number."); - return multisig_kex_msg{round, base_privkey, std::move(msg_pubkeys)}; + for (const auto &expanded_msg : expanded_msgs) + CHECK_AND_ASSERT_THROW_MES(expanded_msg.get_round() == round, "All messages must have the same kex round number."); } //---------------------------------------------------------------------------------------------------------------------- /** @@ -327,19 +326,19 @@ namespace multisig static std::uint32_t multisig_kex_msgs_sanitize_pubkeys(const crypto::public_key &own_pubkey, const std::vector<multisig_kex_msg> &expanded_msgs, const std::vector<crypto::public_key> &exclude_pubkeys, - std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>> &sanitized_pubkeys_out) + multisig_keyset_map_memsafe_t &sanitized_pubkeys_out) { + // all messages should have the same round (redundant sanity check) CHECK_AND_ASSERT_THROW_MES(expanded_msgs.size() > 0, "At least one input message expected."); + const std::uint32_t round{expanded_msgs[0].get_round()}; + check_messages_round(expanded_msgs, round); - std::uint32_t round = expanded_msgs[0].get_round(); sanitized_pubkeys_out.clear(); // get all pubkeys from input messages, add them to pubkey:origins map // - origins = all the signing pubkeys that recommended a given msg pubkey for (const auto &expanded_msg : expanded_msgs) { - CHECK_AND_ASSERT_THROW_MES(expanded_msg.get_round() == round, "All messages must have the same kex round number."); - // ignore messages from self if (expanded_msg.get_signing_pubkey() == own_pubkey) continue; @@ -378,7 +377,7 @@ namespace multisig * * brief: evaluate_multisig_kex_round_msgs - Evaluate pubkeys from a kex round in order to prepare for the next round. * - Sanitizes input msgs. - * - Require uniqueness in: 'signers', 'exclude_pubkeys'. + * - Require uniqueness in: 'exclude_pubkeys'. * - Requires each input pubkey be recommended by 'num_recommendations = expected_round' msg signers. * - For a final multisig key to be truly 'M-of-N', each of the the private key's components must be * shared by (N - M + 1) signers. @@ -388,39 +387,21 @@ namespace multisig * with the local account. * - Requires that 'exclude_pubkeys' has [num_signers - 1 CHOOSE (expected_round - 1)] pubkeys. * - These should be derivations the local account has corresponding to round 'expected_round'. - * param: base_privkey - multisig account's base private key + * param: base_pubkey - multisig account's base public key * param: expected_round - expected kex round of input messages - * param: threshold - threshold for multisig (M in M-of-N) * param: signers - expected participants in multisig kex * param: expanded_msgs - set of multisig kex messages to process * param: exclude_pubkeys - derivations held by the local account corresponding to round 'expected_round' * return: fully sanitized and validated pubkey:origins map for building the account's next kex round message */ //---------------------------------------------------------------------------------------------------------------------- - static std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>> evaluate_multisig_kex_round_msgs( + static multisig_keyset_map_memsafe_t evaluate_multisig_kex_round_msgs( const crypto::public_key &base_pubkey, const std::uint32_t expected_round, - const std::uint32_t threshold, const std::vector<crypto::public_key> &signers, const std::vector<multisig_kex_msg> &expanded_msgs, const std::vector<crypto::public_key> &exclude_pubkeys) { - CHECK_AND_ASSERT_THROW_MES(signers.size() > 1, "Must be at least one other multisig signer."); - CHECK_AND_ASSERT_THROW_MES(signers.size() <= config::MULTISIG_MAX_SIGNERS, - "Too many multisig signers specified (limit = 16 to prevent dangerous combinatorial explosion during key exchange)."); - CHECK_AND_ASSERT_THROW_MES(signers.size() >= threshold, "Multisig threshold may not be larger than number of signers."); - CHECK_AND_ASSERT_THROW_MES(threshold > 0, "Multisig threshold must be > 0."); - CHECK_AND_ASSERT_THROW_MES(expected_round > 0, "Expected round must be > 0."); - CHECK_AND_ASSERT_THROW_MES(expected_round <= multisig_kex_rounds_required(signers.size(), threshold), - "Expecting key exchange messages for an invalid round."); - - std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>> pubkey_origins_map; - - // leave early in the last round of 1-of-N, where all signers share a key so the local signer doesn't care about - // recommendations from other signers - if (threshold == 1 && expected_round == multisig_kex_rounds_required(signers.size(), threshold)) - return pubkey_origins_map; - // exclude_pubkeys should all be unique for (auto it = exclude_pubkeys.begin(); it != exclude_pubkeys.end(); ++it) { @@ -429,7 +410,8 @@ namespace multisig } // sanitize input messages - std::uint32_t round = multisig_kex_msgs_sanitize_pubkeys(base_pubkey, expanded_msgs, exclude_pubkeys, pubkey_origins_map); + multisig_keyset_map_memsafe_t pubkey_origins_map; + const std::uint32_t round = multisig_kex_msgs_sanitize_pubkeys(base_pubkey, expanded_msgs, exclude_pubkeys, pubkey_origins_map); CHECK_AND_ASSERT_THROW_MES(round == expected_round, "Kex messages were for round [" << round << "], but expected round is [" << expected_round << "]"); @@ -486,10 +468,10 @@ namespace multisig // - Each origin should have a shared key with each group of size 'round - 1'. // Note: Keys shared with local are ignored to facilitate kex round boosting, where one or more signers may // have boosted the local signer (implying they didn't have access to the local signer's previous round msg). - std::uint32_t expected_recommendations_others = n_choose_k_f(signers.size() - 2, round - 1); + const std::uint32_t expected_recommendations_others = n_choose_k_f(signers.size() - 2, round - 1); // local: (N - 1) choose (msg_round_num - 1) - std::uint32_t expected_recommendations_self = n_choose_k_f(signers.size() - 1, round - 1); + const std::uint32_t expected_recommendations_self = n_choose_k_f(signers.size() - 1, round - 1); // note: expected_recommendations_others would be 0 in the last round of 1-of-N, but we return early for that case CHECK_AND_ASSERT_THROW_MES(expected_recommendations_self > 0 && expected_recommendations_others > 0, @@ -517,7 +499,60 @@ namespace multisig /** * INTERNAL * - * brief: multisig_kex_process_round - Process kex messages for the active kex round. + * brief: evaluate_multisig_post_kex_round_msgs - Evaluate messages for the post-kex verification round. + * - Sanitizes input msgs. + * - Requires that only one pubkey is recommended. + * - Requires that all signers (other than self) recommend that one pubkey. + * param: base_pubkey - multisig account's base public key + * param: expected_round - expected kex round of input messages + * param: signers - expected participants in multisig kex + * param: expanded_msgs - set of multisig kex messages to process + * return: sanitized and validated pubkey:origins map + */ + //---------------------------------------------------------------------------------------------------------------------- + static multisig_keyset_map_memsafe_t evaluate_multisig_post_kex_round_msgs( + const crypto::public_key &base_pubkey, + const std::uint32_t expected_round, + const std::vector<crypto::public_key> &signers, + const std::vector<multisig_kex_msg> &expanded_msgs) + { + // sanitize input messages + const std::vector<crypto::public_key> dummy; + multisig_keyset_map_memsafe_t pubkey_origins_map; + const std::uint32_t round = multisig_kex_msgs_sanitize_pubkeys(base_pubkey, expanded_msgs, dummy, pubkey_origins_map); + CHECK_AND_ASSERT_THROW_MES(round == expected_round, + "Kex messages were for round [" << round << "], but expected round is [" << expected_round << "]"); + + // evaluate pubkeys collected + + // 1) there should only be two pubkeys + CHECK_AND_ASSERT_THROW_MES(pubkey_origins_map.size() == 2, + "Multisig post-kex round messages from other signers did not all contain two pubkeys."); + + // 2) both keys should be recommended by the same set of signers + CHECK_AND_ASSERT_THROW_MES(pubkey_origins_map.begin()->second == (++(pubkey_origins_map.begin()))->second, + "Multisig post-kex round messages from other signers did not all recommend the same pubkey pair."); + + // 3) all signers should be present in the recommendation list + auto origins = pubkey_origins_map.begin()->second; + origins.insert(base_pubkey); //add self + + CHECK_AND_ASSERT_THROW_MES(origins.size() == signers.size(), + "Multisig post-kex round message origins don't line up with multisig signer set."); + + for (const crypto::public_key &signer : signers) + { + CHECK_AND_ASSERT_THROW_MES(origins.find(signer) != origins.end(), + "Could not find an expected signer in multisig post-kex round messages (all signers expected)."); + } + + return pubkey_origins_map; + } + //---------------------------------------------------------------------------------------------------------------------- + /** + * INTERNAL + * + * brief: multisig_kex_process_round_msgs - Process kex messages for the active kex round. * - A wrapper around evaluate_multisig_kex_round_msgs() -> multisig_kex_make_next_msg(). * - In other words, evaluate the input messages and try to make a message for the next round. * - Note: Must be called on the final round's msgs to evaluate the final key components @@ -536,43 +571,62 @@ namespace multisig * return: multisig kex message for next round, or empty message if 'current_round' is the final round */ //---------------------------------------------------------------------------------------------------------------------- - static multisig_kex_msg multisig_kex_process_round(const crypto::secret_key &base_privkey, + static void multisig_kex_process_round_msgs(const crypto::secret_key &base_privkey, const crypto::public_key &base_pubkey, const std::uint32_t current_round, const std::uint32_t threshold, const std::vector<crypto::public_key> &signers, const std::vector<multisig_kex_msg> &expanded_msgs, const std::vector<crypto::public_key> &exclude_pubkeys, - std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>> &keys_to_origins_map_out) + multisig_keyset_map_memsafe_t &keys_to_origins_map_out) { - // evaluate messages - std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>> evaluated_pubkeys = - evaluate_multisig_kex_round_msgs(base_pubkey, current_round, threshold, signers, expanded_msgs, exclude_pubkeys); + check_multisig_config(current_round, threshold, signers.size()); + const std::uint32_t kex_rounds_required{multisig_kex_rounds_required(signers.size(), threshold)}; - // produce message for next round (if there is one) - if (current_round < multisig_kex_rounds_required(signers.size(), threshold)) + // process messages into a [pubkey : {origins}] map + multisig_keyset_map_memsafe_t evaluated_pubkeys; + + if (threshold == 1 && current_round == kex_rounds_required) { - return multisig_kex_make_next_msg(base_privkey, - current_round + 1, - threshold, - signers.size(), - evaluated_pubkeys, - keys_to_origins_map_out); + // in the last main kex round of 1-of-N, all signers share a key so the local signer doesn't care about evaluating + // recommendations from other signers } - else + else if (current_round <= kex_rounds_required) { - // no more rounds, so collect the key shares recommended by other signers for the final aggregate key - keys_to_origins_map_out.clear(); - keys_to_origins_map_out = std::move(evaluated_pubkeys); + // for normal kex rounds, fully evaluate kex round messages + evaluated_pubkeys = evaluate_multisig_kex_round_msgs(base_pubkey, + current_round, + signers, + expanded_msgs, + exclude_pubkeys); + } + else //(current_round == kex_rounds_required + 1) + { + // for the post-kex verification round, validate the last kex round's messages + evaluated_pubkeys = evaluate_multisig_post_kex_round_msgs(base_pubkey, + current_round, + signers, + expanded_msgs); + } - return multisig_kex_msg{}; + // prepare keys-to-origins map for updating the multisig account + if (current_round < kex_rounds_required) + { + // normal kex round: make new keys + multisig_kex_make_round_keys(base_privkey, std::move(evaluated_pubkeys), keys_to_origins_map_out); + } + else if (current_round >= kex_rounds_required) + { + // last kex round: collect the key shares recommended by other signers for the final aggregate key + // post-kex verification round: save the keys found in input messages + keys_to_origins_map_out = std::move(evaluated_pubkeys); } } //---------------------------------------------------------------------------------------------------------------------- // multisig_account: INTERNAL //---------------------------------------------------------------------------------------------------------------------- void multisig_account::initialize_kex_update(const std::vector<multisig_kex_msg> &expanded_msgs, - const std::uint32_t rounds_required, + const std::uint32_t kex_rounds_required, std::vector<crypto::public_key> &exclude_pubkeys_out) { if (m_kex_rounds_complete == 0) @@ -605,7 +659,7 @@ namespace multisig "Failed to derive public key"); // if N-of-N, then the base privkey will be used directly to make the account's share of the final key - if (rounds_required == 1) + if (kex_rounds_required == 1) { m_multisig_privkeys.clear(); m_multisig_privkeys.emplace_back(m_base_privkey); @@ -629,13 +683,29 @@ namespace multisig //---------------------------------------------------------------------------------------------------------------------- // multisig_account: INTERNAL //---------------------------------------------------------------------------------------------------------------------- - void multisig_account::finalize_kex_update(const std::uint32_t rounds_required, - std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>> result_keys_to_origins_map) + void multisig_account::finalize_kex_update(const std::uint32_t kex_rounds_required, + multisig_keyset_map_memsafe_t result_keys_to_origins_map) { + std::vector<crypto::public_key> next_msg_keys; + // prepare for next round (or complete the multisig account fully) - if (rounds_required == m_kex_rounds_complete + 1) + if (m_kex_rounds_complete == kex_rounds_required) + { + // post-kex verification round: check that the multisig pubkey and common pubkey were recommended by other signers + CHECK_AND_ASSERT_THROW_MES(result_keys_to_origins_map.count(m_multisig_pubkey) > 0, + "Multisig post-kex round: expected multisig pubkey wasn't found in other signers' messages."); + CHECK_AND_ASSERT_THROW_MES(result_keys_to_origins_map.count(m_common_pubkey) > 0, + "Multisig post-kex round: expected common pubkey wasn't found in other signers' messages."); + + // save keys that should be recommended to other signers + // - for convenience, re-recommend the post-kex verification message once an account is complete + next_msg_keys.reserve(2); + next_msg_keys.push_back(m_multisig_pubkey); + next_msg_keys.push_back(m_common_pubkey); + } + else if (m_kex_rounds_complete + 1 == kex_rounds_required) { - // finished (have set of msgs to complete address) + // finished with main kex rounds (have set of msgs to complete address) // when 'completing the final round', result keys are other signers' shares of the final key std::vector<crypto::public_key> result_keys; @@ -652,8 +722,14 @@ namespace multisig // no longer need the account's pubkeys saved for this round (they were only used to build exclude_pubkeys) // TODO: record [pre-aggregation pubkeys : origins] map for aggregation-style signing m_kex_keys_to_origins_map.clear(); + + // save keys that should be recommended to other signers + // - for post-kex verification, recommend the multisig pubkeys to notify other signers that the local signer is done + next_msg_keys.reserve(2); + next_msg_keys.push_back(m_multisig_pubkey); + next_msg_keys.push_back(m_common_pubkey); } - else if (rounds_required == m_kex_rounds_complete + 2) + else if (m_kex_rounds_complete + 2 == kex_rounds_required) { // one more round (must send/receive one more set of kex msgs) // - at this point, have local signer's pre-aggregation private key shares of the final address @@ -668,6 +744,7 @@ namespace multisig m_multisig_privkeys.reserve(result_keys_to_origins_map.size()); m_kex_keys_to_origins_map.clear(); + next_msg_keys.reserve(result_keys_to_origins_map.size()); for (const auto &derivation_and_origins : result_keys_to_origins_map) { @@ -679,37 +756,59 @@ namespace multisig // save the account's kex key mappings for this round [derived pubkey : other signers who will have the same key] m_kex_keys_to_origins_map[derived_pubkey] = std::move(derivation_and_origins.second); + + // save keys that should be recommended to other signers + // - The keys multisig_key*G are sent to other participants in the message, so they can be used to produce the final + // multisig key via generate_multisig_spend_public_key(). + next_msg_keys.push_back(derived_pubkey); } } - else + else //(m_kex_rounds_complete + 3 <= kex_rounds_required) { // next round is an 'intermediate' key exchange round, so there is nothing special to do here - // save the account's kex keys for this round [DH derivation : other signers who will have the same derivation] + // save keys that should be recommended to other signers + // - Send this round's DH derivations to other participants, who will make more DH derivations for the following round. + next_msg_keys.reserve(result_keys_to_origins_map.size()); + + for (const auto &derivation_and_origins : result_keys_to_origins_map) + next_msg_keys.push_back(derivation_and_origins.first); + + // save the account's kex keys for this round [DH derivation : other signers who should have the same derivation] m_kex_keys_to_origins_map = std::move(result_keys_to_origins_map); } // a full set of msgs has been collected and processed, so the 'round is complete' ++m_kex_rounds_complete; + + // make next round's message (or reproduce the post-kex verification round if kex is complete) + m_next_round_kex_message = multisig_kex_msg{ + (m_kex_rounds_complete > kex_rounds_required ? kex_rounds_required : m_kex_rounds_complete) + 1, + m_base_privkey, + std::move(next_msg_keys)}.get_msg(); } //---------------------------------------------------------------------------------------------------------------------- // multisig_account: INTERNAL //---------------------------------------------------------------------------------------------------------------------- void multisig_account::kex_update_impl(const std::vector<multisig_kex_msg> &expanded_msgs) { - CHECK_AND_ASSERT_THROW_MES(expanded_msgs.size() > 0, "No key exchange messages passed in."); + // check messages are for the expected kex round + check_messages_round(expanded_msgs, m_kex_rounds_complete + 1); + + // check kex round count + const std::uint32_t kex_rounds_required{multisig_kex_rounds_required(m_signers.size(), m_threshold)}; - const std::uint32_t rounds_required = multisig_kex_rounds_required(m_signers.size(), m_threshold); - CHECK_AND_ASSERT_THROW_MES(rounds_required > 0, "Multisig kex rounds required unexpectedly 0."); + CHECK_AND_ASSERT_THROW_MES(kex_rounds_required > 0, "Multisig kex rounds required unexpectedly 0."); + CHECK_AND_ASSERT_THROW_MES(m_kex_rounds_complete < kex_rounds_required + 1, + "Multisig kex has already completed all required rounds (including post-kex verification)."); // initialize account update std::vector<crypto::public_key> exclude_pubkeys; - initialize_kex_update(expanded_msgs, rounds_required, exclude_pubkeys); - - // evaluate messages and get this account's kex msg for the next round - std::unordered_map<crypto::public_key_memsafe, std::unordered_set<crypto::public_key>> result_keys_to_origins_map; + initialize_kex_update(expanded_msgs, kex_rounds_required, exclude_pubkeys); - m_next_round_kex_message = multisig_kex_process_round( + // process messages into a [pubkey : {origins}] map + multisig_keyset_map_memsafe_t result_keys_to_origins_map; + multisig_kex_process_round_msgs( m_base_privkey, m_base_pubkey, m_kex_rounds_complete + 1, @@ -717,10 +816,10 @@ namespace multisig m_signers, expanded_msgs, exclude_pubkeys, - result_keys_to_origins_map).get_msg(); + result_keys_to_origins_map); // finish account update - finalize_kex_update(rounds_required, std::move(result_keys_to_origins_map)); + finalize_kex_update(kex_rounds_required, std::move(result_keys_to_origins_map)); } //---------------------------------------------------------------------------------------------------------------------- } //namespace multisig diff --git a/src/net/CMakeLists.txt b/src/net/CMakeLists.txt index e93e27bcd..a4d31eedf 100644 --- a/src/net/CMakeLists.txt +++ b/src/net/CMakeLists.txt @@ -1,4 +1,5 @@ -# Copyright (c) 2018, The Monero Project +# Copyright (c) 2018-2022, The Monero Project + # # All rights reserved. # @@ -28,8 +29,7 @@ set(net_sources dandelionpp.cpp error.cpp http.cpp i2p_address.cpp parse.cpp resolve.cpp socks.cpp socks_connect.cpp tor_address.cpp zmq.cpp) -set(net_headers dandelionpp.h error.h http.cpp i2p_address.h parse.h socks.h resolve.h - socks_connect.h tor_address.h zmq.h) +monero_find_all_headers(net_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_add_library(net ${net_sources} ${net_headers}) target_link_libraries(net common epee ${ZMQ_LIB} ${Boost_ASIO_LIBRARY}) diff --git a/src/net/dandelionpp.cpp b/src/net/dandelionpp.cpp index e0d2821e5..e75fb2753 100644 --- a/src/net/dandelionpp.cpp +++ b/src/net/dandelionpp.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/net/dandelionpp.h b/src/net/dandelionpp.h index 345f868af..e344bc7ce 100644 --- a/src/net/dandelionpp.h +++ b/src/net/dandelionpp.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/net/error.cpp b/src/net/error.cpp index d2e713bc5..254db7ae1 100644 --- a/src/net/error.cpp +++ b/src/net/error.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/error.h b/src/net/error.h index 746eb0ecb..969eefc41 100644 --- a/src/net/error.h +++ b/src/net/error.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/fwd.h b/src/net/fwd.h index 7cae88251..b105da115 100644 --- a/src/net/fwd.h +++ b/src/net/fwd.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/http.cpp b/src/net/http.cpp index f54b65c29..c0ed3d430 100644 --- a/src/net/http.cpp +++ b/src/net/http.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/http.h b/src/net/http.h index 91a345851..bbb8ee984 100644 --- a/src/net/http.h +++ b/src/net/http.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/i2p_address.cpp b/src/net/i2p_address.cpp index ada4eb0d3..b0194a525 100644 --- a/src/net/i2p_address.cpp +++ b/src/net/i2p_address.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/net/i2p_address.h b/src/net/i2p_address.h index 5a694419d..7f6ef1b3f 100644 --- a/src/net/i2p_address.h +++ b/src/net/i2p_address.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/net/parse.cpp b/src/net/parse.cpp index 298576ba4..1df6175b4 100644 --- a/src/net/parse.cpp +++ b/src/net/parse.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/parse.h b/src/net/parse.h index 4d5efe161..648076d7b 100644 --- a/src/net/parse.h +++ b/src/net/parse.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/resolve.cpp b/src/net/resolve.cpp index 1b43cf6c4..f4881ffe5 100644 --- a/src/net/resolve.cpp +++ b/src/net/resolve.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/resolve.h b/src/net/resolve.h index 46bd8e617..39b1d1830 100644 --- a/src/net/resolve.h +++ b/src/net/resolve.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/socks.cpp b/src/net/socks.cpp index 6463e669e..97ef4a672 100644 --- a/src/net/socks.cpp +++ b/src/net/socks.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2020, The Monero Project +// Copyright (c) 2018-2022, The Monero Project // // All rights reserved. // diff --git a/src/net/socks.h b/src/net/socks.h index 506b53195..af67d4abe 100644 --- a/src/net/socks.h +++ b/src/net/socks.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2020, The Monero Project +// Copyright (c) 2018-2022, The Monero Project // // All rights reserved. // diff --git a/src/net/socks_connect.cpp b/src/net/socks_connect.cpp index c797a24d4..5317564de 100644 --- a/src/net/socks_connect.cpp +++ b/src/net/socks_connect.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/net/socks_connect.h b/src/net/socks_connect.h index 45bb10efe..587e3cd3c 100644 --- a/src/net/socks_connect.h +++ b/src/net/socks_connect.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/net/tor_address.cpp b/src/net/tor_address.cpp index a04dcb042..ac36dbffd 100644 --- a/src/net/tor_address.cpp +++ b/src/net/tor_address.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/tor_address.h b/src/net/tor_address.h index 22d8cc119..5b036f0d4 100644 --- a/src/net/tor_address.h +++ b/src/net/tor_address.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/net/zmq.cpp b/src/net/zmq.cpp index 15560ca7e..bd7855f21 100644 --- a/src/net/zmq.cpp +++ b/src/net/zmq.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/net/zmq.h b/src/net/zmq.h index fa4ef2fc9..18bb80c8b 100644 --- a/src/net/zmq.h +++ b/src/net/zmq.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/p2p/CMakeLists.txt b/src/p2p/CMakeLists.txt index 0cd38f253..af58d2bb0 100644 --- a/src/p2p/CMakeLists.txt +++ b/src/p2p/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index d9050200a..f9803fd81 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index ac815a100..98d8ecfff 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 199601d00..a3bc3bf24 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -55,7 +55,6 @@ #include "math_helper.h" #include "misc_log_ex.h" #include "p2p_protocol_defs.h" -#include "net/local_ip.h" #include "crypto/crypto.h" #include "storages/levin_abstract_invoke2.h" #include "cryptonote_core/cryptonote_core.h" diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h index 92b7596ae..ef4552f44 100644 --- a/src/p2p/net_node_common.h +++ b/src/p2p/net_node_common.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/p2p/net_peerlist.cpp b/src/p2p/net_peerlist.cpp index 50dc6da77..3e132c91f 100644 --- a/src/p2p/net_peerlist.cpp +++ b/src/p2p/net_peerlist.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index 0662789b9..dc480462d 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -31,6 +31,7 @@ #pragma once #include <iosfwd> +#include <iterator> #include <list> #include <string> #include <vector> @@ -46,7 +47,6 @@ #include "crypto/crypto.h" #include "cryptonote_config.h" #include "net/enums.h" -#include "net/local_ip.h" #include "p2p_protocol_defs.h" #include "syncobj.h" @@ -184,6 +184,7 @@ namespace nodetool private: void trim_white_peerlist(); void trim_gray_peerlist(); + static peerlist_entry get_nth_latest_peer(peers_indexed& peerlist, size_t n); friend class boost::serialization::access; epee::critical_section m_peerlist_lock; @@ -214,6 +215,16 @@ namespace nodetool } } //-------------------------------------------------------------------------------------------------- + inline + peerlist_entry peerlist_manager::get_nth_latest_peer(peers_indexed& peerlist, const size_t n) + { + // Is not thread-safe nor does it check bounds. Do this before calling. Indexing starts at 0. + peers_indexed::index<by_time>::type& by_time_index = peerlist.get<by_time>(); + auto by_time_it = --by_time_index.end(); + std::advance(by_time_it, -static_cast<long long>(n)); + return *by_time_it; + } + //-------------------------------------------------------------------------------------------------- inline bool peerlist_manager::merge_peerlist(const std::vector<peerlist_entry>& outer_bs, const std::function<bool(const peerlist_entry&)> &f) { @@ -235,8 +246,7 @@ namespace nodetool if(i >= m_peers_white.size()) return false; - peers_indexed::index<by_time>::type& by_time_index = m_peers_white.get<by_time>(); - p = *epee::misc_utils::move_it_backward(--by_time_index.end(), i); + p = peerlist_manager::get_nth_latest_peer(m_peers_white, i); return true; } //-------------------------------------------------------------------------------------------------- @@ -247,8 +257,7 @@ namespace nodetool if(i >= m_peers_gray.size()) return false; - peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>(); - p = *epee::misc_utils::move_it_backward(--by_time_index.end(), i); + p = peerlist_manager::get_nth_latest_peer(m_peers_gray, i); return true; } //-------------------------------------------------------------------------------------------------- @@ -437,9 +446,7 @@ namespace nodetool } size_t random_index = crypto::rand_idx(m_peers_gray.size()); - - peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>(); - pe = *epee::misc_utils::move_it_backward(--by_time_index.end(), random_index); + pe = peerlist_manager::get_nth_latest_peer(m_peers_gray, random_index); return true; diff --git a/src/p2p/net_peerlist_boost_serialization.h b/src/p2p/net_peerlist_boost_serialization.h index 1cf4cb026..7d8bd1480 100644 --- a/src/p2p/net_peerlist_boost_serialization.h +++ b/src/p2p/net_peerlist_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h index 12763d4ee..8b9cd0f09 100644 --- a/src/p2p/p2p_protocol_defs.h +++ b/src/p2p/p2p_protocol_defs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -30,6 +30,7 @@ #pragma once +#include <iomanip> #include <boost/uuid/uuid.hpp> #include <boost/serialization/version.hpp> #include "serialization/keyvalue_serialization.h" diff --git a/src/platform/mingw/alloca.h b/src/platform/mingw/alloca.h index b514051aa..10a9db198 100644 --- a/src/platform/mingw/alloca.h +++ b/src/platform/mingw/alloca.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/platform/msc/alloca.h b/src/platform/msc/alloca.h index a9ca8cc84..3b197bf6d 100644 --- a/src/platform/msc/alloca.h +++ b/src/platform/msc/alloca.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/platform/msc/inline_c.h b/src/platform/msc/inline_c.h index 2a4952cff..36d3d0026 100644 --- a/src/platform/msc/inline_c.h +++ b/src/platform/msc/inline_c.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/platform/msc/stdbool.h b/src/platform/msc/stdbool.h index 445b625b4..d4932e8f8 100644 --- a/src/platform/msc/stdbool.h +++ b/src/platform/msc/stdbool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/platform/msc/sys/param.h b/src/platform/msc/sys/param.h index e5d208003..61002e1a1 100644 --- a/src/platform/msc/sys/param.h +++ b/src/platform/msc/sys/param.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/ringct/CMakeLists.txt b/src/ringct/CMakeLists.txt index 40b2dfd55..d415e6409 100644 --- a/src/ringct/CMakeLists.txt +++ b/src/ringct/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2016-2020, The Monero Project +# Copyright (c) 2016-2022, The Monero Project # # All rights reserved. # @@ -31,13 +31,10 @@ set(ringct_basic_sources rctTypes.cpp rctCryptoOps.c multiexp.cc - bulletproofs.cc) + bulletproofs.cc + bulletproofs_plus.cc) -set(ringct_basic_private_headers - rctOps.h - rctTypes.h - multiexp.h - bulletproofs.h) +monero_find_all_headers(ringct_basic_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(ringct_basic ${crypto_private_headers}) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index a6e12c9b3..ba7ab2c0d 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -70,13 +70,12 @@ static rct::key inner_product(const rct::keyV &a, const rct::keyV &b); static constexpr size_t maxN = 64; static constexpr size_t maxM = BULLETPROOF_MAX_OUTPUTS; -static rct::key Hi[maxN*maxM], Gi[maxN*maxM]; static ge_p3 Hi_p3[maxN*maxM], Gi_p3[maxN*maxM]; static std::shared_ptr<straus_cached_data> straus_HiGi_cache; static std::shared_ptr<pippenger_cached_data> pippenger_HiGi_cache; -static const rct::key TWO = { {0x02, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } }; -static const rct::key MINUS_ONE = { { 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } }; -static const rct::key MINUS_INV_EIGHT = { { 0x74, 0xa4, 0x19, 0x7a, 0xf0, 0x7d, 0x0b, 0xf7, 0x05, 0xc2, 0xda, 0x25, 0x2b, 0x5c, 0x0b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a } }; +static const constexpr rct::key TWO = { {0x02, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } }; +static const constexpr rct::key MINUS_ONE = { { 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } }; +static const constexpr rct::key MINUS_INV_EIGHT = { { 0x74, 0xa4, 0x19, 0x7a, 0xf0, 0x7d, 0x0b, 0xf7, 0x05, 0xc2, 0xda, 0x25, 0x2b, 0x5c, 0x0b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a } }; static const rct::keyV oneN = vector_dup(rct::identity(), maxN); static const rct::keyV twoN = vector_powers(TWO, maxN); static const rct::key ip12 = inner_product(oneN, twoN); @@ -100,8 +99,7 @@ static inline bool is_reduced(const rct::key &scalar) static rct::key get_exponent(const rct::key &base, size_t idx) { - static const std::string domain_separator(config::HASH_KEY_BULLETPROOF_EXPONENT); - std::string hashed = std::string((const char*)base.bytes, sizeof(base)) + domain_separator + tools::get_varint_data(idx); + std::string hashed = std::string((const char*)base.bytes, sizeof(base)) + config::HASH_KEY_BULLETPROOF_EXPONENT + tools::get_varint_data(idx); rct::key e; ge_p3 e_p3; rct::hash_to_p3(e_p3, rct::hash2rct(crypto::cn_fast_hash(hashed.data(), hashed.size()))); @@ -121,10 +119,10 @@ static void init_exponents() data.reserve(maxN*maxM*2); for (size_t i = 0; i < maxN*maxM; ++i) { - Hi[i] = get_exponent(rct::H, i * 2); - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Hi_p3[i], Hi[i].bytes) == 0, "ge_frombytes_vartime failed"); - Gi[i] = get_exponent(rct::H, i * 2 + 1); - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Gi_p3[i], Gi[i].bytes) == 0, "ge_frombytes_vartime failed"); + const rct::key Hi = get_exponent(rct::H, i * 2); + CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Hi_p3[i], Hi.bytes) == 0, "ge_frombytes_vartime failed"); + const rct::key Gi = get_exponent(rct::H, i * 2 + 1); + CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Gi_p3[i], Gi.bytes) == 0, "ge_frombytes_vartime failed"); data.push_back({rct::zero(), Gi_p3[i]}); data.push_back({rct::zero(), Hi_p3[i]}); @@ -133,11 +131,10 @@ static void init_exponents() straus_HiGi_cache = straus_init_cache(data, STRAUS_SIZE_LIMIT); pippenger_HiGi_cache = pippenger_init_cache(data, 0, PIPPENGER_SIZE_LIMIT); - MINFO("Hi/Gi cache size: " << (sizeof(Hi)+sizeof(Gi))/1024 << " kB"); MINFO("Hi_p3/Gi_p3 cache size: " << (sizeof(Hi_p3)+sizeof(Gi_p3))/1024 << " kB"); MINFO("Straus cache size: " << straus_get_cache_size(straus_HiGi_cache)/1024 << " kB"); MINFO("Pippenger cache size: " << pippenger_get_cache_size(pippenger_HiGi_cache)/1024 << " kB"); - size_t cache_size = (sizeof(Hi)+sizeof(Hi_p3))*2 + straus_get_cache_size(straus_HiGi_cache) + pippenger_get_cache_size(pippenger_HiGi_cache); + size_t cache_size = straus_get_cache_size(straus_HiGi_cache) + pippenger_get_cache_size(pippenger_HiGi_cache); MINFO("Total cache size: " << cache_size/1024 << "kB"); init_done = true; } @@ -895,7 +892,8 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs) multiexp_data.resize(2 * maxMN); PERF_TIMER_START_BP(VERIFY_line_24_25_invert); - const std::vector<rct::key> inverses = invert(to_invert); + const std::vector<rct::key> inverses = invert(std::move(to_invert)); + to_invert.clear(); PERF_TIMER_STOP_BP(VERIFY_line_24_25_invert); // setup weighted aggregates diff --git a/src/ringct/bulletproofs.h b/src/ringct/bulletproofs.h index d8a9fa4ff..c3fe6f8b9 100644 --- a/src/ringct/bulletproofs.h +++ b/src/ringct/bulletproofs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/ringct/bulletproofs_plus.cc b/src/ringct/bulletproofs_plus.cc new file mode 100644 index 000000000..3d27849c1 --- /dev/null +++ b/src/ringct/bulletproofs_plus.cc @@ -0,0 +1,1121 @@ +// Copyright (c) 2017-2020, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Implements the Bulletproofs+ prover and verifier algorithms +// +// Preprint: https://eprint.iacr.org/2020/735, version 17 Jun 2020 +// +// NOTE ON NOTATION: +// In the signature constructions used in Monero, commitments to zero are treated as +// public keys against the curve group generator `G`. This means that amount +// commitments must use another generator `H` for values in order to show balance. +// The result is that the roles of `g` and `h` in the preprint are effectively swapped +// in this code, taking on the roles of `H` and `G`, respectively. Read carefully! + +#include <stdlib.h> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_guard.hpp> +#include "misc_log_ex.h" +#include "span.h" +#include "cryptonote_config.h" +extern "C" +{ +#include "crypto/crypto-ops.h" +} +#include "rctOps.h" +#include "multiexp.h" +#include "bulletproofs_plus.h" + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "bulletproof_plus" + +#define STRAUS_SIZE_LIMIT 232 +#define PIPPENGER_SIZE_LIMIT 0 + +namespace rct +{ + // Vector functions + static rct::key vector_exponent(const rct::keyV &a, const rct::keyV &b); + static rct::keyV vector_of_scalar_powers(const rct::key &x, size_t n); + + // Proof bounds + static constexpr size_t maxN = 64; // maximum number of bits in range + static constexpr size_t maxM = BULLETPROOF_PLUS_MAX_OUTPUTS; // maximum number of outputs to aggregate into a single proof + + // Cached public generators + static ge_p3 Hi_p3[maxN*maxM], Gi_p3[maxN*maxM]; + static std::shared_ptr<straus_cached_data> straus_HiGi_cache; + static std::shared_ptr<pippenger_cached_data> pippenger_HiGi_cache; + + // Useful scalar constants + static const constexpr rct::key ZERO = { {0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } }; // 0 + static const constexpr rct::key ONE = { {0x01, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } }; // 1 + static const constexpr rct::key TWO = { {0x02, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } }; // 2 + static const constexpr rct::key MINUS_ONE = { { 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } }; // -1 + static const constexpr rct::key MINUS_INV_EIGHT = { { 0x74, 0xa4, 0x19, 0x7a, 0xf0, 0x7d, 0x0b, 0xf7, 0x05, 0xc2, 0xda, 0x25, 0x2b, 0x5c, 0x0b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a } }; // -(8**(-1)) + static rct::key TWO_SIXTY_FOUR_MINUS_ONE; // 2**64 - 1 + + // Initial transcript hash + static rct::key initial_transcript; + + static boost::mutex init_mutex; + + // Use the generator caches to compute a multiscalar multiplication + static inline rct::key multiexp(const std::vector<MultiexpData> &data, size_t HiGi_size) + { + if (HiGi_size > 0) + { + static_assert(232 <= STRAUS_SIZE_LIMIT, "Straus in precalc mode can only be calculated till STRAUS_SIZE_LIMIT"); + return HiGi_size <= 232 && data.size() == HiGi_size ? straus(data, straus_HiGi_cache, 0) : pippenger(data, pippenger_HiGi_cache, HiGi_size, get_pippenger_c(data.size())); + } + else + { + return data.size() <= 95 ? straus(data, NULL, 0) : pippenger(data, NULL, 0, get_pippenger_c(data.size())); + } + } + + // Confirm that a scalar is properly reduced + static inline bool is_reduced(const rct::key &scalar) + { + return sc_check(scalar.bytes) == 0; + } + + // Use hashed values to produce indexed public generators + static ge_p3 get_exponent(const rct::key &base, size_t idx) + { + std::string hashed = std::string((const char*)base.bytes, sizeof(base)) + config::HASH_KEY_BULLETPROOF_PLUS_EXPONENT + tools::get_varint_data(idx); + rct::key generator; + ge_p3 generator_p3; + rct::hash_to_p3(generator_p3, rct::hash2rct(crypto::cn_fast_hash(hashed.data(), hashed.size()))); + ge_p3_tobytes(generator.bytes, &generator_p3); + CHECK_AND_ASSERT_THROW_MES(!(generator == rct::identity()), "Exponent is point at infinity"); + return generator_p3; + } + + // Construct public generators + static void init_exponents() + { + boost::lock_guard<boost::mutex> lock(init_mutex); + + // Only needs to be done once + static bool init_done = false; + if (init_done) + return; + + std::vector<MultiexpData> data; + data.reserve(maxN*maxM*2); + for (size_t i = 0; i < maxN*maxM; ++i) + { + Hi_p3[i] = get_exponent(rct::H, i * 2); + Gi_p3[i] = get_exponent(rct::H, i * 2 + 1); + + data.push_back({rct::zero(), Gi_p3[i]}); + data.push_back({rct::zero(), Hi_p3[i]}); + } + + straus_HiGi_cache = straus_init_cache(data, STRAUS_SIZE_LIMIT); + pippenger_HiGi_cache = pippenger_init_cache(data, 0, PIPPENGER_SIZE_LIMIT); + + // Compute 2**64 - 1 for later use in simplifying verification + TWO_SIXTY_FOUR_MINUS_ONE = TWO; + for (size_t i = 0; i < 6; i++) + { + sc_mul(TWO_SIXTY_FOUR_MINUS_ONE.bytes, TWO_SIXTY_FOUR_MINUS_ONE.bytes, TWO_SIXTY_FOUR_MINUS_ONE.bytes); + } + sc_sub(TWO_SIXTY_FOUR_MINUS_ONE.bytes, TWO_SIXTY_FOUR_MINUS_ONE.bytes, ONE.bytes); + + // Generate the initial Fiat-Shamir transcript hash, which is constant across all proofs + const std::string domain_separator(config::HASH_KEY_BULLETPROOF_PLUS_TRANSCRIPT); + ge_p3 initial_transcript_p3; + rct::hash_to_p3(initial_transcript_p3, rct::hash2rct(crypto::cn_fast_hash(domain_separator.data(), domain_separator.size()))); + ge_p3_tobytes(initial_transcript.bytes, &initial_transcript_p3); + + init_done = true; + } + + // Given two scalar arrays, construct a vector pre-commitment: + // + // a = (a_0, ..., a_{n-1}) + // b = (b_0, ..., b_{n-1}) + // + // Outputs a_0*Gi_0 + ... + a_{n-1}*Gi_{n-1} + + // b_0*Hi_0 + ... + b_{n-1}*Hi_{n-1} + static rct::key vector_exponent(const rct::keyV &a, const rct::keyV &b) + { + CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + CHECK_AND_ASSERT_THROW_MES(a.size() <= maxN*maxM, "Incompatible sizes of a and maxN"); + + std::vector<MultiexpData> multiexp_data; + multiexp_data.reserve(a.size()*2); + for (size_t i = 0; i < a.size(); ++i) + { + multiexp_data.emplace_back(a[i], Gi_p3[i]); + multiexp_data.emplace_back(b[i], Hi_p3[i]); + } + return multiexp(multiexp_data, 2 * a.size()); + } + + // Helper function used to compute the L and R terms used in the inner-product round function + static rct::key compute_LR(size_t size, const rct::key &y, const std::vector<ge_p3> &G, size_t G0, const std::vector<ge_p3> &H, size_t H0, const rct::keyV &a, size_t a0, const rct::keyV &b, size_t b0, const rct::key &c, const rct::key &d) + { + CHECK_AND_ASSERT_THROW_MES(size + G0 <= G.size(), "Incompatible size for G"); + CHECK_AND_ASSERT_THROW_MES(size + H0 <= H.size(), "Incompatible size for H"); + CHECK_AND_ASSERT_THROW_MES(size + a0 <= a.size(), "Incompatible size for a"); + CHECK_AND_ASSERT_THROW_MES(size + b0 <= b.size(), "Incompatible size for b"); + CHECK_AND_ASSERT_THROW_MES(size <= maxN*maxM, "size is too large"); + + std::vector<MultiexpData> multiexp_data; + multiexp_data.resize(size*2 + 2); + rct::key temp; + for (size_t i = 0; i < size; ++i) + { + sc_mul(temp.bytes, a[a0+i].bytes, y.bytes); + sc_mul(multiexp_data[i*2].scalar.bytes, temp.bytes, INV_EIGHT.bytes); + multiexp_data[i*2].point = G[G0+i]; + + sc_mul(multiexp_data[i*2+1].scalar.bytes, b[b0+i].bytes, INV_EIGHT.bytes); + multiexp_data[i*2+1].point = H[H0+i]; + } + + sc_mul(multiexp_data[2*size].scalar.bytes, c.bytes, INV_EIGHT.bytes); + ge_p3 H_p3; + ge_frombytes_vartime(&H_p3, rct::H.bytes); + multiexp_data[2*size].point = H_p3; + + sc_mul(multiexp_data[2*size+1].scalar.bytes, d.bytes, INV_EIGHT.bytes); + ge_p3 G_p3; + ge_frombytes_vartime(&G_p3, rct::G.bytes); + multiexp_data[2*size+1].point = G_p3; + + return multiexp(multiexp_data, 0); + } + + // Given a scalar, construct a vector of its powers: + // + // Output (1,x,x**2,...,x**{n-1}) + static rct::keyV vector_of_scalar_powers(const rct::key &x, size_t n) + { + CHECK_AND_ASSERT_THROW_MES(n != 0, "Need n > 0"); + + rct::keyV res(n); + res[0] = rct::identity(); + if (n == 1) + return res; + res[1] = x; + for (size_t i = 2; i < n; ++i) + { + sc_mul(res[i].bytes, res[i-1].bytes, x.bytes); + } + return res; + } + + // Given a scalar, construct the sum of its powers from 2 to n (where n is a power of 2): + // + // Output x**2 + x**4 + x**6 + ... + x**n + static rct::key sum_of_even_powers(const rct::key &x, size_t n) + { + CHECK_AND_ASSERT_THROW_MES((n & (n - 1)) == 0, "Need n to be a power of 2"); + CHECK_AND_ASSERT_THROW_MES(n != 0, "Need n > 0"); + + rct::key x1 = copy(x); + sc_mul(x1.bytes, x1.bytes, x1.bytes); + + rct::key res = copy(x1); + while (n > 2) + { + sc_muladd(res.bytes, x1.bytes, res.bytes, res.bytes); + sc_mul(x1.bytes, x1.bytes, x1.bytes); + n /= 2; + } + + return res; + } + + // Given a scalar, return the sum of its powers from 1 to n + // + // Output x**1 + x**2 + x**3 + ... + x**n + static rct::key sum_of_scalar_powers(const rct::key &x, size_t n) + { + CHECK_AND_ASSERT_THROW_MES(n != 0, "Need n > 0"); + + rct::key res = ONE; + if (n == 1) + return x; + + n += 1; + rct::key x1 = copy(x); + + const bool is_power_of_2 = (n & (n - 1)) == 0; + if (is_power_of_2) + { + sc_add(res.bytes, res.bytes, x1.bytes); + while (n > 2) + { + sc_mul(x1.bytes, x1.bytes, x1.bytes); + sc_muladd(res.bytes, x1.bytes, res.bytes, res.bytes); + n /= 2; + } + } + else + { + rct::key prev = x1; + for (size_t i = 1; i < n; ++i) + { + if (i > 1) + sc_mul(prev.bytes, prev.bytes, x1.bytes); + sc_add(res.bytes, res.bytes, prev.bytes); + } + } + sc_sub(res.bytes, res.bytes, ONE.bytes); + + return res; + } + + // Given two scalar arrays, construct the weighted inner product against another scalar + // + // Output a_0*b_0*y**1 + a_1*b_1*y**2 + ... + a_{n-1}*b_{n-1}*y**n + static rct::key weighted_inner_product(const epee::span<const rct::key> &a, const epee::span<const rct::key> &b, const rct::key &y) + { + CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + rct::key res = rct::zero(); + rct::key y_power = ONE; + rct::key temp; + for (size_t i = 0; i < a.size(); ++i) + { + sc_mul(temp.bytes, a[i].bytes, b[i].bytes); + sc_mul(y_power.bytes, y_power.bytes, y.bytes); + sc_muladd(res.bytes, temp.bytes, y_power.bytes, res.bytes); + } + return res; + } + + static rct::key weighted_inner_product(const rct::keyV &a, const epee::span<const rct::key> &b, const rct::key &y) + { + CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + return weighted_inner_product(epee::to_span(a), b, y); + } + + // Fold inner-product point vectors + static void hadamard_fold(std::vector<ge_p3> &v, const rct::key &a, const rct::key &b) + { + CHECK_AND_ASSERT_THROW_MES((v.size() & 1) == 0, "Vector size should be even"); + const size_t sz = v.size() / 2; + for (size_t n = 0; n < sz; ++n) + { + ge_dsmp c[2]; + ge_dsm_precomp(c[0], &v[n]); + ge_dsm_precomp(c[1], &v[sz + n]); + ge_double_scalarmult_precomp_vartime2_p3(&v[n], a.bytes, c[0], b.bytes, c[1]); + } + v.resize(sz); + } + + // Add vectors componentwise + static rct::keyV vector_add(const rct::keyV &a, const rct::keyV &b) + { + CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + rct::keyV res(a.size()); + for (size_t i = 0; i < a.size(); ++i) + { + sc_add(res[i].bytes, a[i].bytes, b[i].bytes); + } + return res; + } + + // Add a scalar to all elements of a vector + static rct::keyV vector_add(const rct::keyV &a, const rct::key &b) + { + rct::keyV res(a.size()); + for (size_t i = 0; i < a.size(); ++i) + { + sc_add(res[i].bytes, a[i].bytes, b.bytes); + } + return res; + } + + // Subtract a scalar from all elements of a vector + static rct::keyV vector_subtract(const rct::keyV &a, const rct::key &b) + { + rct::keyV res(a.size()); + for (size_t i = 0; i < a.size(); ++i) + { + sc_sub(res[i].bytes, a[i].bytes, b.bytes); + } + return res; + } + + // Multiply a scalar by all elements of a vector + static rct::keyV vector_scalar(const epee::span<const rct::key> &a, const rct::key &x) + { + rct::keyV res(a.size()); + for (size_t i = 0; i < a.size(); ++i) + { + sc_mul(res[i].bytes, a[i].bytes, x.bytes); + } + return res; + } + + // Inversion helper function + static rct::key sm(rct::key y, int n, const rct::key &x) + { + while (n--) + sc_mul(y.bytes, y.bytes, y.bytes); + sc_mul(y.bytes, y.bytes, x.bytes); + return y; + } + + // Compute the inverse of a nonzero + static rct::key invert(const rct::key &x) + { + CHECK_AND_ASSERT_THROW_MES(!(x == ZERO), "Cannot invert zero!"); + rct::key _1, _10, _100, _11, _101, _111, _1001, _1011, _1111; + + _1 = x; + sc_mul(_10.bytes, _1.bytes, _1.bytes); + sc_mul(_100.bytes, _10.bytes, _10.bytes); + sc_mul(_11.bytes, _10.bytes, _1.bytes); + sc_mul(_101.bytes, _10.bytes, _11.bytes); + sc_mul(_111.bytes, _10.bytes, _101.bytes); + sc_mul(_1001.bytes, _10.bytes, _111.bytes); + sc_mul(_1011.bytes, _10.bytes, _1001.bytes); + sc_mul(_1111.bytes, _100.bytes, _1011.bytes); + + rct::key inv; + sc_mul(inv.bytes, _1111.bytes, _1.bytes); + + inv = sm(inv, 123 + 3, _101); + inv = sm(inv, 2 + 2, _11); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 4, _1001); + inv = sm(inv, 2, _11); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 1 + 3, _101); + inv = sm(inv, 3 + 3, _101); + inv = sm(inv, 3, _111); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 2 + 3, _111); + inv = sm(inv, 2 + 2, _11); + inv = sm(inv, 1 + 4, _1011); + inv = sm(inv, 2 + 4, _1011); + inv = sm(inv, 6 + 4, _1001); + inv = sm(inv, 2 + 2, _11); + inv = sm(inv, 3 + 2, _11); + inv = sm(inv, 3 + 2, _11); + inv = sm(inv, 1 + 4, _1001); + inv = sm(inv, 1 + 3, _111); + inv = sm(inv, 2 + 4, _1111); + inv = sm(inv, 1 + 4, _1011); + inv = sm(inv, 3, _101); + inv = sm(inv, 2 + 4, _1111); + inv = sm(inv, 3, _101); + inv = sm(inv, 1 + 2, _11); + + return inv; + } + + // Invert a batch of scalars, all of which _must_ be nonzero + static rct::keyV invert(rct::keyV x) + { + rct::keyV scratch; + scratch.reserve(x.size()); + + rct::key acc = rct::identity(); + for (size_t n = 0; n < x.size(); ++n) + { + CHECK_AND_ASSERT_THROW_MES(!(x[n] == ZERO), "Cannot invert zero!"); + scratch.push_back(acc); + if (n == 0) + acc = x[0]; + else + sc_mul(acc.bytes, acc.bytes, x[n].bytes); + } + + acc = invert(acc); + + rct::key tmp; + for (int i = x.size(); i-- > 0; ) + { + sc_mul(tmp.bytes, acc.bytes, x[i].bytes); + sc_mul(x[i].bytes, acc.bytes, scratch[i].bytes); + acc = tmp; + } + + return x; + } + + // Compute the slice of a vector + static epee::span<const rct::key> slice(const rct::keyV &a, size_t start, size_t stop) + { + CHECK_AND_ASSERT_THROW_MES(start < a.size(), "Invalid start index"); + CHECK_AND_ASSERT_THROW_MES(stop <= a.size(), "Invalid stop index"); + CHECK_AND_ASSERT_THROW_MES(start < stop, "Invalid start/stop indices"); + return epee::span<const rct::key>(&a[start], stop - start); + } + + // Update the transcript + static rct::key transcript_update(rct::key &transcript, const rct::key &update_0) + { + rct::key data[2]; + data[0] = transcript; + data[1] = update_0; + rct::hash_to_scalar(transcript, data, sizeof(data)); + return transcript; + } + + static rct::key transcript_update(rct::key &transcript, const rct::key &update_0, const rct::key &update_1) + { + rct::key data[3]; + data[0] = transcript; + data[1] = update_0; + data[2] = update_1; + rct::hash_to_scalar(transcript, data, sizeof(data)); + return transcript; + } + + // Given a value v [0..2**N) and a mask gamma, construct a range proof + BulletproofPlus bulletproof_plus_PROVE(const rct::key &sv, const rct::key &gamma) + { + return bulletproof_plus_PROVE(rct::keyV(1, sv), rct::keyV(1, gamma)); + } + + BulletproofPlus bulletproof_plus_PROVE(uint64_t v, const rct::key &gamma) + { + return bulletproof_plus_PROVE(std::vector<uint64_t>(1, v), rct::keyV(1, gamma)); + } + + // Given a set of values v [0..2**N) and masks gamma, construct a range proof + BulletproofPlus bulletproof_plus_PROVE(const rct::keyV &sv, const rct::keyV &gamma) + { + // Sanity check on inputs + CHECK_AND_ASSERT_THROW_MES(sv.size() == gamma.size(), "Incompatible sizes of sv and gamma"); + CHECK_AND_ASSERT_THROW_MES(!sv.empty(), "sv is empty"); + for (const rct::key &sve: sv) + CHECK_AND_ASSERT_THROW_MES(is_reduced(sve), "Invalid sv input"); + for (const rct::key &g: gamma) + CHECK_AND_ASSERT_THROW_MES(is_reduced(g), "Invalid gamma input"); + + init_exponents(); + + // Useful proof bounds + // + // N: number of bits in each range (here, 64) + // logN: base-2 logarithm + // M: first power of 2 greater than or equal to the number of range proofs to aggregate + // logM: base-2 logarithm + constexpr size_t logN = 6; // log2(64) + constexpr size_t N = 1<<logN; + size_t M, logM; + for (logM = 0; (M = 1<<logM) <= maxM && M < sv.size(); ++logM); + CHECK_AND_ASSERT_THROW_MES(M <= maxM, "sv/gamma are too large"); + const size_t logMN = logM + logN; + const size_t MN = M * N; + + rct::keyV V(sv.size()); + rct::keyV aL(MN), aR(MN); + rct::keyV aL8(MN), aR8(MN); + rct::key temp; + rct::key temp2; + + // Prepare output commitments and offset by a factor of 8**(-1) + // + // This offset is applied to other group elements as well; + // it allows us to apply a multiply-by-8 operation in the verifier efficiently + // to ensure that the resulting group elements are in the prime-order point subgroup + // and avoid much more constly multiply-by-group-order operations. + for (size_t i = 0; i < sv.size(); ++i) + { + rct::key gamma8, sv8; + sc_mul(gamma8.bytes, gamma[i].bytes, INV_EIGHT.bytes); + sc_mul(sv8.bytes, sv[i].bytes, INV_EIGHT.bytes); + rct::addKeys2(V[i], gamma8, sv8, rct::H); + } + + // Decompose values + // + // Note that this effectively pads the set to a power of 2, which is required for the inner-product argument later. + for (size_t j = 0; j < M; ++j) + { + for (size_t i = N; i-- > 0; ) + { + if (j < sv.size() && (sv[j][i/8] & (((uint64_t)1)<<(i%8)))) + { + aL[j*N+i] = rct::identity(); + aL8[j*N+i] = INV_EIGHT; + aR[j*N+i] = aR8[j*N+i] = rct::zero(); + } + else + { + aL[j*N+i] = aL8[j*N+i] = rct::zero(); + aR[j*N+i] = MINUS_ONE; + aR8[j*N+i] = MINUS_INV_EIGHT; + } + } + } + +try_again: + // This is a Fiat-Shamir transcript + rct::key transcript = copy(initial_transcript); + transcript = transcript_update(transcript, rct::hash_to_scalar(V)); + + // A + rct::key alpha = rct::skGen(); + rct::key pre_A = vector_exponent(aL8, aR8); + rct::key A; + sc_mul(temp.bytes, alpha.bytes, INV_EIGHT.bytes); + rct::addKeys(A, pre_A, rct::scalarmultBase(temp)); + + // Challenges + rct::key y = transcript_update(transcript, A); + if (y == rct::zero()) + { + MINFO("y is 0, trying again"); + goto try_again; + } + rct::key z = transcript = rct::hash_to_scalar(y); + if (z == rct::zero()) + { + MINFO("z is 0, trying again"); + goto try_again; + } + rct::key z_squared; + sc_mul(z_squared.bytes, z.bytes, z.bytes); + + // Windowed vector + // d[j*N+i] = z**(2*(j+1)) * 2**i + // + // We compute this iteratively in order to reduce scalar operations. + rct::keyV d(MN, rct::zero()); + d[0] = z_squared; + for (size_t i = 1; i < N; i++) + { + sc_mul(d[i].bytes, d[i-1].bytes, TWO.bytes); + } + + for (size_t j = 1; j < M; j++) + { + for (size_t i = 0; i < N; i++) + { + sc_mul(d[j*N+i].bytes, d[(j-1)*N+i].bytes, z_squared.bytes); + } + } + + rct::keyV y_powers = vector_of_scalar_powers(y, MN+2); + + // Prepare inner product terms + rct::keyV aL1 = vector_subtract(aL, z); + + rct::keyV aR1 = vector_add(aR, z); + rct::keyV d_y(MN); + for (size_t i = 0; i < MN; i++) + { + sc_mul(d_y[i].bytes, d[i].bytes, y_powers[MN-i].bytes); + } + aR1 = vector_add(aR1, d_y); + + rct::key alpha1 = alpha; + temp = ONE; + for (size_t j = 0; j < sv.size(); j++) + { + sc_mul(temp.bytes, temp.bytes, z_squared.bytes); + sc_mul(temp2.bytes, y_powers[MN+1].bytes, temp.bytes); + sc_mul(temp2.bytes, temp2.bytes, gamma[j].bytes); + sc_add(alpha1.bytes, alpha1.bytes, temp2.bytes); + } + + // These are used in the inner product rounds + size_t nprime = MN; + std::vector<ge_p3> Gprime(MN); + std::vector<ge_p3> Hprime(MN); + rct::keyV aprime(MN); + rct::keyV bprime(MN); + + const rct::key yinv = invert(y); + rct::keyV yinvpow(MN); + yinvpow[0] = ONE; + for (size_t i = 0; i < MN; ++i) + { + Gprime[i] = Gi_p3[i]; + Hprime[i] = Hi_p3[i]; + if (i > 0) + { + sc_mul(yinvpow[i].bytes, yinvpow[i-1].bytes, yinv.bytes); + } + aprime[i] = aL1[i]; + bprime[i] = aR1[i]; + } + rct::keyV L(logMN); + rct::keyV R(logMN); + int round = 0; + + // Inner-product rounds + while (nprime > 1) + { + nprime /= 2; + + rct::key cL = weighted_inner_product(slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size()), y); + rct::key cR = weighted_inner_product(vector_scalar(slice(aprime, nprime, aprime.size()), y_powers[nprime]), slice(bprime, 0, nprime), y); + + rct::key dL = rct::skGen(); + rct::key dR = rct::skGen(); + + L[round] = compute_LR(nprime, yinvpow[nprime], Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, cL, dL); + R[round] = compute_LR(nprime, y_powers[nprime], Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, cR, dR); + + const rct::key challenge = transcript_update(transcript, L[round], R[round]); + if (challenge == rct::zero()) + { + MINFO("challenge is 0, trying again"); + goto try_again; + } + + const rct::key challenge_inv = invert(challenge); + + sc_mul(temp.bytes, yinvpow[nprime].bytes, challenge.bytes); + hadamard_fold(Gprime, challenge_inv, temp); + hadamard_fold(Hprime, challenge, challenge_inv); + + sc_mul(temp.bytes, challenge_inv.bytes, y_powers[nprime].bytes); + aprime = vector_add(vector_scalar(slice(aprime, 0, nprime), challenge), vector_scalar(slice(aprime, nprime, aprime.size()), temp)); + bprime = vector_add(vector_scalar(slice(bprime, 0, nprime), challenge_inv), vector_scalar(slice(bprime, nprime, bprime.size()), challenge)); + + rct::key challenge_squared; + sc_mul(challenge_squared.bytes, challenge.bytes, challenge.bytes); + rct::key challenge_squared_inv = invert(challenge_squared); + sc_muladd(alpha1.bytes, dL.bytes, challenge_squared.bytes, alpha1.bytes); + sc_muladd(alpha1.bytes, dR.bytes, challenge_squared_inv.bytes, alpha1.bytes); + + ++round; + } + + // Final round computations + rct::key r = rct::skGen(); + rct::key s = rct::skGen(); + rct::key d_ = rct::skGen(); + rct::key eta = rct::skGen(); + + std::vector<MultiexpData> A1_data; + A1_data.reserve(4); + A1_data.resize(4); + + sc_mul(A1_data[0].scalar.bytes, r.bytes, INV_EIGHT.bytes); + A1_data[0].point = Gprime[0]; + + sc_mul(A1_data[1].scalar.bytes, s.bytes, INV_EIGHT.bytes); + A1_data[1].point = Hprime[0]; + + sc_mul(A1_data[2].scalar.bytes, d_.bytes, INV_EIGHT.bytes); + ge_p3 G_p3; + ge_frombytes_vartime(&G_p3, rct::G.bytes); + A1_data[2].point = G_p3; + + sc_mul(temp.bytes, r.bytes, y.bytes); + sc_mul(temp.bytes, temp.bytes, bprime[0].bytes); + sc_mul(temp2.bytes, s.bytes, y.bytes); + sc_mul(temp2.bytes, temp2.bytes, aprime[0].bytes); + sc_add(temp.bytes, temp.bytes, temp2.bytes); + sc_mul(A1_data[3].scalar.bytes, temp.bytes, INV_EIGHT.bytes); + ge_p3 H_p3; + ge_frombytes_vartime(&H_p3, rct::H.bytes); + A1_data[3].point = H_p3; + + rct::key A1 = multiexp(A1_data, 0); + + sc_mul(temp.bytes, r.bytes, y.bytes); + sc_mul(temp.bytes, temp.bytes, s.bytes); + sc_mul(temp.bytes, temp.bytes, INV_EIGHT.bytes); + sc_mul(temp2.bytes, eta.bytes, INV_EIGHT.bytes); + rct::key B; + rct::addKeys2(B, temp2, temp, rct::H); + + rct::key e = transcript_update(transcript, A1, B); + if (e == rct::zero()) + { + MINFO("e is 0, trying again"); + goto try_again; + } + rct::key e_squared; + sc_mul(e_squared.bytes, e.bytes, e.bytes); + + rct::key r1; + sc_muladd(r1.bytes, aprime[0].bytes, e.bytes, r.bytes); + + rct::key s1; + sc_muladd(s1.bytes, bprime[0].bytes, e.bytes, s.bytes); + + rct::key d1; + sc_muladd(d1.bytes, d_.bytes, e.bytes, eta.bytes); + sc_muladd(d1.bytes, alpha1.bytes, e_squared.bytes, d1.bytes); + + return BulletproofPlus(std::move(V), A, A1, B, r1, s1, d1, std::move(L), std::move(R)); + } + + BulletproofPlus bulletproof_plus_PROVE(const std::vector<uint64_t> &v, const rct::keyV &gamma) + { + CHECK_AND_ASSERT_THROW_MES(v.size() == gamma.size(), "Incompatible sizes of v and gamma"); + + // vG + gammaH + rct::keyV sv(v.size()); + for (size_t i = 0; i < v.size(); ++i) + { + sv[i] = rct::d2h(v[i]); + } + return bulletproof_plus_PROVE(sv, gamma); + } + + struct bp_plus_proof_data_t + { + rct::key y, z, e; + std::vector<rct::key> challenges; + size_t logM, inv_offset; + }; + + // Given a batch of range proofs, determine if they are all valid + bool bulletproof_plus_VERIFY(const std::vector<const BulletproofPlus*> &proofs) + { + init_exponents(); + + const size_t logN = 6; + const size_t N = 1 << logN; + + // Set up + size_t max_length = 0; // size of each of the longest proof's inner-product vectors + size_t nV = 0; // number of output commitments across all proofs + size_t inv_offset = 0; + size_t max_logM = 0; + + std::vector<bp_plus_proof_data_t> proof_data; + proof_data.reserve(proofs.size()); + + // We'll perform only a single batch inversion across all proofs in the batch, + // since batch inversion requires only one scalar inversion operation. + std::vector<rct::key> to_invert; + to_invert.reserve(11 * proofs.size()); // maximal size, given the aggregation limit + + for (const BulletproofPlus *p: proofs) + { + const BulletproofPlus &proof = *p; + + // Sanity checks + CHECK_AND_ASSERT_MES(is_reduced(proof.r1), false, "Input scalar not in range"); + CHECK_AND_ASSERT_MES(is_reduced(proof.s1), false, "Input scalar not in range"); + CHECK_AND_ASSERT_MES(is_reduced(proof.d1), false, "Input scalar not in range"); + + CHECK_AND_ASSERT_MES(proof.V.size() >= 1, false, "V does not have at least one element"); + CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), false, "Mismatched L and R sizes"); + CHECK_AND_ASSERT_MES(proof.L.size() > 0, false, "Empty proof"); + + max_length = std::max(max_length, proof.L.size()); + nV += proof.V.size(); + + proof_data.push_back({}); + bp_plus_proof_data_t &pd = proof_data.back(); + + // Reconstruct the challenges + rct::key transcript = copy(initial_transcript); + transcript = transcript_update(transcript, rct::hash_to_scalar(proof.V)); + pd.y = transcript_update(transcript, proof.A); + CHECK_AND_ASSERT_MES(!(pd.y == rct::zero()), false, "y == 0"); + pd.z = transcript = rct::hash_to_scalar(pd.y); + CHECK_AND_ASSERT_MES(!(pd.z == rct::zero()), false, "z == 0"); + + // Determine the number of inner-product rounds based on proof size + size_t M; + for (pd.logM = 0; (M = 1<<pd.logM) <= maxM && M < proof.V.size(); ++pd.logM); + CHECK_AND_ASSERT_MES(proof.L.size() == 6+pd.logM, false, "Proof is not the expected size"); + max_logM = std::max(pd.logM, max_logM); + + const size_t rounds = pd.logM+logN; + CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds"); + + // The inner-product challenges are computed per round + pd.challenges.resize(rounds); + for (size_t j = 0; j < rounds; ++j) + { + pd.challenges[j] = transcript_update(transcript, proof.L[j], proof.R[j]); + CHECK_AND_ASSERT_MES(!(pd.challenges[j] == rct::zero()), false, "challenges[j] == 0"); + } + + // Final challenge + pd.e = transcript_update(transcript,proof.A1,proof.B); + CHECK_AND_ASSERT_MES(!(pd.e == rct::zero()), false, "e == 0"); + + // Batch scalar inversions + pd.inv_offset = inv_offset; + for (size_t j = 0; j < rounds; ++j) + to_invert.push_back(pd.challenges[j]); + to_invert.push_back(pd.y); + inv_offset += rounds + 1; + } + CHECK_AND_ASSERT_MES(max_length < 32, false, "At least one proof is too large"); + size_t maxMN = 1u << max_length; + + rct::key temp; + rct::key temp2; + + // Final batch proof data + std::vector<MultiexpData> multiexp_data; + multiexp_data.reserve(nV + (2 * (max_logM + logN) + 3) * proofs.size() + 2 * maxMN); + multiexp_data.resize(2 * maxMN); + + const std::vector<rct::key> inverses = invert(std::move(to_invert)); + to_invert.clear(); + + // Weights and aggregates + // + // The idea is to take the single multiscalar multiplication used in the verification + // of each proof in the batch and weight it using a random weighting factor, resulting + // in just one multiscalar multiplication check to zero for the entire batch. + // We can further simplify the verifier complexity by including common group elements + // only once in this single multiscalar multiplication. + // Common group elements' weighted scalar sums are tracked across proofs for this reason. + // + // To build a multiscalar multiplication for each proof, we use the method described in + // Section 6.1 of the preprint. Note that the result given there does not account for + // the construction of the inner-product inputs that are produced in the range proof + // verifier algorithm; we have done so here. + rct::key G_scalar = rct::zero(); + rct::key H_scalar = rct::zero(); + rct::keyV Gi_scalars(maxMN, rct::zero()); + rct::keyV Hi_scalars(maxMN, rct::zero()); + + int proof_data_index = 0; + rct::keyV challenges_cache; + std::vector<ge_p3> proof8_V, proof8_L, proof8_R; + + // Process each proof and add to the weighted batch + for (const BulletproofPlus *p: proofs) + { + const BulletproofPlus &proof = *p; + const bp_plus_proof_data_t &pd = proof_data[proof_data_index++]; + + CHECK_AND_ASSERT_MES(proof.L.size() == 6+pd.logM, false, "Proof is not the expected size"); + const size_t M = 1 << pd.logM; + const size_t MN = M*N; + + // Random weighting factor must be nonzero, which is exceptionally unlikely! + rct::key weight = ZERO; + while (weight == ZERO) + { + weight = rct::skGen(); + } + + // Rescale previously offset proof elements + // + // This ensures that all such group elements are in the prime-order subgroup. + proof8_V.resize(proof.V.size()); for (size_t i = 0; i < proof.V.size(); ++i) rct::scalarmult8(proof8_V[i], proof.V[i]); + proof8_L.resize(proof.L.size()); for (size_t i = 0; i < proof.L.size(); ++i) rct::scalarmult8(proof8_L[i], proof.L[i]); + proof8_R.resize(proof.R.size()); for (size_t i = 0; i < proof.R.size(); ++i) rct::scalarmult8(proof8_R[i], proof.R[i]); + ge_p3 proof8_A1; + ge_p3 proof8_B; + ge_p3 proof8_A; + rct::scalarmult8(proof8_A1, proof.A1); + rct::scalarmult8(proof8_B, proof.B); + rct::scalarmult8(proof8_A, proof.A); + + // Compute necessary powers of the y-challenge + rct::key y_MN = copy(pd.y); + rct::key y_MN_1; + size_t temp_MN = MN; + while (temp_MN > 1) + { + sc_mul(y_MN.bytes, y_MN.bytes, y_MN.bytes); + temp_MN /= 2; + } + sc_mul(y_MN_1.bytes, y_MN.bytes, pd.y.bytes); + + // V_j: -e**2 * z**(2*j+1) * y**(MN+1) * weight + rct::key e_squared; + sc_mul(e_squared.bytes, pd.e.bytes, pd.e.bytes); + + rct::key z_squared; + sc_mul(z_squared.bytes, pd.z.bytes, pd.z.bytes); + + sc_sub(temp.bytes, ZERO.bytes, e_squared.bytes); + sc_mul(temp.bytes, temp.bytes, y_MN_1.bytes); + sc_mul(temp.bytes, temp.bytes, weight.bytes); + for (size_t j = 0; j < proof8_V.size(); j++) + { + sc_mul(temp.bytes, temp.bytes, z_squared.bytes); + multiexp_data.emplace_back(temp, proof8_V[j]); + } + + // B: -weight + sc_mul(temp.bytes, MINUS_ONE.bytes, weight.bytes); + multiexp_data.emplace_back(temp, proof8_B); + + // A1: -weight*e + sc_mul(temp.bytes, temp.bytes, pd.e.bytes); + multiexp_data.emplace_back(temp, proof8_A1); + + // A: -weight*e*e + rct::key minus_weight_e_squared; + sc_mul(minus_weight_e_squared.bytes, temp.bytes, pd.e.bytes); + multiexp_data.emplace_back(minus_weight_e_squared, proof8_A); + + // G: weight*d1 + sc_muladd(G_scalar.bytes, weight.bytes, proof.d1.bytes, G_scalar.bytes); + + // Windowed vector + // d[j*N+i] = z**(2*(j+1)) * 2**i + rct::keyV d(MN, rct::zero()); + d[0] = z_squared; + for (size_t i = 1; i < N; i++) + { + sc_add(d[i].bytes, d[i-1].bytes, d[i-1].bytes); + } + + for (size_t j = 1; j < M; j++) + { + for (size_t i = 0; i < N; i++) + { + sc_mul(d[j*N+i].bytes, d[(j-1)*N+i].bytes, z_squared.bytes); + } + } + + // More efficient computation of sum(d) + rct::key sum_d; + sc_mul(sum_d.bytes, TWO_SIXTY_FOUR_MINUS_ONE.bytes, sum_of_even_powers(pd.z, 2*M).bytes); + + // H: weight*( r1*y*s1 + e**2*( y**(MN+1)*z*sum(d) + (z**2-z)*sum(y) ) ) + rct::key sum_y = sum_of_scalar_powers(pd.y, MN); + sc_sub(temp.bytes, z_squared.bytes, pd.z.bytes); + sc_mul(temp.bytes, temp.bytes, sum_y.bytes); + + sc_mul(temp2.bytes, y_MN_1.bytes, pd.z.bytes); + sc_mul(temp2.bytes, temp2.bytes, sum_d.bytes); + sc_add(temp.bytes, temp.bytes, temp2.bytes); + sc_mul(temp.bytes, temp.bytes, e_squared.bytes); + sc_mul(temp2.bytes, proof.r1.bytes, pd.y.bytes); + sc_mul(temp2.bytes, temp2.bytes, proof.s1.bytes); + sc_add(temp.bytes, temp.bytes, temp2.bytes); + sc_muladd(H_scalar.bytes, temp.bytes, weight.bytes, H_scalar.bytes); + + // Compute the number of rounds for the inner-product argument + const size_t rounds = pd.logM+logN; + CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds"); + + const rct::key *challenges_inv = &inverses[pd.inv_offset]; + const rct::key yinv = inverses[pd.inv_offset + rounds]; + + // Compute challenge products + challenges_cache.resize(1<<rounds); + challenges_cache[0] = challenges_inv[0]; + challenges_cache[1] = pd.challenges[0]; + for (size_t j = 1; j < rounds; ++j) + { + const size_t slots = 1<<(j+1); + for (size_t s = slots; s-- > 0; --s) + { + sc_mul(challenges_cache[s].bytes, challenges_cache[s/2].bytes, pd.challenges[j].bytes); + sc_mul(challenges_cache[s-1].bytes, challenges_cache[s/2].bytes, challenges_inv[j].bytes); + } + } + + // Gi and Hi + rct::key e_r1_w_y; + sc_mul(e_r1_w_y.bytes, pd.e.bytes, proof.r1.bytes); + sc_mul(e_r1_w_y.bytes, e_r1_w_y.bytes, weight.bytes); + rct::key e_s1_w; + sc_mul(e_s1_w.bytes, pd.e.bytes, proof.s1.bytes); + sc_mul(e_s1_w.bytes, e_s1_w.bytes, weight.bytes); + rct::key e_squared_z_w; + sc_mul(e_squared_z_w.bytes, e_squared.bytes, pd.z.bytes); + sc_mul(e_squared_z_w.bytes, e_squared_z_w.bytes, weight.bytes); + rct::key minus_e_squared_z_w; + sc_sub(minus_e_squared_z_w.bytes, ZERO.bytes, e_squared_z_w.bytes); + rct::key minus_e_squared_w_y; + sc_sub(minus_e_squared_w_y.bytes, ZERO.bytes, e_squared.bytes); + sc_mul(minus_e_squared_w_y.bytes, minus_e_squared_w_y.bytes, weight.bytes); + sc_mul(minus_e_squared_w_y.bytes, minus_e_squared_w_y.bytes, y_MN.bytes); + for (size_t i = 0; i < MN; ++i) + { + rct::key g_scalar = copy(e_r1_w_y); + rct::key h_scalar; + + // Use the binary decomposition of the index + sc_muladd(g_scalar.bytes, g_scalar.bytes, challenges_cache[i].bytes, e_squared_z_w.bytes); + sc_muladd(h_scalar.bytes, e_s1_w.bytes, challenges_cache[(~i) & (MN-1)].bytes, minus_e_squared_z_w.bytes); + + // Complete the scalar derivation + sc_add(Gi_scalars[i].bytes, Gi_scalars[i].bytes, g_scalar.bytes); + sc_muladd(h_scalar.bytes, minus_e_squared_w_y.bytes, d[i].bytes, h_scalar.bytes); + sc_add(Hi_scalars[i].bytes, Hi_scalars[i].bytes, h_scalar.bytes); + + // Update iterated values + sc_mul(e_r1_w_y.bytes, e_r1_w_y.bytes, yinv.bytes); + sc_mul(minus_e_squared_w_y.bytes, minus_e_squared_w_y.bytes, yinv.bytes); + } + + // L_j: -weight*e*e*challenges[j]**2 + // R_j: -weight*e*e*challenges[j]**(-2) + for (size_t j = 0; j < rounds; ++j) + { + sc_mul(temp.bytes, pd.challenges[j].bytes, pd.challenges[j].bytes); + sc_mul(temp.bytes, temp.bytes, minus_weight_e_squared.bytes); + multiexp_data.emplace_back(temp, proof8_L[j]); + + sc_mul(temp.bytes, challenges_inv[j].bytes, challenges_inv[j].bytes); + sc_mul(temp.bytes, temp.bytes, minus_weight_e_squared.bytes); + multiexp_data.emplace_back(temp, proof8_R[j]); + } + } + + // Verify all proofs in the weighted batch + multiexp_data.emplace_back(G_scalar, rct::G); + multiexp_data.emplace_back(H_scalar, rct::H); + for (size_t i = 0; i < maxMN; ++i) + { + multiexp_data[i * 2] = {Gi_scalars[i], Gi_p3[i]}; + multiexp_data[i * 2 + 1] = {Hi_scalars[i], Hi_p3[i]}; + } + if (!(multiexp(multiexp_data, 2 * maxMN) == rct::identity())) + { + MERROR("Verification failure"); + return false; + } + + return true; + } + + bool bulletproof_plus_VERIFY(const std::vector<BulletproofPlus> &proofs) + { + std::vector<const BulletproofPlus*> proof_pointers; + proof_pointers.reserve(proofs.size()); + for (const BulletproofPlus &proof: proofs) + proof_pointers.push_back(&proof); + return bulletproof_plus_VERIFY(proof_pointers); + } + + bool bulletproof_plus_VERIFY(const BulletproofPlus &proof) + { + std::vector<const BulletproofPlus*> proofs; + proofs.push_back(&proof); + return bulletproof_plus_VERIFY(proofs); + } +} diff --git a/contrib/epee/include/net/net_fwd.h b/src/ringct/bulletproofs_plus.h index f5b6f8db4..d9084075a 100644 --- a/contrib/epee/include/net/net_fwd.h +++ b/src/ringct/bulletproofs_plus.h @@ -1,21 +1,21 @@ -// Copyright (c) 2019-2020, The Monero Project -// +// Copyright (c) 2017-2020, The Monero Project +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. -// +// // 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL @@ -28,11 +28,22 @@ #pragma once -namespace epee +#ifndef BULLETPROOFS_PLUS_H +#define BULLETPROOFS_PLUS_H + +#include "rctTypes.h" + +namespace rct { - namespace net_utils - { - struct ssl_authentication_t; - class ssl_options_t; - } + +BulletproofPlus bulletproof_plus_PROVE(const rct::key &v, const rct::key &gamma); +BulletproofPlus bulletproof_plus_PROVE(uint64_t v, const rct::key &gamma); +BulletproofPlus bulletproof_plus_PROVE(const rct::keyV &v, const rct::keyV &gamma); +BulletproofPlus bulletproof_plus_PROVE(const std::vector<uint64_t> &v, const rct::keyV &gamma); +bool bulletproof_plus_VERIFY(const BulletproofPlus &proof); +bool bulletproof_plus_VERIFY(const std::vector<const BulletproofPlus*> &proofs); +bool bulletproof_plus_VERIFY(const std::vector<BulletproofPlus> &proofs); + } + +#endif diff --git a/src/ringct/multiexp.cc b/src/ringct/multiexp.cc index f256325a1..67814682a 100644 --- a/src/ringct/multiexp.cc +++ b/src/ringct/multiexp.cc @@ -1,4 +1,5 @@ -// Copyright (c) 2017, The Monero Project +// Copyright (c) 2017-2022, The Monero Project + // // All rights reserved. // diff --git a/src/ringct/multiexp.h b/src/ringct/multiexp.h index b52707933..788516c0b 100644 --- a/src/ringct/multiexp.h +++ b/src/ringct/multiexp.h @@ -1,4 +1,5 @@ -// Copyright (c) 2017, The Monero Project +// Copyright (c) 2017-2022, The Monero Project + // // All rights reserved. // diff --git a/src/ringct/rctCryptoOps.c b/src/ringct/rctCryptoOps.c index 506f85c16..a2bb68665 100644 --- a/src/ringct/rctCryptoOps.c +++ b/src/ringct/rctCryptoOps.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/ringct/rctCryptoOps.h b/src/ringct/rctCryptoOps.h index dabb2606a..2d6e13bb7 100644 --- a/src/ringct/rctCryptoOps.h +++ b/src/ringct/rctCryptoOps.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index f5950c53c..d7883baac 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -35,6 +35,7 @@ #include "common/util.h" #include "rctSigs.h" #include "bulletproofs.h" +#include "bulletproofs_plus.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "cryptonote_config.h" @@ -78,6 +79,36 @@ namespace return rct::Bulletproof{rct::keyV(n_outs, I), I, I, I, I, I, I, rct::keyV(nrl, I), rct::keyV(nrl, I), I, I, I}; } + rct::BulletproofPlus make_dummy_bulletproof_plus(const std::vector<uint64_t> &outamounts, rct::keyV &C, rct::keyV &masks) + { + const size_t n_outs = outamounts.size(); + const rct::key I = rct::identity(); + size_t nrl = 0; + while ((1u << nrl) < n_outs) + ++nrl; + nrl += 6; + + C.resize(n_outs); + masks.resize(n_outs); + for (size_t i = 0; i < n_outs; ++i) + { + masks[i] = I; + rct::key sv8, sv; + sv = rct::zero(); + sv.bytes[0] = outamounts[i] & 255; + sv.bytes[1] = (outamounts[i] >> 8) & 255; + sv.bytes[2] = (outamounts[i] >> 16) & 255; + sv.bytes[3] = (outamounts[i] >> 24) & 255; + sv.bytes[4] = (outamounts[i] >> 32) & 255; + sv.bytes[5] = (outamounts[i] >> 40) & 255; + sv.bytes[6] = (outamounts[i] >> 48) & 255; + sv.bytes[7] = (outamounts[i] >> 56) & 255; + sc_mul(sv8.bytes, sv.bytes, rct::INV_EIGHT.bytes); + rct::addKeys2(C[i], rct::INV_EIGHT, sv8, rct::H); + } + + return rct::BulletproofPlus{rct::keyV(n_outs, I), I, I, I, I, I, I, rct::keyV(nrl, I), rct::keyV(nrl, I)}; + } } namespace rct { @@ -107,6 +138,32 @@ namespace rct { catch (...) { return false; } } + BulletproofPlus proveRangeBulletproofPlus(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk, hw::device &hwdev) + { + CHECK_AND_ASSERT_THROW_MES(amounts.size() == sk.size(), "Invalid amounts/sk sizes"); + masks.resize(amounts.size()); + for (size_t i = 0; i < masks.size(); ++i) + masks[i] = hwdev.genCommitmentMask(sk[i]); + BulletproofPlus proof = bulletproof_plus_PROVE(amounts, masks); + CHECK_AND_ASSERT_THROW_MES(proof.V.size() == amounts.size(), "V does not have the expected size"); + C = proof.V; + return proof; + } + + bool verBulletproofPlus(const BulletproofPlus &proof) + { + try { return bulletproof_plus_VERIFY(proof); } + // we can get deep throws from ge_frombytes_vartime if input isn't valid + catch (...) { return false; } + } + + bool verBulletproofPlus(const std::vector<const BulletproofPlus*> &proofs) + { + try { return bulletproof_plus_VERIFY(proofs); } + // we can get deep throws from ge_frombytes_vartime if input isn't valid + catch (...) { return false; } + } + //Borromean (c.f. gmax/andytoshi's paper) boroSig genBorromean(const key64 x, const key64 P1, const key64 P2, const bits indices) { key64 L[2], alpha; @@ -611,6 +668,25 @@ namespace rct { kv.push_back(p.t); } } + else if (rv.type == RCTTypeBulletproofPlus) + { + kv.reserve((6*2+6) * rv.p.bulletproofs_plus.size()); + for (const auto &p: rv.p.bulletproofs_plus) + { + // V are not hashed as they're expanded from outPk.mask + // (and thus hashed as part of rctSigBase above) + kv.push_back(p.A); + kv.push_back(p.A1); + kv.push_back(p.B); + kv.push_back(p.r1); + kv.push_back(p.s1); + kv.push_back(p.d1); + for (size_t n = 0; n < p.L.size(); ++n) + kv.push_back(p.L[n]); + for (size_t n = 0; n < p.R.size(); ++n) + kv.push_back(p.R[n]); + } + } else { kv.reserve((64*3+1) * rv.p.rangeSigs.size()); @@ -1031,7 +1107,7 @@ namespace rct { //mask amount and mask rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].amount = d2h(amounts[i]); - hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG); + hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus); } //set txn fee @@ -1063,7 +1139,7 @@ namespace rct { //RCT simple //for post-rct only rctSig genRctSimple(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<multisig_kLRki> *kLRki, multisig_out *msout, const std::vector<unsigned int> & index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev) { - const bool bulletproof = rct_config.range_proof_type != RangeProofBorromean; + const bool bulletproof_or_plus = rct_config.range_proof_type > RangeProofBorromean; CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts"); CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk"); CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations"); @@ -1079,11 +1155,14 @@ namespace rct { } rctSig rv; - if (bulletproof) + if (bulletproof_or_plus) { switch (rct_config.bp_version) { case 0: + case 4: + rv.type = RCTTypeBulletproofPlus; + break; case 3: rv.type = RCTTypeCLSAG; break; @@ -1102,7 +1181,7 @@ namespace rct { rv.message = message; rv.outPk.resize(destinations.size()); - if (!bulletproof) + if (!bulletproof_or_plus) rv.p.rangeSigs.resize(destinations.size()); rv.ecdhInfo.resize(destinations.size()); @@ -1114,17 +1193,19 @@ namespace rct { //add destination to sig rv.outPk[i].dest = copy(destinations[i]); //compute range proof - if (!bulletproof) + if (!bulletproof_or_plus) rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, outamounts[i]); #ifdef DBG - if (!bulletproof) + if (!bulletproof_or_plus) CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof"); #endif } rv.p.bulletproofs.clear(); - if (bulletproof) + rv.p.bulletproofs_plus.clear(); + if (bulletproof_or_plus) { + const bool plus = is_rct_bulletproof_plus(rv.type); size_t n_amounts = outamounts.size(); size_t amounts_proved = 0; if (rct_config.range_proof_type == RangeProofPaddedBulletproof) @@ -1133,19 +1214,31 @@ namespace rct { if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE) { // use a fake bulletproof for speed - rv.p.bulletproofs.push_back(make_dummy_bulletproof(outamounts, C, masks)); + if (plus) + rv.p.bulletproofs_plus.push_back(make_dummy_bulletproof_plus(outamounts, C, masks)); + else + rv.p.bulletproofs.push_back(make_dummy_bulletproof(outamounts, C, masks)); } else { const epee::span<const key> keys{&amount_keys[0], amount_keys.size()}; - rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys, hwdev)); + if (plus) + rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, outamounts, keys, hwdev)); + else + rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys, hwdev)); #ifdef DBG - CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); + if (plus) + CHECK_AND_ASSERT_THROW_MES(verBulletproofPlus(rv.p.bulletproofs_plus.back()), "verBulletproofPlus failed on newly created proof"); + else + CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); #endif } for (i = 0; i < outamounts.size(); ++i) { - rv.outPk[i].mask = rct::scalarmult8(C[i]); + if (plus) + rv.outPk[i].mask = C[i]; + else + rv.outPk[i].mask = rct::scalarmult8(C[i]); outSk[i].mask = masks[i]; } } @@ -1153,7 +1246,7 @@ namespace rct { { size_t batch_size = 1; if (rct_config.range_proof_type == RangeProofMultiOutputBulletproof) - while (batch_size * 2 + amounts_proved <= n_amounts && batch_size * 2 <= BULLETPROOF_MAX_OUTPUTS) + while (batch_size * 2 + amounts_proved <= n_amounts && batch_size * 2 <= (plus ? BULLETPROOF_PLUS_MAX_OUTPUTS : BULLETPROOF_MAX_OUTPUTS)) batch_size *= 2; rct::keyV C, masks; std::vector<uint64_t> batch_amounts(batch_size); @@ -1162,19 +1255,31 @@ namespace rct { if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE) { // use a fake bulletproof for speed - rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts, C, masks)); + if (plus) + rv.p.bulletproofs_plus.push_back(make_dummy_bulletproof_plus(batch_amounts, C, masks)); + else + rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts, C, masks)); } else { const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size}; - rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys, hwdev)); + if (plus) + rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, batch_amounts, keys, hwdev)); + else + rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys, hwdev)); #ifdef DBG - CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); + if (plus) + CHECK_AND_ASSERT_THROW_MES(verBulletproofPlus(rv.p.bulletproofs_plus.back()), "verBulletproofPlus failed on newly created proof"); + else + CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); #endif } for (i = 0; i < batch_size; ++i) { - rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]); + if (plus) + rv.outPk[i + amounts_proved].mask = C[i]; + else + rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]); outSk[i + amounts_proved].mask = masks[i]; } amounts_proved += batch_size; @@ -1189,7 +1294,7 @@ namespace rct { //mask amount and mask rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].amount = d2h(outamounts[i]); - hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG); + hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus); } //set txn fee @@ -1197,9 +1302,9 @@ namespace rct { // TODO: unused ?? // key txnFeeKey = scalarmultH(d2h(rv.txnFee)); rv.mixRing = mixRing; - keyV &pseudoOuts = bulletproof ? rv.p.pseudoOuts : rv.pseudoOuts; + keyV &pseudoOuts = bulletproof_or_plus ? rv.p.pseudoOuts : rv.pseudoOuts; pseudoOuts.resize(inamounts.size()); - if (rv.type == RCTTypeCLSAG) + if (is_rct_clsag(rv.type)) rv.p.CLSAGs.resize(inamounts.size()); else rv.p.MGs.resize(inamounts.size()); @@ -1218,11 +1323,11 @@ namespace rct { if (msout) { msout->c.resize(inamounts.size()); - msout->mu_p.resize(rv.type == RCTTypeCLSAG ? inamounts.size() : 0); + msout->mu_p.resize(is_rct_clsag(rv.type) ? inamounts.size() : 0); } for (i = 0 ; i < inamounts.size(); i++) { - if (rv.type == RCTTypeCLSAG) + if (is_rct_clsag(rv.type)) { rv.p.CLSAGs[i] = proveRctCLSAGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], kLRki ? &(*kLRki)[i]: NULL, msout ? &msout->c[i] : NULL, msout ? &msout->mu_p[i] : NULL, index[i], hwdev); } @@ -1328,20 +1433,25 @@ namespace rct { tools::threadpool& tpool = tools::threadpool::getInstance(); tools::threadpool::waiter waiter(tpool); std::deque<bool> results; - std::vector<const Bulletproof*> proofs; + std::vector<const Bulletproof*> bp_proofs; + std::vector<const BulletproofPlus*> bpp_proofs; size_t max_non_bp_proofs = 0, offset = 0; for (const rctSig *rvp: rvv) { CHECK_AND_ASSERT_MES(rvp, false, "rctSig pointer is NULL"); const rctSig &rv = *rvp; - CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG, + CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus, false, "verRctSemanticsSimple called on non simple rctSig"); const bool bulletproof = is_rct_bulletproof(rv.type); - if (bulletproof) + const bool bulletproof_plus = is_rct_bulletproof_plus(rv.type); + if (bulletproof || bulletproof_plus) { - CHECK_AND_ASSERT_MES(rv.outPk.size() == n_bulletproof_amounts(rv.p.bulletproofs), false, "Mismatched sizes of outPk and bulletproofs"); - if (rv.type == RCTTypeCLSAG) + if (bulletproof_plus) + CHECK_AND_ASSERT_MES(rv.outPk.size() == n_bulletproof_plus_amounts(rv.p.bulletproofs_plus), false, "Mismatched sizes of outPk and bulletproofs_plus"); + else + CHECK_AND_ASSERT_MES(rv.outPk.size() == n_bulletproof_amounts(rv.p.bulletproofs), false, "Mismatched sizes of outPk and bulletproofs"); + if (is_rct_clsag(rv.type)) { CHECK_AND_ASSERT_MES(rv.p.MGs.empty(), false, "MGs are not empty for CLSAG"); CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.p.CLSAGs.size(), false, "Mismatched sizes of rv.p.pseudoOuts and rv.p.CLSAGs"); @@ -1361,7 +1471,7 @@ namespace rct { } CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo"); - if (!bulletproof) + if (!bulletproof && !bulletproof_plus) max_non_bp_proofs += rv.p.rangeSigs.size(); } @@ -1371,11 +1481,15 @@ namespace rct { const rctSig &rv = *rvp; const bool bulletproof = is_rct_bulletproof(rv.type); - const keyV &pseudoOuts = bulletproof ? rv.p.pseudoOuts : rv.pseudoOuts; + const bool bulletproof_plus = is_rct_bulletproof_plus(rv.type); + const keyV &pseudoOuts = bulletproof || bulletproof_plus ? rv.p.pseudoOuts : rv.pseudoOuts; rct::keyV masks(rv.outPk.size()); for (size_t i = 0; i < rv.outPk.size(); i++) { - masks[i] = rv.outPk[i].mask; + if (bulletproof_plus) + masks[i] = rct::scalarmult8(rv.outPk[i].mask); + else + masks[i] = rv.outPk[i].mask; } key sumOutpks = addKeys(masks); DP(sumOutpks); @@ -1391,10 +1505,15 @@ namespace rct { return false; } - if (bulletproof) + if (bulletproof_plus) + { + for (size_t i = 0; i < rv.p.bulletproofs_plus.size(); i++) + bpp_proofs.push_back(&rv.p.bulletproofs_plus[i]); + } + else if (bulletproof) { for (size_t i = 0; i < rv.p.bulletproofs.size(); i++) - proofs.push_back(&rv.p.bulletproofs[i]); + bp_proofs.push_back(&rv.p.bulletproofs[i]); } else { @@ -1403,9 +1522,18 @@ namespace rct { offset += rv.p.rangeSigs.size(); } } - if (!proofs.empty() && !verBulletproof(proofs)) + if (!bpp_proofs.empty() && !verBulletproofPlus(bpp_proofs)) + { + LOG_PRINT_L1("Aggregate range proof verified failed"); + if (!waiter.wait()) + return false; + return false; + } + if (!bp_proofs.empty() && !verBulletproof(bp_proofs)) { LOG_PRINT_L1("Aggregate range proof verified failed"); + if (!waiter.wait()) + return false; return false; } @@ -1445,11 +1573,12 @@ namespace rct { { PERF_TIMER(verRctNonSemanticsSimple); - CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG, + CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus, false, "verRctNonSemanticsSimple called on non simple rctSig"); const bool bulletproof = is_rct_bulletproof(rv.type); + const bool bulletproof_plus = is_rct_bulletproof_plus(rv.type); // semantics check is early, and mixRing/MGs aren't resolved yet - if (bulletproof) + if (bulletproof || bulletproof_plus) CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.p.pseudoOuts and mixRing"); else CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing"); @@ -1460,7 +1589,7 @@ namespace rct { tools::threadpool& tpool = tools::threadpool::getInstance(); tools::threadpool::waiter waiter(tpool); - const keyV &pseudoOuts = bulletproof ? rv.p.pseudoOuts : rv.pseudoOuts; + const keyV &pseudoOuts = bulletproof || bulletproof_plus ? rv.p.pseudoOuts : rv.pseudoOuts; const key message = get_pre_mlsag_hash(rv, hw::get_device("default")); @@ -1468,10 +1597,8 @@ namespace rct { results.resize(rv.mixRing.size()); for (size_t i = 0 ; i < rv.mixRing.size() ; i++) { tpool.submit(&waiter, [&, i] { - if (rv.type == RCTTypeCLSAG) - { + if (is_rct_clsag(rv.type)) results[i] = verRctCLSAGSimple(message, rv.p.CLSAGs[i], rv.mixRing[i], pseudoOuts[i]); - } else results[i] = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], pseudoOuts[i]); }); @@ -1518,10 +1645,12 @@ namespace rct { //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; - hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG); + hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus); mask = ecdh_info.mask; key amount = ecdh_info.amount; key C = rv.outPk[i].mask; + if (is_rct_bulletproof_plus(rv.type)) + C = scalarmult8(C); DP("C"); DP(C); key Ctmp; @@ -1542,16 +1671,19 @@ namespace rct { } xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask, hw::device &hwdev) { - CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG, false, "decodeRct called on non simple rctSig"); + CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus, + false, "decodeRct called on non simple rctSig"); CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index"); CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo"); //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; - hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG); + hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus); mask = ecdh_info.mask; key amount = ecdh_info.amount; key C = rv.outPk[i].mask; + if (is_rct_bulletproof_plus(rv.type)) + C = scalarmult8(C); DP("C"); DP(C); key Ctmp; @@ -1574,6 +1706,7 @@ namespace rct { bool signMultisigMLSAG(rctSig &rv, const std::vector<unsigned int> &indices, const keyV &k, const multisig_out &msout, const key &secret_key) { CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2, false, "unsupported rct type"); + CHECK_AND_ASSERT_MES(!is_rct_clsag(rv.type), false, "CLSAG signature type in MLSAG signature function"); CHECK_AND_ASSERT_MES(indices.size() == k.size(), false, "Mismatched k/indices sizes"); CHECK_AND_ASSERT_MES(k.size() == rv.p.MGs.size(), false, "Mismatched k/MGs size"); CHECK_AND_ASSERT_MES(k.size() == msout.c.size(), false, "Mismatched k/msout.c size"); @@ -1598,7 +1731,7 @@ namespace rct { } bool signMultisigCLSAG(rctSig &rv, const std::vector<unsigned int> &indices, const keyV &k, const multisig_out &msout, const key &secret_key) { - CHECK_AND_ASSERT_MES(rv.type == RCTTypeCLSAG, false, "unsupported rct type"); + CHECK_AND_ASSERT_MES(is_rct_clsag(rv.type), false, "unsupported rct type"); CHECK_AND_ASSERT_MES(indices.size() == k.size(), false, "Mismatched k/indices sizes"); CHECK_AND_ASSERT_MES(k.size() == rv.p.CLSAGs.size(), false, "Mismatched k/CLSAGs size"); CHECK_AND_ASSERT_MES(k.size() == msout.c.size(), false, "Mismatched k/msout.c size"); @@ -1620,7 +1753,7 @@ namespace rct { } bool signMultisig(rctSig &rv, const std::vector<unsigned int> &indices, const keyV &k, const multisig_out &msout, const key &secret_key) { - if (rv.type == RCTTypeCLSAG) + if (is_rct_clsag(rv.type)) return signMultisigCLSAG(rv, indices, k, msout, secret_key); else return signMultisigMLSAG(rv, indices, k, msout, secret_key); diff --git a/src/ringct/rctTypes.cpp b/src/ringct/rctTypes.cpp index 1f674056d..c22b0524f 100644 --- a/src/ringct/rctTypes.cpp +++ b/src/ringct/rctTypes.cpp @@ -196,6 +196,7 @@ namespace rct { case RCTTypeBulletproof: case RCTTypeBulletproof2: case RCTTypeCLSAG: + case RCTTypeBulletproofPlus: return true; default: return false; @@ -215,6 +216,17 @@ namespace rct { } } + bool is_rct_bulletproof_plus(int type) + { + switch (type) + { + case RCTTypeBulletproofPlus: + return true; + default: + return false; + } + } + bool is_rct_borromean(int type) { switch (type) @@ -227,19 +239,34 @@ namespace rct { } } - size_t n_bulletproof_amounts(const Bulletproof &proof) + bool is_rct_clsag(int type) { - CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size"); - CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size"); + switch (type) + { + case RCTTypeCLSAG: + case RCTTypeBulletproofPlus: + return true; + default: + return false; + } + } + + static size_t n_bulletproof_amounts_base(const size_t L_size, const size_t R_size, const size_t V_size, const size_t max_outputs) + { + CHECK_AND_ASSERT_MES(L_size >= 6, 0, "Invalid bulletproof L size"); + CHECK_AND_ASSERT_MES(L_size == R_size, 0, "Mismatched bulletproof L/R size"); static const size_t extra_bits = 4; - static_assert((1 << extra_bits) == BULLETPROOF_MAX_OUTPUTS, "log2(BULLETPROOF_MAX_OUTPUTS) is out of date"); - CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size"); - CHECK_AND_ASSERT_MES(proof.V.size() <= (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L"); - CHECK_AND_ASSERT_MES(proof.V.size() * 2 > (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L"); - CHECK_AND_ASSERT_MES(proof.V.size() > 0, 0, "Empty bulletproof"); - return proof.V.size(); + CHECK_AND_ASSERT_MES((1 << extra_bits) == max_outputs, 0, "log2(max_outputs) is out of date"); + CHECK_AND_ASSERT_MES(L_size <= 6 + extra_bits, 0, "Invalid bulletproof L size"); + CHECK_AND_ASSERT_MES(V_size <= (1u<<(L_size-6)), 0, "Invalid bulletproof V/L"); + CHECK_AND_ASSERT_MES(V_size * 2 > (1u<<(L_size-6)), 0, "Invalid bulletproof V/L"); + CHECK_AND_ASSERT_MES(V_size > 0, 0, "Empty bulletproof"); + return V_size; } + size_t n_bulletproof_amounts(const Bulletproof &proof) { return n_bulletproof_amounts_base(proof.L.size(), proof.R.size(), proof.V.size(), BULLETPROOF_MAX_OUTPUTS); } + size_t n_bulletproof_plus_amounts(const BulletproofPlus &proof) { return n_bulletproof_amounts_base(proof.L.size(), proof.R.size(), proof.V.size(), BULLETPROOF_PLUS_MAX_OUTPUTS); } + size_t n_bulletproof_amounts(const std::vector<Bulletproof> &proofs) { size_t n = 0; @@ -254,15 +281,31 @@ namespace rct { return n; } - size_t n_bulletproof_max_amounts(const Bulletproof &proof) + size_t n_bulletproof_plus_amounts(const std::vector<BulletproofPlus> &proofs) + { + size_t n = 0; + for (const BulletproofPlus &proof: proofs) + { + size_t n2 = n_bulletproof_plus_amounts(proof); + CHECK_AND_ASSERT_MES(n2 < std::numeric_limits<uint32_t>::max() - n, 0, "Invalid number of bulletproofs"); + if (n2 == 0) + return 0; + n += n2; + } + return n; + } + + static size_t n_bulletproof_max_amounts_base(size_t L_size, size_t R_size, size_t max_outputs) { - CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size"); - CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size"); + CHECK_AND_ASSERT_MES(L_size >= 6, 0, "Invalid bulletproof L size"); + CHECK_AND_ASSERT_MES(L_size == R_size, 0, "Mismatched bulletproof L/R size"); static const size_t extra_bits = 4; - static_assert((1 << extra_bits) == BULLETPROOF_MAX_OUTPUTS, "log2(BULLETPROOF_MAX_OUTPUTS) is out of date"); - CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size"); - return 1 << (proof.L.size() - 6); + CHECK_AND_ASSERT_MES((1 << extra_bits) == max_outputs, 0, "log2(max_outputs) is out of date"); + CHECK_AND_ASSERT_MES(L_size <= 6 + extra_bits, 0, "Invalid bulletproof L size"); + return 1 << (L_size - 6); } + size_t n_bulletproof_max_amounts(const Bulletproof &proof) { return n_bulletproof_max_amounts_base(proof.L.size(), proof.R.size(), BULLETPROOF_MAX_OUTPUTS); } + size_t n_bulletproof_plus_max_amounts(const BulletproofPlus &proof) { return n_bulletproof_max_amounts_base(proof.L.size(), proof.R.size(), BULLETPROOF_PLUS_MAX_OUTPUTS); } size_t n_bulletproof_max_amounts(const std::vector<Bulletproof> &proofs) { @@ -278,4 +321,18 @@ namespace rct { return n; } + size_t n_bulletproof_plus_max_amounts(const std::vector<BulletproofPlus> &proofs) + { + size_t n = 0; + for (const BulletproofPlus &proof: proofs) + { + size_t n2 = n_bulletproof_plus_max_amounts(proof); + CHECK_AND_ASSERT_MES(n2 < std::numeric_limits<uint32_t>::max() - n, 0, "Invalid number of bulletproofs"); + if (n2 == 0) + return 0; + n += n2; + } + return n; + } + } diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 278ff4164..59ed4d6a6 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -238,11 +238,48 @@ namespace rct { END_SERIALIZE() }; + struct BulletproofPlus + { + rct::keyV V; + rct::key A, A1, B; + rct::key r1, s1, d1; + rct::keyV L, R; + + BulletproofPlus() {} + BulletproofPlus(const rct::key &V, const rct::key &A, const rct::key &A1, const rct::key &B, const rct::key &r1, const rct::key &s1, const rct::key &d1, const rct::keyV &L, const rct::keyV &R): + V({V}), A(A), A1(A1), B(B), r1(r1), s1(s1), d1(d1), L(L), R(R) {} + BulletproofPlus(const rct::keyV &V, const rct::key &A, const rct::key &A1, const rct::key &B, const rct::key &r1, const rct::key &s1, const rct::key &d1, const rct::keyV &L, const rct::keyV &R): + V(V), A(A), A1(A1), B(B), r1(r1), s1(s1), d1(d1), L(L), R(R) {} + + bool operator==(const BulletproofPlus &other) const { return V == other.V && A == other.A && A1 == other.A1 && B == other.B && r1 == other.r1 && s1 == other.s1 && d1 == other.d1 && L == other.L && R == other.R; } + + BEGIN_SERIALIZE_OBJECT() + // Commitments aren't saved, they're restored via outPk + // FIELD(V) + FIELD(A) + FIELD(A1) + FIELD(B) + FIELD(r1) + FIELD(s1) + FIELD(d1) + FIELD(L) + FIELD(R) + + if (L.empty() || L.size() != R.size()) + return false; + END_SERIALIZE() + }; + size_t n_bulletproof_amounts(const Bulletproof &proof); size_t n_bulletproof_max_amounts(const Bulletproof &proof); size_t n_bulletproof_amounts(const std::vector<Bulletproof> &proofs); size_t n_bulletproof_max_amounts(const std::vector<Bulletproof> &proofs); + size_t n_bulletproof_plus_amounts(const BulletproofPlus &proof); + size_t n_bulletproof_plus_max_amounts(const BulletproofPlus &proof); + size_t n_bulletproof_plus_amounts(const std::vector<BulletproofPlus> &proofs); + size_t n_bulletproof_plus_max_amounts(const std::vector<BulletproofPlus> &proofs); + //A container to hold all signatures necessary for RingCT // rangeSigs holds all the rangeproof data of a transaction // MG holds the MLSAG signature of a transaction @@ -257,6 +294,7 @@ namespace rct { RCTTypeBulletproof = 3, RCTTypeBulletproof2 = 4, RCTTypeCLSAG = 5, + RCTTypeBulletproofPlus = 6, }; enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof }; struct RCTConfig { @@ -285,7 +323,7 @@ namespace rct { FIELD(type) if (type == RCTTypeNull) return ar.good(); - if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG) + if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus) return false; VARINT_FIELD(txnFee) // inputs/outputs not saved, only here for serialization help @@ -314,7 +352,7 @@ namespace rct { return false; for (size_t i = 0; i < outputs; ++i) { - if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG) + if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus) { ar.begin_object(); if (!typename Archive<W>::is_saving()) @@ -360,6 +398,7 @@ namespace rct { struct rctSigPrunable { std::vector<rangeSig> rangeSigs; std::vector<Bulletproof> bulletproofs; + std::vector<BulletproofPlus> bulletproofs_plus; std::vector<mgSig> MGs; // simple rct has N, full has 1 std::vector<clsag> CLSAGs; keyV pseudoOuts; //C - for simple rct @@ -376,9 +415,28 @@ namespace rct { return false; if (type == RCTTypeNull) return ar.good(); - if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG) + if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus) return false; - if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG) + if (type == RCTTypeBulletproofPlus) + { + uint32_t nbp = bulletproofs_plus.size(); + VARINT_FIELD(nbp) + ar.tag("bpp"); + ar.begin_array(); + if (nbp > outputs) + return false; + PREPARE_CUSTOM_VECTOR_SERIALIZATION(nbp, bulletproofs_plus); + for (size_t i = 0; i < nbp; ++i) + { + FIELDS(bulletproofs_plus[i]) + if (nbp - i > 1) + ar.delimit_array(); + } + if (n_bulletproof_plus_max_amounts(bulletproofs_plus) < outputs) + return false; + ar.end_array(); + } + else if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG) { uint32_t nbp = bulletproofs.size(); if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG) @@ -416,7 +474,7 @@ namespace rct { ar.end_array(); } - if (type == RCTTypeCLSAG) + if (type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus) { ar.tag("CLSAGs"); ar.begin_array(); @@ -507,7 +565,7 @@ namespace rct { } ar.end_array(); } - if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG) + if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus) { ar.tag("pseudoOuts"); ar.begin_array(); @@ -528,6 +586,7 @@ namespace rct { BEGIN_SERIALIZE_OBJECT() FIELD(rangeSigs) FIELD(bulletproofs) + FIELD(bulletproofs_plus) FIELD(MGs) FIELD(CLSAGs) FIELD(pseudoOuts) @@ -538,12 +597,12 @@ namespace rct { keyV& get_pseudo_outs() { - return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG ? p.pseudoOuts : pseudoOuts; + return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts; } keyV const& get_pseudo_outs() const { - return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG ? p.pseudoOuts : pseudoOuts; + return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts; } BEGIN_SERIALIZE_OBJECT() @@ -655,7 +714,9 @@ namespace rct { bool is_rct_simple(int type); bool is_rct_bulletproof(int type); + bool is_rct_bulletproof_plus(int type); bool is_rct_borromean(int type); + bool is_rct_clsag(int type); static inline const rct::key &pk2rct(const crypto::public_key &pk) { return (const rct::key&)pk; } static inline const rct::key &sk2rct(const crypto::secret_key &sk) { return (const rct::key&)sk; } @@ -711,6 +772,7 @@ VARIANT_TAG(debug_archive, rct::Bulletproof, "rct::bulletproof"); VARIANT_TAG(debug_archive, rct::multisig_kLRki, "rct::multisig_kLRki"); VARIANT_TAG(debug_archive, rct::multisig_out, "rct::multisig_out"); VARIANT_TAG(debug_archive, rct::clsag, "rct::clsag"); +VARIANT_TAG(debug_archive, rct::BulletproofPlus, "rct::bulletproof_plus"); VARIANT_TAG(binary_archive, rct::key, 0x90); VARIANT_TAG(binary_archive, rct::key64, 0x91); @@ -728,6 +790,7 @@ VARIANT_TAG(binary_archive, rct::Bulletproof, 0x9c); VARIANT_TAG(binary_archive, rct::multisig_kLRki, 0x9d); VARIANT_TAG(binary_archive, rct::multisig_out, 0x9e); VARIANT_TAG(binary_archive, rct::clsag, 0x9f); +VARIANT_TAG(binary_archive, rct::BulletproofPlus, 0xa0); VARIANT_TAG(json_archive, rct::key, "rct_key"); VARIANT_TAG(json_archive, rct::key64, "rct_key64"); @@ -745,5 +808,6 @@ VARIANT_TAG(json_archive, rct::Bulletproof, "rct_bulletproof"); VARIANT_TAG(json_archive, rct::multisig_kLRki, "rct_multisig_kLR"); VARIANT_TAG(json_archive, rct::multisig_out, "rct_multisig_out"); VARIANT_TAG(json_archive, rct::clsag, "rct_clsag"); +VARIANT_TAG(json_archive, rct::BulletproofPlus, "rct_bulletproof_plus"); #endif /* RCTTYPES_H */ diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 15e433e10..edfc70067 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/rpc/bootstrap_node_selector.cpp b/src/rpc/bootstrap_node_selector.cpp index 34845060e..a1cad3e59 100644 --- a/src/rpc/bootstrap_node_selector.cpp +++ b/src/rpc/bootstrap_node_selector.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/rpc/bootstrap_node_selector.h b/src/rpc/bootstrap_node_selector.h index 47722a008..616c180fc 100644 --- a/src/rpc/bootstrap_node_selector.h +++ b/src/rpc/bootstrap_node_selector.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index dbbdfc02a..869040657 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -48,6 +48,7 @@ using namespace epee; #include "cryptonote_basic/merge_mining.h" #include "cryptonote_core/tx_sanity_check.h" #include "misc_language.h" +#include "net/local_ip.h" #include "net/parse.h" #include "storages/http_abstract_invoke.h" #include "crypto/hash.h" @@ -364,6 +365,8 @@ namespace cryptonote std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options) ); + m_net_server.get_config_object().m_max_content_length = MAX_RPC_CONTENT_LENGTH; + if (store_ssl_key && inited) { // new keys were generated, store for next run @@ -478,6 +481,7 @@ namespace cryptonote } CHECK_PAYMENT_MIN1(req, res, COST_PER_GET_INFO, false); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); const bool restricted = m_restricted && ctx; @@ -583,6 +587,7 @@ namespace cryptonote } CHECK_PAYMENT(req, res, 1); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); // quick check for noop if (!req.block_ids.empty()) @@ -593,7 +598,7 @@ namespace cryptonote if (last_block_hash == req.block_ids.front()) { res.start_height = 0; - res.current_height = m_core.get_current_blockchain_height(); + res.current_height = last_block_height + 1; res.status = CORE_RPC_STATUS_OK; return true; } @@ -714,6 +719,7 @@ namespace cryptonote res.blocks.clear(); res.blocks.reserve(req.heights.size()); CHECK_PAYMENT_MIN1(req, res, req.heights.size() * COST_PER_BLOCK, false); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); for (uint64_t height : req.heights) { block blk; @@ -1575,6 +1581,7 @@ namespace cryptonote return r; CHECK_PAYMENT(req, res, 1); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); const bool restricted = m_restricted && ctx; const bool request_has_rpc_origin = ctx != NULL; @@ -1599,6 +1606,7 @@ namespace cryptonote return r; CHECK_PAYMENT(req, res, 1); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); const bool restricted = m_restricted && ctx; const bool request_has_rpc_origin = ctx != NULL; @@ -1701,11 +1709,14 @@ namespace cryptonote error_resp.message = "Wrong parameters, expected height"; return false; } + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); uint64_t h = req[0]; - if(m_core.get_current_blockchain_height() <= h) + uint64_t blockchain_height = m_core.get_current_blockchain_height(); + if(blockchain_height <= h) { error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; - error_resp.message = std::string("Requested block height: ") + std::to_string(h) + " greater than current top block height: " + std::to_string(m_core.get_current_blockchain_height() - 1); + error_resp.message = std::string("Requested block height: ") + std::to_string(h) + " greater than current top block height: " + std::to_string(blockchain_height - 1); + return false; } res = string_tools::pod_to_hex(m_core.get_block_id_by_height(h)); return true; @@ -1855,6 +1866,7 @@ namespace cryptonote return false; } } + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); crypto::hash seed_hash, next_seed_hash; if (!get_block_template(info.address, req.prev_block.empty() ? NULL : &prev_block, blob_reserve, reserved_offset, wdiff, res.height, res.expected_reward, b, res.seed_height, seed_hash, next_seed_hash, error_resp)) return false; @@ -2328,6 +2340,7 @@ namespace cryptonote CHECK_CORE_READY(); CHECK_PAYMENT_MIN1(req, res, COST_PER_BLOCK_HEADER, false); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); uint64_t last_block_height; crypto::hash last_block_hash; m_core.get_blockchain_top(last_block_height, last_block_hash); @@ -2368,6 +2381,8 @@ namespace cryptonote return false; } + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); + auto get = [this](const std::string &hash, bool fill_pow_hash, block_header_response &block_header, bool restricted, epee::json_rpc::error& error_resp) -> bool { crypto::hash block_hash; bool hash_parsed = parse_hash256(hash, block_hash); @@ -2427,13 +2442,6 @@ namespace cryptonote if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCK_HEADERS_RANGE>(invoke_http_mode::JON_RPC, "getblockheadersrange", req, res, r)) return r; - const uint64_t bc_height = m_core.get_current_blockchain_height(); - if (req.start_height >= bc_height || req.end_height >= bc_height || req.start_height > req.end_height) - { - error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; - error_resp.message = "Invalid start/end heights."; - return false; - } const bool restricted = m_restricted && ctx; if (restricted && req.end_height - req.start_height > RESTRICTED_BLOCK_HEADER_RANGE) { @@ -2443,6 +2451,16 @@ namespace cryptonote } CHECK_PAYMENT_MIN1(req, res, (req.end_height - req.start_height + 1) * COST_PER_BLOCK_HEADER, false); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); + + const uint64_t bc_height = m_core.get_current_blockchain_height(); + if (req.start_height >= bc_height || req.end_height >= bc_height || req.start_height > req.end_height) + { + error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; + error_resp.message = "Invalid start/end heights."; + return false; + } + for (uint64_t h = req.start_height; h <= req.end_height; ++h) { crypto::hash block_hash = m_core.get_block_id_by_height(h); @@ -2487,10 +2505,12 @@ namespace cryptonote if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT>(invoke_http_mode::JON_RPC, "getblockheaderbyheight", req, res, r)) return r; - if(m_core.get_current_blockchain_height() <= req.height) + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); + uint64_t blockchain_height = m_core.get_current_blockchain_height(); + if(blockchain_height <= req.height) { error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; - error_resp.message = std::string("Requested block height: ") + std::to_string(req.height) + " greater than current top block height: " + std::to_string(m_core.get_current_blockchain_height() - 1); + error_resp.message = std::string("Requested block height: ") + std::to_string(req.height) + " greater than current top block height: " + std::to_string(blockchain_height - 1); return false; } CHECK_PAYMENT_MIN1(req, res, COST_PER_BLOCK_HEADER, false); @@ -2523,6 +2543,7 @@ namespace cryptonote return r; CHECK_PAYMENT_MIN1(req, res, COST_PER_BLOCK, false); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); crypto::hash block_hash; if (!req.hash.empty()) @@ -2537,10 +2558,11 @@ namespace cryptonote } else { - if(m_core.get_current_blockchain_height() <= req.height) + uint64_t blockchain_height = m_core.get_current_blockchain_height(); + if(blockchain_height <= req.height) { error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; - error_resp.message = std::string("Requested block height: ") + std::to_string(req.height) + " greater than current top block height: " + std::to_string(m_core.get_current_blockchain_height() - 1); + error_resp.message = std::string("Requested block height: ") + std::to_string(req.height) + " greater than current top block height: " + std::to_string(blockchain_height - 1); return false; } block_hash = m_core.get_block_id_by_height(req.height); @@ -2848,6 +2870,7 @@ namespace cryptonote bool core_rpc_server::on_get_coinbase_tx_sum(const COMMAND_RPC_GET_COINBASE_TX_SUM::request& req, COMMAND_RPC_GET_COINBASE_TX_SUM::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx) { RPC_TRACKER(get_coinbase_tx_sum); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); const uint64_t bc_height = m_core.get_current_blockchain_height(); if (req.height >= bc_height || req.count > bc_height) { @@ -2870,7 +2893,17 @@ namespace cryptonote return r; CHECK_PAYMENT(req, res, COST_PER_FEE_ESTIMATE); - res.fee = m_core.get_blockchain_storage().get_dynamic_base_fee_estimate(req.grace_blocks); + + const uint8_t version = m_core.get_blockchain_storage().get_current_hard_fork_version(); + if (version >= HF_VERSION_2021_SCALING) + { + m_core.get_blockchain_storage().get_dynamic_base_fee_estimate_2021_scaling(req.grace_blocks, res.fees); + res.fee = res.fees[0]; + } + else + { + res.fee = m_core.get_blockchain_storage().get_dynamic_base_fee_estimate(req.grace_blocks); + } res.quantization_mask = Blockchain::get_fee_quantization_mask(); res.status = CORE_RPC_STATUS_OK; return true; @@ -2879,6 +2912,7 @@ namespace cryptonote bool core_rpc_server::on_get_alternate_chains(const COMMAND_RPC_GET_ALTERNATE_CHAINS::request& req, COMMAND_RPC_GET_ALTERNATE_CHAINS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx) { RPC_TRACKER(get_alternate_chains); + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); try { std::vector<std::pair<Blockchain::block_extended_info, std::vector<crypto::hash>>> chains = m_core.get_blockchain_storage().get_alternative_chains(); @@ -3181,6 +3215,7 @@ namespace cryptonote bool r; if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG>(invoke_http_mode::JON_RPC, "get_txpool_backlog", req, res, r)) return r; + db_rtxn_guard rtxn_guard(&m_core.get_blockchain_storage().get_db()); size_t n_txes = m_core.get_pool_transactions_count(); CHECK_PAYMENT_MIN1(req, res, COST_PER_TX_POOL_STATS * n_txes, false); diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 664af3686..0274f4db8 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index d25196841..1be2610ff 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -2191,11 +2191,13 @@ namespace cryptonote { uint64_t fee; uint64_t quantization_mask; + std::vector<uint64_t> fees; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE_PARENT(rpc_access_response_base) KV_SERIALIZE(fee) KV_SERIALIZE_OPT(quantization_mask, (uint64_t)1) + KV_SERIALIZE(fees) END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init<response_t> response; diff --git a/src/rpc/core_rpc_server_error_codes.h b/src/rpc/core_rpc_server_error_codes.h index 232df0373..1ba2392a9 100644 --- a/src/rpc/core_rpc_server_error_codes.h +++ b/src/rpc/core_rpc_server_error_codes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index cdfc363a9..0466c92c2 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/daemon_handler.h b/src/rpc/daemon_handler.h index 31c4f3ec4..74885cf30 100644 --- a/src/rpc/daemon_handler.h +++ b/src/rpc/daemon_handler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/daemon_messages.cpp b/src/rpc/daemon_messages.cpp index 887486f77..a7c921ff9 100644 --- a/src/rpc/daemon_messages.cpp +++ b/src/rpc/daemon_messages.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/daemon_messages.h b/src/rpc/daemon_messages.h index dea37c9a6..fb33f0d4a 100644 --- a/src/rpc/daemon_messages.h +++ b/src/rpc/daemon_messages.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/daemon_rpc_version.h b/src/rpc/daemon_rpc_version.h index 2955d5449..62847fd58 100644 --- a/src/rpc/daemon_rpc_version.h +++ b/src/rpc/daemon_rpc_version.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/fwd.h b/src/rpc/fwd.h index 72537f5a5..cd9eacb9a 100644 --- a/src/rpc/fwd.h +++ b/src/rpc/fwd.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/instanciations.cpp b/src/rpc/instanciations.cpp index ac992d4ad..6e48d36a8 100644 --- a/src/rpc/instanciations.cpp +++ b/src/rpc/instanciations.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/message.cpp b/src/rpc/message.cpp index f6c6b887d..005c40ea2 100644 --- a/src/rpc/message.cpp +++ b/src/rpc/message.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/message.h b/src/rpc/message.h index 04bf1a111..730b3ec74 100644 --- a/src/rpc/message.h +++ b/src/rpc/message.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/message_data_structs.h b/src/rpc/message_data_structs.h index 86424653f..dd9d198ed 100644 --- a/src/rpc/message_data_structs.h +++ b/src/rpc/message_data_structs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp index b2d019ae7..74f0879af 100644 --- a/src/rpc/rpc_args.cpp +++ b/src/rpc/rpc_args.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h index f06e539bd..0b0dac57a 100644 --- a/src/rpc/rpc_args.h +++ b/src/rpc/rpc_args.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_handler.h b/src/rpc/rpc_handler.h index 9757fc462..c84460549 100644 --- a/src/rpc/rpc_handler.h +++ b/src/rpc/rpc_handler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_payment.cpp b/src/rpc/rpc_payment.cpp index f0c513911..2e05f04fb 100644 --- a/src/rpc/rpc_payment.cpp +++ b/src/rpc/rpc_payment.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2020, The Monero Project +// Copyright (c) 2018-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_payment.h b/src/rpc/rpc_payment.h index fdf1f953f..e93f27d24 100644 --- a/src/rpc/rpc_payment.h +++ b/src/rpc/rpc_payment.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2020, The Monero Project +// Copyright (c) 2018-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_payment_costs.h b/src/rpc/rpc_payment_costs.h index 9bc0f8a2b..6ba4e8064 100644 --- a/src/rpc/rpc_payment_costs.h +++ b/src/rpc/rpc_payment_costs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_payment_signature.cpp b/src/rpc/rpc_payment_signature.cpp index a5dc21717..4e4798aae 100644 --- a/src/rpc/rpc_payment_signature.cpp +++ b/src/rpc/rpc_payment_signature.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2020, The Monero Project +// Copyright (c) 2018-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_payment_signature.h b/src/rpc/rpc_payment_signature.h index bf7ee061f..55ba49e9a 100644 --- a/src/rpc/rpc_payment_signature.h +++ b/src/rpc/rpc_payment_signature.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2020, The Monero Project +// Copyright (c) 2018-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_version_str.cpp b/src/rpc/rpc_version_str.cpp index b8b231c16..528c92415 100644 --- a/src/rpc/rpc_version_str.cpp +++ b/src/rpc/rpc_version_str.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/rpc_version_str.h b/src/rpc/rpc_version_str.h index b0cb47c5f..b81a76980 100644 --- a/src/rpc/rpc_version_str.h +++ b/src/rpc/rpc_version_str.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/zmq_pub.cpp b/src/rpc/zmq_pub.cpp index 074b55207..81e6de99a 100644 --- a/src/rpc/zmq_pub.cpp +++ b/src/rpc/zmq_pub.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/rpc/zmq_pub.h b/src/rpc/zmq_pub.h index c636e1d7b..9554f26be 100644 --- a/src/rpc/zmq_pub.h +++ b/src/rpc/zmq_pub.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/src/rpc/zmq_server.cpp b/src/rpc/zmq_server.cpp index 4028df96a..398a0499a 100644 --- a/src/rpc/zmq_server.cpp +++ b/src/rpc/zmq_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/rpc/zmq_server.h b/src/rpc/zmq_server.h index ddf44b411..2d4049baa 100644 --- a/src/rpc/zmq_server.h +++ b/src/rpc/zmq_server.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/CMakeLists.txt b/src/serialization/CMakeLists.txt index 34e274b6c..d3b9e57ca 100644 --- a/src/serialization/CMakeLists.txt +++ b/src/serialization/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2016-2020, The Monero Project +# Copyright (c) 2016-2022, The Monero Project # # All rights reserved. # @@ -31,8 +31,7 @@ set(serialization_sources set(serialization_headers) -set(serialization_private_headers - json_object.h) +monero_find_all_headers(serialization_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(serialization ${serialization_private_headers}) diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h index acda70039..07a4ec169 100644 --- a/src/serialization/binary_archive.h +++ b/src/serialization/binary_archive.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/binary_utils.h b/src/serialization/binary_utils.h index 8444f220e..9b41e9529 100644 --- a/src/serialization/binary_utils.h +++ b/src/serialization/binary_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/container.h b/src/serialization/container.h index 77681ec93..7b59e9408 100644 --- a/src/serialization/container.h +++ b/src/serialization/container.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/containers.h b/src/serialization/containers.h index bc4a89527..dd2de829a 100644 --- a/src/serialization/containers.h +++ b/src/serialization/containers.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/crypto.h b/src/serialization/crypto.h index d635a9ee9..c2a4846ee 100644 --- a/src/serialization/crypto.h +++ b/src/serialization/crypto.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -85,6 +85,7 @@ BLOB_SERIALIZER(crypto::secret_key); BLOB_SERIALIZER(crypto::key_derivation); BLOB_SERIALIZER(crypto::key_image); BLOB_SERIALIZER(crypto::signature); +BLOB_SERIALIZER(crypto::view_tag); VARIANT_TAG(debug_archive, crypto::hash, "hash"); VARIANT_TAG(debug_archive, crypto::hash8, "hash8"); VARIANT_TAG(debug_archive, crypto::public_key, "public_key"); @@ -92,4 +93,5 @@ VARIANT_TAG(debug_archive, crypto::secret_key, "secret_key"); VARIANT_TAG(debug_archive, crypto::key_derivation, "key_derivation"); VARIANT_TAG(debug_archive, crypto::key_image, "key_image"); VARIANT_TAG(debug_archive, crypto::signature, "signature"); +VARIANT_TAG(debug_archive, crypto::view_tag, "view_tag"); diff --git a/src/serialization/debug_archive.h b/src/serialization/debug_archive.h index e8ccb9a58..479ed0cac 100644 --- a/src/serialization/debug_archive.h +++ b/src/serialization/debug_archive.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/difficulty_type.h b/src/serialization/difficulty_type.h index 75d1fd13f..b13693c26 100644 --- a/src/serialization/difficulty_type.h +++ b/src/serialization/difficulty_type.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/json_archive.h b/src/serialization/json_archive.h index bab6dfa94..8c4486d05 100644 --- a/src/serialization/json_archive.h +++ b/src/serialization/json_archive.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index b03da1edc..8de5860f6 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // @@ -300,7 +300,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::transaction& tx) } const auto& rsig = tx.rct_signatures; - if (!cryptonote::is_coinbase(tx) && rsig.p.bulletproofs.empty() && rsig.p.rangeSigs.empty() && rsig.p.MGs.empty() && rsig.get_pseudo_outs().empty() && sigs == val.MemberEnd()) + if (!cryptonote::is_coinbase(tx) && rsig.p.bulletproofs.empty() && rsig.p.bulletproofs_plus.empty() && rsig.p.rangeSigs.empty() && rsig.p.MGs.empty() && rsig.get_pseudo_outs().empty() && sigs == val.MemberEnd()) tx.pruned = true; } @@ -563,6 +563,27 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_key& txout) GET_FROM_JSON_OBJECT(val, txout.key, key); } +void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_tagged_key& txout) +{ + dest.StartObject(); + + INSERT_INTO_JSON_OBJECT(dest, key, txout.key); + INSERT_INTO_JSON_OBJECT(dest, view_tag, txout.view_tag); + + dest.EndObject(); +} + +void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_tagged_key& txout) +{ + if (!val.IsObject()) + { + throw WRONG_TYPE("json object"); + } + + GET_FROM_JSON_OBJECT(val, txout.key, key); + GET_FROM_JSON_OBJECT(val, txout.view_tag, view_tag); +} + void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_out& txout) { dest.StartObject(); @@ -578,6 +599,10 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::t { INSERT_INTO_JSON_OBJECT(dest, to_key, output); } + void operator()(cryptonote::txout_to_tagged_key const& output) const + { + INSERT_INTO_JSON_OBJECT(dest, to_tagged_key, output); + } void operator()(cryptonote::txout_to_script const& output) const { INSERT_INTO_JSON_OBJECT(dest, to_script, output); @@ -616,6 +641,12 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_out& txout) fromJsonValue(elem.value, tmpVal); txout.target = std::move(tmpVal); } + else if (elem.name == "to_tagged_key") + { + cryptonote::txout_to_tagged_key tmpVal; + fromJsonValue(elem.value, tmpVal); + txout.target = std::move(tmpVal); + } else if (elem.name == "to_script") { cryptonote::txout_to_script tmpVal; @@ -1100,13 +1131,14 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& } // prunable - if (!sig.p.bulletproofs.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty()) + if (!sig.p.bulletproofs.empty() || !sig.p.bulletproofs_plus.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty()) { dest.Key("prunable"); dest.StartObject(); INSERT_INTO_JSON_OBJECT(dest, range_proofs, sig.p.rangeSigs); INSERT_INTO_JSON_OBJECT(dest, bulletproofs, sig.p.bulletproofs); + INSERT_INTO_JSON_OBJECT(dest, bulletproofs_plus, sig.p.bulletproofs_plus); INSERT_INTO_JSON_OBJECT(dest, mlsags, sig.p.MGs); INSERT_INTO_JSON_OBJECT(dest, pseudo_outs, sig.get_pseudo_outs()); @@ -1141,6 +1173,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig) GET_FROM_JSON_OBJECT(prunable->value, sig.p.rangeSigs, range_proofs); GET_FROM_JSON_OBJECT(prunable->value, sig.p.bulletproofs, bulletproofs); + GET_FROM_JSON_OBJECT(prunable->value, sig.p.bulletproofs_plus, bulletproofs_plus); GET_FROM_JSON_OBJECT(prunable->value, sig.p.MGs, mlsags); GET_FROM_JSON_OBJECT(prunable->value, pseudo_outs, pseudo_outs); @@ -1150,6 +1183,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig) { sig.p.rangeSigs.clear(); sig.p.bulletproofs.clear(); + sig.p.bulletproofs_plus.clear(); sig.p.MGs.clear(); sig.get_pseudo_outs().clear(); } @@ -1258,6 +1292,41 @@ void fromJsonValue(const rapidjson::Value& val, rct::Bulletproof& p) GET_FROM_JSON_OBJECT(val, p.t, t); } +void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::BulletproofPlus& p) +{ + dest.StartObject(); + + INSERT_INTO_JSON_OBJECT(dest, V, p.V); + INSERT_INTO_JSON_OBJECT(dest, A, p.A); + INSERT_INTO_JSON_OBJECT(dest, A1, p.A1); + INSERT_INTO_JSON_OBJECT(dest, B, p.B); + INSERT_INTO_JSON_OBJECT(dest, r1, p.r1); + INSERT_INTO_JSON_OBJECT(dest, s1, p.s1); + INSERT_INTO_JSON_OBJECT(dest, d1, p.d1); + INSERT_INTO_JSON_OBJECT(dest, L, p.L); + INSERT_INTO_JSON_OBJECT(dest, R, p.R); + + dest.EndObject(); +} + +void fromJsonValue(const rapidjson::Value& val, rct::BulletproofPlus& p) +{ + if (!val.IsObject()) + { + throw WRONG_TYPE("json object"); + } + + GET_FROM_JSON_OBJECT(val, p.V, V); + GET_FROM_JSON_OBJECT(val, p.A, A); + GET_FROM_JSON_OBJECT(val, p.A1, A1); + GET_FROM_JSON_OBJECT(val, p.B, B); + GET_FROM_JSON_OBJECT(val, p.r1, r1); + GET_FROM_JSON_OBJECT(val, p.s1, s1); + GET_FROM_JSON_OBJECT(val, p.d1, d1); + GET_FROM_JSON_OBJECT(val, p.L, L); + GET_FROM_JSON_OBJECT(val, p.R, R); +} + void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::boroSig& sig) { dest.StartObject(); diff --git a/src/serialization/json_object.h b/src/serialization/json_object.h index c858faf5a..968707165 100644 --- a/src/serialization/json_object.h +++ b/src/serialization/json_object.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // @@ -230,6 +230,9 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_scripthash& void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_key& txout); void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_key& txout); +void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_tagged_key& txout); +void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_tagged_key& txout); + void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_out& txout); void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_out& txout); @@ -292,6 +295,9 @@ void fromJsonValue(const rapidjson::Value& val, rct::rangeSig& sig); void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::Bulletproof& p); void fromJsonValue(const rapidjson::Value& val, rct::Bulletproof& p); +void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::BulletproofPlus& p); +void fromJsonValue(const rapidjson::Value& val, rct::BulletproofPlus& p); + void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::boroSig& sig); void fromJsonValue(const rapidjson::Value& val, rct::boroSig& sig); diff --git a/src/serialization/json_utils.h b/src/serialization/json_utils.h index 8115877dc..63f4bc043 100644 --- a/src/serialization/json_utils.h +++ b/src/serialization/json_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/list.h b/src/serialization/list.h index 411e7800d..16ee1b034 100644 --- a/src/serialization/list.h +++ b/src/serialization/list.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/pair.h b/src/serialization/pair.h index 2d9a89242..f18260dc8 100644 --- a/src/serialization/pair.h +++ b/src/serialization/pair.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index 4acadeab3..590b84428 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/string.h b/src/serialization/string.h index f1f8f4ab0..976924602 100644 --- a/src/serialization/string.h +++ b/src/serialization/string.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/serialization/variant.h b/src/serialization/variant.h index 6debb63d1..2b3c75ce5 100644 --- a/src/serialization/variant.h +++ b/src/serialization/variant.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/simplewallet/CMakeLists.txt b/src/simplewallet/CMakeLists.txt index a0820c8eb..b659d9f48 100644 --- a/src/simplewallet/CMakeLists.txt +++ b/src/simplewallet/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -31,8 +31,7 @@ set(simplewallet_sources set(simplewallet_headers) -set(simplewallet_private_headers - simplewallet.h) +monero_find_all_headers(simplewallet_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(simplewallet ${simplewallet_private_headers}) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 891253830..d3e40ab74 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -99,10 +99,6 @@ typedef cryptonote::simple_wallet sw; #define EXTENDED_LOGS_FILE "wallet_details.log" -#define DEFAULT_MIX 10 - -#define MIN_RING_SIZE 11 // Used to inform user about min ring size -- does not track actual protocol - #define OLD_AGE_WARN_THRESHOLD (30 * 86400 / DIFFICULTY_TARGET_V2) // 30 days #define LOCK_IDLE_SCOPE() \ @@ -1091,7 +1087,9 @@ bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, boo auto local_args = args; local_args.erase(local_args.begin()); std::string multisig_extra_info = m_wallet->make_multisig(orig_pwd_container->password(), local_args, threshold); - if (!multisig_extra_info.empty()) + bool ready; + m_wallet->multisig(&ready); + if (!ready) { success_msg_writer() << tr("Another step is needed"); success_msg_writer() << multisig_extra_info; @@ -1152,7 +1150,7 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> & return false; } - if (args.size() < 2) + if (args.size() < 1) { PRINT_USAGE(USAGE_EXCHANGE_MULTISIG_KEYS); return false; @@ -1161,7 +1159,9 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> & try { std::string multisig_extra_info = m_wallet->exchange_multisig_keys(orig_pwd_container->password(), args); - if (!multisig_extra_info.empty()) + bool ready; + m_wallet->multisig(&ready); + if (!ready) { message_writer() << tr("Another step is needed"); message_writer() << multisig_extra_info; @@ -2472,59 +2472,6 @@ bool simple_wallet::set_store_tx_info(const std::vector<std::string> &args/* = s return true; } -bool simple_wallet::set_default_ring_size(const std::vector<std::string> &args/* = std::vector<std::string>()*/) -{ - if (m_wallet->watch_only()) - { - fail_msg_writer() << tr("wallet is watch-only and cannot transfer"); - return true; - } - try - { - if (strchr(args[1].c_str(), '-')) - { - fail_msg_writer() << tr("ring size must be an integer >= ") << MIN_RING_SIZE; - return true; - } - uint32_t ring_size = boost::lexical_cast<uint32_t>(args[1]); - if (ring_size < MIN_RING_SIZE && ring_size != 0) - { - fail_msg_writer() << tr("ring size must be an integer >= ") << MIN_RING_SIZE; - return true; - } - - if (ring_size != 0 && ring_size != DEFAULT_MIX+1) - { - if (m_wallet->use_fork_rules(8, 0)) - { - message_writer() << tr("WARNING: from v8, ring size will be fixed and this setting will be ignored."); - } - else - { - message_writer() << tr("WARNING: this is a non default ring size, which may harm your privacy. Default is recommended."); - } - } - - const auto pwd_container = get_and_verify_password(); - if (pwd_container) - { - m_wallet->default_mixin(ring_size > 0 ? ring_size - 1 : 0); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); - } - return true; - } - catch(const boost::bad_lexical_cast &) - { - fail_msg_writer() << tr("ring size must be an integer >= ") << MIN_RING_SIZE; - return true; - } - catch(...) - { - fail_msg_writer() << tr("could not change default ring size"); - return true; - } -} - bool simple_wallet::set_default_priority(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { uint32_t priority = 0; @@ -2988,6 +2935,19 @@ bool simple_wallet::set_track_uses(const std::vector<std::string> &args/* = std: return true; } +bool simple_wallet::set_show_wallet_name_when_locked(const std::vector<std::string> &args/* = std::vector<std::string>()*/) +{ + const auto pwd_container = get_and_verify_password(); + if (pwd_container) + { + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->show_wallet_name_when_locked(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); + } + return true; +} + bool simple_wallet::set_inactivity_lock_timeout(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { #ifdef _WIN32 @@ -3373,8 +3333,6 @@ simple_wallet::simple_wallet() " Whether to print detailed information about ring members during confirmation.\n " "store-tx-info <1|0>\n " " Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference.\n " - "default-ring-size <n>\n " - " Set the default ring size (obsolete).\n " "auto-refresh <1|0>\n " " Whether to automatically synchronize new blocks from the daemon.\n " "refresh-type <full|optimize-coinbase|no-coinbase|default>\n " @@ -3431,6 +3389,8 @@ simple_wallet::simple_wallet() " Whether to automatically start mining for RPC payment if the daemon requires it.\n" "credits-target <unsigned int>\n" " The RPC payment credits balance to target (0 for default).\n " + "show-wallet-name-when-locked <1|0>\n " + " Set this if you would like to display the wallet name when locked.\n " "inactivity-lock-timeout <unsigned int>\n " " How many seconds to wait before locking the wallet (0 to disable).")); m_cmd_binder.set_handler("encrypted_seed", @@ -3491,7 +3451,7 @@ simple_wallet::simple_wallet() "** Set of address indices used as inputs in this transfer.")); m_cmd_binder.set_handler("export_transfers", boost::bind(&simple_wallet::on_command, this, &simple_wallet::export_transfers, _1), - tr("export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<filepath>]"), + tr("export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<filepath>] [option=<with_keys>]"), tr("Export to CSV the incoming/outgoing transfers within an optional height range.")); m_cmd_binder.set_handler("unspent_outputs", boost::bind(&simple_wallet::on_command, this, &simple_wallet::unspent_outputs, _1), @@ -3836,6 +3796,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) success_msg_writer() << "setup-background-mining = " << setup_background_mining_string; success_msg_writer() << "device-name = " << m_wallet->device_name(); success_msg_writer() << "export-format = " << (m_wallet->export_format() == tools::wallet2::ExportFormat::Ascii ? "ascii" : "binary"); + success_msg_writer() << "show-wallet-name-when-locked = " << m_wallet->show_wallet_name_when_locked(); success_msg_writer() << "inactivity-lock-timeout = " << m_wallet->inactivity_lock_timeout() #ifdef _WIN32 << " (disabled on Windows)" @@ -3880,7 +3841,6 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) CHECK_SIMPLE_VARIABLE("always-confirm-transfers", set_always_confirm_transfers, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("print-ring-members", set_print_ring_members, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("store-tx-info", set_store_tx_info, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("default-ring-size", set_default_ring_size, tr("integer >= ") << MIN_RING_SIZE); CHECK_SIMPLE_VARIABLE("auto-refresh", set_auto_refresh, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("refresh-type", set_refresh_type, tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)")); CHECK_SIMPLE_VARIABLE("priority", set_default_priority, tr("0, 1, 2, 3, or 4, or one of ") << join_priority_strings(", ")); @@ -3903,6 +3863,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) CHECK_SIMPLE_VARIABLE("ignore-outputs-above", set_ignore_outputs_above, tr("amount")); CHECK_SIMPLE_VARIABLE("ignore-outputs-below", set_ignore_outputs_below, tr("amount")); CHECK_SIMPLE_VARIABLE("track-uses", set_track_uses, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("show-wallet-name-when-locked", set_show_wallet_name_when_locked, tr("1 or 0")); CHECK_SIMPLE_VARIABLE("inactivity-lock-timeout", set_inactivity_lock_timeout, tr("unsigned integer (seconds, 0 to disable)")); CHECK_SIMPLE_VARIABLE("setup-background-mining", set_setup_background_mining, tr("1/yes or 0/no")); CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("<device_name[:device_spec]>")); @@ -6463,6 +6424,16 @@ void simple_wallet::check_for_inactivity_lock(bool user) { const char *inactivity_msg = user ? "" : tr("Locked due to inactivity."); tools::msg_writer() << inactivity_msg << (inactivity_msg[0] ? " " : "") << tr("The wallet password is required to unlock the console."); + + const bool show_wallet_name = m_wallet->show_wallet_name_when_locked(); + if (show_wallet_name) + { + tools::msg_writer() << tr("Filename: ") << m_wallet->get_wallet_file(); + tools::msg_writer() << tr("Network type: ") << ( + m_wallet->nettype() == cryptonote::TESTNET ? tr("Testnet") : + m_wallet->nettype() == cryptonote::STAGENET ? tr("Stagenet") : tr("Mainnet") + ); + } try { if (get_and_verify_password()) @@ -6512,7 +6483,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri priority = m_wallet->adjust_priority(priority); - size_t fake_outs_count = DEFAULT_MIX; + const size_t min_ring_size = m_wallet->get_min_ring_size(); + size_t fake_outs_count = min_ring_size - 1; if(local_args.size() > 0) { size_t ring_size; if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0])) @@ -6835,7 +6807,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri if (vin.type() == typeid(txin_to_key)) { const txin_to_key& in_to_key = boost::get<txin_to_key>(vin); - if (in_to_key.key_offsets.size() != DEFAULT_MIX + 1) + if (in_to_key.key_offsets.size() != min_ring_size) default_ring_size = false; } } @@ -7113,7 +7085,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co priority = m_wallet->adjust_priority(priority); - size_t fake_outs_count = DEFAULT_MIX; + size_t fake_outs_count = m_wallet->get_min_ring_size() - 1; if(local_args.size() > 0) { size_t ring_size; if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0])) @@ -7390,7 +7362,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_) priority = m_wallet->adjust_priority(priority); - size_t fake_outs_count = DEFAULT_MIX; + size_t fake_outs_count = m_wallet->get_min_ring_size() - 1; if(local_args.size() > 0) { size_t ring_size; if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0])) @@ -7994,6 +7966,15 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_) return true; } //---------------------------------------------------------------------------------------------------- +std::string get_tx_key_stream(crypto::secret_key tx_key, std::vector<crypto::secret_key> additional_tx_keys) +{ + ostringstream oss; + oss << epee::string_tools::pod_to_hex(tx_key); + for (size_t i = 0; i < additional_tx_keys.size(); ++i) + oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]); + return oss.str(); +} + bool simple_wallet::get_tx_key(const std::vector<std::string> &args_) { std::vector<std::string> local_args = args_; @@ -8023,11 +8004,8 @@ bool simple_wallet::get_tx_key(const std::vector<std::string> &args_) bool found_tx_key = m_wallet->get_tx_key(txid, tx_key, additional_tx_keys); if (found_tx_key) { - ostringstream oss; - oss << epee::string_tools::pod_to_hex(tx_key); - for (size_t i = 0; i < additional_tx_keys.size(); ++i) - oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]); - success_msg_writer() << tr("Tx key: ") << oss.str(); + std::string stream = get_tx_key_stream(tx_key, additional_tx_keys); + success_msg_writer() << tr("Tx key: ") << stream; return true; } else @@ -8838,13 +8816,11 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) { std::vector<std::string> local_args = args_; - if(local_args.size() > 5) { - fail_msg_writer() << tr("usage: export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<path>]"); + if(local_args.size() > 6) { + fail_msg_writer() << tr("usage: export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<path>] [option=<with_keys>]"); return true; } - LOCK_IDLE_SCOPE(); - std::vector<transfer_view> all_transfers; // might consumes arguments in local_args @@ -8858,17 +8834,36 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) filename = local_args[0].substr(7, -1); local_args.erase(local_args.begin()); } + // check for export with tx keys + bool export_keys = false; + if (local_args.size() > 0 && local_args[0].substr(0, 7) == "option=") + { + export_keys = local_args[0].substr(7, -1) == "with_keys"; + local_args.erase(local_args.begin()); + } + if (export_keys) + { + if (m_wallet->key_on_device() && m_wallet->get_account().get_device().get_type() != hw::device::TREZOR) + { + fail_msg_writer() << tr("command not supported by HW wallet"); + return true; + } + SCOPED_WALLET_UNLOCK(); + } else + { + LOCK_IDLE_SCOPE(); + } std::ofstream file(filename); // header file << - boost::format("%8.8s,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,%s,%s") % - tr("block") % tr("direction") % tr("unlocked") % tr("timestamp") % tr("amount") % tr("running balance") % tr("hash") % tr("payment ID") % tr("fee") % tr("destination") % tr("amount") % tr("index") % tr("note") + boost::format("%8.8s,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,%s,%s,%s") % + tr("block") % tr("direction") % tr("unlocked") % tr("timestamp") % tr("amount") % tr("running balance") % tr("hash") % tr("payment ID") % tr("fee") % tr("destination") % tr("amount") % tr("index") % tr("note") % tr("tx key") << std::endl; uint64_t running_balance = 0; - auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,\"%s\",%s"); + auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,\"%s\",%s,%s"); for (const auto& transfer : all_transfers) { @@ -8881,6 +8876,15 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) running_balance -= transfer.amount + transfer.fee; } + crypto::secret_key tx_key; + std::vector<crypto::secret_key> additional_tx_keys; + bool found_tx_key = m_wallet->get_tx_key(transfer.hash, tx_key, additional_tx_keys); + std::string key_string; + if (export_keys && found_tx_key) + { + key_string = get_tx_key_stream(tx_key, additional_tx_keys); + } + file << formatter % transfer.block % transfer.direction @@ -8895,6 +8899,7 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) % (transfer.outputs.size() ? print_money(transfer.outputs[0].second) : "") % boost::algorithm::join(transfer.index | boost::adaptors::transformed([](uint32_t i) { return std::to_string(i); }), ", ") % transfer.note + % key_string << std::endl; for (size_t i = 1; i < transfer.outputs.size(); ++i) @@ -8913,6 +8918,7 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) % print_money(transfer.outputs[i].second) % "" % "" + % "" << std::endl; } } @@ -9534,8 +9540,8 @@ void simple_wallet::print_accounts(const std::string& tag) total_balance += m_wallet->balance(account_index, false); total_unlocked_balance += m_wallet->unlocked_balance(account_index, false); } - success_msg_writer() << tr("----------------------------------------------------------------------------------"); - success_msg_writer() << boost::format(tr("%15s %21s %21s")) % "Total" % print_money(total_balance) % print_money(total_unlocked_balance); + success_msg_writer() << tr("------------------------------------------------------------------------------------"); + success_msg_writer() << boost::format(tr("%15s %21s %21s")) % "Total" % print_money(total_balance) % print_money(total_unlocked_balance); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::vector<std::string>()*/) @@ -9759,7 +9765,7 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg { if (info.has_payment_id) { - success_msg_writer() << boost::format(tr("Integrated address: %s, payment ID: %s")) % + success_msg_writer() << boost::format(tr("Standard address: %s, payment ID: %s")) % get_account_address_as_str(m_wallet->nettype(), false, info.address) % epee::string_tools::pod_to_hex(info.payment_id); device_show_integrated(info.payment_id); } diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 4bb2c6a71..4c005c53a 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -125,7 +125,6 @@ namespace cryptonote bool set_always_confirm_transfers(const std::vector<std::string> &args = std::vector<std::string>()); bool set_print_ring_members(const std::vector<std::string> &args = std::vector<std::string>()); bool set_store_tx_info(const std::vector<std::string> &args = std::vector<std::string>()); - bool set_default_ring_size(const std::vector<std::string> &args = std::vector<std::string>()); bool set_auto_refresh(const std::vector<std::string> &args = std::vector<std::string>()); bool set_refresh_type(const std::vector<std::string> &args = std::vector<std::string>()); bool set_confirm_missing_payment_id(const std::vector<std::string> &args = std::vector<std::string>()); @@ -148,6 +147,7 @@ namespace cryptonote bool set_ignore_outputs_above(const std::vector<std::string> &args = std::vector<std::string>()); bool set_ignore_outputs_below(const std::vector<std::string> &args = std::vector<std::string>()); bool set_track_uses(const std::vector<std::string> &args = std::vector<std::string>()); + bool set_show_wallet_name_when_locked(const std::vector<std::string> &args = std::vector<std::string>()); bool set_inactivity_lock_timeout(const std::vector<std::string> &args = std::vector<std::string>()); bool set_setup_background_mining(const std::vector<std::string> &args = std::vector<std::string>()); bool set_device_name(const std::vector<std::string> &args = std::vector<std::string>()); diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index 2dd64a38f..6095f99d5 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/wallet/api/CMakeLists.txt b/src/wallet/api/CMakeLists.txt index 655cdfefd..af7948d8a 100644 --- a/src/wallet/api/CMakeLists.txt +++ b/src/wallet/api/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp index 0b0e17464..c73653e37 100644 --- a/src/wallet/api/address_book.cpp +++ b/src/wallet/api/address_book.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/address_book.h b/src/wallet/api/address_book.h index 40da46853..5b0655000 100644 --- a/src/wallet/api/address_book.h +++ b/src/wallet/api/address_book.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp index f7e74591f..70a702796 100644 --- a/src/wallet/api/pending_transaction.cpp +++ b/src/wallet/api/pending_transaction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h index 274c60851..0a9779c07 100644 --- a/src/wallet/api/pending_transaction.h +++ b/src/wallet/api/pending_transaction.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/subaddress.cpp b/src/wallet/api/subaddress.cpp index 227bb343d..9e358b4c8 100644 --- a/src/wallet/api/subaddress.cpp +++ b/src/wallet/api/subaddress.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/subaddress.h b/src/wallet/api/subaddress.h index 18c9ed59e..53ece126d 100644 --- a/src/wallet/api/subaddress.h +++ b/src/wallet/api/subaddress.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/subaddress_account.cpp b/src/wallet/api/subaddress_account.cpp index 5e502ed5b..e8153df3d 100644 --- a/src/wallet/api/subaddress_account.cpp +++ b/src/wallet/api/subaddress_account.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/subaddress_account.h b/src/wallet/api/subaddress_account.h index 1318d4da5..94cab47fb 100644 --- a/src/wallet/api/subaddress_account.h +++ b/src/wallet/api/subaddress_account.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index 4649089ea..9f5e41156 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h index fe77253e6..1d52f4a69 100644 --- a/src/wallet/api/transaction_history.h +++ b/src/wallet/api/transaction_history.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/transaction_info.cpp b/src/wallet/api/transaction_info.cpp index edbdc469a..572b04316 100644 --- a/src/wallet/api/transaction_info.cpp +++ b/src/wallet/api/transaction_info.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h index 5eeeb04c2..6337f2aaa 100644 --- a/src/wallet/api/transaction_info.h +++ b/src/wallet/api/transaction_info.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp index 4ccfafebd..6165a2240 100644 --- a/src/wallet/api/unsigned_transaction.cpp +++ b/src/wallet/api/unsigned_transaction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/unsigned_transaction.h b/src/wallet/api/unsigned_transaction.h index 07649e39e..30065a7fa 100644 --- a/src/wallet/api/unsigned_transaction.h +++ b/src/wallet/api/unsigned_transaction.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/utils.cpp b/src/wallet/api/utils.cpp index 19151b5f6..d8dcedc5f 100644 --- a/src/wallet/api/utils.cpp +++ b/src/wallet/api/utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index b058619a3..7cd8656e1 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -1742,8 +1742,9 @@ uint64_t WalletImpl::estimateTransactionFee(const std::vector<std::pair<std::str extra_size, m_wallet->use_fork_rules(8, 0), m_wallet->use_fork_rules(HF_VERSION_CLSAG, 0), + m_wallet->use_fork_rules(HF_VERSION_BULLETPROOF_PLUS, 0), + m_wallet->use_fork_rules(HF_VERSION_VIEW_TAGS, 0), m_wallet->get_base_fee(), - m_wallet->get_fee_multiplier(m_wallet->adjust_priority(static_cast<uint32_t>(priority))), m_wallet->get_fee_quantization_mask()); } diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 7e1e62081..0e61ee330 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index 6da547054..c6f81f0e4 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -423,7 +423,6 @@ struct WalletListener /** * @brief Interface for wallet operations. - * TODO: check if /include/IWallet.h is still actual */ struct Wallet { diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index f5d5e2168..e81b8f83a 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 1e8cff877..a223e1df9 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/message_store.cpp b/src/wallet/message_store.cpp index 34b4f440b..cf1d91d5a 100644 --- a/src/wallet/message_store.cpp +++ b/src/wallet/message_store.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/wallet/message_store.h b/src/wallet/message_store.h index 0f53587d4..c5421a702 100644 --- a/src/wallet/message_store.h +++ b/src/wallet/message_store.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/wallet/message_transporter.cpp b/src/wallet/message_transporter.cpp index 4dd4b8f01..c985eb583 100644 --- a/src/wallet/message_transporter.cpp +++ b/src/wallet/message_transporter.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/wallet/message_transporter.h b/src/wallet/message_transporter.h index 557833f2c..b7d3c8107 100644 --- a/src/wallet/message_transporter.h +++ b/src/wallet/message_transporter.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp index 148f957eb..7810abdd2 100644 --- a/src/wallet/node_rpc_proxy.cpp +++ b/src/wallet/node_rpc_proxy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -70,6 +70,7 @@ void NodeRPCProxy::invalidate() m_dynamic_base_fee_estimate = 0; m_dynamic_base_fee_estimate_cached_height = 0; m_dynamic_base_fee_estimate_grace_blocks = 0; + m_dynamic_base_fee_estimate_vector.clear(); m_fee_quantization_mask = 1; m_rpc_version = 0; m_target_height = 0; @@ -210,7 +211,7 @@ boost::optional<std::string> NodeRPCProxy::get_earliest_height(uint8_t version, return boost::optional<std::string>(); } -boost::optional<std::string> NodeRPCProxy::get_dynamic_base_fee_estimate(uint64_t grace_blocks, uint64_t &fee) +boost::optional<std::string> NodeRPCProxy::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, std::vector<uint64_t> &fees) { uint64_t height; @@ -238,13 +239,24 @@ boost::optional<std::string> NodeRPCProxy::get_dynamic_base_fee_estimate(uint64_ m_dynamic_base_fee_estimate = resp_t.fee; m_dynamic_base_fee_estimate_cached_height = height; m_dynamic_base_fee_estimate_grace_blocks = grace_blocks; + m_dynamic_base_fee_estimate_vector = !resp_t.fees.empty() ? std::move(resp_t.fees) : std::vector<uint64_t>{m_dynamic_base_fee_estimate}; m_fee_quantization_mask = resp_t.quantization_mask; } - fee = m_dynamic_base_fee_estimate; + fees = m_dynamic_base_fee_estimate_vector; return boost::optional<std::string>(); } +boost::optional<std::string> NodeRPCProxy::get_dynamic_base_fee_estimate(uint64_t grace_blocks, uint64_t &fee) +{ + std::vector<uint64_t> fees; + auto res = get_dynamic_base_fee_estimate_2021_scaling(grace_blocks, fees); + if (res) + return res; + fee = fees[0]; + return boost::none; +} + boost::optional<std::string> NodeRPCProxy::get_fee_quantization_mask(uint64_t &fee_quantization_mask) { uint64_t height; diff --git a/src/wallet/node_rpc_proxy.h b/src/wallet/node_rpc_proxy.h index f5e3fca5f..07675cdb0 100644 --- a/src/wallet/node_rpc_proxy.h +++ b/src/wallet/node_rpc_proxy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -56,6 +56,7 @@ public: boost::optional<std::string> get_adjusted_time(uint64_t &adjusted_time); boost::optional<std::string> get_earliest_height(uint8_t version, uint64_t &earliest_height); boost::optional<std::string> get_dynamic_base_fee_estimate(uint64_t grace_blocks, uint64_t &fee); + boost::optional<std::string> get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, std::vector<uint64_t> &fees); boost::optional<std::string> get_fee_quantization_mask(uint64_t &fee_quantization_mask); boost::optional<std::string> get_rpc_payment_info(bool mining, bool &payment_required, uint64_t &credits, uint64_t &diff, uint64_t &credits_per_hash_found, cryptonote::blobdata &blob, uint64_t &height, uint64_t &seed_height, crypto::hash &seed_hash, crypto::hash &next_seed_hash, uint32_t &cookie); @@ -85,6 +86,7 @@ private: uint64_t m_dynamic_base_fee_estimate; uint64_t m_dynamic_base_fee_estimate_cached_height; uint64_t m_dynamic_base_fee_estimate_grace_blocks; + std::vector<uint64_t> m_dynamic_base_fee_estimate_vector; uint64_t m_fee_quantization_mask; uint64_t m_adjusted_time; uint32_t m_rpc_version; diff --git a/src/wallet/ringdb.cpp b/src/wallet/ringdb.cpp index 025a2037f..bfbbbaeb7 100644 --- a/src/wallet/ringdb.cpp +++ b/src/wallet/ringdb.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/wallet/ringdb.h b/src/wallet/ringdb.h index 9c7e624bc..e9941bf94 100644 --- a/src/wallet/ringdb.h +++ b/src/wallet/ringdb.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 9e95a26c1..9be36bc26 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -290,15 +290,15 @@ void do_prepare_file_names(const std::string& file_path, std::string& keys_file, mms_file = file_path + ".mms"; } -uint64_t calculate_fee(uint64_t fee_per_kb, size_t bytes, uint64_t fee_multiplier) +uint64_t calculate_fee(uint64_t fee_per_kb, size_t bytes) { uint64_t kB = (bytes + 1023) / 1024; - return kB * fee_per_kb * fee_multiplier; + return kB * fee_per_kb; } -uint64_t calculate_fee_from_weight(uint64_t base_fee, uint64_t weight, uint64_t fee_multiplier, uint64_t fee_quantization_mask) +uint64_t calculate_fee_from_weight(uint64_t base_fee, uint64_t weight, uint64_t fee_quantization_mask) { - uint64_t fee = weight * base_fee * fee_multiplier; + uint64_t fee = weight * base_fee; fee = (fee + fee_quantization_mask - 1) / fee_quantization_mask * fee_quantization_mask; return fee; } @@ -781,7 +781,7 @@ void drop_from_short_history(std::list<crypto::hash> &short_chain_history, size_ } } -size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag) +size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags) { size_t size = 0; @@ -805,12 +805,12 @@ size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra size += 1; // rangeSigs - if (bulletproof) + if (bulletproof || bulletproof_plus) { size_t log_padded_outputs = 0; while ((1<<log_padded_outputs) < n_outputs) ++log_padded_outputs; - size += (2 * (6 + log_padded_outputs) + 4 + 5) * 32 + 3; + size += (2 * (6 + log_padded_outputs) + (bulletproof_plus ? 6 : (4 + 5))) * 32 + 3; } else size += (2*64*32+32+64*32) * n_outputs; @@ -821,6 +821,9 @@ size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra else size += n_inputs * (64 * (mixin+1) + 32); + if (use_view_tags) + size += n_outputs * sizeof(crypto::view_tag); + // mixRing - not serialized, can be reconstructed /* size += 2 * 32 * (mixin+1) * n_inputs; */ @@ -833,29 +836,29 @@ size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra // txnFee size += 4; - LOG_PRINT_L2("estimated " << (bulletproof ? "bulletproof" : "borromean") << " rct tx size for " << n_inputs << " inputs with ring size " << (mixin+1) << " and " << n_outputs << " outputs: " << size << " (" << ((32 * n_inputs/*+1*/) + 2 * 32 * (mixin+1) * n_inputs + 32 * n_outputs) << " saved)"); + LOG_PRINT_L2("estimated " << (bulletproof_plus ? "bulletproof plus" : bulletproof ? "bulletproof" : "borromean") << " rct tx size for " << n_inputs << " inputs with ring size " << (mixin+1) << " and " << n_outputs << " outputs: " << size << " (" << ((32 * n_inputs/*+1*/) + 2 * 32 * (mixin+1) * n_inputs + 32 * n_outputs) << " saved)"); return size; } -size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag) +size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags) { if (use_rct) - return estimate_rct_tx_size(n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag); + return estimate_rct_tx_size(n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags); else - return n_inputs * (mixin+1) * APPROXIMATE_INPUT_BYTES + extra_size; + return n_inputs * (mixin+1) * APPROXIMATE_INPUT_BYTES + extra_size + (use_view_tags ? (n_outputs * sizeof(crypto::view_tag)) : 0); } -uint64_t estimate_tx_weight(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag) +uint64_t estimate_tx_weight(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags) { - size_t size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag); - if (use_rct && bulletproof && n_outputs > 2) + size_t size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags); + if (use_rct && (bulletproof || bulletproof_plus) && n_outputs > 2) { - const uint64_t bp_base = 368; + const uint64_t bp_base = (32 * ((bulletproof_plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2) size_t log_padded_outputs = 2; while ((1<<log_padded_outputs) < n_outputs) ++log_padded_outputs; uint64_t nlr = 2 * (6 + log_padded_outputs); - const uint64_t bp_size = 32 * (9 + nlr); + const uint64_t bp_size = 32 * ((bulletproof_plus ? 6 : 9) + nlr); const uint64_t bp_clawback = (bp_base * (1<<log_padded_outputs) - bp_size) * 4 / 5; MDEBUG("clawback on size " << size << ": " << bp_clawback); size += bp_clawback; @@ -868,17 +871,27 @@ uint8_t get_bulletproof_fork() return 8; } +uint8_t get_bulletproof_plus_fork() +{ + return HF_VERSION_BULLETPROOF_PLUS; +} + uint8_t get_clsag_fork() { return HF_VERSION_CLSAG; } -uint64_t calculate_fee(bool use_per_byte_fee, const cryptonote::transaction &tx, size_t blob_size, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask) +uint8_t get_view_tag_fork() +{ + return HF_VERSION_VIEW_TAGS; +} + +uint64_t calculate_fee(bool use_per_byte_fee, const cryptonote::transaction &tx, size_t blob_size, uint64_t base_fee, uint64_t fee_quantization_mask) { if (use_per_byte_fee) - return calculate_fee_from_weight(base_fee, cryptonote::get_transaction_weight(tx, blob_size), fee_multiplier, fee_quantization_mask); + return calculate_fee_from_weight(base_fee, cryptonote::get_transaction_weight(tx, blob_size), fee_quantization_mask); else - return calculate_fee(base_fee, blob_size, fee_multiplier); + return calculate_fee(base_fee, blob_size); } bool get_short_payment_id(crypto::hash8 &payment_id8, const tools::wallet2::pending_tx &ptx, hw::device &hwdev) @@ -1168,6 +1181,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std m_ignore_outputs_above(MONEY_SUPPLY), m_ignore_outputs_below(0), m_track_uses(false), + m_show_wallet_name_when_locked(false), m_inactivity_lock_timeout(DEFAULT_INACTIVITY_LOCK_TIMEOUT), m_setup_background_mining(BackgroundMiningMaybe), m_persistent_rpc_client_id(false), @@ -1759,13 +1773,14 @@ void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivatio hw::device &hwdev = m_account.get_device(); boost::unique_lock<hw::device> hwdev_lock (hwdev); hwdev.set_mode(hw::device::TRANSACTION_PARSE); - if (o.target.type() != typeid(txout_to_key)) + crypto::public_key output_public_key; + if (!get_output_public_key(o, output_public_key)) { tx_scan_info.error = true; LOG_ERROR("wrong type id in transaction out"); return; } - tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get<txout_to_key>(o.target).key, derivation, additional_derivations, i, hwdev); + tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, output_public_key, derivation, additional_derivations, i, hwdev, get_output_view_tag(o)); if(tx_scan_info.received) { tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs @@ -1816,6 +1831,7 @@ static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation & case rct::RCTTypeBulletproof: case rct::RCTTypeBulletproof2: case rct::RCTTypeCLSAG: + case rct::RCTTypeBulletproofPlus: return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask, hwdev); case rct::RCTTypeFull: return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask, hwdev); @@ -1849,17 +1865,20 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons } } + crypto::public_key output_public_key; + THROW_WALLET_EXCEPTION_IF(!get_output_public_key(tx.vout[i], output_public_key), error::wallet_internal_error, "Failed to get output public key"); + if (m_multisig) { - tx_scan_info.in_ephemeral.pub = boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key; + tx_scan_info.in_ephemeral.pub = output_public_key; tx_scan_info.in_ephemeral.sec = crypto::null_skey; tx_scan_info.ki = rct::rct2ki(rct::zero()); } else { - bool r = cryptonote::generate_key_image_helper_precomp(m_account.get_keys(), boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key, tx_scan_info.received->derivation, i, tx_scan_info.received->index, tx_scan_info.in_ephemeral, tx_scan_info.ki, m_account.get_device()); + bool r = cryptonote::generate_key_image_helper_precomp(m_account.get_keys(), output_public_key, tx_scan_info.received->derivation, i, tx_scan_info.received->index, tx_scan_info.in_ephemeral, tx_scan_info.ki, m_account.get_device()); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image"); - THROW_WALLET_EXCEPTION_IF(tx_scan_info.in_ephemeral.pub != boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key, + THROW_WALLET_EXCEPTION_IF(tx_scan_info.in_ephemeral.pub != output_public_key, error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key"); } @@ -1986,8 +2005,6 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote int num_vouts_received = 0; tx_pub_key = pub_key_field.pub_key; - tools::threadpool& tpool = tools::threadpool::getInstance(); - tools::threadpool::waiter waiter(tpool); const cryptonote::account_keys& keys = m_account.get_keys(); crypto::key_derivation derivation; @@ -2057,10 +2074,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote // the first one was already checked for (size_t i = 1; i < tx.vout.size(); ++i) { - tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i, - std::cref(is_out_data_ptr), std::ref(tx_scan_info[i]), std::ref(output_found[i])), true); + check_acc_out_precomp_once(tx.vout[i], derivation, additional_derivations, i, is_out_data_ptr, tx_scan_info[i], output_found[i]); } - THROW_WALLET_EXCEPTION_IF(!waiter.wait(), error::wallet_internal_error, "Exception in thread pool"); // then scan all outputs from 0 hw::device &hwdev = m_account.get_device(); boost::unique_lock<hw::device> hwdev_lock (hwdev); @@ -2080,32 +2095,6 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote } } } - else if (tx.vout.size() > 1 && tools::threadpool::getInstance().get_max_concurrency() > 1 && !is_out_data_ptr) - { - for (size_t i = 0; i < tx.vout.size(); ++i) - { - tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i, - std::cref(is_out_data_ptr), std::ref(tx_scan_info[i]), std::ref(output_found[i])), true); - } - THROW_WALLET_EXCEPTION_IF(!waiter.wait(), error::wallet_internal_error, "Exception in thread pool"); - - hw::device &hwdev = m_account.get_device(); - boost::unique_lock<hw::device> hwdev_lock (hwdev); - hwdev.set_mode(hw::device::NONE); - for (size_t i = 0; i < tx.vout.size(); ++i) - { - THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); - if (tx_scan_info[i].received) - { - hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations); - scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool); - if (!tx_scan_info[i].error) - { - tx_amounts_individual_outs[tx_scan_info[i].received->index].push_back(tx_scan_info[i].money_transfered); - } - } - } - } else { for (size_t i = 0; i < tx.vout.size(); ++i) @@ -2786,25 +2775,34 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry for (size_t k = 0; k < n_vouts; ++k) { const auto &o = tx.vout[k]; - if (o.target.type() == typeid(cryptonote::txout_to_key)) + crypto::public_key output_public_key; + if (get_output_public_key(o, output_public_key)) { std::vector<crypto::key_derivation> additional_derivations; additional_derivations.reserve(tx_cache_data[txidx].additional.size()); for (const auto &iod: tx_cache_data[txidx].additional) additional_derivations.push_back(iod.derivation); - const auto &key = boost::get<txout_to_key>(o.target).key; for (size_t l = 0; l < tx_cache_data[txidx].primary.size(); ++l) { THROW_WALLET_EXCEPTION_IF(tx_cache_data[txidx].primary[l].received.size() != n_vouts, error::wallet_internal_error, "Unexpected received array size"); - tx_cache_data[txidx].primary[l].received[k] = is_out_to_acc_precomp(m_subaddresses, key, tx_cache_data[txidx].primary[l].derivation, additional_derivations, k, hwdev); + tx_cache_data[txidx].primary[l].received[k] = is_out_to_acc_precomp(m_subaddresses, output_public_key, tx_cache_data[txidx].primary[l].derivation, additional_derivations, k, hwdev, get_output_view_tag(o)); additional_derivations.clear(); } } } }; + struct geniod_params + { + const cryptonote::transaction &tx; + size_t n_outs; + size_t txidx; + }; + std::vector<geniod_params> geniods; + geniods.reserve(num_txes); txidx = 0; + uint8_t hf_version_view_tags = get_view_tag_fork(); for (size_t i = 0; i < blocks.size(); ++i) { if (should_skip_block(parsed_blocks[i].block, start_height + i)) @@ -2818,18 +2816,51 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry THROW_WALLET_EXCEPTION_IF(txidx >= tx_cache_data.size(), error::wallet_internal_error, "txidx out of range"); const cryptonote::transaction& tx = parsed_blocks[i].block.miner_tx; const size_t n_vouts = (m_refresh_type == RefreshType::RefreshOptimizeCoinbase && tx.version < 2) ? 1 : tx.vout.size(); - tpool.submit(&waiter, [&, n_vouts, txidx](){ geniod(tx, n_vouts, txidx); }, true); + if (parsed_blocks[i].block.major_version >= hf_version_view_tags) + geniods.push_back(geniod_params{ tx, n_vouts, txidx }); + else + tpool.submit(&waiter, [&, n_vouts, txidx](){ geniod(tx, n_vouts, txidx); }, true); } ++txidx; for (size_t j = 0; j < parsed_blocks[i].txes.size(); ++j) { THROW_WALLET_EXCEPTION_IF(txidx >= tx_cache_data.size(), error::wallet_internal_error, "txidx out of range"); - tpool.submit(&waiter, [&, i, j, txidx](){ geniod(parsed_blocks[i].txes[j], parsed_blocks[i].txes[j].vout.size(), txidx); }, true); + if (parsed_blocks[i].block.major_version >= hf_version_view_tags) + geniods.push_back(geniod_params{ parsed_blocks[i].txes[j], parsed_blocks[i].txes[j].vout.size(), txidx }); + else + tpool.submit(&waiter, [&, i, j, txidx](){ geniod(parsed_blocks[i].txes[j], parsed_blocks[i].txes[j].vout.size(), txidx); }, true); ++txidx; } } THROW_WALLET_EXCEPTION_IF(txidx != tx_cache_data.size(), error::wallet_internal_error, "txidx did not reach expected value"); + + // View tags significantly speed up the geniod function that determines if an output belongs to the account. + // Because the speedup is so large, the overhead from submitting individual geniods to the thread pool eats into + // the benefit of executing in parallel. So to maximize the benefit from threads when view tags are enabled, + // the wallet starts submitting geniod function calls to the thread pool in batches of size GENIOD_BATCH_SIZE. + if (geniods.size()) + { + size_t GENIOD_BATCH_SIZE = 100; + size_t num_batch_txes = 0; + size_t batch_start = 0; + while (batch_start < geniods.size()) + { + size_t batch_end = std::min(batch_start + GENIOD_BATCH_SIZE, geniods.size()); + THROW_WALLET_EXCEPTION_IF(batch_end < batch_start, error::wallet_internal_error, "Thread batch end overflow"); + tpool.submit(&waiter, [&geniods, &geniod, batch_start, batch_end]() { + for (size_t i = batch_start; i < batch_end; ++i) + { + const geniod_params &gp = geniods[i]; + geniod(gp.tx, gp.n_outs, gp.txidx); + } + }, true); + num_batch_txes += batch_end - batch_start; + batch_start = batch_end; + } + THROW_WALLET_EXCEPTION_IF(num_batch_txes != geniods.size(), error::wallet_internal_error, "txes batched for thread pool did not reach expected value"); + } THROW_WALLET_EXCEPTION_IF(!waiter.wait(), error::wallet_internal_error, "Exception in thread pool"); + hwdev.set_mode(hw::device::NONE); size_t tx_cache_data_offset = 0; @@ -3966,6 +3997,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee: value2.SetInt(m_track_uses ? 1 : 0); json.AddMember("track_uses", value2, json.GetAllocator()); + value2.SetInt(m_show_wallet_name_when_locked ? 1 : 0); + json.AddMember("show_wallet_name_when_locked", value2, json.GetAllocator()); + value2.SetInt(m_inactivity_lock_timeout); json.AddMember("inactivity_lock_timeout", value2, json.GetAllocator()); @@ -4150,6 +4184,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_ignore_outputs_above = MONEY_SUPPLY; m_ignore_outputs_below = 0; m_track_uses = false; + m_show_wallet_name_when_locked = false; m_inactivity_lock_timeout = DEFAULT_INACTIVITY_LOCK_TIMEOUT; m_setup_background_mining = BackgroundMiningMaybe; m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR; @@ -4324,6 +4359,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_ignore_outputs_below = field_ignore_outputs_below; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, track_uses, int, Int, false, false); m_track_uses = field_track_uses; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, show_wallet_name_when_locked, int, Int, false, false); + m_show_wallet_name_when_locked = field_show_wallet_name_when_locked; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, inactivity_lock_timeout, uint32_t, Uint, false, DEFAULT_INACTIVITY_LOCK_TIMEOUT); m_inactivity_lock_timeout = field_inactivity_lock_timeout; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, setup_background_mining, BackgroundMiningSetupType, Int, false, BackgroundMiningMaybe); @@ -5088,7 +5125,7 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor // reconstruct multisig account crypto::public_key dummy; - multisig::multisig_account::kex_origins_map_t kex_origins_map; + multisig::multisig_keyset_map_memsafe_t kex_origins_map; for (const auto &derivation : m_multisig_derivations) kex_origins_map[derivation]; @@ -5101,7 +5138,7 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor get_account().get_keys().m_multisig_keys, get_account().get_keys().m_view_secret_key, m_account_public_address.m_spend_public_key, - dummy, //common pubkey: not used + m_account_public_address.m_view_public_key, m_multisig_rounds_passed, std::move(kex_origins_map), "" @@ -5188,7 +5225,10 @@ bool wallet2::multisig(bool *ready, uint32_t *threshold, uint32_t *total) const if (total) *total = m_multisig_signers.size(); if (ready) - *ready = !(get_account().get_keys().m_account_address.m_spend_public_key == rct::rct2pk(rct::identity())); + { + *ready = !(get_account().get_keys().m_account_address.m_spend_public_key == rct::rct2pk(rct::identity())) && + (m_multisig_rounds_passed == multisig::multisig_kex_rounds_required(m_multisig_signers.size(), m_multisig_threshold) + 1); + } return true; } //---------------------------------------------------------------------------------------------------- @@ -6442,7 +6482,7 @@ std::string wallet2::dump_tx_to_str(const std::vector<pending_tx> &ptx_vector) c txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(tx, m_account.get_device())); } - txs.transfers = export_outputs(); + txs.new_transfers = export_outputs(); // save as binary std::ostringstream oss; binary_archive<true> ar(oss); @@ -6583,7 +6623,10 @@ bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &s //---------------------------------------------------------------------------------------------------- bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pending_tx> &txs, signed_tx_set &signed_txes) { - import_outputs(exported_txs.transfers); + if (!exported_txs.new_transfers.second.empty()) + import_outputs(exported_txs.new_transfers); + else + import_outputs(exported_txs.transfers); // sign the transactions for (size_t n = 0; n < exported_txs.txes.size(); ++n) @@ -6597,7 +6640,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin crypto::secret_key tx_key; std::vector<crypto::secret_key> additional_tx_keys; rct::multisig_out msout; - bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, rct_config, m_multisig ? &msout : NULL); + bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, rct_config, m_multisig ? &msout : NULL, sd.use_view_tags); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype); // we don't test tx size, because we don't know the current limit, due to not having a blockchain, // and it's a bit pointless to fail there anyway, since it'd be a (good) guess only. We sign anyway, @@ -6682,16 +6725,17 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin for (size_t i = 0; i < tx.vout.size(); ++i) { - if (tx.vout[i].target.type() != typeid(cryptonote::txout_to_key)) + crypto::public_key output_public_key; + if (!get_output_public_key(tx.vout[i], output_public_key)) continue; - const cryptonote::txout_to_key &out = boost::get<cryptonote::txout_to_key>(tx.vout[i].target); + // if this output is back to this wallet, we can calculate its key image already - if (!is_out_to_acc_precomp(m_subaddresses, out.key, derivation, additional_derivations, i, hwdev)) + if (!is_out_to_acc_precomp(m_subaddresses, output_public_key, derivation, additional_derivations, i, hwdev, get_output_view_tag(tx.vout[i]))) continue; crypto::key_image ki; cryptonote::keypair in_ephemeral; - if (generate_key_image_helper(keys, m_subaddresses, out.key, tx_pub_key, additional_tx_pub_keys, i, in_ephemeral, ki, hwdev)) - signed_txes.tx_key_images[out.key] = ki; + if (generate_key_image_helper(keys, m_subaddresses, output_public_key, tx_pub_key, additional_tx_pub_keys, i, in_ephemeral, ki, hwdev)) + signed_txes.tx_key_images[output_public_key] = ki; else MERROR("Failed to calculate key image"); } @@ -7116,7 +7160,8 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto rct::multisig_out msout = ptx.multisig_sigs.front().msout; auto sources = sd.sources; rct::RCTConfig rct_config = sd.rct_config; - bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, rct_config, &msout, false); + bool shuffle_outs = false; + bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, rct_config, &msout, shuffle_outs, sd.use_view_tags); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(get_transaction_prefix_hash (tx) != get_transaction_prefix_hash(ptx.tx), @@ -7216,17 +7261,17 @@ bool wallet2::sign_multisig_tx_from_file(const std::string &filename, std::vecto return sign_multisig_tx_to_file(exported_txs, filename, txids); } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask) const +uint64_t wallet2::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask) const { if (use_per_byte_fee) { - const size_t estimated_tx_weight = estimate_tx_weight(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag); - return calculate_fee_from_weight(base_fee, estimated_tx_weight, fee_multiplier, fee_quantization_mask); + const size_t estimated_tx_weight = estimate_tx_weight(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags); + return calculate_fee_from_weight(base_fee, estimated_tx_weight, fee_quantization_mask); } else { - const size_t estimated_tx_size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag); - return calculate_fee(base_fee, estimated_tx_size, fee_multiplier); + const size_t estimated_tx_size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags); + return calculate_fee(base_fee, estimated_tx_size); } } @@ -7299,6 +7344,40 @@ uint64_t wallet2::get_base_fee() return get_dynamic_base_fee_estimate(); } //---------------------------------------------------------------------------------------------------- +uint64_t wallet2::get_base_fee(uint32_t priority) +{ + const bool use_2021_scaling = use_fork_rules(HF_VERSION_2021_SCALING, -30 * 1); + if (use_2021_scaling) + { + // clamp and map to 0..3 indices, mapping 0 (default, but should not end up here) to 0, and 1..4 to 0..3 + if (priority == 0) + priority = 1; + else if (priority > 4) + priority = 4; + --priority; + + std::vector<uint64_t> fees; + boost::optional<std::string> result = m_node_rpc_proxy.get_dynamic_base_fee_estimate_2021_scaling(FEE_ESTIMATE_GRACE_BLOCKS, fees); + if (result) + { + MERROR("Failed to determine base fee, using default"); + return FEE_PER_BYTE; + } + if (priority >= fees.size()) + { + MERROR("Failed to determine base fee for priority " << priority << ", using default"); + return FEE_PER_BYTE; + } + return fees[priority]; + } + else + { + const uint64_t base_fee = get_base_fee(); + const uint64_t fee_multiplier = get_fee_multiplier(priority); + return base_fee * fee_multiplier; + } +} +//---------------------------------------------------------------------------------------------------- uint64_t wallet2::get_fee_quantization_mask() { if(m_light_wallet) @@ -7330,6 +7409,8 @@ int wallet2::get_fee_algorithm() //------------------------------------------------------------------------------------------------------------------------------ uint64_t wallet2::get_min_ring_size() { + if (use_fork_rules(HF_VERSION_MIN_MIXIN_15, 0)) + return 16; if (use_fork_rules(8, 10)) return 11; if (use_fork_rules(7, 10)) @@ -7343,6 +7424,8 @@ uint64_t wallet2::get_min_ring_size() //------------------------------------------------------------------------------------------------------------------------------ uint64_t wallet2::get_max_ring_size() { + if (use_fork_rules(HF_VERSION_MIN_MIXIN_15, 0)) + return 16; if (use_fork_rules(8, 10)) return 11; return 0; @@ -7373,9 +7456,8 @@ uint32_t wallet2::adjust_priority(uint32_t priority) { // check if there's a backlog in the tx pool const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0); - const uint64_t base_fee = get_base_fee(); - const uint64_t fee_multiplier = get_fee_multiplier(1); - const double fee_level = fee_multiplier * base_fee * (use_per_byte_fee ? 1 : (12/(double)13 / (double)1024)); + const uint64_t base_fee = get_base_fee(1); + const double fee_level = base_fee * (use_per_byte_fee ? 1 : (12/(double)13 / (double)1024)); const std::vector<std::pair<uint64_t, uint64_t>> blocks = estimate_backlog({std::make_pair(fee_level, fee_level)}); if (blocks.size() != 1) { @@ -8412,7 +8494,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> { size_t i = base + n; if (req.outputs[i].index == td.m_global_output_index) - if (daemon_resp.outs[i].key == boost::get<txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key) + if (daemon_resp.outs[i].key == td.get_public_key()) if (daemon_resp.outs[i].mask == mask) if (daemon_resp.outs[i].unlocked) real_out_found = true; @@ -8421,7 +8503,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> "Daemon response did not include the requested real output"); // pick real out first (it will be sorted when done) - outs.back().push_back(std::make_tuple(td.m_global_output_index, boost::get<txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key, mask)); + outs.back().push_back(std::make_tuple(td.m_global_output_index, td.get_public_key(), mask)); // then pick outs from an existing ring, if any if (td.m_key_image_known && !td.m_key_image_partial) @@ -8512,7 +8594,8 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> template<typename T> void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_entry>& dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count, std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, - uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx) + uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx, + bool use_view_tags) { using namespace cryptonote; // throw if attempting a transaction with no destinations @@ -8585,7 +8668,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent tx_output_entry real_oe; real_oe.first = td.m_global_output_index; - real_oe.second.dest = rct::pk2rct(boost::get<txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key); + real_oe.second.dest = rct::pk2rct(td.get_public_key()); real_oe.second.mask = rct::commit(td.amount(), td.m_mask); *it_to_replace = real_oe; src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_tx, td.m_pk_index); @@ -8623,7 +8706,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent std::vector<crypto::secret_key> additional_tx_keys; rct::multisig_out msout; LOG_PRINT_L2("constructing tx"); - bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, {}, m_multisig ? &msout : NULL); + bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, {}, m_multisig ? &msout : NULL, use_view_tags); LOG_PRINT_L2("constructed tx, r="<<r); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(upper_transaction_weight_limit <= get_transaction_weight(tx), error::tx_too_big, tx, upper_transaction_weight_limit); @@ -8661,6 +8744,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent ptx.construction_data.unlock_time = unlock_time; ptx.construction_data.use_rct = false; ptx.construction_data.rct_config = { rct::RangeProofBorromean, 0 }; + ptx.construction_data.use_view_tags = use_view_tags; ptx.construction_data.dests = dsts; // record which subaddress indices are being used as inputs ptx.construction_data.subaddr_account = subaddr_account; @@ -8672,7 +8756,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count, std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, - uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config) + uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config, bool use_view_tags) { using namespace cryptonote; // throw if attempting a transaction with no destinations @@ -8857,7 +8941,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry rct::multisig_out msout; LOG_PRINT_L2("constructing tx"); auto sources_copy = sources; - bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, rct_config, m_multisig ? &msout : NULL); + bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, rct_config, m_multisig ? &msout : NULL, use_view_tags); LOG_PRINT_L2("constructed tx, r="<<r); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(upper_transaction_weight_limit <= get_transaction_weight(tx), error::tx_too_big, tx, upper_transaction_weight_limit); @@ -8902,7 +8986,8 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry LOG_PRINT_L2("Creating supplementary multisig transaction"); cryptonote::transaction ms_tx; auto sources_copy_copy = sources_copy; - bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources_copy_copy, splitted_dsts, change_dts.addr, extra, ms_tx, unlock_time,tx_key, additional_tx_keys, true, rct_config, &msout, false); + bool shuffle_outs = false; + bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources_copy_copy, splitted_dsts, change_dts.addr, extra, ms_tx, unlock_time,tx_key, additional_tx_keys, true, rct_config, &msout, shuffle_outs, use_view_tags); LOG_PRINT_L2("constructed tx, r="<<r); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(upper_transaction_weight_limit <= get_transaction_weight(tx), error::tx_too_big, tx, upper_transaction_weight_limit); @@ -8946,9 +9031,10 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry ptx.construction_data.unlock_time = unlock_time; ptx.construction_data.use_rct = true; ptx.construction_data.rct_config = { - tx.rct_signatures.p.bulletproofs.empty() ? rct::RangeProofBorromean : rct::RangeProofPaddedBulletproof, - use_fork_rules(HF_VERSION_CLSAG, -10) ? 3 : use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1 + rct::RangeProofPaddedBulletproof, + use_fork_rules(HF_VERSION_BULLETPROOF_PLUS, -10) ? 4 : 3 }; + ptx.construction_data.use_view_tags = use_fork_rules(get_view_tag_fork(), 0); ptx.construction_data.dests = dsts; // record which subaddress indices are being used as inputs ptx.construction_data.subaddr_account = subaddr_account; @@ -9642,14 +9728,15 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0); const bool use_rct = use_fork_rules(4, 0); const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0); + const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0); const bool clsag = use_fork_rules(get_clsag_fork(), 0); const rct::RCTConfig rct_config { - bulletproof ? rct::RangeProofPaddedBulletproof : rct::RangeProofBorromean, - bulletproof ? (use_fork_rules(HF_VERSION_CLSAG, -10) ? 3 : use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1) : 0 + rct::RangeProofPaddedBulletproof, + bulletproof_plus ? 4 : 3 }; + const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0); - const uint64_t base_fee = get_base_fee(); - const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm()); + const uint64_t base_fee = get_base_fee(priority); const uint64_t fee_quantization_mask = get_fee_quantization_mask(); // throw if attempting a transaction with no destinations @@ -9681,7 +9768,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp // early out if we know we can't make it anyway // we could also check for being within FEE_PER_KB, but if the fee calculation // ever changes, this might be missed, so let this go through - const uint64_t min_fee = (fee_multiplier * base_fee * estimate_tx_size(use_rct, 1, fake_outs_count, 2, extra.size(), bulletproof, clsag)); + const uint64_t min_fee = (base_fee * estimate_tx_size(use_rct, 1, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags)); uint64_t balance_subtotal = 0; uint64_t unlocked_balance_subtotal = 0; for (uint32_t index_minor : subaddr_indices) @@ -9699,11 +9786,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp LOG_PRINT_L2("Candidate subaddress index for spending: " << i); // determine threshold for fractional amount - const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag); - const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag); + const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags); + const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags); THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!"); const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring; - const uint64_t fractional_threshold = (fee_multiplier * base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024); + const uint64_t fractional_threshold = (base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024); // gather all dust and non-dust outputs belonging to specified subaddresses size_t num_nondust_outputs = 0; @@ -9797,7 +9884,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp { // this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which // will get us a known fee. - uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, base_fee, fee_multiplier, fee_quantization_mask); + uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask); preferred_inputs = pick_preferred_rct_inputs(needed_money + estimated_fee, subaddr_account, subaddr_indices); if (!preferred_inputs.empty()) { @@ -9910,7 +9997,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp } else { - while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag) < TX_WEIGHT_TARGET(upper_transaction_weight_limit)) + while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags) < TX_WEIGHT_TARGET(upper_transaction_weight_limit)) { // we can fully pay that destination LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) << @@ -9927,7 +10014,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp ++original_output_index; } - if (!out_slots_exhausted && available_amount > 0 && !dsts.empty() && estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag) < TX_WEIGHT_TARGET(upper_transaction_weight_limit)) { + if (!out_slots_exhausted && available_amount > 0 && !dsts.empty() && + estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags) < TX_WEIGHT_TARGET(upper_transaction_weight_limit)) { // we can partially fill that destination LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) << " for " << print_money(available_amount) << "/" << print_money(dsts[0].amount)); @@ -9965,7 +10053,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp } else { - const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag); + const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags); try_tx = dsts.empty() || (estimated_rct_tx_weight >= TX_WEIGHT_TARGET(upper_transaction_weight_limit)); THROW_WALLET_EXCEPTION_IF(try_tx && tx.dsts.empty(), error::tx_too_big, estimated_rct_tx_weight, upper_transaction_weight_limit); } @@ -9976,7 +10064,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp pending_tx test_ptx; const size_t num_outputs = get_num_outputs(tx.dsts, m_transfers, tx.selected_transfers); - needed_fee = estimate_fee(use_per_byte_fee, use_rct ,tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, base_fee, fee_multiplier, fee_quantization_mask); + needed_fee = estimate_fee(use_per_byte_fee, use_rct ,tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask); auto try_carving_from_partial_payment = [&](uint64_t needed_fee, uint64_t available_for_fee) { @@ -10025,12 +10113,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp tx.selected_transfers.size() << " inputs"); if (use_rct) transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - test_tx, test_ptx, rct_config); + test_tx, test_ptx, rct_config, use_view_tags); else transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); + detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags); auto txBlob = t_serializable_object_to_blob(test_ptx.tx); - needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask); + needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask); available_for_fee = test_ptx.fee + test_ptx.change_dts.amount + (!test_ptx.dust_added_to_fee ? test_ptx.dust : 0); LOG_PRINT_L2("Made a " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(available_for_fee) << " available for fee (" << print_money(needed_fee) << " needed)"); @@ -10050,12 +10138,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp while (needed_fee > test_ptx.fee) { if (use_rct) transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - test_tx, test_ptx, rct_config); + test_tx, test_ptx, rct_config, use_view_tags); else transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); + detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags); txBlob = t_serializable_object_to_blob(test_ptx.tx); - needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask); + needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask); LOG_PRINT_L2("Made an attempt at a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(test_ptx.fee) << " fee and " << print_money(test_ptx.change_dts.amount) << " change"); } @@ -10123,7 +10211,8 @@ skip_tx: extra, /* const std::vector<uint8_t>& extra, */ test_tx, /* OUT cryptonote::transaction& tx, */ test_ptx, /* OUT cryptonote::transaction& tx, */ - rct_config); + rct_config, + use_view_tags); /* const bool use_view_tags */ } else { transfer_selected(tx.dsts, tx.selected_transfers, @@ -10135,7 +10224,8 @@ skip_tx: detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, - test_ptx); + test_ptx, + use_view_tags); } auto txBlob = t_serializable_object_to_blob(test_ptx.tx); tx.tx = test_tx; @@ -10236,14 +10326,15 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below // determine threshold for fractional amount const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0); const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0); + const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0); const bool clsag = use_fork_rules(get_clsag_fork(), 0); - const uint64_t base_fee = get_base_fee(); - const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm()); - const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag); - const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag); + const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0); + const uint64_t base_fee = get_base_fee(priority); + const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags); + const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags); THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!"); const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring; - const uint64_t fractional_threshold = (fee_multiplier * base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024); + const uint64_t fractional_threshold = (base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024); THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account, false) == 0, error::wallet_internal_error, "No unlocked balance in the specified account"); @@ -10346,13 +10437,14 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE); const bool use_rct = fake_outs_count > 0 && use_fork_rules(4, 0); const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0); + const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0); const bool clsag = use_fork_rules(get_clsag_fork(), 0); const rct::RCTConfig rct_config { - bulletproof ? rct::RangeProofPaddedBulletproof : rct::RangeProofBorromean, - bulletproof ? (use_fork_rules(HF_VERSION_CLSAG, -10) ? 3 : use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1) : 0, + rct::RangeProofPaddedBulletproof, + bulletproof_plus ? 4 : 3 }; - const uint64_t base_fee = get_base_fee(); - const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm()); + const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0); + const uint64_t base_fee = get_base_fee(priority); const uint64_t fee_quantization_mask = get_fee_quantization_mask(); LOG_PRINT_L2("Starting with " << unused_transfers_indices.size() << " non-dust outputs and " << unused_dust_indices.size() << " dust outputs"); @@ -10378,12 +10470,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton uint64_t fee_dust_threshold; if (use_fork_rules(HF_VERSION_PER_BYTE_FEE)) { - const uint64_t estimated_tx_weight_with_one_extra_output = estimate_tx_weight(use_rct, tx.selected_transfers.size() + 1, fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag); - fee_dust_threshold = calculate_fee_from_weight(base_fee, estimated_tx_weight_with_one_extra_output, fee_multiplier, fee_quantization_mask); + const uint64_t estimated_tx_weight_with_one_extra_output = estimate_tx_weight(use_rct, tx.selected_transfers.size() + 1, fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags); + fee_dust_threshold = calculate_fee_from_weight(base_fee, estimated_tx_weight_with_one_extra_output, fee_quantization_mask); } else { - fee_dust_threshold = base_fee * fee_multiplier * (upper_transaction_weight_limit + 1023) / 1024; + fee_dust_threshold = base_fee * (upper_transaction_weight_limit + 1023) / 1024; } size_t idx = @@ -10409,7 +10501,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton // here, check if we need to sent tx and start a new one LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit " << upper_transaction_weight_limit); - const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 2, extra.size(), bulletproof, clsag); + const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags); bool try_tx = (unused_dust_indices.empty() && unused_transfers_indices.empty()) || ( estimated_rct_tx_weight >= TX_WEIGHT_TARGET(upper_transaction_weight_limit)); if (try_tx) { @@ -10417,7 +10509,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton pending_tx test_ptx; const size_t num_outputs = get_num_outputs(tx.dsts, m_transfers, tx.selected_transfers); - needed_fee = estimate_fee(use_per_byte_fee, use_rct, tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, base_fee, fee_multiplier, fee_quantization_mask); + needed_fee = estimate_fee(use_per_byte_fee, use_rct, tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask); // add N - 1 outputs for correct initial fee estimation for (size_t i = 0; i < ((outputs > 1) ? outputs - 1 : outputs); ++i) @@ -10427,12 +10519,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton tx.selected_transfers.size() << " outputs"); if (use_rct) transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - test_tx, test_ptx, rct_config); + test_tx, test_ptx, rct_config, use_view_tags); else transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); + detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags); auto txBlob = t_serializable_object_to_blob(test_ptx.tx); - needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask); + needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask); available_for_fee = test_ptx.fee + test_ptx.change_dts.amount; for (auto &dt: test_ptx.dests) available_for_fee += dt.amount; @@ -10464,12 +10556,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton } if (use_rct) transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - test_tx, test_ptx, rct_config); + test_tx, test_ptx, rct_config, use_view_tags); else transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, - detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); + detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags); txBlob = t_serializable_object_to_blob(test_ptx.tx); - needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask); + needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask); LOG_PRINT_L2("Made an attempt at a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(test_ptx.fee) << " fee and " << print_money(test_ptx.change_dts.amount) << " change"); } while (needed_fee > test_ptx.fee); @@ -10503,10 +10595,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton pending_tx test_ptx; if (use_rct) { transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra, - test_tx, test_ptx, rct_config); + test_tx, test_ptx, rct_config, use_view_tags); } else { transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra, - detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); + detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags); } auto txBlob = t_serializable_object_to_blob(test_ptx.tx); tx.tx = test_tx; @@ -10575,7 +10667,7 @@ void wallet2::cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_ hw::wallet_shim wallet_shim; setup_shim(&wallet_shim, this); aux_data.tx_recipients = dsts_info; - aux_data.bp_version = (use_fork_rules(HF_VERSION_CLSAG, -10) ? 3 : use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1); + aux_data.bp_version = (use_fork_rules(HF_VERSION_BULLETPROOF_PLUS, -10) ? 4 : use_fork_rules(HF_VERSION_CLSAG, -10) ? 3 : use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1); aux_data.hard_fork = get_current_hard_fork(); dev_cold->tx_sign(&wallet_shim, txs, exported_txs, aux_data); tx_device_aux = aux_data.tx_device_aux; @@ -10796,7 +10888,7 @@ std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions() const bool hf1_rules = use_fork_rules(2, 10); // first hard fork has version 2 tx_dust_policy dust_policy(hf1_rules ? 0 : ::config::DEFAULT_DUST_THRESHOLD); - const uint64_t base_fee = get_base_fee(); + const uint64_t base_fee = get_base_fee(1); // may throw std::vector<size_t> unmixable_outputs = select_available_unmixable_outputs(); @@ -11045,13 +11137,12 @@ std::string wallet2::get_spend_proof(const crypto::hash &txid, const std::string // derive the real output keypair const transfer_details& in_td = m_transfers[found->second]; - const txout_to_key* const in_tx_out_pkey = boost::get<txout_to_key>(std::addressof(in_td.m_tx.vout[in_td.m_internal_output_index].target)); - THROW_WALLET_EXCEPTION_IF(in_tx_out_pkey == nullptr, error::wallet_internal_error, "Output is not txout_to_key"); + crypto::public_key in_tx_out_pkey = in_td.get_public_key(); const crypto::public_key in_tx_pub_key = get_tx_pub_key_from_extra(in_td.m_tx, in_td.m_pk_index); const std::vector<crypto::public_key> in_additionakl_tx_pub_keys = get_additional_tx_pub_keys_from_extra(in_td.m_tx); keypair in_ephemeral; crypto::key_image in_img; - THROW_WALLET_EXCEPTION_IF(!generate_key_image_helper(m_account.get_keys(), m_subaddresses, in_tx_out_pkey->key, in_tx_pub_key, in_additionakl_tx_pub_keys, in_td.m_internal_output_index, in_ephemeral, in_img, m_account.get_device()), + THROW_WALLET_EXCEPTION_IF(!generate_key_image_helper(m_account.get_keys(), m_subaddresses, in_tx_out_pkey, in_tx_pub_key, in_additionakl_tx_pub_keys, in_td.m_internal_output_index, in_ephemeral, in_img, m_account.get_device()), error::wallet_internal_error, "failed to generate key image"); THROW_WALLET_EXCEPTION_IF(in_key->k_image != in_img, error::wallet_internal_error, "key image mismatch"); @@ -11250,24 +11341,12 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt for (size_t n = 0; n < tx.vout.size(); ++n) { - const cryptonote::txout_to_key* const out_key = boost::get<cryptonote::txout_to_key>(std::addressof(tx.vout[n].target)); - if (!out_key) + crypto::public_key output_public_key; + if (!get_output_public_key(tx.vout[n], output_public_key)) continue; - crypto::public_key derived_out_key; - bool r = crypto::derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key); - THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key"); - bool found = out_key->key == derived_out_key; - crypto::key_derivation found_derivation = derivation; - if (!found && !additional_derivations.empty()) - { - r = crypto::derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key); - THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key"); - found = out_key->key == derived_out_key; - found_derivation = additional_derivations[n]; - } - - if (found) + crypto::key_derivation found_derivation; + if (is_out_to_acc(address, output_public_key, derivation, additional_derivations, n, get_output_view_tag(tx.vout[n]), found_derivation)) { uint64_t amount; if (tx.version == 1 || tx.rct_signatures.type == rct::RCTTypeNull) @@ -11279,8 +11358,10 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt crypto::secret_key scalar1; crypto::derivation_to_scalar(found_derivation, n, scalar1); rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n]; - rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG); - const rct::key C = tx.rct_signatures.outPk[n].mask; + rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus); + rct::key C = tx.rct_signatures.outPk[n].mask; + if (rct::is_rct_bulletproof_plus(tx.rct_signatures.type)) + C = rct::scalarmult8(C); rct::key Ctmp; THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.mask.bytes) != 0, error::wallet_internal_error, "Bad ECDH input mask"); THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.amount.bytes) != 0, error::wallet_internal_error, "Bad ECDH input amount"); @@ -11359,6 +11440,42 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de } } +bool wallet2::is_out_to_acc(const cryptonote::account_public_address &address, const crypto::public_key& out_key, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const size_t output_index, const boost::optional<crypto::view_tag> &view_tag_opt, crypto::key_derivation &found_derivation) const +{ + crypto::public_key derived_out_key; + bool found = false; + bool r; + // first run quick check if output has matching view tag, otherwise output should not belong to account + if (out_can_be_to_acc(view_tag_opt, derivation, output_index)) + { + // if view tag match, run slower check deriving output pub key and comparing to expected + r = crypto::derive_public_key(derivation, output_index, address.m_spend_public_key, derived_out_key); + THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key"); + if (out_key == derived_out_key) + { + found = true; + found_derivation = derivation; + } + } + + if (!found && !additional_derivations.empty()) + { + const crypto::key_derivation &additional_derivation = additional_derivations[output_index]; + if (out_can_be_to_acc(view_tag_opt, additional_derivation, output_index)) + { + r = crypto::derive_public_key(additional_derivation, output_index, address.m_spend_public_key, derived_out_key); + THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key"); + if (out_key == derived_out_key) + { + found = true; + found_derivation = additional_derivation; + } + } + } + + return found; +} + std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message) { // fetch tx pubkey from the daemon @@ -11895,8 +12012,8 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr THROW_WALLET_EXCEPTION_IF(proof.index_in_tx >= tx.vout.size(), error::wallet_internal_error, "index_in_tx is out of bound"); - const cryptonote::txout_to_key* const out_key = boost::get<cryptonote::txout_to_key>(std::addressof(tx.vout[proof.index_in_tx].target)); - THROW_WALLET_EXCEPTION_IF(!out_key, error::wallet_internal_error, "Output key wasn't found") + crypto::public_key output_public_key; + THROW_WALLET_EXCEPTION_IF(!get_output_public_key(tx.vout[proof.index_in_tx], output_public_key), error::wallet_internal_error, "Output key wasn't found"); // get tx pub key const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx); @@ -11911,7 +12028,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr return false; // check signature for key image - const std::vector<const crypto::public_key*> pubs = { &out_key->key }; + const std::vector<const crypto::public_key*> pubs = { &output_public_key }; ok = crypto::check_ring_signature(prefix_hash, proof.key_image, &pubs[0], 1, &proof.key_image_sig); if (!ok) return false; @@ -11920,7 +12037,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr crypto::key_derivation derivation; THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(proof.shared_secret, rct::rct2sk(rct::I), derivation), error::wallet_internal_error, "Failed to generate key derivation"); crypto::public_key subaddr_spendkey; - crypto::derive_subaddress_public_key(out_key->key, derivation, proof.index_in_tx, subaddr_spendkey); + crypto::derive_subaddress_public_key(output_public_key, derivation, proof.index_in_tx, subaddr_spendkey); THROW_WALLET_EXCEPTION_IF(subaddr_spendkeys.count(subaddr_spendkey) == 0, error::wallet_internal_error, "The address doesn't seem to have received the fund"); @@ -11932,7 +12049,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr crypto::secret_key shared_secret; crypto::derivation_to_scalar(derivation, proof.index_in_tx, shared_secret); rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[proof.index_in_tx]; - rct::ecdhDecode(ecdh_info, rct::sk2rct(shared_secret), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG); + rct::ecdhDecode(ecdh_info, rct::sk2rct(shared_secret), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus); amount = rct::h2d(ecdh_info.amount); } total += amount; @@ -12017,10 +12134,10 @@ uint64_t wallet2::get_approximate_blockchain_height() const const int seconds_per_block = DIFFICULTY_TARGET_V2; // Calculated blockchain height uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block; - // testnet got some huge rollbacks, so the estimation is way off - static const uint64_t approximate_testnet_rolled_back_blocks = 342100; - if (m_nettype == TESTNET && approx_blockchain_height > approximate_testnet_rolled_back_blocks) - approx_blockchain_height -= approximate_testnet_rolled_back_blocks; + // testnet and stagenet got some huge rollbacks, so the estimation is way off + static const uint64_t approximate_rolled_back_blocks = m_nettype == TESTNET ? 342100 : 30000; + if ((m_nettype == TESTNET || m_nettype == STAGENET) && approx_blockchain_height > approximate_rolled_back_blocks) + approx_blockchain_height -= approximate_rolled_back_blocks; LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height); return approx_blockchain_height; } @@ -12374,11 +12491,7 @@ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>> const transfer_details &td = m_transfers[n]; // get ephemeral public key - const cryptonote::tx_out &out = td.m_tx.vout[td.m_internal_output_index]; - THROW_WALLET_EXCEPTION_IF(out.target.type() != typeid(txout_to_key), error::wallet_internal_error, - "Output is not txout_to_key"); - const cryptonote::txout_to_key &o = boost::get<const cryptonote::txout_to_key>(out.target); - const crypto::public_key pkey = o.key; + const crypto::public_key pkey = td.get_public_key(); // get tx pub key std::vector<tx_extra_field> tx_extra_fields; @@ -12495,11 +12608,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag const crypto::signature &signature = signed_key_images[n].second; // get ephemeral public key - const cryptonote::tx_out &out = td.m_tx.vout[td.m_internal_output_index]; - THROW_WALLET_EXCEPTION_IF(out.target.type() != typeid(txout_to_key), error::wallet_internal_error, - "Non txout_to_key output found"); - const cryptonote::txout_to_key &o = boost::get<cryptonote::txout_to_key>(out.target); - const crypto::public_key pkey = o.key; + const crypto::public_key pkey = td.get_public_key(); if (!td.m_key_image_known || !(key_image == td.m_key_image)) { @@ -12853,10 +12962,10 @@ void wallet2::import_blockchain(const std::tuple<size_t, crypto::hash, std::vect m_last_block_reward = cryptonote::get_outs_money_amount(genesis.miner_tx); } //---------------------------------------------------------------------------------------------------- -std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> wallet2::export_outputs(bool all) const +std::pair<uint64_t, std::vector<tools::wallet2::exported_transfer_details>> wallet2::export_outputs(bool all) const { PERF_TIMER(export_outputs); - std::vector<tools::wallet2::transfer_details> outs; + std::vector<tools::wallet2::exported_transfer_details> outs; size_t offset = 0; if (!all) @@ -12868,7 +12977,22 @@ std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> wallet2::expo { const transfer_details &td = m_transfers[n]; - outs.push_back(td); + exported_transfer_details etd; + etd.m_pubkey = td.get_public_key(); + etd.m_tx_pubkey = get_tx_pub_key_from_extra(td.m_tx, td.m_pk_index); + etd.m_internal_output_index = td.m_internal_output_index; + etd.m_global_output_index = td.m_global_output_index; + etd.m_flags.flags = 0; + etd.m_flags.m_spent = td.m_spent; + etd.m_flags.m_frozen = td.m_frozen; + etd.m_flags.m_rct = td.m_rct; + etd.m_flags.m_key_image_known = td.m_key_image_known; + etd.m_flags.m_key_image_request = td.m_key_image_request; + etd.m_flags.m_key_image_partial = td.m_key_image_partial; + etd.m_amount = td.m_amount; + etd.m_additional_tx_keys = get_additional_tx_pub_keys_from_extra(td.m_tx); + + outs.push_back(etd); } return std::make_pair(offset, outs); @@ -12940,9 +13064,7 @@ process: THROW_WALLET_EXCEPTION_IF(td.m_internal_output_index >= td.m_tx.vout.size(), error::wallet_internal_error, "Internal index is out of range"); - THROW_WALLET_EXCEPTION_IF(td.m_tx.vout[td.m_internal_output_index].target.type() != typeid(cryptonote::txout_to_key), - error::wallet_internal_error, "Unsupported output type"); - const crypto::public_key& out_key = boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key; + crypto::public_key out_key = td.get_public_key(); bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, out_key, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, td.m_key_image, m_account.get_device()); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image"); if (should_expand(td.m_subaddr_index)) @@ -12961,6 +13083,93 @@ process: return m_transfers.size(); } //---------------------------------------------------------------------------------------------------- +size_t wallet2::import_outputs(const std::pair<uint64_t, std::vector<tools::wallet2::exported_transfer_details>> &outputs) +{ + PERF_TIMER(import_outputs); + + THROW_WALLET_EXCEPTION_IF(outputs.first > m_transfers.size(), error::wallet_internal_error, + "Imported outputs omit more outputs that we know of. Try using export_outputs all."); + + const size_t offset = outputs.first; + const size_t original_size = m_transfers.size(); + m_transfers.resize(offset + outputs.second.size()); + for (size_t i = 0; i < offset; ++i) + m_transfers[i].m_key_image_request = false; + for (size_t i = 0; i < outputs.second.size(); ++i) + { + exported_transfer_details etd = outputs.second[i]; + transfer_details &td = m_transfers[i + offset]; + + // setup td with "cheao" loaded data + td.m_block_height = 0; + td.m_txid = crypto::null_hash; + td.m_global_output_index = etd.m_global_output_index; + td.m_spent = etd.m_flags.m_spent; + td.m_frozen = etd.m_flags.m_frozen; + td.m_spent_height = 0; + td.m_mask = rct::identity(); + td.m_amount = etd.m_amount; + td.m_rct = etd.m_flags.m_rct; + td.m_key_image_known = etd.m_flags.m_key_image_known; + td.m_key_image_request = etd.m_flags.m_key_image_request; + td.m_key_image_partial = false; + + // skip those we've already imported, or which have different data + if (i + offset < original_size) + { + bool needs_processing = false; + if (!td.m_key_image_known) + needs_processing = true; + else if (!(etd.m_internal_output_index == td.m_internal_output_index)) + needs_processing = true; + else if (!(etd.m_pubkey == td.get_public_key())) + needs_processing = true; + + if (!needs_processing) + continue; + } + + // construct a synthetix tx prefix that has the info we'll need: the output with its pubkey, the tx pubkey in extra + td.m_tx = {}; + + THROW_WALLET_EXCEPTION_IF(etd.m_internal_output_index >= 65536, error::wallet_internal_error, "internal output index seems outrageously high, rejecting"); + td.m_internal_output_index = etd.m_internal_output_index; + cryptonote::txout_to_key tk; + tk.key = etd.m_pubkey; + cryptonote::tx_out out; + out.amount = etd.m_amount; + out.target = tk; + td.m_tx.vout.resize(etd.m_internal_output_index); + td.m_tx.vout.push_back(out); + + td.m_pk_index = 0; + add_tx_pub_key_to_extra(td.m_tx, etd.m_tx_pubkey); + if (!etd.m_additional_tx_keys.empty()) + add_additional_tx_pub_keys_to_extra(td.m_tx.extra, etd.m_additional_tx_keys); + + // the hot wallet wouldn't have known about key images (except if we already exported them) + cryptonote::keypair in_ephemeral; + + const crypto::public_key &tx_pub_key = etd.m_tx_pubkey; + const std::vector<crypto::public_key> &additional_tx_pub_keys = etd.m_additional_tx_keys; + const crypto::public_key& out_key = etd.m_pubkey; + bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, out_key, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, td.m_key_image, m_account.get_device()); + THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image"); + if (should_expand(td.m_subaddr_index)) + expand_subaddresses(td.m_subaddr_index); + td.m_key_image_known = true; + td.m_key_image_request = true; + td.m_key_image_partial = false; + THROW_WALLET_EXCEPTION_IF(in_ephemeral.pub != out_key, + error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key at index " + boost::lexical_cast<std::string>(i + offset)); + + m_key_images[td.m_key_image] = i + offset; + m_pub_keys[td.get_public_key()] = i + offset; + } + + return m_transfers.size(); +} +//---------------------------------------------------------------------------------------------------- size_t wallet2::import_outputs_from_str(const std::string &outputs_st) { PERF_TIMER(import_outputs_from_str); @@ -12999,10 +13208,23 @@ size_t wallet2::import_outputs_from_str(const std::string &outputs_st) try { std::string body(data, headerlen); - std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> outputs; + + std::pair<uint64_t, std::vector<tools::wallet2::exported_transfer_details>> new_outputs; try { binary_archive<false> ar{epee::strspan<std::uint8_t>(body)}; + if (::serialization::serialize(ar, new_outputs)) + if (::serialization::check_stream_state(ar)) + loaded = true; + } + catch (...) {} + if (!loaded) + new_outputs.second.clear(); + + std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> outputs; + if (!loaded) try + { + binary_archive<false> ar{epee::strspan<std::uint8_t>(body)}; if (::serialization::serialize(ar, outputs)) if (::serialization::check_stream_state(ar)) loaded = true; @@ -13028,7 +13250,7 @@ size_t wallet2::import_outputs_from_str(const std::string &outputs_st) outputs.second = {}; } - imported_outputs = import_outputs(outputs); + imported_outputs = new_outputs.second.empty() ? import_outputs(outputs) : import_outputs(new_outputs); } catch (const std::exception &e) { @@ -14066,9 +14288,11 @@ std::pair<size_t, uint64_t> wallet2::estimate_tx_size_and_weight(bool use_rct, i n_outputs = 2; // extra dummy output const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0); + const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0); const bool clsag = use_fork_rules(get_clsag_fork(), 0); - size_t size = estimate_tx_size(use_rct, n_inputs, ring_size - 1, n_outputs, extra_size, bulletproof, clsag); - uint64_t weight = estimate_tx_weight(use_rct, n_inputs, ring_size - 1, n_outputs, extra_size, bulletproof, clsag); + const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0); + size_t size = estimate_tx_size(use_rct, n_inputs, ring_size - 1, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags); + uint64_t weight = estimate_tx_weight(use_rct, n_inputs, ring_size - 1, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags); return std::make_pair(size, weight); } //---------------------------------------------------------------------------------------------------- diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index d64832b13..660e6a14b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -347,7 +347,12 @@ private: bool is_rct() const { return m_rct; } uint64_t amount() const { return m_amount; } - const crypto::public_key &get_public_key() const { return boost::get<const cryptonote::txout_to_key>(m_tx.vout[m_internal_output_index].target).key; } + const crypto::public_key get_public_key() const { + crypto::public_key output_public_key; + THROW_WALLET_EXCEPTION_IF(!get_output_public_key(m_tx.vout[m_internal_output_index], output_public_key), + error::wallet_internal_error, "Unable to get output public key from output"); + return output_public_key; + }; BEGIN_SERIALIZE_OBJECT() FIELD(m_block_height) @@ -373,6 +378,40 @@ private: END_SERIALIZE() }; + struct exported_transfer_details + { + crypto::public_key m_pubkey; + uint64_t m_internal_output_index; + uint64_t m_global_output_index; + crypto::public_key m_tx_pubkey; + union + { + struct + { + uint8_t m_spent: 1; + uint8_t m_frozen: 1; + uint8_t m_rct: 1; + uint8_t m_key_image_known: 1; + uint8_t m_key_image_request: 1; // view wallets: we want to request it; cold wallets: it was requested + uint8_t m_key_image_partial: 1; + }; + uint8_t flags; + } m_flags; + uint64_t m_amount; + std::vector<crypto::public_key> m_additional_tx_keys; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(m_pubkey) + VARINT_FIELD(m_internal_output_index) + VARINT_FIELD(m_global_output_index) + FIELD(m_tx_pubkey) + FIELD(m_flags.flags) + VARINT_FIELD(m_amount) + FIELD(m_additional_tx_keys) + END_SERIALIZE() + }; + typedef std::vector<uint64_t> amounts_container; struct payment_details { @@ -495,10 +534,21 @@ private: uint64_t unlock_time; bool use_rct; rct::RCTConfig rct_config; + bool use_view_tags; std::vector<cryptonote::tx_destination_entry> dests; // original setup, does not include change uint32_t subaddr_account; // subaddress account of your wallet to be used in this transfer std::set<uint32_t> subaddr_indices; // set of address indices used as inputs in this transfer + enum construction_flags_ : uint8_t + { + _use_rct = 1 << 0, // 00000001 + _use_view_tags = 1 << 1 // 00000010 + // next flag = 1 << 2 // 00000100 + // ... + // final flag = 1 << 7 // 10000000 + }; + uint8_t construction_flags; + BEGIN_SERIALIZE_OBJECT() FIELD(sources) FIELD(change_dts) @@ -506,7 +556,26 @@ private: FIELD(selected_transfers) FIELD(extra) FIELD(unlock_time) - FIELD(use_rct) + + // converted `use_rct` field into construction_flags when view tags + // were introduced to maintain backwards compatibility + if (!typename Archive<W>::is_saving()) + { + FIELD_N("use_rct", construction_flags) + use_rct = (construction_flags & _use_rct) > 0; + use_view_tags = (construction_flags & _use_view_tags) > 0; + } + else + { + construction_flags = 0; + if (use_rct) + construction_flags ^= _use_rct; + if (use_view_tags) + construction_flags ^= _use_view_tags; + + FIELD_N("use_rct", construction_flags) + } + FIELD(rct_config) FIELD(dests) FIELD(subaddr_account) @@ -575,11 +644,15 @@ private: { std::vector<tx_construction_data> txes; std::pair<size_t, wallet2::transfer_container> transfers; + std::pair<size_t, std::vector<wallet2::exported_transfer_details>> new_transfers; BEGIN_SERIALIZE_OBJECT() - VERSION_FIELD(0) + VERSION_FIELD(1) FIELD(txes) - FIELD(transfers) + if (version >= 1) + FIELD(new_transfers) + else + FIELD(transfers) END_SERIALIZE() }; @@ -929,10 +1002,10 @@ private: template<typename T> void transfer_selected(const std::vector<cryptonote::tx_destination_entry>& dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count, std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, - uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx); + uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx, const bool use_view_tags); void transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count, std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, - uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config); + uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config, const bool use_view_tags); void commit_tx(pending_tx& ptx_vector); void commit_tx(std::vector<pending_tx>& ptx_vector); @@ -1052,9 +1125,7 @@ private: for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details &td = m_transfers[i]; - const cryptonote::tx_out &out = td.m_tx.vout[td.m_internal_output_index]; - const cryptonote::txout_to_key &o = boost::get<const cryptonote::txout_to_key>(out.target); - m_pub_keys.emplace(o.key, i); + m_pub_keys.emplace(td.get_public_key(), i); } return; } @@ -1204,6 +1275,8 @@ private: void ignore_outputs_below(uint64_t value) { m_ignore_outputs_below = value; } bool track_uses() const { return m_track_uses; } void track_uses(bool value) { m_track_uses = value; } + bool show_wallet_name_when_locked() const { return m_show_wallet_name_when_locked; } + void show_wallet_name_when_locked(bool value) { m_show_wallet_name_when_locked = value; } BackgroundMiningSetupType setup_background_mining() const { return m_setup_background_mining; } void setup_background_mining(BackgroundMiningSetupType value) { m_setup_background_mining = value; } uint32_t inactivity_lock_timeout() const { return m_inactivity_lock_timeout; } @@ -1231,6 +1304,7 @@ private: void check_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations); void check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations); void check_tx_key_helper(const cryptonote::transaction &tx, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received) const; + bool is_out_to_acc(const cryptonote::account_public_address &address, const crypto::public_key& out_key, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const size_t output_index, const boost::optional<crypto::view_tag> &view_tag_opt, crypto::key_derivation &found_derivation) const; std::string get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message); std::string get_tx_proof(const cryptonote::transaction &tx, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message) const; bool check_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received, bool &in_pool, uint64_t &confirmations); @@ -1347,8 +1421,9 @@ private: bool verify_with_public_key(const std::string &data, const crypto::public_key &public_key, const std::string &signature) const; // Import/Export wallet data - std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> export_outputs(bool all = false) const; + std::pair<uint64_t, std::vector<tools::wallet2::exported_transfer_details>> export_outputs(bool all = false) const; std::string export_outputs_to_str(bool all = false) const; + size_t import_outputs(const std::pair<uint64_t, std::vector<tools::wallet2::exported_transfer_details>> &outputs); size_t import_outputs(const std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> &outputs); size_t import_outputs_from_str(const std::string &outputs_st); payment_container export_payments() const; @@ -1386,8 +1461,9 @@ private: std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(const std::vector<std::pair<double, double>> &fee_levels); std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(uint64_t min_tx_weight, uint64_t max_tx_weight, const std::vector<uint64_t> &fees); - uint64_t estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask) const; + uint64_t estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask) const; uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm = -1); + uint64_t get_base_fee(uint32_t priority); uint64_t get_base_fee(); uint64_t get_fee_quantization_mask(); uint64_t get_min_ring_size(); @@ -1717,6 +1793,7 @@ private: uint64_t m_ignore_outputs_above; uint64_t m_ignore_outputs_below; bool m_track_uses; + bool m_show_wallet_name_when_locked; uint32_t m_inactivity_lock_timeout; BackgroundMiningSetupType m_setup_background_mining; bool m_persistent_rpc_client_id; diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index 066e98e52..ce13fc573 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_args.h b/src/wallet/wallet_args.h index 21e5f187c..350fce24e 100644 --- a/src/wallet/wallet_args.h +++ b/src/wallet/wallet_args.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 011780f43..df594aa21 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_light_rpc.h b/src/wallet/wallet_light_rpc.h index c2a7dc021..743a147f6 100644 --- a/src/wallet/wallet_light_rpc.h +++ b/src/wallet/wallet_light_rpc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_rpc_helpers.h b/src/wallet/wallet_rpc_helpers.h index 6f50b6727..93fa6996a 100644 --- a/src/wallet/wallet_rpc_helpers.h +++ b/src/wallet/wallet_rpc_helpers.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2020, The Monero Project +// Copyright (c) 2018-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_rpc_payments.cpp b/src/wallet/wallet_rpc_payments.cpp index bf278f695..61eaa8070 100644 --- a/src/wallet/wallet_rpc_payments.cpp +++ b/src/wallet/wallet_rpc_payments.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2020, The Monero Project +// Copyright (c) 2018-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index a173b5a50..57baf428f 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -622,7 +622,7 @@ namespace tools res.total_unlocked_balance = 0; cryptonote::subaddress_index subaddr_index = {0,0}; const std::pair<std::map<std::string, std::string>, std::vector<std::string>> account_tags = m_wallet->get_account_tags(); - if (!req.tag.empty() && account_tags.first.count(req.tag) == 0) + if (!req.tag.empty() && account_tags.first.count(req.tag) == 0 && !req.regexp) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = (boost::format(tr("Tag %s is unregistered.")) % req.tag).str(); @@ -630,7 +630,9 @@ namespace tools } for (; subaddr_index.major < m_wallet->get_num_subaddress_accounts(); ++subaddr_index.major) { - if (!req.tag.empty() && req.tag != account_tags.second[subaddr_index.major]) + bool no_match = !req.regexp ? (!req.tag.empty() && req.tag != account_tags.second[subaddr_index.major]) + : (!req.tag.empty() && !boost::regex_match(account_tags.second[subaddr_index.major], boost::regex(req.tag))); + if (no_match) continue; wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::subaddress_account_info info; info.account_index = subaddr_index.major; @@ -643,6 +645,12 @@ namespace tools res.total_balance += info.balance; res.total_unlocked_balance += info.unlocked_balance; } + if (res.subaddress_accounts.size() == 0 && req.regexp) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = (boost::format(tr("No matches for regex filter %s .")) % req.tag).str(); + return false; + } } catch (const std::exception& e) { @@ -1760,12 +1768,6 @@ namespace tools er.message = "Already integrated address"; return false; } - if (req.payment_id.empty()) - { - er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; - er.message = "Payment ID shouldn't be left unspecified"; - return false; - } res.integrated_address = get_account_integrated_address_as_str(m_wallet->nettype(), info.address, payment_id); } res.payment_id = epee::string_tools::pod_to_hex(payment_id); @@ -4132,7 +4134,8 @@ namespace tools try { res.multisig_info = m_wallet->exchange_multisig_keys(req.password, req.multisig_info); - if (res.multisig_info.empty()) + m_wallet->multisig(&ready); + if (ready) { res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); } diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 7169c9136..3088fd9c2 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 867ea54bd..fe53e293f 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -47,7 +47,7 @@ // advance which version they will stop working with // Don't go over 32767 for any of these #define WALLET_RPC_VERSION_MAJOR 1 -#define WALLET_RPC_VERSION_MINOR 24 +#define WALLET_RPC_VERSION_MINOR 25 #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) namespace tools @@ -243,10 +243,12 @@ namespace wallet_rpc { std::string tag; // all accounts if empty, otherwise those accounts with this tag bool strict_balances; + bool regexp; // allow regular expression filters if set to true BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tag) KV_SERIALIZE_OPT(strict_balances, false) + KV_SERIALIZE_OPT(regexp, false) END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init<request_t> request; diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h index b991029a9..914939573 100644 --- a/src/wallet/wallet_rpc_server_error_codes.h +++ b/src/wallet/wallet_rpc_server_error_codes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 85fa8f1dd..5a3c49560 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/benchmark.cpp b/tests/benchmark.cpp index 0461f4c11..6a845d61a 100644 --- a/tests/benchmark.cpp +++ b/tests/benchmark.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/block_weight/CMakeLists.txt b/tests/block_weight/CMakeLists.txt index 9bde90be4..d36de3e9a 100644 --- a/tests/block_weight/CMakeLists.txt +++ b/tests/block_weight/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2018, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/block_weight/block_weight.cpp b/tests/block_weight/block_weight.cpp index 60606d53f..b478a5633 100644 --- a/tests/block_weight/block_weight.cpp +++ b/tests/block_weight/block_weight.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/block_weight/block_weight.py b/tests/block_weight/block_weight.py index f396585a4..16154bab9 100755 --- a/tests/block_weight/block_weight.py +++ b/tests/block_weight/block_weight.py @@ -2,7 +2,7 @@ # Simulate a maximal block attack on the Monero network # This uses the scheme proposed by ArticMine # Written by Sarang Nother -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project from __future__ import print_function import sys import math diff --git a/tests/core_proxy/CMakeLists.txt b/tests/core_proxy/CMakeLists.txt index 63c511665..a18a46c8d 100644 --- a/tests/core_proxy/CMakeLists.txt +++ b/tests/core_proxy/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/core_proxy/core_proxy.cpp b/tests/core_proxy/core_proxy.cpp index 09be8758b..c029bc235 100644 --- a/tests/core_proxy/core_proxy.cpp +++ b/tests/core_proxy/core_proxy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_proxy/core_proxy.h b/tests/core_proxy/core_proxy.h index 94f148e8c..fe10dde6e 100644 --- a/tests/core_proxy/core_proxy.h +++ b/tests/core_proxy/core_proxy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/CMakeLists.txt b/tests/core_tests/CMakeLists.txt index 7455639ca..d098a8e04 100644 --- a/tests/core_tests/CMakeLists.txt +++ b/tests/core_tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -44,6 +44,7 @@ set(core_tests_sources v2_tests.cpp rct.cpp bulletproofs.cpp + bulletproof_plus.cpp rct2.cpp wallet_tools.cpp) @@ -65,6 +66,7 @@ set(core_tests_headers v2_tests.h rct.h bulletproofs.h + bulletproof_plus.h rct2.h wallet_tools.h) diff --git a/tests/core_tests/block_reward.cpp b/tests/core_tests/block_reward.cpp index 55eb517df..b1175e297 100644 --- a/tests/core_tests/block_reward.cpp +++ b/tests/core_tests/block_reward.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/block_reward.h b/tests/core_tests/block_reward.h index ef62abc7f..77d0bd5f9 100644 --- a/tests/core_tests/block_reward.h +++ b/tests/core_tests/block_reward.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index fb8ddbe11..711f67b41 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -671,3 +671,127 @@ bool gen_block_low_coinbase::generate(std::vector<test_event_entry>& events) con return true; } + +bool gen_block_miner_tx_out_has_no_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + bool use_view_tags = false; + + BLOCK_VALIDATION_INIT_GENERATE(); + + MAKE_MINER_TX_MANUALLY(miner_tx, blk_0); + + CHECK_AND_ASSERT_MES(!cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should not have a view tag"); + + crypto::public_key output_public_key; + crypto::view_tag view_tag; + cryptonote::get_output_public_key(miner_tx.vout[0], output_public_key); + + // explicitly call the setter to ensure it does not set a view tag on the miner tx output + cryptonote::set_tx_out(miner_tx.vout[0].amount, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]); + CHECK_AND_ASSERT_MES(!cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should still not have a view tag"); + + block blk_1; + generator.construct_block_manually(blk_1, blk_0, miner_account, test_generator::bf_miner_tx, 0, 0, 0, crypto::hash(), 0, miner_tx); + events.push_back(blk_1); + + DO_CALLBACK(events, "check_block_accepted"); + + return true; +} + +bool gen_block_miner_tx_out_has_no_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + bool use_view_tags = false; + + BLOCK_VALIDATION_INIT_GENERATE(); + + keypair txkey; + MAKE_MINER_TX_AND_KEY_AT_HF_MANUALLY(miner_tx, blk_0, HF_VERSION_VIEW_TAGS+1, &txkey); + + crypto::public_key output_public_key; + crypto::view_tag view_tag; + cryptonote::get_output_public_key(miner_tx.vout[0], output_public_key); + + // remove the view tag that is currently set on the miner tx output at this point + cryptonote::set_tx_out(miner_tx.vout[0].amount, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]); + CHECK_AND_ASSERT_MES(!cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should not have a view tag"); + + block blk_1; + generator.construct_block_manually(blk_1, blk_0, miner_account, + test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_miner_tx, + HF_VERSION_VIEW_TAGS+1, HF_VERSION_VIEW_TAGS+1, 0, crypto::hash(), 0, miner_tx); + events.push_back(blk_1); + + DO_CALLBACK(events, "check_block_purged"); + + return true; +} + +bool gen_block_miner_tx_out_has_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + bool use_view_tags = true; + + BLOCK_VALIDATION_INIT_GENERATE(); + + keypair txkey; + MAKE_MINER_TX_AND_KEY_MANUALLY(miner_tx, blk_0, &txkey); + + // derive the view tag for the miner tx output + crypto::key_derivation derivation; + crypto::public_key output_public_key; + crypto::view_tag view_tag; + crypto::generate_key_derivation(miner_account.get_keys().m_account_address.m_view_public_key, txkey.sec, derivation); + crypto::derive_public_key(derivation, 0, miner_account.get_keys().m_account_address.m_spend_public_key, output_public_key); + crypto::derive_view_tag(derivation, 0, view_tag); + + // set the view tag on the miner tx output + cryptonote::set_tx_out(miner_tx.vout[0].amount, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]); + boost::optional<crypto::view_tag> actual_vt = cryptonote::get_output_view_tag(miner_tx.vout[0]); + CHECK_AND_ASSERT_MES(actual_vt && *actual_vt == view_tag, false, "unexpected output view tag"); + + block blk_1; + generator.construct_block_manually(blk_1, blk_0, miner_account, test_generator::bf_miner_tx, 0, 0, 0, crypto::hash(), 0, miner_tx); + events.push_back(blk_1); + + DO_CALLBACK(events, "check_block_purged"); + + return true; +} + +bool gen_block_miner_tx_out_has_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + bool use_view_tags = true; + + BLOCK_VALIDATION_INIT_GENERATE(); + + keypair txkey; + MAKE_MINER_TX_AND_KEY_AT_HF_MANUALLY(miner_tx, blk_0, HF_VERSION_VIEW_TAGS, &txkey); + + CHECK_AND_ASSERT_MES(cryptonote::get_output_view_tag(miner_tx.vout[0]), false, "output should have a view tag"); + + // derive the view tag for the miner tx output + crypto::key_derivation derivation; + crypto::public_key output_public_key; + crypto::view_tag view_tag; + crypto::generate_key_derivation(miner_account.get_keys().m_account_address.m_view_public_key, txkey.sec, derivation); + crypto::derive_public_key(derivation, 0, miner_account.get_keys().m_account_address.m_spend_public_key, output_public_key); + crypto::derive_view_tag(derivation, 0, view_tag); + + boost::optional<crypto::view_tag> actual_vt = cryptonote::get_output_view_tag(miner_tx.vout[0]); + CHECK_AND_ASSERT_MES(actual_vt && *actual_vt == view_tag, false, "unexpected output view tag"); + + // set the view tag on the miner tx output + cryptonote::set_tx_out(miner_tx.vout[0].amount, output_public_key, use_view_tags, view_tag, miner_tx.vout[0]); + boost::optional<crypto::view_tag> actual_vt_after_setting = cryptonote::get_output_view_tag(miner_tx.vout[0]); + CHECK_AND_ASSERT_MES(actual_vt_after_setting && *actual_vt_after_setting == view_tag, false, "unexpected output view tag after setting"); + + block blk_1; + generator.construct_block_manually(blk_1, blk_0, miner_account, + test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_miner_tx, + HF_VERSION_VIEW_TAGS, HF_VERSION_VIEW_TAGS, 0, crypto::hash(), 0, miner_tx); + events.push_back(blk_1); + + DO_CALLBACK(events, "check_block_accepted"); + + return true; +} diff --git a/tests/core_tests/block_validation.h b/tests/core_tests/block_validation.h index 0dd4e145c..3a157aaa9 100644 --- a/tests/core_tests/block_validation.h +++ b/tests/core_tests/block_validation.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -230,3 +230,37 @@ struct get_test_options<gen_block_low_coinbase> { hard_forks, 0 }; }; + +struct gen_block_miner_tx_out_has_no_view_tag_before_hf_view_tags : public gen_block_accepted_base<2> +{ + bool generate(std::vector<test_event_entry>& events) const; +}; + +struct gen_block_miner_tx_out_has_no_view_tag_from_hf_view_tags : public gen_block_verification_base<1> +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> +struct get_test_options<gen_block_miner_tx_out_has_no_view_tag_from_hf_view_tags> { + const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(HF_VERSION_VIEW_TAGS+1, 1), std::make_pair(0, 0)}; + const cryptonote::test_options test_options = { + hard_forks, 0 + }; +}; + +struct gen_block_miner_tx_out_has_view_tag_before_hf_view_tags : public gen_block_verification_base<1> +{ + bool generate(std::vector<test_event_entry>& events) const; +}; + +struct gen_block_miner_tx_out_has_view_tag_from_hf_view_tags : public gen_block_accepted_base<2> +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> +struct get_test_options<gen_block_miner_tx_out_has_view_tag_from_hf_view_tags> { + const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(HF_VERSION_VIEW_TAGS, 1), std::make_pair(0, 0)}; + const cryptonote::test_options test_options = { + hard_forks, 0 + }; +}; diff --git a/tests/core_tests/bulletproof_plus.cpp b/tests/core_tests/bulletproof_plus.cpp new file mode 100644 index 000000000..c3879e646 --- /dev/null +++ b/tests/core_tests/bulletproof_plus.cpp @@ -0,0 +1,373 @@ +// Copyright (c) 2014-2020, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#include "ringct/rctSigs.h" +#include "ringct/bulletproofs_plus.h" +#include "chaingen.h" +#include "bulletproof_plus.h" +#include "device/device.hpp" + +using namespace epee; +using namespace crypto; +using namespace cryptonote; + +//---------------------------------------------------------------------------------------------------------------------- +// Tests + +bool gen_bpp_tx_validation_base::generate_with(std::vector<test_event_entry>& events, + size_t mixin, size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config, uint8_t hf_version, + const std::function<bool(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations, size_t tx_idx)> &pre_tx, + const std::function<bool(transaction &tx, size_t tx_idx)> &post_tx) const +{ + uint64_t ts_start = 1338224400; + + GENERATE_ACCOUNT(miner_account); + MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start); + + // create 12 miner accounts, and have them mine the next 12 blocks + cryptonote::account_base miner_accounts[12]; + const cryptonote::block *prev_block = &blk_0; + cryptonote::block blocks[12 + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW]; + for (size_t n = 0; n < 12; ++n) { + miner_accounts[n].generate(); + CHECK_AND_ASSERT_MES(generator.construct_block_manually(blocks[n], *prev_block, miner_accounts[n], + test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version, + 2, 2, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long + crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, 2), + false, "Failed to generate block"); + events.push_back(blocks[n]); + prev_block = blocks + n; + } + + // rewind + cryptonote::block blk_r, blk_last; + { + blk_last = blocks[11]; + for (size_t i = 0; i < CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW; ++i) + { + CHECK_AND_ASSERT_MES(generator.construct_block_manually(blocks[12+i], blk_last, miner_account, + test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version, + 2, 2, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long + crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, 2), + false, "Failed to generate block"); + events.push_back(blocks[12+i]); + blk_last = blocks[12+i]; + } + blk_r = blk_last; + } + + // create 4 txes from these miners in another block, to generate some rct outputs + std::vector<transaction> rct_txes; + cryptonote::block blk_txes; + std::vector<crypto::hash> starting_rct_tx_hashes; + uint64_t fees = 0; + static const uint64_t input_amounts_available[] = {5000000000000, 30000000000000, 100000000000, 80000000000}; + for (size_t n = 0; n < n_txes; ++n) + { + std::vector<tx_source_entry> sources; + + sources.resize(1); + tx_source_entry& src = sources.back(); + + const uint64_t needed_amount = input_amounts_available[n]; + src.amount = input_amounts_available[n]; + size_t real_index_in_tx = 0; + for (size_t m = 0; m <= mixin; ++m) { + size_t index_in_tx = 0; + for (size_t i = 0; i < blocks[m].miner_tx.vout.size(); ++i) + if (blocks[m].miner_tx.vout[i].amount == needed_amount) + index_in_tx = i; + CHECK_AND_ASSERT_MES(blocks[m].miner_tx.vout[index_in_tx].amount == needed_amount, false, "Expected amount not found"); + src.push_output(m, boost::get<txout_to_key>(blocks[m].miner_tx.vout[index_in_tx].target).key, src.amount); + if (m == n) + real_index_in_tx = index_in_tx; + } + src.real_out_tx_key = cryptonote::get_tx_pub_key_from_extra(blocks[n].miner_tx); + src.real_output = n; + src.real_output_in_tx_index = real_index_in_tx; + src.mask = rct::identity(); + src.rct = false; + + //fill outputs entry + tx_destination_entry td; + td.addr = miner_accounts[n].get_keys().m_account_address; + std::vector<tx_destination_entry> destinations; + for (int o = 0; amounts_paid[o] != (uint64_t)-1; ++o) + { + td.amount = amounts_paid[o]; + destinations.push_back(td); + } + + if (pre_tx && !pre_tx(sources, destinations, n)) + { + MDEBUG("pre_tx returned failure"); + return false; + } + + crypto::secret_key tx_key; + std::vector<crypto::secret_key> additional_tx_keys; + std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; + subaddresses[miner_accounts[n].get_keys().m_account_address.m_spend_public_key] = {0,0}; + rct_txes.resize(rct_txes.size() + 1); + bool r = construct_tx_and_get_tx_key(miner_accounts[n].get_keys(), subaddresses, sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), rct_txes.back(), 0, tx_key, additional_tx_keys, true, rct_config[n]); + CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); + + if (post_tx && !post_tx(rct_txes.back(), n)) + { + MDEBUG("post_tx returned failure"); + return false; + } + + //events.push_back(rct_txes.back()); + starting_rct_tx_hashes.push_back(get_transaction_hash(rct_txes.back())); + LOG_PRINT_L0("Test tx: " << obj_to_json_str(rct_txes.back())); + + for (int o = 0; amounts_paid[o] != (uint64_t)-1; ++o) + { + crypto::key_derivation derivation; + bool r = crypto::generate_key_derivation(destinations[o].addr.m_view_public_key, tx_key, derivation); + CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); + crypto::secret_key amount_key; + crypto::derivation_to_scalar(derivation, o, amount_key); + rct::key rct_tx_mask; + const uint8_t type = rct_txes.back().rct_signatures.type; + if (rct::is_rct_simple(type)) + rct::decodeRctSimple(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default")); + else + rct::decodeRct(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default")); + } + + while (amounts_paid[0] != (size_t)-1) + ++amounts_paid; + ++amounts_paid; + + uint64_t fee = 0; + get_tx_fee(rct_txes.back(), fee); + fees += fee; + } + if (!valid) + DO_CALLBACK(events, "mark_invalid_tx"); + events.push_back(rct_txes); + + CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes, blk_last, miner_account, + test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_tx_hashes | test_generator::bf_hf_version | test_generator::bf_max_outs | test_generator::bf_tx_fees, + hf_version, hf_version, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long + crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 6, hf_version, fees), + false, "Failed to generate block"); + if (!valid) + DO_CALLBACK(events, "mark_invalid_block"); + events.push_back(blk_txes); + blk_last = blk_txes; + + return true; +} + +bool gen_bpp_tx_validation_base::check_bpp(const cryptonote::transaction &tx, size_t tx_idx, const size_t *sizes, const char *context) const +{ + DEFINE_TESTS_ERROR_CONTEXT(context); + CHECK_TEST_CONDITION(tx.version >= 2); + CHECK_TEST_CONDITION(rct::is_rct_bulletproof_plus(tx.rct_signatures.type)); + size_t n_sizes = 0, n_amounts = 0; + for (size_t n = 0; n < tx_idx; ++n) + { + while (sizes[0] != (size_t)-1) + ++sizes; + ++sizes; + } + while (sizes[n_sizes] != (size_t)-1) + n_amounts += sizes[n_sizes++]; + CHECK_TEST_CONDITION(tx.rct_signatures.p.bulletproofs_plus.size() == n_sizes); + CHECK_TEST_CONDITION(rct::n_bulletproof_plus_max_amounts(tx.rct_signatures.p.bulletproofs_plus) == n_amounts); + for (size_t n = 0; n < n_sizes; ++n) + CHECK_TEST_CONDITION(rct::n_bulletproof_plus_max_amounts(tx.rct_signatures.p.bulletproofs_plus[n]) == sizes[n]); + return true; +} + +bool gen_bpp_tx_invalid_before_fork::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; + const size_t bp_sizes[] = {2, (size_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 4 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS - 1, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bpp(tx, tx_idx, bp_sizes, "gen_bpp_tx_invalid_before_fork"); }); +} + +bool gen_bpp_tx_valid_at_fork::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; + const size_t bp_sizes[] = {2, (size_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 4 } }; + return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bpp(tx, tx_idx, bp_sizes, "gen_bpp_tx_valid_at_fork"); }); +} + +bool gen_bpp_tx_invalid_1_1::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof , 4 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, NULL); +} + +bool gen_bpp_tx_valid_2::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; + const size_t bp_sizes[] = {2, (size_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 4 } }; + return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bpp(tx, tx_idx, bp_sizes, "gen_bpp_tx_valid_2"); }); +} + +bool gen_bpp_tx_valid_3::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {5000, 5000, 5000, (uint64_t)-1}; + const size_t bp_sizes[] = {4, (size_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof , 4 } }; + return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bpp(tx, tx_idx, bp_sizes, "gen_bpp_tx_valid_3"); }); +} + +bool gen_bpp_tx_valid_16::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, (uint64_t)-1}; + const size_t bp_sizes[] = {16, (size_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof , 4 } }; + return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bpp(tx, tx_idx, bp_sizes, "gen_bpp_tx_valid_16"); }); +} + +bool gen_bpp_tx_invalid_4_2_1::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof , 4 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, NULL); +} + +bool gen_bpp_tx_invalid_16_16::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof , 4 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, NULL); +} + +bool gen_bpp_txs_valid_2_and_2::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {1000, 1000, (size_t)-1, 1000, 1000, (uint64_t)-1}; + const size_t bp_sizes[] = {2, (size_t)-1, 2, (size_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 4 }, {rct::RangeProofPaddedBulletproof, 4 } }; + return generate_with(events, mixin, 2, amounts_paid, true, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bpp(tx, tx_idx, bp_sizes, "gen_bpp_txs_valid_2_and_2"); }); +} + +bool gen_bpp_txs_invalid_2_and_8_2_and_16_16_1::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = {{rct::RangeProofMultiOutputBulletproof, 4}, {rct::RangeProofMultiOutputBulletproof, 4}, {rct::RangeProofMultiOutputBulletproof, 4}}; + return generate_with(events, mixin, 3, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, NULL); +} + +bool gen_bpp_txs_valid_2_and_3_and_2_and_4::generate(std::vector<test_event_entry>& events) const +{ + const size_t mixin = 10; + const uint64_t amounts_paid[] = {11111115000, 11111115000, (uint64_t)-1, 11111115000, 11111115000, 11111115001, (uint64_t)-1, 11111115000, 11111115002, (uint64_t)-1, 11111115000, 11111115000, 11111115000, 11111115003, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = {{rct::RangeProofPaddedBulletproof, 4}, {rct::RangeProofPaddedBulletproof, 4}, {rct::RangeProofPaddedBulletproof, 4}, {rct::RangeProofPaddedBulletproof, 4}}; + const size_t bp_sizes[] = {2, (size_t)-1, 4, (size_t)-1, 2, (size_t)-1, 4, (size_t)-1}; + return generate_with(events, mixin, 4, amounts_paid, true, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx) { return check_bpp(tx, tx_idx, bp_sizes, "gen_bpp_txs_valid_2_and_3_and_2_and_4"); }); +} + +bool gen_bpp_tx_invalid_not_enough_proofs::generate(std::vector<test_event_entry>& events) const +{ + DEFINE_TESTS_ERROR_CONTEXT("gen_bpp_tx_invalid_not_enough_proofs"); + const size_t mixin = 10; + const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){ + CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus); + CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty()); + tx.rct_signatures.p.bulletproofs_plus.pop_back(); + CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty()); + return true; + }); +} + +bool gen_bpp_tx_invalid_empty_proofs::generate(std::vector<test_event_entry>& events) const +{ + DEFINE_TESTS_ERROR_CONTEXT("gen_bpp_tx_invalid_empty_proofs"); + const size_t mixin = 10; + const uint64_t amounts_paid[] = {50000, 50000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){ + CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus); + tx.rct_signatures.p.bulletproofs_plus.clear(); + return true; + }); +} + +bool gen_bpp_tx_invalid_too_many_proofs::generate(std::vector<test_event_entry>& events) const +{ + DEFINE_TESTS_ERROR_CONTEXT("gen_bpp_tx_invalid_too_many_proofs"); + const size_t mixin = 10; + const uint64_t amounts_paid[] = {10000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){ + CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus); + CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty()); + tx.rct_signatures.p.bulletproofs_plus.push_back(tx.rct_signatures.p.bulletproofs_plus.back()); + return true; + }); +} + +bool gen_bpp_tx_invalid_wrong_amount::generate(std::vector<test_event_entry>& events) const +{ + DEFINE_TESTS_ERROR_CONTEXT("gen_bpp_tx_invalid_wrong_amount"); + const size_t mixin = 10; + const uint64_t amounts_paid[] = {10000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){ + CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus); + CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty()); + tx.rct_signatures.p.bulletproofs_plus.back() = rct::bulletproof_plus_PROVE(1000, rct::skGen()); + return true; + }); +} + +bool gen_bpp_tx_invalid_clsag_type::generate(std::vector<test_event_entry>& events) const +{ + DEFINE_TESTS_ERROR_CONTEXT("gen_bpp_tx_invalid_clsag_type"); + const size_t mixin = 10; + const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 3 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS + 1, NULL, [&](cryptonote::transaction &tx, size_t tx_idx){ + return true; + }); +} diff --git a/tests/core_tests/bulletproof_plus.h b/tests/core_tests/bulletproof_plus.h new file mode 100644 index 000000000..481044fd4 --- /dev/null +++ b/tests/core_tests/bulletproof_plus.h @@ -0,0 +1,206 @@ +// Copyright (c) 2014-2020, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once +#include "chaingen.h" + +struct gen_bpp_tx_validation_base : public test_chain_unit_base +{ + gen_bpp_tx_validation_base() + : m_invalid_tx_index(0) + , m_invalid_block_index(0) + { + REGISTER_CALLBACK_METHOD(gen_bpp_tx_validation_base, mark_invalid_tx); + REGISTER_CALLBACK_METHOD(gen_bpp_tx_validation_base, mark_invalid_block); + } + + bool check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool tx_added, size_t event_idx, const cryptonote::transaction& /*tx*/) + { + if (m_invalid_tx_index == event_idx) + return tvc.m_verifivation_failed; + else + return !tvc.m_verifivation_failed && tx_added; + } + + bool check_tx_verification_context_array(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t tx_added, size_t event_idx, const std::vector<cryptonote::transaction>& /*txs*/) + { + size_t failed = 0; + for (const cryptonote::tx_verification_context &tvc: tvcs) + if (tvc.m_verifivation_failed) + ++failed; + if (m_invalid_tx_index == event_idx) + return failed > 0; + else + return failed == 0 && tx_added == tvcs.size(); + } + + bool check_block_verification_context(const cryptonote::block_verification_context& bvc, size_t event_idx, const cryptonote::block& /*block*/) + { + if (m_invalid_block_index == event_idx) + return bvc.m_verifivation_failed; + else + return !bvc.m_verifivation_failed; + } + + bool mark_invalid_block(cryptonote::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/) + { + m_invalid_block_index = ev_index + 1; + return true; + } + + bool mark_invalid_tx(cryptonote::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/) + { + m_invalid_tx_index = ev_index + 1; + return true; + } + + bool generate_with(std::vector<test_event_entry>& events, size_t mixin, + size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config, uint8_t hf_version, + const std::function<bool(std::vector<cryptonote::tx_source_entry> &sources, std::vector<cryptonote::tx_destination_entry> &destinations, size_t)> &pre_tx, + const std::function<bool(cryptonote::transaction &tx, size_t)> &post_tx) const; + + bool check_bpp(const cryptonote::transaction &tx, size_t tx_idx, const size_t *sizes, const char *context) const; + +private: + size_t m_invalid_tx_index; + size_t m_invalid_block_index; +}; + +template<> +struct get_test_options<gen_bpp_tx_validation_base> { + const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(HF_VERSION_BULLETPROOF_PLUS, 73), std::make_pair(0, 0)}; + const cryptonote::test_options test_options = { + hard_forks, 0 + }; +}; + +template<uint8_t test_version = 1> +struct get_bpp_versioned_test_options: public get_test_options<gen_bpp_tx_validation_base> { + const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(test_version, 73), std::make_pair(0, 0)}; + const cryptonote::test_options test_options = { + hard_forks, 0 + }; +}; + +struct gen_bpp_tx_invalid_before_fork : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_invalid_before_fork>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS - 1> {}; + +struct gen_bpp_tx_valid_at_fork : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_valid_at_fork>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_invalid_1_1 : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_invalid_1_1>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_valid_2 : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_valid_2>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_valid_3 : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_valid_3>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_valid_16 : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_valid_16>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_invalid_4_2_1 : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_invalid_4_2_1>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_invalid_16_16 : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_invalid_16_16>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_txs_valid_2_and_2 : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_txs_valid_2_and_2>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_txs_invalid_2_and_8_2_and_16_16_1 : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_txs_invalid_2_and_8_2_and_16_16_1>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_txs_valid_2_and_3_and_2_and_4 : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_txs_valid_2_and_3_and_2_and_4>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_invalid_not_enough_proofs : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_invalid_not_enough_proofs>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_invalid_empty_proofs : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_invalid_empty_proofs>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_invalid_too_many_proofs : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_invalid_too_many_proofs>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_invalid_wrong_amount : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_invalid_wrong_amount>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS> {}; + +struct gen_bpp_tx_invalid_clsag_type : public gen_bpp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bpp_tx_invalid_clsag_type>: public get_bpp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS + 1> {}; diff --git a/tests/core_tests/bulletproofs.cpp b/tests/core_tests/bulletproofs.cpp index c46b5e657..2f0f33cd6 100644 --- a/tests/core_tests/bulletproofs.cpp +++ b/tests/core_tests/bulletproofs.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -158,7 +158,7 @@ bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& eve crypto::derivation_to_scalar(derivation, o, amount_key); rct::key rct_tx_mask; const uint8_t type = rct_txes.back().rct_signatures.type; - if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2 || type == rct::RCTTypeCLSAG) + if (rct::is_rct_simple(type)) rct::decodeRctSimple(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default")); else rct::decodeRct(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default")); @@ -232,7 +232,7 @@ bool gen_bp_tx_invalid_1_1::generate(std::vector<test_event_entry>& events) cons { const size_t mixin = 10; const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof , 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof , 3 } }; return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, NULL); } @@ -241,7 +241,7 @@ bool gen_bp_tx_valid_2::generate(std::vector<test_event_entry>& events) const const size_t mixin = 10; const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; const size_t bp_sizes[] = {2, (size_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 3 } }; return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_2"); }); } @@ -250,7 +250,7 @@ bool gen_bp_tx_valid_3::generate(std::vector<test_event_entry>& events) const const size_t mixin = 10; const uint64_t amounts_paid[] = {5000, 5000, 5000, (uint64_t)-1}; const size_t bp_sizes[] = {4, (size_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof , 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 3 } }; return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_3"); }); } @@ -259,7 +259,7 @@ bool gen_bp_tx_valid_16::generate(std::vector<test_event_entry>& events) const const size_t mixin = 10; const uint64_t amounts_paid[] = {500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, (uint64_t)-1}; const size_t bp_sizes[] = {16, (size_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof , 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 3 } }; return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_16"); }); } @@ -267,7 +267,7 @@ bool gen_bp_tx_invalid_4_2_1::generate(std::vector<test_event_entry>& events) co { const size_t mixin = 10; const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof , 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof, 3 } }; return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, NULL); } @@ -275,7 +275,7 @@ bool gen_bp_tx_invalid_16_16::generate(std::vector<test_event_entry>& events) co { const size_t mixin = 10; const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof , 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof, 3 } }; return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, NULL); } @@ -284,7 +284,7 @@ bool gen_bp_txs_valid_2_and_2::generate(std::vector<test_event_entry>& events) c const size_t mixin = 10; const uint64_t amounts_paid[] = {1000, 1000, (size_t)-1, 1000, 1000, (uint64_t)-1}; const size_t bp_sizes[] = {2, (size_t)-1, 2, (size_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 0 }, {rct::RangeProofPaddedBulletproof, 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 3 }, {rct::RangeProofPaddedBulletproof, 3 } }; return generate_with(events, mixin, 2, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_2"); }); } @@ -292,7 +292,7 @@ bool gen_bp_txs_invalid_2_and_8_2_and_16_16_1::generate(std::vector<test_event_e { const size_t mixin = 10; const uint64_t amounts_paid[] = {1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = {{rct::RangeProofMultiOutputBulletproof, 0}, {rct::RangeProofMultiOutputBulletproof, 0}, {rct::RangeProofMultiOutputBulletproof, 0}}; + const rct::RCTConfig rct_config[] = {{rct::RangeProofMultiOutputBulletproof, 3}, {rct::RangeProofMultiOutputBulletproof, 3}, {rct::RangeProofMultiOutputBulletproof, 3}}; return generate_with(events, mixin, 3, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, NULL); } @@ -300,7 +300,7 @@ bool gen_bp_txs_valid_2_and_3_and_2_and_4::generate(std::vector<test_event_entry { const size_t mixin = 10; const uint64_t amounts_paid[] = {11111115000, 11111115000, (uint64_t)-1, 11111115000, 11111115000, 11111115001, (uint64_t)-1, 11111115000, 11111115002, (uint64_t)-1, 11111115000, 11111115000, 11111115000, 11111115003, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = {{rct::RangeProofPaddedBulletproof, 0}, {rct::RangeProofPaddedBulletproof, 0}, {rct::RangeProofPaddedBulletproof, 0}, {rct::RangeProofPaddedBulletproof, 0}}; + const rct::RCTConfig rct_config[] = {{rct::RangeProofPaddedBulletproof, 3}, {rct::RangeProofPaddedBulletproof, 3}, {rct::RangeProofPaddedBulletproof, 3}, {rct::RangeProofPaddedBulletproof, 3}}; const size_t bp_sizes[] = {2, (size_t)-1, 4, (size_t)-1, 2, (size_t)-1, 4, (size_t)-1}; return generate_with(events, mixin, 4, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx) { return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_3_and_2_and_4"); }); } @@ -310,7 +310,7 @@ bool gen_bp_tx_invalid_not_enough_proofs::generate(std::vector<test_event_entry> DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_not_enough_proofs"); const size_t mixin = 10; const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 3 } }; return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, [&](cryptonote::transaction &tx, size_t idx){ CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG); CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty()); @@ -325,7 +325,7 @@ bool gen_bp_tx_invalid_empty_proofs::generate(std::vector<test_event_entry>& eve DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_empty_proofs"); const size_t mixin = 10; const uint64_t amounts_paid[] = {50000, 50000, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 3 } }; return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, [&](cryptonote::transaction &tx, size_t idx){ CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG); tx.rct_signatures.p.bulletproofs.clear(); @@ -338,7 +338,7 @@ bool gen_bp_tx_invalid_too_many_proofs::generate(std::vector<test_event_entry>& DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_too_many_proofs"); const size_t mixin = 10; const uint64_t amounts_paid[] = {10000, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 3 } }; return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, [&](cryptonote::transaction &tx, size_t idx){ CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG); CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty()); @@ -352,7 +352,7 @@ bool gen_bp_tx_invalid_wrong_amount::generate(std::vector<test_event_entry>& eve DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_wrong_amount"); const size_t mixin = 10; const uint64_t amounts_paid[] = {10000, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 3 } }; return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, [&](cryptonote::transaction &tx, size_t idx){ CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG); CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty()); @@ -366,7 +366,7 @@ bool gen_bp_tx_invalid_borromean_type::generate(std::vector<test_event_entry>& e DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_borromean_type"); const size_t mixin = 10; const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; - const rct::RCTConfig rct_config[] = { { rct::RangeProofBorromean, 0 } }; + const rct::RCTConfig rct_config[] = { { rct::RangeProofBorromean, 3 } }; return generate_with(events, mixin, 1, amounts_paid, false, rct_config, 11, NULL, [&](cryptonote::transaction &tx, size_t tx_idx){ return true; }); @@ -382,3 +382,14 @@ bool gen_bp_tx_invalid_bulletproof2_type::generate(std::vector<test_event_entry> return true; }); } + +bool gen_bp_tx_invalid_clsag_type::generate(std::vector<test_event_entry>& events) const +{ + DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_clsag_type"); + const size_t mixin = 10; + const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; + const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 3 } }; + return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS + 1, NULL, [&](cryptonote::transaction &tx, size_t tx_idx){ + return true; + }); +} diff --git a/tests/core_tests/bulletproofs.h b/tests/core_tests/bulletproofs.h index b30d82e68..56c83f522 100644 --- a/tests/core_tests/bulletproofs.h +++ b/tests/core_tests/bulletproofs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -211,3 +211,9 @@ struct gen_bp_tx_invalid_bulletproof2_type : public gen_bp_tx_validation_base bool generate(std::vector<test_event_entry>& events) const; }; template<> struct get_test_options<gen_bp_tx_invalid_bulletproof2_type>: public get_bp_versioned_test_options<HF_VERSION_CLSAG + 1> {}; + +struct gen_bp_tx_invalid_clsag_type : public gen_bp_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_bp_tx_invalid_clsag_type>: public get_bp_versioned_test_options<HF_VERSION_BULLETPROOF_PLUS + 1> {}; diff --git a/tests/core_tests/chain_split_1.cpp b/tests/core_tests/chain_split_1.cpp index 640ccfcc6..db3eca591 100644 --- a/tests/core_tests/chain_split_1.cpp +++ b/tests/core_tests/chain_split_1.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/chain_split_1.h b/tests/core_tests/chain_split_1.h index 59c7c4bd3..10d9eb78f 100644 --- a/tests/core_tests/chain_split_1.h +++ b/tests/core_tests/chain_split_1.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/chain_switch_1.cpp b/tests/core_tests/chain_switch_1.cpp index d0d04d1c9..5765b7d1f 100644 --- a/tests/core_tests/chain_switch_1.cpp +++ b/tests/core_tests/chain_switch_1.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/chain_switch_1.h b/tests/core_tests/chain_switch_1.h index c7ba83502..9a50d10cf 100644 --- a/tests/core_tests/chain_switch_1.h +++ b/tests/core_tests/chain_switch_1.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index d1aeef488..61195c7b0 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -462,7 +462,9 @@ bool init_output_indices(map_output_idx_t& outs, std::map<uint64_t, std::vector< size_t tx_global_idx = outs[out.amount].size() - 1; outs[out.amount][tx_global_idx].idx = tx_global_idx; // Is out to me? - if (is_out_to_acc(from.get_keys(), boost::get<txout_to_key>(out.target), get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), j)) { + crypto::public_key output_public_key; + cryptonote::get_output_public_key(out, output_public_key); + if (is_out_to_acc(from.get_keys(), output_public_key, get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), j)) { outs_mine[out.amount].push_back(tx_global_idx); } } @@ -972,7 +974,7 @@ std::vector<cryptonote::tx_destination_entry> build_dsts(std::initializer_list<d bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins, const account_public_address& miner_address, transaction& tx, uint64_t fee, - keypair* p_txkey/* = 0*/) + uint8_t hf_version/* = 1*/, keypair* p_txkey/* = 0*/) { keypair txkey; txkey = keypair::generate(hw::get_device("default")); @@ -987,7 +989,7 @@ bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins // This will work, until size of constructed block is less then CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE uint64_t block_reward; - if (!get_block_reward(0, 0, already_generated_coins, block_reward, 1)) + if (!get_block_reward(0, 0, already_generated_coins, block_reward, hf_version)) { LOG_PRINT_L0("Block is too big"); return false; @@ -999,12 +1001,20 @@ bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation); crypto::derive_public_key(derivation, 0, miner_address.m_spend_public_key, out_eph_public_key); + bool use_view_tags = hf_version >= HF_VERSION_VIEW_TAGS; + crypto::view_tag view_tag; + if (use_view_tags) + crypto::derive_view_tag(derivation, 0, view_tag); + tx_out out; - out.amount = block_reward; - out.target = txout_to_key(out_eph_public_key); + cryptonote::set_tx_out(block_reward, out_eph_public_key, use_view_tags, view_tag, out); + tx.vout.push_back(out); - tx.version = 1; + if (hf_version >= HF_VERSION_DYNAMIC_FEE) + tx.version = 2; + else + tx.version = 1; tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW; return true; diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index a1101a3b1..5c8c9f79f 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -423,7 +423,8 @@ uint64_t sum_amount(const std::vector<cryptonote::tx_source_entry>& sources); bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins, const cryptonote::account_public_address& miner_address, cryptonote::transaction& tx, - uint64_t fee, cryptonote::keypair* p_txkey = nullptr); + uint64_t fee, uint8_t hf_version = 1, + cryptonote::keypair* p_txkey = nullptr); bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote::transaction& tx, const cryptonote::block& blk_head, const cryptonote::account_base& from, const var_addr_t& to, uint64_t amount, @@ -967,12 +968,14 @@ inline bool do_replay_file(const std::string& filename) std::list<cryptonote::transaction> SET_NAME; \ MAKE_TX_MIX_LIST_RCT(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD); -#define MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, KEY) \ +#define MAKE_MINER_TX_AND_KEY_AT_HF_MANUALLY(TX, BLK, HF_VERSION, KEY) \ transaction TX; \ if (!construct_miner_tx_manually(get_block_height(BLK) + 1, generator.get_already_generated_coins(BLK), \ - miner_account.get_keys().m_account_address, TX, 0, KEY)) \ + miner_account.get_keys().m_account_address, TX, 0, HF_VERSION, KEY)) \ return false; +#define MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, KEY) MAKE_MINER_TX_AND_KEY_AT_HF_MANUALLY(TX, BLK, 1, KEY) + #define MAKE_MINER_TX_MANUALLY(TX, BLK) MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, 0) #define SET_EVENT_VISITOR_SETT(VEC_EVENTS, SETT) VEC_EVENTS.push_back(event_visitor_settings(SETT)); diff --git a/tests/core_tests/chaingen001.cpp b/tests/core_tests/chaingen001.cpp index 6d1741b06..43d2f5501 100644 --- a/tests/core_tests/chaingen001.cpp +++ b/tests/core_tests/chaingen001.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index c55154917..b89dff445 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -35,6 +35,8 @@ #include "tx_pool.h" #include "transaction_tests.h" +#include <boost/regex.hpp> + namespace po = boost::program_options; namespace @@ -131,6 +133,10 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_block_miner_tx_out_is_big); GENERATE_AND_PLAY(gen_block_miner_tx_has_no_out); GENERATE_AND_PLAY(gen_block_miner_tx_has_out_to_alice); + GENERATE_AND_PLAY(gen_block_miner_tx_out_has_no_view_tag_before_hf_view_tags); + GENERATE_AND_PLAY(gen_block_miner_tx_out_has_no_view_tag_from_hf_view_tags); + GENERATE_AND_PLAY(gen_block_miner_tx_out_has_view_tag_before_hf_view_tags); + GENERATE_AND_PLAY(gen_block_miner_tx_out_has_view_tag_from_hf_view_tags); GENERATE_AND_PLAY(gen_block_has_invalid_tx); GENERATE_AND_PLAY(gen_block_is_too_big); GENERATE_AND_PLAY(gen_block_invalid_binary_format); // Takes up to 3 hours, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 500, up to 30 minutes, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10 @@ -217,6 +223,15 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_rct_tx_pre_rct_increase_vin_and_fee); GENERATE_AND_PLAY(gen_rct_tx_pre_rct_altered_extra); GENERATE_AND_PLAY(gen_rct_tx_rct_altered_extra); + GENERATE_AND_PLAY(gen_rct_tx_pre_rct_has_no_view_tag_before_hf_view_tags); + // TODO: base test needs to be restructured to handle pre rct outputs after HF v12 + // GENERATE_AND_PLAY(gen_rct_tx_pre_rct_has_no_view_tag_from_hf_view_tags); + GENERATE_AND_PLAY(gen_rct_tx_pre_rct_has_view_tag_before_hf_view_tags); + // GENERATE_AND_PLAY(gen_rct_tx_pre_rct_has_view_tag_from_hf_view_tags); + GENERATE_AND_PLAY(gen_rct_tx_rct_has_no_view_tag_before_hf_view_tags); + GENERATE_AND_PLAY(gen_rct_tx_rct_has_no_view_tag_from_hf_view_tags); + GENERATE_AND_PLAY(gen_rct_tx_rct_has_view_tag_before_hf_view_tags); + GENERATE_AND_PLAY(gen_rct_tx_rct_has_view_tag_from_hf_view_tags); GENERATE_AND_PLAY(gen_rct_tx_uses_output_too_early); GENERATE_AND_PLAY(gen_multisig_tx_valid_22_1_2); @@ -265,6 +280,24 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_bp_tx_invalid_wrong_amount); GENERATE_AND_PLAY(gen_bp_tx_invalid_borromean_type); GENERATE_AND_PLAY(gen_bp_tx_invalid_bulletproof2_type); + GENERATE_AND_PLAY(gen_bp_tx_invalid_clsag_type); + + GENERATE_AND_PLAY(gen_bpp_tx_invalid_before_fork); + GENERATE_AND_PLAY(gen_bpp_tx_valid_at_fork); + GENERATE_AND_PLAY(gen_bpp_tx_invalid_1_1); + GENERATE_AND_PLAY(gen_bpp_tx_valid_2); + GENERATE_AND_PLAY(gen_bpp_tx_valid_3); + GENERATE_AND_PLAY(gen_bpp_tx_valid_16); + GENERATE_AND_PLAY(gen_bpp_tx_invalid_4_2_1); + GENERATE_AND_PLAY(gen_bpp_tx_invalid_16_16); + GENERATE_AND_PLAY(gen_bpp_txs_valid_2_and_2); + GENERATE_AND_PLAY(gen_bpp_txs_invalid_2_and_8_2_and_16_16_1); + GENERATE_AND_PLAY(gen_bpp_txs_valid_2_and_3_and_2_and_4); + GENERATE_AND_PLAY(gen_bpp_tx_invalid_not_enough_proofs); + GENERATE_AND_PLAY(gen_bpp_tx_invalid_empty_proofs); + GENERATE_AND_PLAY(gen_bpp_tx_invalid_too_many_proofs); + GENERATE_AND_PLAY(gen_bpp_tx_invalid_wrong_amount); + GENERATE_AND_PLAY(gen_bpp_tx_invalid_clsag_type); GENERATE_AND_PLAY(gen_rct2_tx_clsag_malleability); diff --git a/tests/core_tests/chaingen_tests_list.h b/tests/core_tests/chaingen_tests_list.h index db78c3e41..13fc52632 100644 --- a/tests/core_tests/chaingen_tests_list.h +++ b/tests/core_tests/chaingen_tests_list.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -43,6 +43,7 @@ #include "rct.h" #include "multisig.h" #include "bulletproofs.h" +#include "bulletproof_plus.h" #include "rct2.h" /************************************************************************/ /* */ diff --git a/tests/core_tests/double_spend.cpp b/tests/core_tests/double_spend.cpp index 04a7a6921..4750f82e3 100644 --- a/tests/core_tests/double_spend.cpp +++ b/tests/core_tests/double_spend.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/double_spend.h b/tests/core_tests/double_spend.h index 9f00348aa..6dccd6a0c 100644 --- a/tests/core_tests/double_spend.h +++ b/tests/core_tests/double_spend.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/double_spend.inl b/tests/core_tests/double_spend.inl index 22af95a37..59460e674 100644 --- a/tests/core_tests/double_spend.inl +++ b/tests/core_tests/double_spend.inl @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/integer_overflow.cpp b/tests/core_tests/integer_overflow.cpp index 5cb5a7959..31853ca24 100644 --- a/tests/core_tests/integer_overflow.cpp +++ b/tests/core_tests/integer_overflow.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/integer_overflow.h b/tests/core_tests/integer_overflow.h index 384178bbd..2c8ac9251 100644 --- a/tests/core_tests/integer_overflow.h +++ b/tests/core_tests/integer_overflow.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/multisig.cpp b/tests/core_tests/multisig.cpp index 73bc1f104..58d60fd90 100644 --- a/tests/core_tests/multisig.cpp +++ b/tests/core_tests/multisig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -81,9 +81,7 @@ static bool make_multisig_accounts(std::vector<cryptonote::account_base> &accoun for (std::size_t account_index{0}; account_index < accounts.size(); ++account_index) { multisig_accounts[account_index].initialize_kex(threshold, signers, round_msgs); - - if (!multisig_accounts[account_index].multisig_is_ready()) - temp_round_msgs[account_index] = multisig_accounts[account_index].get_next_kex_round_msg(); + temp_round_msgs[account_index] = multisig_accounts[account_index].get_next_kex_round_msg(); } // perform key exchange rounds @@ -94,9 +92,7 @@ static bool make_multisig_accounts(std::vector<cryptonote::account_base> &accoun for (std::size_t account_index{0}; account_index < multisig_accounts.size(); ++account_index) { multisig_accounts[account_index].kex_update(round_msgs); - - if (!multisig_accounts[account_index].multisig_is_ready()) - temp_round_msgs[account_index] = multisig_accounts[account_index].get_next_kex_round_msg(); + temp_round_msgs[account_index] = multisig_accounts[account_index].get_next_kex_round_msg(); } } @@ -165,7 +161,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry account_base &account = n < inputs ? miner_account[creator] : miner_accounts[n]; CHECK_AND_ASSERT_MES(generator.construct_block_manually(blocks[n], *prev_block, account, test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_max_outs, - 10, 10, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long + HF_VERSION_BULLETPROOF_PLUS, HF_VERSION_BULLETPROOF_PLUS, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 1, 4), false, "Failed to generate block"); events.push_back(blocks[n]); @@ -181,7 +177,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry cryptonote::block blk; CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_accounts[0], test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_max_outs, - 10, 10, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long + HF_VERSION_BULLETPROOF_PLUS, HF_VERSION_BULLETPROOF_PLUS, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 1, 4), false, "Failed to generate block"); events.push_back(blk); @@ -339,6 +335,11 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry td.amount = amount_paid; std::vector<tx_destination_entry> destinations; destinations.push_back(td); + cryptonote::account_base dummy; + dummy.generate(); + td.addr = dummy.get_keys().m_account_address; + td.amount = 0; + destinations.push_back(td); if (pre_tx) pre_tx(sources, destinations); @@ -353,7 +354,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry #endif std::vector<crypto::secret_key> additional_tx_secret_keys; auto sources_copy = sources; - r = construct_tx_and_get_tx_key(miner_account[creator].get_keys(), subaddresses, sources, destinations, boost::none, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_secret_keys, true, { rct::RangeProofPaddedBulletproof, 2 }, msoutp); + r = construct_tx_and_get_tx_key(miner_account[creator].get_keys(), subaddresses, sources, destinations, boost::none, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_secret_keys, true, { rct::RangeProofPaddedBulletproof, 0 }, msoutp); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); #ifndef NO_MULTISIG @@ -443,8 +444,10 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry crypto::secret_key scalar1; crypto::derivation_to_scalar(derivation, n, scalar1); rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n]; - rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG); + rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus); rct::key C = tx.rct_signatures.outPk[n].mask; + if (rct::is_rct_bulletproof_plus(tx.rct_signatures.type)) + C = rct::scalarmult8(C); rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H); CHECK_AND_ASSERT_MES(rct::equalKeys(C, Ctmp), false, "Failed to decode amount"); amount += rct::h2d(ecdh_info.amount); diff --git a/tests/core_tests/multisig.h b/tests/core_tests/multisig.h index 333c4fe38..e9a2cf5f3 100644 --- a/tests/core_tests/multisig.h +++ b/tests/core_tests/multisig.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -82,7 +82,7 @@ private: template<> struct get_test_options<gen_multisig_tx_validation_base> { - const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(10, 1), std::make_pair(0, 0)}; + const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(HF_VERSION_BULLETPROOF_PLUS, 1), std::make_pair(0, 0)}; const cryptonote::test_options test_options = { hard_forks, 0 }; diff --git a/tests/core_tests/rct.cpp b/tests/core_tests/rct.cpp index 6ce99e76e..0926483fe 100644 --- a/tests/core_tests/rct.cpp +++ b/tests/core_tests/rct.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -41,7 +41,7 @@ using namespace cryptonote; // Tests bool gen_rct_tx_validation_base::generate_with_full(std::vector<test_event_entry>& events, - const int *out_idx, int mixin, uint64_t amount_paid, size_t second_rewind, uint8_t last_version, const rct::RCTConfig &rct_config, bool valid, + const int *out_idx, int mixin, uint64_t amount_paid, size_t second_rewind, uint8_t last_version, const rct::RCTConfig &rct_config, bool use_view_tags, bool valid, const std::function<void(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations)> &pre_tx, const std::function<void(transaction &tx)> &post_tx) const { @@ -98,7 +98,9 @@ bool gen_rct_tx_validation_base::generate_with_full(std::vector<test_event_entry const size_t index_in_tx = 5; src.amount = 30000000000000; for (int m = 0; m < 4; ++m) { - src.push_output(m, boost::get<txout_to_key>(blocks[m].miner_tx.vout[index_in_tx].target).key, src.amount); + crypto::public_key output_public_key; + cryptonote::get_output_public_key(blocks[m].miner_tx.vout[index_in_tx], output_public_key); + src.push_output(m, output_public_key, src.amount); } src.real_out_tx_key = cryptonote::get_tx_pub_key_from_extra(blocks[n].miner_tx); src.real_output = n; @@ -133,16 +135,19 @@ bool gen_rct_tx_validation_base::generate_with_full(std::vector<test_event_entry crypto::secret_key amount_key; crypto::derivation_to_scalar(derivation, o, amount_key); const uint8_t type = rct_txes[n].rct_signatures.type; - if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2 || type == rct::RCTTypeCLSAG) + if (rct::is_rct_simple(type)) rct::decodeRctSimple(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4], hw::get_device("default")); else rct::decodeRct(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4], hw::get_device("default")); } + uint64_t fee = 0; + get_tx_fee(rct_txes[n], fee); + CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes[n], blk_last, miner_account, - test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_tx_hashes | test_generator::bf_hf_version | test_generator::bf_max_outs, + test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_tx_hashes | test_generator::bf_hf_version | test_generator::bf_max_outs | test_generator::bf_tx_fees, 4, 4, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long - crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 6, 4), + crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 6, 4, fee), false, "Failed to generate block"); events.push_back(blk_txes[n]); blk_last = blk_txes[n]; @@ -224,7 +229,7 @@ bool gen_rct_tx_validation_base::generate_with_full(std::vector<test_event_entry std::vector<crypto::secret_key> additional_tx_keys; std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; subaddresses[miner_accounts[0].get_keys().m_account_address.m_spend_public_key] = {0,0}; - bool r = construct_tx_and_get_tx_key(miner_accounts[0].get_keys(), subaddresses, sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_keys, true, rct_config); + bool r = construct_tx_and_get_tx_key(miner_accounts[0].get_keys(), subaddresses, sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_keys, true, rct_config, NULL, use_view_tags); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); if (post_tx) @@ -244,7 +249,8 @@ bool gen_rct_tx_validation_base::generate_with(std::vector<test_event_entry>& ev const std::function<void(transaction &tx)> &post_tx) const { const rct::RCTConfig rct_config { rct::RangeProofBorromean, 0 }; - return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, 4, rct_config, valid, pre_tx, post_tx); + bool use_view_tags = false; + return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, 4, rct_config, use_view_tags, valid, pre_tx, post_tx); } bool gen_rct_tx_valid_from_pre_rct::generate(std::vector<test_event_entry>& events) const @@ -517,11 +523,99 @@ bool gen_rct_tx_rct_altered_extra::generate(std::vector<test_event_entry>& event NULL, [&failed](transaction &tx) {std::string extra_nonce; crypto::hash pid = crypto::null_hash; set_payment_id_to_tx_extra_nonce(extra_nonce, pid); if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) failed = true; }) && !failed; } +bool gen_rct_tx_pre_rct_has_no_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + const int mixin = 2; + const int out_idx[] = {0, -1}; + const uint64_t amount_paid = 10000; + bool use_view_tags = false; + bool valid = true; + return generate_with_full(events, out_idx, mixin, amount_paid, 0, 0, {}, use_view_tags, valid, NULL, NULL); +} + +bool gen_rct_tx_pre_rct_has_no_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + const int mixin = 10; + const int out_idx[] = {0, -1}; + const uint64_t amount_paid = 10000; + const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 3 }; + bool use_view_tags = false; + bool valid = false; + return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, HF_VERSION_VIEW_TAGS, rct_config, use_view_tags, valid, NULL, NULL); +} + +bool gen_rct_tx_pre_rct_has_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + const int mixin = 2; + const int out_idx[] = {0, -1}; + const uint64_t amount_paid = 10000; + bool use_view_tags = true; + bool valid = false; + return generate_with_full(events, out_idx, mixin, amount_paid, 0, 0, {}, use_view_tags, valid, NULL, NULL); +} + +bool gen_rct_tx_pre_rct_has_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + const int mixin = 10; + const int out_idx[] = {0, -1}; + const uint64_t amount_paid = 10000; + const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 3 }; + bool use_view_tags = true; + bool valid = true; + return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, HF_VERSION_VIEW_TAGS, rct_config, use_view_tags, valid, NULL, NULL); +} + +bool gen_rct_tx_rct_has_no_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + const int mixin = 2; + const int out_idx[] = {1, -1}; + const uint64_t amount_paid = 10000; + const rct::RCTConfig rct_config { rct::RangeProofBorromean, 0 }; + bool use_view_tags = false; + bool valid = true; + return generate_with_full(events, out_idx, mixin, amount_paid, 0, 0, rct_config, use_view_tags, valid, NULL, NULL); +} + +bool gen_rct_tx_rct_has_no_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + const int mixin = 10; + const int out_idx[] = {1, -1}; + const uint64_t amount_paid = 10000; + const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 3 }; + bool use_view_tags = false; + bool valid = false; + return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, HF_VERSION_VIEW_TAGS+1, rct_config, use_view_tags, valid, NULL, NULL); +} + +bool gen_rct_tx_rct_has_view_tag_before_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + const int mixin = 2; + const int out_idx[] = {1, -1}; + const uint64_t amount_paid = 10000; + const rct::RCTConfig rct_config { rct::RangeProofBorromean, 0 }; + bool use_view_tags = true; + bool valid = false; + return generate_with_full(events, out_idx, mixin, amount_paid, 0, 0, rct_config, use_view_tags, valid, NULL, NULL); +} + +bool gen_rct_tx_rct_has_view_tag_from_hf_view_tags::generate(std::vector<test_event_entry>& events) const +{ + const int mixin = 10; + const int out_idx[] = {1, -1}; + const uint64_t amount_paid = 10000; + const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 3 }; + bool use_view_tags = true; + bool valid = true; + return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, HF_VERSION_VIEW_TAGS, rct_config, use_view_tags, valid, NULL, NULL); +} + bool gen_rct_tx_uses_output_too_early::generate(std::vector<test_event_entry>& events) const { const int mixin = 10; const int out_idx[] = {1, -1}; const uint64_t amount_paid = 10000; const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 2 }; - return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE-3, HF_VERSION_ENFORCE_MIN_AGE, rct_config, false, NULL, NULL); + bool use_view_tags = false; + bool valid = false; + return generate_with_full(events, out_idx, mixin, amount_paid, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE-3, HF_VERSION_ENFORCE_MIN_AGE, rct_config, use_view_tags, valid, NULL, NULL); } diff --git a/tests/core_tests/rct.h b/tests/core_tests/rct.h index 0aaa93c94..c20e8a580 100644 --- a/tests/core_tests/rct.h +++ b/tests/core_tests/rct.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -70,7 +70,7 @@ struct gen_rct_tx_validation_base : public test_chain_unit_base } bool generate_with_full(std::vector<test_event_entry>& events, const int *out_idx, int mixin, - uint64_t amount_paid, size_t second_rewind, uint8_t last_version, const rct::RCTConfig &rct_config, bool valid, + uint64_t amount_paid, size_t second_rewind, uint8_t last_version, const rct::RCTConfig &rct_config, bool use_view_tags, bool valid, const std::function<void(std::vector<cryptonote::tx_source_entry> &sources, std::vector<cryptonote::tx_destination_entry> &destinations)> &pre_tx, const std::function<void(cryptonote::transaction &tx)> &post_tx) const; bool generate_with(std::vector<test_event_entry>& events, const int *out_idx, int mixin, @@ -266,6 +266,74 @@ struct gen_rct_tx_rct_altered_extra : public gen_rct_tx_validation_base }; template<> struct get_test_options<gen_rct_tx_rct_altered_extra>: public get_test_options<gen_rct_tx_validation_base> {}; +struct gen_rct_tx_pre_rct_has_no_view_tag_before_hf_view_tags : public gen_rct_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_rct_tx_pre_rct_has_no_view_tag_before_hf_view_tags>: public get_test_options<gen_rct_tx_validation_base> {}; + +struct gen_rct_tx_pre_rct_has_no_view_tag_from_hf_view_tags : public gen_rct_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_rct_tx_pre_rct_has_no_view_tag_from_hf_view_tags> { + const std::pair<uint8_t, uint64_t> hard_forks[5] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(HF_VERSION_VIEW_TAGS, 69), std::make_pair(0, 0)}; + const cryptonote::test_options test_options = { + hard_forks, 0 + }; +}; + +struct gen_rct_tx_pre_rct_has_view_tag_before_hf_view_tags : public gen_rct_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_rct_tx_pre_rct_has_view_tag_before_hf_view_tags>: public get_test_options<gen_rct_tx_validation_base> {}; + +struct gen_rct_tx_pre_rct_has_view_tag_from_hf_view_tags : public gen_rct_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_rct_tx_pre_rct_has_view_tag_from_hf_view_tags> { + const std::pair<uint8_t, uint64_t> hard_forks[5] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(HF_VERSION_VIEW_TAGS, 69), std::make_pair(0, 0)}; + const cryptonote::test_options test_options = { + hard_forks, 0 + }; +}; + +struct gen_rct_tx_rct_has_no_view_tag_before_hf_view_tags : public gen_rct_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_rct_tx_rct_has_no_view_tag_before_hf_view_tags>: public get_test_options<gen_rct_tx_validation_base> {}; + +struct gen_rct_tx_rct_has_no_view_tag_from_hf_view_tags : public gen_rct_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_rct_tx_rct_has_no_view_tag_from_hf_view_tags> { + const std::pair<uint8_t, uint64_t> hard_forks[5] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(HF_VERSION_VIEW_TAGS+1, 69), std::make_pair(0, 0)}; + const cryptonote::test_options test_options = { + hard_forks, 0 + }; +}; + +struct gen_rct_tx_rct_has_view_tag_before_hf_view_tags : public gen_rct_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_rct_tx_rct_has_view_tag_before_hf_view_tags>: public get_test_options<gen_rct_tx_validation_base> {}; + +struct gen_rct_tx_rct_has_view_tag_from_hf_view_tags : public gen_rct_tx_validation_base +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> struct get_test_options<gen_rct_tx_rct_has_view_tag_from_hf_view_tags> { + const std::pair<uint8_t, uint64_t> hard_forks[5] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(HF_VERSION_VIEW_TAGS, 69), std::make_pair(0, 0)}; + const cryptonote::test_options test_options = { + hard_forks, 0 + }; +}; + struct gen_rct_tx_uses_output_too_early : public gen_rct_tx_validation_base { bool generate(std::vector<test_event_entry>& events) const; diff --git a/tests/core_tests/rct2.cpp b/tests/core_tests/rct2.cpp index 8d7c4b3eb..d98cbd453 100644 --- a/tests/core_tests/rct2.cpp +++ b/tests/core_tests/rct2.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -158,7 +158,7 @@ bool gen_rct2_tx_validation_base::generate_with(std::vector<test_event_entry>& e crypto::derivation_to_scalar(derivation, o, amount_key); rct::key rct_tx_mask; const uint8_t type = rct_txes.back().rct_signatures.type; - if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2 || type == rct::RCTTypeCLSAG) + if (rct::is_rct_simple(type)) rct::decodeRctSimple(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default")); else rct::decodeRct(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default")); diff --git a/tests/core_tests/rct2.h b/tests/core_tests/rct2.h index 2fe9d6113..c85bd44a2 100644 --- a/tests/core_tests/rct2.h +++ b/tests/core_tests/rct2.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/ring_signature_1.cpp b/tests/core_tests/ring_signature_1.cpp index b4a7d8853..e6a76179e 100644 --- a/tests/core_tests/ring_signature_1.cpp +++ b/tests/core_tests/ring_signature_1.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/ring_signature_1.h b/tests/core_tests/ring_signature_1.h index 10e0ab9ee..47592732f 100644 --- a/tests/core_tests/ring_signature_1.h +++ b/tests/core_tests/ring_signature_1.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp index efd294336..0f8df5030 100644 --- a/tests/core_tests/transaction_tests.cpp +++ b/tests/core_tests/transaction_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/transaction_tests.h b/tests/core_tests/transaction_tests.h index e74d48296..15cb5df7b 100644 --- a/tests/core_tests/transaction_tests.h +++ b/tests/core_tests/transaction_tests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/tx_pool.cpp b/tests/core_tests/tx_pool.cpp index 166eb6075..fab40a972 100644 --- a/tests/core_tests/tx_pool.cpp +++ b/tests/core_tests/tx_pool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/tx_pool.h b/tests/core_tests/tx_pool.h index 1fbdcadf1..5155454f8 100644 --- a/tests/core_tests/tx_pool.h +++ b/tests/core_tests/tx_pool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/tx_validation.cpp b/tests/core_tests/tx_validation.cpp index 244763988..b2b742b93 100644 --- a/tests/core_tests/tx_validation.cpp +++ b/tests/core_tests/tx_validation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/tx_validation.h b/tests/core_tests/tx_validation.h index 5f91f1291..929d61f66 100644 --- a/tests/core_tests/tx_validation.h +++ b/tests/core_tests/tx_validation.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/v2_tests.cpp b/tests/core_tests/v2_tests.cpp index 8baf5eb0a..68db46f51 100644 --- a/tests/core_tests/v2_tests.cpp +++ b/tests/core_tests/v2_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/v2_tests.h b/tests/core_tests/v2_tests.h index 23a6c43b6..b812e32e2 100644 --- a/tests/core_tests/v2_tests.h +++ b/tests/core_tests/v2_tests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/core_tests/wallet_tools.h b/tests/core_tests/wallet_tools.h index 03db04c99..982862d45 100644 --- a/tests/core_tests/wallet_tools.h +++ b/tests/core_tests/wallet_tools.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/crypto/CMakeLists.txt b/tests/crypto/CMakeLists.txt index c8ea5a604..f364ada84 100644 --- a/tests/crypto/CMakeLists.txt +++ b/tests/crypto/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/crypto/cnv4-jit.c b/tests/crypto/cnv4-jit.c index ac5bc0f52..23f3c3cb1 100644 --- a/tests/crypto/cnv4-jit.c +++ b/tests/crypto/cnv4-jit.c @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/crypto/crypto-ops-data.c b/tests/crypto/crypto-ops-data.c index 0f187a3ea..eeb3a3253 100644 --- a/tests/crypto/crypto-ops-data.c +++ b/tests/crypto/crypto-ops-data.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/crypto/crypto-ops.c b/tests/crypto/crypto-ops.c index 576b6e4b5..0203484de 100644 --- a/tests/crypto/crypto-ops.c +++ b/tests/crypto/crypto-ops.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/crypto/crypto-tests.h b/tests/crypto/crypto-tests.h index 29a50e0fb..661ba5854 100644 --- a/tests/crypto/crypto-tests.h +++ b/tests/crypto/crypto-tests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/crypto/crypto.cpp b/tests/crypto/crypto.cpp index e1be38054..b6ddf9f01 100644 --- a/tests/crypto/crypto.cpp +++ b/tests/crypto/crypto.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/crypto/hash.c b/tests/crypto/hash.c index 680f2c4b4..fc2c1594d 100644 --- a/tests/crypto/hash.c +++ b/tests/crypto/hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/crypto/main.cpp b/tests/crypto/main.cpp index 5486937c2..045ffc08d 100644 --- a/tests/crypto/main.cpp +++ b/tests/crypto/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -260,7 +260,6 @@ int main(int argc, char *argv[]) { goto error; } } else if (cmd == "check_ge_p3_identity") { - cerr << "Testing: " << cmd << endl; public_key point; bool expected_bad, expected_good, result_badfunc, result_goodfunc; get(input, point, expected_bad, expected_good); @@ -269,6 +268,15 @@ int main(int argc, char *argv[]) { if (expected_bad != result_badfunc || expected_good != result_goodfunc) { goto error; } + } else if (cmd == "derive_view_tag") { + key_derivation derivation; + size_t output_index; + view_tag expected, actual; + get(input, derivation, output_index, expected); + derive_view_tag(derivation, output_index, actual); + if (expected != actual) { + goto error; + } } else { throw ios_base::failure("Unknown function: " + cmd); } diff --git a/tests/crypto/random.c b/tests/crypto/random.c index eff3b9bbe..09268a029 100644 --- a/tests/crypto/random.c +++ b/tests/crypto/random.c @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/crypto/tests.txt b/tests/crypto/tests.txt index 3a7fe5453..d387aa09d 100644 --- a/tests/crypto/tests.txt +++ b/tests/crypto/tests.txt @@ -5473,3 +5473,59 @@ check_ge_p3_identity 046e1450f147f3ade34d149973913cc75d4e7b9669eb1ed61da0f1d4a0b check_ge_p3_identity ca8a2f621cfc7aa3efcd7ddf55dce5352e757b38aca0869b050c0a27824e5c5e true true check_ge_p3_identity 64a247eef6087d86e1e9fa048a3c181fdb1728431f29ba738634bdc38f02a859 true true check_ge_p3_identity cff0c7170a41395b0658ee42b76545c45360736b973ab2f31f6f227b9415df67 true true +derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 0 76 +derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 1 d6 +derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 2 87 +derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 3 1b +derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 12 d6 +derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 13 e9 +derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 14 12 +derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 15 26 +derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 0 70 +derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 1 81 +derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 2 a0 +derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 3 ec +derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 12 22 +derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 13 0a +derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 14 87 +derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 15 76 +derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 0 93 +derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 1 67 +derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 2 9d +derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 3 2d +derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 12 63 +derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 13 cf +derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 14 ef +derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 15 10 +derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 0 90 +derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 1 5a +derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 2 de +derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 3 21 +derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 12 57 +derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 13 52 +derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 14 6f +derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 15 eb +derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 0 c6 +derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 1 60 +derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 2 f0 +derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 3 71 +derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 12 0e +derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 13 42 +derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 14 b2 +derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 15 61 +derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 0 4c +derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 1 9b +derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 2 64 +derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 3 ff +derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 12 e3 +derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 13 24 +derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 14 ea +derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 15 3b +derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 0 74 +derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 1 77 +derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 2 a9 +derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 3 44 +derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 12 75 +derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 13 05 +derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 14 ca +derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 15 00 diff --git a/tests/cryptolib.pl b/tests/cryptolib.pl index 42604c782..4fa08263c 100644 --- a/tests/cryptolib.pl +++ b/tests/cryptolib.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/cryptotest.pl b/tests/cryptotest.pl index b5d4dd2df..19376a4e5 100644 --- a/tests/cryptotest.pl +++ b/tests/cryptotest.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/daemon_tests/CMakeLists.txt b/tests/daemon_tests/CMakeLists.txt index a3fce119d..3e8caa22a 100644 --- a/tests/daemon_tests/CMakeLists.txt +++ b/tests/daemon_tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/daemon_tests/transfers.cpp b/tests/daemon_tests/transfers.cpp index 5afe93457..3baa99ec6 100644 --- a/tests/daemon_tests/transfers.cpp +++ b/tests/daemon_tests/transfers.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/difficulty/CMakeLists.txt b/tests/difficulty/CMakeLists.txt index 231038440..db35f87ce 100644 --- a/tests/difficulty/CMakeLists.txt +++ b/tests/difficulty/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/difficulty/difficulty.cpp b/tests/difficulty/difficulty.cpp index aee17e9d5..09b6371ed 100644 --- a/tests/difficulty/difficulty.cpp +++ b/tests/difficulty/difficulty.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/functional_tests/CMakeLists.txt b/tests/functional_tests/CMakeLists.txt index 337097a34..5511cab1c 100644 --- a/tests/functional_tests/CMakeLists.txt +++ b/tests/functional_tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/address_book.py b/tests/functional_tests/address_book.py index 37a5915c9..396ce505e 100755 --- a/tests/functional_tests/address_book.py +++ b/tests/functional_tests/address_book.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 #encoding=utf-8 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/bans.py b/tests/functional_tests/bans.py index 3e265a11e..96d4c0aeb 100755 --- a/tests/functional_tests/bans.py +++ b/tests/functional_tests/bans.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/blockchain.py b/tests/functional_tests/blockchain.py index b8f8bac1a..328c225ff 100755 --- a/tests/functional_tests/blockchain.py +++ b/tests/functional_tests/blockchain.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Monero Project +# Copyright (c) 2018-2022, The Monero Project + # # All rights reserved. # @@ -80,10 +81,10 @@ class BlockchainTest(): assert ok res = daemon.get_fee_estimate() - assert res.fee == 234562 + assert res.fee == 1200000 assert res.quantization_mask == 10000 res = daemon.get_fee_estimate(10) - assert res.fee <= 234562 + assert res.fee <= 1200000 # generate blocks res_generateblocks = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', blocks) @@ -242,10 +243,10 @@ class BlockchainTest(): assert res.histogram[i].recent_instances == 0 res = daemon.get_fee_estimate() - assert res.fee == 234560 + assert res.fee == 1200000 assert res.quantization_mask == 10000 res = daemon.get_fee_estimate(10) - assert res.fee <= 234560 + assert res.fee <= 1200000 def _test_alt_chains(self): print('Testing alt chains') diff --git a/tests/functional_tests/cold_signing.py b/tests/functional_tests/cold_signing.py index 35e00e105..31d5780bb 100755 --- a/tests/functional_tests/cold_signing.py +++ b/tests/functional_tests/cold_signing.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # @@ -101,7 +101,7 @@ class ColdSigningTest(): res = self.cold_wallet.export_key_images(True) self.hot_wallet.import_key_images(res.signed_key_images, offset = res.offset) - res = self.hot_wallet.transfer([dst], ring_size = 11, get_tx_key = False) + res = self.hot_wallet.transfer([dst], ring_size = 16, get_tx_key = False) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 0 @@ -121,7 +121,7 @@ class ColdSigningTest(): desc = res.desc[0] assert desc.amount_in >= amount + fee assert desc.amount_out == desc.amount_in - fee - assert desc.ring_size == 11 + assert desc.ring_size == 16 assert desc.unlock_time == 0 assert desc.payment_id in ['', '0000000000000000'] assert desc.change_amount == desc.amount_in - 1000000000000 - fee diff --git a/tests/functional_tests/cpu_power_test.cpp b/tests/functional_tests/cpu_power_test.cpp index 54c4bfc9f..372bd891b 100644 --- a/tests/functional_tests/cpu_power_test.cpp +++ b/tests/functional_tests/cpu_power_test.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2021, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/functional_tests/daemon_info.py b/tests/functional_tests/daemon_info.py index 14fc14062..116e6b73d 100755 --- a/tests/functional_tests/daemon_info.py +++ b/tests/functional_tests/daemon_info.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Monero Project +# Copyright (c) 2018-2022, The Monero Project + # # All rights reserved. # diff --git a/tests/functional_tests/get_output_distribution.py b/tests/functional_tests/get_output_distribution.py index 24b6e9008..43c7b4a74 100755 --- a/tests/functional_tests/get_output_distribution.py +++ b/tests/functional_tests/get_output_distribution.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/integrated_address.py b/tests/functional_tests/integrated_address.py index c3b730de0..d4b7cd2ff 100755 --- a/tests/functional_tests/integrated_address.py +++ b/tests/functional_tests/integrated_address.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # @@ -80,13 +80,11 @@ class IntegratedAddressTest(): except: fails += 1 try: wallet.make_integrated_address(standard_address = '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', payment_id = '112233445566778') except: fails += 1 - try: wallet.make_integrated_address(standard_address = '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', payment_id = '') - except: fails += 1 try: wallet.make_integrated_address(standard_address = '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', payment_id = '112233445566778g') except: fails += 1 try: wallet.make_integrated_address(standard_address = '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', payment_id = '1122334455667788112233445566778811223344556677881122334455667788') except: fails += 1 - assert fails == 5 + assert fails == 4 print('Checking bad standard address') fails = 0 diff --git a/tests/functional_tests/main.cpp b/tests/functional_tests/main.cpp index 8d140f721..41c55e4d4 100644 --- a/tests/functional_tests/main.cpp +++ b/tests/functional_tests/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -51,7 +51,7 @@ namespace const command_line::arg_descriptor<std::string> arg_daemon_addr_b = {"daemon-addr-b", "", "127.0.0.1:8082"}; const command_line::arg_descriptor<uint64_t> arg_transfer_amount = {"transfer_amount", "", 60000000000000}; - const command_line::arg_descriptor<size_t> arg_mix_in_factor = {"mix-in-factor", "", 10}; + const command_line::arg_descriptor<size_t> arg_mix_in_factor = {"mix-in-factor", "", 15}; const command_line::arg_descriptor<size_t> arg_tx_count = {"tx-count", "", 100}; const command_line::arg_descriptor<size_t> arg_tx_per_second = {"tx-per-second", "", 20}; const command_line::arg_descriptor<size_t> arg_test_repeat_count = {"test_repeat_count", "", 1}; diff --git a/tests/functional_tests/make_test_signature.cc b/tests/functional_tests/make_test_signature.cc index cb1723847..e9dab8bd4 100644 --- a/tests/functional_tests/make_test_signature.cc +++ b/tests/functional_tests/make_test_signature.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/functional_tests/mining.py b/tests/functional_tests/mining.py index 7ecbdeed5..f1aa15c14 100755 --- a/tests/functional_tests/mining.py +++ b/tests/functional_tests/mining.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Monero Project +# Copyright (c) 2018-2022, The Monero Project + # # All rights reserved. # diff --git a/tests/functional_tests/multisig.py b/tests/functional_tests/multisig.py index bb7ccbe56..89cb2fdc7 100755 --- a/tests/functional_tests/multisig.py +++ b/tests/functional_tests/multisig.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # @@ -44,7 +44,7 @@ class MultisigTest(): self.mine('41mro238grj56GnrWkakAKTkBy2yDcXYsUZ2iXCM9pe5Ueajd2RRc6Fhh3uBXT2UAKhAsUJ7Fg5zjjF2U1iGciFk5ief4ZP', 5) self.mine('44vZSprQKJQRFe6t1VHgU4ESvq2dv7TjBLVGE7QscKxMdFSiyyPCEV64NnKUQssFPyWxc2meyt7j63F2S2qtCTRL6dakeff', 5) self.mine('47puypSwsV1gvUDratmX4y58fSwikXVehEiBhVLxJA1gRCxHyrRgTDr4NnKUQssFPyWxc2meyt7j63F2S2qtCTRL6aRPj5U', 5) - self.mine('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 60) + self.mine('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80) self.test_states() @@ -125,17 +125,18 @@ class MultisigTest(): for i in range(N_total): res = self.wallet[i].is_multisig() assert res.multisig == True - assert res.ready == (M_threshold == N_total) + assert not res.ready assert res.threshold == M_threshold assert res.total == N_total while True: - n_empty = 0 - for i in range(len(next_stage)): - if len(next_stage[i]) == 0: - n_empty += 1 - assert n_empty == 0 or n_empty == len(next_stage) - if n_empty == len(next_stage): + n_ready = 0 + for i in range(N_total): + res = self.wallet[i].is_multisig() + if res.ready == True: + n_ready += 1 + assert n_ready == 0 or n_ready == N_total + if n_ready == N_total: break info = next_stage next_stage = [] @@ -162,54 +163,72 @@ class MultisigTest(): 'peeled mixture ionic radar utopia puddle buying illness nuns gadget river spout cavernous bounced paradise drunk looking cottage jump tequila melting went winter adjust spout', 'dilute gutter certain antics pamphlet macro enjoy left slid guarded bogeys upload nineteen bomb jubilee enhanced irritate turnip eggs swung jukebox loudly reduce sedan slid', ] - info = [] - wallet = [None, None, None] - for i in range(3): - wallet[i] = Wallet(idx = i) - try: wallet[i].close_wallet() + info2of2 = [] + wallet2of2 = [None, None] + for i in range(2): + wallet2of2[i] = Wallet(idx = i) + try: wallet2of2[i].close_wallet() except: pass - res = wallet[i].restore_deterministic_wallet(seed = seeds[i]) - res = wallet[i].is_multisig() + res = wallet2of2[i].restore_deterministic_wallet(seed = seeds[i]) + res = wallet2of2[i].is_multisig() assert not res.multisig - res = wallet[i].prepare_multisig() + res = wallet2of2[i].prepare_multisig() assert len(res.multisig_info) > 0 - info.append(res.multisig_info) - - for i in range(3): - ok = False - try: res = wallet[i].exchange_multisig_keys(info) - except: ok = True - assert ok - res = wallet[i].is_multisig() - assert not res.multisig - - res = wallet[0].make_multisig(info[0:2], 2) - res = wallet[0].is_multisig() + info2of2.append(res.multisig_info) + + kex_info = [] + res = wallet2of2[0].make_multisig(info2of2, 2) + kex_info.append(res.multisig_info) + res = wallet2of2[1].make_multisig(info2of2, 2) + kex_info.append(res.multisig_info) + res = wallet2of2[0].exchange_multisig_keys(kex_info) + res = wallet2of2[0].is_multisig() assert res.multisig assert res.ready ok = False - try: res = wallet[0].prepare_multisig() + try: res = wallet2of2[0].prepare_multisig() except: ok = True assert ok ok = False - try: res = wallet[0].make_multisig(info[0:2], 2) + try: res = wallet2of2[0].make_multisig(info2of2, 2) except: ok = True assert ok - res = wallet[1].make_multisig(info, 2) - res = wallet[1].is_multisig() + info2of3 = [] + wallet2of3 = [None, None, None] + for i in range(3): + wallet2of3[i] = Wallet(idx = i) + try: wallet2of3[i].close_wallet() + except: pass + res = wallet2of3[i].restore_deterministic_wallet(seed = seeds[i]) + res = wallet2of3[i].is_multisig() + assert not res.multisig + res = wallet2of3[i].prepare_multisig() + assert len(res.multisig_info) > 0 + info2of3.append(res.multisig_info) + + for i in range(3): + ok = False + try: res = wallet2of3[i].exchange_multisig_keys(info) + except: ok = True + assert ok + res = wallet2of3[i].is_multisig() + assert not res.multisig + + res = wallet2of3[1].make_multisig(info2of3, 2) + res = wallet2of3[1].is_multisig() assert res.multisig assert not res.ready ok = False - try: res = wallet[1].prepare_multisig() + try: res = wallet2of3[1].prepare_multisig() except: ok = True assert ok ok = False - try: res = wallet[1].make_multisig(info[0:2], 2) + try: res = wallet2of3[1].make_multisig(info2of3[0:2], 2) except: ok = True assert ok @@ -261,7 +280,7 @@ class MultisigTest(): desc = res.desc[0] assert desc.amount_in >= amount + fee assert desc.amount_out == desc.amount_in - fee - assert desc.ring_size == 11 + assert desc.ring_size == 16 assert desc.unlock_time == 0 assert not 'payment_id' in desc or desc.payment_id in ['', '0000000000000000'] assert desc.change_amount == desc.amount_in - 1000000000000 - fee diff --git a/tests/functional_tests/p2p.py b/tests/functional_tests/p2p.py index 0b33411f9..ec2206aa8 100755 --- a/tests/functional_tests/p2p.py +++ b/tests/functional_tests/p2p.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Monero Project +# Copyright (c) 2018-2022, The Monero Project + # # All rights reserved. # diff --git a/tests/functional_tests/proofs.py b/tests/functional_tests/proofs.py index e58d29f94..fe734d697 100755 --- a/tests/functional_tests/proofs.py +++ b/tests/functional_tests/proofs.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/rpc_payment.py b/tests/functional_tests/rpc_payment.py index d0f9c2913..ab478436c 100755 --- a/tests/functional_tests/rpc_payment.py +++ b/tests/functional_tests/rpc_payment.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/sign_message.py b/tests/functional_tests/sign_message.py index dbb7cfd6d..ea342aa7c 100755 --- a/tests/functional_tests/sign_message.py +++ b/tests/functional_tests/sign_message.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/speed.py b/tests/functional_tests/speed.py index c0c1d23c2..5b942bb06 100755 --- a/tests/functional_tests/speed.py +++ b/tests/functional_tests/speed.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Monero Project +# Copyright (c) 2018-2022, The Monero Project + # # All rights reserved. # diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp index 3f5f90d3b..41cf1bea5 100644 --- a/tests/functional_tests/transactions_flow_test.cpp +++ b/tests/functional_tests/transactions_flow_test.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/functional_tests/transactions_flow_test.h b/tests/functional_tests/transactions_flow_test.h index 8e2dfd92c..33a513bd2 100644 --- a/tests/functional_tests/transactions_flow_test.h +++ b/tests/functional_tests/transactions_flow_test.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/functional_tests/transactions_generation_from_blockchain.cpp b/tests/functional_tests/transactions_generation_from_blockchain.cpp index 3ba401529..fa4c19982 100644 --- a/tests/functional_tests/transactions_generation_from_blockchain.cpp +++ b/tests/functional_tests/transactions_generation_from_blockchain.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/functional_tests/transactions_generation_from_blockchain.h b/tests/functional_tests/transactions_generation_from_blockchain.h index 70a2486d6..2fe14f4ef 100644 --- a/tests/functional_tests/transactions_generation_from_blockchain.h +++ b/tests/functional_tests/transactions_generation_from_blockchain.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py index 07a24546e..dd15369d3 100755 --- a/tests/functional_tests/transfer.py +++ b/tests/functional_tests/transfer.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # @@ -82,11 +82,11 @@ class TransferTest(): res = daemon.get_info() height = res.height - daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80) + daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 100) for i in range(len(self.wallet)): self.wallet[i].refresh() res = self.wallet[i].get_height() - assert res.height == height + 80 + assert res.height == height + 100 def transfer(self): daemon = Daemon() @@ -110,23 +110,23 @@ class TransferTest(): print ('Checking short payment IDs cannot be used when not in an integrated address') ok = False - try: self.wallet[0].transfer([dst], ring_size = 11, payment_id = '1234567812345678', get_tx_key = False) + try: self.wallet[0].transfer([dst], ring_size = 16, payment_id = '1234567812345678', get_tx_key = False) except: ok = True assert ok print ('Checking long payment IDs are rejected') ok = False - try: self.wallet[0].transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False, get_tx_hex = True) + try: self.wallet[0].transfer([dst], ring_size = 16, payment_id = payment_id, get_tx_key = False, get_tx_hex = True) except: ok = True assert ok print ('Checking empty destination is rejected') ok = False - try: self.wallet[0].transfer([], ring_size = 11, get_tx_key = False) + try: self.wallet[0].transfer([], ring_size = 16, get_tx_key = False) except: ok = True assert ok - res = self.wallet[0].transfer([dst], ring_size = 11, get_tx_key = False, get_tx_hex = True) + res = self.wallet[0].transfer([dst], ring_size = 16, get_tx_key = False, get_tx_hex = True) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 0 @@ -231,7 +231,7 @@ class TransferTest(): print("Creating transfer to another, manual relay") dst = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1000000000000} - res = self.wallet[0].transfer([dst], ring_size = 11, get_tx_key = True, do_not_relay = True, get_tx_hex = True) + res = self.wallet[0].transfer([dst], ring_size = 16, get_tx_key = True, do_not_relay = True, get_tx_hex = True) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 32*2 @@ -321,7 +321,7 @@ class TransferTest(): dst0 = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} dst1 = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1100000000000} dst2 = {'address': '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', 'amount': 1200000000000} - res = self.wallet[0].transfer([dst0, dst1, dst2], ring_size = 11, get_tx_key = True) + res = self.wallet[0].transfer([dst0, dst1, dst2], ring_size = 16, get_tx_key = True) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 32*2 diff --git a/tests/functional_tests/txpool.py b/tests/functional_tests/txpool.py index e886200da..e92b5a530 100755 --- a/tests/functional_tests/txpool.py +++ b/tests/functional_tests/txpool.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/uri.py b/tests/functional_tests/uri.py index 4d79c6b82..1fefbb87d 100755 --- a/tests/functional_tests/uri.py +++ b/tests/functional_tests/uri.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 #encoding=utf-8 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/util_resources.py b/tests/functional_tests/util_resources.py index 0ea96c129..e030312da 100755 --- a/tests/functional_tests/util_resources.py +++ b/tests/functional_tests/util_resources.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 -# Copyright (c) 2021 The Monero Project +# Copyright (c) 2021-2022, The Monero Project + # # All rights reserved. # diff --git a/tests/functional_tests/validate_address.py b/tests/functional_tests/validate_address.py index d201cdf68..eb6ebbe91 100755 --- a/tests/functional_tests/validate_address.py +++ b/tests/functional_tests/validate_address.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/functional_tests/wallet.py b/tests/functional_tests/wallet.py index 91164daf9..1ad05c98f 100755 --- a/tests/functional_tests/wallet.py +++ b/tests/functional_tests/wallet.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 #encoding=utf-8 -# Copyright (c) 2019-2020 The Monero Project +# Copyright (c) 2019-2022, The Monero Project # # All rights reserved. # diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt index 0cf1740ad..e42c6d2a7 100644 --- a/tests/fuzz/CMakeLists.txt +++ b/tests/fuzz/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/fuzz/base58.cpp b/tests/fuzz/base58.cpp index 3a06353ec..b873381f7 100644 --- a/tests/fuzz/base58.cpp +++ b/tests/fuzz/base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/block.cpp b/tests/fuzz/block.cpp index f8be29842..c02c22e54 100644 --- a/tests/fuzz/block.cpp +++ b/tests/fuzz/block.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/bulletproof.cpp b/tests/fuzz/bulletproof.cpp index 06416fe34..49c068ed6 100644 --- a/tests/fuzz/bulletproof.cpp +++ b/tests/fuzz/bulletproof.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/cold-outputs.cpp b/tests/fuzz/cold-outputs.cpp index 69eb7b61f..a7e8a6530 100644 --- a/tests/fuzz/cold-outputs.cpp +++ b/tests/fuzz/cold-outputs.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/cold-transaction.cpp b/tests/fuzz/cold-transaction.cpp index bf5fba1f7..91cce1ac9 100644 --- a/tests/fuzz/cold-transaction.cpp +++ b/tests/fuzz/cold-transaction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/fuzzer.cpp b/tests/fuzz/fuzzer.cpp index eaaef5aa5..18fdc1c7e 100644 --- a/tests/fuzz/fuzzer.cpp +++ b/tests/fuzz/fuzzer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/fuzzer.h b/tests/fuzz/fuzzer.h index f45e69f73..cc30e765b 100644 --- a/tests/fuzz/fuzzer.h +++ b/tests/fuzz/fuzzer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/http-client.cpp b/tests/fuzz/http-client.cpp index 65df24a3f..7858d4d16 100644 --- a/tests/fuzz/http-client.cpp +++ b/tests/fuzz/http-client.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/levin.cpp b/tests/fuzz/levin.cpp index 209a75221..d86f6b940 100644 --- a/tests/fuzz/levin.cpp +++ b/tests/fuzz/levin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/load_from_binary.cpp b/tests/fuzz/load_from_binary.cpp index 6d6826e2e..f2d4ba78f 100644 --- a/tests/fuzz/load_from_binary.cpp +++ b/tests/fuzz/load_from_binary.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/load_from_json.cpp b/tests/fuzz/load_from_json.cpp index 8788a92b6..ceb8d0800 100644 --- a/tests/fuzz/load_from_json.cpp +++ b/tests/fuzz/load_from_json.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/parse_url.cpp b/tests/fuzz/parse_url.cpp index cc1323eb5..f0f11ac01 100644 --- a/tests/fuzz/parse_url.cpp +++ b/tests/fuzz/parse_url.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/signature.cpp b/tests/fuzz/signature.cpp index 443057a57..77575ffb5 100644 --- a/tests/fuzz/signature.cpp +++ b/tests/fuzz/signature.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/transaction.cpp b/tests/fuzz/transaction.cpp index 94f0a849f..2eaf7b9eb 100644 --- a/tests/fuzz/transaction.cpp +++ b/tests/fuzz/transaction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/fuzz/tx-extra.cpp b/tests/fuzz/tx-extra.cpp index 35b14b802..161114e04 100644 --- a/tests/fuzz/tx-extra.cpp +++ b/tests/fuzz/tx-extra.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/fuzz/utf8.cpp b/tests/fuzz/utf8.cpp index bf304a351..aa03dc269 100644 --- a/tests/fuzz/utf8.cpp +++ b/tests/fuzz/utf8.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/hash-target.cpp b/tests/hash-target.cpp index 038eaab47..94af9203d 100644 --- a/tests/hash-target.cpp +++ b/tests/hash-target.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/hash/CMakeLists.txt b/tests/hash/CMakeLists.txt index 1d7d4cc5e..118e0e726 100644 --- a/tests/hash/CMakeLists.txt +++ b/tests/hash/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/hash/main.cpp b/tests/hash/main.cpp index bf612684c..3cae92a83 100644 --- a/tests/hash/main.cpp +++ b/tests/hash/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/io.h b/tests/io.h index f5e2b518d..9b2a298c5 100644 --- a/tests/io.h +++ b/tests/io.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/libwallet_api_tests/CMakeLists.txt b/tests/libwallet_api_tests/CMakeLists.txt index 1c7a7cae4..c4ec443c1 100644 --- a/tests/libwallet_api_tests/CMakeLists.txt +++ b/tests/libwallet_api_tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index 8413d8621..806f8afc2 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/net_load_tests/CMakeLists.txt b/tests/net_load_tests/CMakeLists.txt index c334df4ba..71c04fa3a 100644 --- a/tests/net_load_tests/CMakeLists.txt +++ b/tests/net_load_tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/net_load_tests/clt.cpp b/tests/net_load_tests/clt.cpp index b55f73971..6149de653 100644 --- a/tests/net_load_tests/clt.cpp +++ b/tests/net_load_tests/clt.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/net_load_tests/net_load_tests.h b/tests/net_load_tests/net_load_tests.h index 59eef7bd1..06e42b38d 100644 --- a/tests/net_load_tests/net_load_tests.h +++ b/tests/net_load_tests/net_load_tests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/net_load_tests/srv.cpp b/tests/net_load_tests/srv.cpp index fabe14f49..1fd2224ab 100644 --- a/tests/net_load_tests/srv.cpp +++ b/tests/net_load_tests/srv.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt index 542d204e0..c079afe3a 100644 --- a/tests/performance_tests/CMakeLists.txt +++ b/tests/performance_tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -43,9 +43,11 @@ set(performance_tests_headers generate_keypair.h signature.h is_out_to_acc.h + out_can_be_to_acc.h subaddress_expand.h range_proof.h bulletproof.h + bulletproof_plus.h crypto_ops.h sc_reduce32.h sc_check.h diff --git a/tests/performance_tests/bulletproof.h b/tests/performance_tests/bulletproof.h index 835d518f6..3a147f2f4 100644 --- a/tests/performance_tests/bulletproof.h +++ b/tests/performance_tests/bulletproof.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/include/INode.h b/tests/performance_tests/bulletproof_plus.h index 8ad8d03a1..9aad61065 100644 --- a/include/INode.h +++ b/tests/performance_tests/bulletproof_plus.h @@ -30,34 +30,70 @@ #pragma once -#include <cstdint> -#include <system_error> +#include "ringct/rctSigs.h" +#include "ringct/bulletproofs_plus.h" -namespace CryptoNote { - -class INodeObserver { +template<bool a_verify, size_t n_amounts> +class test_bulletproof_plus +{ public: - virtual void initCompleted(std::error_code result) {} + static const size_t approx_loop_count = 100 / n_amounts; + static const size_t loop_count = (approx_loop_count >= 10 ? approx_loop_count : 10) / (a_verify ? 1 : 5); + static const bool verify = a_verify; + + bool init() + { + proof = rct::bulletproof_plus_PROVE(std::vector<uint64_t>(n_amounts, 749327532984), rct::skvGen(n_amounts)); + return true; + } - virtual void peerCountUpdated(size_t count) {} - virtual void lastLocalBlockHeightUpdated(uint64_t height) {} - virtual void lastKnownBlockHeightUpdated(uint64_t height) {} + bool test() + { + bool ret = true; + if (verify) + ret = rct::bulletproof_plus_VERIFY(proof); + else + rct::bulletproof_plus_PROVE(std::vector<uint64_t>(n_amounts, 749327532984), rct::skvGen(n_amounts)); + return ret; + } - virtual void blockchainReorganized(uint64_t height) {} +private: + rct::BulletproofPlus proof; }; -class INode { +template<bool batch, size_t start, size_t repeat, size_t mul, size_t add, size_t N> +class test_aggregated_bulletproof_plus +{ public: - virtual ~INode() = 0; - virtual void addObserver(INodeObserver* observer) = 0; - virtual void removeObserver(INodeObserver* observer) = 0; + static const size_t loop_count = 500 / (N * repeat); - virtual void init() = 0; - virtual void shutdown() = 0; + bool init() + { + size_t o = start; + for (size_t n = 0; n < N; ++n) + { + for (size_t i = 0; i < repeat; ++i) + proofs.push_back(rct::bulletproof_plus_PROVE(std::vector<uint64_t>(o, 749327532984), rct::skvGen(o))); + o = o * mul + add; + } + return true; + } - virtual size_t getPeerCount() = 0; - virtual uint64_t getLastLocalBlockHeight() = 0; - virtual uint64_t getLastKnownBlockHeight() = 0; -}; + bool test() + { + if (batch) + { + return rct::bulletproof_plus_VERIFY(proofs); + } + else + { + for (const rct::BulletproofPlus &proof: proofs) + if (!rct::bulletproof_plus_VERIFY(proof)) + return false; + return true; + } + } -} +private: + std::vector<rct::BulletproofPlus> proofs; +}; diff --git a/tests/performance_tests/check_hash.h b/tests/performance_tests/check_hash.h index 09737defb..174865bd4 100644 --- a/tests/performance_tests/check_hash.h +++ b/tests/performance_tests/check_hash.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/check_tx_signature.h b/tests/performance_tests/check_tx_signature.h index 5122336e7..b542f91b1 100644 --- a/tests/performance_tests/check_tx_signature.h +++ b/tests/performance_tests/check_tx_signature.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/cn_fast_hash.h b/tests/performance_tests/cn_fast_hash.h index f2177232f..bba051ace 100644 --- a/tests/performance_tests/cn_fast_hash.h +++ b/tests/performance_tests/cn_fast_hash.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/cn_slow_hash.h b/tests/performance_tests/cn_slow_hash.h index e124e00b0..2cb3dbba5 100644 --- a/tests/performance_tests/cn_slow_hash.h +++ b/tests/performance_tests/cn_slow_hash.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/construct_tx.h b/tests/performance_tests/construct_tx.h index 6bf7a82ef..00bd75b40 100644 --- a/tests/performance_tests/construct_tx.h +++ b/tests/performance_tests/construct_tx.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/crypto_ops.h b/tests/performance_tests/crypto_ops.h index 9db2e413a..6ef1641dc 100644 --- a/tests/performance_tests/crypto_ops.h +++ b/tests/performance_tests/crypto_ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/derive_public_key.h b/tests/performance_tests/derive_public_key.h index 7980d2cd4..b36d35a6b 100644 --- a/tests/performance_tests/derive_public_key.h +++ b/tests/performance_tests/derive_public_key.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/derive_secret_key.h b/tests/performance_tests/derive_secret_key.h index f395d0ccf..0697e076d 100644 --- a/tests/performance_tests/derive_secret_key.h +++ b/tests/performance_tests/derive_secret_key.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/src/p2p/stdafx.h b/tests/performance_tests/derive_view_tag.h index a689b1c15..ee4efb16d 100644 --- a/src/p2p/stdafx.h +++ b/tests/performance_tests/derive_view_tag.h @@ -1,21 +1,21 @@ -// Copyright (c) 2014-2020, The Monero Project -// +// Copyright (c) 2014-2021, The Monero Project +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. -// +// // 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL @@ -25,29 +25,38 @@ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #pragma once -#include "targetver.h" +#include "crypto/crypto.h" +#include "cryptonote_basic/cryptonote_basic.h" +#include "single_tx_test_base.h" -#if !defined(__GNUC__) -#define _CRTDBG_MAP_ALLOC -#include <stdlib.h> -#include <crtdbg.h> -#endif +class test_derive_view_tag : public single_tx_test_base +{ +public: + static const size_t loop_count = 10000; + bool init() + { + if (!single_tx_test_base::init()) + return false; + crypto::generate_key_derivation(m_tx_pub_key, m_bob.get_keys().m_view_secret_key, m_key_derivation); -#include <stdio.h> - - -#define BOOST_FILESYSTEM_VERSION 3 -#define ENABLE_RELEASE_LOGGING -#include "log_opt_defs.h" -#include "misc_log_ex.h" - + return true; + } + bool test() + { + crypto::view_tag view_tag; + crypto::derive_view_tag(m_key_derivation, 0, view_tag); + return true; + } +private: + crypto::key_derivation m_key_derivation; +}; diff --git a/tests/performance_tests/equality.h b/tests/performance_tests/equality.h index 1748ce096..5f548f811 100644 --- a/tests/performance_tests/equality.h +++ b/tests/performance_tests/equality.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/ge_frombytes_vartime.h b/tests/performance_tests/ge_frombytes_vartime.h index 1f70ec345..912961b50 100644 --- a/tests/performance_tests/ge_frombytes_vartime.h +++ b/tests/performance_tests/ge_frombytes_vartime.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/ge_tobytes.h b/tests/performance_tests/ge_tobytes.h index 2bcbfc9d7..a0566b081 100644 --- a/tests/performance_tests/ge_tobytes.h +++ b/tests/performance_tests/ge_tobytes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/generate_key_derivation.h b/tests/performance_tests/generate_key_derivation.h index ee6b2e4c7..bb445b235 100644 --- a/tests/performance_tests/generate_key_derivation.h +++ b/tests/performance_tests/generate_key_derivation.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/generate_key_image.h b/tests/performance_tests/generate_key_image.h index 53afd020b..e2fcb26a1 100644 --- a/tests/performance_tests/generate_key_image.h +++ b/tests/performance_tests/generate_key_image.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/generate_key_image_helper.h b/tests/performance_tests/generate_key_image_helper.h index 38ffa3e50..2fa0cb244 100644 --- a/tests/performance_tests/generate_key_image_helper.h +++ b/tests/performance_tests/generate_key_image_helper.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/generate_keypair.h b/tests/performance_tests/generate_keypair.h index 66c83162d..403157f18 100644 --- a/tests/performance_tests/generate_keypair.h +++ b/tests/performance_tests/generate_keypair.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/is_out_to_acc.h b/tests/performance_tests/is_out_to_acc.h index 023a7a13b..75d4a5c46 100644 --- a/tests/performance_tests/is_out_to_acc.h +++ b/tests/performance_tests/is_out_to_acc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -43,8 +43,9 @@ public: bool test() { - const cryptonote::txout_to_key& tx_out = boost::get<cryptonote::txout_to_key>(m_tx.vout[0].target); - return cryptonote::is_out_to_acc(m_bob.get_keys(), tx_out, m_tx_pub_key, m_additional_tx_pub_keys, 0); + crypto::public_key output_public_key; + cryptonote::get_output_public_key(m_tx.vout[0], output_public_key); + return cryptonote::is_out_to_acc(m_bob.get_keys(), output_public_key, m_tx_pub_key, m_additional_tx_pub_keys, 0); } }; diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index e59bb52fd..71c736977 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -42,6 +42,7 @@ #include "cn_slow_hash.h" #include "derive_public_key.h" #include "derive_secret_key.h" +#include "derive_view_tag.h" #include "ge_frombytes_vartime.h" #include "ge_tobytes.h" #include "generate_key_derivation.h" @@ -50,6 +51,7 @@ #include "generate_keypair.h" #include "signature.h" #include "is_out_to_acc.h" +#include "out_can_be_to_acc.h" #include "subaddress_expand.h" #include "sc_reduce32.h" #include "sc_check.h" @@ -58,6 +60,7 @@ #include "equality.h" #include "range_proof.h" #include "bulletproof.h" +#include "bulletproof_plus.h" #include "crypto_ops.h" #include "multiexp.h" #include "sig_mlsag.h" @@ -193,6 +196,9 @@ int main(int argc, char** argv) TEST_PERFORMANCE0(filter, p, test_is_out_to_acc); TEST_PERFORMANCE0(filter, p, test_is_out_to_acc_precomp); + TEST_PERFORMANCE2(filter, p, test_out_can_be_to_acc, false, true); // no view tag, owned + TEST_PERFORMANCE2(filter, p, test_out_can_be_to_acc, true, false); // use view tag, not owned + TEST_PERFORMANCE2(filter, p, test_out_can_be_to_acc, true, true); // use view tag, owned TEST_PERFORMANCE0(filter, p, test_generate_key_image_helper); TEST_PERFORMANCE0(filter, p, test_generate_key_derivation); TEST_PERFORMANCE0(filter, p, test_generate_key_image); @@ -205,6 +211,7 @@ int main(int argc, char** argv) TEST_PERFORMANCE0(filter, p, test_sc_check); TEST_PERFORMANCE1(filter, p, test_signature, false); TEST_PERFORMANCE1(filter, p, test_signature, true); + TEST_PERFORMANCE0(filter, p, test_derive_view_tag); TEST_PERFORMANCE2(filter, p, test_wallet2_expand_subaddresses, 50, 200); @@ -241,6 +248,26 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_range_proof, true); TEST_PERFORMANCE1(filter, p, test_range_proof, false); + TEST_PERFORMANCE2(filter, p, test_bulletproof_plus, true, 1); // 1 bulletproof_plus with 1 amount + TEST_PERFORMANCE2(filter, p, test_bulletproof_plus, false, 1); + + TEST_PERFORMANCE2(filter, p, test_bulletproof_plus, true, 2); // 1 bulletproof_plus with 2 amounts + TEST_PERFORMANCE2(filter, p, test_bulletproof_plus, false, 2); + + TEST_PERFORMANCE2(filter, p, test_bulletproof_plus, true, 15); // 1 bulletproof_plus with 15 amounts + TEST_PERFORMANCE2(filter, p, test_bulletproof_plus, false, 15); + + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, false, 2, 1, 1, 0, 4); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, true, 2, 1, 1, 0, 4); // 4 proofs, each with 2 amounts + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, false, 8, 1, 1, 0, 4); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, true, 8, 1, 1, 0, 4); // 4 proofs, each with 8 amounts + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, false, 1, 1, 2, 0, 4); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, true, 1, 1, 2, 0, 4); // 4 proofs with 1, 2, 4, 8 amounts + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, false, 1, 8, 1, 1, 4); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, true, 1, 8, 1, 1, 4); // 32 proofs, with 1, 2, 3, 4 amounts, 8 of each + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, false, 2, 1, 1, 0, 64); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof_plus, true, 2, 1, 1, 0, 64); // 64 proof, each with 2 amounts + TEST_PERFORMANCE2(filter, p, test_bulletproof, true, 1); // 1 bulletproof with 1 amount TEST_PERFORMANCE2(filter, p, test_bulletproof, false, 1); diff --git a/tests/performance_tests/multi_tx_test_base.h b/tests/performance_tests/multi_tx_test_base.h index 39ab6b26f..2a121a15d 100644 --- a/tests/performance_tests/multi_tx_test_base.h +++ b/tests/performance_tests/multi_tx_test_base.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/multiexp.h b/tests/performance_tests/multiexp.h index b6e86ebd4..c9abb7cb3 100644 --- a/tests/performance_tests/multiexp.h +++ b/tests/performance_tests/multiexp.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/performance_tests/out_can_be_to_acc.h b/tests/performance_tests/out_can_be_to_acc.h new file mode 100644 index 000000000..86e236b7b --- /dev/null +++ b/tests/performance_tests/out_can_be_to_acc.h @@ -0,0 +1,103 @@ +// Copyright (c) 2014-2021, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include "crypto/crypto.h" +#include "cryptonote_basic/cryptonote_basic.h" + +#include "single_tx_test_base.h" + +using namespace crypto; + +// use_view_tags: whether to enable view tag checking +// is_owned: whether the output is owned by us +template<bool use_view_tags, bool is_owned> +class test_out_can_be_to_acc : public single_tx_test_base +{ + public: + static const size_t loop_count = 1000; + + bool init() + { + if (!single_tx_test_base::init()) + return false; + + crypto::key_derivation key_derivation; + crypto::view_tag vt; + + m_output_index = 0; + m_view_secret_key = m_bob.get_keys().m_view_secret_key; + m_spend_public_key = m_bob.get_keys().m_account_address.m_spend_public_key; + + cryptonote::get_output_public_key(m_tx.vout[m_output_index], m_output_public_key); + + if (use_view_tags) + { + crypto::generate_key_derivation(m_tx_pub_key, m_view_secret_key, key_derivation); + crypto::derive_view_tag(key_derivation, m_output_index, vt); + m_view_tag_opt = vt; + } + else + m_view_tag_opt = boost::optional<crypto::view_tag>(); + + return true; + } + + bool test() + { + // include key derivation to demonstrate performance improvement when using view tags + crypto::key_derivation key_derivation; + crypto::generate_key_derivation(m_tx_pub_key, m_view_secret_key, key_derivation); + + // if using view tags, this ensures we computed the view tag properly + if (!cryptonote::out_can_be_to_acc(m_view_tag_opt, key_derivation, m_output_index)) + return false; + + // if user owns output, this tests the output public key matches the derived + if (is_owned) + { + crypto::public_key output_public_key; + crypto::derive_public_key(key_derivation, m_output_index, m_spend_public_key, output_public_key); + + if (m_output_public_key != output_public_key) + return false; + } + + return true; + } + + private: + size_t m_output_index; + crypto::secret_key m_view_secret_key; + crypto::public_key m_spend_public_key; + crypto::public_key m_output_public_key; + boost::optional<crypto::view_tag> m_view_tag_opt; +}; diff --git a/tests/performance_tests/performance_tests.h b/tests/performance_tests/performance_tests.h index 7bedfdd4e..1a423879b 100644 --- a/tests/performance_tests/performance_tests.h +++ b/tests/performance_tests/performance_tests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/performance_utils.h b/tests/performance_tests/performance_utils.h index 8617058f4..8555bb6b7 100644 --- a/tests/performance_tests/performance_utils.h +++ b/tests/performance_tests/performance_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/range_proof.h b/tests/performance_tests/range_proof.h index e1eef7343..64dc56691 100644 --- a/tests/performance_tests/range_proof.h +++ b/tests/performance_tests/range_proof.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/rct_mlsag.h b/tests/performance_tests/rct_mlsag.h index 638dd6385..4cdbcd601 100644 --- a/tests/performance_tests/rct_mlsag.h +++ b/tests/performance_tests/rct_mlsag.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/sc_check.h b/tests/performance_tests/sc_check.h index 036abf12d..fed0b2881 100644 --- a/tests/performance_tests/sc_check.h +++ b/tests/performance_tests/sc_check.h @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/performance_tests/sc_reduce32.h b/tests/performance_tests/sc_reduce32.h index 8da9f8b3d..b18bfb0e3 100644 --- a/tests/performance_tests/sc_reduce32.h +++ b/tests/performance_tests/sc_reduce32.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/sig_clsag.h b/tests/performance_tests/sig_clsag.h index c59e1e869..53c38c56b 100644 --- a/tests/performance_tests/sig_clsag.h +++ b/tests/performance_tests/sig_clsag.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/sig_mlsag.h b/tests/performance_tests/sig_mlsag.h index 89645e155..60a306753 100644 --- a/tests/performance_tests/sig_mlsag.h +++ b/tests/performance_tests/sig_mlsag.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/signature.h b/tests/performance_tests/signature.h index 44d4ad78c..632dd649b 100644 --- a/tests/performance_tests/signature.h +++ b/tests/performance_tests/signature.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/single_tx_test_base.h b/tests/performance_tests/single_tx_test_base.h index 59222be70..3700866f0 100644 --- a/tests/performance_tests/single_tx_test_base.h +++ b/tests/performance_tests/single_tx_test_base.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/performance_tests/subaddress_expand.h b/tests/performance_tests/subaddress_expand.h index 5bbf344a4..f4ed568e1 100644 --- a/tests/performance_tests/subaddress_expand.h +++ b/tests/performance_tests/subaddress_expand.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/trezor/CMakeLists.txt b/tests/trezor/CMakeLists.txt index 382d8e46f..7c8cdf776 100644 --- a/tests/trezor/CMakeLists.txt +++ b/tests/trezor/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2018, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/tests/trezor/daemon.cpp b/tests/trezor/daemon.cpp index dd9fd49ee..546a8a180 100644 --- a/tests/trezor/daemon.cpp +++ b/tests/trezor/daemon.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/trezor/daemon.h b/tests/trezor/daemon.h index 4b8094e05..3131881ce 100644 --- a/tests/trezor/daemon.h +++ b/tests/trezor/daemon.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/trezor/tools.cpp b/tests/trezor/tools.cpp index 432350cf6..1660c3986 100644 --- a/tests/trezor/tools.cpp +++ b/tests/trezor/tools.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/trezor/tools.h b/tests/trezor/tools.h index d348a5137..c163907d9 100644 --- a/tests/trezor/tools.h +++ b/tests/trezor/tools.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/trezor/trezor_tests.cpp b/tests/trezor/trezor_tests.cpp index 972a588f3..0db05760a 100644 --- a/tests/trezor/trezor_tests.cpp +++ b/tests/trezor/trezor_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/trezor/trezor_tests.h b/tests/trezor/trezor_tests.h index 67714f102..2953cc2bd 100644 --- a/tests/trezor/trezor_tests.h +++ b/tests/trezor/trezor_tests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 556e0ec40..55818dc93 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -36,6 +36,7 @@ set(unit_tests_sources block_reward.cpp bootstrap_node_selector.cpp bulletproofs.cpp + bulletproofs_plus.cpp canonical_amounts.cpp chacha.cpp checkpoints.cpp @@ -76,6 +77,7 @@ set(unit_tests_sources pruning.cpp random.cpp rolling_median.cpp + scaling_2021.cpp serialization.cpp sha256.cpp slow_memmem.cpp diff --git a/tests/unit_tests/account.cpp b/tests/unit_tests/account.cpp index 2ab2f893a..0ca16fe24 100644 --- a/tests/unit_tests/account.cpp +++ b/tests/unit_tests/account.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/address_from_url.cpp b/tests/unit_tests/address_from_url.cpp index b6b205aac..d54ec6be5 100644 --- a/tests/unit_tests/address_from_url.cpp +++ b/tests/unit_tests/address_from_url.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/aligned.cpp b/tests/unit_tests/aligned.cpp index 2b733faf2..fadf5cc41 100644 --- a/tests/unit_tests/aligned.cpp +++ b/tests/unit_tests/aligned.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/apply_permutation.cpp b/tests/unit_tests/apply_permutation.cpp index 9376dc10a..61e98b892 100644 --- a/tests/unit_tests/apply_permutation.cpp +++ b/tests/unit_tests/apply_permutation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/base58.cpp b/tests/unit_tests/base58.cpp index b7e9dfcf1..165c52a8e 100644 --- a/tests/unit_tests/base58.cpp +++ b/tests/unit_tests/base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/block_queue.cpp b/tests/unit_tests/block_queue.cpp index 01c742c11..ec191c636 100644 --- a/tests/unit_tests/block_queue.cpp +++ b/tests/unit_tests/block_queue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/block_reward.cpp b/tests/unit_tests/block_reward.cpp index 2f0ea92f3..9d06c8e86 100644 --- a/tests/unit_tests/block_reward.cpp +++ b/tests/unit_tests/block_reward.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/blockchain_db.cpp b/tests/unit_tests/blockchain_db.cpp index 29cdd73b9..17828645a 100644 --- a/tests/unit_tests/blockchain_db.cpp +++ b/tests/unit_tests/blockchain_db.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/bootstrap_node_selector.cpp b/tests/unit_tests/bootstrap_node_selector.cpp index c609d1223..ec0fc638f 100644 --- a/tests/unit_tests/bootstrap_node_selector.cpp +++ b/tests/unit_tests/bootstrap_node_selector.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/bulletproofs.cpp b/tests/unit_tests/bulletproofs.cpp index ee617938c..493eb9426 100644 --- a/tests/unit_tests/bulletproofs.cpp +++ b/tests/unit_tests/bulletproofs.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -131,7 +131,7 @@ TEST(bulletproofs, multi_splitting) } rct::ctkeyV outSk; - rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 0 }; + rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 4 }; rct::rctSig s = rct::genRctSimple(rct::zero(), sc, destinations, inamounts, outamounts, available, mixRing, amount_keys, NULL, NULL, index, outSk, rct_config, hw::get_device("default")); ASSERT_TRUE(rct::verRctSimple(s)); for (size_t i = 0; i < n_outputs; ++i) diff --git a/tests/unit_tests/bulletproofs_plus.cpp b/tests/unit_tests/bulletproofs_plus.cpp new file mode 100644 index 000000000..a64320233 --- /dev/null +++ b/tests/unit_tests/bulletproofs_plus.cpp @@ -0,0 +1,169 @@ +// Copyright (c) 2017-2020, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#include "gtest/gtest.h" + +#include "string_tools.h" +#include "ringct/rctOps.h" +#include "ringct/rctSigs.h" +#include "ringct/bulletproofs_plus.h" +#include "cryptonote_basic/blobdatatype.h" +#include "cryptonote_basic/cryptonote_format_utils.h" +#include "device/device.hpp" +#include "misc_log_ex.h" + +TEST(bulletproofs_plus, valid_zero) +{ + rct::BulletproofPlus proof = bulletproof_plus_PROVE(0, rct::skGen()); + ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof)); +} + +TEST(bulletproofs_plus, valid_max) +{ + rct::BulletproofPlus proof = bulletproof_plus_PROVE(0xffffffffffffffff, rct::skGen()); + ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof)); +} + +TEST(bulletproofs_plus, valid_random) +{ + for (int n = 0; n < 8; ++n) + { + rct::BulletproofPlus proof = bulletproof_plus_PROVE(crypto::rand<uint64_t>(), rct::skGen()); + ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof)); + } +} + +TEST(bulletproofs_plus, valid_multi_random) +{ + for (int n = 0; n < 8; ++n) + { + size_t outputs = 2 + n; + std::vector<uint64_t> amounts; + rct::keyV gamma; + for (size_t i = 0; i < outputs; ++i) + { + amounts.push_back(crypto::rand<uint64_t>()); + gamma.push_back(rct::skGen()); + } + rct::BulletproofPlus proof = bulletproof_plus_PROVE(amounts, gamma); + ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof)); + } +} + +TEST(bulletproofs_plus, valid_aggregated) +{ + static const size_t N_PROOFS = 8; + std::vector<rct::BulletproofPlus> proofs(N_PROOFS); + for (size_t n = 0; n < N_PROOFS; ++n) + { + size_t outputs = 2 + n; + std::vector<uint64_t> amounts; + rct::keyV gamma; + for (size_t i = 0; i < outputs; ++i) + { + amounts.push_back(crypto::rand<uint64_t>()); + gamma.push_back(rct::skGen()); + } + proofs[n] = bulletproof_plus_PROVE(amounts, gamma); + } + ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proofs)); +} + +TEST(bulletproofs_plus, invalid_8) +{ + rct::key invalid_amount = rct::zero(); + invalid_amount[8] = 1; + rct::BulletproofPlus proof = bulletproof_plus_PROVE(invalid_amount, rct::skGen()); + ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof)); +} + +TEST(bulletproofs_plus, invalid_31) +{ + rct::key invalid_amount = rct::zero(); + invalid_amount[31] = 1; + rct::BulletproofPlus proof = bulletproof_plus_PROVE(invalid_amount, rct::skGen()); + ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof)); +} + +static const char * const torsion_elements[] = +{ + "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "0000000000000000000000000000000000000000000000000000000000000000", + "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "0000000000000000000000000000000000000000000000000000000000000080", + "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", +}; + +TEST(bulletproofs_plus, invalid_torsion) +{ + rct::BulletproofPlus proof = bulletproof_plus_PROVE(7329838943733, rct::skGen()); + ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof)); + for (const auto &xs: torsion_elements) + { + rct::key x; + ASSERT_TRUE(epee::string_tools::hex_to_pod(xs, x)); + ASSERT_FALSE(rct::isInMainSubgroup(x)); + for (auto &k: proof.V) + { + const rct::key org_k = k; + rct::addKeys(k, org_k, x); + ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof)); + k = org_k; + } + for (auto &k: proof.L) + { + const rct::key org_k = k; + rct::addKeys(k, org_k, x); + ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof)); + k = org_k; + } + for (auto &k: proof.R) + { + const rct::key org_k = k; + rct::addKeys(k, org_k, x); + ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof)); + k = org_k; + } + const rct::key org_A = proof.A; + rct::addKeys(proof.A, org_A, x); + ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof)); + proof.A = org_A; + const rct::key org_A1 = proof.A1; + rct::addKeys(proof.A1, org_A1, x); + ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof)); + proof.A1 = org_A1; + const rct::key org_B = proof.B; + rct::addKeys(proof.B, org_B, x); + ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof)); + proof.B = org_B; + } +} diff --git a/tests/unit_tests/canonical_amounts.cpp b/tests/unit_tests/canonical_amounts.cpp index 5c141098b..5c2466b9e 100644 --- a/tests/unit_tests/canonical_amounts.cpp +++ b/tests/unit_tests/canonical_amounts.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/chacha.cpp b/tests/unit_tests/chacha.cpp index 4e434de4d..2e37f8030 100644 --- a/tests/unit_tests/chacha.cpp +++ b/tests/unit_tests/chacha.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/checkpoints.cpp b/tests/unit_tests/checkpoints.cpp index 26f2b51f7..3b36fa027 100644 --- a/tests/unit_tests/checkpoints.cpp +++ b/tests/unit_tests/checkpoints.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/command_line.cpp b/tests/unit_tests/command_line.cpp index 09c41a33c..6b9025c7c 100644 --- a/tests/unit_tests/command_line.cpp +++ b/tests/unit_tests/command_line.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/crypto.cpp b/tests/unit_tests/crypto.cpp index b550b35b0..7f926534a 100644 --- a/tests/unit_tests/crypto.cpp +++ b/tests/unit_tests/crypto.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/decompose_amount_into_digits.cpp b/tests/unit_tests/decompose_amount_into_digits.cpp index a4c850bbe..bf0e9263f 100644 --- a/tests/unit_tests/decompose_amount_into_digits.cpp +++ b/tests/unit_tests/decompose_amount_into_digits.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/device.cpp b/tests/unit_tests/device.cpp index c0e8fecc1..1f0dfaf78 100644 --- a/tests/unit_tests/device.cpp +++ b/tests/unit_tests/device.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/difficulty.cpp b/tests/unit_tests/difficulty.cpp index 008b9a94f..4c6f06b2b 100644 --- a/tests/unit_tests/difficulty.cpp +++ b/tests/unit_tests/difficulty.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/dns_resolver.cpp b/tests/unit_tests/dns_resolver.cpp index b0157bb0a..a6b733592 100644 --- a/tests/unit_tests/dns_resolver.cpp +++ b/tests/unit_tests/dns_resolver.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/epee_boosted_tcp_server.cpp b/tests/unit_tests/epee_boosted_tcp_server.cpp index 992122dd2..54d27be1b 100644 --- a/tests/unit_tests/epee_boosted_tcp_server.cpp +++ b/tests/unit_tests/epee_boosted_tcp_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/epee_levin_protocol_handler_async.cpp b/tests/unit_tests/epee_levin_protocol_handler_async.cpp index d9de99b8b..38a18695d 100644 --- a/tests/unit_tests/epee_levin_protocol_handler_async.cpp +++ b/tests/unit_tests/epee_levin_protocol_handler_async.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/epee_serialization.cpp b/tests/unit_tests/epee_serialization.cpp index 95a2b6ecd..f46630615 100644 --- a/tests/unit_tests/epee_serialization.cpp +++ b/tests/unit_tests/epee_serialization.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp index b83a809b7..1c756e77c 100644 --- a/tests/unit_tests/epee_utils.cpp +++ b/tests/unit_tests/epee_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -31,6 +31,7 @@ #include <boost/endian/conversion.hpp> #include <boost/range/algorithm/equal.hpp> #include <boost/range/algorithm_ext/iota.hpp> +#include <boost/range/iterator_range.hpp> #include <cstdint> #include <gtest/gtest.h> #include <iterator> @@ -1748,68 +1749,44 @@ TEST(parsing, isdigit) TEST(parsing, number) { - boost::string_ref val; - std::string s; - std::string::const_iterator i; + struct match_number_test_data { + std::string in_str; + std::string expect_out_str; + bool expect_is_float; + bool expect_is_signed; + }; + + // Add test cases as needed + struct match_number_test_data test_data[] = { + { "0 ", "0", false, false }, + { "000 ", "000", false, false }, + { "10x", "10", false, false }, + { "10.09/", "10.09", true, false }, + { "-1.r", "-1.", true, true }, + { "-49.;", "-49.", true, true }, + { "0.78/", "0.78", true, false }, + { "33E9$", "33E9", true, false }, + { ".34e2=", ".34e2", true, false }, + { "-9.34e-2=", "-9.34e-2", true, true }, + { "+9.34e+03=", "+9.34e+03", true, false } + }; // the parser expects another character to end the number, and accepts things // that aren't numbers, as it's meant as a pre-filter for strto* functions, // so we just check that numbers get accepted, but don't test non numbers - - s = "0 "; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "0"); - - s = "000 "; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "000"); - - s = "10x"; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "10"); - - s = "10.09/"; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "10.09"); - - s = "-1.r"; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "-1."); - - s = "-49.;"; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "-49."); - - s = "0.78/"; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "0.78"); - - s = "33E9$"; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "33E9"); - - s = ".34e2="; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, ".34e2"); - - s = "-9.34e-2="; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "-9.34e-2"); - - s = "+9.34e+03="; - i = s.begin(); - epee::misc_utils::parse::match_number(i, s.end(), val); - ASSERT_EQ(val, "+9.34e+03"); + // We set is_float/signed_val to the opposite of what we expect the result to + // make sure that match_number2 is changing the bools as expected + + for (const auto& tdata : test_data) { + std::string::const_iterator it = tdata.in_str.begin(); + boost::string_ref out_val = "<unassigned>"; + bool is_float_val = !tdata.expect_is_float; + bool is_signed_val = !tdata.expect_is_signed; + epee::misc_utils::parse::match_number2(it, tdata.in_str.end(), out_val, is_float_val, is_signed_val); + EXPECT_EQ(out_val, tdata.expect_out_str); + EXPECT_EQ(is_float_val, tdata.expect_is_float); + EXPECT_EQ(is_signed_val, tdata.expect_is_signed); + } } TEST(parsing, unicode) @@ -1818,13 +1795,44 @@ TEST(parsing, unicode) std::string s; std::string::const_iterator si; - s = "\"\""; si = s.begin(); ASSERT_TRUE(epee::misc_utils::parse::match_string(si, s.end(), bs)); ASSERT_EQ(bs, ""); - s = "\"\\u0000\""; si = s.begin(); ASSERT_TRUE(epee::misc_utils::parse::match_string(si, s.end(), bs)); ASSERT_EQ(bs, std::string(1, '\0')); - s = "\"\\u0020\""; si = s.begin(); ASSERT_TRUE(epee::misc_utils::parse::match_string(si, s.end(), bs)); ASSERT_EQ(bs, " "); - s = "\"\\u1\""; si = s.begin(); ASSERT_FALSE(epee::misc_utils::parse::match_string(si, s.end(), bs)); - s = "\"\\u12\""; si = s.begin(); ASSERT_FALSE(epee::misc_utils::parse::match_string(si, s.end(), bs)); - s = "\"\\u123\""; si = s.begin(); ASSERT_FALSE(epee::misc_utils::parse::match_string(si, s.end(), bs)); - s = "\"\\u1234\""; si = s.begin(); ASSERT_TRUE(epee::misc_utils::parse::match_string(si, s.end(), bs)); ASSERT_EQ(bs, "ሴ"); - s = "\"foo\\u1234bar\""; si = s.begin(); ASSERT_TRUE(epee::misc_utils::parse::match_string(si, s.end(), bs)); ASSERT_EQ(bs, "fooሴbar"); - s = "\"\\u3042\\u307e\\u3084\\u304b\\u3059\""; si = s.begin(); ASSERT_TRUE(epee::misc_utils::parse::match_string(si, s.end(), bs)); ASSERT_EQ(bs, "あまやかす"); + s = "\"\""; + si = s.begin(); + epee::misc_utils::parse::match_string2(si, s.end(), bs); + EXPECT_EQ(bs, ""); + + s = "\"\\u0000\""; + si = s.begin(); + epee::misc_utils::parse::match_string2(si, s.end(), bs); + EXPECT_EQ(bs, std::string(1, '\0')); + + s = "\"\\u0020\""; + si = s.begin(); + epee::misc_utils::parse::match_string2(si, s.end(), bs); + EXPECT_EQ(bs, " "); + + s = "\"\\u1\""; + si = s.begin(); + EXPECT_THROW(epee::misc_utils::parse::match_string2(si, s.end(), bs), std::runtime_error); + + s = "\"\\u12\""; + si = s.begin(); + EXPECT_THROW(epee::misc_utils::parse::match_string2(si, s.end(), bs), std::runtime_error); + + s = "\"\\u123\""; + si = s.begin(); + EXPECT_THROW(epee::misc_utils::parse::match_string2(si, s.end(), bs), std::runtime_error); + + s = "\"\\u1234\""; + si = s.begin(); + epee::misc_utils::parse::match_string2(si, s.end(), bs); + EXPECT_EQ(bs, "ሴ"); + + s = "\"foo\\u1234bar\""; si = s.begin(); + epee::misc_utils::parse::match_string2(si, s.end(), bs); + EXPECT_EQ(bs, "fooሴbar"); + + s = "\"\\u3042\\u307e\\u3084\\u304b\\u3059\""; + si = s.begin(); + epee::misc_utils::parse::match_string2(si, s.end(), bs); + EXPECT_EQ(bs, "あまやかす"); } diff --git a/tests/unit_tests/expect.cpp b/tests/unit_tests/expect.cpp index efa843496..6162ed830 100644 --- a/tests/unit_tests/expect.cpp +++ b/tests/unit_tests/expect.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/fee.cpp b/tests/unit_tests/fee.cpp index d98b9e974..39f3014a2 100644 --- a/tests/unit_tests/fee.cpp +++ b/tests/unit_tests/fee.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/get_xtype_from_string.cpp b/tests/unit_tests/get_xtype_from_string.cpp index 17492ed19..2831b65b0 100644 --- a/tests/unit_tests/get_xtype_from_string.cpp +++ b/tests/unit_tests/get_xtype_from_string.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index 912651de4..bb2632d01 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/hashchain.cpp b/tests/unit_tests/hashchain.cpp index 5d85e960c..1831d0504 100644 --- a/tests/unit_tests/hashchain.cpp +++ b/tests/unit_tests/hashchain.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/hmac_keccak.cpp b/tests/unit_tests/hmac_keccak.cpp index ec7c90dbe..e05bcca44 100644 --- a/tests/unit_tests/hmac_keccak.cpp +++ b/tests/unit_tests/hmac_keccak.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/http.cpp b/tests/unit_tests/http.cpp index df3088a8b..60afe788e 100644 --- a/tests/unit_tests/http.cpp +++ b/tests/unit_tests/http.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/json_serialization.h b/tests/unit_tests/json_serialization.h index 2d8267261..5ae97a3dd 100644 --- a/tests/unit_tests/json_serialization.h +++ b/tests/unit_tests/json_serialization.h @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/keccak.cpp b/tests/unit_tests/keccak.cpp index a869fbaec..1ebe63646 100644 --- a/tests/unit_tests/keccak.cpp +++ b/tests/unit_tests/keccak.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/levin.cpp b/tests/unit_tests/levin.cpp index 069bc19b2..60d0079b6 100644 --- a/tests/unit_tests/levin.cpp +++ b/tests/unit_tests/levin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/lmdb.cpp b/tests/unit_tests/lmdb.cpp index c37c83a32..b6a0d000c 100644 --- a/tests/unit_tests/lmdb.cpp +++ b/tests/unit_tests/lmdb.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/logging.cpp b/tests/unit_tests/logging.cpp index b3ffb9aa6..2c10f2c0a 100644 --- a/tests/unit_tests/logging.cpp +++ b/tests/unit_tests/logging.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/long_term_block_weight.cpp b/tests/unit_tests/long_term_block_weight.cpp index c0b057c9a..973055097 100644 --- a/tests/unit_tests/long_term_block_weight.cpp +++ b/tests/unit_tests/long_term_block_weight.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/main.cpp b/tests/unit_tests/main.cpp index ab14fee4e..12792bfe8 100644 --- a/tests/unit_tests/main.cpp +++ b/tests/unit_tests/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/memwipe.cpp b/tests/unit_tests/memwipe.cpp index 4f06b401e..97f003471 100644 --- a/tests/unit_tests/memwipe.cpp +++ b/tests/unit_tests/memwipe.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/mlocker.cpp b/tests/unit_tests/mlocker.cpp index c97dc2c1d..948909af8 100644 --- a/tests/unit_tests/mlocker.cpp +++ b/tests/unit_tests/mlocker.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/mnemonics.cpp b/tests/unit_tests/mnemonics.cpp index 0f9a81b46..7b778d3cf 100644 --- a/tests/unit_tests/mnemonics.cpp +++ b/tests/unit_tests/mnemonics.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/mul_div.cpp b/tests/unit_tests/mul_div.cpp index 07f48f088..1733a47f0 100644 --- a/tests/unit_tests/mul_div.cpp +++ b/tests/unit_tests/mul_div.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/multiexp.cpp b/tests/unit_tests/multiexp.cpp index 212aa0e40..8f2a3cc27 100644 --- a/tests/unit_tests/multiexp.cpp +++ b/tests/unit_tests/multiexp.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/multisig.cpp b/tests/unit_tests/multisig.cpp index 362a658de..5ddd78955 100644 --- a/tests/unit_tests/multisig.cpp +++ b/tests/unit_tests/multisig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // @@ -120,7 +120,7 @@ static void check_results(const std::vector<std::string> &intermediate_infos, for (size_t i = 0; i < wallets.size(); ++i) { - EXPECT_TRUE(intermediate_infos[i].empty()); + EXPECT_TRUE(!intermediate_infos[i].empty()); bool ready; uint32_t threshold, total; EXPECT_TRUE(wallets[i].multisig(&ready, &threshold, &total)); @@ -171,7 +171,7 @@ static void make_wallets(std::vector<tools::wallet2>& wallets, unsigned int M) { ASSERT_TRUE(wallets.size() > 1 && wallets.size() <= KEYS_COUNT); ASSERT_TRUE(M <= wallets.size()); - std::uint32_t rounds_required = multisig::multisig_kex_rounds_required(wallets.size(), M); + std::uint32_t total_rounds_required = multisig::multisig_kex_rounds_required(wallets.size(), M) + 1; std::uint32_t rounds_complete{0}; // initialize wallets, get first round multisig kex msgs @@ -203,18 +203,17 @@ static void make_wallets(std::vector<tools::wallet2>& wallets, unsigned int M) ++rounds_complete; // perform kex rounds until kex is complete - while (!intermediate_infos[0].empty()) + bool ready; + wallets[0].multisig(&ready); + while (!ready) { - bool ready{false}; - wallets[0].multisig(&ready); - EXPECT_FALSE(ready); - intermediate_infos = exchange_round(wallets, intermediate_infos); + wallets[0].multisig(&ready); ++rounds_complete; } - EXPECT_EQ(rounds_required, rounds_complete); + EXPECT_EQ(total_rounds_required, rounds_complete); check_results(intermediate_infos, wallets, M); } diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp index 2836fd948..838f1af37 100644 --- a/tests/unit_tests/net.cpp +++ b/tests/unit_tests/net.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp index 7907e9a9a..134fa6ece 100644 --- a/tests/unit_tests/node_server.cpp +++ b/tests/unit_tests/node_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp index 4de4a8d0a..8e76a3d78 100644 --- a/tests/unit_tests/notify.cpp +++ b/tests/unit_tests/notify.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/output_distribution.cpp b/tests/unit_tests/output_distribution.cpp index eec694d1e..b70fdedf8 100644 --- a/tests/unit_tests/output_distribution.cpp +++ b/tests/unit_tests/output_distribution.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/output_selection.cpp b/tests/unit_tests/output_selection.cpp index 20dc58e03..02619207e 100644 --- a/tests/unit_tests/output_selection.cpp +++ b/tests/unit_tests/output_selection.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/parse_amount.cpp b/tests/unit_tests/parse_amount.cpp index b581f8dd2..9a2a21c2b 100644 --- a/tests/unit_tests/parse_amount.cpp +++ b/tests/unit_tests/parse_amount.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/pruning.cpp b/tests/unit_tests/pruning.cpp index 83c35df68..3577c6924 100644 --- a/tests/unit_tests/pruning.cpp +++ b/tests/unit_tests/pruning.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/random.cpp b/tests/unit_tests/random.cpp index 7653453cd..926cb775a 100644 --- a/tests/unit_tests/random.cpp +++ b/tests/unit_tests/random.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 2388d647b..f3ca2b2b4 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/ringdb.cpp b/tests/unit_tests/ringdb.cpp index 0838d2bd9..b41781f51 100644 --- a/tests/unit_tests/ringdb.cpp +++ b/tests/unit_tests/ringdb.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/rolling_median.cpp b/tests/unit_tests/rolling_median.cpp index d415c5b95..07da0f0ef 100644 --- a/tests/unit_tests/rolling_median.cpp +++ b/tests/unit_tests/rolling_median.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // @@ -211,3 +211,21 @@ TEST(rolling_median, size) ASSERT_EQ(m.size(), std::min<int>(10, i + 2)); } } + +TEST(rolling_median, copy) +{ + epee::misc_utils::rolling_median_t<uint64_t> m(100); + + for (int i = 0; i < 100; ++i) + m.insert(rand()); + + epee::misc_utils::rolling_median_t<uint64_t> copy(m); + + for (int i = 0; i < 5000; ++i) + { + uint64_t v = rand(); + m.insert(v); + copy.insert(v); + ASSERT_EQ(m.median(), copy.median()); + } +} diff --git a/tests/unit_tests/rpc_version_str.cpp b/tests/unit_tests/rpc_version_str.cpp index 249d297cf..61b389a80 100644 --- a/tests/unit_tests/rpc_version_str.cpp +++ b/tests/unit_tests/rpc_version_str.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020, The Monero Project +// Copyright (c) 2019-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/scaling_2021.cpp b/tests/unit_tests/scaling_2021.cpp new file mode 100644 index 000000000..9e8d15544 --- /dev/null +++ b/tests/unit_tests/scaling_2021.cpp @@ -0,0 +1,187 @@ +// Copyright (c) 2019-2020, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// References: +// - https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021.pdf +// - https://github.com/monero-project/research-lab/issues/70 + +#define IN_UNIT_TESTS + +#include "gtest/gtest.h" +#include "cryptonote_core/blockchain.h" +#include "cryptonote_core/tx_pool.h" +#include "cryptonote_core/cryptonote_core.h" +#include "blockchain_db/testdb.h" + +namespace +{ + +class TestDB: public cryptonote::BaseTestDB +{ +public: + TestDB() { m_open = true; } +}; + +} + +#define PREFIX_WINDOW(hf_version,window) \ + std::unique_ptr<cryptonote::Blockchain> bc; \ + cryptonote::tx_memory_pool txpool(*bc); \ + bc.reset(new cryptonote::Blockchain(txpool)); \ + struct get_test_options { \ + const std::pair<uint8_t, uint64_t> hard_forks[3]; \ + const cryptonote::test_options test_options = { \ + hard_forks, \ + window, \ + }; \ + get_test_options(): hard_forks{std::make_pair(1, (uint64_t)0), std::make_pair((uint8_t)hf_version, (uint64_t)1), std::make_pair((uint8_t)0, (uint64_t)0)} {} \ + } opts; \ + cryptonote::Blockchain *blockchain = bc.get(); \ + bool r = blockchain->init(new TestDB(), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL); \ + ASSERT_TRUE(r) + +#define PREFIX(hf_version) PREFIX_WINDOW(hf_version, TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW) + +TEST(fee_2021_scaling, relay_fee_cases_from_pdf) +{ + PREFIX_WINDOW(HF_VERSION_2021_SCALING, CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE); + + ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 300000, HF_VERSION_2021_SCALING-1), 8000); + ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 300000, HF_VERSION_2021_SCALING), 38000); + ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 1425000, HF_VERSION_2021_SCALING-1), 1684 /*1680*/); + ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 1425000, HF_VERSION_2021_SCALING), 1684 /*1680*/); + ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 1500000, HF_VERSION_2021_SCALING-1), 1600); + ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 1500000, HF_VERSION_2021_SCALING), 1520); + + ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 300000, HF_VERSION_2021_SCALING-1), 4000); + ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 300000, HF_VERSION_2021_SCALING), 19000); + ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 1425000, HF_VERSION_2021_SCALING-1), 842 /*840*/); + ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 1425000, HF_VERSION_2021_SCALING), 842 /*840*/); + ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 1500000, HF_VERSION_2021_SCALING-1), 800); + ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 1500000, HF_VERSION_2021_SCALING), 760); +} + +TEST(fee_2021_scaling, wallet_fee_cases_from_pdf) +{ + PREFIX_WINDOW(HF_VERSION_2021_SCALING, CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE); + std::vector<uint64_t> fees; + + fees.clear(); + bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 300000, 300000, fees); + ASSERT_EQ(fees.size(), 4); + ASSERT_EQ(fees[0], 20000); + ASSERT_EQ(fees[1], 80000); + ASSERT_EQ(fees[2], 320000); + ASSERT_EQ(fees[3], 4000000); + + fees.clear(); + bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 15000000, 300000, fees); + ASSERT_EQ(fees.size(), 4); + ASSERT_EQ(fees[0], 20000); + ASSERT_EQ(fees[1], 80000); + ASSERT_EQ(fees[2], 320000); + ASSERT_EQ(fees[3], 1300000); + + fees.clear(); + bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 1425000, 1425000, fees); + ASSERT_EQ(fees.size(), 4); + ASSERT_EQ(fees[0], 890); + ASSERT_EQ(fees[1], 3600); + ASSERT_EQ(fees[2], 68000); + ASSERT_EQ(fees[3], 850000 /* 842000 */); + + fees.clear(); + bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 1500000, 1500000, fees); + ASSERT_EQ(fees.size(), 4); + ASSERT_EQ(fees[0], 800); + ASSERT_EQ(fees[1], 3200); + ASSERT_EQ(fees[2], 64000); + ASSERT_EQ(fees[3], 800000); + + fees.clear(); + bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 75000000, 1500000, fees); + ASSERT_EQ(fees.size(), 4); + ASSERT_EQ(fees[0], 800); + ASSERT_EQ(fees[1], 3200); + ASSERT_EQ(fees[2], 64000); + ASSERT_EQ(fees[3], 260000); +} + +TEST(fee_2021_scaling, rounding) +{ + ASSERT_EQ(cryptonote::round_money_up("27810", 3), "27900.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("37.94", 3), "38.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("0.5555", 3), "0.556000000000"); + ASSERT_EQ(cryptonote::round_money_up("0.002342", 3), "0.002350000000"); + + ASSERT_EQ(cryptonote::round_money_up("27810", 2), "28000.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("37.94", 2), "38.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("0.5555", 2), "0.560000000000"); + ASSERT_EQ(cryptonote::round_money_up("0.002342", 2), "0.002400000000"); + + ASSERT_EQ(cryptonote::round_money_up("0", 8), "0.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("0.0", 8), "0.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("50.0", 8), "50.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("0.002342", 8), "0.002342000000"); + ASSERT_EQ(cryptonote::round_money_up("0.002342", 1), "0.003000000000"); + ASSERT_EQ(cryptonote::round_money_up("12345", 8), "12345.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("45678", 1), "50000.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("1.234", 1), "2.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("1.0000001", 4), "1.001000000000"); + ASSERT_EQ(cryptonote::round_money_up("1.0020001", 4), "1.003000000000"); + + ASSERT_EQ(cryptonote::round_money_up("1.999999", 1), "2.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("1.999999", 2), "2.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("1.999999", 3), "2.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("1.999999", 4), "2.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("1.999999", 5), "2.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("1.999999", 6), "2.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("1.999999", 7), "1.999999000000"); + ASSERT_EQ(cryptonote::round_money_up("1.999999", 8), "1.999999000000"); + ASSERT_EQ(cryptonote::round_money_up("1.999999", 9), "1.999999000000"); + + ASSERT_EQ(cryptonote::round_money_up("2.000001", 1), "3.000000000000"); + ASSERT_EQ(cryptonote::round_money_up("2.000001", 2), "2.100000000000"); + ASSERT_EQ(cryptonote::round_money_up("2.000001", 3), "2.010000000000"); + ASSERT_EQ(cryptonote::round_money_up("2.000001", 4), "2.001000000000"); + ASSERT_EQ(cryptonote::round_money_up("2.000001", 5), "2.000100000000"); + ASSERT_EQ(cryptonote::round_money_up("2.000001", 6), "2.000010000000"); + ASSERT_EQ(cryptonote::round_money_up("2.000001", 7), "2.000001000000"); + ASSERT_EQ(cryptonote::round_money_up("2.000001", 8), "2.000001000000"); + ASSERT_EQ(cryptonote::round_money_up("2.000001", 9), "2.000001000000"); + ASSERT_EQ(cryptonote::round_money_up("2.000001", 4000), "2.000001000000"); + + ASSERT_EQ(cryptonote::round_money_up("999", 2), "1000.000000000000"); + + ASSERT_THROW(cryptonote::round_money_up("1.23", 0), std::runtime_error); + ASSERT_THROW(cryptonote::round_money_up("18446744.073709551615", 1), std::runtime_error); + ASSERT_THROW(cryptonote::round_money_up("18446744.073709551615", 2), std::runtime_error); + ASSERT_THROW(cryptonote::round_money_up("18446744.073709551615", 12), std::runtime_error); + ASSERT_THROW(cryptonote::round_money_up("18446744.073709551615", 19), std::runtime_error); + ASSERT_EQ(cryptonote::round_money_up("18446744.073709551615", 20), "18446744.073709551615"); +} diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index f4c73d3d5..9e8a28f7c 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/sha256.cpp b/tests/unit_tests/sha256.cpp index 0232511d4..486f31c5b 100644 --- a/tests/unit_tests/sha256.cpp +++ b/tests/unit_tests/sha256.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/slow_memmem.cpp b/tests/unit_tests/slow_memmem.cpp index 602fdae38..aa1bea128 100644 --- a/tests/unit_tests/slow_memmem.cpp +++ b/tests/unit_tests/slow_memmem.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/subaddress.cpp b/tests/unit_tests/subaddress.cpp index bf24022e8..17fc0fe78 100644 --- a/tests/unit_tests/subaddress.cpp +++ b/tests/unit_tests/subaddress.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/test_notifier.cpp b/tests/unit_tests/test_notifier.cpp index 7fd9809c5..ffa0b3965 100644 --- a/tests/unit_tests/test_notifier.cpp +++ b/tests/unit_tests/test_notifier.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/test_peerlist.cpp b/tests/unit_tests/test_peerlist.cpp index 78404f9f9..98caabafd 100644 --- a/tests/unit_tests/test_peerlist.cpp +++ b/tests/unit_tests/test_peerlist.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/test_protocol_pack.cpp b/tests/unit_tests/test_protocol_pack.cpp index 1a4fd30f8..78bf01d4b 100644 --- a/tests/unit_tests/test_protocol_pack.cpp +++ b/tests/unit_tests/test_protocol_pack.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/test_tx_utils.cpp b/tests/unit_tests/test_tx_utils.cpp index 0d0dc8819..2991a143e 100644 --- a/tests/unit_tests/test_tx_utils.cpp +++ b/tests/unit_tests/test_tx_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/threadpool.cpp b/tests/unit_tests/threadpool.cpp index 1017f04ff..c1ea722c8 100644 --- a/tests/unit_tests/threadpool.cpp +++ b/tests/unit_tests/threadpool.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/tx_proof.cpp b/tests/unit_tests/tx_proof.cpp index 0adb8713e..04fe7aaa2 100644 --- a/tests/unit_tests/tx_proof.cpp +++ b/tests/unit_tests/tx_proof.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/unbound.cpp b/tests/unit_tests/unbound.cpp index b404ca922..1cac02901 100644 --- a/tests/unit_tests/unbound.cpp +++ b/tests/unit_tests/unbound.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/unit_tests_utils.h b/tests/unit_tests/unit_tests_utils.h index 1784ffb21..6b3fe1f44 100644 --- a/tests/unit_tests/unit_tests_utils.h +++ b/tests/unit_tests/unit_tests_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/uri.cpp b/tests/unit_tests/uri.cpp index 83312a3c9..0ece6d4c1 100644 --- a/tests/unit_tests/uri.cpp +++ b/tests/unit_tests/uri.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2020, The Monero Project +// Copyright (c) 2016-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/varint.cpp b/tests/unit_tests/varint.cpp index a8dee677a..9bf30c5ed 100644 --- a/tests/unit_tests/varint.cpp +++ b/tests/unit_tests/varint.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/vercmp.cpp b/tests/unit_tests/vercmp.cpp index 90f4fdf79..627a53c3b 100644 --- a/tests/unit_tests/vercmp.cpp +++ b/tests/unit_tests/vercmp.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // // All rights reserved. // diff --git a/tests/unit_tests/wipeable_string.cpp b/tests/unit_tests/wipeable_string.cpp index 0e0bf8906..ef6964f9e 100644 --- a/tests/unit_tests/wipeable_string.cpp +++ b/tests/unit_tests/wipeable_string.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2018, The Monero Project +// Copyright (c) 2018-2022, The Monero Project + // // All rights reserved. // diff --git a/tests/unit_tests/zmq_rpc.cpp b/tests/unit_tests/zmq_rpc.cpp index 66a7f3ac1..c98f0011b 100644 --- a/tests/unit_tests/zmq_rpc.cpp +++ b/tests/unit_tests/zmq_rpc.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020, The Monero Project +// Copyright (c) 2020-2022, The Monero Project + // // All rights reserved. // diff --git a/translations/CMakeLists.txt b/translations/CMakeLists.txt index 927d1733a..3b43360f8 100644 --- a/translations/CMakeLists.txt +++ b/translations/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2020, The Monero Project +# Copyright (c) 2017-2022, The Monero Project # # All rights reserved. # diff --git a/translations/generate_translations_header.c b/translations/generate_translations_header.c index 42248a184..01dc139b4 100644 --- a/translations/generate_translations_header.c +++ b/translations/generate_translations_header.c @@ -1,5 +1,5 @@ // Copyright (c) 2013, Sergey Lyubka -// Copyright (c) 2017-2020, The Monero Project +// Copyright (c) 2017-2022, The Monero Project // All rights reserved. // Released under the MIT license. diff --git a/utils/build_scripts/windows.bat b/utils/build_scripts/windows.bat index a90f27c0c..77ffd1c96 100644 --- a/utils/build_scripts/windows.bat +++ b/utils/build_scripts/windows.bat @@ -1,4 +1,4 @@ -:: Copyright (c) 2014-2020, The Monero Project +:: Copyright (c) 2014-2022, The Monero Project :: :: All rights reserved. :: diff --git a/utils/health/build-scripts/clang-build-time-analyzer-clone-build.sh b/utils/health/build-scripts/clang-build-time-analyzer-clone-build.sh index de5f35a38..9284cbbd4 100755 --- a/utils/health/build-scripts/clang-build-time-analyzer-clone-build.sh +++ b/utils/health/build-scripts/clang-build-time-analyzer-clone-build.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/utils/health/clang-build-time-analyzer-run.sh b/utils/health/clang-build-time-analyzer-run.sh index fb7eeaced..583b4ed30 100755 --- a/utils/health/clang-build-time-analyzer-run.sh +++ b/utils/health/clang-build-time-analyzer-run.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/utils/health/clang-include-what-you-use-run.sh b/utils/health/clang-include-what-you-use-run.sh index 655a188bd..50db929b0 100755 --- a/utils/health/clang-include-what-you-use-run.sh +++ b/utils/health/clang-include-what-you-use-run.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/utils/health/clang-tidy-run-cc.sh b/utils/health/clang-tidy-run-cc.sh index 0cf737131..5c8e8acb3 100755 --- a/utils/health/clang-tidy-run-cc.sh +++ b/utils/health/clang-tidy-run-cc.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -# Copyright (c) 2014-2021, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/utils/health/clang-tidy-run-common.sh b/utils/health/clang-tidy-run-common.sh index a086821a6..b16d96584 100755 --- a/utils/health/clang-tidy-run-common.sh +++ b/utils/health/clang-tidy-run-common.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -# Copyright (c) 2014-2021, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/utils/health/clang-tidy-run-cpp.sh b/utils/health/clang-tidy-run-cpp.sh index 7cf08fe78..3b5ea4b04 100755 --- a/utils/health/clang-tidy-run-cpp.sh +++ b/utils/health/clang-tidy-run-cpp.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -# Copyright (c) 2014-2021, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/utils/health/valgrind-tests.sh b/utils/health/valgrind-tests.sh index 9f5e7e7c0..b1fb0b0f4 100755 --- a/utils/health/valgrind-tests.sh +++ b/utils/health/valgrind-tests.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # diff --git a/utils/python-rpc/framework/daemon.py b/utils/python-rpc/framework/daemon.py index 397000b68..2bb7e664f 100644 --- a/utils/python-rpc/framework/daemon.py +++ b/utils/python-rpc/framework/daemon.py @@ -1,4 +1,5 @@ -# Copyright (c) 2018 The Monero Project +# Copyright (c) 2018-2022, The Monero Project + # # All rights reserved. # diff --git a/utils/python-rpc/framework/rpc.py b/utils/python-rpc/framework/rpc.py index b857be4d2..58b1eb794 100644 --- a/utils/python-rpc/framework/rpc.py +++ b/utils/python-rpc/framework/rpc.py @@ -1,4 +1,5 @@ -# Copyright (c) 2018 The Monero Project +# Copyright (c) 2018-2022, The Monero Project + # # All rights reserved. # diff --git a/utils/python-rpc/framework/wallet.py b/utils/python-rpc/framework/wallet.py index e531bf13d..037beee84 100644 --- a/utils/python-rpc/framework/wallet.py +++ b/utils/python-rpc/framework/wallet.py @@ -1,4 +1,5 @@ -# Copyright (c) 2018 The Monero Project +# Copyright (c) 2018-2022, The Monero Project + # # All rights reserved. # |