diff --git a/.gitmodules b/.gitmodules index e68cde5e..191af28d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,7 @@ path = src/gui/qt-daemon/layout url = https://github.com/hyle-team/zano_ui.git branch = main +[submodule "contrib/tor-connect"] + path = contrib/tor-connect + url = https://github.com/hyle-team/tor-connect.git + branch = main \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f21fb093..99243a7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,18 +56,23 @@ if(APPLE) endif() set(USE_PCH FALSE CACHE BOOL "Use shared precompiled headers") +set(DISABLE_TOR FALSE CACHE BOOL "Disable TOR library(and related tor-connect submodule)") +set(TESTNET FALSE CACHE BOOL "Compile for testnet") +set(BUILD_GUI FALSE CACHE BOOL "Build qt-daemon") include_directories(src contrib/eos_portable_archive contrib contrib/epee/include "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib") add_definitions(-DSTATICLIB) -set(TESTNET FALSE CACHE BOOL "Compile for testnet") if(TESTNET) message("!!!!!! NOTICE: Project is building for TESTNET !!!!!!") add_definitions(-DTESTNET) endif() -set(BUILD_GUI FALSE CACHE BOOL "Build qt-daemon") +if(DISABLE_TOR) + message("NOTICE: Building with disabled TOR support!") + add_definitions(-DDISABLE_TOR) +endif() set(STATIC ${MSVC} CACHE BOOL "Link libraries statically") @@ -197,7 +202,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Android") set(Boost_LIBRARY_DIRS "${Boost_LIBRARY_DIRS}/${CMAKE_ANDROID_ARCH_ABI}/") set(Boost_LIBRARIES "${Boost_LIBRARY_DIRS}libboost_system.a;${Boost_LIBRARY_DIRS}libboost_filesystem.a;${Boost_LIBRARY_DIRS}libboost_thread.a;${Boost_LIBRARY_DIRS}libboost_timer.a;${Boost_LIBRARY_DIRS}libboost_date_time.a;${Boost_LIBRARY_DIRS}libboost_chrono.a;${Boost_LIBRARY_DIRS}libboost_regex.a;${Boost_LIBRARY_DIRS}libboost_serialization.a;${Boost_LIBRARY_DIRS}libboost_atomic.a;${Boost_LIBRARY_DIRS}libboost_program_options.a") else() - find_package(Boost 1.55 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale) + find_package(Boost 1.70 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale) endif() diff --git a/README.md b/README.md index 189c88cf..c6ad2f56 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ Be sure to clone the repository properly:\ | [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2015 (14.0 update 1) | 2017 (15.9.0) | 2019 | | [XCode](https://developer.apple.com/downloads/) (macOS) | 9.2 | 12.3 | 12.3 | | [CMake](https://cmake.org/download/) | 2.8.6 | 3.15.5 | 3.20 | -| [Boost](https://www.boost.org/users/download/) | 1.56 | 1.68 | 1.76 | +| [Boost](https://www.boost.org/users/download/) | 1.70 | 1.70 | 1.76 | +| [OpenSSL](https://www.openssl.org/source/) [(win)](https://slproweb.com/products/Win32OpenSSL.html) | - | 1.1.1n | 1.1.1n | | [Qt](https://download.qt.io/archive/qt/) (*only for GUI*) | 5.8.0 | 5.11.2 | 5.15.2 | Note:\ @@ -35,18 +36,18 @@ Recommended OS version: Ubuntu 18.04 LTS. [*server version*] - sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen + sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen checkinstall zlib1g-dev [*GUI version*] - sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen mesa-common-dev libglu1-mesa-dev + sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen checkinstall zlib1g-dev mesa-common-dev libglu1-mesa-dev 2. Download and build Boost - wget https://boostorg.jfrog.io/artifactory/main/release/1.68.0/source/boost_1_68_0.tar.bz2 - tar -xjf boost_1_68_0.tar.bz2 - cd boost_1_68_0 - ./bootstrap.sh --with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer + curl -OL https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.bz2 + tar -xjf boost_1_70_0.tar.bz2 + cd boost_1_70_0 + ./bootstrap.sh --with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer,log ./b2 3. Install Qt\ @@ -54,28 +55,44 @@ Recommended OS version: Ubuntu 18.04 LTS. [*GUI version*] - wget https://download.qt.io/new_archive/qt/5.11/5.11.2/qt-opensource-linux-x64-5.11.2.run + curl -OL https://download.qt.io/new_archive/qt/5.11/5.11.2/qt-opensource-linux-x64-5.11.2.run chmod +x qt-opensource-linux-x64-5.11.2.run ./qt-opensource-linux-x64-5.11.2.run Then follow the instructions in Wizard. Don't forget to tick the WebEngine module checkbox! -4. Set environment variables properly\ + +4. Install OpenSSL + + We recommend installing OpenSSL v1.1.1n locally unless you would like to use the same version system-wide. + + curl -OL https://www.openssl.org/source/openssl-1.1.1n.tar.gz + tar xaf openssl-1.1.1n.tar.gz + cd openssl-1.1.1n/ + ./config --prefix=/home/user/openssl --openssldir=/home/user/openssl shared zlib + make + make test + make install + + +5. Set environment variables properly\ For instance, by adding the following lines to `~/.bashrc` [*server version*] - export BOOST_ROOT=/home/user/boost_1_68_0 + export BOOST_ROOT=/home/user/boost_1_70_0 + export OPENSSL_ROOT_DIR=/home/user/openssl [*GUI version*] - export BOOST_ROOT=/home/user/boost_1_68_0 + export BOOST_ROOT=/home/user/boost_1_70_0 + export OPENSSL_ROOT_DIR=/home/user/openssl export QT_PREFIX_PATH=/home/user/Qt5.11.2/5.11.2/gcc_64 -5. Building binaries - 1. Building daemon and simplewallet: +6. Build the binaries + 1. Build daemon and simplewallet: cd zano/ && make -j1 or @@ -88,7 +105,7 @@ For instance, by adding the following lines to `~/.bashrc` **NOTICE 2**: If you'd like to build binaries for the testnet, use `cmake -D TESTNET=TRUE ..` instead of `cmake ..` . - 1. Building GUI: + 1. Build GUI: cd zano utils/build_sript_linux.sh @@ -99,9 +116,9 @@ For instance, by adding the following lines to `~/.bashrc` ### Windows Recommended OS version: Windows 7 x64. -1. Install required prerequisites (Boost, Qt, CMake). +1. Install required prerequisites (Boost, Qt, CMake, OpenSSL). 2. Edit paths in `utils/configure_local_paths.cmd`. -3. Run `utils/configure_win64_msvs2015_gui.cmd` or `utils/configure_win64_msvs2017_gui.cmd` according to your MSVC version. +3. Run one of `utils/configure_win64_msvsNNNN_gui.cmd` according to your MSVC version. 4. Go to the build folder and open generated Zano.sln in MSVC. 5. Build. @@ -115,7 +132,7 @@ In order to correctly deploy Qt GUI application, you also need to do the followi
### macOS -Recommended OS version: macOS Sierra 10.15.4 x64. +Recommended OS version: macOS Big Sur 11.4 x64. 1. Install required prerequisites. 2. Set environment variables as stated in `utils/macosx_build_config.command`. 3. `mkdir build`
`cd build`
`cmake ..`
`make` diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 779876a1..601672d5 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -5,6 +5,10 @@ add_subdirectory(zlib) add_subdirectory(db) add_subdirectory(ethereum) +if( NOT DISABLE_TOR) + add_subdirectory(tor-connect) +endif() + if(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android") message("excluded upnp support for IOS build") @@ -17,6 +21,10 @@ set_property(TARGET libminiupnpc-static PROPERTY FOLDER "contrib") set_property(TARGET zlibstatic PROPERTY FOLDER "contrib") set_property(TARGET mdbx PROPERTY FOLDER "contrib") set_property(TARGET lmdb PROPERTY FOLDER "contrib") +if( NOT DISABLE_TOR) + set_property(TARGET tor-connect PROPERTY FOLDER "contrib") +endif() + set_property(TARGET upnpc-static mdbx_chk mdbx_copy mdbx_dump mdbx_load mdbx_stat PROPERTY FOLDER "unused") if(MSVC) diff --git a/contrib/db/libmdbx/src/elements/version.c.in b/contrib/db/libmdbx/src/elements/version.c.in index 2854bd5d..356b1857 100644 --- a/contrib/db/libmdbx/src/elements/version.c.in +++ b/contrib/db/libmdbx/src/elements/version.c.in @@ -3,10 +3,10 @@ #include "internals.h" -#if MDBX_VERSION_MAJOR != ${MDBX_VERSION_MAJOR} || \ - MDBX_VERSION_MINOR != ${MDBX_VERSION_MINOR} -#error "API version mismatch! Had `git fetch --tags` done?" -#endif +//#if MDBX_VERSION_MAJOR != ${MDBX_VERSION_MAJOR} || \ +// MDBX_VERSION_MINOR != ${MDBX_VERSION_MINOR} +//#error "API version mismatch! Had `git fetch --tags` done?" +//#endif static const char sourcery[] = STRINGIFY(MDBX_BUILD_SOURCERY); diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h index 276dfe02..1389ba03 100644 --- a/contrib/epee/include/misc_language.h +++ b/contrib/epee/include/misc_language.h @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include "include_base_utils.h" #include "auto_val_init.h" @@ -111,17 +113,6 @@ namespace misc_utils return (std::numeric_limits::max)(); } - // TEMPLATE STRUCT less - template - 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 bool is_less_as_pod(const _Ty& _Left, const _Ty& _Right) { // apply operator< to operands diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 2bb45f69..6829b645 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -693,7 +693,7 @@ bool boosted_tcp_server::connect(const std::string& adr, con shared_context->cond.notify_one(); }; - sock_.async_connect(remote_endpoint, boost::bind(connect_callback, _1, local_shared_context)); + sock_.async_connect(remote_endpoint, boost::bind(connect_callback, boost::placeholders::_1, local_shared_context)); while(local_shared_context->ec == boost::asio::error::would_block) { bool r = false; try { diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index be81ba41..c0b57596 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -831,7 +831,7 @@ using namespace std; return false; }else { //Apparently there are no signs of the form of transfer, will receive data until the connection is closed - m_state = reciev_machine_state_error; + m_state = reciev_machine_state_body_connection_close; LOG_PRINT("Undefinded transfer type, consider http_body_transfer_connection_close method. header: " << m_header_cache, LOG_LEVEL_2); return false; } diff --git a/contrib/epee/include/net/levin_client.h b/contrib/epee/include/net/levin_client.h index 335f6ba0..cc656e9d 100644 --- a/contrib/epee/include/net/levin_client.h +++ b/contrib/epee/include/net/levin_client.h @@ -46,11 +46,12 @@ namespace levin /************************************************************************/ /* */ /************************************************************************/ - class levin_client_impl + template + class levin_client_impl_t { public: - levin_client_impl(); - virtual ~levin_client_impl(); + levin_client_impl_t(); + virtual ~levin_client_impl_t(); 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"); @@ -61,26 +62,30 @@ namespace levin virtual int notify(int command, const std::string& in_buff); protected: - net_utils::blocked_mode_client m_transport; + transport_t m_transport; + //net_utils::blocked_mode_client m_transport; }; /************************************************************************/ /* */ /************************************************************************/ - class levin_client_impl2: public levin_client_impl + template + class levin_client_impl2: public levin_client_impl_t { public: int invoke(int command, const std::string& in_buff, std::string& buff_out); int notify(int command, const std::string& in_buff); + + transport_t& get_transport() {return this->m_transport;} }; } namespace net_utils { - typedef levin::levin_client_impl levin_client; - typedef levin::levin_client_impl2 levin_client2; + typedef levin::levin_client_impl_t levin_client; + typedef levin::levin_client_impl2 levin_client2; } } diff --git a/contrib/epee/include/net/levin_client.inl b/contrib/epee/include/net/levin_client.inl index 6f7c473e..62089afa 100644 --- a/contrib/epee/include/net/levin_client.inl +++ b/contrib/epee/include/net/levin_client.inl @@ -32,175 +32,174 @@ #include "string_tools.h" 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 std::string& in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_command = 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!=LEVIN_SIGNATURE) - { - LOG_PRINT_L0("Signature missmatch 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 = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_command = 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, const std::string& in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_command = static_cast(command); - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - if(!m_transport.send(&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - //Since other side of connection could be running by async server, - //we can receive some unexpected notify(forwarded broadcast notifications for example). - //let's ignore every notify in the channel until we get invoke response - std::string local_buff; - - while (true) + namespace levin { - if (!m_transport.recv_n(local_buff, sizeof(bucket_head2))) - return LEVIN_ERROR_NET_ERROR; - head = *(bucket_head2*)local_buff.data(); - if (head.m_signature != LEVIN_SIGNATURE) + template + bool levin_client_impl_t::connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip) { - LOG_PRINT_L0("Signature missmatch in response"); - return LEVIN_ERROR_SIGNATURE_MISMATCH; + return m_transport.connect(string_tools::get_ip_string_from_int32(ip), port, timeout, timeout, bind_ip); } - if (!m_transport.recv_n(buff_out, head.m_cb)) - return LEVIN_ERROR_NET_ERROR; - - //now check if this is response to invoke (and extra validate if it's response to this(!) invoke) - if (head.m_flags&LEVIN_PACKET_RESPONSE) + //------------------------------------------------------------------------------ + template + bool levin_client_impl_t::connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip) { - //we got response, extra validate if its response to our request - CHECK_AND_ASSERT_MES(head.m_command == static_cast(command), LEVIN_ERROR_PROTOCOL_INCONSISTENT, "command id missmatch in response: " << head.m_command << ", expected: " << command); + return m_transport.connect(addr, port, timeout, timeout, bind_ip); + } + //------------------------------------------------------------------------------ + template + bool levin_client_impl_t::is_connected() + { + return m_transport.is_connected(); + } + //------------------------------------------------------------------------------ + template + bool levin_client_impl_t::disconnect() + { + return m_transport.disconnect(); + } + //------------------------------------------------------------------------------ + template + levin_client_impl_t::levin_client_impl_t() + { + } + //------------------------------------------------------------------------------ + template + levin_client_impl_t::~levin_client_impl_t() + { + disconnect(); + } + //------------------------------------------------------------------------------ + template + int levin_client_impl_t::invoke(int command, const std::string& in_buff, std::string& buff_out) + { + if (!is_connected()) + return -1; + + bucket_head head = { 0 }; + head.m_signature = LEVIN_SIGNATURE; + head.m_cb = in_buff.size(); + head.m_have_to_return_data = true; + head.m_command = 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 != LEVIN_SIGNATURE) + { + LOG_PRINT_L0("Signature missmatch in response"); + return -1; + } + + if (!m_transport.recv_n(buff_out, head.m_cb)) + return -1; + return head.m_return_code; } + //------------------------------------------------------------------------------ + template + int levin_client_impl_t::notify(int command, const std::string& in_buff) + { + if (!this->is_connected()) + return -1; + + bucket_head head = { 0 }; + head.m_signature = LEVIN_SIGNATURE; + head.m_cb = in_buff.size(); + head.m_have_to_return_data = false; + head.m_command = command; + + if (!m_transport.send((const char*)&head, sizeof(head))) + return -1; + + if (!m_transport.send(in_buff)) + return -1; + + return 1; + } + //------------------------------------------------------------------------------ + template + int levin_client_impl2::invoke(int command, const std::string& in_buff, std::string& buff_out) + { + if (!this->is_connected()) + return -1; + + bucket_head2 head = { 0 }; + head.m_signature = LEVIN_SIGNATURE; + head.m_cb = in_buff.size(); + head.m_have_to_return_data = true; + head.m_command = static_cast(command); + head.m_protocol_version = LEVIN_PROTOCOL_VER_1; + head.m_flags = LEVIN_PACKET_REQUEST; + if (!this->m_transport.send(&head, sizeof(head))) + return -1; + + if (!this->m_transport.send(in_buff)) + return -1; + + //Since other side of connection could be running by async server, + //we can receive some unexpected notify(forwarded broadcast notifications for example). + //let's ignore every notify in the channel until we get invoke response + std::string local_buff; + + while (true) + { + if (!this->m_transport.recv_n(local_buff, sizeof(bucket_head2))) + return LEVIN_ERROR_NET_ERROR; + + head = *(bucket_head2*)local_buff.data(); + if (head.m_signature != LEVIN_SIGNATURE) + { + LOG_PRINT_L0("Signature missmatch in response"); + return LEVIN_ERROR_SIGNATURE_MISMATCH; + } + if (!this->m_transport.recv_n(buff_out, head.m_cb)) + return LEVIN_ERROR_NET_ERROR; + + //now check if this is response to invoke (and extra validate if it's response to this(!) invoke) + if (head.m_flags&LEVIN_PACKET_RESPONSE) + { + //we got response, extra validate if its response to our request + CHECK_AND_ASSERT_MES(head.m_command == static_cast(command), LEVIN_ERROR_PROTOCOL_INCONSISTENT, "command id missmatch in response: " << head.m_command << ", expected: " << command); + return head.m_return_code; + } + } + //never comes here + return LEVIN_ERROR_INTERNAL; + } + //------------------------------------------------------------------------------ + template + int levin_client_impl2::notify(int command, const std::string& in_buff) + { + if (!this->is_connected()) + return -1; + + bucket_head2 head = { 0 }; + head.m_signature = LEVIN_SIGNATURE; + head.m_cb = in_buff.size(); + head.m_have_to_return_data = false; + head.m_command = command; + head.m_protocol_version = LEVIN_PROTOCOL_VER_1; + head.m_flags = LEVIN_PACKET_REQUEST; + + if (!this->m_transport.send((const char*)&head, sizeof(head))) + return -1; + + if (!this->m_transport.send(in_buff)) + return -1; + + return 1; + } + } - //never comes here - return LEVIN_ERROR_INTERNAL; -} -//------------------------------------------------------------------------------ -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 = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - - if(!m_transport.send((const char*)&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - return 1; -} - -} } //------------------------------------------------------------------------------ \ No newline at end of file diff --git a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h index 01f9e257..d33d5ad1 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h @@ -27,6 +27,7 @@ #pragma once #include +#include #include namespace epee diff --git a/contrib/epee/include/storages/levin_abstract_invoke2.h b/contrib/epee/include/storages/levin_abstract_invoke2.h index 1b2c74a4..4c1c5569 100644 --- a/contrib/epee/include/storages/levin_abstract_invoke2.h +++ b/contrib/epee/include/storages/levin_abstract_invoke2.h @@ -267,20 +267,20 @@ namespace epee #define HANDLE_INVOKE2(command_id, func, type_name_in, typename_out) \ if(!is_notify && command_id == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);} + {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, buff_out, boost::bind(func, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3, boost::placeholders::_4), context);} #define HANDLE_INVOKE_T2(COMMAND, func) \ if(!is_notify && COMMAND::ID == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);} + {handled=true;return epee::net_utils::buff_to_t_adapter(command, in_buff, buff_out, boost::bind(func, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3, boost::placeholders::_4), context);} #define HANDLE_NOTIFY2(command_id, func, type_name_in) \ if(is_notify && command_id == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} + {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, boost::bind(func, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3), context);} #define HANDLE_NOTIFY_T2(NOTIFY, func) \ if(is_notify && NOTIFY::ID == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} + {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, boost::bind(func, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3), context);} #define CHAIN_INVOKE_MAP2(func) \ diff --git a/contrib/tor-connect b/contrib/tor-connect new file mode 160000 index 00000000..aa509880 --- /dev/null +++ b/contrib/tor-connect @@ -0,0 +1 @@ +Subproject commit aa509880f06292ac8078046f3d49ff854e400716 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a044fab8..da31da22 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -121,16 +121,19 @@ add_library(currency_core ${CURRENCY_CORE}) add_dependencies(currency_core version ${PCH_LIB_NAME}) ENABLE_SHARED_PCH(currency_core CURRENCY_CORE) +add_library(wallet ${WALLET}) if(CMAKE_SYSTEM_NAME STREQUAL "Android" ) - add_library(wallet ${WALLET}) add_dependencies(wallet version ${PCH_LIB_NAME}) target_link_libraries(wallet currency_core crypto common zlibstatic ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} android log) else() - add_library(wallet ${WALLET}) add_dependencies(wallet version ${PCH_LIB_NAME}) ENABLE_SHARED_PCH(wallet WALLET) endif() +if(NOT DISABLE_TOR) + target_link_libraries(wallet tor-connect) +endif() + @@ -159,7 +162,7 @@ target_link_libraries(currency_core lmdb mdbx) add_executable(daemon ${DAEMON} ${P2P} ${CURRENCY_PROTOCOL}) add_dependencies(daemon version) - target_link_libraries(daemon rpc stratum currency_core crypto common libminiupnpc-static zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) +target_link_libraries(daemon rpc stratum currency_core crypto common libminiupnpc-static zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) ENABLE_SHARED_PCH(daemon DAEMON) ENABLE_SHARED_PCH_EXECUTABLE(daemon) @@ -170,8 +173,9 @@ ENABLE_SHARED_PCH(connectivity_tool CONN_TOOL) ENABLE_SHARED_PCH_EXECUTABLE(connectivity_tool) add_executable(simplewallet ${SIMPLEWALLET}) -add_dependencies(simplewallet version) +add_dependencies(simplewallet version) target_link_libraries(simplewallet wallet rpc currency_core crypto common zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) + ENABLE_SHARED_PCH(simplewallet SIMPLEWALLET) ENABLE_SHARED_PCH_EXECUTABLE(simplewallet) diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index 6595763f..0474f9cd 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -10,36 +10,36 @@ namespace command_line { - const arg_descriptor arg_help = {"help", "Produce help message"}; - const arg_descriptor arg_version = {"version", "Output version information"}; - const arg_descriptor arg_data_dir = {"data-dir", "Specify data directory", ""}; + const arg_descriptor arg_help ("help", "Produce help message"); + const arg_descriptor arg_version ("version", "Output version information"); + const arg_descriptor arg_data_dir ("data-dir", "Specify data directory", ""); - const arg_descriptor arg_stop_after_height = { "stop-after-height", "If specified, the daemon will stop immediately after a block with the given height is added", 0 }; + const arg_descriptor arg_stop_after_height ( "stop-after-height", "If specified, the daemon will stop immediately after a block with the given height is added", 0 ); - const arg_descriptor arg_config_file = { "config-file", "Specify configuration file", std::string(CURRENCY_NAME_SHORT ".conf") }; - const arg_descriptor arg_os_version = { "os-version", "" }; + const arg_descriptor arg_config_file ( "config-file", "Specify configuration file", std::string(CURRENCY_NAME_SHORT ".conf") ); + const arg_descriptor arg_os_version ( "os-version", "" ); - const arg_descriptor arg_log_dir = { "log-dir", "", "", true}; - const arg_descriptor arg_log_file = { "log-file", "", "" }; - const arg_descriptor arg_log_level = { "log-level", "", LOG_LEVEL_0, true }; + const arg_descriptor arg_log_dir ( "log-dir", ""); + const arg_descriptor arg_log_file ( "log-file", "", ""); + const arg_descriptor arg_log_level ( "log-level", ""); - const arg_descriptor arg_console = { "no-console", "Disable daemon console commands" }; - const arg_descriptor arg_show_details = { "currency-details", "Display currency details" }; - const arg_descriptor arg_show_rpc_autodoc = { "show_rpc_autodoc", "Display rpc auto-generated documentation template" }; + const arg_descriptor arg_console ( "no-console", "Disable daemon console commands" ); + const arg_descriptor arg_show_details ( "currency-details", "Display currency details" ); + const arg_descriptor arg_show_rpc_autodoc ( "show_rpc_autodoc", "Display rpc auto-generated documentation template" ); - const arg_descriptor arg_disable_upnp = { "disable-upnp", "Disable UPnP (enhances local network privacy)", false, true }; - const arg_descriptor arg_disable_ntp = { "disable-ntp", "Disable NTP, could enhance to time synchronization issue but increase network privacy, consider using disable-stop-if-time-out-of-sync with it", false, true }; + const arg_descriptor arg_disable_upnp ( "disable-upnp", "Disable UPnP (enhances local network privacy)"); + const arg_descriptor arg_disable_ntp ( "disable-ntp", "Disable NTP, could enhance to time synchronization issue but increase network privacy, consider using disable-stop-if-time-out-of-sync with it"); - const arg_descriptor arg_disable_stop_if_time_out_of_sync = { "disable-stop-if-time-out-of-sync", "Do not stop the daemon if serious time synchronization problem is detected", false, true }; - const arg_descriptor arg_disable_stop_on_low_free_space = { "disable-stop-on-low-free-space", "Do not stop the daemon if free space at data dir is critically low", false, true }; - const arg_descriptor arg_enable_offers_service = { "enable-offers-service", "Enables marketplace feature", false, false}; - const arg_descriptor arg_db_engine = { "db-engine", "Specify database engine for storage. May be \"lmdb\"(default) or \"mdbx\"", ARG_DB_ENGINE_LMDB, false }; + const arg_descriptor arg_disable_stop_if_time_out_of_sync ( "disable-stop-if-time-out-of-sync", "Do not stop the daemon if serious time synchronization problem is detected"); + const arg_descriptor arg_disable_stop_on_low_free_space ( "disable-stop-on-low-free-space", "Do not stop the daemon if free space at data dir is critically low"); + const arg_descriptor arg_enable_offers_service ( "enable-offers-service", "Enables marketplace feature", false); + const arg_descriptor arg_db_engine ( "db-engine", "Specify database engine for storage. May be \"lmdb\"(default) or \"mdbx\"", ARG_DB_ENGINE_LMDB ); - const arg_descriptor arg_no_predownload = { "no-predownload", "Do not pre-download blockchain database", }; - const arg_descriptor arg_force_predownload = { "force-predownload", "Pre-download blockchain database regardless of it's status", }; - const arg_descriptor arg_validate_predownload = { "validate-predownload", "Paranoid mode, re-validate each block from pre-downloaded database and rebuild own database", }; - const arg_descriptor arg_predownload_link = { "predownload-link", "Override url for blockchain database pre-downloading", "", true }; + const arg_descriptor arg_no_predownload ( "no-predownload", "Do not pre-download blockchain database"); + const arg_descriptor arg_force_predownload ( "force-predownload", "Pre-download blockchain database regardless of it's status"); + const arg_descriptor arg_validate_predownload ( "validate-predownload", "Paranoid mode, re-validate each block from pre-downloaded database and rebuild own database"); + const arg_descriptor arg_predownload_link ( "predownload-link", "Override url for blockchain database pre-downloading"); - const arg_descriptor arg_deeplink = { "deeplink-params", "Deeplink parameter, in that case app just forward params to running app", "", true }; + const arg_descriptor arg_deeplink ( "deeplink-params", "Deeplink parameter, in that case app just forward params to running app"); } diff --git a/src/common/command_line.h b/src/common/command_line.h index 652d1777..2c147d20 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -26,32 +26,38 @@ namespace command_line arg_descriptor(const char* _name, const char* _description): name(_name), description(_description), - not_use_default(true), + use_default(false), default_value(T()) {} arg_descriptor(const char* _name, const char* _description, const T& default_val) : name(_name), description(_description), - not_use_default(false), + use_default(true), default_value(default_val) {} - arg_descriptor(const char* _name, const char* _description, const T& default_val, bool not_use_default) : - name(_name), - description(_description), - default_value(default_val), - not_use_default(not_use_default) - {} +// arg_descriptor(const char* _name, const char* _description, const T& default_val, bool not_use_default) : +// name(_name), +// description(_description), +// default_value(default_val), +// not_use_default(not_use_default) +// {} + const char* name; const char* description; + bool use_default; T default_value; - bool not_use_default; }; template struct arg_descriptor, false> { + arg_descriptor(const char* _name, const char* _description) : + name(_name), + description(_description) + {} + typedef std::vector value_type; const char* name; @@ -79,7 +85,7 @@ namespace command_line boost::program_options::typed_value* make_semantic(const arg_descriptor& arg) { auto semantic = boost::program_options::value(); - if (!arg.not_use_default) + if (arg.use_default) semantic->default_value(arg.default_value); return semantic; } @@ -88,7 +94,7 @@ namespace command_line boost::program_options::typed_value* make_semantic(const arg_descriptor& arg, const T& def) { auto semantic = boost::program_options::value(); - if (!arg.not_use_default) + if (arg.use_default) semantic->default_value(def); return semantic; } diff --git a/src/common/ntp.cpp b/src/common/ntp.cpp index fdbc2a5b..db55610a 100644 --- a/src/common/ntp.cpp +++ b/src/common/ntp.cpp @@ -94,7 +94,7 @@ public: // Start the asynchronous operation itself. The handle_receive function // used as a callback will update the ec and length variables. socket_.async_receive(boost::asio::buffer(buffer), - boost::bind(&udp_blocking_client::handle_receive, _1, _2, &ec, &length)); + boost::bind(&udp_blocking_client::handle_receive, boost::placeholders::_1, boost::placeholders::_2, &ec, &length)); // Block until the asynchronous operation has completed. do io_service_.run_one(); while (ec == boost::asio::error::would_block); @@ -194,7 +194,12 @@ namespace tools ntp_packet packet_sent = AUTO_VAL_INIT(packet_sent); packet_sent.li_vn_mode = 0x1b; auto packet_sent_time = std::chrono::high_resolution_clock::now(); - socket.send_to(boost::asio::buffer(&packet_sent, sizeof packet_sent), receiver_endpoint); + auto send_res = socket.send_to(boost::asio::buffer(&packet_sent, sizeof packet_sent), receiver_endpoint); + if (send_res != sizeof packet_sent) + { + LOG_PRINT_L3("NTP: get_ntp_time(" << host_name << "): wrong send_res: " << send_res << ", expected sizeof packet_sent = " << sizeof packet_sent); + return 0; + } ntp_packet packet_received = AUTO_VAL_INIT(packet_received); boost::asio::ip::udp::endpoint sender_endpoint; diff --git a/src/common/pre_download.h b/src/common/pre_download.h index b6d4a74d..3a3e8666 100644 --- a/src/common/pre_download.h +++ b/src/common/pre_download.h @@ -21,8 +21,8 @@ namespace tools }; #ifndef TESTNET - static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_1480000.pak", "2b664de02450cc0082efb6c75824d33ffe694b9b17b21fc7966bcb9be9ac31f7", 1570460883, 3221176320 }; - static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_1480000.pak", "67770faa7db22dfe97982611d7471ba5673145589e81e02ed99832644ae328f6", 2042582638, 2968252416 }; + static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_1569000.pak", "c2aff6fb65c2d7a40492738c75d1d04f2f35388d3c1a664aeb77420f2d90d644", 1740147926, 3221176320 }; + static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_1569000.pak", "f673636638b666b36c976168a3c64b2fd1fcf071c41b5d9cf01ed58a5924f80a", 2244905636, 3216977920 }; #else static constexpr pre_download_entry c_pre_download_mdbx = { "", "", 0, 0 }; static constexpr pre_download_entry c_pre_download_lmdb = { "", "", 0, 0 }; diff --git a/src/common/threads_pool.h b/src/common/threads_pool.h index 4e4e3905..461e8843 100644 --- a/src/common/threads_pool.h +++ b/src/common/threads_pool.h @@ -51,11 +51,11 @@ namespace utils int num_threads = std::thread::hardware_concurrency(); this->init(num_threads); } - void init(unsigned int num_threads) + void init(size_t num_threads) { m_is_stop = false; - for (int i = 0; i < num_threads; i++) + for (size_t i = 0; i < num_threads; i++) { m_threads.push_back(std::thread([this]() {this->worker_func(); })); } @@ -81,7 +81,7 @@ namespace utils std::mutex batch_mutex; - std::atomic cnt = 0; + std::atomic cnt(0); for (const auto& jb : cntr) { call_executor_base* pjob = jb.get(); diff --git a/src/common/tor_helper.h b/src/common/tor_helper.h new file mode 100644 index 00000000..48cabba1 --- /dev/null +++ b/src/common/tor_helper.h @@ -0,0 +1,17 @@ +// Copyright (c) 2014-2018 Zano Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include "tor-connect/torlib/tor_wrapper.h" + + + +namespace tools +{ + typedef epee::levin::levin_client_impl2 levin_over_tor_client; + +} + + diff --git a/src/connectivity_tool/conn_tool.cpp b/src/connectivity_tool/conn_tool.cpp index d1f2115b..1ee022b3 100644 --- a/src/connectivity_tool/conn_tool.cpp +++ b/src/connectivity_tool/conn_tool.cpp @@ -38,32 +38,32 @@ using namespace nodetool; namespace { - const command_line::arg_descriptor arg_ip = {"ip", "set ip", "127.0.0.1", false}; - const command_line::arg_descriptor arg_port = {"port", "set port"}; - const command_line::arg_descriptor arg_rpc_port = {"rpc-port", "set rpc port", RPC_DEFAULT_PORT, false}; - const command_line::arg_descriptor arg_timeout = {"timeout", "set timeout", 5000, false}; - const command_line::arg_descriptor arg_priv_key = {"private-key", "private key to subscribe debug command", "", true}; - const command_line::arg_descriptor arg_peer_id = {"peer-id", "peerid if known(if not - will be requested)", 0}; - const command_line::arg_descriptor arg_generate_keys = {"generate-keys-pair", "generate private and public keys pair"}; - const command_line::arg_descriptor arg_request_stat_info = {"request-stat-info", "request statistics information"}; - const command_line::arg_descriptor arg_log_journal_len = { "log-journal-len", "Specify length of list of last error messages in log", 0, true }; - const command_line::arg_descriptor arg_request_net_state = {"request-net-state", "request network state information (peer list, connections count)"}; - const command_line::arg_descriptor arg_get_daemon_info = {"rpc-get-daemon-info", "request daemon state info vie rpc (--rpc-port option should be set ).", "", true}; - const command_line::arg_descriptor arg_get_aliases = {"rpc-get-aliases", "request daemon aliases all list", "", true}; - const command_line::arg_descriptor arg_increment_build_no = { "increment-build-no", "Increment build nimber", "", true }; - const command_line::arg_descriptor arg_upate_maintainers_info = {"update-maintainers-info", "Push maintainers info into the network, update-maintainers-info=file-with-info.json", "", true}; - const command_line::arg_descriptor arg_update_build_no = {"update-build-no", "Updated version number in version template file", "", true}; - const command_line::arg_descriptor arg_generate_genesis = {"generate-genesis", "Generate genesis coinbase based on config file", "", true }; - const command_line::arg_descriptor arg_genesis_split_amount = { "genesis-split-amount", "Set split amount for generating genesis block", 0, true }; - const command_line::arg_descriptor arg_get_info_flags = { "getinfo-flags-hex", "Set of bits for rpc-get-daemon-info", "", true }; - const command_line::arg_descriptor arg_set_peer_log_level = { "set-peer-log-level", "Set log level for remote peer", 0, true }; - const command_line::arg_descriptor arg_download_peer_log = { "download-peer-log", "Download log from remote peer [,]", "", true }; - const command_line::arg_descriptor arg_do_consloe_log = { "do-console-log", "Tool generates debug console output(debug purposes)", "", true }; - const command_line::arg_descriptor arg_generate_integrated_address = { "generate-integrated-address", "Tool create integrated address from simple address and payment_id", "", true }; - const command_line::arg_descriptor arg_pack_file = {"pack-file", "perform gzip-packing and calculate hash for a given file", "", true }; - const command_line::arg_descriptor arg_unpack_file = {"unpack-file", "Perform gzip-unpacking and calculate hash for a given file", "", true }; - const command_line::arg_descriptor arg_target_file = {"target-file", "Specify target file for pack-file and unpack-file commands", "", true }; - //const command_line::arg_descriptor arg_send_ipc = {"send-ipc", "Send IPC request to UI", "", true }; + const command_line::arg_descriptor arg_ip ("ip", "set ip", "127.0.0.1"); + const command_line::arg_descriptor arg_port ("port", "set port"); + const command_line::arg_descriptor arg_rpc_port ("rpc-port", "set rpc port", RPC_DEFAULT_PORT); + const command_line::arg_descriptor arg_timeout ("timeout", "set timeout", 5000); + const command_line::arg_descriptor arg_priv_key ("private-key", "private key to subscribe debug command"); + const command_line::arg_descriptor arg_peer_id ("peer-id", "peerid if known(if not - will be requested)", 0); + const command_line::arg_descriptor arg_generate_keys ("generate-keys-pair", "generate private and public keys pair"); + const command_line::arg_descriptor arg_request_stat_info ("request-stat-info", "request statistics information"); + const command_line::arg_descriptor arg_log_journal_len ( "log-journal-len", "Specify length of list of last error messages in log"); + const command_line::arg_descriptor arg_request_net_state ("request-net-state", "request network state information (peer list, connections count)"); + const command_line::arg_descriptor arg_get_daemon_info ("rpc-get-daemon-info", "request daemon state info vie rpc (--rpc-port option should be set )."); + const command_line::arg_descriptor arg_get_aliases ("rpc-get-aliases", "request daemon aliases all list"); + const command_line::arg_descriptor arg_increment_build_no ( "increment-build-no", "Increment build nimber"); + const command_line::arg_descriptor arg_upate_maintainers_info ("update-maintainers-info", "Push maintainers info into the network, update-maintainers-info=file-with-info.json"); + const command_line::arg_descriptor arg_update_build_no ("update-build-no", "Updated version number in version template file"); + const command_line::arg_descriptor arg_generate_genesis ("generate-genesis", "Generate genesis coinbase based on config file"); + const command_line::arg_descriptor arg_genesis_split_amount ( "genesis-split-amount", "Set split amount for generating genesis block"); + const command_line::arg_descriptor arg_get_info_flags ( "getinfo-flags-hex", "Set of bits for rpc-get-daemon-info", ""); + const command_line::arg_descriptor arg_set_peer_log_level ( "set-peer-log-level", "Set log level for remote peer"); + const command_line::arg_descriptor arg_download_peer_log ( "download-peer-log", "Download log from remote peer [,]"); + const command_line::arg_descriptor arg_do_consloe_log ( "do-console-log", "Tool generates debug console output(debug purposes)"); + const command_line::arg_descriptor arg_generate_integrated_address ( "generate-integrated-address", "Tool create integrated address from simple address and payment_id"); + const command_line::arg_descriptor arg_pack_file ("pack-file", "perform gzip-packing and calculate hash for a given file"); + const command_line::arg_descriptor arg_unpack_file ("unpack-file", "Perform gzip-unpacking and calculate hash for a given file"); + const command_line::arg_descriptor arg_target_file ("target-file", "Specify target file for pack-file and unpack-file commands"); + //const command_line::arg_descriptor arg_send_ipc ("send-ipc", "Send IPC request to UI"); } typedef COMMAND_REQUEST_STAT_INFO_T::stat_info> COMMAND_REQUEST_STAT_INFO; @@ -640,7 +640,7 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) response_schema rs = AUTO_VAL_INIT(rs); - levin::levin_client_impl2 transport; + net_utils::levin_client2 transport; if(!transport.connect(command_line::get_arg(vm, arg_ip), static_cast(command_line::get_arg(vm, arg_port)), static_cast(command_line::get_arg(vm, arg_timeout)))) { std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "Failed to connect to " << command_line::get_arg(vm, arg_ip) << ":" << command_line::get_arg(vm, arg_port) << "\"" << ENDL << "}" << ENDL; @@ -878,7 +878,7 @@ bool generate_and_print_keys() } //--------------------------------------------------------------------------------------------------------------- template -bool invoke_debug_command(po::variables_map& vm, const crypto::secret_key& sk, levin::levin_client_impl2& transport, peerid_type& peer_id, typename command_t::request& req, typename command_t::response& rsp) +bool invoke_debug_command(po::variables_map& vm, const crypto::secret_key& sk, net_utils::levin_client2& transport, peerid_type& peer_id, typename command_t::request& req, typename command_t::response& rsp) { if (!transport.is_connected()) { @@ -933,7 +933,7 @@ bool handle_set_peer_log_level(po::variables_map& vm) return false; } - levin::levin_client_impl2 transport; + net_utils::levin_client2 transport; peerid_type peer_id = 0; COMMAND_SET_LOG_LEVEL::request req = AUTO_VAL_INIT(req); @@ -982,7 +982,7 @@ bool handle_download_peer_log(po::variables_map& vm) } uint64_t start_offset = static_cast(start_offset_signed); - levin::levin_client_impl2 transport; + net_utils::levin_client2 transport; peerid_type peer_id = 0; COMMAND_REQUEST_LOG::request req = AUTO_VAL_INIT(req); diff --git a/src/crypto/crypto-sugar.cpp b/src/crypto/crypto-sugar.cpp index 4774e9b7..8b8779ae 100644 --- a/src/crypto/crypto-sugar.cpp +++ b/src/crypto/crypto-sugar.cpp @@ -21,6 +21,7 @@ namespace crypto const scalar_t c_scalar_1div8 = { 0x6106e529e2dc2f79, 0x07d39db37d1cdad0, 0x0, 0x0600000000000000 }; const point_t c_point_H = { 0x05087c1f5b9b32d6, 0x00547595f445c3b5, 0x764df64578552f2a, 0x8a49a651e0e0da45 }; // == Hp(G), this is being checked in bpp_basics + const point_t c_point_H2 = { 0x70c8d1ab9dbf1cc0, 0xc561bb12639a8516, 0x3cfff1def9e5b268, 0xe0936386f3bcce1a }; // == Hp("h2_generator"), cheched in bpp_basics const point_t c_point_0 = point_t(point_t::tag_zero()); } // namespace crypto diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h index 5542b9fb..a2681642 100644 --- a/src/crypto/crypto-sugar.h +++ b/src/crypto/crypto-sugar.h @@ -431,6 +431,31 @@ namespace crypto return result; } + // Little-endian assumed; TODO: consider Big-endian support + bool get_bit(uint8_t bit_index) const + { + return (m_u64[bit_index >> 6] & (1ull << (bit_index & 63))) != 0; + } + + // Little-endian assumed; TODO: consider Big-endian support + void set_bit(size_t bit_index) + { + m_u64[bit_index >> 6] |= (1ull << (bit_index & 63)); + } + + // Little-endian assumed; TODO: consider Big-endian support + void clear_bit(size_t bit_index) + { + m_u64[bit_index >> 6] &= ~(1ull << (bit_index & 63)); + } + + static scalar_t power_of_2(uint8_t exponent) + { + scalar_t result = 0; + result.set_bit(exponent); + return result; + } + }; // struct scalar_t // @@ -890,6 +915,7 @@ namespace crypto extern const point_g_t c_point_G; extern const point_t c_point_H; + extern const point_t c_point_H2; extern const point_t c_point_0; // @@ -1063,6 +1089,21 @@ namespace crypto ge_bytes_hash_to_ec_32(&result.m_p3, (const unsigned char*)&p); return result; } + + static point_t hp(const scalar_t& s) + { + point_t result; + ge_bytes_hash_to_ec_32(&result.m_p3, s.data()); + return result; + } + + static point_t hp(const void* data, size_t size) + { + point_t result; + ge_bytes_hash_to_ec(&result.m_p3, data, size); + return result; + } + }; // hash_helper_t struct diff --git a/src/crypto/range_proof_bpp.h b/src/crypto/range_proof_bpp.h new file mode 100644 index 00000000..cd61ca85 --- /dev/null +++ b/src/crypto/range_proof_bpp.h @@ -0,0 +1,699 @@ +// Copyright (c) 2021-2022 Zano Project (https://zano.org/) +// Copyright (c) 2021-2022 sowle (val@zano.org, crypto.sowle@gmail.com) +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#pragma once + +// +// This file contains the implementation of range proof protocol. +// Namely, Bulletproofs+ https://eprint.iacr.org/2020/735 +// + +namespace crypto +{ + struct bpp_signature + { + std::vector L; // size = ceil( log_2(m * n) ) + std::vector R; + public_key A0; + public_key A; + public_key B; + scalar_t r; + scalar_t s; + scalar_t delta; + }; + +#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL +#define DBG_PRINT(x) std::cout << x << ENDL + + template + bool bpp_gen(const scalar_vec_t& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector& commitments, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + static_assert(CT::c_bpp_n <= 255, "too big N"); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size(), 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced(), 3); + + const size_t c_bpp_log2_m = constexpr_ceil_log2(values.size()); + const size_t c_bpp_m = 1ull << c_bpp_log2_m; + const size_t c_bpp_mn = c_bpp_m * CT::c_bpp_n; + const size_t c_bpp_log2_mn = c_bpp_log2_m + CT::c_bpp_log2_n; + + // pre-multiply all output points by c_scalar_1div8 + // in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify()) + + // calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H + commitments.resize(values.size()); + for (size_t i = 0; i < values.size(); ++i) + CT::calc_pedersen_commitment(values[i] * c_scalar_1div8, masks[i] * c_scalar_1div8, commitments[i]); + + + // s.a. BP+ paper, page 15, eq. 11 + // decompose v into aL and aR: + // v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product + // aR = aL - (1, 1, ... 1) + // aR o aL = 0 + + // aLs = (aL_0, aL_1, ..., aL_m-1) -- `bit` matrix of c_bpp_m x c_bpp_n, each element is a scalar + + scalar_mat_t aLs(c_bpp_mn), aRs(c_bpp_mn); + aLs.zero(); + aRs.zero(); + // m >= values.size, first set up [0..values.size-1], then -- [values.size..m-1] (padding area) + for (size_t i = 0; i < values.size(); ++i) + { + const scalar_t& v = values[i]; + for (uint8_t j = 0; j < CT::c_bpp_n; ++j) + { + if (v.get_bit(j)) + aLs(i, j) = c_scalar_1; // aL = 1, aR = 0 + else + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + } + } + + for (size_t i = values.size(); i < c_bpp_m; ++i) + for (size_t j = 0; j < CT::c_bpp_n; ++j) + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + + + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, commitments); + + // BP+ paper, page 15: The prover begins with sending A = g^aL h^aR h^alpha (group element) + // so we calculate A0 = alpha * H + SUM(aL_i * G_i) + SUM(aR_i * H_i) + + scalar_t alpha = scalar_t::random(); + point_t A0 = alpha * CT::bpp_H; + + for (size_t i = 0; i < c_bpp_mn; ++i) + A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i); + + // part of 1/8 defense scheme + A0 *= c_scalar_1div8; + A0.to_public_key(sig.A0); + + DBG_VAL_PRINT(alpha); + DBG_VAL_PRINT(A0); + + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + scalar_t y = hsc.calc_hash(); + scalar_t z = hash_helper_t::hs(y); + e = z; // transcript for further steps + DBG_VAL_PRINT(y); + DBG_VAL_PRINT(z); + + // Computing vector d for aggregated version of the protocol (BP+ paper, page 17) + // (note: elements are stored column-by-column in memory) + // d = | 1 * z^(2*1), 1 * z^(2*2), 1 * z^(2*3), ..., 1 * z^(2*m) | + // | 2 * z^(2*1), 2 * z^(2*2), 2 * z^(2*3), ..., 2 * z^(2*m) | + // | 4 * z^(2*1), 4 * z^(2*2), 4 * z^(2*3), ..., 4 * z^(2*m) | + // | ....................................................................................... | + // | 2^(n-1) * z^(2*1), 2^(n-1) * z^(2*2), 2^(n-1) * z^(2*3), ..., 2^(n-1) * z^(2*m)) | + // Note: sum(d_i) = (2^n - 1) * ((z^2)^1 + (z^2)^2 + ... (z^2)^m)) = (2^n-1) * sum_of_powers(x^2, log(m)) + + scalar_t z_sq = z * z; + scalar_mat_t d(c_bpp_mn); + d(0, 0) = z_sq; + // first row + for (size_t i = 1; i < c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * z_sq; + // all rows + for (size_t j = 1; j < CT::c_bpp_n; ++j) + for (size_t i = 0; i < c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + + // calculate extended Vandermonde vector y = (1, y, y^2, ..., y^(mn+1)) (BP+ paper, page 18, Fig. 3) + // (calculate two more elements (1 and y^(mn+1)) for convenience) + scalar_vec_t y_powers(c_bpp_mn + 2); + y_powers[0] = 1; + for (size_t i = 1; i <= c_bpp_mn + 1; ++i) + y_powers[i] = y_powers[i - 1] * y; + + const scalar_t& y_mn_p1 = y_powers[c_bpp_mn + 1]; + + DBG_PRINT("Hs(y_powers): " << y_powers.calc_hs()); + + // aL_hat = aL - 1*z + scalar_vec_t aLs_hat = aLs - z; + // aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3) + scalar_vec_t aRs_hat = aRs + z; + for (size_t i = 0; i < c_bpp_mn; ++i) + aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i]; + + DBG_PRINT("Hs(aLs_hat): " << aLs_hat.calc_hs()); + DBG_PRINT("Hs(aRs_hat): " << aRs_hat.calc_hs()); + + // calculate alpha_hat + // alpha_hat = alpha + SUM(z^(2j) * gamma_j * y^(mn+1)) for j = 1..m + // i.e. \hat{\alpha} = \alpha + y^{m n+1} \sum_{j = 1}^{m} z^{2j} \gamma_j + scalar_t alpha_hat = 0; + for (size_t i = 0; i < masks.size(); ++i) + alpha_hat += d(i, 0) * masks[i]; + alpha_hat = alpha + y_mn_p1 * alpha_hat; + + DBG_VAL_PRINT(alpha_hat); + + // calculate 1, y^-1, y^-2, ... + const scalar_t y_inverse = y.reciprocal(); + scalar_vec_t y_inverse_powers(c_bpp_mn / 2 + 1); // the greatest power we need is c_bpp_mn/2 (at the first reduction round) + y_inverse_powers[0] = 1; + for (size_t i = 1, size = y_inverse_powers.size(); i < size; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inverse; + + // prepare generator's vector + std::vector g(c_bpp_mn), h(c_bpp_mn); + for (size_t i = 0; i < c_bpp_mn; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + + // WIP zk-argument called with zk-WIP(g, h, G, H, A_hat, aL_hat, aR_hat, alpha_hat) + + scalar_vec_t& a = aLs_hat; + scalar_vec_t& b = aRs_hat; + + sig.L.resize(c_bpp_log2_mn); + sig.R.resize(c_bpp_log2_mn); + + // zk-WIP reduction rounds (s.a. the preprint page 13 Fig. 1) + for (size_t n = c_bpp_mn / 2, ni = 0; n >= 1; n /= 2, ++ni) + { + DBG_PRINT(ENDL << "#" << ni); + + // zk-WIP(g, h, G, H, P, a, b, alpha) + + scalar_t dL = scalar_t::random(); + DBG_VAL_PRINT(dL); + scalar_t dR = scalar_t::random(); + DBG_VAL_PRINT(dR); + + // a = (a1, a2), b = (b1, b2) -- vectors of scalars + // cL = -- scalar + scalar_t cL = 0; + for (size_t i = 0; i < n; ++i) + cL += a[i] * y_powers[i + 1] * b[n + i]; + + DBG_VAL_PRINT(cL); + + // cR = * y^n -- scalar + scalar_t cR = 0; + for (size_t i = 0; i < n; ++i) + cR += a[n + i] * y_powers[i + 1] * b[i]; + cR *= y_powers[n]; + + DBG_VAL_PRINT(cR); + + // L = y^-n * a1 * g2 + b2 * h1 + cL * G + dL * H -- point + point_t sum = c_point_0; + for (size_t i = 0; i < n; ++i) + sum += a[i] * g[n + i]; + point_t L; + CT::calc_pedersen_commitment(cL, dL, L); + for (size_t i = 0; i < n; ++i) + L += b[n + i] * h[i]; + L += y_inverse_powers[n] * sum; + L *= c_scalar_1div8; + DBG_VAL_PRINT(L); + + // R = y^n * a2 * g1 + b1 * h2 + cR * G + dR * H -- point + sum.zero(); + for (size_t i = 0; i < n; ++i) + sum += a[n + i] * g[i]; + point_t R; + CT::calc_pedersen_commitment(cR, dR, R); + for (size_t i = 0; i < n; ++i) + R += b[i] * h[n + i]; + R += y_powers[n] * sum; + R *= c_scalar_1div8; + DBG_VAL_PRINT(R); + + // put L, R to the sig + L.to_public_key(sig.L[ni]); + R.to_public_key(sig.R[ni]); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[ni]); + hsc.add_pub_key(sig.R[ni]); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // recalculate arguments for the next round + scalar_t e_squared = e * e; + scalar_t e_inverse = e.reciprocal(); + scalar_t e_inverse_squared = e_inverse * e_inverse; + scalar_t e_y_inv_n = e * y_inverse_powers[n]; + scalar_t e_inv_y_n = e_inverse * y_powers[n]; + + // g_hat = e^-1 * g1 + (e * y^-n) * g2 -- vector of points + for (size_t i = 0; i < n; ++i) + g[i] = e_inverse * g[i] + e_y_inv_n * g[n + i]; + + // h_hat = e * h1 + e^-1 * h2 -- vector of points + for (size_t i = 0; i < n; ++i) + h[i] = e * h[i] + e_inverse * h[n + i]; + + // P_hat = e^2 * L + P + e^-2 * R -- point + + // a_hat = e * a1 + e^-1 * y^n * a2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + a[i] = e * a[i] + e_inv_y_n * a[n + i]; + + // b_hat = e^-1 * b1 + e * b2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + b[i] = e_inverse * b[i] + e * b[n + i]; + + // alpha_hat = e^2 * dL + alpha + e^-2 * dR -- scalar + alpha_hat += e_squared * dL + e_inverse_squared * dR; + + // run next iteraton zk-WIP(g_hat, h_hat, G, H, P_hat, a_hat, b_hat, alpha_hat) + } + DBG_PRINT(""); + + // zk-WIP last round + scalar_t r = scalar_t::random(); + scalar_t s = scalar_t::random(); + scalar_t delta = scalar_t::random(); + scalar_t eta = scalar_t::random(); + DBG_VAL_PRINT(r); + DBG_VAL_PRINT(s); + DBG_VAL_PRINT(delta); + DBG_VAL_PRINT(eta); + + // A = r * g + s * h + (r y b + s y a) * G + delta * H -- point + point_t A = c_point_0; + CT::calc_pedersen_commitment(y * (r * b[0] + s * a[0]), delta, A); + A += r * g[0] + s * h[0]; + A *= c_scalar_1div8; + A.to_public_key(sig.A); + DBG_VAL_PRINT(A); + + // B = (r * y * s) * G + eta * H + point_t B = c_point_0; + CT::calc_pedersen_commitment(r * y * s, eta, B); + B *= c_scalar_1div8; + B.to_public_key(sig.B); + DBG_VAL_PRINT(B); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // finalize the signature + sig.r = r + e * a[0]; + sig.s = s + e * b[0]; + sig.delta = eta + e * delta + e * e * alpha_hat; + DBG_VAL_PRINT(sig.r); + DBG_VAL_PRINT(sig.s); + DBG_VAL_PRINT(sig.delta); + + return true; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } // bpp_gen() + + + struct bpp_sig_commit_ref_t + { + bpp_sig_commit_ref_t(const bpp_signature& sig, const std::vector& commitments) + : sig(sig) + , commitments(commitments) + {} + const bpp_signature& sig; + const std::vector& commitments; + }; + + + template + bool bpp_verify(const std::vector& sigs, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + DBG_PRINT(ENDL << " . . . . bpp_verify() . . . . "); + + static_assert(CT::c_bpp_n <= 255, "too big N"); + const size_t kn = sigs.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(kn > 0, 1); + + struct intermediate_element_t + { + scalar_t y; + scalar_t z; + scalar_t z_sq; + scalar_vec_t e; + scalar_vec_t e_sq; + scalar_t e_final; + scalar_t e_final_sq; + size_t inv_e_offset; // offset in batch_for_inverse + size_t inv_y_offset; // offset in batch_for_inverse + size_t c_bpp_log2_m; + size_t c_bpp_m; + size_t c_bpp_mn; + point_t A; + point_t A0; + point_t B; + std::vector L; + std::vector R; + }; + std::vector interms(kn); + + size_t c_bpp_log2_m_max = 0; + for (size_t k = 0; k < kn; ++k) + { + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bsc.commitments.size() > 0, 2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() > 0 && sig.L.size() == sig.R.size(), 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.r.is_reduced() && sig.s.is_reduced() && sig.delta.is_reduced(), 4); + + intermediate_element_t& interm = interms[k]; + interm.c_bpp_log2_m = constexpr_ceil_log2(bsc.commitments.size()); + if (c_bpp_log2_m_max < interm.c_bpp_log2_m) + c_bpp_log2_m_max = interm.c_bpp_log2_m; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() == interm.c_bpp_log2_m + CT::c_bpp_log2_n, 5); + + interm.c_bpp_m = 1ull << interm.c_bpp_log2_m; + interm.c_bpp_mn = interm.c_bpp_m * CT::c_bpp_n; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A0.from_public_key(sig.A0), 6); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A.from_public_key(sig.A), 7); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.B.from_public_key(sig.B), 8); + interm.L.resize(sig.L.size()); + interm.R.resize(sig.R.size()); + for (size_t i = 0; i < interm.L.size(); ++i) + { + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.L[i].from_public_key(sig.L[i]), 9); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.R[i].from_public_key(sig.R[i]), 10); + } + } + const size_t c_bpp_m_max = 1ull << c_bpp_log2_m_max; + const size_t c_bpp_mn_max = c_bpp_m_max * CT::c_bpp_n; + const size_t c_bpp_LR_size_max = c_bpp_log2_m_max + CT::c_bpp_log2_n; + + + // + // prepare stuff + // + /* + std::vector g(c_bpp_mn_max), h(c_bpp_mn_max); + for (size_t i = 0; i < c_bpp_mn_max; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + */ + + scalar_vec_t batch_for_inverse; + batch_for_inverse.reserve(kn + kn * c_bpp_LR_size_max); + + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // restore y and z + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, bsc.commitments); + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + hsc.assign_calc_hash(interm.y); + interm.z = hash_helper_t::hs(interm.y); + interm.z_sq = interm.z * interm.z; + DBG_VAL_PRINT(interm.y); + DBG_VAL_PRINT(interm.z); + e = interm.z; // transcript for further steps + + interm.inv_y_offset = batch_for_inverse.size(); + batch_for_inverse.push_back(interm.y); + interm.inv_e_offset = batch_for_inverse.size(); + + interm.e.resize(sig.L.size()); + interm.e_sq.resize(sig.L.size()); + + for (size_t i = 0; i < sig.L.size(); ++i) + { + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[i]); + hsc.add_pub_key(sig.R[i]); + hsc.assign_calc_hash(e); + interm.e[i] = e; + interm.e_sq[i] = e * e; + DBG_PRINT("e[" << i << "]: " << e); + batch_for_inverse.push_back(e); + } + + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + hsc.assign_calc_hash(interm.e_final); + interm.e_final_sq = interm.e_final * interm.e_final; + DBG_VAL_PRINT(interm.e_final); + } + + batch_for_inverse.invert(); + + // Notation: + // 1_vec ^ n = (1, 1, 1, ..., 1) + // 2_vec ^ n = (2^0, 2^1, 2^2, ..., 2^(n-1)) + // -1_vec ^ n = ((-1)^0, (-1)^1, (-1)^2, ... (-1)^(n-1)) = (1, -1, 1, -1, ...) + // y<^n = (y^n, y^(n-1), ..., y^1) + // y>^n = (y^1, y^2, ..., y^n) + + // from page 13, Fig 1: + // Verifier outputs Accept IFF the following equality holds (single proof): + // P^e^2 * A^e * B == g ^ (r' e) * h ^ (s' e) * G ^ (r' y s') * H ^ delta' + // (where g and h are calculated in each round) + // The same equation in additive notation: + // e^2 * P + e * A + B == (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H + // <=> + // (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H - e^2 * P - e * A - B == 0 (*) + // where A, B, r', s', delta' is taken from the signature + // and P_{k+1} = e^2 * L_k + P_k + e^-2 * R_k for all rounds + // + // from page 18, Fig 3: + // P and V computes: + // A_hat = A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // (calculated once) + // + // As suggested in Section 6.1 "Practical Optimizations": + // 1) g and h exponentianions can be optimized in order not to be calculated at each round as the following (page 20): + // + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - + // - e^2 * A_hat + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 (**) + // + // where: + // g, h - vector of fixed generators + // s_vec_i = y^(1-i) * PROD{j=1..log(n)}(e_j ^ b(i,j)) + // s'_vec_i = PROD{j=1..log(n)}(e_j ^ -b(i,j)) + // b(i, j) = { 2 * ((1<<(j-1)) & (i-1)) - 1) (counting both from 1) (page 20) + // b(i, j) = { 2 * ((1< + + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - + // - e^2 * (A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // ) + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 + + // => + + // (for single signature) + // + // (r' * e * s_vec - e^2 * (- 1_vec^(mn) * z)) * g | these are + // + (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) * h | fixed generators + // + (r' y s' - e^2 * ((z - z^2)*SUM(y^>mn) - z*y^(mn+1)*SUM(d)) * G | across all + // + delta' * H | the signatures + // + // - e^2 * A0 + // - e^2 * y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j)) + // - e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + // - e * A - B = 0 (***) + // + // All (***) will be muptiplied by random weightning factor and then summed up. + + // Calculate cummulative sclalar multiplicand for fixed generators across all the sigs. + scalar_vec_t g_scalars; + g_scalars.resize(c_bpp_mn_max, 0); + scalar_vec_t h_scalars; + h_scalars.resize(c_bpp_mn_max, 0); + scalar_t G_scalar = 0; + scalar_t H_scalar = 0; + point_t summand = c_point_0; + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // random weightning factor for speed-optimized batch verification (preprint page 20) + const scalar_t rwf = scalar_t::random(); + DBG_PRINT("rwf: " << rwf); + + // prepare d vector (see also d structure description in proof function) + scalar_mat_t d(interm.c_bpp_mn); + d(0, 0) = interm.z_sq; + // first row + for (size_t i = 1; i < interm.c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * interm.z_sq; + // all rows + for (size_t j = 1; j < CT::c_bpp_n; ++j) + for (size_t i = 0; i < interm.c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + // sum(d) (see also note in proof function for this) + const scalar_t sum_d = CT::get_2_to_the_power_of_N_minus_1() * sum_of_powers(interm.z_sq, interm.c_bpp_log2_m); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + DBG_PRINT("sum(d): " << sum_d); + + const scalar_t& y_inv = batch_for_inverse[interm.inv_y_offset]; + auto get_e_inv = [&](size_t i) { return batch_for_inverse[interm.inv_e_offset + i]; }; // i belongs to [0; L.size()-1] + + // prepare s_vec (unlike the paper here we moved y-component out of s_vec for convenience, so s_vec'[x] = s_vec[~x & (MN-1)]) + // complexity (sc_mul's): MN+2*log2(MN)-2 + // the idea is the following: + // s_vec[00000b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^-1 * (e_1)^-1 * (e_0)^-1 + // s_vec[00101b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^+1 * (e_1)^-1 * (e_0)^+1 + const size_t log2_mn = sig.L.size(); // at the beginning we made sure that sig.L.size() == c_bpp_log2_m + c_bpp_log2_n + scalar_vec_t s_vec(interm.c_bpp_mn); + s_vec[0] = get_e_inv(0); + for (size_t i = 1; i < log2_mn; ++i) + s_vec[0] *= get_e_inv(i); // s_vec[0] = (e_0)^-1 * (e_1)^-1 * .. (e_{log2_mn-1})^-1 + DBG_PRINT("[0] " << s_vec[0]); + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + { + size_t base_el_index = i & (i - 1); // base element index: 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10... base element differs in one bit (0) from the current one (1) + size_t bit_index = log2_mn - calc_lsb_32((uint32_t)i) - 1; // the bit index where current element has the difference with the base + s_vec[i] = s_vec[base_el_index] * interm.e_sq[bit_index]; // (e_j)^-1 * (e_j)^2 = (e_j)^+1 + DBG_PRINT("[" << i << "] " << " " << base_el_index << ", " << bit_index << " : " << s_vec[i]); + } + + // prepare y_inv vector + scalar_vec_t y_inverse_powers(interm.c_bpp_mn); + y_inverse_powers[0] = 1; + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inv; + + // y^(mn+1) + scalar_t y_power_mnp1 = interm.y; + for (size_t i = 0; i < log2_mn; ++i) + y_power_mnp1 *= y_power_mnp1; + y_power_mnp1 *= interm.y; + DBG_VAL_PRINT(y_power_mnp1); + + // now calculate all multiplicands for common generators + + // g vector multiplicands: + // rwf * (r' * e * (1, y^-1, y^-2, ...) o s_vec + e^2 * z) = + // rwf * r' * e * ((1, y^-1, ...) o s_vec) + rwf * e^2 * z * (1, 1, ...) + scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_r_e = rwf * interm.e_final * sig.r; + for (size_t i = 0; i < interm.c_bpp_mn; ++i) + g_scalars[i] += rwf_r_e * y_inverse_powers[i] * s_vec[i] + rwf_e_sq_z; + + DBG_PRINT("Hs(g_scalars): " << g_scalars.calc_hs()); + + // h vector multiplicands: + // rwf * (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) + // rwf * s' * e * s'_vec - rwf * e^2 * z * (1, 1...) - rwf * e^2 * (d o y<^(mn)) + //scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_s_e = rwf * sig.s * interm.e_final; + scalar_t rwf_e_sq_y = rwf * interm.e_final_sq * interm.y; + for (size_t i = interm.c_bpp_mn - 1; i != SIZE_MAX; --i) + { + h_scalars[i] += rwf_s_e * s_vec[interm.c_bpp_mn - 1 - i] - rwf_e_sq_z - rwf_e_sq_y * d[i]; + rwf_e_sq_y *= interm.y; + } + + DBG_PRINT("Hs(h_scalars): " << h_scalars.calc_hs()); + + // G point multiplicands: + // rwf * (r' y s' - e ^ 2 * ((z - z ^ 2)*SUM(y^>mn) - z * y^(mn+1) * SUM(d)) = + // = rwf * r' y s' - rwf * e^2 * (z - z ^ 2)*SUM(y^>mn) + rwf * e^2 * z * y^(mn+1) * SUM(d) + G_scalar += rwf * sig.r * interm.y * sig.s + rwf_e_sq_y * sum_d * interm.z; + G_scalar -= rwf * interm.e_final_sq * (interm.z - interm.z_sq) * sum_of_powers(interm.y, log2_mn); + DBG_PRINT("sum_y: " << sum_of_powers(interm.y, log2_mn)); + DBG_PRINT("G_scalar: " << G_scalar); + + // H point multiplicands: + // rwf * delta + H_scalar += rwf * sig.delta; + DBG_PRINT("H_scalar: " << H_scalar); + + // uncommon generators' multiplicands + point_t summand_8 = c_point_0; // this summand to be multiplied by 8 before adding to the main summand + // - rwf * e^2 * A0 + summand_8 -= rwf * interm.e_final_sq * interm.A0; + DBG_PRINT("A0_scalar: " << c_scalar_Lm1 * interm.e_final_sq * rwf); + + // - rwf * e^2 * y^(mn+1) * (SUM{j=1..m} (z^2)^j * V_j)) + scalar_t e_sq_y_mn1_z_sq_power = rwf * interm.e_final_sq * y_power_mnp1; + for (size_t j = 0; j < bsc.commitments.size(); ++j) + { + e_sq_y_mn1_z_sq_power *= interm.z_sq; + summand_8 -= e_sq_y_mn1_z_sq_power * bsc.commitments[j]; + DBG_PRINT("V_scalar[" << j << "]: " << c_scalar_Lm1 * e_sq_y_mn1_z_sq_power); + } + + // - rwf * e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + scalar_t rwf_e_sq = rwf * interm.e_final_sq; + for (size_t j = 0; j < log2_mn; ++j) + { + summand_8 -= rwf_e_sq * (interm.e_sq[j] * interm.L[j] + get_e_inv(j) * get_e_inv(j) * interm.R[j]); + DBG_PRINT("L_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * interm.e_sq[j]); + DBG_PRINT("R_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * get_e_inv(j) * get_e_inv(j)); + } + + // - rwf * e * A - rwf * B = 0 + summand_8 -= rwf * interm.e_final * interm.A + rwf * interm.B; + DBG_PRINT("A_scalar: " << c_scalar_Lm1 * rwf * interm.e_final); + DBG_PRINT("B_scalar: " << c_scalar_Lm1 * rwf); + + summand_8.modify_mul8(); + summand += summand_8; + } + + point_t GH_exponents = c_point_0; + CT::calc_pedersen_commitment(G_scalar, H_scalar, GH_exponents); + bool result = multiexp_and_check_being_zero(g_scalars, h_scalars, summand + GH_exponents); + if (result) + DBG_PRINT(ENDL << " . . . . bpp_verify() -- SUCCEEDED!!!" << ENDL); + return result; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } + +} // namespace crypto diff --git a/src/crypto/range_proof_bppe.h b/src/crypto/range_proof_bppe.h new file mode 100644 index 00000000..7aaed80c --- /dev/null +++ b/src/crypto/range_proof_bppe.h @@ -0,0 +1,719 @@ +// Copyright (c) 2022 Zano Project (https://zano.org/) +// Copyright (c) 2022 sowle (val@zano.org, crypto.sowle@gmail.com) +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#pragma once + +// +// This file contains the implementation of range proof protocol. +// Namely, Bulletproofs+ https://eprint.iacr.org/2020/735 +// Double-blinded commitments extension implemented as in Appendix D in the Zarcanum whitepaper: https://eprint.iacr.org/2021/1478 + +namespace crypto +{ + struct bppe_signature + { + std::vector L; // size = log_2(m * n) + std::vector R; + public_key A0; + public_key A; + public_key B; + scalar_t r; + scalar_t s; + scalar_t delta_1; + scalar_t delta_2; + }; + +#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL +#define DBG_PRINT(x) std::cout << x << ENDL + + template + bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, bppe_signature& sig, std::vector& commitments, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bppe_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + static_assert(CT::c_bpp_n <= 255, "too big N"); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size() && masks.size() == masks2.size(), 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced() && masks2.is_reduced(), 3); + + const size_t c_bpp_log2_m = constexpr_ceil_log2(values.size()); + const size_t c_bpp_m = 1ull << c_bpp_log2_m; + const size_t c_bpp_mn = c_bpp_m * CT::c_bpp_n; + const size_t c_bpp_log2_mn = c_bpp_log2_m + CT::c_bpp_log2_n; + + // pre-multiply all output points by c_scalar_1div8 + // in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify()) + + // calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H + 1/8 * masks2[i] * H2 + commitments.resize(values.size()); + for (size_t i = 0; i < values.size(); ++i) + CT::calc_pedersen_commitment_2(values[i] * c_scalar_1div8, masks[i] * c_scalar_1div8, masks2[i] * c_scalar_1div8, commitments[i]); + + + // s.a. BP+ paper, page 15, eq. 11 + // decompose v into aL and aR: + // v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product + // aR = aL - (1, 1, ... 1) + // aR o aL = 0 + + // aLs = (aL_0, aL_1, ..., aL_m-1) -- `bit` matrix of c_bpp_m x c_bpp_n, each element is a scalar + + scalar_mat_t aLs(c_bpp_mn), aRs(c_bpp_mn); + aLs.zero(); + aRs.zero(); + // m >= values.size, first set up [0..values.size-1], then -- [values.size..m-1] (padding area) + for (size_t i = 0; i < values.size(); ++i) + { + const scalar_t& v = values[i]; + for (uint8_t j = 0; j < CT::c_bpp_n; ++j) + { + if (v.get_bit(j)) + aLs(i, j) = c_scalar_1; // aL = 1, aR = 0 + else + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + } + } + + for (size_t i = values.size(); i < c_bpp_m; ++i) + for (size_t j = 0; j < CT::c_bpp_n; ++j) + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + + + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, commitments); + + // Zarcanum paper, page 33, Fig. D.3: The prover chooses alpha_1, alpha_2 and computes A = g^aL h^aR h_1^alpha_1 h_2^alpha_2 + // so we calculate A0 = alpha_1 * H + alpha_2 * H_2 + SUM(aL_i * G_i) + SUM(aR_i * H_i) + + scalar_t alpha_1 = scalar_t::random(), alpha_2 = scalar_t::random(); + point_t A0 = alpha_1 * CT::bpp_H + alpha_2 * CT::bpp_H2; + + for (size_t i = 0; i < c_bpp_mn; ++i) + A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i); + + // part of 1/8 defense scheme + A0 *= c_scalar_1div8; + A0.to_public_key(sig.A0); + + DBG_VAL_PRINT(alpha_1); + DBG_VAL_PRINT(alpha_2); + DBG_VAL_PRINT(A0); + + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + scalar_t y = hsc.calc_hash(); + scalar_t z = hash_helper_t::hs(y); + e = z; // transcript for further steps + DBG_VAL_PRINT(y); + DBG_VAL_PRINT(z); + + // Computing vector d for aggregated version of the protocol (BP+ paper, page 17) + // (note: elements are stored column-by-column in memory) + // d = | 1 * z^(2*1), 1 * z^(2*2), 1 * z^(2*3), ..., 1 * z^(2*m) | + // | 2 * z^(2*1), 2 * z^(2*2), 2 * z^(2*3), ..., 2 * z^(2*m) | + // | 4 * z^(2*1), 4 * z^(2*2), 4 * z^(2*3), ..., 4 * z^(2*m) | + // | ....................................................................................... | + // | 2^(n-1) * z^(2*1), 2^(n-1) * z^(2*2), 2^(n-1) * z^(2*3), ..., 2^(n-1) * z^(2*m)) | + // Note: sum(d_i) = (2^n - 1) * ((z^2)^1 + (z^2)^2 + ... (z^2)^m)) = (2^n-1) * sum_of_powers(x^2, log(m)) + + scalar_t z_sq = z * z; + scalar_mat_t d(c_bpp_mn); + d(0, 0) = z_sq; + // first row + for (size_t i = 1; i < c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * z_sq; + // all rows + for (size_t j = 1; j < CT::c_bpp_n; ++j) + for (size_t i = 0; i < c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + + // calculate extended Vandermonde vector y = (1, y, y^2, ..., y^(mn+1)) (BP+ paper, page 18, Fig. 3) + // (calculate two more elements (1 and y^(mn+1)) for convenience) + scalar_vec_t y_powers(c_bpp_mn + 2); + y_powers[0] = 1; + for (size_t i = 1; i <= c_bpp_mn + 1; ++i) + y_powers[i] = y_powers[i - 1] * y; + + const scalar_t& y_mn_p1 = y_powers[c_bpp_mn + 1]; + + DBG_PRINT("Hs(y_powers): " << y_powers.calc_hs()); + + // aL_hat = aL - 1*z + scalar_vec_t aLs_hat = aLs - z; + // aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3) + scalar_vec_t aRs_hat = aRs + z; + for (size_t i = 0; i < c_bpp_mn; ++i) + aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i]; + + DBG_PRINT("Hs(aLs_hat): " << aLs_hat.calc_hs()); + DBG_PRINT("Hs(aRs_hat): " << aRs_hat.calc_hs()); + + // calculate alpha_hat + // alpha_hat_1 = alpha_1 + SUM(z^(2j) * gamma_1,j * y^(mn+1)) for j = 1..m + // alpha_hat_2 = alpha_2 + SUM(z^(2j) * gamma_2,j * y^(mn+1)) for j = 1..m + // i.e. \hat{\alpha} = \alpha + y^{m n+1} \sum_{j = 1}^{m} z^{2j} \gamma_j + scalar_t alpha_hat_1 = 0, alpha_hat_2 = 0; + for (size_t i = 0; i < masks.size(); ++i) + { + alpha_hat_1 += d(i, 0) * masks[i]; + alpha_hat_2 += d(i, 0) * masks2[i]; + } + alpha_hat_1 = alpha_1 + y_mn_p1 * alpha_hat_1; + alpha_hat_2 = alpha_2 + y_mn_p1 * alpha_hat_2; + + DBG_VAL_PRINT(alpha_hat_1); + DBG_VAL_PRINT(alpha_hat_2); + + // calculate 1, y^-1, y^-2, ... + const scalar_t y_inverse = y.reciprocal(); + scalar_vec_t y_inverse_powers(c_bpp_mn / 2 + 1); // the greatest power we need is c_bpp_mn/2 (at the first reduction round) + y_inverse_powers[0] = 1; + for (size_t i = 1, size = y_inverse_powers.size(); i < size; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inverse; + + // prepare generator's vector + std::vector g(c_bpp_mn), h(c_bpp_mn); + for (size_t i = 0; i < c_bpp_mn; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + + // WIP zk-argument called with zk-WIP(g, h, G, H, H2, A_hat, aL_hat, aR_hat, alpha_hat_1, alpha_hat_2) + + scalar_vec_t& a = aLs_hat; + scalar_vec_t& b = aRs_hat; + + sig.L.resize(c_bpp_log2_mn); + sig.R.resize(c_bpp_log2_mn); + + // zk-WIP reduction rounds (s.a. Zarcanum preprint page 24 Fig. D.1) + for (size_t n = c_bpp_mn / 2, ni = 0; n >= 1; n /= 2, ++ni) + { + DBG_PRINT(ENDL << "#" << ni); + + // zk-WIP(g, h, G, H, H2, P, a, b, alpha_1, alpha_2) + + scalar_t dL = scalar_t::random(), dL2 = scalar_t::random(); + DBG_VAL_PRINT(dL); DBG_VAL_PRINT(dL2); + scalar_t dR = scalar_t::random(), dR2 = scalar_t::random(); + DBG_VAL_PRINT(dR); DBG_VAL_PRINT(dR2); + + // a = (a1, a2), b = (b1, b2) -- vectors of scalars + // cL = -- scalar + scalar_t cL = 0; + for (size_t i = 0; i < n; ++i) + cL += a[i] * y_powers[i + 1] * b[n + i]; + + DBG_VAL_PRINT(cL); + + // cR = * y^n -- scalar + scalar_t cR = 0; + for (size_t i = 0; i < n; ++i) + cR += a[n + i] * y_powers[i + 1] * b[i]; + cR *= y_powers[n]; + + DBG_VAL_PRINT(cR); + + // L = y^-n * a1 * g2 + b2 * h1 + cL * G + dL * H + dL2 * H2 -- point + point_t sum = c_point_0; + for (size_t i = 0; i < n; ++i) + sum += a[i] * g[n + i]; + point_t L; + CT::calc_pedersen_commitment_2(cL, dL, dL2, L); + for (size_t i = 0; i < n; ++i) + L += b[n + i] * h[i]; + L += y_inverse_powers[n] * sum; + L *= c_scalar_1div8; + DBG_VAL_PRINT(L); + + // R = y^n * a2 * g1 + b1 * h2 + cR * G + dR * H + dR2 * H2 -- point + sum.zero(); + for (size_t i = 0; i < n; ++i) + sum += a[n + i] * g[i]; + point_t R; + CT::calc_pedersen_commitment_2(cR, dR, dR2, R); + for (size_t i = 0; i < n; ++i) + R += b[i] * h[n + i]; + R += y_powers[n] * sum; + R *= c_scalar_1div8; + DBG_VAL_PRINT(R); + + // put L, R to the sig + L.to_public_key(sig.L[ni]); + R.to_public_key(sig.R[ni]); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[ni]); + hsc.add_pub_key(sig.R[ni]); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // recalculate arguments for the next round + scalar_t e_squared = e * e; + scalar_t e_inverse = e.reciprocal(); + scalar_t e_inverse_squared = e_inverse * e_inverse; + scalar_t e_y_inv_n = e * y_inverse_powers[n]; + scalar_t e_inv_y_n = e_inverse * y_powers[n]; + + // g_hat = e^-1 * g1 + (e * y^-n) * g2 -- vector of points + for (size_t i = 0; i < n; ++i) + g[i] = e_inverse * g[i] + e_y_inv_n * g[n + i]; + + // h_hat = e * h1 + e^-1 * h2 -- vector of points + for (size_t i = 0; i < n; ++i) + h[i] = e * h[i] + e_inverse * h[n + i]; + + // P_hat = e^2 * L + P + e^-2 * R -- point + + // a_hat = e * a1 + e^-1 * y^n * a2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + a[i] = e * a[i] + e_inv_y_n * a[n + i]; + + // b_hat = e^-1 * b1 + e * b2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + b[i] = e_inverse * b[i] + e * b[n + i]; + + // alpha_hat_1 = e^2 * dL + alpha_1 + e^-2 * dR -- scalar + // alpha_hat_2 = e^2 * dL2 + alpha_2 + e^-2 * dR2 -- scalar + alpha_hat_1 += e_squared * dL + e_inverse_squared * dR; + alpha_hat_2 += e_squared * dL2 + e_inverse_squared * dR2; + + // run next iteraton zk-WIP(g_hat, h_hat, G, H, H2, P_hat, a_hat, b_hat, alpha_hat_1, alpha_hat_2) + } + DBG_PRINT(""); + + // zk-WIP last round + scalar_t r = scalar_t::random(); + scalar_t s = scalar_t::random(); + scalar_t delta_1 = scalar_t::random(), delta_2 = scalar_t::random(); + scalar_t eta_1 = scalar_t::random(), eta_2 = scalar_t::random(); + DBG_VAL_PRINT(r); + DBG_VAL_PRINT(s); + DBG_VAL_PRINT(delta_1); DBG_VAL_PRINT(delta_2); + DBG_VAL_PRINT(eta_1); DBG_VAL_PRINT(eta_2); + + // A = r * g + s * h + (r y b + s y a) * G + delta_1 * H + delta_2 * H2 -- point + point_t A = c_point_0; + CT::calc_pedersen_commitment_2(y * (r * b[0] + s * a[0]), delta_1, delta_2, A); + A += r * g[0] + s * h[0]; + A *= c_scalar_1div8; + A.to_public_key(sig.A); + DBG_VAL_PRINT(A); + + // B = (r * y * s) * G + eta_1 * H + eta_2 * H2 + point_t B = c_point_0; + CT::calc_pedersen_commitment_2(r * y * s, eta_1, eta_2, B); + B *= c_scalar_1div8; + B.to_public_key(sig.B); + DBG_VAL_PRINT(B); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // finalize the signature + sig.r = r + e * a[0]; + sig.s = s + e * b[0]; + sig.delta_1 = eta_1 + e * delta_1 + e * e * alpha_hat_1; + sig.delta_2 = eta_2 + e * delta_2 + e * e * alpha_hat_2; + DBG_VAL_PRINT(sig.r); + DBG_VAL_PRINT(sig.s); + DBG_VAL_PRINT(sig.delta_1); + DBG_VAL_PRINT(sig.delta_2); + + return true; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } // bppe_gen() + + + struct bppe_sig_commit_ref_t + { + bppe_sig_commit_ref_t(const bppe_signature& sig, const std::vector& commitments) + : sig(sig) + , commitments(commitments) + {} + const bppe_signature& sig; + const std::vector& commitments; + }; + + + template + bool bppe_verify(const std::vector& sigs, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bppe_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + DBG_PRINT(ENDL << " . . . . bppe_verify() . . . . "); + + static_assert(CT::c_bpp_n <= 255, "too big N"); + const size_t kn = sigs.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(kn > 0, 1); + + struct intermediate_element_t + { + scalar_t y; + scalar_t z; + scalar_t z_sq; + scalar_vec_t e; + scalar_vec_t e_sq; + scalar_t e_final; + scalar_t e_final_sq; + size_t inv_e_offset; // offset in batch_for_inverse + size_t inv_y_offset; // offset in batch_for_inverse + size_t c_bpp_log2_m; + size_t c_bpp_m; + size_t c_bpp_mn; + point_t A; + point_t A0; + point_t B; + std::vector L; + std::vector R; + }; + std::vector interms(kn); + + size_t c_bpp_log2_m_max = 0; + for (size_t k = 0; k < kn; ++k) + { + const bppe_sig_commit_ref_t& bsc = sigs[k]; + const bppe_signature& sig = bsc.sig; + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bsc.commitments.size() > 0, 2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() > 0 && sig.L.size() == sig.R.size(), 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.r.is_reduced() && sig.s.is_reduced() && sig.delta_1.is_reduced() && sig.delta_2.is_reduced(), 4); + + intermediate_element_t& interm = interms[k]; + interm.c_bpp_log2_m = constexpr_ceil_log2(bsc.commitments.size()); + if (c_bpp_log2_m_max < interm.c_bpp_log2_m) + c_bpp_log2_m_max = interm.c_bpp_log2_m; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() == interm.c_bpp_log2_m + CT::c_bpp_log2_n, 5); + + interm.c_bpp_m = 1ull << interm.c_bpp_log2_m; + interm.c_bpp_mn = interm.c_bpp_m * CT::c_bpp_n; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A0.from_public_key(sig.A0), 6); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A.from_public_key(sig.A), 7); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.B.from_public_key(sig.B), 8); + interm.L.resize(sig.L.size()); + interm.R.resize(sig.R.size()); + for (size_t i = 0; i < interm.L.size(); ++i) + { + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.L[i].from_public_key(sig.L[i]), 9); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.R[i].from_public_key(sig.R[i]), 10); + } + } + const size_t c_bpp_m_max = 1ull << c_bpp_log2_m_max; + const size_t c_bpp_mn_max = c_bpp_m_max * CT::c_bpp_n; + const size_t c_bpp_LR_size_max = c_bpp_log2_m_max + CT::c_bpp_log2_n; + + + // + // prepare stuff + // + /* + std::vector g(c_bpp_mn_max), h(c_bpp_mn_max); + for (size_t i = 0; i < c_bpp_mn_max; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + */ + + scalar_vec_t batch_for_inverse; + batch_for_inverse.reserve(kn + kn * c_bpp_LR_size_max); + + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bppe_sig_commit_ref_t& bsc = sigs[k]; + const bppe_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // restore y and z + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, bsc.commitments); + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + hsc.assign_calc_hash(interm.y); + interm.z = hash_helper_t::hs(interm.y); + interm.z_sq = interm.z * interm.z; + DBG_VAL_PRINT(interm.y); + DBG_VAL_PRINT(interm.z); + e = interm.z; // transcript for further steps + + interm.inv_y_offset = batch_for_inverse.size(); + batch_for_inverse.push_back(interm.y); + interm.inv_e_offset = batch_for_inverse.size(); + + interm.e.resize(sig.L.size()); + interm.e_sq.resize(sig.L.size()); + + for (size_t i = 0; i < sig.L.size(); ++i) + { + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[i]); + hsc.add_pub_key(sig.R[i]); + hsc.assign_calc_hash(e); + interm.e[i] = e; + interm.e_sq[i] = e * e; + DBG_PRINT("e[" << i << "]: " << e); + batch_for_inverse.push_back(e); + } + + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + hsc.assign_calc_hash(interm.e_final); + interm.e_final_sq = interm.e_final * interm.e_final; + DBG_VAL_PRINT(interm.e_final); + } + + batch_for_inverse.invert(); + + // Notation: + // 1_vec ^ n = (1, 1, 1, ..., 1) + // 2_vec ^ n = (2^0, 2^1, 2^2, ..., 2^(n-1)) + // -1_vec ^ n = ((-1)^0, (-1)^1, (-1)^2, ... (-1)^(n-1)) = (1, -1, 1, -1, ...) + // y<^n = (y^n, y^(n-1), ..., y^1) + // y>^n = (y^1, y^2, ..., y^n) + + // from Zarcanum page 24, Fig D.1: + // Verifier outputs Accept IFF the following holds: + // P^e^2 * A^e * B == g ^ (r' e) * h ^ (s' e) * G ^ (r' y s') * H ^ delta'_1 * H2 ^ delta'_2 + // (where g and h are calculated in each round) + // The same equation in additive notation: + // e^2 * P + e * A + B == (r' * e) * g + (s' * e) * h + (r' y s') * G + delta'_1 * H + delta'_2 * H2 + // <=> + // (r' * e) * g + (s' * e) * h + (r' y s') * G + delta'_1 * H + delta'_2 * H2 - e^2 * P - e * A - B == 0 (*) + // where A, B, r', s', delta'_1, delta'_2 is taken from the signature + // and P_{k+1} = e^2 * L_k + P_k + e^-2 * R_k for all rounds + // + // from Zarcanum preprint page 33, Fig D.3: + // P and V computes: + // A_hat = A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // (calculated once) + // + // As suggested in BPP preprint Section 6.1 "Practical Optimizations": + // 1) g and h exponentianions can be optimized in order not to be calculated at each round + // as the following (page 20, with delta'_2 and H2 added): + // + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta'_1 * H + delta'_2 * H2 - + // - e^2 * A_hat + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 (**) + // + // where: + // g, h - vector of fixed generators + // s_vec_i = y^(1-i) * PROD{j=1..log(n)}(e_j ^ b(i,j)) + // s'_vec_i = PROD{j=1..log(n)}(e_j ^ -b(i,j)) + // b(i, j) = { 2 * ((1<<(j-1)) & (i-1)) - 1) (counting both from 1) (page 20) + // b(i, j) = { 2 * ((1< + + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta'_1 * H + delta'_2 * H2 - + // - e^2 * (A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // ) + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 + + // => + + // (for single signature) + // + // (r' * e * s_vec - e^2 * (- 1_vec^(mn) * z)) * g | these are + // + (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) * h | fixed generators + // + (r' y s' - e^2 * ((z - z^2)*SUM(y^>mn) - z*y^(mn+1)*SUM(d)) * G | across all + // + delta'_1 * H | the signatures + // + delta'_2 * H2 | the signatures + // + // - e^2 * A0 + // - e^2 * y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j)) + // - e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + // - e * A - B = 0 (***) + // + // All (***) will be muptiplied by random weightning factor and then summed up. + + // Calculate cummulative sclalar multiplicand for fixed generators across all the sigs. + scalar_vec_t g_scalars; + g_scalars.resize(c_bpp_mn_max, 0); + scalar_vec_t h_scalars; + h_scalars.resize(c_bpp_mn_max, 0); + scalar_t G_scalar = 0; + scalar_t H_scalar = 0; + scalar_t H2_scalar = 0; + point_t summand = c_point_0; + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bppe_sig_commit_ref_t& bsc = sigs[k]; + const bppe_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // random weightning factor for speed-optimized batch verification (preprint page 20) + const scalar_t rwf = scalar_t::random(); + DBG_PRINT("rwf: " << rwf); + + // prepare d vector (see also d structure description in proof function) + scalar_mat_t d(interm.c_bpp_mn); + d(0, 0) = interm.z_sq; + // first row + for (size_t i = 1; i < interm.c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * interm.z_sq; + // all rows + for (size_t j = 1; j < CT::c_bpp_n; ++j) + for (size_t i = 0; i < interm.c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + // sum(d) (see also note in proof function for this) + const scalar_t sum_d = CT::get_2_to_the_power_of_N_minus_1() * sum_of_powers(interm.z_sq, interm.c_bpp_log2_m); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + DBG_PRINT("sum(d): " << sum_d); + + const scalar_t& y_inv = batch_for_inverse[interm.inv_y_offset]; + auto get_e_inv = [&](size_t i) { return batch_for_inverse[interm.inv_e_offset + i]; }; // i belongs to [0; L.size()-1] + + // prepare s_vec (unlike the paper here we moved y-component out of s_vec for convenience, so s_vec'[x] = s_vec[~x & (MN-1)]) + // complexity (sc_mul's): MN+2*log2(MN)-2 + // the idea is the following: + // s_vec[00000b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^-1 * (e_1)^-1 * (e_0)^-1 + // s_vec[00101b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^+1 * (e_1)^-1 * (e_0)^+1 + const size_t log2_mn = sig.L.size(); // at the beginning we made sure that sig.L.size() == c_bpp_log2_m + c_bpp_log2_n + scalar_vec_t s_vec(interm.c_bpp_mn); + s_vec[0] = get_e_inv(0); + for (size_t i = 1; i < log2_mn; ++i) + s_vec[0] *= get_e_inv(i); // s_vec[0] = (e_0)^-1 * (e_1)^-1 * .. (e_{log2_mn-1})^-1 + DBG_PRINT("[0] " << s_vec[0]); + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + { + size_t base_el_index = i & (i - 1); // base element index: 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10... base element differs in one bit (0) from the current one (1) + size_t bit_index = log2_mn - calc_lsb_32((uint32_t)i) - 1; // the bit index where current element has the difference with the base + s_vec[i] = s_vec[base_el_index] * interm.e_sq[bit_index]; // (e_j)^-1 * (e_j)^2 = (e_j)^+1 + DBG_PRINT("[" << i << "] " << " " << base_el_index << ", " << bit_index << " : " << s_vec[i]); + } + + // prepare y_inv vector + scalar_vec_t y_inverse_powers(interm.c_bpp_mn); + y_inverse_powers[0] = 1; + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inv; + + // y^(mn+1) + scalar_t y_power_mnp1 = interm.y; + for (size_t i = 0; i < log2_mn; ++i) + y_power_mnp1 *= y_power_mnp1; + y_power_mnp1 *= interm.y; + DBG_VAL_PRINT(y_power_mnp1); + + // now calculate all multiplicands for common generators + + // g vector multiplicands: + // rwf * (r' * e * (1, y^-1, y^-2, ...) o s_vec + e^2 * z) = + // rwf * r' * e * ((1, y^-1, ...) o s_vec) + rwf * e^2 * z * (1, 1, ...) + scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_r_e = rwf * interm.e_final * sig.r; + for (size_t i = 0; i < interm.c_bpp_mn; ++i) + g_scalars[i] += rwf_r_e * y_inverse_powers[i] * s_vec[i] + rwf_e_sq_z; + + DBG_PRINT("Hs(g_scalars): " << g_scalars.calc_hs()); + + // h vector multiplicands: + // rwf * (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) + // rwf * s' * e * s'_vec - rwf * e^2 * z * (1, 1...) - rwf * e^2 * (d o y<^(mn)) + //scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_s_e = rwf * sig.s * interm.e_final; + scalar_t rwf_e_sq_y = rwf * interm.e_final_sq * interm.y; + for (size_t i = interm.c_bpp_mn - 1; i != SIZE_MAX; --i) + { + h_scalars[i] += rwf_s_e * s_vec[interm.c_bpp_mn - 1 - i] - rwf_e_sq_z - rwf_e_sq_y * d[i]; + rwf_e_sq_y *= interm.y; + } + + DBG_PRINT("Hs(h_scalars): " << h_scalars.calc_hs()); + + // G point multiplicands: + // rwf * (r' y s' - e ^ 2 * ((z - z ^ 2)*SUM(y^>mn) - z * y^(mn+1) * SUM(d)) = + // = rwf * r' y s' - rwf * e^2 * (z - z ^ 2)*SUM(y^>mn) + rwf * e^2 * z * y^(mn+1) * SUM(d) + G_scalar += rwf * sig.r * interm.y * sig.s + rwf_e_sq_y * sum_d * interm.z; + G_scalar -= rwf * interm.e_final_sq * (interm.z - interm.z_sq) * sum_of_powers(interm.y, log2_mn); + DBG_PRINT("sum_y: " << sum_of_powers(interm.y, log2_mn)); + DBG_PRINT("G_scalar: " << G_scalar); + + // H point multiplicands: + // rwf * delta_1 + H_scalar += rwf * sig.delta_1; + DBG_PRINT("H_scalar: " << H_scalar); + + // H2 point multiplicands: + // rwf * delta_2 + H2_scalar += rwf * sig.delta_2; + DBG_PRINT("H2_scalar: " << H2_scalar); + + // uncommon generators' multiplicands + point_t summand_8 = c_point_0; // this summand to be multiplied by 8 before adding to the main summand + // - rwf * e^2 * A0 + summand_8 -= rwf * interm.e_final_sq * interm.A0; + DBG_PRINT("A0_scalar: " << c_scalar_Lm1 * interm.e_final_sq * rwf); + + // - rwf * e^2 * y^(mn+1) * (SUM{j=1..m} (z^2)^j * V_j)) + scalar_t e_sq_y_mn1_z_sq_power = rwf * interm.e_final_sq * y_power_mnp1; + for (size_t j = 0; j < bsc.commitments.size(); ++j) + { + e_sq_y_mn1_z_sq_power *= interm.z_sq; + summand_8 -= e_sq_y_mn1_z_sq_power * bsc.commitments[j]; + DBG_PRINT("V_scalar[" << j << "]: " << c_scalar_Lm1 * e_sq_y_mn1_z_sq_power); + } + + // - rwf * e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + scalar_t rwf_e_sq = rwf * interm.e_final_sq; + for (size_t j = 0; j < log2_mn; ++j) + { + summand_8 -= rwf_e_sq * (interm.e_sq[j] * interm.L[j] + get_e_inv(j) * get_e_inv(j) * interm.R[j]); + DBG_PRINT("L_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * interm.e_sq[j]); + DBG_PRINT("R_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * get_e_inv(j) * get_e_inv(j)); + } + + // - rwf * e * A - rwf * B = 0 + summand_8 -= rwf * interm.e_final * interm.A + rwf * interm.B; + DBG_PRINT("A_scalar: " << c_scalar_Lm1 * rwf * interm.e_final); + DBG_PRINT("B_scalar: " << c_scalar_Lm1 * rwf); + + summand_8.modify_mul8(); + summand += summand_8; + } + + point_t GH_exponents = c_point_0; + CT::calc_pedersen_commitment_2(G_scalar, H_scalar, H2_scalar, GH_exponents); + bool result = multiexp_and_check_being_zero(g_scalars, h_scalars, summand + GH_exponents); + if (result) + DBG_PRINT(ENDL << " . . . . bppe_verify() -- SUCCEEDED!!!" << ENDL); + return result; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } + +} // namespace crypto diff --git a/src/crypto/range_proofs.cpp b/src/crypto/range_proofs.cpp index b6750a09..783a0c2b 100644 --- a/src/crypto/range_proofs.cpp +++ b/src/crypto/range_proofs.cpp @@ -6,7 +6,4 @@ namespace crypto { - const point_t& bpp_crypto_trait_zano::bpp_H = c_point_H; - - } diff --git a/src/crypto/range_proofs.h b/src/crypto/range_proofs.h index b3d04d68..bcd03393 100644 --- a/src/crypto/range_proofs.h +++ b/src/crypto/range_proofs.h @@ -1,14 +1,9 @@ -// Copyright (c) 2021 Zano Project (https://zano.org/) -// Copyright (c) 2021 sowle (val@zano.org, crypto.sowle@gmail.com) +// Copyright (c) 2021-2022 Zano Project (https://zano.org/) +// Copyright (c) 2021-2022 sowle (val@zano.org, crypto.sowle@gmail.com) // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once -// -// This file contains the implementation of range proof protocol. -// Namely, Bulletproofs+ https://eprint.iacr.org/2020/735.pdf -// - #include "epee/include/misc_log_ex.h" #include "crypto-sugar.h" @@ -28,27 +23,23 @@ namespace crypto return result; } - constexpr size_t c_bpp_log2_n = 6; - constexpr size_t c_bpp_n = 64; // 2^64 is the upper bound for the witness's range - constexpr size_t c_bpp_values_max = 16; // maximum number of elements in BP+ proof, i.e. max allowed BP+ outputs - constexpr size_t c_bpp_mn_max = c_bpp_n * c_bpp_values_max; + + // returns greatest k, s.t. 2**k <= v + // tests in crypto_tests_range_proofs.h + constexpr size_t constexpr_floor_log2(size_t v) + { + return v <= 1 ? 0 : constexpr_floor_log2(v >> 1) + 1; + } // returns smallest k, s.t. v <= 2**k - inline size_t calc_exp_power_of_2_upper_bound(size_t v) + // tests in crypto_tests_range_proofs.h + constexpr size_t constexpr_ceil_log2(size_t v) { - constexpr size_t max_v = (SIZE_MAX >> 1) + 1; - //if (v > max_v) - // return 0; - - size_t pow = 1, result = 0; - while (v > pow) - { - pow <<= 1; - ++result; - } - return result; + return v <= 1 ? 0 : constexpr_floor_log2(v - 1) + 1; } + + // returns least significant bit uing de Bruijn sequence // http://graphics.stanford.edu/~seander/bithacks.html inline uint8_t calc_lsb_32(uint32_t v) @@ -61,17 +52,28 @@ namespace crypto return multiply_de_bruijn_bit_position[((uint32_t)((v & -(int32_t)v) * 0x077CB531U)) >> 27]; } - + //////////////////////////////////////// // crypto trait for Zano //////////////////////////////////////// + template struct bpp_crypto_trait_zano { + static constexpr size_t c_bpp_n = N; // the upper bound for the witness's range + static constexpr size_t c_bpp_values_max = values_max; // maximum number of elements in BP+ proof, i.e. max allowed BP+ outputs + static constexpr size_t c_bpp_log2_n = constexpr_ceil_log2(c_bpp_n); + static constexpr size_t c_bpp_mn_max = c_bpp_n * c_bpp_values_max; + static void calc_pedersen_commitment(const scalar_t& value, const scalar_t& mask, point_t& commitment) { commitment = value * c_point_G + mask * c_point_H; } + static void calc_pedersen_commitment_2(const scalar_t& value, const scalar_t& mask1, const scalar_t& mask2, point_t& commitment) + { + commitment = value * c_point_G + mask1 * c_point_H + mask2 * c_point_H2; + } + static const scalar_t& get_initial_transcript() { static scalar_t value = hash_helper_t::hs("Zano BP+ initial transcript"); @@ -86,6 +88,7 @@ namespace crypto e = hsc.calc_hash(); } + // TODO: refactor with proper OOB handling static const point_t& get_generator(bool select_H, size_t index) { if (index >= c_bpp_mn_max) @@ -107,333 +110,29 @@ namespace crypto return generators[2 * index + (select_H ? 1 : 0)]; } + static const scalar_t& get_2_to_the_power_of_N_minus_1() + { + static scalar_t result = scalar_t::power_of_2(c_bpp_n) - 1; + return result; + } + static const point_t& bpp_H; - }; + static const point_t& bpp_H2; + }; // struct bpp_crypto_trait_zano + + template + const point_t& bpp_crypto_trait_zano::bpp_H = c_point_H; + + template + const point_t& bpp_crypto_trait_zano::bpp_H2 = c_point_H2; - struct bpp_signature - { - std::vector L; // size = log_2(m * n) - std::vector R; - public_key A0; - public_key A; - public_key B; - scalar_t r; - scalar_t s; - scalar_t delta; - }; - -#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL -#define DBG_PRINT(x) std::cout << x << ENDL - - template - bool bpp_gen(const std::vector& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector& commitments, uint8_t* p_err = nullptr) - { -#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ - if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ - if (p_err) { *p_err = err_code; } return false; } - - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= c_bpp_values_max && values.size() == masks.size(), 1); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced(), 3); - - const size_t c_bpp_log2_m = calc_exp_power_of_2_upper_bound(values.size()); - const size_t c_bpp_m = 1ull << c_bpp_log2_m; - const size_t c_bpp_mn = c_bpp_m * c_bpp_n; - const size_t c_bpp_log2_mn = c_bpp_log2_m + c_bpp_log2_n; - - // pre-multiply all output points by c_scalar_1div8 - // in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify()) - - // calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H - commitments.resize(values.size()); - for (size_t i = 0; i < values.size(); ++i) - CT::calc_pedersen_commitment(scalar_t(values[i]) * c_scalar_1div8, masks[i] * c_scalar_1div8, commitments[i]); - - - // s.a. BP+ paper, page 15, eq. 11 - // decompose v into aL and aR: - // v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product - // aR = aL - (1, 1, ... 1) - // aR o aL = 0 - - // aLs = (aL_0, aL_1, ..., aL_m-1) -- `bit` matrix of c_bpp_m x c_bpp_n, each element is a scalar - - scalar_mat_t aLs(c_bpp_mn), aRs(c_bpp_mn); - aLs.zero(); - aRs.zero(); - // m >= values.size, first set up [0..values.size-1], then -- [values.size..m-1] (padding area) - for (size_t i = 0; i < values.size(); ++i) - { - uint64_t v = values[i]; - for (size_t j = 0; j < c_bpp_n; ++j) - { - if (v & 1) - aLs(i, j) = c_scalar_1; // aL = 1, aR = 0 - else - aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 - v >>= 1; - } - } - - for (size_t i = values.size(); i < c_bpp_m; ++i) - for (size_t j = 0; j < c_bpp_n; ++j) - aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 - - - // using e as Fiat-Shamir transcript - scalar_t e = CT::get_initial_transcript(); - DBG_PRINT("initial transcript: " << e); - - hash_helper_t::hs_t hsc; - CT::update_transcript(hsc, e, commitments); - - // BP+ paper, page 15: The prover begins with sending A = g^aL h^aR h^alpha (group element) - // so we calculate A0 = alpha * H + SUM(aL_i * G_i) + SUM(aR_i * H_i) - - scalar_t alpha = scalar_t::random(); - point_t A0 = alpha * CT::bpp_H; - - for (size_t i = 0; i < c_bpp_mn; ++i) - A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i); - - // part of 1/8 defense scheme - A0 *= c_scalar_1div8; - A0.to_public_key(sig.A0); - - DBG_VAL_PRINT(alpha); - DBG_VAL_PRINT(A0); - - // calculate scalar challenges y and z - hsc.add_scalar(e); - hsc.add_pub_key(sig.A0); - scalar_t y = hsc.calc_hash(); - scalar_t z = hash_helper_t::hs(y); - e = z; // transcript for further steps - DBG_VAL_PRINT(y); - DBG_VAL_PRINT(z); - - // Computing vector d for aggregated version of the protocol (BP+ paper, page 17) - // (note: elements is stored column-by-column in memory) - // d = | 1 * z^(2*1), 1 * z^(2*2), 1 * z^(2*3), ..., 1 * z^(2*m) | - // | 2 * z^(2*1), 2 * z^(2*2), 2 * z^(2*3), ..., 2 * z^(2*m) | - // | 4 * z^(2*1), 4 * z^(2*2), 4 * z^(2*3), ..., 4 * z^(2*m) | - // | ....................................................................................... | - // | 2^(n-1) * z^(2*1), 2^(n-1) * z^(2*2), 2^(n-1) * z^(2*3), ..., 2^(n-1) * z^(2*m)) | - // Note: sum(d_i) = (2^n - 1) * ((z^2)^1 + (z^2)^2 + ... (z^2)^m)) = (2^n-1) * sum_of_powers(x^2, log(m)) - - scalar_t z_sq = z * z; - scalar_mat_t d(c_bpp_mn); - d(0, 0) = z_sq; - // first row - for (size_t i = 1; i < c_bpp_m; ++i) - d(i, 0) = d(i - 1, 0) * z_sq; - // all rows - for (size_t j = 1; j < c_bpp_n; ++j) - for (size_t i = 0; i < c_bpp_m; ++i) - d(i, j) = d(i, j - 1) + d(i, j - 1); - - DBG_PRINT("Hs(d): " << d.calc_hs()); - - // calculate extended Vandermonde vector y = (1, y, y^2, ..., y^(mn+1)) (BP+ paper, page 18, Fig. 3) - // (calculate two more elements (1 and y^(mn+1)) for convenience) - scalar_vec_t y_powers(c_bpp_mn + 2); - y_powers[0] = 1; - for (size_t i = 1; i <= c_bpp_mn + 1; ++i) - y_powers[i] = y_powers[i - 1] * y; - - const scalar_t& y_mn_p1 = y_powers[c_bpp_mn + 1]; - - DBG_PRINT("Hs(y_powers): " << y_powers.calc_hs()); - - // aL_hat = aL - 1*z - scalar_vec_t aLs_hat = aLs - z; - // aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3) - scalar_vec_t aRs_hat = aRs + z; - for (size_t i = 0; i < c_bpp_mn; ++i) - aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i]; - - DBG_PRINT("Hs(aLs_hat): " << aLs_hat.calc_hs()); - DBG_PRINT("Hs(aRs_hat): " << aRs_hat.calc_hs()); - - // calculate alpha_hat - // alpha_hat = alpha + SUM(z^(2j) * gamma_j * y^(mn+1)) for j = 1..m - // i.e. \hat{\alpha} = \alpha + y^{m n+1} \sum_{j = 1}^{m} z^{2j} \gamma_j - scalar_t alpha_hat = 0; - for (size_t i = 0; i < masks.size(); ++i) - alpha_hat += d(i, 0) * masks[i]; - alpha_hat = alpha + y_mn_p1 * alpha_hat; - - DBG_VAL_PRINT(alpha_hat); - - // calculate y^-1, y^-2, ... - const scalar_t y_inverse = y.reciprocal(); - scalar_vec_t y_inverse_powers(c_bpp_mn / 2 + 1); // the greatest power we need is c_bpp_mn/2 (at the first reduction round) - y_inverse_powers[0] = 1; - for (size_t i = 1, size = y_inverse_powers.size(); i < size; ++i) - y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inverse; - - // prepare generator's vector - std::vector g(c_bpp_mn), h(c_bpp_mn); - for (size_t i = 0; i < c_bpp_mn; ++i) - { - g[i] = CT::get_generator(false, i); - h[i] = CT::get_generator(true, i); - } - - // WIP zk-argument called with zk-WIP(g, h, G, H, A_hat, aL_hat, aR_hat, alpha_hat) - - scalar_vec_t& a = aLs_hat; - scalar_vec_t& b = aRs_hat; - - sig.L.resize(c_bpp_log2_mn); - sig.R.resize(c_bpp_log2_mn); - - // zk-WIP reduction rounds (s.a. the preprint page 13 Fig. 1) - for (size_t n = c_bpp_mn / 2, ni = 0; n >= 1; n /= 2, ++ni) - { - DBG_PRINT(ENDL << "#" << ni); - - // zk-WIP(g, h, G, H, P, a, b, alpha) - - scalar_t dL = scalar_t::random(); - DBG_VAL_PRINT(dL); - scalar_t dR = scalar_t::random(); - DBG_VAL_PRINT(dR); - - // a = (a1, a2), b = (b1, b2) -- vectors of scalars - // cL = -- scalar - scalar_t cL = 0; - for (size_t i = 0; i < n; ++i) - cL += a[i] * y_powers[i + 1] * b[n + i]; - - DBG_VAL_PRINT(cL); - - // cR = * y^n -- scalar - scalar_t cR = 0; - for (size_t i = 0; i < n; ++i) - cR += a[n + i] * y_powers[i + 1] * b[i]; - cR *= y_powers[n]; - - DBG_VAL_PRINT(cR); - - // L = y^-n * a1 * g2 + b2 * h1 + cL * G + dL * H -- point - point_t sum = c_point_0; - for (size_t i = 0; i < n; ++i) - sum += a[i] * g[n + i]; - point_t L; - CT::calc_pedersen_commitment(cL, dL, L); - for (size_t i = 0; i < n; ++i) - L += b[n + i] * h[i]; - L += y_inverse_powers[n] * sum; - L *= c_scalar_1div8; - DBG_VAL_PRINT(L); - - // R = y^n * a2 * g1 + b1 * h2 + cR * G + dR * H -- point - sum.zero(); - for (size_t i = 0; i < n; ++i) - sum += a[n + i] * g[i]; - point_t R; - CT::calc_pedersen_commitment(cR, dR, R); - for (size_t i = 0; i < n; ++i) - R += b[i] * h[n + i]; - R += y_powers[n] * sum; - R *= c_scalar_1div8; - DBG_VAL_PRINT(R); - - // put L, R to the sig - L.to_public_key(sig.L[ni]); - R.to_public_key(sig.R[ni]); - - // update the transcript - hsc.add_scalar(e); - hsc.add_pub_key(sig.L[ni]); - hsc.add_pub_key(sig.R[ni]); - e = hsc.calc_hash(); - DBG_VAL_PRINT(e); - - // recalculate arguments for the next round - scalar_t e_squared = e * e; - scalar_t e_inverse = e.reciprocal(); - scalar_t e_inverse_squared = e_inverse * e_inverse; - scalar_t e_y_inv_n = e * y_inverse_powers[n]; - scalar_t e_inv_y_n = e_inverse * y_powers[n]; - - // g_hat = e^-1 * g1 + (e * y^-n) * g2 -- vector of points - for (size_t i = 0; i < n; ++i) - g[i] = e_inverse * g[i] + e_y_inv_n * g[n + i]; - - // h_hat = e * h1 + e^-1 * h2 -- vector of points - for (size_t i = 0; i < n; ++i) - h[i] = e * h[i] + e_inverse * h[n + i]; - - // P_hat = e^2 * L + P + e^-2 * R -- point - - // a_hat = e * a1 + e^-1 * y^n * a2 -- vector of scalars - for (size_t i = 0; i < n; ++i) - a[i] = e * a[i] + e_inv_y_n * a[n + i]; - - // b_hat = e^-1 * b1 + e * b2 -- vector of scalars - for (size_t i = 0; i < n; ++i) - b[i] = e_inverse * b[i] + e * b[n + i]; - - // alpha_hat = e^2 * dL + alpha + e^-2 * dR -- scalar - alpha_hat += e_squared * dL + e_inverse_squared * dR; - - // run next iteraton zk-WIP(g_hat, h_hat, G, H, P_hat, a_hat, b_hat, alpha_hat) - } - DBG_PRINT(""); - - // zk-WIP last round - scalar_t r = scalar_t::random(); - scalar_t s = scalar_t::random(); - scalar_t delta = scalar_t::random(); - scalar_t eta = scalar_t::random(); - DBG_VAL_PRINT(r); - DBG_VAL_PRINT(s); - DBG_VAL_PRINT(delta); - DBG_VAL_PRINT(eta); - - // A = r * g + s * h + (r y b + s y a) * G + delta * H -- point - point_t A = c_point_0; - CT::calc_pedersen_commitment(y * (r * b[0] + s * a[0]), delta, A); - A += r * g[0] + s * h[0]; - A *= c_scalar_1div8; - A.to_public_key(sig.A); - DBG_VAL_PRINT(A); - - // B = (r * y * s) * G + eta * H - point_t B = c_point_0; - CT::calc_pedersen_commitment(r * y * s, eta, B); - B *= c_scalar_1div8; - B.to_public_key(sig.B); - DBG_VAL_PRINT(B); - - // update the transcript - hsc.add_scalar(e); - hsc.add_pub_key(sig.A); - hsc.add_pub_key(sig.B); - e = hsc.calc_hash(); - DBG_VAL_PRINT(e); - - // finalize the signature - sig.r = r + e * a[0]; - sig.s = s + e * b[0]; - sig.delta = eta + e * delta + e * e * alpha_hat; - DBG_VAL_PRINT(sig.r); - DBG_VAL_PRINT(sig.s); - DBG_VAL_PRINT(sig.delta); - - return true; -#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE - } // bpp_gen() - - // efficient multiexponentiation (naive stub implementation atm, TODO) template bool multiexp_and_check_being_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand) { - CHECK_AND_ASSERT_MES(g_scalars.size() < c_bpp_mn_max, false, "g_scalars oversized"); - CHECK_AND_ASSERT_MES(h_scalars.size() < c_bpp_mn_max, false, "h_scalars oversized"); + CHECK_AND_ASSERT_MES(g_scalars.size() < CT::c_bpp_mn_max, false, "g_scalars oversized"); + CHECK_AND_ASSERT_MES(h_scalars.size() < CT::c_bpp_mn_max, false, "h_scalars oversized"); point_t result = summand; @@ -452,372 +151,7 @@ namespace crypto } - struct bpp_sig_commit_ref_t - { - bpp_sig_commit_ref_t(const bpp_signature& sig, const std::vector& commitments) - : sig(sig) - , commitments(commitments) - {} - const bpp_signature& sig; - const std::vector& commitments; - }; - - - template - bool bpp_verify(const std::vector& sigs, uint8_t* p_err = nullptr) - { -#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ - if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ - if (p_err) { *p_err = err_code; } return false; } - - DBG_PRINT(ENDL << " . . . . bpp_verify() . . . . "); - - const size_t kn = sigs.size(); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(kn > 0, 1); - - struct intermediate_element_t - { - scalar_t y; - scalar_t z; - scalar_t z_sq; - scalar_vec_t e; - scalar_vec_t e_sq; - scalar_t e_final; - scalar_t e_final_sq; - size_t inv_e_offset; // offset in batch_for_inverse - size_t inv_y_offset; // offset in batch_for_inverse - size_t c_bpp_log2_m; - size_t c_bpp_m; - size_t c_bpp_mn; - point_t A; - point_t A0; - point_t B; - std::vector L; - std::vector R; - }; - std::vector interms(kn); - - size_t c_bpp_log2_m_max = 0; - for (size_t k = 0; k < kn; ++k) - { - const bpp_sig_commit_ref_t& bsc = sigs[k]; - const bpp_signature& sig = bsc.sig; - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bsc.commitments.size() > 0, 2); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() > 0 && sig.L.size() == sig.R.size(), 3); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.r.is_reduced() && sig.s.is_reduced() && sig.delta.is_reduced(), 4); - - intermediate_element_t& interm = interms[k]; - interm.c_bpp_log2_m = calc_exp_power_of_2_upper_bound(bsc.commitments.size()); - if (c_bpp_log2_m_max < interm.c_bpp_log2_m) - c_bpp_log2_m_max = interm.c_bpp_log2_m; - - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() == interm.c_bpp_log2_m + c_bpp_log2_n, 5); - - interm.c_bpp_m = 1ull << interm.c_bpp_log2_m; - interm.c_bpp_mn = interm.c_bpp_m * c_bpp_n; - - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A0.from_public_key(sig.A0), 6); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A.from_public_key(sig.A), 7); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.B.from_public_key(sig.B), 8); - interm.L.resize(sig.L.size()); - interm.R.resize(sig.R.size()); - for (size_t i = 0; i < interm.L.size(); ++i) - { - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.L[i].from_public_key(sig.L[i]), 9); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.R[i].from_public_key(sig.R[i]), 10); - } - } - const size_t c_bpp_m_max = 1ull << c_bpp_log2_m_max; - const size_t c_bpp_mn_max = c_bpp_m_max * c_bpp_n; - const size_t c_bpp_LR_size_max = c_bpp_log2_m_max + c_bpp_log2_n; - - - // - // prepare stuff - // - /* - std::vector g(c_bpp_mn_max), h(c_bpp_mn_max); - for (size_t i = 0; i < c_bpp_mn_max; ++i) - { - g[i] = CT::get_generator(false, i); - h[i] = CT::get_generator(true, i); - } - */ - - scalar_vec_t batch_for_inverse; - batch_for_inverse.reserve(kn + kn * c_bpp_LR_size_max); - - - for (size_t k = 0; k < kn; ++k) - { - DBG_PRINT(ENDL << "SIG #" << k); - const bpp_sig_commit_ref_t& bsc = sigs[k]; - const bpp_signature& sig = bsc.sig; - intermediate_element_t& interm = interms[k]; - - // restore y and z - // using e as Fiat-Shamir transcript - scalar_t e = CT::get_initial_transcript(); - DBG_PRINT("initial transcript: " << e); - hash_helper_t::hs_t hsc; - CT::update_transcript(hsc, e, bsc.commitments); - // calculate scalar challenges y and z - hsc.add_scalar(e); - hsc.add_pub_key(sig.A0); - hsc.assign_calc_hash(interm.y); - interm.z = hash_helper_t::hs(interm.y); - interm.z_sq = interm.z * interm.z; - DBG_VAL_PRINT(interm.y); - DBG_VAL_PRINT(interm.z); - e = interm.z; // transcript for further steps - - interm.inv_y_offset = batch_for_inverse.size(); - batch_for_inverse.push_back(interm.y); - interm.inv_e_offset = batch_for_inverse.size(); - - interm.e.resize(sig.L.size()); - interm.e_sq.resize(sig.L.size()); - - for (size_t i = 0; i < sig.L.size(); ++i) - { - hsc.add_scalar(e); - hsc.add_pub_key(sig.L[i]); - hsc.add_pub_key(sig.R[i]); - hsc.assign_calc_hash(e); - interm.e[i] = e; - interm.e_sq[i] = e * e; - DBG_PRINT("e[" << i << "]: " << e); - batch_for_inverse.push_back(e); - } - - hsc.add_scalar(e); - hsc.add_pub_key(sig.A); - hsc.add_pub_key(sig.B); - hsc.assign_calc_hash(interm.e_final); - interm.e_final_sq = interm.e_final * interm.e_final; - DBG_VAL_PRINT(interm.e_final); - } - - batch_for_inverse.invert(); - - // Notation: - // 1_vec ^ n = (1, 1, 1, ..., 1) - // 2_vec ^ n = (2^0, 2^1, 2^2, ..., 2^(n-1)) - // -1_vec ^ n = ((-1)^0, (-1)^1, (-1)^2, ... (-1)^(n-1)) = (1, -1, 1, -1, ...) - // y<^n = (y^n, y^(n-1), ..., y^1) - // y>^n = (y^1, y^2, ..., y^n) - - // from page 13, Fig 1: - // Verifier outputs Accept IFF the following equality holds (single proof): - // P^e^2 * A^e * B == g ^ (r' e) * h ^ (s' e) * G ^ (r' y s') * H ^ delta' - // (where g and h are calculated in each round) - // The same equation in additive notation: - // e^2 * P + e * A + B == (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H - // <=> - // (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H - e^2 * P - e * A - B == 0 (*) - // where A, B, r', s', delta' is taken from the signature - // and P_{k+1} = e^2 * L_k + P_k + e^-2 * R_k for all rounds - // - // from page 18, Fig 3: - // P and V computes: - // A_hat = A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + - // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + - // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G - // (calculated once) - // - // As suggested in Section 6.1 "Practical Optimizations": - // 1) g and h exponentianions can be optimized in order not to be calculated at each round as the following (page 20): - // - // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - - // - e^2 * A_hat - // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) - // - e * A - B = 0 (**) - // - // where: - // g, h - vector of fixed generators - // s_vec_i = y^(1-i) * PROD{j=1..log(n)}(e_j ^ b(i,j)) - // s'_vec_i = PROD{j=1..log(n)}(e_j ^ -b(i,j)) - // b(i, j) = { 2 * ((1<<(j-1)) & (i-1)) - 1) (counting both from 1) (page 20) - // b(i, j) = { 2 * ((1< - - // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - - // - e^2 * (A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + - // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + - // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G - // ) - // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) - // - e * A - B = 0 - - // => - - // (for single signature) - // - // (r' * e * s_vec - e^2 * (- 1_vec^(mn) * z)) * g | these are - // + (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) * h | fixed generators - // + (r' y s' - e^2 * ((z - z^2)*SUM(y^>mn) - z*y^(mn+1)*SUM(d)) * G | across all - // + delta' * H | the signatures - // - // - e^2 * A0 - // - e^2 * y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j)) - // - e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) - // - e * A - B = 0 (***) - // - // All (***) will be muptiplied by random weightning factor and then summed up. - - // Calculate cummulative sclalar multiplicand for fixed generators across all the sigs. - scalar_vec_t g_scalars; - g_scalars.resize(c_bpp_mn_max, 0); - scalar_vec_t h_scalars; - h_scalars.resize(c_bpp_mn_max, 0); - scalar_t G_scalar = 0; - scalar_t H_scalar = 0; - point_t summand = c_point_0; - - for (size_t k = 0; k < kn; ++k) - { - DBG_PRINT(ENDL << "SIG #" << k); - const bpp_sig_commit_ref_t& bsc = sigs[k]; - const bpp_signature& sig = bsc.sig; - intermediate_element_t& interm = interms[k]; - - // random weightning factor for speed-optimized batch verification (preprint page 20) - const scalar_t rwf = scalar_t::random(); - DBG_PRINT("rwf: " << rwf); - - // prepare d vector (see also d structure description in proof function) - scalar_mat_t d(interm.c_bpp_mn); - d(0, 0) = interm.z_sq; - // first row - for (size_t i = 1; i < interm.c_bpp_m; ++i) - d(i, 0) = d(i - 1, 0) * interm.z_sq; - // all rows - for (size_t j = 1; j < c_bpp_n; ++j) - for (size_t i = 0; i < interm.c_bpp_m; ++i) - d(i, j) = d(i, j - 1) + d(i, j - 1); - // sum(d) (see also note in proof function for this) - static const scalar_t c_scalar_2_power_n_minus_1 = { 0xffffffffffffffff, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }; - const scalar_t sum_d = c_scalar_2_power_n_minus_1 * sum_of_powers(interm.z_sq, interm.c_bpp_log2_m); - - DBG_PRINT("Hs(d): " << d.calc_hs()); - DBG_PRINT("sum(d): " << sum_d); - - const scalar_t& y_inv = batch_for_inverse[interm.inv_y_offset]; - auto get_e_inv = [&](size_t i) { return batch_for_inverse[interm.inv_e_offset + i]; }; // i belongs to [0; L.size()-1] - - // prepare s_vec (unlike the paper here we moved y-component out of s_vec for convenience, so s_vec'[x] = s_vec[~x & (MN-1)]) - // complexity (sc_mul's): MN+2*log2(MN)-2 - // the idea is the following: - // s_vec[00000b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^-1 * (e_1)^-1 * (e_0)^-1 - // s_vec[00101b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^+1 * (e_1)^-1 * (e_0)^+1 - const size_t log2_mn = sig.L.size(); // at the beginning we made sure that sig.L.size() == c_bpp_log2_m + c_bpp_log2_n - scalar_vec_t s_vec(interm.c_bpp_mn); - s_vec[0] = get_e_inv(0); - for (size_t i = 1; i < log2_mn; ++i) - s_vec[0] *= get_e_inv(i); // s_vec[0] = (e_0)^-1 * (e_1)^-1 * .. (e_{log2_mn-1})^-1 - DBG_PRINT("[0] " << s_vec[0]); - for (size_t i = 1; i < interm.c_bpp_mn; ++i) - { - size_t base_el_index = i & (i - 1); // base element index: 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10... base element differs in one bit (0) from the current one (1) - size_t bit_index = log2_mn - calc_lsb_32((uint32_t)i) - 1; // the bit index where current element has the difference with the base - s_vec[i] = s_vec[base_el_index] * interm.e_sq[bit_index]; // (e_j)^-1 * (e_j)^2 = (e_j)^+1 - DBG_PRINT("[" << i << "] " << " " << base_el_index << ", " << bit_index << " : " << s_vec[i]); - } - - // prepare y_inv vector - scalar_vec_t y_inverse_powers(interm.c_bpp_mn); - y_inverse_powers[0] = 1; - for (size_t i = 1; i < interm.c_bpp_mn; ++i) - y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inv; - - // y^(mn+1) - scalar_t y_power_mnp1 = interm.y; - for (size_t i = 0; i < log2_mn; ++i) - y_power_mnp1 *= y_power_mnp1; - y_power_mnp1 *= interm.y; - DBG_VAL_PRINT(y_power_mnp1); - - // now calculate all multiplicands for common generators - - // g vector multiplicands: - // rwf * (r' * e * (1, y^-1, y^-2, ...) o s_vec + e^2 * z) = - // rwf * r' * e * ((1, y^-1, ...) o s_vec) + rwf * e^2 * z * (1, 1, ...) - scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; - scalar_t rwf_r_e = rwf * interm.e_final * sig.r; - for (size_t i = 0; i < interm.c_bpp_mn; ++i) - g_scalars[i] += rwf_r_e * y_inverse_powers[i] * s_vec[i] + rwf_e_sq_z; - - DBG_PRINT("Hs(g_scalars): " << g_scalars.calc_hs()); - - // h vector multiplicands: - // rwf * (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) - // rwf * s' * e * s'_vec - rwf * e^2 * z * (1, 1...) - rwf * e^2 * (d o y<^(mn)) - //scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; - scalar_t rwf_s_e = rwf * sig.s * interm.e_final; - scalar_t rwf_e_sq_y = rwf * interm.e_final_sq * interm.y; - for (size_t i = interm.c_bpp_mn - 1; i != SIZE_MAX; --i) - { - h_scalars[i] += rwf_s_e * s_vec[interm.c_bpp_mn - 1 - i] - rwf_e_sq_z - rwf_e_sq_y * d[i]; - rwf_e_sq_y *= interm.y; - } - - DBG_PRINT("Hs(h_scalars): " << h_scalars.calc_hs()); - - // G point multiplicands: - // rwf * (r' y s' - e ^ 2 * ((z - z ^ 2)*SUM(y^>mn) - z * y^(mn+1) * SUM(d)) = - // = rwf * r' y s' - rwf * e^2 * (z - z ^ 2)*SUM(y^>mn) + rwf * e^2 * z * y^(mn+1) * SUM(d) - G_scalar += rwf * sig.r * interm.y * sig.s + rwf_e_sq_y * sum_d * interm.z; - G_scalar -= rwf * interm.e_final_sq * (interm.z - interm.z_sq) * sum_of_powers(interm.y, log2_mn); - DBG_PRINT("sum_y: " << sum_of_powers(interm.y, log2_mn)); - DBG_PRINT("G_scalar: " << G_scalar); - - // H point multiplicands: - // rwf * delta - H_scalar += rwf * sig.delta; - DBG_PRINT("H_scalar: " << H_scalar); - - // uncommon generators' multiplicands - point_t summand_8 = c_point_0; // this summand to be multiplied by 8 before adding to the main summand - // - rwf * e^2 * A0 - summand_8 -= rwf * interm.e_final_sq * interm.A0; - DBG_PRINT("A0_scalar: " << c_scalar_Lm1 * interm.e_final_sq * rwf); - - // - rwf * e^2 * y^(mn+1) * (SUM{j=1..m} (z^2)^j * V_j)) - scalar_t e_sq_y_mn1_z_sq_power = rwf * interm.e_final_sq * y_power_mnp1; - for (size_t j = 0; j < bsc.commitments.size(); ++j) - { - e_sq_y_mn1_z_sq_power *= interm.z_sq; - summand_8 -= e_sq_y_mn1_z_sq_power * bsc.commitments[j]; - DBG_PRINT("V_scalar[" << j << "]: " << c_scalar_Lm1 * e_sq_y_mn1_z_sq_power); - } - - // - rwf * e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) - scalar_t rwf_e_sq = rwf * interm.e_final_sq; - for (size_t j = 0; j < log2_mn; ++j) - { - summand_8 -= rwf_e_sq * (interm.e_sq[j] * interm.L[j] + get_e_inv(j) * get_e_inv(j) * interm.R[j]); - DBG_PRINT("L_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * interm.e_sq[j]); - DBG_PRINT("R_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * get_e_inv(j) * get_e_inv(j)); - } - - // - rwf * e * A - rwf * B = 0 - summand_8 -= rwf * interm.e_final * interm.A + rwf * interm.B; - DBG_PRINT("A_scalar: " << c_scalar_Lm1 * rwf * interm.e_final); - DBG_PRINT("B_scalar: " << c_scalar_Lm1 * rwf); - - summand_8.modify_mul8(); - summand += summand_8; - } - - point_t GH_exponents = c_point_0; - CT::calc_pedersen_commitment(G_scalar, H_scalar, GH_exponents); - bool result = multiexp_and_check_being_zero(g_scalars, h_scalars, summand + GH_exponents); - if (result) - DBG_PRINT(ENDL << " . . . . bpp_verify() -- SUCCEEDED!!!" << ENDL); - return result; -#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE - } - } // namespace crypto + +#include "range_proof_bpp.h" +#include "range_proof_bppe.h" diff --git a/src/currency_core/bc_offers_service.cpp b/src/currency_core/bc_offers_service.cpp index 59064632..b6349e90 100644 --- a/src/currency_core/bc_offers_service.cpp +++ b/src/currency_core/bc_offers_service.cpp @@ -13,7 +13,7 @@ #include "storages/portable_storage_template_helper.h" -command_line::arg_descriptor arg_market_disable = { "disable-market", "Start GUI with market service disabled", false, true }; +command_line::arg_descriptor arg_market_disable ( "disable-market", "Start GUI with market service disabled"); namespace bc_services diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 6bb47719..9ab636f5 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -80,8 +80,8 @@ DISABLE_VS_WARNINGS(4267) namespace { - const command_line::arg_descriptor arg_db_cache_l1 = { "db-cache-l1", "Specify size of memory mapped db cache file", 0, true }; - const command_line::arg_descriptor arg_db_cache_l2 = { "db-cache-l2", "Specify cached elements in db helpers", 0, true }; + const command_line::arg_descriptor arg_db_cache_l1 ( "db-cache-l1", "Specify size of memory mapped db cache file"); + const command_line::arg_descriptor arg_db_cache_l2 ( "db-cache-l2", "Specify cached elements in db helpers"); } //------------------------------------------------------------------ diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 29e76ab1..18e38c67 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -250,6 +250,8 @@ + static_assert(CURRENCY_MINER_TX_MAX_OUTS <= CURRENCY_TX_MAX_ALLOWED_OUTS, "Miner tx must obey normal tx max outs limit"); static_assert(PREMINE_AMOUNT / WALLET_MAX_ALLOWED_OUTPUT_AMOUNT < CURRENCY_MINER_TX_MAX_OUTS, "Premine can't be divided into reasonable number of outs"); +#define CURRENCY_RELAY_TXS_MAX_COUNT 5 \ No newline at end of file diff --git a/src/currency_core/miner.cpp b/src/currency_core/miner.cpp index 005c274c..d52e51e2 100644 --- a/src/currency_core/miner.cpp +++ b/src/currency_core/miner.cpp @@ -33,10 +33,10 @@ namespace currency namespace { - const command_line::arg_descriptor arg_extra_messages = {"extra-messages-file", "Specify file for extra messages to include into coinbase transactions", "", true}; - const command_line::arg_descriptor arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true}; - const command_line::arg_descriptor arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true}; - const command_line::arg_descriptor arg_block_template_extra_text = { "miner-text-info", "Set block extra text info", "", true }; + const command_line::arg_descriptor arg_extra_messages ("extra-messages-file", "Specify file for extra messages to include into coinbase transactions"); + const command_line::arg_descriptor arg_start_mining ("start-mining", "Specify wallet address to mining for"); + const command_line::arg_descriptor arg_mining_threads ("mining-threads", "Specify mining threads count"); + const command_line::arg_descriptor arg_block_template_extra_text ( "miner-text-info", "Set block extra text info"); } diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 7a65990e..581dfdb8 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -666,7 +666,7 @@ namespace currency bool tx_memory_pool::force_relay_pool() const { LOG_PRINT_GREEN("Preparing relay message...", LOG_LEVEL_0); - NOTIFY_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& k, const tx_details& v) { diff --git a/src/currency_protocol/currency_protocol_defs.h b/src/currency_protocol/currency_protocol_defs.h index 48f09e21..2a0eead6 100644 --- a/src/currency_protocol/currency_protocol_defs.h +++ b/src/currency_protocol/currency_protocol_defs.h @@ -71,7 +71,7 @@ namespace currency /************************************************************************/ /* */ /************************************************************************/ - struct NOTIFY_NEW_TRANSACTIONS + struct NOTIFY_OR_INVOKE_NEW_TRANSACTIONS { const static int ID = BC_COMMANDS_POOL_BASE + 2; @@ -83,6 +83,16 @@ namespace currency KV_SERIALIZE(txs) END_KV_SERIALIZE_MAP() }; + + struct response + { + std::string code; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(code) + END_KV_SERIALIZE_MAP() + }; + }; /************************************************************************/ /* */ diff --git a/src/currency_protocol/currency_protocol_handler.h b/src/currency_protocol/currency_protocol_handler.h index cae17241..1e420919 100644 --- a/src/currency_protocol/currency_protocol_handler.h +++ b/src/currency_protocol/currency_protocol_handler.h @@ -35,14 +35,15 @@ namespace currency typedef core_stat_info stat_info; typedef t_currency_protocol_handler currency_protocol_handler; typedef CORE_SYNC_DATA payload_type; - typedef std::pair relay_que_entry; + typedef std::pair relay_que_entry; t_currency_protocol_handler(t_core& rcore, nodetool::i_p2p_endpoint* p_net_layout); ~t_currency_protocol_handler(); BEGIN_INVOKE_MAP2(currency_protocol_handler) HANDLE_NOTIFY_T2(NOTIFY_NEW_BLOCK, ¤cy_protocol_handler::handle_notify_new_block) - HANDLE_NOTIFY_T2(NOTIFY_NEW_TRANSACTIONS, ¤cy_protocol_handler::handle_notify_new_transactions) + HANDLE_NOTIFY_T2(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS, ¤cy_protocol_handler::handle_notify_new_transactions) + HANDLE_INVOKE_T2(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS, ¤cy_protocol_handler::handle_invoke_new_transaction) HANDLE_NOTIFY_T2(NOTIFY_REQUEST_GET_OBJECTS, ¤cy_protocol_handler::handle_request_get_objects) HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_GET_OBJECTS, ¤cy_protocol_handler::handle_response_get_objects) HANDLE_NOTIFY_T2(NOTIFY_REQUEST_CHAIN, ¤cy_protocol_handler::handle_request_chain) @@ -76,16 +77,18 @@ namespace currency private: //----------------- commands handlers ---------------------------------------------- int handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& context); - int handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& context); + int handle_notify_new_transactions(int command, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& context); + int handle_invoke_new_transaction(int command, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& req, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response& rsp, currency_connection_context& context); int handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context); int handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request& arg, currency_connection_context& context); int handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, currency_connection_context& context); int handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, currency_connection_context& context); - + + //----------------- i_bc_protocol_layout --------------------------------------- virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& exclude_context); - virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context); + virtual bool relay_transactions(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context); //---------------------------------------------------------------------------------- //bool get_payload_sync_data(HANDSHAKE_DATA::request& hshd, currency_connection_context& context); bool request_missing_objects(currency_connection_context& context, bool check_having_blocks); @@ -93,7 +96,7 @@ namespace currency void relay_que_worker(); void process_current_relay_que(const std::list& que); bool check_stop_flag_and_drop_cc(currency_connection_context& context); - + int handle_new_transaction_from_net(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& req, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response& rsp, currency_connection_context& context, bool is_notify); t_core& m_core; nodetool::p2p_endpoint_stub m_p2p_stub; diff --git a/src/currency_protocol/currency_protocol_handler.inl b/src/currency_protocol/currency_protocol_handler.inl index 03b93b67..2ec82588 100644 --- a/src/currency_protocol/currency_protocol_handler.inl +++ b/src/currency_protocol/currency_protocol_handler.inl @@ -369,45 +369,79 @@ namespace currency } //------------------------------------------------------------------------------------------------------------------------ template - int t_currency_protocol_handler::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& context) + int t_currency_protocol_handler::handle_notify_new_transactions(int command, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& context) + { + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response rsp_dummy = AUTO_VAL_INIT(rsp_dummy); + return this->handle_new_transaction_from_net(arg, rsp_dummy, context, true); + } + //------------------------------------------------------------------------------------------------------------------------ + template + int t_currency_protocol_handler::handle_invoke_new_transaction(int command, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& req, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response& rsp, currency_connection_context& context) + { + return this->handle_new_transaction_from_net(req, rsp, context, false); + } + //------------------------------------------------------------------------------------------------------------------------ + template + int t_currency_protocol_handler::handle_new_transaction_from_net(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response& rsp, currency_connection_context& context, bool is_notify) { //do not process requests if it comes from node wich is debugged if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address) + { + rsp.code = API_RETURN_CODE_ACCESS_DENIED; return 1; + } - if(context.m_state != currency_connection_context::state_normal) + //if(context.m_state != currency_connection_context::state_normal) + // return 1; + if (!this->is_synchronized()) + { + rsp.code = API_RETURN_CODE_BUSY; return 1; + } + + uint64_t inital_tx_count = arg.txs.size(); + + if (inital_tx_count > CURRENCY_RELAY_TXS_MAX_COUNT) + { + LOG_PRINT_L1("NOTIFY_NEW_TRANSACTIONS: To many transactions in NOTIFY_OR_INVOKE_NEW_TRANSACTIONS(" << inital_tx_count << ")"); + rsp.code = API_RETURN_CODE_OVERFLOW; + return 1; + } + TIME_MEASURE_START_MS(new_transactions_handle_time); - for(auto tx_blob_it = arg.txs.begin(); tx_blob_it!=arg.txs.end();) + for (auto tx_blob_it = arg.txs.begin(); tx_blob_it != arg.txs.end();) { currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc); m_core.handle_incoming_tx(*tx_blob_it, tvc, false); - if(tvc.m_verification_failed) + if (tvc.m_verification_failed) { LOG_PRINT_L0("NOTIFY_NEW_TRANSACTIONS: Tx verification failed, dropping connection"); - m_p2p->drop_connection(context); - + if(is_notify) + m_p2p->drop_connection(context); + else + rsp.code = API_RETURN_CODE_FAIL; return 1; } - if(tvc.m_should_be_relayed) + if (tvc.m_should_be_relayed) ++tx_blob_it; else arg.txs.erase(tx_blob_it++); } - if(arg.txs.size()) + if (arg.txs.size()) { //TODO: add announce usage here relay_transactions(arg, context); } TIME_MEASURE_FINISH_MS(new_transactions_handle_time); - LOG_PRINT_L2("NOTIFY_NEW_TRANSACTIONS: " << new_transactions_handle_time << "ms (inital_tx_count: " << inital_tx_count << ", relayed_tx_count: " << arg.txs.size() << ")"); - - return true; + LOG_PRINT_L2("NOTIFY_OR_INVOKE_NEW_TRANSACTIONS(is_notify=" << is_notify <<"): " << new_transactions_handle_time << "ms (inital_tx_count: " << inital_tx_count << ", relayed_tx_count: " << arg.txs.size() << ")"); + rsp.code = API_RETURN_CODE_OK; + return 1; } + //------------------------------------------------------------------------------------------------------------------------ template int t_currency_protocol_handler::handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context) @@ -756,7 +790,7 @@ namespace currency m_p2p->get_connections(connections); for (auto& cc : connections) { - NOTIFY_NEW_TRANSACTIONS::request req = AUTO_VAL_INIT(req); + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request req = AUTO_VAL_INIT(req); for (auto& qe : que) { //exclude relaying to original sender @@ -766,7 +800,7 @@ namespace currency } if (req.txs.size()) { - post_notify(req, cc); + post_notify(req, cc); if (debug_ss.tellp()) debug_ss << ", "; @@ -944,7 +978,7 @@ namespace currency } //------------------------------------------------------------------------------------------------------------------------ template - bool t_currency_protocol_handler::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context) + bool t_currency_protocol_handler::relay_transactions(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context) { #ifdef ASYNC_RELAY_MODE { @@ -956,7 +990,7 @@ namespace currency //m_relay_que_cv.notify_all(); return true; #else - return relay_post_notify(arg, exclude_context); + return relay_post_notify(arg, exclude_context); #endif } } diff --git a/src/currency_protocol/currency_protocol_handler_common.h b/src/currency_protocol/currency_protocol_handler_common.h index 2bff506c..d07153f5 100644 --- a/src/currency_protocol/currency_protocol_handler_common.h +++ b/src/currency_protocol/currency_protocol_handler_common.h @@ -17,7 +17,7 @@ namespace currency struct i_currency_protocol { virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& exclude_context)=0; - virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context)=0; + virtual bool relay_transactions(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context)=0; //virtual bool request_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context)=0; }; @@ -30,7 +30,7 @@ namespace currency { return false; } - virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& /*arg*/, currency_connection_context& /*exclude_context*/) + virtual bool relay_transactions(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& /*arg*/, currency_connection_context& /*exclude_context*/) { return false; } diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 889c1c55..43f1efe6 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -146,7 +146,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_cmd_only, command_line::arg_version); command_line::add_arg(desc_cmd_only, command_line::arg_os_version); // tools::get_default_data_dir() can't be called during static initialization - command_line::add_arg(desc_cmd_only, command_line::arg_data_dir, tools::get_default_data_dir()); + command_line::add_arg(desc_cmd_sett, command_line::arg_data_dir, tools::get_default_data_dir()); command_line::add_arg(desc_cmd_only, command_line::arg_stop_after_height); command_line::add_arg(desc_cmd_only, command_line::arg_config_file); command_line::add_arg(desc_cmd_only, command_line::arg_disable_upnp); @@ -154,8 +154,8 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_cmd_sett, command_line::arg_log_dir); command_line::add_arg(desc_cmd_sett, command_line::arg_log_level); command_line::add_arg(desc_cmd_sett, command_line::arg_console); - command_line::add_arg(desc_cmd_sett, command_line::arg_show_details); - command_line::add_arg(desc_cmd_sett, command_line::arg_show_rpc_autodoc); + command_line::add_arg(desc_cmd_only, command_line::arg_show_details); + command_line::add_arg(desc_cmd_only, command_line::arg_show_rpc_autodoc); command_line::add_arg(desc_cmd_sett, command_line::arg_disable_stop_if_time_out_of_sync); command_line::add_arg(desc_cmd_sett, command_line::arg_disable_stop_on_low_free_space); command_line::add_arg(desc_cmd_sett, command_line::arg_enable_offers_service); @@ -168,7 +168,7 @@ int main(int argc, char* argv[]) arg_market_disable.default_value = true; - arg_market_disable.not_use_default = false; + arg_market_disable.use_default = true; currency::core::init_options(desc_cmd_sett); currency::core_rpc_server::init_options(desc_cmd_sett); diff --git a/src/daemon/daemon_commands_handler.h b/src/daemon/daemon_commands_handler.h index 4573b806..78d2ffef 100644 --- a/src/daemon/daemon_commands_handler.h +++ b/src/daemon/daemon_commands_handler.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include "console_handler.h" #include "p2p/net_node.h" @@ -18,6 +19,8 @@ #include "serialization/binary_utils.h" #include "simplewallet/password_container.h" +namespace ph = boost::placeholders; + PUSH_VS_WARNINGS DISABLE_VS_WARNINGS(4100) @@ -31,49 +34,49 @@ class daemon_commands_handler public: daemon_commands_handler(nodetool::node_server >& srv, currency::core_rpc_server& rpc) :m_srv(srv), m_rpc(rpc) { - m_cmd_binder.set_handler("help", boost::bind(&console_handlers_binder::help, &m_cmd_binder, _1), "Show this help"); - m_cmd_binder.set_handler("print_pl", boost::bind(&daemon_commands_handler::print_pl, this, _1), "Print peer list"); - m_cmd_binder.set_handler("print_cn", boost::bind(&daemon_commands_handler::print_cn, this, _1), "Print connections"); - m_cmd_binder.set_handler("print_bc", boost::bind(&daemon_commands_handler::print_bc, this, _1), "Print blockchain info in a given blocks range, print_bc []"); - m_cmd_binder.set_handler("print_bc_tx", boost::bind(&daemon_commands_handler::print_bc_tx, this, _1), "Print blockchain info with trnsactions in a given blocks range, print_bc []"); - //m_cmd_binder.set_handler("print_bci", boost::bind(&daemon_commands_handler::print_bci, this, _1)); - m_cmd_binder.set_handler("print_bc_outs", boost::bind(&daemon_commands_handler::print_bc_outs, this, _1)); - m_cmd_binder.set_handler("print_market", boost::bind(&daemon_commands_handler::print_market, this, _1)); - m_cmd_binder.set_handler("print_bc_outs_stats", boost::bind(&daemon_commands_handler::print_bc_outs_stats, this, _1)); - m_cmd_binder.set_handler("print_block", boost::bind(&daemon_commands_handler::print_block, this, _1), "Print block, print_block | "); - m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_commands_handler::print_block_info, this, _1), "Print block info, print_block | "); - m_cmd_binder.set_handler("print_tx_prun_info", boost::bind(&daemon_commands_handler::print_tx_prun_info, this, _1), "Print tx prunning info"); - m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_commands_handler::print_tx, this, _1), "Print transaction, print_tx "); - m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_commands_handler::start_mining, this, _1), "Start mining for specified address, start_mining [threads=1]"); - m_cmd_binder.set_handler("stop_mining", boost::bind(&daemon_commands_handler::stop_mining, this, _1), "Stop mining"); - m_cmd_binder.set_handler("print_pool", boost::bind(&daemon_commands_handler::print_pool, this, _1), "Print transaction pool (long format)"); - m_cmd_binder.set_handler("print_pool_sh", boost::bind(&daemon_commands_handler::print_pool_sh, this, _1), "Print transaction pool (short format)"); - m_cmd_binder.set_handler("show_hr", boost::bind(&daemon_commands_handler::show_hr, this, _1), "Start showing hash rate"); - m_cmd_binder.set_handler("hide_hr", boost::bind(&daemon_commands_handler::hide_hr, this, _1), "Stop showing hash rate"); - m_cmd_binder.set_handler("save", boost::bind(&daemon_commands_handler::save, this, _1), "Save blockchain"); - m_cmd_binder.set_handler("print_daemon_stat", boost::bind(&daemon_commands_handler::print_daemon_stat, this, _1), "Print daemon stat"); - m_cmd_binder.set_handler("print_debug_stat", boost::bind(&daemon_commands_handler::print_debug_stat, this, _1), "Print debug stat info"); - m_cmd_binder.set_handler("get_transactions_statics", boost::bind(&daemon_commands_handler::get_transactions_statistics, this, _1), "Calculates transactions statistics"); - m_cmd_binder.set_handler("force_relay_tx_pool", boost::bind(&daemon_commands_handler::force_relay_tx_pool, this, _1), "re-relay all transactions from pool"); - m_cmd_binder.set_handler("enable_channel", boost::bind(&daemon_commands_handler::enable_channel, this, _1), "Enable specified log channel"); - m_cmd_binder.set_handler("disable_channel", boost::bind(&daemon_commands_handler::disable_channel, this, _1), "Enable specified log channel"); - m_cmd_binder.set_handler("clear_cache", boost::bind(&daemon_commands_handler::clear_cache, this, _1), "Clear blockchain storage cache"); - m_cmd_binder.set_handler("clear_altblocks", boost::bind(&daemon_commands_handler::clear_altblocks, this, _1), "Clear blockchain storage cache"); - m_cmd_binder.set_handler("truncate_bc", boost::bind(&daemon_commands_handler::truncate_bc, this, _1), "Truncate blockchain to specified height"); - m_cmd_binder.set_handler("inspect_block_index", boost::bind(&daemon_commands_handler::inspect_block_index, this, _1), "Inspects block index for internal errors"); - m_cmd_binder.set_handler("print_db_performance_data", boost::bind(&daemon_commands_handler::print_db_performance_data, this, _1), "Dumps all db containers performance counters"); - m_cmd_binder.set_handler("search_by_id", boost::bind(&daemon_commands_handler::search_by_id, this, _1), "Search all possible elemets by given id"); - m_cmd_binder.set_handler("find_key_image", boost::bind(&daemon_commands_handler::find_key_image, this, _1), "Try to find tx related to key_image"); - m_cmd_binder.set_handler("rescan_aliases", boost::bind(&daemon_commands_handler::rescan_aliases, this, _1), "Debug function"); - m_cmd_binder.set_handler("forecast_difficulty", boost::bind(&daemon_commands_handler::forecast_difficulty, this, _1), "Prints PoW and PoS difficulties for as many future blocks as possible based on current conditions"); - m_cmd_binder.set_handler("print_deadlock_guard", boost::bind(&daemon_commands_handler::print_deadlock_guard, this, _1), "Print all threads which is blocked or involved in mutex ownership"); - m_cmd_binder.set_handler("print_block_from_hex_blob", boost::bind(&daemon_commands_handler::print_block_from_hex_blob, this, _1), "Unserialize block from hex binary data to json-like representation"); - m_cmd_binder.set_handler("print_tx_from_hex_blob", boost::bind(&daemon_commands_handler::print_tx_from_hex_blob, this, _1), "Unserialize transaction from hex binary data to json-like representation"); - m_cmd_binder.set_handler("print_tx_outputs_usage", boost::bind(&daemon_commands_handler::print_tx_outputs_usage, this, _1), "Analyse if tx outputs for involved in subsequent transactions"); - m_cmd_binder.set_handler("print_difficulties_of_last_n_blocks", boost::bind(&daemon_commands_handler::print_difficulties_of_last_n_blocks, this, _1), "Print difficulties of last n blocks"); - m_cmd_binder.set_handler("debug_remote_node_mode", boost::bind(&daemon_commands_handler::debug_remote_node_mode, this, _1), " - If node got connected put node into 'debug mode' i.e. no sync process of other communication except ping responses, maintenance secrete key will be requested"); + m_cmd_binder.set_handler("help", boost::bind(&console_handlers_binder::help, &m_cmd_binder, ph::_1), "Show this help"); + m_cmd_binder.set_handler("print_pl", boost::bind(&daemon_commands_handler::print_pl, this, ph::_1), "Print peer list"); + m_cmd_binder.set_handler("print_cn", boost::bind(&daemon_commands_handler::print_cn, this, ph::_1), "Print connections"); + m_cmd_binder.set_handler("print_bc", boost::bind(&daemon_commands_handler::print_bc, this, ph::_1), "Print blockchain info in a given blocks range, print_bc []"); + m_cmd_binder.set_handler("print_bc_tx", boost::bind(&daemon_commands_handler::print_bc_tx, this, ph::_1), "Print blockchain info with trnsactions in a given blocks range, print_bc []"); + //m_cmd_binder.set_handler("print_bci", boost::bind(&daemon_commands_handler::print_bci, this, ph::_1)); + m_cmd_binder.set_handler("print_bc_outs", boost::bind(&daemon_commands_handler::print_bc_outs, this, ph::_1)); + m_cmd_binder.set_handler("print_market", boost::bind(&daemon_commands_handler::print_market, this, ph::_1)); + m_cmd_binder.set_handler("print_bc_outs_stats", boost::bind(&daemon_commands_handler::print_bc_outs_stats, this, ph::_1)); + m_cmd_binder.set_handler("print_block", boost::bind(&daemon_commands_handler::print_block, this, ph::_1), "Print block, print_block | "); + m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_commands_handler::print_block_info, this, ph::_1), "Print block info, print_block | "); + m_cmd_binder.set_handler("print_tx_prun_info", boost::bind(&daemon_commands_handler::print_tx_prun_info, this, ph::_1), "Print tx prunning info"); + m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_commands_handler::print_tx, this, ph::_1), "Print transaction, print_tx "); + m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_commands_handler::start_mining, this, ph::_1), "Start mining for specified address, start_mining [threads=1]"); + m_cmd_binder.set_handler("stop_mining", boost::bind(&daemon_commands_handler::stop_mining, this, ph::_1), "Stop mining"); + m_cmd_binder.set_handler("print_pool", boost::bind(&daemon_commands_handler::print_pool, this, ph::_1), "Print transaction pool (long format)"); + m_cmd_binder.set_handler("print_pool_sh", boost::bind(&daemon_commands_handler::print_pool_sh, this, ph::_1), "Print transaction pool (short format)"); + m_cmd_binder.set_handler("show_hr", boost::bind(&daemon_commands_handler::show_hr, this, ph::_1), "Start showing hash rate"); + m_cmd_binder.set_handler("hide_hr", boost::bind(&daemon_commands_handler::hide_hr, this, ph::_1), "Stop showing hash rate"); + m_cmd_binder.set_handler("save", boost::bind(&daemon_commands_handler::save, this, ph::_1), "Save blockchain"); + m_cmd_binder.set_handler("print_daemon_stat", boost::bind(&daemon_commands_handler::print_daemon_stat, this, ph::_1), "Print daemon stat"); + m_cmd_binder.set_handler("print_debug_stat", boost::bind(&daemon_commands_handler::print_debug_stat, this, ph::_1), "Print debug stat info"); + m_cmd_binder.set_handler("get_transactions_statics", boost::bind(&daemon_commands_handler::get_transactions_statistics, this, ph::_1), "Calculates transactions statistics"); + m_cmd_binder.set_handler("force_relay_tx_pool", boost::bind(&daemon_commands_handler::force_relay_tx_pool, this, ph::_1), "re-relay all transactions from pool"); + m_cmd_binder.set_handler("enable_channel", boost::bind(&daemon_commands_handler::enable_channel, this, ph::_1), "Enable specified log channel"); + m_cmd_binder.set_handler("disable_channel", boost::bind(&daemon_commands_handler::disable_channel, this, ph::_1), "Enable specified log channel"); + m_cmd_binder.set_handler("clear_cache", boost::bind(&daemon_commands_handler::clear_cache, this, ph::_1), "Clear blockchain storage cache"); + m_cmd_binder.set_handler("clear_altblocks", boost::bind(&daemon_commands_handler::clear_altblocks, this, ph::_1), "Clear blockchain storage cache"); + m_cmd_binder.set_handler("truncate_bc", boost::bind(&daemon_commands_handler::truncate_bc, this, ph::_1), "Truncate blockchain to specified height"); + m_cmd_binder.set_handler("inspect_block_index", boost::bind(&daemon_commands_handler::inspect_block_index, this, ph::_1), "Inspects block index for internal errors"); + m_cmd_binder.set_handler("print_db_performance_data", boost::bind(&daemon_commands_handler::print_db_performance_data, this, ph::_1), "Dumps all db containers performance counters"); + m_cmd_binder.set_handler("search_by_id", boost::bind(&daemon_commands_handler::search_by_id, this, ph::_1), "Search all possible elemets by given id"); + m_cmd_binder.set_handler("find_key_image", boost::bind(&daemon_commands_handler::find_key_image, this, ph::_1), "Try to find tx related to key_image"); + m_cmd_binder.set_handler("rescan_aliases", boost::bind(&daemon_commands_handler::rescan_aliases, this, ph::_1), "Debug function"); + m_cmd_binder.set_handler("forecast_difficulty", boost::bind(&daemon_commands_handler::forecast_difficulty, this, ph::_1), "Prints PoW and PoS difficulties for as many future blocks as possible based on current conditions"); + m_cmd_binder.set_handler("print_deadlock_guard", boost::bind(&daemon_commands_handler::print_deadlock_guard, this, ph::_1), "Print all threads which is blocked or involved in mutex ownership"); + m_cmd_binder.set_handler("print_block_from_hex_blob", boost::bind(&daemon_commands_handler::print_block_from_hex_blob, this, ph::_1), "Unserialize block from hex binary data to json-like representation"); + m_cmd_binder.set_handler("print_tx_from_hex_blob", boost::bind(&daemon_commands_handler::print_tx_from_hex_blob, this, ph::_1), "Unserialize transaction from hex binary data to json-like representation"); + m_cmd_binder.set_handler("print_tx_outputs_usage", boost::bind(&daemon_commands_handler::print_tx_outputs_usage, this, ph::_1), "Analyse if tx outputs for involved in subsequent transactions"); + m_cmd_binder.set_handler("print_difficulties_of_last_n_blocks", boost::bind(&daemon_commands_handler::print_difficulties_of_last_n_blocks, this, ph::_1), "Print difficulties of last n blocks"); + m_cmd_binder.set_handler("debug_remote_node_mode", boost::bind(&daemon_commands_handler::debug_remote_node_mode, this, ph::_1), " - If node got connected put node into 'debug mode' i.e. no sync process of other communication except ping responses, maintenance secrete key will be requested"); #ifdef _DEBUG - m_cmd_binder.set_handler("debug_set_time_adj", boost::bind(&daemon_commands_handler::debug_set_time_adj, this, _1), "DEBUG: set core time adjustment"); + m_cmd_binder.set_handler("debug_set_time_adj", boost::bind(&daemon_commands_handler::debug_set_time_adj, this, ph::_1), "DEBUG: set core time adjustment"); #endif } diff --git a/src/gui/qt-daemon/application/mainwindow.cpp b/src/gui/qt-daemon/application/mainwindow.cpp index 646e4d3b..77e558cb 100644 --- a/src/gui/qt-daemon/application/mainwindow.cpp +++ b/src/gui/qt-daemon/application/mainwindow.cpp @@ -100,6 +100,7 @@ MainWindow::MainWindow() , m_system_shutdown(false) , m_view(nullptr) , m_channel(nullptr) + , m_ui_dispatch_id_counter(0) { #ifndef _MSC_VER //workaround for macos broken tolower from std, very dirty hack @@ -415,7 +416,7 @@ bool MainWindow::init(const std::string& html_path) //QtWebEngine::initialize(); init_tray_icon(html_path); set_html_path(html_path); - + m_threads_pool.init(2); m_backend.subscribe_to_core_events(this); bool r = QSslSocket::supportsSsl(); @@ -920,6 +921,41 @@ QString MainWindow::start_backend(const QString& params) CATCH_ENTRY_FAIL_API_RESPONCE(); } +QString MainWindow::sync_call(const QString& func_name, const QString& params) +{ + if (func_name == "transfer") + { + return this->transfer(params); + } + else if (func_name == "test_call") + { + return params; + } + else + { + return QString(QString() + "{ \"status\": \"Method '" + func_name + "' not found\"}"); + } +} + +QString MainWindow::async_call(const QString& func_name, const QString& params) +{ + + uint64_t job_id = m_ui_dispatch_id_counter++; + QString method_name = func_name; + QString argements = params; + + auto async_callback = [this, method_name, argements, job_id]() + { + QString res_str = this->sync_call(method_name, argements); + this->dispatch_async_call_result(std::to_string(job_id).c_str(), res_str); //general function + }; + + m_threads_pool.add_job(async_callback); + LOG_PRINT_L2("[UI_ASYNC_CALL]: started " << method_name.toStdString() << ", job id: " << job_id); + return QString::fromStdString(std::string("{ \"job_id\": ") + std::to_string(job_id) + "}"); +} + + bool MainWindow::update_wallet_status(const view::wallet_status_info& wsi) { TRY_ENTRY(); @@ -947,6 +983,17 @@ bool MainWindow::set_options(const view::gui_options& opt) CATCH_ENTRY2(false); } +bool MainWindow::update_tor_status(const view::current_action_status& opt) +{ + TRY_ENTRY(); + std::string json_str; + epee::serialization::store_t_to_json(opt, json_str, 0, epee::serialization::eol_lf); + LOG_PRINT_L0("SENDING SIGNAL -> [HANDLE_CURRENT_ACTION_STATE]:" << std::endl << json_str); + QMetaObject::invokeMethod(this, "handle_current_action_state", Qt::QueuedConnection, Q_ARG(QString, json_str.c_str())); + return true; + CATCH_ENTRY2(false); +} + bool MainWindow::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { TRY_ENTRY(); @@ -1654,6 +1701,20 @@ QString MainWindow::get_log_level(const QString& param) CATCH_ENTRY_FAIL_API_RESPONCE(); } +QString MainWindow::set_enable_tor(const QString& param) +{ + TRY_ENTRY(); + LOG_API_TIMING(); + PREPARE_ARG_FROM_JSON(currency::struct_with_one_t_type, enabl_tor); + m_backend.set_use_tor(enabl_tor.v); + //epee::log_space::get_set_log_detalisation_level(true, enabl_tor.v); + default_ar.error_code = API_RETURN_CODE_OK; + LOG_PRINT("[TOR]: Enable TOR set to " << enabl_tor.v, LOG_LEVEL_MIN); + + return MAKE_RESPONSE(default_ar); + CATCH_ENTRY_FAIL_API_RESPONCE(); +} + // QString MainWindow::dump_all_offers() // { // LOG_API_TIMING(); diff --git a/src/gui/qt-daemon/application/mainwindow.h b/src/gui/qt-daemon/application/mainwindow.h index 4f7af71d..f01dbe93 100644 --- a/src/gui/qt-daemon/application/mainwindow.h +++ b/src/gui/qt-daemon/application/mainwindow.h @@ -18,6 +18,8 @@ #include "currency_core/offers_services_helpers.h" #endif +#include "common/threads_pool.h" + QT_BEGIN_NAMESPACE class QWebEngineView; class QLineEdit; @@ -137,6 +139,7 @@ public: QString stop_pos_mining(const QString& param); QString set_log_level(const QString& param); QString get_log_level(const QString& param); + QString set_enable_tor(const QString& param); // QString dump_all_offers(); QString webkit_launched_script(); QString get_smart_wallet_info(const QString& param); @@ -179,6 +182,9 @@ public: QString is_remnotenode_mode_preconfigured(); QString start_backend(const QString& params); + QString async_call(const QString& func_name, const QString& params); + QString sync_call(const QString& func_name, const QString& params); + //for test purposes onlys QString request_dummy(); @@ -192,11 +198,11 @@ signals: void wallet_sync_progress(const QString str); void handle_internal_callback(const QString str, const QString callback_name); void update_pos_mining_text(const QString str); - void do_dispatch(const QString status, const QString params); //general function void on_core_event(const QString method_name); //general function void set_options(const QString str); //general function - void get_wallet_name(); void handle_deeplink_click(const QString str); + void handle_current_action_state(const QString str); + void dispatch_async_call_result(const QString id, const QString resp); //general function private: //-------------------- i_core_event_handler -------------------- @@ -216,6 +222,7 @@ private: virtual bool init(const std::string& path); virtual bool pos_block_found(const currency::block& block_found); virtual bool set_options(const view::gui_options& opt); + virtual bool update_tor_status(const view::current_action_status& opt); //--------- QAbstractNativeEventFilter --------------------------- virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result); //---------------------------------------------- @@ -257,6 +264,8 @@ private: std::atomic m_gui_deinitialize_done_1; std::atomic m_backend_stopped_2; std::atomic m_system_shutdown; + std::atomic m_ui_dispatch_id_counter; + utils::threads_pool m_threads_pool; std::string m_master_password; diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index 709a1e6a..b091d45a 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit 709a1e6a3eb5ae7af48bbadf6b4c512b637b75b3 +Subproject commit b091d45ad697db2d35e94de41be3f175bad0f71d diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 477d7e8b..a63e88ed 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -26,18 +26,18 @@ namespace nodetool namespace { - const command_line::arg_descriptor arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"}; - const command_line::arg_descriptor arg_p2p_bind_port = {"p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)}; - const command_line::arg_descriptor arg_p2p_external_port = {"p2p-external-port", "External port for p2p network protocol (if port forwarding used with NAT)", 0}; - const command_line::arg_descriptor arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"}; - const command_line::arg_descriptor > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"}; - const command_line::arg_descriptor > arg_p2p_add_priority_node = {"add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"}; - const command_line::arg_descriptor arg_p2p_use_only_priority_nodes = {"use-only-priority-nodes", "Try to connect only to priority nodes"}; - const command_line::arg_descriptor > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"}; - const command_line::arg_descriptor arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true}; - const command_line::arg_descriptor arg_p2p_offline_mode = { "offline-mode", "Don't connect to any node and reject any connections", false, true }; - const command_line::arg_descriptor arg_p2p_disable_debug_reqs = { "disable-debug-p2p-requests", "Disable p2p debug requests", false, true }; - const command_line::arg_descriptor arg_p2p_ip_auto_blocking = { "p2p-ip-auto-blocking", "Enable (1) or disable (0) peers auto-blocking by IP <0|1>. Default: 0", 0, false }; + const command_line::arg_descriptor arg_p2p_bind_ip ("p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"); + const command_line::arg_descriptor arg_p2p_bind_port ("p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)); + const command_line::arg_descriptor arg_p2p_external_port ("p2p-external-port", "External port for p2p network protocol (if port forwarding used with NAT)", 0); + const command_line::arg_descriptor arg_p2p_allow_local_ip ("allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"); + const command_line::arg_descriptor > arg_p2p_add_peer ("add-peer", "Manually add peer to local peerlist"); + const command_line::arg_descriptor > arg_p2p_add_priority_node ("add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"); + const command_line::arg_descriptor arg_p2p_use_only_priority_nodes ("use-only-priority-nodes", "Try to connect only to priority nodes"); + const command_line::arg_descriptor > arg_p2p_seed_node ("seed-node", "Connect to a node to retrieve peer addresses, and disconnect"); + const command_line::arg_descriptor arg_p2p_hide_my_port ("hide-my-port", "Do not announce yourself as peerlist candidate"); + const command_line::arg_descriptor arg_p2p_offline_mode ( "offline-mode", "Don't connect to any node and reject any connections"); + const command_line::arg_descriptor arg_p2p_disable_debug_reqs ( "disable-debug-p2p-requests", "Disable p2p debug requests"); + const command_line::arg_descriptor arg_p2p_ip_auto_blocking ( "p2p-ip-auto-blocking", "Enable (1) or disable (0) peers auto-blocking by IP <0|1>. Default: 0", 1); } //----------------------------------------------------------------------------------- diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index c16efcac..5adc60f9 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -22,9 +22,9 @@ namespace currency { namespace { - const command_line::arg_descriptor arg_rpc_bind_ip = {"rpc-bind-ip", "", "127.0.0.1"}; - const command_line::arg_descriptor arg_rpc_bind_port = {"rpc-bind-port", "", std::to_string(RPC_DEFAULT_PORT)}; - const command_line::arg_descriptor arg_rpc_ignore_status = {"rpc-ignore-offline", "Let rpc calls despite online/offline status", false, true }; + const command_line::arg_descriptor arg_rpc_bind_ip ("rpc-bind-ip", "", "127.0.0.1"); + const command_line::arg_descriptor arg_rpc_bind_port ("rpc-bind-port", "", std::to_string(RPC_DEFAULT_PORT)); + const command_line::arg_descriptor arg_rpc_ignore_status ("rpc-ignore-offline", "Let rpc calls despite online/offline status"); } //----------------------------------------------------------------------------------- void core_rpc_server::init_options(boost::program_options::options_description& desc) @@ -705,7 +705,7 @@ namespace currency } - NOTIFY_NEW_TRANSACTIONS::request r; + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request r; r.txs.push_back(tx_blob); m_core.get_protocol()->relay_transactions(r, fake_context); //TODO: make sure that tx has reached other nodes here, probably wait to receive reflections from other nodes @@ -716,7 +716,7 @@ namespace currency bool core_rpc_server::on_force_relaey_raw_txs(const COMMAND_RPC_FORCE_RELAY_RAW_TXS::request& req, COMMAND_RPC_FORCE_RELAY_RAW_TXS::response& res, connection_context& cntx) { CHECK_CORE_READY(); - NOTIFY_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); for (const auto& t : req.txs_as_hex) { diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index cfb48a64..1cc8d064 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -33,30 +33,32 @@ using namespace epee; using namespace currency; using boost::lexical_cast; namespace po = boost::program_options; +namespace ph = boost::placeholders; #define EXTENDED_LOGS_FILE "wallet_details.log" namespace { - const command_line::arg_descriptor arg_wallet_file = {"wallet-file", "Use wallet ", ""}; - const command_line::arg_descriptor arg_generate_new_wallet = {"generate-new-wallet", "Generate new wallet and save it to or
.wallet by default", ""}; - const command_line::arg_descriptor arg_generate_new_auditable_wallet = {"generate-new-auditable-wallet", "Generate new auditable wallet and store it to ", ""}; - const command_line::arg_descriptor arg_daemon_address = {"daemon-address", "Use daemon instance at :", ""}; - const command_line::arg_descriptor arg_daemon_host = {"daemon-host", "Use daemon instance at host instead of localhost", ""}; - const command_line::arg_descriptor arg_password = {"password", "Wallet password", "", true}; - const command_line::arg_descriptor arg_dont_refresh = { "no-refresh", "Do not refresh after load", false, true }; - const command_line::arg_descriptor arg_dont_set_date = { "no-set-creation-date", "Do not set wallet creation date", false, false }; - const command_line::arg_descriptor arg_daemon_port = {"daemon-port", "Use daemon instance at port instead of default", 0}; - const command_line::arg_descriptor arg_log_level = {"set-log", "", 0, true}; - const command_line::arg_descriptor arg_do_pos_mining = { "do-pos-mining", "Do PoS mining", false, false }; - const command_line::arg_descriptor arg_pos_mining_reward_address = { "pos-mining-reward-address", "Block reward will be sent to the giving address if specified", "" }; - const command_line::arg_descriptor arg_restore_wallet = { "restore-wallet", "Restore wallet from seed phrase or tracking seed and save it to ", "" }; - const command_line::arg_descriptor arg_offline_mode = { "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)", false, true }; - const command_line::arg_descriptor arg_scan_for_wallet = { "scan-for-wallet", "", "", true }; - const command_line::arg_descriptor arg_addr_to_compare = { "addr-to-compare", "", "", true }; + const command_line::arg_descriptor arg_wallet_file ("wallet-file", "Use wallet ", ""); + const command_line::arg_descriptor arg_generate_new_wallet ("generate-new-wallet", "Generate new wallet and save it to or
.wallet by default", ""); + const command_line::arg_descriptor arg_generate_new_auditable_wallet ("generate-new-auditable-wallet", "Generate new auditable wallet and store it to ", ""); + const command_line::arg_descriptor arg_daemon_address ("daemon-address", "Use daemon instance at :", ""); + const command_line::arg_descriptor arg_daemon_host ("daemon-host", "Use daemon instance at host instead of localhost", ""); + const command_line::arg_descriptor arg_password ("password", "Wallet password"); + const command_line::arg_descriptor arg_dont_refresh ( "no-refresh", "Do not refresh after load"); + const command_line::arg_descriptor arg_dont_set_date ( "no-set-creation-date", "Do not set wallet creation date", false); + const command_line::arg_descriptor arg_daemon_port ("daemon-port", "Use daemon instance at port instead of default", 0); + const command_line::arg_descriptor arg_log_level ("set-log", ""); + const command_line::arg_descriptor arg_do_pos_mining ( "do-pos-mining", "Do PoS mining", false); + const command_line::arg_descriptor arg_pos_mining_reward_address ( "pos-mining-reward-address", "Block reward will be sent to the giving address if specified", "" ); + const command_line::arg_descriptor arg_restore_wallet ( "restore-wallet", "Restore wallet from seed phrase or tracking seed and save it to ", "" ); + const command_line::arg_descriptor arg_offline_mode ( "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)"); + const command_line::arg_descriptor arg_scan_for_wallet ( "scan-for-wallet", ""); + const command_line::arg_descriptor arg_addr_to_compare ( "addr-to-compare", ""); + const command_line::arg_descriptor arg_disable_tor_relay ( "disable-tor-relay", "Do PoS mining", false); - const command_line::arg_descriptor< std::vector > arg_command = {"command", ""}; + const command_line::arg_descriptor< std::vector > arg_command ("command", ""); inline std::string interpret_rpc_response(bool ok, const std::string& status) { @@ -123,17 +125,9 @@ namespace m_flush = false; LOG_PRINT(m_oss.str(), m_log_level) - - if (epee::log_space::console_color_default == m_color) - { - std::cout << m_oss.str(); - } - else - { - epee::log_space::set_console_color(m_color, m_bright); - std::cout << m_oss.str(); - epee::log_space::reset_console_color(); - } + epee::log_space::set_console_color(m_color, m_bright); + std::cout << m_oss.str(); + epee::log_space::reset_console_color(); std::cout << std::endl; } @@ -186,49 +180,51 @@ simple_wallet::simple_wallet() m_refresh_progress_reporter(*this), m_offline_mode(false) { - m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::start_mining, this, _1), "start_mining - Start mining in daemon"); - m_cmd_binder.set_handler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, _1), "Stop mining in daemon"); - m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, _1), "Resynchronize transactions and balance"); - m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, _1), "Show current wallet balance"); - m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability"); - m_cmd_binder.set_handler("incoming_counts", boost::bind(&simple_wallet::show_incoming_transfers_counts, this, _1), "incoming_transfers counts"); - m_cmd_binder.set_handler("list_recent_transfers", boost::bind(&simple_wallet::list_recent_transfers, this, _1), "list_recent_transfers [offset] [count] - Show recent maximum 1000 transfers, offset default = 0, count default = 100 "); - m_cmd_binder.set_handler("export_recent_transfers", boost::bind(&simple_wallet::export_recent_transfers, this, _1), "list_recent_transfers_tx - Write recent transfer in json to wallet_recent_transfers.txt"); - m_cmd_binder.set_handler("list_outputs", boost::bind(&simple_wallet::list_outputs, this, _1), "list_outputs [spent|unspent] - Lists all the outputs that have ever been sent to this wallet if called without arguments, otherwise it lists only the spent or unspent outputs"); - m_cmd_binder.set_handler("dump_transfers", boost::bind(&simple_wallet::dump_trunsfers, this, _1), "dump_transfers - Write transfers in json to dump_transfers.txt"); - m_cmd_binder.set_handler("dump_keyimages", boost::bind(&simple_wallet::dump_key_images, this, _1), "dump_keyimages - Write key_images in json to dump_key_images.txt"); - m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), "payments [ ... ] - Show payments , ... "); - m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), "Show blockchain height"); - m_cmd_binder.set_handler("wallet_bc_height", boost::bind(&simple_wallet::show_wallet_bcheight, this, _1), "Show blockchain height"); - m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer, this, _1), "transfer [ ... ] [payment_id] - Transfer ,... to ,... , respectively. is the number of transactions yours is indistinguishable from (from 0 to maximum available), is an optional HEX-encoded string"); - m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), "set_log - Change current log detalisation level, is a number 0-4"); - m_cmd_binder.set_handler("enable_console_logger", boost::bind(&simple_wallet::enable_console_logger, this, _1), "Enables console logging"); - m_cmd_binder.set_handler("resync", boost::bind(&simple_wallet::resync_wallet, this, _1), "Causes wallet to reset all transfers and re-synchronize wallet"); - m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), "Show this help"); - m_cmd_binder.set_handler("get_transfer_info", boost::bind(&simple_wallet::get_transfer_info, this, _1), "displays transfer info by key_image or index"); - m_cmd_binder.set_handler("scan_for_collision", boost::bind(&simple_wallet::scan_for_key_image_collisions, this, _1), "Rescan transfers for key image collisions"); - m_cmd_binder.set_handler("fix_collisions", boost::bind(&simple_wallet::fix_collisions, this, _1), "Rescan transfers for key image collisions"); - m_cmd_binder.set_handler("scan_transfers_for_id", boost::bind(&simple_wallet::scan_transfers_for_id, this, _1), "Rescan transfers for tx_id"); - m_cmd_binder.set_handler("scan_transfers_for_ki", boost::bind(&simple_wallet::scan_transfers_for_ki, this, _1), "Rescan transfers for key image"); - m_cmd_binder.set_handler("print_utxo_distribution", boost::bind(&simple_wallet::print_utxo_distribution, this, _1), "Prints utxo distribution"); - m_cmd_binder.set_handler("sweep_below", boost::bind(&simple_wallet::sweep_below, this, _1), "sweep_below
[payment_id] - Tries to transfers all coins with amount below the given limit to the given address"); + m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::start_mining, this, ph::_1), "start_mining - Start mining in daemon"); + m_cmd_binder.set_handler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, ph::_1), "Stop mining in daemon"); + m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, ph::_1), "Resynchronize transactions and balance"); + m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, ph::_1), "Show current wallet balance"); + m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, ph::_1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability"); + m_cmd_binder.set_handler("incoming_counts", boost::bind(&simple_wallet::show_incoming_transfers_counts, this, ph::_1), "incoming_transfers counts"); + m_cmd_binder.set_handler("list_recent_transfers", boost::bind(&simple_wallet::list_recent_transfers, this, ph::_1), "list_recent_transfers [offset] [count] - Show recent maximum 1000 transfers, offset default = 0, count default = 100 "); + m_cmd_binder.set_handler("export_recent_transfers", boost::bind(&simple_wallet::export_recent_transfers, this, ph::_1), "list_recent_transfers_tx - Write recent transfer in json to wallet_recent_transfers.txt"); + m_cmd_binder.set_handler("list_outputs", boost::bind(&simple_wallet::list_outputs, this, ph::_1), "list_outputs [spent|unspent] - Lists all the outputs that have ever been sent to this wallet if called without arguments, otherwise it lists only the spent or unspent outputs"); + m_cmd_binder.set_handler("dump_transfers", boost::bind(&simple_wallet::dump_trunsfers, this, ph::_1), "dump_transfers - Write transfers in json to dump_transfers.txt"); + m_cmd_binder.set_handler("dump_keyimages", boost::bind(&simple_wallet::dump_key_images, this, ph::_1), "dump_keyimages - Write key_images in json to dump_key_images.txt"); + m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, ph::_1), "payments [ ... ] - Show payments , ... "); + m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this,ph::_1), "Show blockchain height"); + m_cmd_binder.set_handler("wallet_bc_height", boost::bind(&simple_wallet::show_wallet_bcheight, this,ph::_1), "Show blockchain height"); + m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer, this,ph::_1), "transfer [ ... ] [payment_id] - Transfer ,... to ,... , respectively. is the number of transactions yours is indistinguishable from (from 0 to maximum available), is an optional HEX-encoded string"); + m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this,ph::_1), "set_log - Change current log detalisation level, is a number 0-4"); + m_cmd_binder.set_handler("enable_console_logger", boost::bind(&simple_wallet::enable_console_logger, this,ph::_1), "Enables console logging"); + m_cmd_binder.set_handler("resync", boost::bind(&simple_wallet::resync_wallet, this,ph::_1), "Causes wallet to reset all transfers and re-synchronize wallet"); + m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this,ph::_1), "Show this help"); + m_cmd_binder.set_handler("get_transfer_info", boost::bind(&simple_wallet::get_transfer_info, this,ph::_1), "displays transfer info by key_image or index"); + m_cmd_binder.set_handler("scan_for_collision", boost::bind(&simple_wallet::scan_for_key_image_collisions, this,ph::_1), "Rescan transfers for key image collisions"); + m_cmd_binder.set_handler("fix_collisions", boost::bind(&simple_wallet::fix_collisions, this,ph::_1), "Rescan transfers for key image collisions"); + m_cmd_binder.set_handler("scan_transfers_for_id", boost::bind(&simple_wallet::scan_transfers_for_id, this,ph::_1), "Rescan transfers for tx_id"); + m_cmd_binder.set_handler("scan_transfers_for_ki", boost::bind(&simple_wallet::scan_transfers_for_ki, this,ph::_1), "Rescan transfers for key image"); + m_cmd_binder.set_handler("print_utxo_distribution", boost::bind(&simple_wallet::print_utxo_distribution, this,ph::_1), "Prints utxo distribution"); + m_cmd_binder.set_handler("sweep_below", boost::bind(&simple_wallet::sweep_below, this,ph::_1), "sweep_below
[payment_id] - Tries to transfers all coins with amount below the given limit to the given address"); - m_cmd_binder.set_handler("address", boost::bind(&simple_wallet::print_address, this, _1), "Show current wallet public address"); - m_cmd_binder.set_handler("integrated_address", boost::bind(&simple_wallet::integrated_address, this, _1), "integrated_address [||"); + m_cmd_binder.set_handler("get_tx_key", boost::bind(&simple_wallet::get_tx_key, this,ph::_1), "Get transaction one-time secret key (r) for a given "); - m_cmd_binder.set_handler("tracking_seed", boost::bind(&simple_wallet::tracking_seed, this, _1), "For auditable wallets: prints tracking seed for wallet's audit by a third party"); + m_cmd_binder.set_handler("tracking_seed", boost::bind(&simple_wallet::tracking_seed, this,ph::_1), "For auditable wallets: prints tracking seed for wallet's audit by a third party"); - m_cmd_binder.set_handler("save", boost::bind(&simple_wallet::save, this, _1), "Save wallet synchronized data"); - m_cmd_binder.set_handler("save_watch_only", boost::bind(&simple_wallet::save_watch_only, this, _1), "save_watch_only - save as watch-only wallet file."); + m_cmd_binder.set_handler("save", boost::bind(&simple_wallet::save, this,ph::_1), "Save wallet synchronized data"); + m_cmd_binder.set_handler("save_watch_only", boost::bind(&simple_wallet::save_watch_only, this,ph::_1), "save_watch_only - save as watch-only wallet file."); - m_cmd_binder.set_handler("sign_transfer", boost::bind(&simple_wallet::sign_transfer, this, _1), "sign_transfer - sign unsigned tx from a watch-only wallet"); - m_cmd_binder.set_handler("submit_transfer", boost::bind(&simple_wallet::submit_transfer, this, _1), "submit_transfer - broadcast signed tx"); - m_cmd_binder.set_handler("export_history", boost::bind(&simple_wallet::submit_transfer, this, _1), "Export transaction history in CSV file"); + m_cmd_binder.set_handler("sign_transfer", boost::bind(&simple_wallet::sign_transfer, this,ph::_1), "sign_transfer - sign unsigned tx from a watch-only wallet"); + m_cmd_binder.set_handler("submit_transfer", boost::bind(&simple_wallet::submit_transfer, this,ph::_1), "submit_transfer - broadcast signed tx"); + m_cmd_binder.set_handler("export_history", boost::bind(&simple_wallet::submit_transfer, this,ph::_1), "Export transaction history in CSV file"); + m_cmd_binder.set_handler("tor_enable", boost::bind(&simple_wallet::tor_enable, this, _1), "Enable relaying transactions over TOR network(enabled by default)"); + m_cmd_binder.set_handler("tor_disable", boost::bind(&simple_wallet::tor_disable, this, _1), "Enable relaying transactions over TOR network(enabled by default)"); } //---------------------------------------------------------------------------------------------------- simple_wallet::~simple_wallet() @@ -361,6 +357,11 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) bool r = open_wallet(m_wallet_file, pwd_container.password()); CHECK_AND_ASSERT_MES(r, false, "could not open account"); } + if (m_disable_tor) + { + m_wallet->set_disable_tor_relay(true); + message_writer(epee::log_space::console_color_default, true, std::string(), LOG_LEVEL_0) << "Notice: Relaying transactions over TOR disabled with command line parameter"; + } return true; } @@ -384,6 +385,7 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_ m_do_not_set_date = command_line::get_arg(vm, arg_dont_set_date); m_do_pos_mining = command_line::get_arg(vm, arg_do_pos_mining); m_restore_wallet = command_line::get_arg(vm, arg_restore_wallet); + m_disable_tor = command_line::get_arg(vm, arg_disable_tor_relay); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::try_connect_to_daemon() @@ -658,6 +660,34 @@ void simple_wallet::on_message(i_wallet2_callback::message_severity severity, co message_writer(color, true, std::string()) << m; } //---------------------------------------------------------------------------------------------------- +void simple_wallet::on_tor_status_change(const std::string& state) +{ + std::string human_message; + if (state == TOR_LIB_STATE_INITIALIZING) + human_message = "Initializing..."; + else if (state == TOR_LIB_STATE_DOWNLOADING_CONSENSUS) + human_message = "Downloading consensus..."; + else if (state == TOR_LIB_STATE_MAKING_TUNNEL_A) + human_message = "Building tunnel to A..."; + else if (state == TOR_LIB_STATE_MAKING_TUNNEL_B) + human_message = "Building tunnel to B..."; + else if (state == TOR_LIB_STATE_CREATING_STREAM) + human_message = "Creating stream..."; + else if (state == TOR_LIB_STATE_SUCCESS) + human_message = "Successfully created stream"; + else if (state == TOR_LIB_STATE_FAILED) + human_message = "Failed created stream"; + else if (state == WALLET_LIB_STATE_SENDING) + human_message = "Sending transaction..."; + else if (state == WALLET_LIB_SENT_SUCCESS) + human_message = "Successfully sent!"; + else if (state == WALLET_LIB_SEND_FAILED) + human_message = "Sending failed"; + + + message_writer(epee::log_space::console_color_yellow, true, std::string("[TOR]: ")) << human_message; +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::refresh(const std::vector& args) { if (m_offline_mode) @@ -1710,6 +1740,21 @@ bool simple_wallet::submit_transfer(const std::vector &args) } return true; } +//---------------------------------------------------------------------------------------------------- +bool simple_wallet::tor_enable(const std::vector &args) +{ + success_msg_writer(true) << "TOR relaying enabled"; + m_wallet->set_disable_tor_relay(false); + return true; +} +//---------------------------------------------------------------------------------------------------- +bool simple_wallet::tor_disable(const std::vector &args) +{ + m_wallet->set_disable_tor_relay(true); + success_msg_writer(true) << "TOR relaying disabled"; + return true; +} + //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_below(const std::vector &args) { @@ -1960,6 +2005,8 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, command_line::arg_log_level); command_line::add_arg(desc_params, arg_scan_for_wallet); command_line::add_arg(desc_params, arg_addr_to_compare); + command_line::add_arg(desc_params, arg_disable_tor_relay); + tools::wallet_rpc_server::init_options(desc_params); @@ -2154,6 +2201,13 @@ int main(int argc, char* argv[]) } else // if(command_line::has_arg(vm, tools::wallet_rpc_server::arg_rpc_bind_port)) { + if (command_line::get_arg(vm, arg_do_pos_mining)) + { + // PoS mining can be turned on only in RPC server mode, please provide --rpc-bind-port to make this + fail_msg_writer() << "PoS mining can be turned on only in RPC server mode, please provide --rpc-bind-port=PORT_NO to enable staking in simplewallet"; + return EXIT_FAILURE; + } + //runs wallet with console interface sw->set_offline_mode(offline_mode); r = sw->init(vm); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 35f99128..f5138544 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -86,6 +86,8 @@ namespace currency bool sign_transfer(const std::vector &args); bool submit_transfer(const std::vector &args); bool sweep_below(const std::vector &args); + bool tor_enable(const std::vector &args); + bool tor_disable(const std::vector &args); bool validate_wrap_status(uint64_t amount); bool get_alias_from_daemon(const std::string& alias_name, currency::extra_alias_entry_base& ai); @@ -98,6 +100,7 @@ namespace currency virtual void on_new_block(uint64_t height, const currency::block& block) override; virtual void on_transfer2(const tools::wallet_public::wallet_transfer_info& wti, uint64_t balance, uint64_t unlocked_balance, uint64_t total_mined) override; virtual void on_message(i_wallet2_callback::message_severity severity, const std::string& m) override; + virtual void on_tor_status_change(const std::string& state) override; //---------------------------------------------------------- @@ -166,6 +169,7 @@ namespace currency bool m_do_not_set_date; bool m_do_pos_mining; bool m_offline_mode; + bool m_disable_tor; std::string m_restore_wallet; epee::console_handlers_binder m_cmd_binder; diff --git a/src/stratum/stratum_server.cpp b/src/stratum/stratum_server.cpp index 5e239baa..f952cd7a 100644 --- a/src/stratum/stratum_server.cpp +++ b/src/stratum/stratum_server.cpp @@ -39,25 +39,25 @@ namespace #define VDIFF_RETARGET_SHARES_COUNT 12 // enforce retargeting if this many shares are received (high performace in terms of current difficulty) #define VDIFF_VARIANCE_PERCENT_DEFAULT 25 // % - const command_line::arg_descriptor arg_stratum = {"stratum", "Stratum server: enable" }; - const command_line::arg_descriptor arg_stratum_bind_ip = {"stratum-bind-ip", "Stratum server: IP to bind", STRATUM_BIND_IP_DEFAULT }; - const command_line::arg_descriptor arg_stratum_bind_port = {"stratum-bind-port", "Stratum server: port to listen at", std::to_string(STRATUM_DEFAULT_PORT) }; - const command_line::arg_descriptor arg_stratum_threads = {"stratum-threads-count", "Stratum server: number of server threads", STRATUM_THREADS_COUNT_DEFAULT }; + const command_line::arg_descriptor arg_stratum ("stratum", "Stratum server: enable" ); + const command_line::arg_descriptor arg_stratum_bind_ip ("stratum-bind-ip", "Stratum server: IP to bind", STRATUM_BIND_IP_DEFAULT ); + const command_line::arg_descriptor arg_stratum_bind_port ("stratum-bind-port", "Stratum server: port to listen at", std::to_string(STRATUM_DEFAULT_PORT) ); + const command_line::arg_descriptor arg_stratum_threads ("stratum-threads-count", "Stratum server: number of server threads", STRATUM_THREADS_COUNT_DEFAULT ); const command_line::arg_descriptor arg_stratum_miner_address = {"stratum-miner-address", "Stratum server: miner address. All workers" " will mine to this address. If not set here, ALL workers should use the very same wallet address as username." - " If set here - they're allowed to log in with username '" WORKER_ALLOWED_USERNAME "' instead of address.", "", true }; + " If set here - they're allowed to log in with username '" WORKER_ALLOWED_USERNAME "' instead of address."}; const command_line::arg_descriptor arg_stratum_block_template_update_period = {"stratum-template-update-period", "Stratum server: if there are no new blocks, update block template this often (sec.)", STRATUM_BLOCK_TEMPLATE_UPD_PERIOD_DEFAULT }; - const command_line::arg_descriptor arg_stratum_hr_print_interval = {"stratum-hr-print-interval", "Stratum server: how often to print hashrate stats (sec.)", STRATUM_TOTAL_HR_PRINT_INTERVAL_S_DEFAULT }; + const command_line::arg_descriptor arg_stratum_hr_print_interval ("stratum-hr-print-interval", "Stratum server: how often to print hashrate stats (sec.)", STRATUM_TOTAL_HR_PRINT_INTERVAL_S_DEFAULT ); - const command_line::arg_descriptor arg_stratum_vdiff_target_min = {"stratum-vdiff-target-min", "Stratum server: minimum worker difficulty", VDIFF_TARGET_MIN_DEFAULT }; - const command_line::arg_descriptor arg_stratum_vdiff_target_max = {"stratum-vdiff-target-max", "Stratum server: maximum worker difficulty", VDIFF_TARGET_MAX_DEFAULT }; - const command_line::arg_descriptor arg_stratum_vdiff_target_time = {"stratum-vdiff-target-time", "Stratum server: target time per share (i.e. try to get one share per this many seconds)", VDIFF_TARGET_TIME_DEFAULT }; - const command_line::arg_descriptor arg_stratum_vdiff_retarget_time = {"stratum-vdiff-retarget-time", "Stratum server: check to see if we should retarget this often (sec.)", VDIFF_RETARGET_TIME_DEFAULT }; - const command_line::arg_descriptor arg_stratum_vdiff_retarget_shares = {"stratum-vdiff-retarget-shares", "Stratum server: enforce retargeting if got this many shares", VDIFF_RETARGET_SHARES_COUNT }; - const command_line::arg_descriptor arg_stratum_vdiff_variance_percent = {"stratum-vdiff-variance-percent", "Stratum server: allow average time to very this % from target without retarget", VDIFF_VARIANCE_PERCENT_DEFAULT }; - const command_line::arg_descriptor arg_stratum_always_online = { "stratum-always-online", "Stratum server consider the core being synchronized regardless of online status, useful for debugging with --offline-mode" }; + const command_line::arg_descriptor arg_stratum_vdiff_target_min ("stratum-vdiff-target-min", "Stratum server: minimum worker difficulty", VDIFF_TARGET_MIN_DEFAULT ); + const command_line::arg_descriptor arg_stratum_vdiff_target_max ("stratum-vdiff-target-max", "Stratum server: maximum worker difficulty", VDIFF_TARGET_MAX_DEFAULT ); + const command_line::arg_descriptor arg_stratum_vdiff_target_time ("stratum-vdiff-target-time", "Stratum server: target time per share (i.e. try to get one share per this many seconds)", VDIFF_TARGET_TIME_DEFAULT ); + const command_line::arg_descriptor arg_stratum_vdiff_retarget_time ("stratum-vdiff-retarget-time", "Stratum server: check to see if we should retarget this often (sec.)", VDIFF_RETARGET_TIME_DEFAULT ); + const command_line::arg_descriptor arg_stratum_vdiff_retarget_shares ("stratum-vdiff-retarget-shares", "Stratum server: enforce retargeting if got this many shares", VDIFF_RETARGET_SHARES_COUNT ); + const command_line::arg_descriptor arg_stratum_vdiff_variance_percent ("stratum-vdiff-variance-percent", "Stratum server: allow average time to very this % from target without retarget", VDIFF_VARIANCE_PERCENT_DEFAULT ); + const command_line::arg_descriptor arg_stratum_always_online ( "stratum-always-online", "Stratum server consider the core being synchronized regardless of online status, useful for debugging with --offline-mode" ); //============================================================================================================================== diff --git a/src/version.h.in b/src/version.h.in index a9c7f0d9..a6d24549 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -4,10 +4,10 @@ #define BUILD_COMMIT_ID "@VERSION@" #define PROJECT_MAJOR_VERSION "1" -#define PROJECT_MINOR_VERSION "4" -#define PROJECT_REVISION "1" +#define PROJECT_MINOR_VERSION "5" +#define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 142 +#define PROJECT_VERSION_BUILD_NO 143 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" diff --git a/src/wallet/view_iface.h b/src/wallet/view_iface.h index 8c5e52c4..3243242e 100644 --- a/src/wallet/view_iface.h +++ b/src/wallet/view_iface.h @@ -600,6 +600,18 @@ public: END_KV_SERIALIZE_MAP() }; + struct current_action_status + { + uint64_t wallet_id; + std::string status; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(wallet_id) + KV_SERIALIZE(status) + END_KV_SERIALIZE_MAP() + }; + + struct wallet_sync_status_info { bool is_daemon_connected; @@ -742,9 +754,11 @@ public: struct gui_options { bool use_debug_mode; + bool disable_price_fetch; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(use_debug_mode) + KV_SERIALIZE(disable_price_fetch) END_KV_SERIALIZE_MAP() }; @@ -828,6 +842,7 @@ public: virtual bool pos_block_found(const currency::block& block_found){ return true; } virtual bool money_transfer_cancel(const transfer_event_info& wsi){ return true; } virtual bool set_options(const gui_options& opt){ return true; } + virtual bool update_tor_status(const current_action_status & opt) { return true; } }; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index cbceb80b..26778182 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -13,6 +13,7 @@ #include #include #include "include_base_utils.h" +#include "net/levin_client.h" using namespace epee; #include "string_coding.h" @@ -30,8 +31,16 @@ using namespace epee; #include "version.h" #include "common/encryption_filter.h" #include "crypto/bitcoin/sha256_helper.h" +#ifndef DISABLE_TOR + #include "common/tor_helper.h" +#endif + +#include "storages/levin_abstract_invoke2.h" + using namespace currency; + + #define MINIMUM_REQUIRED_WALLET_FREE_SPACE_BYTES (100*1024*1024) // 100 MB #undef LOG_DEFAULT_CHANNEL @@ -53,7 +62,8 @@ namespace tools m_minimum_height(WALLET_MINIMUM_HEIGHT_UNSET_CONST), m_pos_mint_packing_size(WALLET_DEFAULT_POS_MINT_PACKING_SIZE), m_current_wallet_file_size(0), - m_use_deffered_global_outputs(false) + m_use_deffered_global_outputs(false), + m_disable_tor_relay(false) { m_core_runtime_config = currency::get_default_core_runtime_config(); } @@ -394,8 +404,9 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t if (it != m_active_htlcs.end()) { transfer_details& td = m_transfers[it->second]; - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout.size() > td.m_internal_output_index, "Internal error: wrong index in m_transfers"); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type() == typeid(txout_htlc), "Internal error: wrong index in m_transfers"); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout.size() > td.m_internal_output_index, "Internal error: wrong td.m_internal_output_index: " << td.m_internal_output_index); + const boost::typeindex::type_info& ti = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type(); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(ti == typeid(txout_htlc), "Internal error: wrong type of output's target: " << ti.name()); //input spend active htlc m_transfers[it->second].m_spent_height = height; transfer_details_extra_option_htlc_info& tdeohi = get_or_add_field_to_variant_vector(td.varian_options); @@ -3275,7 +3286,7 @@ void wallet2::wti_to_csv_entry(std::ostream& ss, const wallet_public::wallet_tra ss << (wti.is_income ? "in" : "out") << ","; ss << (wti.is_service ? "[SERVICE]" : "") << (wti.is_mixing ? "[MIXINS]" : "") << (wti.is_mining ? "[MINING]" : "") << ","; ss << wti.tx_type << ","; - ss << wti.fee << ENDL; + ss << print_money(wti.fee) << ENDL; }; void wallet2::wti_to_txt_line(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index) @@ -3316,7 +3327,7 @@ void wallet2::export_transaction_history(std::ostream& ss, const std::string& fo else { //csv by default - ss << "N, Date, Amount, Comment, Address, ID, Height, Unlock timestamp, Tx size, Alias, In/Out, Flags, Type, Fee" << ENDL; + ss << "N, Date, Amount, Comment, Address, ID, Height, Unlock timestamp, Tx size, Alias, PaymentID, In/Out, Flags, Type, Fee" << ENDL; } @@ -3326,6 +3337,7 @@ void wallet2::export_transaction_history(std::ostream& ss, const std::string& fo if (currency::is_coinbase(wti.tx)) return true; } + wti.fee = currency::get_tx_fee(wti.tx); cb(ss, wti, index); return true; }); @@ -4581,22 +4593,76 @@ uint64_t wallet2::get_needed_money(uint64_t fee, const std::vectoron_tor_status_change(state_code); +} //---------------------------------------------------------------------------------------------------------------- void wallet2::send_transaction_to_network(const transaction& tx) { - COMMAND_RPC_SEND_RAW_TX::request req; - req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(tx)); - COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp; - bool r = m_core_proxy->call_COMMAND_RPC_SEND_RAW_TX(req, daemon_send_resp); - THROW_IF_TRUE_WALLET_EX(!r, error::no_connection_to_daemon, "sendrawtransaction"); - THROW_IF_TRUE_WALLET_EX(daemon_send_resp.status == API_RETURN_CODE_BUSY, error::daemon_busy, "sendrawtransaction"); - THROW_IF_TRUE_WALLET_EX(daemon_send_resp.status == API_RETURN_CODE_DISCONNECTED, error::no_connection_to_daemon, "Transfer attempt while daemon offline"); - THROW_IF_TRUE_WALLET_EX(daemon_send_resp.status != API_RETURN_CODE_OK, error::tx_rejected, tx, daemon_send_resp.status); +#ifndef DISABLE_TOR + if (!m_disable_tor_relay) + { + //TODO check that core synchronized + //epee::net_utils::levin_client2 p2p_client; + + //make few attempts + tools::levin_over_tor_client p2p_client; + p2p_client.get_transport().set_notifier(this); + bool succeseful_sent = false; + for (size_t i = 0; i != 3; i++) + { + if (!p2p_client.connect("144.76.183.143", 2121, 10000)) + { + continue;//THROW_IF_FALSE_WALLET_EX(false, error::no_connection_to_daemon, "Failed to connect to TOR node"); + } + + + currency::NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request p2p_req = AUTO_VAL_INIT(p2p_req); + currency::NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response p2p_rsp = AUTO_VAL_INIT(p2p_rsp); + p2p_req.txs.push_back(t_serializable_object_to_blob(tx)); + this->notify_state_change(WALLET_LIB_STATE_SENDING); + epee::net_utils::invoke_remote_command2(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::ID, p2p_req, p2p_rsp, p2p_client); + p2p_client.disconnect(); + if (p2p_rsp.code == API_RETURN_CODE_OK) + { + this->notify_state_change(WALLET_LIB_SENT_SUCCESS); + succeseful_sent = true; + break; + } + this->notify_state_change(WALLET_LIB_SEND_FAILED); + //checking if transaction got relayed to other nodes and + //return; + } + if (!succeseful_sent) + { + this->notify_state_change(WALLET_LIB_SEND_FAILED); + THROW_IF_FALSE_WALLET_EX(succeseful_sent, error::no_connection_to_daemon, "Faile to build TOR stream"); + } + } + else +#endif // + { + COMMAND_RPC_SEND_RAW_TX::request req; + req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(tx)); + COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp; + bool r = m_core_proxy->call_COMMAND_RPC_SEND_RAW_TX(req, daemon_send_resp); + THROW_IF_TRUE_WALLET_EX(!r, error::no_connection_to_daemon, "sendrawtransaction"); + THROW_IF_TRUE_WALLET_EX(daemon_send_resp.status == API_RETURN_CODE_BUSY, error::daemon_busy, "sendrawtransaction"); + THROW_IF_TRUE_WALLET_EX(daemon_send_resp.status == API_RETURN_CODE_DISCONNECTED, error::no_connection_to_daemon, "Transfer attempt while daemon offline"); + THROW_IF_TRUE_WALLET_EX(daemon_send_resp.status != API_RETURN_CODE_OK, error::tx_rejected, tx, daemon_send_resp.status); + + WLT_LOG_L2("transaction " << get_transaction_hash(tx) << " generated ok and sent to daemon:" << ENDL << currency::obj_to_json_str(tx)); + } - WLT_LOG_L2("transaction " << get_transaction_hash(tx) << " generated ok and sent to daemon:" << ENDL << currency::obj_to_json_str(tx)); } - +//---------------------------------------------------------------------------------------------------------------- void wallet2::add_sent_tx_detailed_info(const transaction& tx, const std::vector& destinations, const std::vector& selected_transfers) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index fdf2afad..e57ff79a 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -41,6 +41,7 @@ #include "currency_core/bc_escrow_service.h" #include "common/pod_array_file_container.h" #include "wallet_chain_shortener.h" +#include "tor-connect/torlib/tor_lib_iface.h" #define WALLET_DEFAULT_TX_SPENDABLE_AGE 10 @@ -121,6 +122,7 @@ namespace tools virtual void on_sync_progress(const uint64_t& /*percents*/) {} virtual void on_transfer_canceled(const wallet_public::wallet_transfer_info& wti) {} virtual void on_message(message_severity /*severity*/, const std::string& /*m*/) {} + virtual void on_tor_status_change(const std::string& state) {} }; struct tx_dust_policy @@ -338,7 +340,7 @@ namespace tools // END_SERIALIZE() // }; - class wallet2 + class wallet2: public tools::tor::t_transport_state_notifier { wallet2(const wallet2&) = delete; public: @@ -861,6 +863,7 @@ namespace tools uint64_t get_wallet_file_size()const; void set_use_deffered_global_outputs(bool use); construct_tx_param get_default_construct_tx_param_inital(); + void set_disable_tor_relay(bool disable); void export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions = true); @@ -876,6 +879,11 @@ namespace tools bool check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& origin, crypto::hash& redeem_tx_id); private: + // -------- t_transport_state_notifier ------------------------------------------------ + virtual void notify_state_change(const std::string& state_code, const std::string& details = std::string()); + // ------------------------------------------------------------------------------------ + + void add_transfers_to_expiration_list(const std::vector& selected_transfers, uint64_t expiration, uint64_t change_amount, const crypto::hash& related_tx_id); void remove_transfer_from_expiration_list(uint64_t transfer_index); void load_keys(const std::string& keys_file_name, const std::string& password, uint64_t file_signature, keys_file_data& kf_data); @@ -1060,6 +1068,7 @@ private: mutable uint64_t m_current_wallet_file_size; bool m_use_deffered_global_outputs; + bool m_disable_tor_relay; //this needed to access wallets state in coretests, for creating abnormal blocks and tranmsactions friend class test_generator; diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index c2636d70..46c93f30 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -16,6 +16,12 @@ // TODO: get rid of all these types, leave only wallet_error with a string message and string/enum error designator + +#define WALLET_LIB_STATE_SENDING "STATE_SENDING" +#define WALLET_LIB_SENT_SUCCESS "STATE_SENT_SUCCESS" +#define WALLET_LIB_SEND_FAILED "STATE_SEND_FAILED" + + namespace tools { namespace error @@ -64,7 +70,10 @@ namespace tools std::string to_string() const { std::ostringstream ss; - ss << m_loc << ':' << typeid(*this).name() << "[" << m_error_code << "]: " << Base::what(); + ss << m_loc << ':' << typeid(*this).name(); + if (!m_error_code.empty()) + ss << "[" << m_error_code << "]"; + ss << ": " << Base::what(); return ss.str(); } diff --git a/src/wallet/wallet_id_adapter.h b/src/wallet/wallet_id_adapter.h index b36b5bac..4a4b0a8c 100644 --- a/src/wallet/wallet_id_adapter.h +++ b/src/wallet/wallet_id_adapter.h @@ -16,6 +16,7 @@ public: virtual void on_pos_block_found(size_t wallet_id, const currency::block& /*block*/) {} virtual void on_sync_progress(size_t wallet_id, const uint64_t& /*percents*/) {} virtual void on_transfer_canceled(size_t wallet_id, const tools::wallet_public::wallet_transfer_info& wti) {} + virtual void on_tor_status_change(size_t wallet_id, const std::string& state) {} }; struct i_wallet_to_i_backend_adapter: public tools::i_wallet2_callback @@ -39,6 +40,11 @@ struct i_wallet_to_i_backend_adapter: public tools::i_wallet2_callback virtual void on_transfer_canceled(const tools::wallet_public::wallet_transfer_info& wti) { m_pbackend->on_transfer_canceled(m_wallet_id, wti); } + virtual void on_tor_status_change(const std::string& state) + { + m_pbackend->on_tor_status_change(m_wallet_id, state); + } + private: i_backend_wallet_callback* m_pbackend; size_t m_wallet_id; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index ca888e83..43d9625b 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -43,10 +43,10 @@ using namespace epee; namespace tools { //----------------------------------------------------------------------------------- - const command_line::arg_descriptor wallet_rpc_server::arg_rpc_bind_port = {"rpc-bind-port", "Starts wallet as rpc server for wallet operations, sets bind port for server", "", true}; - const command_line::arg_descriptor wallet_rpc_server::arg_rpc_bind_ip = {"rpc-bind-ip", "Specify ip to bind rpc server", "127.0.0.1"}; - const command_line::arg_descriptor wallet_rpc_server::arg_miner_text_info = { "miner-text-info", "Wallet password", "", true }; - const command_line::arg_descriptor wallet_rpc_server::arg_deaf_mode = { "deaf", "Put wallet into 'deaf' mode make it ignore any rpc commands(usable for safe PoS mining)", false, true }; + const command_line::arg_descriptor wallet_rpc_server::arg_rpc_bind_port ("rpc-bind-port", "Starts wallet as rpc server for wallet operations, sets bind port for server"); + const command_line::arg_descriptor wallet_rpc_server::arg_rpc_bind_ip ("rpc-bind-ip", "Specify ip to bind rpc server", "127.0.0.1"); + const command_line::arg_descriptor wallet_rpc_server::arg_miner_text_info ( "miner-text-info", "Wallet password"); + const command_line::arg_descriptor wallet_rpc_server::arg_deaf_mode ( "deaf", "Put wallet into 'deaf' mode make it ignore any rpc commands(usable for safe PoS mining)"); void wallet_rpc_server::init_options(boost::program_options::options_description& desc) { diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 9171a27f..54a5cb26 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -51,15 +51,16 @@ #define HTTP_PROXY_TIMEOUT 2000 #define HTTP_PROXY_ATTEMPTS_COUNT 1 -const command_line::arg_descriptor arg_alloc_win_console = { "alloc-win-console", "Allocates debug console with GUI", false }; -const command_line::arg_descriptor arg_html_folder = { "html-path", "Manually set GUI html folder path", "", true }; -const command_line::arg_descriptor arg_xcode_stub = { "-NSDocumentRevisionsDebugMode", "Substitute for xcode bug", "", true }; -const command_line::arg_descriptor arg_enable_gui_debug_mode = { "gui-debug-mode", "Enable debug options in GUI", false, true }; -const command_line::arg_descriptor arg_qt_remote_debugging_port = { "remote-debugging-port", "Specify port for Qt remote debugging", 30333, true }; -const command_line::arg_descriptor arg_remote_node = { "remote-node", "Switch GUI to work with remote node instead of local daemon", "", true }; -const command_line::arg_descriptor arg_enable_qt_logs = { "enable-qt-logs", "Forward Qt log messages into main log", false, true }; +const command_line::arg_descriptor arg_alloc_win_console ( "alloc-win-console", "Allocates debug console with GUI", false ); +const command_line::arg_descriptor arg_html_folder ( "html-path", "Manually set GUI html folder path"); +const command_line::arg_descriptor arg_xcode_stub ( "-NSDocumentRevisionsDebugMode", "Substitute for xcode bug"); +const command_line::arg_descriptor arg_enable_gui_debug_mode ( "gui-debug-mode", "Enable debug options in GUI"); +const command_line::arg_descriptor arg_qt_remote_debugging_port ( "remote-debugging-port", "Specify port for Qt remote debugging"); +const command_line::arg_descriptor arg_remote_node ( "remote-node", "Switch GUI to work with remote node instead of local daemon"); +const command_line::arg_descriptor arg_enable_qt_logs ( "enable-qt-logs", "Forward Qt log messages into main log"); const command_line::arg_descriptor arg_disable_logs_init("disable-logs-init", "Disable log initialization in GUI"); -const command_line::arg_descriptor arg_qt_dev_tools = { "qt-dev-tools", "Enable main web page inspection with Chromium DevTools, [,scale], e.g. \"horizontal,1.3\"", "", false }; +const command_line::arg_descriptor arg_qt_dev_tools ( "qt-dev-tools", "Enable main web page inspection with Chromium DevTools, [,scale], e.g. \"horizontal,1.3\"", ""); +const command_line::arg_descriptor arg_disable_price_fetch("gui-disable-price-fetch", "Disable price fetching in UI(for privacy matter)"); wallets_manager::wallets_manager():m_pview(&m_view_stub), m_stop_singal_sent(false), @@ -81,7 +82,8 @@ wallets_manager::wallets_manager():m_pview(&m_view_stub), m_is_pos_allowed(false), m_qt_logs_enbaled(false), m_dont_save_wallet_at_stop(false), - m_use_deffered_global_outputs(false) + m_use_deffered_global_outputs(false), + m_use_tor(true) { #ifndef MOBILE_WALLET_BUILD m_offers_service.set_disabled(true); @@ -162,17 +164,17 @@ bool wallets_manager::init_command_line(int argc, char* argv[], std::string& fai command_line::add_arg(desc_cmd_only, command_line::arg_version); command_line::add_arg(desc_cmd_only, command_line::arg_os_version); // tools::get_default_data_dir() can't be called during static initialization - command_line::add_arg(desc_cmd_only, command_line::arg_data_dir, tools::get_default_data_dir()); + command_line::add_arg(desc_cmd_sett, command_line::arg_data_dir, tools::get_default_data_dir()); command_line::add_arg(desc_cmd_only, command_line::arg_stop_after_height); command_line::add_arg(desc_cmd_only, command_line::arg_config_file); command_line::add_arg(desc_cmd_sett, command_line::arg_log_dir); command_line::add_arg(desc_cmd_sett, command_line::arg_log_level); command_line::add_arg(desc_cmd_sett, command_line::arg_console); - command_line::add_arg(desc_cmd_sett, command_line::arg_show_details); + command_line::add_arg(desc_cmd_only, command_line::arg_show_details); command_line::add_arg(desc_cmd_sett, arg_alloc_win_console); command_line::add_arg(desc_cmd_sett, arg_html_folder); - command_line::add_arg(desc_cmd_sett, arg_xcode_stub); + command_line::add_arg(desc_cmd_only, arg_xcode_stub); command_line::add_arg(desc_cmd_sett, arg_enable_gui_debug_mode); command_line::add_arg(desc_cmd_sett, arg_qt_remote_debugging_port); command_line::add_arg(desc_cmd_sett, arg_remote_node); @@ -183,8 +185,10 @@ bool wallets_manager::init_command_line(int argc, char* argv[], std::string& fai command_line::add_arg(desc_cmd_sett, command_line::arg_force_predownload); command_line::add_arg(desc_cmd_sett, command_line::arg_validate_predownload); command_line::add_arg(desc_cmd_sett, command_line::arg_predownload_link); - command_line::add_arg(desc_cmd_sett, command_line::arg_deeplink); + command_line::add_arg(desc_cmd_only, command_line::arg_deeplink); command_line::add_arg(desc_cmd_sett, command_line::arg_disable_ntp); + command_line::add_arg(desc_cmd_sett, arg_disable_price_fetch); + #ifndef MOBILE_WALLET_BUILD @@ -298,10 +302,15 @@ bool wallets_manager::init(view::i_view* pview_handler) { log_space::log_singletone::get_set_log_detalisation_level(true, command_line::get_arg(m_vm, command_line::arg_log_level)); } - if (command_line::has_arg(m_vm, arg_enable_gui_debug_mode)) + if (command_line::has_arg(m_vm, arg_enable_gui_debug_mode) && command_line::get_arg(m_vm, arg_enable_gui_debug_mode)) { m_ui_opt.use_debug_mode = true; } + if (command_line::has_arg(m_vm, arg_disable_price_fetch) && command_line::get_arg(m_vm, arg_disable_price_fetch)) + { + m_ui_opt.disable_price_fetch = true; + } + //set up logging options std::string log_dir; @@ -791,6 +800,8 @@ void wallets_manager::init_wallet_entry(wallet_vs_options& wo, uint64_t id) m_wallet_log_prefixes.resize(id + 1); m_wallet_log_prefixes[id] = std::string("[") + epee::string_tools::num_to_string_fast(id) + ":" + wo.w->get()->get_account().get_public_address_str().substr(0, 6) + "] "; } + + wo.w->get()->set_disable_tor_relay(!m_use_tor); } @@ -1842,6 +1853,17 @@ void wallets_manager::on_pos_block_found(size_t wallet_id, const currency::block { m_pview->pos_block_found(b); } +bool wallets_manager::set_use_tor(bool use_tor) +{ + m_use_tor = use_tor; + SHARED_CRITICAL_REGION_LOCAL(m_wallets_lock); + for (auto& w : m_wallets) + { + w.second.w->get()->set_disable_tor_relay(!m_use_tor); + } + return true; +} + void wallets_manager::on_sync_progress(size_t wallet_id, const uint64_t& percents) { // do not lock m_wallets_lock down the callstack! It will lead to a deadlock, because wallet locked_object is aready locked @@ -1871,6 +1893,13 @@ void wallets_manager::on_transfer_canceled(size_t wallet_id, const tools::wallet } m_pview->money_transfer_cancel(tei); } + +void wallets_manager::on_tor_status_change(size_t wallet_id, const std::string& state) +{ + view::current_action_status tsu = { wallet_id , state }; + m_pview->update_tor_status(tsu); +} + void wallets_manager::wallet_vs_options::worker_func() { LOG_PRINT_GREEN("[WALLET_HANDLER] Wallet handler thread started, addr: " << w->get()->get_account().get_public_address_str(), LOG_LEVEL_0); diff --git a/src/wallet/wallets_manager.h b/src/wallet/wallets_manager.h index ac64041c..77656785 100644 --- a/src/wallet/wallets_manager.h +++ b/src/wallet/wallets_manager.h @@ -163,7 +163,7 @@ public: bool is_qt_logs_enabled() const { return m_qt_logs_enbaled; } std::string get_qt_dev_tools_option() const { return m_qt_dev_tools; } void set_use_deffered_global_outputs(bool use) { m_use_deffered_global_outputs = use; } - + bool set_use_tor(bool use_tor); private: void main_worker(const po::variables_map& vm); bool init_local_daemon(); @@ -187,6 +187,8 @@ private: virtual void on_pos_block_found(size_t wallet_id, const currency::block& /*block*/); virtual void on_sync_progress(size_t wallet_id, const uint64_t& /*percents*/); virtual void on_transfer_canceled(size_t wallet_id, const tools::wallet_public::wallet_transfer_info& wti); + virtual void on_tor_status_change(size_t wallet_id, const std::string& state); + std::thread m_main_worker_thread; @@ -224,6 +226,7 @@ private: bool m_qt_logs_enbaled; std::string m_qt_dev_tools; std::atomic m_is_pos_allowed; + std::atomic m_use_tor; std::map m_wallets; diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 01aa5f8b..4ec33355 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -927,6 +927,7 @@ bool test_generator::init_test_wallet(const currency::account_base& account, con w->assign_account(account); w->set_genesis(genesis_hash); w->set_core_proxy(m_wallet_test_core_proxy); + w->set_disable_tor_relay(true); result = w; return true; diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 7cbf4822..e6b9fb02 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -997,10 +997,10 @@ void append_vector_by_another_vector(U& dst, const V& src) #define REGISTER_CALLBACK(CB_NAME, CLBACK) \ - register_callback(CB_NAME, boost::bind(&CLBACK, this, _1, _2, _3)); + register_callback(CB_NAME, boost::bind(&CLBACK, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3)) #define REGISTER_CALLBACK_METHOD(CLASS, METHOD) \ - register_callback(#METHOD, boost::bind(&CLASS::METHOD, this, _1, _2, _3)); + register_callback(#METHOD, boost::bind(&CLASS::METHOD, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3)) #define MAKE_GENESIS_BLOCK(VEC_EVENTS, BLK_NAME, MINER_ACC, TS) \ test_generator generator; \ diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 3e9cbc80..d09d1558 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -21,13 +21,13 @@ namespace po = boost::program_options; namespace { - const command_line::arg_descriptor arg_test_data_path = {"test-data-path", "", ""}; - const command_line::arg_descriptor arg_generate_test_data = {"generate-test-data", ""}; - const command_line::arg_descriptor arg_play_test_data = {"play-test-data", ""}; - const command_line::arg_descriptor arg_generate_and_play_test_data = {"generate-and-play-test-data", ""}; - const command_line::arg_descriptor arg_test_transactions = {"test-transactions", ""}; - const command_line::arg_descriptor arg_run_single_test = {"run-single-test", "" }; - const command_line::arg_descriptor arg_enable_debug_asserts = {"enable-debug-asserts", "" }; + const command_line::arg_descriptor arg_test_data_path ("test-data-path", "", ""); + const command_line::arg_descriptor arg_generate_test_data ("generate-test-data", ""); + const command_line::arg_descriptor arg_play_test_data ("play-test-data", ""); + const command_line::arg_descriptor arg_generate_and_play_test_data ("generate-and-play-test-data", ""); + const command_line::arg_descriptor arg_test_transactions ("test-transactions", ""); + const command_line::arg_descriptor arg_run_single_test ("run-single-test", "" ); + const command_line::arg_descriptor arg_enable_debug_asserts ("enable-debug-asserts", "" ); boost::program_options::variables_map g_vm; } @@ -106,7 +106,7 @@ bool generate_and_play(const char* const genclass_name) std::vector events; bool generated = false; bool result = true; - std::cout << concolor::bright_white << "#TEST# " << genclass_name << concolor::normal << std::endl; + std::cout << ENDL << concolor::bright_white << "#TEST# " << genclass_name << concolor::normal << ENDL << ENDL; LOG_PRINT2("get_object_blobsize.log", "#TEST# " << genclass_name, LOG_LEVEL_3); if (!clean_data_directory()) @@ -667,6 +667,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_options, arg_enable_debug_asserts); command_line::add_arg(desc_options, command_line::arg_data_dir, std::string(".")); command_line::add_arg(desc_options, command_line::arg_stop_after_height); + command_line::add_arg(desc_options, command_line::arg_disable_ntp); currency::core::init_options(desc_options); tools::db::db_backend_selector::init_options(desc_options); diff --git a/tests/core_tests/hard_fork_2.cpp b/tests/core_tests/hard_fork_2.cpp index fcff78a2..28fd1151 100644 --- a/tests/core_tests/hard_fork_2.cpp +++ b/tests/core_tests/hard_fork_2.cpp @@ -922,6 +922,7 @@ bool hard_fork_2_awo_wallets_basic_test::c1(currency::core& c, size bob_wlt_awo->load(bob_wo_filename, ""); bob_wlt_awo->set_core_runtime_config(c.get_blockchain_storage().get_core_runtime_config()); bob_wlt_awo->set_core_proxy(m_core_proxy); + bob_wlt_awo->set_disable_tor_relay(true); CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt, MK_TEST_COINS(110), false, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1 + WALLET_DEFAULT_TX_SPENDABLE_AGE), false, ""); CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt, 0, false, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1 + WALLET_DEFAULT_TX_SPENDABLE_AGE), false, ""); @@ -1054,6 +1055,7 @@ bool hard_fork_2_awo_wallets_basic_test::c1(currency::core& c, size bob_wlt_awo_restored->restore(bob_wo_restored_filename, "", bob_tracking_seed, true, ""); bob_wlt_awo_restored->set_core_runtime_config(c.get_blockchain_storage().get_core_runtime_config()); bob_wlt_awo_restored->set_core_proxy(m_core_proxy); + bob_wlt_awo_restored->set_disable_tor_relay(true); CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob_awo_restored", bob_wlt_awo_restored, MK_TEST_COINS(3), false), false, ""); @@ -1092,6 +1094,7 @@ bool hard_fork_2_awo_wallets_basic_test::c1(currency::core& c, size bob_wlt_non_auditable->restore(bob_non_auditable_filename, "", bob_seed, false, ""); bob_wlt_non_auditable->set_core_runtime_config(c.get_blockchain_storage().get_core_runtime_config()); bob_wlt_non_auditable->set_core_proxy(m_core_proxy); + bob_wlt_non_auditable->set_disable_tor_relay(true); // the balance for non-auditable wallet should be greather by mix_attr!=1 output (7 test coins + 1 left from prev step) CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob_non_auditable", bob_wlt_non_auditable, MK_TEST_COINS(8), false), false, ""); diff --git a/tests/core_tests/random_helper.cpp b/tests/core_tests/random_helper.cpp index eac32896..724d9108 100644 --- a/tests/core_tests/random_helper.cpp +++ b/tests/core_tests/random_helper.cpp @@ -6,52 +6,6 @@ #include "chaingen.h" #include "random_helper.h" -random_state_test_restorer::random_state_test_restorer() -{ - crypto::random_prng_get_state(&m_state, sizeof m_state); -} - -random_state_test_restorer::~random_state_test_restorer() -{ - crypto::random_prng_set_state(&m_state, sizeof m_state); -} - -void random_state_test_restorer::reset_random(uint64_t seed /* = 0 */) -{ - crypto::random_prng_initialize_with_seed(seed); -} - -std::string get_random_text(size_t len) -{ - static const char text_chars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "~!@#$%^&*()-=_+\\/?,.<>|{}[]`';:\" "; - static const uint8_t text_chars_size = sizeof text_chars - 1; // to avoid '\0' - std::string result; - - if (len < 1) - return result; - - result.resize(len); - char* result_buf = &result[0]; - uint8_t* rnd_indices = new uint8_t[len]; - crypto::generate_random_bytes(len, rnd_indices); - - size_t n = len / 4, i; - for (i = 0; i < n; ++i) - { - result_buf[4 * i + 0] = text_chars[rnd_indices[4 * i + 0] % text_chars_size]; - result_buf[4 * i + 1] = text_chars[rnd_indices[4 * i + 1] % text_chars_size]; - result_buf[4 * i + 2] = text_chars[rnd_indices[4 * i + 2] % text_chars_size]; - result_buf[4 * i + 3] = text_chars[rnd_indices[4 * i + 3] % text_chars_size]; - } - for (size_t j = i * 4; j < len; ++j) - { - result_buf[j] = text_chars[rnd_indices[j] % text_chars_size]; - } - - delete[] rnd_indices; - return result; -} - //------------------------------------------------------------------------------ bool random_state_manupulation_test() diff --git a/tests/core_tests/random_helper.h b/tests/core_tests/random_helper.h index c9826665..360b326d 100644 --- a/tests/core_tests/random_helper.h +++ b/tests/core_tests/random_helper.h @@ -13,17 +13,56 @@ // Remebers random state at ctor, restores it at dtor struct random_state_test_restorer { - random_state_test_restorer(); - ~random_state_test_restorer(); - static void reset_random(uint64_t seed = 0); - + random_state_test_restorer() + { + crypto::random_prng_get_state(&m_state, sizeof m_state); + } + ~random_state_test_restorer() + { + crypto::random_prng_set_state(&m_state, sizeof m_state); + } + static void reset_random(uint64_t seed = 0) + { + crypto::random_prng_initialize_with_seed(seed); + } private: uint8_t m_state[RANDOM_STATE_SIZE]; }; #endif // #ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES -std::string get_random_text(size_t len); +inline std::string get_random_text(size_t len) +{ + { + static const char text_chars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "~!@#$%^&*()-=_+\\/?,.<>|{}[]`';:\" "; + static const uint8_t text_chars_size = sizeof text_chars - 1; // to avoid '\0' + std::string result; + + if (len < 1) + return result; + + result.resize(len); + char* result_buf = &result[0]; + uint8_t* rnd_indices = new uint8_t[len]; + crypto::generate_random_bytes(len, rnd_indices); + + size_t n = len / 4, i; + for (i = 0; i < n; ++i) + { + result_buf[4 * i + 0] = text_chars[rnd_indices[4 * i + 0] % text_chars_size]; + result_buf[4 * i + 1] = text_chars[rnd_indices[4 * i + 1] % text_chars_size]; + result_buf[4 * i + 2] = text_chars[rnd_indices[4 * i + 2] % text_chars_size]; + result_buf[4 * i + 3] = text_chars[rnd_indices[4 * i + 3] % text_chars_size]; + } + for (size_t j = i * 4; j < len; ++j) + { + result_buf[j] = text_chars[rnd_indices[j] % text_chars_size]; + } + + delete[] rnd_indices; + return result; + } +} bool random_state_manupulation_test(); bool random_evenness_test(); diff --git a/tests/core_tests/test_core_proxy.h b/tests/core_tests/test_core_proxy.h index 83694ecd..29898012 100644 --- a/tests/core_tests/test_core_proxy.h +++ b/tests/core_tests/test_core_proxy.h @@ -51,7 +51,7 @@ public: //----------------- i_currency_protocol --------------------------------------- virtual bool relay_block(currency::NOTIFY_NEW_BLOCK::request& /*arg*/, currency::currency_connection_context& /*exclude_context*/) override { return false; } - virtual bool relay_transactions(currency::NOTIFY_NEW_TRANSACTIONS::request& arg, currency::currency_connection_context& /*exclude_context*/) override + virtual bool relay_transactions(currency::NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency::currency_connection_context& /*exclude_context*/) override { if (m_core_listener) { diff --git a/tests/core_tests/wallet_tests_basic.cpp b/tests/core_tests/wallet_tests_basic.cpp index fe4ec260..a3d40912 100644 --- a/tests/core_tests/wallet_tests_basic.cpp +++ b/tests/core_tests/wallet_tests_basic.cpp @@ -83,6 +83,7 @@ std::shared_ptr wallet_test::init_playtime_test_wallet(const std w->assign_account(acc); w->set_genesis(genesis_hash); w->set_core_proxy(m_core_proxy); + w->set_disable_tor_relay(true); return w; } diff --git a/tests/functional_tests/crypto_tests.cpp b/tests/functional_tests/crypto_tests.cpp index 83c94b8b..e52b7033 100644 --- a/tests/functional_tests/crypto_tests.cpp +++ b/tests/functional_tests/crypto_tests.cpp @@ -15,6 +15,7 @@ #include "crypto/crypto-sugar.h" #include "crypto/range_proofs.h" +#include "../core_tests/random_helper.h" using namespace crypto; @@ -473,6 +474,7 @@ uint64_t hash_64(const void* data, size_t size) #define ASSERT_TRUE(expr) CHECK_AND_ASSERT_MES(expr, false, "This is not true: " #expr) #define ASSERT_FALSE(expr) CHECK_AND_ASSERT_MES((expr) == false, false, "This is not false: " #expr) #define ASSERT_EQ(a, b) CHECK_AND_ASSERT_MES(a == b, false, #a " != " #b "\n " << a << " != " << b) +#define ASSERT_NEQ(a, b) CHECK_AND_ASSERT_MES(a != b, false, #a " == " #b "\n " << a) typedef bool(*bool_func_ptr_t)(); static std::vector> g_tests; @@ -487,6 +489,7 @@ struct test_keeper_t //////////////////////////////////////////////////////////////////////////////// #include "L2S.h" +#include "crypto_tests_range_proofs.h" //////////////////////////////////////////////////////////////////////////////// @@ -1803,6 +1806,68 @@ TEST(crypto, point_is_zero) } +TEST(crypto, sc_get_bit) +{ + static_assert(sizeof(scalar_t) * 8 == 256, "size missmatch"); + + scalar_t v = 0; // all bits are 0 + for (size_t n = 0; n < 256; ++n) + { + ASSERT_EQ(v.get_bit(static_cast(n)), false); + } + + v = c_scalar_256m1; // all bits are 1 + for (size_t n = 0; n < 256; ++n) + { + ASSERT_EQ(v.get_bit(static_cast(n)), true); + } + + // bits out of the [0; 255] range supposed to be always 0 + for (size_t n = 256; n < 2048; ++n) + { + ASSERT_EQ(v.get_bit(static_cast(n)), false); + } + + // check random value + const scalar_t x = scalar_t::random(); + for (size_t n = 0; n < 64; ++n) + ASSERT_EQ(x.get_bit(static_cast(n)), ((x.m_u64[0] & (1ull << (n - 0))) != 0)); + for (size_t n = 64; n < 128; ++n) + ASSERT_EQ(x.get_bit(static_cast(n)), ((x.m_u64[1] & (1ull << (n - 64))) != 0)); + for (size_t n = 128; n < 192; ++n) + ASSERT_EQ(x.get_bit(static_cast(n)), ((x.m_u64[2] & (1ull << (n - 128))) != 0)); + for (size_t n = 192; n < 256; ++n) + ASSERT_EQ(x.get_bit(static_cast(n)), ((x.m_u64[3] & (1ull << (n - 192))) != 0)); + + return true; +} + + +TEST(crypto, sc_set_bit_clear_bit) +{ + static_assert(sizeof(scalar_t) * 8 == 256, "size missmatch"); + + // check random value + const scalar_t x = scalar_t::random(); + scalar_t y = scalar_t::random(); + ASSERT_NEQ(x, y); + + uint8_t i = 0; + do + { + if (x.get_bit(i)) + y.set_bit(i); + else + y.clear_bit(i); + } while(++i != 0); + + ASSERT_EQ(x, y); + + return true; +} + + + // // test's runner // @@ -1844,7 +1909,7 @@ int crypto_tests(const std::string& cmd_line_param) epee::log_space::log_singletone::get_default_log_folder().c_str()); - + size_t filtered_tests_count = 0; std::vector failed_tests; for (size_t i = 0; i < g_tests.size(); ++i) { @@ -1853,6 +1918,8 @@ int crypto_tests(const std::string& cmd_line_param) if (!wildcard_match(cmd_line_param.c_str(), test.first.c_str())) continue; + ++filtered_tests_count; + LOG_PRINT(" " << std::setw(40) << std::left << test.first << " >", LOG_LEVEL_0); TIME_MEASURE_START(runtime); bool r = false; @@ -1882,10 +1949,16 @@ int crypto_tests(const std::string& cmd_line_param) } } + if (filtered_tests_count == 0) + { + LOG_PRINT_YELLOW(ENDL << ENDL << "No tests were selected, check the filter mask", LOG_LEVEL_0); + return 1; + } + if (failed_tests.empty()) { LOG_PRINT_GREEN(ENDL, LOG_LEVEL_0); - LOG_PRINT_GREEN("All tests passed okay", LOG_LEVEL_0); + LOG_PRINT_GREEN(filtered_tests_count << " tests passed okay", LOG_LEVEL_0); return 0; } diff --git a/tests/functional_tests/crypto_tests_range_proofs.h b/tests/functional_tests/crypto_tests_range_proofs.h new file mode 100644 index 00000000..3ccdc7f4 --- /dev/null +++ b/tests/functional_tests/crypto_tests_range_proofs.h @@ -0,0 +1,261 @@ +// Copyright (c) 2021 Zano Project (https://zano.org/) +// Copyright (c) 2021 sowle (val@zano.org, crypto.sowle@gmail.com) +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#pragma once + +// calc weighted inner pruduct of av and bv w.r.t. Vandermonde vector (y, y^2, y^3, ..., y^n) +// = (<> -- standard inner product, o - componen-wise) +// s.a. BP+ paper, pages 3-4 +bool wip_vandermonde(const scalar_vec_t& av, const scalar_vec_t& bv, const scalar_t& y, scalar_t& result) +{ + result = 0; + size_t n = av.size(); + if (n != bv.size()) + return false; + + scalar_t y_powered = 1; + for (size_t i = 0; i < n; ++i) + { + y_powered *= y; + result.assign_muladd(av[i] * bv[i], y_powered, result); // result.a += av[i] * bv[i] * y_powered; + } + + return true; +} + + +static_assert(constexpr_floor_log2(0) == 0, ""); +static_assert(constexpr_floor_log2(1) == 0, ""); +static_assert(constexpr_floor_log2(2) == 1, ""); +static_assert(constexpr_floor_log2(3) == 1, ""); +static_assert(constexpr_floor_log2(4) == 2, ""); +static_assert(constexpr_floor_log2(5) == 2, ""); +static_assert(constexpr_floor_log2(64) == 6, ""); +static_assert(constexpr_floor_log2(100) == 6, ""); +static_assert(constexpr_floor_log2(100000000) == 26, ""); +static_assert(constexpr_floor_log2(0x7fffffffffffffff) == 62, ""); +static_assert(constexpr_floor_log2(SIZE_MAX) == 63, ""); + +static_assert(constexpr_ceil_log2(0) == 0, ""); +static_assert(constexpr_ceil_log2(1) == 0, ""); +static_assert(constexpr_ceil_log2(2) == 1, ""); +static_assert(constexpr_ceil_log2(3) == 2, ""); +static_assert(constexpr_ceil_log2(4) == 2, ""); +static_assert(constexpr_ceil_log2(5) == 3, ""); +static_assert(constexpr_ceil_log2(64) == 6, ""); +static_assert(constexpr_ceil_log2(100) == 7, ""); +static_assert(constexpr_ceil_log2(100000000) == 27, ""); +static_assert(constexpr_ceil_log2(0x7fffffffffffffff) == 63, ""); +static_assert(constexpr_ceil_log2(SIZE_MAX) == 64, ""); + + +TEST(bpp, basics) +{ + /* + srand(0); + for (size_t i = 0; i < 10; ++i) + std::cout << scalar_t::random().to_string_as_secret_key() << ENDL; + */ + + point_t H = hash_helper_t::hp(c_point_G); + ASSERT_EQ(H, c_point_H); + std::string h2_hash_str("h2_generator"); + point_t H2 = hash_helper_t::hp(h2_hash_str.c_str(), h2_hash_str.size()); + ASSERT_EQ(H2, c_point_H2); + LOG_PRINT_L0("c_point_0 = " << c_point_0 << " = { " << c_point_0.to_hex_comma_separated_uint64_str() << " }"); + LOG_PRINT_L0("Zano G = " << c_point_G << " = { " << c_point_G.to_hex_comma_separated_bytes_str() << " }"); + LOG_PRINT_L0("Zano H = " << H << " = { " << H.to_hex_comma_separated_uint64_str() << " }"); + LOG_PRINT_L0("Zano H2 = " << H2 << " = { " << H2.to_hex_comma_separated_uint64_str() << " }"); + + scalar_vec_t values = { 5 }; + scalar_vec_t masks = { 0 }; + bpp_signature bpp_sig; + std::vector commitments; + uint8_t err = 0; + + bool r = bpp_gen>(values, masks, bpp_sig, commitments, &err); + + ASSERT_TRUE(r); + + return true; +} + + +TEST(bpp, two) +{ + std::vector signatures_vector; + signatures_vector.reserve(10); + std::vector> commitments_vector; + commitments_vector.reserve(10); + + std::vector sigs; + uint8_t err = 0; + bool r = false; + + { + signatures_vector.resize(signatures_vector.size() + 1); + bpp_signature &bpp_sig = signatures_vector.back(); + commitments_vector.resize(commitments_vector.size() + 1); + std::vector& commitments = commitments_vector.back(); + + scalar_vec_t values = { 5 }; + scalar_vec_t masks = { scalar_t(77 + 256 * 77) }; + + r = bpp_gen>(values, masks, bpp_sig, commitments, &err); + ASSERT_TRUE(r); + + sigs.emplace_back(bpp_sig, commitments); + } + + { + signatures_vector.resize(signatures_vector.size() + 1); + bpp_signature &bpp_sig = signatures_vector.back(); + commitments_vector.resize(commitments_vector.size() + 1); + std::vector& commitments = commitments_vector.back(); + + scalar_vec_t values = { 5, 700, 8 }; + scalar_vec_t masks = { scalar_t(77 + 256 * 77), scalar_t(255), scalar_t(17) }; + + r = bpp_gen>(values, masks, bpp_sig, commitments, &err); + ASSERT_TRUE(r); + + sigs.emplace_back(bpp_sig, commitments); + } + + r = bpp_verify>(sigs, &err); + ASSERT_TRUE(r); + + + return true; +} + + +TEST(bpp, power_256) +{ + // make sure the BPP implementation supports values up to 2^256 (Zarcanum needs 2^170 since b_a < z * 2^64, where z = 2^106, s.a. Zarcanum preprint, page 21) + std::vector signatures_vector; + signatures_vector.reserve(10); + std::vector> commitments_vector; + commitments_vector.reserve(10); + + std::vector sig_ñommit_refs; + uint8_t err = 0; + bool r = false; + + { + signatures_vector.resize(signatures_vector.size() + 1); + bpp_signature &bpp_sig = signatures_vector.back(); + commitments_vector.resize(commitments_vector.size() + 1); + std::vector& commitments = commitments_vector.back(); + + scalar_vec_t values = { 5 }; + scalar_vec_t masks = { scalar_t(77 + 256 * 77) }; + + r = bpp_gen>(values, masks, bpp_sig, commitments, &err); + ASSERT_TRUE(r); + + sig_ñommit_refs.emplace_back(bpp_sig, commitments); + } + + { + signatures_vector.resize(signatures_vector.size() + 1); + bpp_signature &bpp_sig = signatures_vector.back(); + commitments_vector.resize(commitments_vector.size() + 1); + std::vector& commitments = commitments_vector.back(); + + scalar_vec_t values = { 5, 700, 8 }; + scalar_vec_t masks = { scalar_t(77 + 256 * 77), scalar_t(255), scalar_t(17) }; + + r = bpp_gen>(values, masks, bpp_sig, commitments, &err); + ASSERT_TRUE(r); + + sig_ñommit_refs.emplace_back(bpp_sig, commitments); + } + + r = bpp_verify>(sig_ñommit_refs, &err); + ASSERT_TRUE(r); + + + return true; +} + + + +// +// tests for Bulletproofs+ Extended (with double-blinded commitments) +// + + +TEST(bppe, basics) +{ + /* + srand(0); + for (size_t i = 0; i < 10; ++i) + std::cout << scalar_t::random().to_string_as_secret_key() << ENDL; + */ + + scalar_vec_t values = { 5 }; + scalar_vec_t masks = { 0 }; + scalar_vec_t masks_2 = { 0 }; + + bppe_signature bppe_sig; + std::vector commitments; + uint8_t err = 0; + + bool r = bppe_gen>(values, masks, masks_2, bppe_sig, commitments, &err); + + ASSERT_TRUE(r); + + return true; +} + +TEST(bppe, two) +{ + std::vector signatures_vector; + signatures_vector.reserve(10); + std::vector> commitments_vector; + commitments_vector.reserve(10); + + std::vector sigs; + uint8_t err = 0; + bool r = false; + + { + signatures_vector.resize(signatures_vector.size() + 1); + bppe_signature &bppe_sig = signatures_vector.back(); + commitments_vector.resize(commitments_vector.size() + 1); + std::vector& commitments = commitments_vector.back(); + + scalar_vec_t values = { 5 }; + scalar_vec_t masks = { scalar_t(77 + 256 * 77) }; + scalar_vec_t masks2 = { scalar_t(88 + 256 * 88) }; + + r = bppe_gen>(values, masks, masks2, bppe_sig, commitments, &err); + ASSERT_TRUE(r); + + sigs.emplace_back(bppe_sig, commitments); + } + + { + signatures_vector.resize(signatures_vector.size() + 1); + bppe_signature &bppe_sig = signatures_vector.back(); + commitments_vector.resize(commitments_vector.size() + 1); + std::vector& commitments = commitments_vector.back(); + + scalar_vec_t values = { 5, 700, 8 }; + scalar_vec_t masks = { scalar_t(77 + 256 * 77), scalar_t(255), scalar_t(17) }; + scalar_vec_t masks2 = { scalar_t(88 + 256 * 88), scalar_t(1), scalar_t(19) }; + + r = bppe_gen>(values, masks, masks2, bppe_sig, commitments, &err); + ASSERT_TRUE(r); + + sigs.emplace_back(bppe_sig, commitments); + } + + r = bppe_verify>(sigs, &err); + ASSERT_TRUE(r); + + + return true; +} diff --git a/tests/functional_tests/main.cpp b/tests/functional_tests/main.cpp index ed53cbe3..b275bd4a 100644 --- a/tests/functional_tests/main.cpp +++ b/tests/functional_tests/main.cpp @@ -23,40 +23,40 @@ using namespace epee; namespace po = boost::program_options; -const command_line::arg_descriptor arg_test_core_prepare_and_store = { "prepare-and-store-events-to-file", "", "", true }; -const command_line::arg_descriptor arg_test_core_load_and_replay = { "load-and-replay-events-from-file", "", "", true }; +const command_line::arg_descriptor arg_test_core_prepare_and_store ( "prepare-and-store-events-to-file", ""); +const command_line::arg_descriptor arg_test_core_load_and_replay ( "load-and-replay-events-from-file", ""); namespace { - const command_line::arg_descriptor arg_test_transactions_flow = {"test-transactions-flow", ""}; - const command_line::arg_descriptor arg_test_miniupnp = {"test-miniupnp", ""}; - const command_line::arg_descriptor arg_test_core_concurrency = {"test-core-concurrency", ""}; + const command_line::arg_descriptor arg_test_transactions_flow ("test-transactions-flow", ""); + const command_line::arg_descriptor arg_test_miniupnp ("test-miniupnp", ""); + const command_line::arg_descriptor arg_test_core_concurrency ("test-core-concurrency", ""); - const command_line::arg_descriptor arg_working_folder = {"working-folder", "", "."}; - const command_line::arg_descriptor arg_source_wallet = {"source-wallet", "", "", true}; - const command_line::arg_descriptor arg_dest_wallet = {"dest-wallet", "", "", true}; - const command_line::arg_descriptor arg_source_wallet_pass = {"source-wallet-pass", "", "", true}; - const command_line::arg_descriptor arg_dest_wallet_pass = {"dest-wallet-pass", "", "", true}; + const command_line::arg_descriptor arg_working_folder ("working-folder", "", "."); + const command_line::arg_descriptor arg_source_wallet ("source-wallet", ""); + const command_line::arg_descriptor arg_dest_wallet ("dest-wallet", ""); + const command_line::arg_descriptor arg_source_wallet_pass ("source-wallet-pass", ""); + const command_line::arg_descriptor arg_dest_wallet_pass ("dest-wallet-pass", ""); - const command_line::arg_descriptor arg_daemon_addr_a = {"daemon-addr-a", "", "127.0.0.1:8080"}; - const command_line::arg_descriptor arg_daemon_addr_b = {"daemon-addr-b", "", "127.0.0.1:8082"}; + const command_line::arg_descriptor arg_daemon_addr_a ("daemon-addr-a", "", "127.0.0.1:8080"); + const command_line::arg_descriptor arg_daemon_addr_b ("daemon-addr-b", "", "127.0.0.1:8082"); - const command_line::arg_descriptor arg_transfer_amount = {"transfer-amount", "", 60000000000000}; - const command_line::arg_descriptor arg_mix_in_factor = {"mix-in-factor", "", 10}; - const command_line::arg_descriptor arg_tx_count = {"tx-count", "", 100}; - const command_line::arg_descriptor arg_tx_per_second = {"tx-per-second", "", 20}; - const command_line::arg_descriptor arg_test_repeat_count = {"test-repeat-count", "", 1}; - const command_line::arg_descriptor arg_action = {"action", "", 0 }; - const command_line::arg_descriptor arg_max_tx_in_pool = { "max-tx-in-pool", "", 10000 }; - const command_line::arg_descriptor arg_data_dir = {"data-dir", "Specify data directory", "."}; - const command_line::arg_descriptor arg_wthreads = {"wthreads", "number of writing threads to run", 1}; - const command_line::arg_descriptor arg_rthreads = {"rthreads", "number of reading threads to run", 1}; - const command_line::arg_descriptor arg_blocks = {"blocks", "number of blocks to generate", 250}; - const command_line::arg_descriptor arg_generate_test_genesis_json = { "generate-test-genesis-json", "generates test genesis json, specify amount of accounts", 0, true }; - const command_line::arg_descriptor arg_deadlock_guard = { "test-deadlock-guard", "Do deadlock guard test", false, true }; - const command_line::arg_descriptor arg_difficulty_analysis = { "difficulty-analysis", "Do difficulty analysis", "", true }; - const command_line::arg_descriptor arg_test_plain_wallet = { "test-plainwallet", "Do testing of plain wallet interface", false, true }; - const command_line::arg_descriptor arg_crypto_tests = { "crypto-tests", "Run experimental crypto tests", "", true }; + const command_line::arg_descriptor arg_transfer_amount ("transfer-amount", "", 60000000000000); + const command_line::arg_descriptor arg_mix_in_factor ("mix-in-factor", "", 10); + const command_line::arg_descriptor arg_tx_count ("tx-count", "", 100); + const command_line::arg_descriptor arg_tx_per_second ("tx-per-second", "", 20); + const command_line::arg_descriptor arg_test_repeat_count ("test-repeat-count", "", 1); + const command_line::arg_descriptor arg_action ("action", "", 0 ); + const command_line::arg_descriptor arg_max_tx_in_pool ( "max-tx-in-pool", "", 10000 ); + const command_line::arg_descriptor arg_data_dir ("data-dir", "Specify data directory", "."); + const command_line::arg_descriptor arg_wthreads ("wthreads", "number of writing threads to run", 1); + const command_line::arg_descriptor arg_rthreads ("rthreads", "number of reading threads to run", 1); + const command_line::arg_descriptor arg_blocks ("blocks", "number of blocks to generate", 250); + const command_line::arg_descriptor arg_generate_test_genesis_json ( "generate-test-genesis-json", "generates test genesis json, specify amount of accounts"); + const command_line::arg_descriptor arg_deadlock_guard ( "test-deadlock-guard", "Do deadlock guard test"); + const command_line::arg_descriptor arg_difficulty_analysis ( "difficulty-analysis", "Do difficulty analysis"); + const command_line::arg_descriptor arg_test_plain_wallet ( "test-plainwallet", "Do testing of plain wallet interface"); + const command_line::arg_descriptor arg_crypto_tests ( "crypto-tests", "Run experimental crypto tests"); } @@ -66,9 +66,6 @@ int main(int argc, char* argv[]) TRY_ENTRY(); string_tools::set_module_name_and_folder(argv[0]); - uint64_t reward = 0; - currency::get_block_reward(false, 500000, 589313, 10300000000000000, reward, 11030); - //set up logging options //log_space::get_set_log_detalisation_level(true, LOG_LEVEL_1); //log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2); diff --git a/utils/build_script_linux.sh b/utils/build_script_linux.sh index 2cd431a2..fe5adbef 100755 --- a/utils/build_script_linux.sh +++ b/utils/build_script_linux.sh @@ -3,16 +3,19 @@ # Environment prerequisites: # 1) QT_PREFIX_PATH should be set to Qt libs folder # 2) BOOST_ROOT should be set to the root of Boost +# 3) OPENSSL_ROOT_DIR should be set to the root of OpenSSL # # for example, place these lines to the end of your ~/.bashrc : # # export BOOST_ROOT=/home/user/boost_1_66_0 # export QT_PREFIX_PATH=/home/user/Qt5.10.1/5.10.1/gcc_64 +# export OPENSSL_ROOT_DIR=/home/user/openssl ARCHIVE_NAME_PREFIX=zano-linux-x64- : "${BOOST_ROOT:?BOOST_ROOT should be set to the root of Boost, ex.: /home/user/boost_1_66_0}" : "${QT_PREFIX_PATH:?QT_PREFIX_PATH should be set to Qt libs folder, ex.: /home/user/Qt5.10.1/5.10.1/gcc_64}" +: "${OPENSSL_ROOT_DIR:?OPENSSL_ROOT_DIR should be set to OpenSSL root folder, ex.: /home/user/openssl}" if [ -n "$build_prefix" ]; then ARCHIVE_NAME_PREFIX=${ARCHIVE_NAME_PREFIX}${build_prefix}- @@ -40,7 +43,7 @@ echo "--------------------------------------------------" echo "Building...." rm -rf build; mkdir -p build/release; cd build/release; -cmake $testnet_def -D STATIC=true -D ARCH=x86-64 -D BUILD_GUI=TRUE -D CMAKE_PREFIX_PATH="$QT_PREFIX_PATH" -D CMAKE_BUILD_TYPE=Release ../.. +cmake $testnet_def -D STATIC=true -D ARCH=x86-64 -D BUILD_GUI=TRUE -D OPENSSL_ROOT_DIR="$OPENSSL_ROOT_DIR" -D CMAKE_PREFIX_PATH="$QT_PREFIX_PATH" -D CMAKE_BUILD_TYPE=Release ../.. if [ $? -ne 0 ]; then echo "Failed to run cmake" exit 1 diff --git a/utils/build_script_mac_osx.sh b/utils/build_script_mac_osx.sh index bb70d5fc..15acd9e3 100755 --- a/utils/build_script_mac_osx.sh +++ b/utils/build_script_mac_osx.sh @@ -8,6 +8,7 @@ curr_path=${BASH_SOURCE%/*} : "${ZANO_BOOST_LIBS_PATH:?variable not set, see also macosx_build_config.command}" : "${ZANO_BUILD_DIR:?variable not set, see also macosx_build_config.command}" : "${CMAKE_OSX_SYSROOT:?CMAKE_OSX_SYSROOT should be set to macOS SDK path, e.g.: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk}" +: "${OPENSSL_ROOT_DIR:?variable not set, see also macosx_build_config.command}" ARCHIVE_NAME_PREFIX=zano-macos-x64- @@ -30,7 +31,7 @@ fi rm -rf $ZANO_BUILD_DIR; mkdir -p "$ZANO_BUILD_DIR/release"; cd "$ZANO_BUILD_DIR/release" -cmake $testnet_def -D CMAKE_OSX_SYSROOT=$CMAKE_OSX_SYSROOT -D BUILD_GUI=TRUE -D CMAKE_PREFIX_PATH="$ZANO_QT_PATH/clang_64" -D CMAKE_BUILD_TYPE=Release -D BOOST_ROOT="$ZANO_BOOST_ROOT" -D BOOST_LIBRARYDIR="$ZANO_BOOST_LIBS_PATH" ../.. +cmake $testnet_def -D OPENSSL_ROOT_DIR=$OPENSSL_ROOT_DIR -D CMAKE_OSX_SYSROOT=$CMAKE_OSX_SYSROOT -D BUILD_GUI=TRUE -D CMAKE_PREFIX_PATH="$ZANO_QT_PATH/clang_64" -D CMAKE_BUILD_TYPE=Release -D BOOST_ROOT="$ZANO_BOOST_ROOT" -D BOOST_LIBRARYDIR="$ZANO_BOOST_LIBS_PATH" ../.. if [ $? -ne 0 ]; then echo "Failed to cmake" exit 1 diff --git a/utils/build_script_windows.bat b/utils/build_script_windows.bat index a224b843..b5a1451d 100644 --- a/utils/build_script_windows.bat +++ b/utils/build_script_windows.bat @@ -1,10 +1,10 @@ -SET QT_PREFIX_PATH=C:\dev\_sdk\Qt5.11.2\5.11.2\msvc2017_64 -SET INNOSETUP_PATH=C:\Program Files (x86)\Inno Setup 5\ISCC.exe -SET ETC_BINARIES_PATH=C:\dev\deploy\etc-binaries -SET BUILDS_PATH=C:\dev\deploy\zano +call configure_local_paths.cmd + +;; MSVC version-specific paths +SET LOCAL_BOOST_LIB_PATH=%LOCAL_BOOST_PATH%\lib64-msvc-14.1 +SET QT_MSVC_PATH=%QT_PREFIX_PATH%\msvc2017_64 + SET ACHIVE_NAME_PREFIX=zano-win-x64- -SET LOCAL_BOOST_PATH=C:\dev\_sdk\boost_1_68_0 -SET LOCAL_BOOST_LIB_PATH=C:\dev\_sdk\boost_1_68_0\lib64-msvc-14.1 SET MY_PATH=%~dp0 SET SOURCES_PATH=%MY_PATH:~0,-7% @@ -44,7 +44,7 @@ cd %SOURCES_PATH% rmdir build /s /q mkdir build cd build -cmake %TESTNET_DEF% -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%" -D BUILD_GUI=TRUE -D STATIC=FALSE -G "Visual Studio 15 2017 Win64" -T host=x64 .. +cmake %TESTNET_DEF% -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_MSVC_PATH%" -D BUILD_GUI=TRUE -D STATIC=FALSE -G "Visual Studio 15 2017 Win64" -T host=x64 .. IF %ERRORLEVEL% NEQ 0 ( goto error ) @@ -108,7 +108,7 @@ copy /Y zanod.exe bunch copy /Y simplewallet.exe bunch copy /Y *.pdb bunch -%QT_PREFIX_PATH%\bin\windeployqt.exe bunch\Zano.exe +%QT_MSVC_PATH%\bin\windeployqt.exe bunch\Zano.exe cd bunch diff --git a/utils/build_script_windows32.bat b/utils/build_script_windows32.bat deleted file mode 100644 index 9bb05564..00000000 --- a/utils/build_script_windows32.bat +++ /dev/null @@ -1,184 +0,0 @@ -SET QT32_PREFIX_PATH=C:\Qt\Qt5.9.1\5.9.1\msvc2015 -SET INNOSETUP_PATH=C:\Program Files (x86)\Inno Setup 5\ISCC.exe -SET ETC32_BINARIES_PATH=C:\home\deploy\etc-binaries-32 -SET BUILDS_PATH=C:\home\deploy\zano -SET ACHIVE_NAME_PREFIX=zano-win-x32-webengine- -SET SOURCES_PATH=C:\home\deploy\zano\src - -SET LOCAL_BOOST_PATH_32=C:\local\boost_1_62_0 -SET LOCAL_BOOST_LIB_PATH_32=C:\local\boost_1_62_0\lib32-msvc-14.0 - - -@echo on - -set BOOST_ROOT=%LOCAL_BOOST_PATH_32% -set BOOST_LIBRARYDIR=%LOCAL_BOOST_LIB_PATH_32% - - - -@echo "---------------- PREPARING BINARIES ---------------------------" -@echo "---------------------------------------------------------------" - - - -cd %SOURCES_PATH% -git pull -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - - -@echo "---------------- BUILDING APPLICATIONS ------------------------" -@echo "---------------------------------------------------------------" - - - - -rmdir build /s /q -mkdir build -cd build -cmake -D CMAKE_PREFIX_PATH="%QT32_PREFIX_PATH%" -D BUILD_GUI=TRUE -D STATIC=FALSE -G "Visual Studio 14" .. -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - -setLocal -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 - -msbuild version.vcxproj /p:Configuration=Release /t:Build -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - -msbuild src/daemon.vcxproj /p:Configuration=Release /t:Build -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - -msbuild src/simplewallet.vcxproj /p:Configuration=Release /t:Build -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - -msbuild src/zano.vcxproj /p:Configuration=Release /t:Build - -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - - -endlocal - -@echo on -echo "sources are built" - - - - - -cd %SOURCES_PATH%/build - -set cmd=src\Release\simplewallet.exe --version -FOR /F "tokens=3" %%a IN ('%cmd%') DO set version=%%a -set version=%version:~0,-2% -echo '%version%' - -cd src\release - - - -@echo on - - -mkdir bunch - -copy /Y zano.exe bunch -copy /Y zanod.exe bunch -copy /Y simplewallet.exe bunch -copy /Y zano.exe bunch -%QT32_PREFIX_PATH%\bin\windeployqt.exe bunch\Zano.exe - -cd bunch - -zip -r %BUILDS_PATH%\builds\%ACHIVE_NAME_PREFIX%%version%.zip *.* -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - - -@echo "Add html" - -cd %SOURCES_PATH%\src\gui\qt-daemon\ -zip -r %BUILDS_PATH%\builds\%ACHIVE_NAME_PREFIX%%version%.zip html -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - - -@echo "Add runtime stuff" - - -cd %ETC32_BINARIES_PATH% -zip -r %BUILDS_PATH%\builds\%ACHIVE_NAME_PREFIX%%version%.zip *.* -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - - -cd %SOURCES_PATH%\build -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - - -@echo "---------------------------------------------------------------" -@echo "-------------------Building installer--------------------------" -@echo "---------------------------------------------------------------" - -mkdir installer_src - - -unzip %BUILDS_PATH%\builds\%ACHIVE_NAME_PREFIX%%version%.zip -d installer_src -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - - -"%INNOSETUP_PATH%" /dBinariesPath=../build/installer_src /DMyAppVersion=%version% /o%BUILDS_PATH%\builds\ /f%ACHIVE_NAME_PREFIX%%version%-installer ..\utils\setup_32.iss -IF %ERRORLEVEL% NEQ 0 ( - goto error -) - - -@echo "---------------------------------------------------------------" -@echo "---------------------------------------------------------------" - -@echo " UPLOADING TO SERVER ...." - -pscp -i C:\Users\Administrator\.ssh\putty.ppk %BUILDS_PATH%\builds\%ACHIVE_NAME_PREFIX%%version%-installer.exe root@95.216.11.16:/usr/share/nginx/html/%ACHIVE_NAME_PREFIX%%version%-installer.exe -IF %ERRORLEVEL% NEQ 0 ( - @echo "FAILED TO UPLOAD TO SERVER" - goto error -) - -echo "New build available at loaction: http://95.216.11.16/%ACHIVE_NAME_PREFIX%%version%-installer.exe" - - - - -goto success - -:error -echo "BUILD FAILED" -exit /B %ERRORLEVEL% - -:success -echo "BUILD SUCCESS" - -cd .. - - - - - - diff --git a/utils/build_script_windows_both.bat b/utils/build_script_windows_both.bat deleted file mode 100644 index 70ded703..00000000 --- a/utils/build_script_windows_both.bat +++ /dev/null @@ -1,24 +0,0 @@ -call utils/build_script_windows.bat -IF %ERRORLEVEL% NEQ 0 ( - @echo "FAILED TO build_script_windows.bat" - goto error -) - - -call utils/build_script_windows32.bat -IF %ERRORLEVEL% NEQ 0 ( - @echo "FAILED TO build_script_windows32.bat" - goto error -) - - - -goto success - -:error -echo "BUILD FAILED" -exit /B %ERRORLEVEL% - -:success -echo "BUILD SUCCESS" - diff --git a/utils/configure_local_paths.cmd.example b/utils/configure_local_paths.cmd.example index 4ed4c3c4..65c5e891 100644 --- a/utils/configure_local_paths.cmd.example +++ b/utils/configure_local_paths.cmd.example @@ -5,4 +5,9 @@ rem Rename to configure_local_paths.cmd and do not commit. rem set QT_PREFIX_PATH=C:\dev\_sdk\Qt5.11.2\5.11.2 -set BOOST_ROOT=C:\dev\_sdk\boost_1_66_0 +set INNOSETUP_PATH=C:\Program Files (x86)\Inno Setup 5\ISCC.exe +set ETC_BINARIES_PATH=C:\dev\deploy\etc-binaries +set BUILDS_PATH=C:\dev\deploy\zano +set LOCAL_BOOST_PATH=C:\dev\_sdk\boost_1_70_0 +set OPENSSL_ROOT_DIR=C:\dev\_sdk\OpenSSL-Win64 +set BOOST_ROOT=%LOCAL_BOOST_PATH% diff --git a/utils/configure_local_paths_msvs2019.cmd b/utils/configure_local_paths_msvs2019.cmd index 742774bf..a8d442b2 100644 --- a/utils/configure_local_paths_msvs2019.cmd +++ b/utils/configure_local_paths_msvs2019.cmd @@ -6,3 +6,4 @@ rem set QT_PREFIX_PATH=C:\dev\_sdk\Qt5.15.2\5.15.2 set BOOST_ROOT=C:\dev\_sdk\boost_1_76_0 +set OPENSSL_ROOT_DIR=C:\dev\_sdk\OpenSSL-Win64 diff --git a/utils/configure_win32_msvs2015_gui.cmd b/utils/configure_win32_msvs2015_gui.cmd index 335ec1c6..f0a84e32 100644 --- a/utils/configure_win32_msvs2015_gui.cmd +++ b/utils/configure_win32_msvs2015_gui.cmd @@ -4,4 +4,4 @@ cd .. @mkdir build_msvc2015_32 cd build_msvc2015_32 -cmake -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2015 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib32-msvc-14.0" -G "Visual Studio 14 2015" ".." +cmake -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2015 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib32-msvc-14.0" -G "Visual Studio 14 2015" ".." diff --git a/utils/configure_win64_msvs2013_gui.cmd b/utils/configure_win64_msvs2013_gui.cmd index ddc715d3..3e8a8b82 100644 --- a/utils/configure_win64_msvs2013_gui.cmd +++ b/utils/configure_win64_msvs2013_gui.cmd @@ -4,4 +4,4 @@ cd .. @mkdir build_msvc2013_64 cd build_msvc2013_64 -cmake -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2013_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-12.0" -G "Visual Studio 12 2013 Win64" ".." \ No newline at end of file +cmake -D BUILD_TESTS=TRUE -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2013_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-12.0" -G "Visual Studio 12 2013 Win64" ".." \ No newline at end of file diff --git a/utils/configure_win64_msvs2015_gui.cmd b/utils/configure_win64_msvs2015_gui.cmd index 73e44d17..d365843e 100644 --- a/utils/configure_win64_msvs2015_gui.cmd +++ b/utils/configure_win64_msvs2015_gui.cmd @@ -4,4 +4,4 @@ cd .. @mkdir build_msvc2015_64 cd build_msvc2015_64 -cmake -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2015_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.0" -G "Visual Studio 14 2015 Win64" -T host=x64 ".." \ No newline at end of file +cmake -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2015_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.0" -G "Visual Studio 14 2015 Win64" -T host=x64 ".." \ No newline at end of file diff --git a/utils/configure_win64_msvs2017_gui.cmd b/utils/configure_win64_msvs2017_gui.cmd index fe6e3eea..7b887d75 100644 --- a/utils/configure_win64_msvs2017_gui.cmd +++ b/utils/configure_win64_msvs2017_gui.cmd @@ -4,4 +4,4 @@ cd .. @mkdir build_msvc2017_64 cd build_msvc2017_64 -cmake -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2017_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.1" -G "Visual Studio 15 2017 Win64" -T host=x64 ".." \ No newline at end of file +cmake -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2017_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.1" -G "Visual Studio 15 2017 Win64" -T host=x64 ".." \ No newline at end of file diff --git a/utils/configure_win64_msvs2017_gui_testnet.cmd b/utils/configure_win64_msvs2017_gui_testnet.cmd index 892a199a..61d34790 100644 --- a/utils/configure_win64_msvs2017_gui_testnet.cmd +++ b/utils/configure_win64_msvs2017_gui_testnet.cmd @@ -4,4 +4,4 @@ cd .. @mkdir build_msvc2017_64_tn cd build_msvc2017_64_tn -cmake -D TESTNET=TRUE -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2017_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.1" -G "Visual Studio 15 2017 Win64" -T host=x64 ".." \ No newline at end of file +cmake -D TESTNET=TRUE -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2017_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.1" -G "Visual Studio 15 2017 Win64" -T host=x64 ".." \ No newline at end of file diff --git a/utils/configure_win64_msvs2019_gui_testnet.cmd b/utils/configure_win64_msvs2019_gui_testnet.cmd index 0fd0d89d..afc14035 100644 --- a/utils/configure_win64_msvs2019_gui_testnet.cmd +++ b/utils/configure_win64_msvs2019_gui_testnet.cmd @@ -4,4 +4,4 @@ cd .. @mkdir build_msvc2019_64_tn cd build_msvc2019_64_tn -cmake -D TESTNET=TRUE -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2019_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.2" -G "Visual Studio 16 2019" -A x64 -T host=x64 ".." +cmake -D TESTNET=TRUE -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2019_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.2" -G "Visual Studio 16 2019" -A x64 -T host=x64 ".." diff --git a/utils/macosx_build_config.command b/utils/macosx_build_config.command index 786e53a0..89cfe02b 100644 --- a/utils/macosx_build_config.command +++ b/utils/macosx_build_config.command @@ -9,3 +9,4 @@ export ZANO_QT_PATH="/Users/roky/Qt5.6.0/5.6" export ZANO_BOOST_ROOT="/Users/roky/boost_1_60_0" export ZANO_BOOST_LIBS_PATH="$ZANO_BOOST_ROOT/stage/lib" export ZANO_BUILD_DIR="build_mac_osx_64" +export OPENSSL_ROOT_DIR="/usr/local/opt/openssl" diff --git a/utils/test_api_files/get_alias_details.json b/utils/test_api_files/get_alias_details.json new file mode 100644 index 00000000..c89f7e97 --- /dev/null +++ b/utils/test_api_files/get_alias_details.json @@ -0,0 +1 @@ +{"method": "get_alias_details","params": {"alias": "zoidb"}} \ No newline at end of file