1
0
Fork 0
forked from lthn/blockchain

Merge branch 'release'

This commit is contained in:
sowle 2022-05-08 19:59:17 +02:00
commit c070839a28
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
81 changed files with 2843 additions and 1538 deletions

4
.gitmodules vendored
View file

@ -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

View file

@ -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()

View file

@ -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
<br />
### 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` <br> `cd build` <br> `cmake ..` <br> `make`

View file

@ -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)

View file

@ -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);

View file

@ -31,6 +31,8 @@
#include <limits>
#include <set>
#include <iterator>
#include <algorithm>
#include <functional>
#include <boost/thread.hpp>
#include "include_base_utils.h"
#include "auto_val_init.h"
@ -111,17 +113,6 @@ namespace misc_utils
return (std::numeric_limits<t_type>::max)();
}
// TEMPLATE STRUCT less
template<class _Ty>
struct less_as_pod
: public std::binary_function<_Ty, _Ty, bool>
{ // functor for operator<
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply operator< to operands
return memcmp(&_Left, &_Right, sizeof(_Left)) < 0;
}
};
template<class _Ty>
bool is_less_as_pod(const _Ty& _Left, const _Ty& _Right)
{ // apply operator< to operands

View file

@ -693,7 +693,7 @@ bool boosted_tcp_server<t_protocol_handler>::connect(const std::string& adr, con
shared_context->cond.notify_one();
};
sock_.async_connect(remote_endpoint, boost::bind<void>(connect_callback, _1, local_shared_context));
sock_.async_connect(remote_endpoint, boost::bind<void>(connect_callback, boost::placeholders::_1, local_shared_context));
while(local_shared_context->ec == boost::asio::error::would_block) {
bool r = false;
try {

View file

@ -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;
}

View file

@ -46,11 +46,12 @@ namespace levin
/************************************************************************/
/* */
/************************************************************************/
class levin_client_impl
template<typename transport_t>
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<typename transport_t>
class levin_client_impl2: public levin_client_impl_t<transport_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<net_utils::blocked_mode_client> levin_client;
typedef levin::levin_client_impl2<net_utils::blocked_mode_client> levin_client2;
}
}

View file

@ -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<uint32_t>(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<typename transport_t>
bool levin_client_impl_t<transport_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<typename transport_t>
bool levin_client_impl_t<transport_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<uint32_t>(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<typename transport_t>
bool levin_client_impl_t<transport_t>::is_connected()
{
return m_transport.is_connected();
}
//------------------------------------------------------------------------------
template<typename transport_t>
bool levin_client_impl_t<transport_t>::disconnect()
{
return m_transport.disconnect();
}
//------------------------------------------------------------------------------
template<typename transport_t>
levin_client_impl_t<transport_t>::levin_client_impl_t()
{
}
//------------------------------------------------------------------------------
template<typename transport_t>
levin_client_impl_t<transport_t>::~levin_client_impl_t()
{
disconnect();
}
//------------------------------------------------------------------------------
template<typename transport_t>
int levin_client_impl_t<transport_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<typename transport_t>
int levin_client_impl_t<transport_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<typename transport_t>
int levin_client_impl2<transport_t>::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<uint32_t>(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<uint32_t>(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<typename transport_t>
int levin_client_impl2<transport_t>::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;
}
}
}
//------------------------------------------------------------------------------

View file

@ -27,6 +27,7 @@
#pragma once
#include <boost/mpl/vector.hpp>
#include <boost/mpl/contains.hpp>
#include <deque>
namespace epee

View file

@ -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<internal_owner_type_name, type_name_in, typename_out>(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<internal_owner_type_name, type_name_in, typename_out>(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<internal_owner_type_name, typename COMMAND::request, typename COMMAND::response>(command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);}
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename COMMAND::request, typename COMMAND::response>(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<internal_owner_type_name, type_name_in>(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);}
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in>(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<internal_owner_type_name, typename NOTIFY::request>(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);}
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename NOTIFY::request>(this, command, in_buff, boost::bind(func, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3), context);}
#define CHAIN_INVOKE_MAP2(func) \

1
contrib/tor-connect Submodule

@ -0,0 +1 @@
Subproject commit aa509880f06292ac8078046f3d49ff854e400716

View file

@ -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)

View file

@ -10,36 +10,36 @@
namespace command_line
{
const arg_descriptor<bool> arg_help = {"help", "Produce help message"};
const arg_descriptor<bool> arg_version = {"version", "Output version information"};
const arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory", ""};
const arg_descriptor<bool> arg_help ("help", "Produce help message");
const arg_descriptor<bool> arg_version ("version", "Output version information");
const arg_descriptor<std::string> arg_data_dir ("data-dir", "Specify data directory", "");
const arg_descriptor<int> 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<int> 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<std::string> arg_config_file = { "config-file", "Specify configuration file", std::string(CURRENCY_NAME_SHORT ".conf") };
const arg_descriptor<bool> arg_os_version = { "os-version", "" };
const arg_descriptor<std::string> arg_config_file ( "config-file", "Specify configuration file", std::string(CURRENCY_NAME_SHORT ".conf") );
const arg_descriptor<bool> arg_os_version ( "os-version", "" );
const arg_descriptor<std::string> arg_log_dir = { "log-dir", "", "", true};
const arg_descriptor<std::string> arg_log_file = { "log-file", "", "" };
const arg_descriptor<int> arg_log_level = { "log-level", "", LOG_LEVEL_0, true };
const arg_descriptor<std::string> arg_log_dir ( "log-dir", "");
const arg_descriptor<std::string> arg_log_file ( "log-file", "", "");
const arg_descriptor<int> arg_log_level ( "log-level", "");
const arg_descriptor<bool> arg_console = { "no-console", "Disable daemon console commands" };
const arg_descriptor<bool> arg_show_details = { "currency-details", "Display currency details" };
const arg_descriptor<bool> arg_show_rpc_autodoc = { "show_rpc_autodoc", "Display rpc auto-generated documentation template" };
const arg_descriptor<bool> arg_console ( "no-console", "Disable daemon console commands" );
const arg_descriptor<bool> arg_show_details ( "currency-details", "Display currency details" );
const arg_descriptor<bool> arg_show_rpc_autodoc ( "show_rpc_autodoc", "Display rpc auto-generated documentation template" );
const arg_descriptor<bool> arg_disable_upnp = { "disable-upnp", "Disable UPnP (enhances local network privacy)", false, true };
const arg_descriptor<bool> 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<bool> arg_disable_upnp ( "disable-upnp", "Disable UPnP (enhances local network privacy)");
const arg_descriptor<bool> 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<bool> 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<bool> 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<bool> arg_enable_offers_service = { "enable-offers-service", "Enables marketplace feature", false, false};
const arg_descriptor<std::string> arg_db_engine = { "db-engine", "Specify database engine for storage. May be \"lmdb\"(default) or \"mdbx\"", ARG_DB_ENGINE_LMDB, false };
const arg_descriptor<bool> 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<bool> 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<bool> arg_enable_offers_service ( "enable-offers-service", "Enables marketplace feature", false);
const arg_descriptor<std::string> arg_db_engine ( "db-engine", "Specify database engine for storage. May be \"lmdb\"(default) or \"mdbx\"", ARG_DB_ENGINE_LMDB );
const arg_descriptor<bool> arg_no_predownload = { "no-predownload", "Do not pre-download blockchain database", };
const arg_descriptor<bool> arg_force_predownload = { "force-predownload", "Pre-download blockchain database regardless of it's status", };
const arg_descriptor<bool> arg_validate_predownload = { "validate-predownload", "Paranoid mode, re-validate each block from pre-downloaded database and rebuild own database", };
const arg_descriptor<std::string> arg_predownload_link = { "predownload-link", "Override url for blockchain database pre-downloading", "", true };
const arg_descriptor<bool> arg_no_predownload ( "no-predownload", "Do not pre-download blockchain database");
const arg_descriptor<bool> arg_force_predownload ( "force-predownload", "Pre-download blockchain database regardless of it's status");
const arg_descriptor<bool> arg_validate_predownload ( "validate-predownload", "Paranoid mode, re-validate each block from pre-downloaded database and rebuild own database");
const arg_descriptor<std::string> arg_predownload_link ( "predownload-link", "Override url for blockchain database pre-downloading");
const arg_descriptor<std::string> arg_deeplink = { "deeplink-params", "Deeplink parameter, in that case app just forward params to running app", "", true };
const arg_descriptor<std::string> arg_deeplink ( "deeplink-params", "Deeplink parameter, in that case app just forward params to running app");
}

View file

@ -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<typename T>
struct arg_descriptor<std::vector<T>, false>
{
arg_descriptor(const char* _name, const char* _description) :
name(_name),
description(_description)
{}
typedef std::vector<T> value_type;
const char* name;
@ -79,7 +85,7 @@ namespace command_line
boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false>& arg)
{
auto semantic = boost::program_options::value<T>();
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<T, char>* make_semantic(const arg_descriptor<T, false>& arg, const T& def)
{
auto semantic = boost::program_options::value<T>();
if (!arg.not_use_default)
if (arg.use_default)
semantic->default_value(def);
return semantic;
}

View file

@ -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;

View file

@ -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 };

View file

@ -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<size_t> cnt = 0;
std::atomic<size_t> cnt(0);
for (const auto& jb : cntr)
{
call_executor_base* pjob = jb.get();

17
src/common/tor_helper.h Normal file
View file

@ -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<tools::tor::tor_transport> levin_over_tor_client;
}

View file

@ -38,32 +38,32 @@ using namespace nodetool;
namespace
{
const command_line::arg_descriptor<std::string> arg_ip = {"ip", "set ip", "127.0.0.1", false};
const command_line::arg_descriptor<size_t> arg_port = {"port", "set port"};
const command_line::arg_descriptor<size_t> arg_rpc_port = {"rpc-port", "set rpc port", RPC_DEFAULT_PORT, false};
const command_line::arg_descriptor<uint32_t> arg_timeout = {"timeout", "set timeout", 5000, false};
const command_line::arg_descriptor<std::string> arg_priv_key = {"private-key", "private key to subscribe debug command", "", true};
const command_line::arg_descriptor<uint64_t> arg_peer_id = {"peer-id", "peerid if known(if not - will be requested)", 0};
const command_line::arg_descriptor<bool> arg_generate_keys = {"generate-keys-pair", "generate private and public keys pair"};
const command_line::arg_descriptor<bool> arg_request_stat_info = {"request-stat-info", "request statistics information"};
const command_line::arg_descriptor<uint64_t> arg_log_journal_len = { "log-journal-len", "Specify length of list of last error messages in log", 0, true };
const command_line::arg_descriptor<bool> arg_request_net_state = {"request-net-state", "request network state information (peer list, connections count)"};
const command_line::arg_descriptor<bool> 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<bool> arg_get_aliases = {"rpc-get-aliases", "request daemon aliases all list", "", true};
const command_line::arg_descriptor<std::string> arg_increment_build_no = { "increment-build-no", "Increment build nimber", "", true };
const command_line::arg_descriptor<std::string> 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<std::string> arg_update_build_no = {"update-build-no", "Updated version number in version template file", "", true};
const command_line::arg_descriptor<std::string> arg_generate_genesis = {"generate-genesis", "Generate genesis coinbase based on config file", "", true };
const command_line::arg_descriptor<uint64_t> arg_genesis_split_amount = { "genesis-split-amount", "Set split amount for generating genesis block", 0, true };
const command_line::arg_descriptor<std::string> arg_get_info_flags = { "getinfo-flags-hex", "Set of bits for rpc-get-daemon-info", "", true };
const command_line::arg_descriptor<int64_t> arg_set_peer_log_level = { "set-peer-log-level", "Set log level for remote peer", 0, true };
const command_line::arg_descriptor<std::string> arg_download_peer_log = { "download-peer-log", "Download log from remote peer <starting_offset>[,<count>]", "", true };
const command_line::arg_descriptor<bool> arg_do_consloe_log = { "do-console-log", "Tool generates debug console output(debug purposes)", "", true };
const command_line::arg_descriptor<std::string> arg_generate_integrated_address = { "generate-integrated-address", "Tool create integrated address from simple address and payment_id", "", true };
const command_line::arg_descriptor<std::string> arg_pack_file = {"pack-file", "perform gzip-packing and calculate hash for a given file", "", true };
const command_line::arg_descriptor<std::string> arg_unpack_file = {"unpack-file", "Perform gzip-unpacking and calculate hash for a given file", "", true };
const command_line::arg_descriptor<std::string> arg_target_file = {"target-file", "Specify target file for pack-file and unpack-file commands", "", true };
//const command_line::arg_descriptor<std::string> arg_send_ipc = {"send-ipc", "Send IPC request to UI", "", true };
const command_line::arg_descriptor<std::string> arg_ip ("ip", "set ip", "127.0.0.1");
const command_line::arg_descriptor<size_t> arg_port ("port", "set port");
const command_line::arg_descriptor<size_t> arg_rpc_port ("rpc-port", "set rpc port", RPC_DEFAULT_PORT);
const command_line::arg_descriptor<uint32_t> arg_timeout ("timeout", "set timeout", 5000);
const command_line::arg_descriptor<std::string> arg_priv_key ("private-key", "private key to subscribe debug command");
const command_line::arg_descriptor<uint64_t> arg_peer_id ("peer-id", "peerid if known(if not - will be requested)", 0);
const command_line::arg_descriptor<bool> arg_generate_keys ("generate-keys-pair", "generate private and public keys pair");
const command_line::arg_descriptor<bool> arg_request_stat_info ("request-stat-info", "request statistics information");
const command_line::arg_descriptor<uint64_t> arg_log_journal_len ( "log-journal-len", "Specify length of list of last error messages in log");
const command_line::arg_descriptor<bool> arg_request_net_state ("request-net-state", "request network state information (peer list, connections count)");
const command_line::arg_descriptor<bool> 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<bool> arg_get_aliases ("rpc-get-aliases", "request daemon aliases all list");
const command_line::arg_descriptor<std::string> arg_increment_build_no ( "increment-build-no", "Increment build nimber");
const command_line::arg_descriptor<std::string> 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<std::string> arg_update_build_no ("update-build-no", "Updated version number in version template file");
const command_line::arg_descriptor<std::string> arg_generate_genesis ("generate-genesis", "Generate genesis coinbase based on config file");
const command_line::arg_descriptor<uint64_t> arg_genesis_split_amount ( "genesis-split-amount", "Set split amount for generating genesis block");
const command_line::arg_descriptor<std::string> arg_get_info_flags ( "getinfo-flags-hex", "Set of bits for rpc-get-daemon-info", "");
const command_line::arg_descriptor<int64_t> arg_set_peer_log_level ( "set-peer-log-level", "Set log level for remote peer");
const command_line::arg_descriptor<std::string> arg_download_peer_log ( "download-peer-log", "Download log from remote peer <starting_offset>[,<count>]");
const command_line::arg_descriptor<bool> arg_do_consloe_log ( "do-console-log", "Tool generates debug console output(debug purposes)");
const command_line::arg_descriptor<std::string> arg_generate_integrated_address ( "generate-integrated-address", "Tool create integrated address from simple address and payment_id");
const command_line::arg_descriptor<std::string> arg_pack_file ("pack-file", "perform gzip-packing and calculate hash for a given file");
const command_line::arg_descriptor<std::string> arg_unpack_file ("unpack-file", "Perform gzip-unpacking and calculate hash for a given file");
const command_line::arg_descriptor<std::string> arg_target_file ("target-file", "Specify target file for pack-file and unpack-file commands");
//const command_line::arg_descriptor<std::string> arg_send_ipc ("send-ipc", "Send IPC request to UI");
}
typedef COMMAND_REQUEST_STAT_INFO_T<t_currency_protocol_handler<core>::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<int>(command_line::get_arg(vm, arg_port)), static_cast<int>(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<class command_t>
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<uint64_t>(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);

View file

@ -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

View file

@ -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

View file

@ -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<public_key> L; // size = ceil( log_2(m * n) )
std::vector<public_key> 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<typename CT>
bool bpp_gen(const scalar_vec_t& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector<point_t>& 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<CT::c_bpp_n> 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<CT::c_bpp_n> 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<point_t> 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 = <a1, ((y, y^2, ...) o b2)> -- 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 = <a2, ((y, y^2, ...) o b1)> * 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<point_t>& commitments)
: sig(sig)
, commitments(commitments)
{}
const bpp_signature& sig;
const std::vector<point_t>& commitments;
};
template<typename CT>
bool bpp_verify(const std::vector<bpp_sig_commit_ref_t>& 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<point_t> L;
std::vector<point_t> R;
};
std::vector<intermediate_element_t> 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<point_t> 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<<j) & i) - 1) (counting both from 0)
//
// 2) we gonna aggregate all (**) for each round by multiplying them to a random weights and then sum up
// insert A_hat into (**) =>
// (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<CT::c_bpp_n> 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<CT>(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

View file

@ -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<public_key> L; // size = log_2(m * n)
std::vector<public_key> 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<typename CT>
bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, bppe_signature& sig, std::vector<point_t>& 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<CT::c_bpp_n> 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<CT::c_bpp_n> 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<point_t> 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 = <a1, ((y, y^2, ...) o b2)> -- 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 = <a2, ((y, y^2, ...) o b1)> * 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<point_t>& commitments)
: sig(sig)
, commitments(commitments)
{}
const bppe_signature& sig;
const std::vector<point_t>& commitments;
};
template<typename CT>
bool bppe_verify(const std::vector<bppe_sig_commit_ref_t>& 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<point_t> L;
std::vector<point_t> R;
};
std::vector<intermediate_element_t> 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<point_t> 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<<j) & i) - 1) (counting both from 0)
//
// 2) we gonna aggregate all (**) for each round by multiplying them to a random weights and then sum up
// insert A_hat into (**) =>
// (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<CT::c_bpp_n> 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<CT>(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

View file

@ -6,7 +6,4 @@
namespace crypto
{
const point_t& bpp_crypto_trait_zano::bpp_H = c_point_H;
}

View file

@ -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<size_t N = 64, size_t values_max = 16>
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<size_t N, size_t values_max>
const point_t& bpp_crypto_trait_zano<N, values_max>::bpp_H = c_point_H;
template<size_t N, size_t values_max>
const point_t& bpp_crypto_trait_zano<N, values_max>::bpp_H2 = c_point_H2;
struct bpp_signature
{
std::vector<public_key> L; // size = log_2(m * n)
std::vector<public_key> 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<typename CT>
bool bpp_gen(const std::vector<uint64_t>& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector<point_t>& 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<c_bpp_n> 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<c_bpp_n> 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<point_t> 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 = <a1, ((y, y^2, ...) o b2)> -- 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 = <a2, ((y, y^2, ...) o b1)> * 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<typename CT>
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<point_t>& commitments)
: sig(sig)
, commitments(commitments)
{}
const bpp_signature& sig;
const std::vector<point_t>& commitments;
};
template<typename CT>
bool bpp_verify(const std::vector<bpp_sig_commit_ref_t>& 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<point_t> L;
std::vector<point_t> R;
};
std::vector<intermediate_element_t> 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<point_t> 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<<j) & i) - 1) (counting both from 0)
//
// 2) we gonna aggregate all (**) for each round by multiplying them to a random weights and then sum up
// insert A_hat into (**) =>
// (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<c_bpp_n> 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<CT>(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"

View file

@ -13,7 +13,7 @@
#include "storages/portable_storage_template_helper.h"
command_line::arg_descriptor<bool> arg_market_disable = { "disable-market", "Start GUI with market service disabled", false, true };
command_line::arg_descriptor<bool> arg_market_disable ( "disable-market", "Start GUI with market service disabled");
namespace bc_services

View file

@ -80,8 +80,8 @@ DISABLE_VS_WARNINGS(4267)
namespace
{
const command_line::arg_descriptor<uint32_t> arg_db_cache_l1 = { "db-cache-l1", "Specify size of memory mapped db cache file", 0, true };
const command_line::arg_descriptor<uint32_t> arg_db_cache_l2 = { "db-cache-l2", "Specify cached elements in db helpers", 0, true };
const command_line::arg_descriptor<uint32_t> arg_db_cache_l1 ( "db-cache-l1", "Specify size of memory mapped db cache file");
const command_line::arg_descriptor<uint32_t> arg_db_cache_l2 ( "db-cache-l2", "Specify cached elements in db helpers");
}
//------------------------------------------------------------------

View file

@ -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

View file

@ -33,10 +33,10 @@ namespace currency
namespace
{
const command_line::arg_descriptor<std::string> arg_extra_messages = {"extra-messages-file", "Specify file for extra messages to include into coinbase transactions", "", true};
const command_line::arg_descriptor<std::string> arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true};
const command_line::arg_descriptor<uint32_t> arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true};
const command_line::arg_descriptor<std::string> arg_block_template_extra_text = { "miner-text-info", "Set block extra text info", "", true };
const command_line::arg_descriptor<std::string> arg_extra_messages ("extra-messages-file", "Specify file for extra messages to include into coinbase transactions");
const command_line::arg_descriptor<std::string> arg_start_mining ("start-mining", "Specify wallet address to mining for");
const command_line::arg_descriptor<uint32_t> arg_mining_threads ("mining-threads", "Specify mining threads count");
const command_line::arg_descriptor<std::string> arg_block_template_extra_text ( "miner-text-info", "Set block extra text info");
}

View file

@ -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)
{

View file

@ -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()
};
};
/************************************************************************/
/* */

View file

@ -35,14 +35,15 @@ namespace currency
typedef core_stat_info stat_info;
typedef t_currency_protocol_handler<t_core> currency_protocol_handler;
typedef CORE_SYNC_DATA payload_type;
typedef std::pair<NOTIFY_NEW_TRANSACTIONS::request, currency_connection_context> relay_que_entry;
typedef std::pair<NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request, currency_connection_context> relay_que_entry;
t_currency_protocol_handler(t_core& rcore, nodetool::i_p2p_endpoint<connection_context>* p_net_layout);
~t_currency_protocol_handler();
BEGIN_INVOKE_MAP2(currency_protocol_handler)
HANDLE_NOTIFY_T2(NOTIFY_NEW_BLOCK, &currency_protocol_handler::handle_notify_new_block)
HANDLE_NOTIFY_T2(NOTIFY_NEW_TRANSACTIONS, &currency_protocol_handler::handle_notify_new_transactions)
HANDLE_NOTIFY_T2(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS, &currency_protocol_handler::handle_notify_new_transactions)
HANDLE_INVOKE_T2(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS, &currency_protocol_handler::handle_invoke_new_transaction)
HANDLE_NOTIFY_T2(NOTIFY_REQUEST_GET_OBJECTS, &currency_protocol_handler::handle_request_get_objects)
HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_GET_OBJECTS, &currency_protocol_handler::handle_response_get_objects)
HANDLE_NOTIFY_T2(NOTIFY_REQUEST_CHAIN, &currency_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<relay_que_entry>& 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<connection_context> m_p2p_stub;

View file

@ -369,45 +369,79 @@ namespace currency
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
int t_currency_protocol_handler<t_core>::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& context)
int t_currency_protocol_handler<t_core>::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<class t_core>
int t_currency_protocol_handler<t_core>::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<class t_core>
int t_currency_protocol_handler<t_core>::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<class t_core>
int t_currency_protocol_handler<t_core>::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<NOTIFY_NEW_TRANSACTIONS>(req, cc);
post_notify<NOTIFY_OR_INVOKE_NEW_TRANSACTIONS>(req, cc);
if (debug_ss.tellp())
debug_ss << ", ";
@ -944,7 +978,7 @@ namespace currency
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
bool t_currency_protocol_handler<t_core>::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context)
bool t_currency_protocol_handler<t_core>::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<NOTIFY_NEW_TRANSACTIONS>(arg, exclude_context);
return relay_post_notify<NOTIFY_OR_INVOKE_NEW_TRANSACTIONS>(arg, exclude_context);
#endif
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -7,6 +7,7 @@
#pragma once
#include <boost/lexical_cast.hpp>
#include <boost/bind/placeholders.hpp>
#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<currency::t_currency_protocol_handler<currency::core> >& 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 <begin_height> [<end_height>]");
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 <begin_height> [<end_height>]");
//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 <block_hash> | <block_height>");
m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_commands_handler::print_block_info, this, _1), "Print block info, print_block <block_hash> | <block_height>");
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 <transaction_hash>");
m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_commands_handler::start_mining, this, _1), "Start mining for specified address, start_mining <addr> [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), "<ip-address> - 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 <begin_height> [<end_height>]");
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 <begin_height> [<end_height>]");
//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 <block_hash> | <block_height>");
m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_commands_handler::print_block_info, this, ph::_1), "Print block info, print_block <block_hash> | <block_height>");
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 <transaction_hash>");
m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_commands_handler::start_mining, this, ph::_1), "Start mining for specified address, start_mining <addr> [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), "<ip-address> - 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
}

View file

@ -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<bool>, 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();

View file

@ -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<bool> m_gui_deinitialize_done_1;
std::atomic<bool> m_backend_stopped_2;
std::atomic<bool> m_system_shutdown;
std::atomic<uint64_t> m_ui_dispatch_id_counter;
utils::threads_pool m_threads_pool;
std::string m_master_password;

@ -1 +1 @@
Subproject commit 709a1e6a3eb5ae7af48bbadf6b4c512b637b75b3
Subproject commit b091d45ad697db2d35e94de41be3f175bad0f71d

View file

@ -26,18 +26,18 @@ namespace nodetool
namespace
{
const command_line::arg_descriptor<std::string> arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"};
const command_line::arg_descriptor<std::string> arg_p2p_bind_port = {"p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)};
const command_line::arg_descriptor<uint32_t> 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<bool> arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"};
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"};
const command_line::arg_descriptor<std::vector<std::string> > 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<bool> arg_p2p_use_only_priority_nodes = {"use-only-priority-nodes", "Try to connect only to priority nodes"};
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"};
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
const command_line::arg_descriptor<bool> arg_p2p_offline_mode = { "offline-mode", "Don't connect to any node and reject any connections", false, true };
const command_line::arg_descriptor<bool> arg_p2p_disable_debug_reqs = { "disable-debug-p2p-requests", "Disable p2p debug requests", false, true };
const command_line::arg_descriptor<uint32_t> 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<std::string> arg_p2p_bind_ip ("p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0");
const command_line::arg_descriptor<std::string> arg_p2p_bind_port ("p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT));
const command_line::arg_descriptor<uint32_t> 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<bool> arg_p2p_allow_local_ip ("allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes");
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer ("add-peer", "Manually add peer to local peerlist");
const command_line::arg_descriptor<std::vector<std::string> > 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<bool> arg_p2p_use_only_priority_nodes ("use-only-priority-nodes", "Try to connect only to priority nodes");
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node ("seed-node", "Connect to a node to retrieve peer addresses, and disconnect");
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port ("hide-my-port", "Do not announce yourself as peerlist candidate");
const command_line::arg_descriptor<bool> arg_p2p_offline_mode ( "offline-mode", "Don't connect to any node and reject any connections");
const command_line::arg_descriptor<bool> arg_p2p_disable_debug_reqs ( "disable-debug-p2p-requests", "Disable p2p debug requests");
const command_line::arg_descriptor<uint32_t> arg_p2p_ip_auto_blocking ( "p2p-ip-auto-blocking", "Enable (1) or disable (0) peers auto-blocking by IP <0|1>. Default: 0", 1);
}
//-----------------------------------------------------------------------------------

View file

@ -22,9 +22,9 @@ namespace currency
{
namespace
{
const command_line::arg_descriptor<std::string> arg_rpc_bind_ip = {"rpc-bind-ip", "", "127.0.0.1"};
const command_line::arg_descriptor<std::string> arg_rpc_bind_port = {"rpc-bind-port", "", std::to_string(RPC_DEFAULT_PORT)};
const command_line::arg_descriptor<bool> arg_rpc_ignore_status = {"rpc-ignore-offline", "Let rpc calls despite online/offline status", false, true };
const command_line::arg_descriptor<std::string> arg_rpc_bind_ip ("rpc-bind-ip", "", "127.0.0.1");
const command_line::arg_descriptor<std::string> arg_rpc_bind_port ("rpc-bind-port", "", std::to_string(RPC_DEFAULT_PORT));
const command_line::arg_descriptor<bool> 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)
{

View file

@ -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<std::string> arg_wallet_file = {"wallet-file", "Use wallet <arg>", ""};
const command_line::arg_descriptor<std::string> arg_generate_new_wallet = {"generate-new-wallet", "Generate new wallet and save it to <arg> or <address>.wallet by default", ""};
const command_line::arg_descriptor<std::string> arg_generate_new_auditable_wallet = {"generate-new-auditable-wallet", "Generate new auditable wallet and store it to <arg>", ""};
const command_line::arg_descriptor<std::string> arg_daemon_address = {"daemon-address", "Use daemon instance at <host>:<port>", ""};
const command_line::arg_descriptor<std::string> arg_daemon_host = {"daemon-host", "Use daemon instance at host <arg> instead of localhost", ""};
const command_line::arg_descriptor<std::string> arg_password = {"password", "Wallet password", "", true};
const command_line::arg_descriptor<bool> arg_dont_refresh = { "no-refresh", "Do not refresh after load", false, true };
const command_line::arg_descriptor<bool> arg_dont_set_date = { "no-set-creation-date", "Do not set wallet creation date", false, false };
const command_line::arg_descriptor<int> arg_daemon_port = {"daemon-port", "Use daemon instance at port <arg> instead of default", 0};
const command_line::arg_descriptor<uint32_t> arg_log_level = {"set-log", "", 0, true};
const command_line::arg_descriptor<bool> arg_do_pos_mining = { "do-pos-mining", "Do PoS mining", false, false };
const command_line::arg_descriptor<std::string> 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<std::string> arg_restore_wallet = { "restore-wallet", "Restore wallet from seed phrase or tracking seed and save it to <arg>", "" };
const command_line::arg_descriptor<bool> arg_offline_mode = { "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)", false, true };
const command_line::arg_descriptor<std::string> arg_scan_for_wallet = { "scan-for-wallet", "", "", true };
const command_line::arg_descriptor<std::string> arg_addr_to_compare = { "addr-to-compare", "", "", true };
const command_line::arg_descriptor<std::string> arg_wallet_file ("wallet-file", "Use wallet <arg>", "");
const command_line::arg_descriptor<std::string> arg_generate_new_wallet ("generate-new-wallet", "Generate new wallet and save it to <arg> or <address>.wallet by default", "");
const command_line::arg_descriptor<std::string> arg_generate_new_auditable_wallet ("generate-new-auditable-wallet", "Generate new auditable wallet and store it to <arg>", "");
const command_line::arg_descriptor<std::string> arg_daemon_address ("daemon-address", "Use daemon instance at <host>:<port>", "");
const command_line::arg_descriptor<std::string> arg_daemon_host ("daemon-host", "Use daemon instance at host <arg> instead of localhost", "");
const command_line::arg_descriptor<std::string> arg_password ("password", "Wallet password");
const command_line::arg_descriptor<bool> arg_dont_refresh ( "no-refresh", "Do not refresh after load");
const command_line::arg_descriptor<bool> arg_dont_set_date ( "no-set-creation-date", "Do not set wallet creation date", false);
const command_line::arg_descriptor<int> arg_daemon_port ("daemon-port", "Use daemon instance at port <arg> instead of default", 0);
const command_line::arg_descriptor<uint32_t> arg_log_level ("set-log", "");
const command_line::arg_descriptor<bool> arg_do_pos_mining ( "do-pos-mining", "Do PoS mining", false);
const command_line::arg_descriptor<std::string> 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<std::string> arg_restore_wallet ( "restore-wallet", "Restore wallet from seed phrase or tracking seed and save it to <arg>", "" );
const command_line::arg_descriptor<bool> arg_offline_mode ( "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)");
const command_line::arg_descriptor<std::string> arg_scan_for_wallet ( "scan-for-wallet", "");
const command_line::arg_descriptor<std::string> arg_addr_to_compare ( "addr-to-compare", "");
const command_line::arg_descriptor<bool> arg_disable_tor_relay ( "disable-tor-relay", "Do PoS mining", false);
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
const command_line::arg_descriptor< std::vector<std::string> > 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 <threads_count> - 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 <payment_id_1> [<payment_id_2> ... <payment_id_N>] - Show payments <payment_id_1>, ... <payment_id_N>");
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 <mixin_count> <addr_1> <amount_1> [<addr_2> <amount_2> ... <addr_N> <amount_N>] [payment_id] - Transfer <amount_1>,... <amount_N> to <address_1>,... <address_N>, respectively. <mixin_count> is the number of transactions yours is indistinguishable from (from 0 to maximum available), <payment_id> is an optional HEX-encoded string");
m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), "set_log <level> - Change current log detalisation level, <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 <mixin_count> <address> <amount_lower_limit> [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 <threads_count> - 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 <payment_id_1> [<payment_id_2> ... <payment_id_N>] - Show payments <payment_id_1>, ... <payment_id_N>");
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 <mixin_count> <addr_1> <amount_1> [<addr_2> <amount_2> ... <addr_N> <amount_N>] [payment_id] - Transfer <amount_1>,... <amount_N> to <address_1>,... <address_N>, respectively. <mixin_count> is the number of transactions yours is indistinguishable from (from 0 to maximum available), <payment_id> is an optional HEX-encoded string");
m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this,ph::_1), "set_log <level> - Change current log detalisation level, <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 <mixin_count> <address> <amount_lower_limit> [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 [<payment_id>|<integrated_address] - encodes given payment_id along with wallet's address into an integrated address (random payment_id will be used if none is provided). Decodes given integrated_address into standard address");
m_cmd_binder.set_handler("show_seed", boost::bind(&simple_wallet::show_seed, this, _1), "Display secret 24 word phrase that could be used to recover this wallet");
m_cmd_binder.set_handler("spendkey", boost::bind(&simple_wallet::spendkey, this, _1), "Display secret spend key");
m_cmd_binder.set_handler("viewkey", boost::bind(&simple_wallet::viewkey, this, _1), "Display secret view key");
m_cmd_binder.set_handler("address", boost::bind(&simple_wallet::print_address, this,ph::_1), "Show current wallet public address");
m_cmd_binder.set_handler("integrated_address", boost::bind(&simple_wallet::integrated_address, this,ph::_1), "integrated_address [<payment_id>|<integrated_address] - encodes given payment_id along with wallet's address into an integrated address (random payment_id will be used if none is provided). Decodes given integrated_address into standard address");
m_cmd_binder.set_handler("show_seed", boost::bind(&simple_wallet::show_seed, this,ph::_1), "Display secret 24 word phrase that could be used to recover this wallet");
m_cmd_binder.set_handler("spendkey", boost::bind(&simple_wallet::spendkey, this,ph::_1), "Display secret spend key");
m_cmd_binder.set_handler("viewkey", boost::bind(&simple_wallet::viewkey, this,ph::_1), "Display secret view key");
m_cmd_binder.set_handler("get_tx_key", boost::bind(&simple_wallet::get_tx_key, this, _1), "Get transaction one-time secret key (r) for a given <txid>");
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 <txid>");
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 <filename> <password> - 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 <filename> <password> - save as watch-only wallet file.");
m_cmd_binder.set_handler("sign_transfer", boost::bind(&simple_wallet::sign_transfer, this, _1), "sign_transfer <unsgined_tx_file> <signed_tx_file> - 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 <signed_tx_file> - 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 <unsgined_tx_file> <signed_tx_file> - 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 <signed_tx_file> - 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<std::string>& args)
{
if (m_offline_mode)
@ -1710,6 +1740,21 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args)
}
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::tor_enable(const std::vector<std::string> &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<std::string> &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<std::string> &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);

View file

@ -86,6 +86,8 @@ namespace currency
bool sign_transfer(const std::vector<std::string> &args);
bool submit_transfer(const std::vector<std::string> &args);
bool sweep_below(const std::vector<std::string> &args);
bool tor_enable(const std::vector<std::string> &args);
bool tor_disable(const std::vector<std::string> &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;

View file

@ -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<bool> arg_stratum = {"stratum", "Stratum server: enable" };
const command_line::arg_descriptor<std::string> arg_stratum_bind_ip = {"stratum-bind-ip", "Stratum server: IP to bind", STRATUM_BIND_IP_DEFAULT };
const command_line::arg_descriptor<std::string> arg_stratum_bind_port = {"stratum-bind-port", "Stratum server: port to listen at", std::to_string(STRATUM_DEFAULT_PORT) };
const command_line::arg_descriptor<size_t> arg_stratum_threads = {"stratum-threads-count", "Stratum server: number of server threads", STRATUM_THREADS_COUNT_DEFAULT };
const command_line::arg_descriptor<bool> arg_stratum ("stratum", "Stratum server: enable" );
const command_line::arg_descriptor<std::string> arg_stratum_bind_ip ("stratum-bind-ip", "Stratum server: IP to bind", STRATUM_BIND_IP_DEFAULT );
const command_line::arg_descriptor<std::string> arg_stratum_bind_port ("stratum-bind-port", "Stratum server: port to listen at", std::to_string(STRATUM_DEFAULT_PORT) );
const command_line::arg_descriptor<size_t> arg_stratum_threads ("stratum-threads-count", "Stratum server: number of server threads", STRATUM_THREADS_COUNT_DEFAULT );
const command_line::arg_descriptor<std::string> 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<size_t> 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<uint64_t> 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<uint64_t> 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<uint64_t> arg_stratum_vdiff_target_min = {"stratum-vdiff-target-min", "Stratum server: minimum worker difficulty", VDIFF_TARGET_MIN_DEFAULT };
const command_line::arg_descriptor<uint64_t> arg_stratum_vdiff_target_max = {"stratum-vdiff-target-max", "Stratum server: maximum worker difficulty", VDIFF_TARGET_MAX_DEFAULT };
const command_line::arg_descriptor<uint64_t> 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<uint64_t> 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<uint64_t> 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<uint64_t> 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<bool> 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<uint64_t> arg_stratum_vdiff_target_min ("stratum-vdiff-target-min", "Stratum server: minimum worker difficulty", VDIFF_TARGET_MIN_DEFAULT );
const command_line::arg_descriptor<uint64_t> arg_stratum_vdiff_target_max ("stratum-vdiff-target-max", "Stratum server: maximum worker difficulty", VDIFF_TARGET_MAX_DEFAULT );
const command_line::arg_descriptor<uint64_t> 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<uint64_t> 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<uint64_t> 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<uint64_t> 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<bool> arg_stratum_always_online ( "stratum-always-online", "Stratum server consider the core being synchronized regardless of online status, useful for debugging with --offline-mode" );
//==============================================================================================================================

View file

@ -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 "]"

View file

@ -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; }
};
}

View file

@ -13,6 +13,7 @@
#include <iostream>
#include <boost/utility/value_init.hpp>
#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<transfer_details_extra_option_htlc_info>(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::vector<currency::tx_
}
return needed_money;
}
//----------------------------------------------------------------------------------------------------------------
void wallet2::set_disable_tor_relay(bool disable)
{
m_disable_tor_relay = disable;
}
//----------------------------------------------------------------------------------------------------------------
void wallet2::notify_state_change(const std::string& state_code, const std::string& details)
{
m_wcallback->on_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<currency::tx_destination_entry>& destinations,
const std::vector<uint64_t>& selected_transfers)

View file

@ -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<uint64_t>& 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;

View file

@ -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();
}

View file

@ -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;

View file

@ -43,10 +43,10 @@ using namespace epee;
namespace tools
{
//-----------------------------------------------------------------------------------
const command_line::arg_descriptor<std::string> 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<std::string> 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<std::string> wallet_rpc_server::arg_miner_text_info = { "miner-text-info", "Wallet password", "", true };
const command_line::arg_descriptor<bool> 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<std::string> 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<std::string> 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<std::string> wallet_rpc_server::arg_miner_text_info ( "miner-text-info", "Wallet password");
const command_line::arg_descriptor<bool> 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)
{

View file

@ -51,15 +51,16 @@
#define HTTP_PROXY_TIMEOUT 2000
#define HTTP_PROXY_ATTEMPTS_COUNT 1
const command_line::arg_descriptor<bool> arg_alloc_win_console = { "alloc-win-console", "Allocates debug console with GUI", false };
const command_line::arg_descriptor<std::string> arg_html_folder = { "html-path", "Manually set GUI html folder path", "", true };
const command_line::arg_descriptor<std::string> arg_xcode_stub = { "-NSDocumentRevisionsDebugMode", "Substitute for xcode bug", "", true };
const command_line::arg_descriptor<bool> arg_enable_gui_debug_mode = { "gui-debug-mode", "Enable debug options in GUI", false, true };
const command_line::arg_descriptor<uint32_t> arg_qt_remote_debugging_port = { "remote-debugging-port", "Specify port for Qt remote debugging", 30333, true };
const command_line::arg_descriptor<std::string> arg_remote_node = { "remote-node", "Switch GUI to work with remote node instead of local daemon", "", true };
const command_line::arg_descriptor<bool> arg_enable_qt_logs = { "enable-qt-logs", "Forward Qt log messages into main log", false, true };
const command_line::arg_descriptor<bool> arg_alloc_win_console ( "alloc-win-console", "Allocates debug console with GUI", false );
const command_line::arg_descriptor<std::string> arg_html_folder ( "html-path", "Manually set GUI html folder path");
const command_line::arg_descriptor<std::string> arg_xcode_stub ( "-NSDocumentRevisionsDebugMode", "Substitute for xcode bug");
const command_line::arg_descriptor<bool> arg_enable_gui_debug_mode ( "gui-debug-mode", "Enable debug options in GUI");
const command_line::arg_descriptor<uint32_t> arg_qt_remote_debugging_port ( "remote-debugging-port", "Specify port for Qt remote debugging");
const command_line::arg_descriptor<std::string> arg_remote_node ( "remote-node", "Switch GUI to work with remote node instead of local daemon");
const command_line::arg_descriptor<bool> arg_enable_qt_logs ( "enable-qt-logs", "Forward Qt log messages into main log");
const command_line::arg_descriptor<bool> arg_disable_logs_init("disable-logs-init", "Disable log initialization in GUI");
const command_line::arg_descriptor<std::string> arg_qt_dev_tools = { "qt-dev-tools", "Enable main web page inspection with Chromium DevTools, <vertical|horizontal>[,scale], e.g. \"horizontal,1.3\"", "", false };
const command_line::arg_descriptor<std::string> arg_qt_dev_tools ( "qt-dev-tools", "Enable main web page inspection with Chromium DevTools, <vertical|horizontal>[,scale], e.g. \"horizontal,1.3\"", "");
const command_line::arg_descriptor<bool> 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);

View file

@ -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<bool> m_is_pos_allowed;
std::atomic<bool> m_use_tor;
std::map<size_t, wallet_vs_options> m_wallets;

View file

@ -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;

View file

@ -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; \

View file

@ -21,13 +21,13 @@ namespace po = boost::program_options;
namespace
{
const command_line::arg_descriptor<std::string> arg_test_data_path = {"test-data-path", "", ""};
const command_line::arg_descriptor<bool> arg_generate_test_data = {"generate-test-data", ""};
const command_line::arg_descriptor<bool> arg_play_test_data = {"play-test-data", ""};
const command_line::arg_descriptor<bool> arg_generate_and_play_test_data = {"generate-and-play-test-data", ""};
const command_line::arg_descriptor<bool> arg_test_transactions = {"test-transactions", ""};
const command_line::arg_descriptor<std::string> arg_run_single_test = {"run-single-test", "" };
const command_line::arg_descriptor<bool> arg_enable_debug_asserts = {"enable-debug-asserts", "" };
const command_line::arg_descriptor<std::string> arg_test_data_path ("test-data-path", "", "");
const command_line::arg_descriptor<bool> arg_generate_test_data ("generate-test-data", "");
const command_line::arg_descriptor<bool> arg_play_test_data ("play-test-data", "");
const command_line::arg_descriptor<bool> arg_generate_and_play_test_data ("generate-and-play-test-data", "");
const command_line::arg_descriptor<bool> arg_test_transactions ("test-transactions", "");
const command_line::arg_descriptor<std::string> arg_run_single_test ("run-single-test", "" );
const command_line::arg_descriptor<bool> 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<test_event_entry> 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);

View file

@ -922,6 +922,7 @@ bool hard_fork_2_awo_wallets_basic_test<before_hf_2>::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<before_hf_2>::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<before_hf_2>::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, "");

View file

@ -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()

View file

@ -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();

View file

@ -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)
{

View file

@ -83,6 +83,7 @@ std::shared_ptr<tools::wallet2> 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;
}

View file

@ -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<std::pair<std::string, bool_func_ptr_t>> 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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(n)), ((x.m_u64[0] & (1ull << (n - 0))) != 0));
for (size_t n = 64; n < 128; ++n)
ASSERT_EQ(x.get_bit(static_cast<uint8_t>(n)), ((x.m_u64[1] & (1ull << (n - 64))) != 0));
for (size_t n = 128; n < 192; ++n)
ASSERT_EQ(x.get_bit(static_cast<uint8_t>(n)), ((x.m_u64[2] & (1ull << (n - 128))) != 0));
for (size_t n = 192; n < 256; ++n)
ASSERT_EQ(x.get_bit(static_cast<uint8_t>(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<size_t> 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;
}

View file

@ -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)
// <a, ((y, y^2, y^3, ...) o b)> = <c, (y, y^2, y^3, ...)> (<> -- 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<point_t> commitments;
uint8_t err = 0;
bool r = bpp_gen<bpp_crypto_trait_zano<>>(values, masks, bpp_sig, commitments, &err);
ASSERT_TRUE(r);
return true;
}
TEST(bpp, two)
{
std::vector<bpp_signature> signatures_vector;
signatures_vector.reserve(10);
std::vector<std::vector<point_t>> commitments_vector;
commitments_vector.reserve(10);
std::vector<bpp_sig_commit_ref_t> 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<point_t>& commitments = commitments_vector.back();
scalar_vec_t values = { 5 };
scalar_vec_t masks = { scalar_t(77 + 256 * 77) };
r = bpp_gen<bpp_crypto_trait_zano<>>(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<point_t>& 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<bpp_crypto_trait_zano<>>(values, masks, bpp_sig, commitments, &err);
ASSERT_TRUE(r);
sigs.emplace_back(bpp_sig, commitments);
}
r = bpp_verify<bpp_crypto_trait_zano<>>(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<bpp_signature> signatures_vector;
signatures_vector.reserve(10);
std::vector<std::vector<point_t>> commitments_vector;
commitments_vector.reserve(10);
std::vector<bpp_sig_commit_ref_t> 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<point_t>& commitments = commitments_vector.back();
scalar_vec_t values = { 5 };
scalar_vec_t masks = { scalar_t(77 + 256 * 77) };
r = bpp_gen<bpp_crypto_trait_zano<>>(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<point_t>& 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<bpp_crypto_trait_zano<>>(values, masks, bpp_sig, commitments, &err);
ASSERT_TRUE(r);
sig_ñommit_refs.emplace_back(bpp_sig, commitments);
}
r = bpp_verify<bpp_crypto_trait_zano<>>(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<point_t> commitments;
uint8_t err = 0;
bool r = bppe_gen<bpp_crypto_trait_zano<>>(values, masks, masks_2, bppe_sig, commitments, &err);
ASSERT_TRUE(r);
return true;
}
TEST(bppe, two)
{
std::vector<bppe_signature> signatures_vector;
signatures_vector.reserve(10);
std::vector<std::vector<point_t>> commitments_vector;
commitments_vector.reserve(10);
std::vector<bppe_sig_commit_ref_t> 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<point_t>& 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<bpp_crypto_trait_zano<>>(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<point_t>& 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<bpp_crypto_trait_zano<>>(values, masks, masks2, bppe_sig, commitments, &err);
ASSERT_TRUE(r);
sigs.emplace_back(bppe_sig, commitments);
}
r = bppe_verify<bpp_crypto_trait_zano<>>(sigs, &err);
ASSERT_TRUE(r);
return true;
}

View file

@ -23,40 +23,40 @@ using namespace epee;
namespace po = boost::program_options;
const command_line::arg_descriptor<std::string> arg_test_core_prepare_and_store = { "prepare-and-store-events-to-file", "", "", true };
const command_line::arg_descriptor<std::string> arg_test_core_load_and_replay = { "load-and-replay-events-from-file", "", "", true };
const command_line::arg_descriptor<std::string> arg_test_core_prepare_and_store ( "prepare-and-store-events-to-file", "");
const command_line::arg_descriptor<std::string> arg_test_core_load_and_replay ( "load-and-replay-events-from-file", "");
namespace
{
const command_line::arg_descriptor<bool> arg_test_transactions_flow = {"test-transactions-flow", ""};
const command_line::arg_descriptor<bool> arg_test_miniupnp = {"test-miniupnp", ""};
const command_line::arg_descriptor<bool> arg_test_core_concurrency = {"test-core-concurrency", ""};
const command_line::arg_descriptor<bool> arg_test_transactions_flow ("test-transactions-flow", "");
const command_line::arg_descriptor<bool> arg_test_miniupnp ("test-miniupnp", "");
const command_line::arg_descriptor<bool> arg_test_core_concurrency ("test-core-concurrency", "");
const command_line::arg_descriptor<std::string> arg_working_folder = {"working-folder", "", "."};
const command_line::arg_descriptor<std::string> arg_source_wallet = {"source-wallet", "", "", true};
const command_line::arg_descriptor<std::string> arg_dest_wallet = {"dest-wallet", "", "", true};
const command_line::arg_descriptor<std::string> arg_source_wallet_pass = {"source-wallet-pass", "", "", true};
const command_line::arg_descriptor<std::string> arg_dest_wallet_pass = {"dest-wallet-pass", "", "", true};
const command_line::arg_descriptor<std::string> arg_working_folder ("working-folder", "", ".");
const command_line::arg_descriptor<std::string> arg_source_wallet ("source-wallet", "");
const command_line::arg_descriptor<std::string> arg_dest_wallet ("dest-wallet", "");
const command_line::arg_descriptor<std::string> arg_source_wallet_pass ("source-wallet-pass", "");
const command_line::arg_descriptor<std::string> arg_dest_wallet_pass ("dest-wallet-pass", "");
const command_line::arg_descriptor<std::string> arg_daemon_addr_a = {"daemon-addr-a", "", "127.0.0.1:8080"};
const command_line::arg_descriptor<std::string> arg_daemon_addr_b = {"daemon-addr-b", "", "127.0.0.1:8082"};
const command_line::arg_descriptor<std::string> arg_daemon_addr_a ("daemon-addr-a", "", "127.0.0.1:8080");
const command_line::arg_descriptor<std::string> arg_daemon_addr_b ("daemon-addr-b", "", "127.0.0.1:8082");
const command_line::arg_descriptor<uint64_t> arg_transfer_amount = {"transfer-amount", "", 60000000000000};
const command_line::arg_descriptor<size_t> arg_mix_in_factor = {"mix-in-factor", "", 10};
const command_line::arg_descriptor<size_t> arg_tx_count = {"tx-count", "", 100};
const command_line::arg_descriptor<size_t> arg_tx_per_second = {"tx-per-second", "", 20};
const command_line::arg_descriptor<size_t> arg_test_repeat_count = {"test-repeat-count", "", 1};
const command_line::arg_descriptor<size_t> arg_action = {"action", "", 0 };
const command_line::arg_descriptor<size_t> arg_max_tx_in_pool = { "max-tx-in-pool", "", 10000 };
const command_line::arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory", "."};
const command_line::arg_descriptor<size_t> arg_wthreads = {"wthreads", "number of writing threads to run", 1};
const command_line::arg_descriptor<size_t> arg_rthreads = {"rthreads", "number of reading threads to run", 1};
const command_line::arg_descriptor<size_t> arg_blocks = {"blocks", "number of blocks to generate", 250};
const command_line::arg_descriptor<size_t> arg_generate_test_genesis_json = { "generate-test-genesis-json", "generates test genesis json, specify amount of accounts", 0, true };
const command_line::arg_descriptor<bool> arg_deadlock_guard = { "test-deadlock-guard", "Do deadlock guard test", false, true };
const command_line::arg_descriptor<std::string> arg_difficulty_analysis = { "difficulty-analysis", "Do difficulty analysis", "", true };
const command_line::arg_descriptor<bool> arg_test_plain_wallet = { "test-plainwallet", "Do testing of plain wallet interface", false, true };
const command_line::arg_descriptor<std::string> arg_crypto_tests = { "crypto-tests", "Run experimental crypto tests", "", true };
const command_line::arg_descriptor<uint64_t> arg_transfer_amount ("transfer-amount", "", 60000000000000);
const command_line::arg_descriptor<size_t> arg_mix_in_factor ("mix-in-factor", "", 10);
const command_line::arg_descriptor<size_t> arg_tx_count ("tx-count", "", 100);
const command_line::arg_descriptor<size_t> arg_tx_per_second ("tx-per-second", "", 20);
const command_line::arg_descriptor<size_t> arg_test_repeat_count ("test-repeat-count", "", 1);
const command_line::arg_descriptor<size_t> arg_action ("action", "", 0 );
const command_line::arg_descriptor<size_t> arg_max_tx_in_pool ( "max-tx-in-pool", "", 10000 );
const command_line::arg_descriptor<std::string> arg_data_dir ("data-dir", "Specify data directory", ".");
const command_line::arg_descriptor<size_t> arg_wthreads ("wthreads", "number of writing threads to run", 1);
const command_line::arg_descriptor<size_t> arg_rthreads ("rthreads", "number of reading threads to run", 1);
const command_line::arg_descriptor<size_t> arg_blocks ("blocks", "number of blocks to generate", 250);
const command_line::arg_descriptor<size_t> arg_generate_test_genesis_json ( "generate-test-genesis-json", "generates test genesis json, specify amount of accounts");
const command_line::arg_descriptor<bool> arg_deadlock_guard ( "test-deadlock-guard", "Do deadlock guard test");
const command_line::arg_descriptor<std::string> arg_difficulty_analysis ( "difficulty-analysis", "Do difficulty analysis");
const command_line::arg_descriptor<bool> arg_test_plain_wallet ( "test-plainwallet", "Do testing of plain wallet interface");
const command_line::arg_descriptor<std::string> 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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 ..

View file

@ -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"

View file

@ -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%

View file

@ -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

View file

@ -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" ".."

View file

@ -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" ".."
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" ".."

View file

@ -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 ".."
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 ".."

View file

@ -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 ".."
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 ".."

View file

@ -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 ".."
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 ".."

View file

@ -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 ".."

View file

@ -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"

View file

@ -0,0 +1 @@
{"method": "get_alias_details","params": {"alias": "zoidb"}}