1
0
Fork 0
forked from lthn/blockchain

Merge branch 'release'

This commit is contained in:
sowle 2020-04-16 12:25:34 +03:00
commit fc0f6cba7f
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
111 changed files with 4562 additions and 1054 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
/build*
/_builds/*
/tags
.DS_Store
._.DS_Store

View file

@ -5,14 +5,28 @@ PROJECT(Zano)
set(VERSION "1.0")
if(POLICY CMP0043)
cmake_policy(SET CMP0043 OLD)
endif()
# if(POLICY CMP0043)
# cmake_policy(SET CMP0043 OLD)
# endif()
if(POLICY CMP0020)
cmake_policy(SET CMP0020 OLD)
endif()
# if(POLICY CMP0020)
# cmake_policy(SET CMP0020 OLD)
# endif()
if(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
add_definitions(-DMOBILE_WALLET_BUILD)
if(CMAKE_SYSTEM_NAME STREQUAL "iOS" )
add_definitions(-DIOS_BUILD)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
add_definitions(-DANDROID_BUILD)
message("Android sdk prefix: ${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}")
message("Android CMAKE_CXX_COMPILER prefix: ${CMAKE_CXX_COMPILER}")
message("Android ANDROID_LD: ${ANDROID_LD}")
endif()
endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@ -24,7 +38,13 @@ if (UNIX AND NOT APPLE)
endif()
else()
# multi configurations for MSVC and XCode
set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
set(CMAKE_CONFIGURATION_TYPES "Release")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
else()
set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
endif()
endif()
message("Generated with config types: ${CMAKE_CONFIGURATION_TYPES}, and built type: ${CMAKE_BUILD_TYPE}")
@ -83,16 +103,16 @@ else()
# set(WARNINGS "${WARNINGS} -Werror")
# endif()
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
set(WARNINGS "${WARNINGS} -Wno-shift-count-overflow -Wno-error=mismatched-tags -Wno-error=null-conversion -Wno-overloaded-shift-op-parentheses -Wno-error=shift-count-overflow -Wno-error=tautological-constant-out-of-range-compare -Wno-error=unused-private-field -Wno-error=unneeded-internal-declaration")
set(WARNINGS "${WARNINGS} -Wno-implicit-function-declaration -Wno-shift-count-overflow -Wno-error=mismatched-tags -Wno-error=null-conversion -Wno-overloaded-shift-op-parentheses -Wno-error=shift-count-overflow -Wno-error=tautological-constant-out-of-range-compare -Wno-error=unused-private-field -Wno-error=unneeded-internal-declaration")
else()
set(WARNINGS "${WARNINGS} -Wno-error=write-strings -Wlogical-op -Wno-error=maybe-uninitialized")
endif()
# Since gcc 4.9 the LTO format is non-standard (slim), so we need the gcc-specific ar and ranlib binaries
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.0))
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.0) AND NOT (CMAKE_SYSTEM_NAME STREQUAL "Android"))
set(CMAKE_AR "gcc-ar")
set(CMAKE_RANLIB "gcc-ranlib")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT APPLE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT APPLE AND NOT (CMAKE_SYSTEM_NAME STREQUAL "Android"))
set(CMAKE_AR "llvm-ar")
set(CMAKE_RANLIB "llvm-ranlib")
endif()
@ -161,11 +181,24 @@ if(STATIC)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
endif()
find_package(Boost 1.53 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale)
if(MSVC AND (${Boost_MAJOR_VERSION} EQUAL 1) AND (${Boost_MINOR_VERSION} EQUAL 54))
message(SEND_ERROR "Boost version 1.54 is unsupported, more details are available here http://goo.gl/RrCFmA")
message("CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
set(Boost_INCLUDE_DIRS "/Users/roky/projects/Zano/mobile_repo/ofxiOSBoost/libs/boost/include")
set(Boost_LIBRARY_DIRS "/Users/roky/projects/Zano/mobile_repo/ofxiOSBoost/libs/boost/ios/")
set(Boost_LIBRARIES "libboost.a")
set(Boost_VERSION "ofxiOSBoost 1.60.0")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
set(Boost_INCLUDE_DIRS "/Users/roky/projects/Zano/mobile_repo/Boost-for-Android-Prebuilt/1.69.0/include")
set(Boost_LIBRARY_DIRS "/Users/roky/projects/Zano/mobile_repo/Boost-for-Android-Prebuilt/1.69.0/libs/llvm/${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")
set(Boost_VERSION "PurpleI2PBoost 1.69.0")
else()
find_package(Boost 1.55 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale)
endif()
message(STATUS "Boost: ${Boost_VERSION} from ${Boost_LIBRARY_DIRS}")
@ -174,7 +207,7 @@ if(MINGW)
set(Boost_LIBRARIES "${Boost_LIBRARIES};ws2_32;mswsock")
elseif(NOT MSVC)
if(NOT APPLE)
set(Boost_LIBRARIES "${Boost_LIBRARIES};rt")
set(Boost_LIBRARIES "${Boost_LIBRARIES};")
if(STATIC)
message("NOTICE: Including static ICU libraries")
set(Boost_LIBRARIES "${Boost_LIBRARIES};icui18n.a;icuuc.a;icudata.a;dl")

View file

@ -1,4 +1,3 @@
[![Coverity Scan](https://scan.coverity.com/projects/18767/badge.svg)](https://scan.coverity.com/projects/zanoproject)
[![Discord](https://img.shields.io/discord/538361472691077130?label=discord&logo=discord)](https://discord.gg/wE3rmYY)
@ -18,39 +17,67 @@ Be sure to properly clone the repository:
| llvm/clang (Linux) | UNKNOWN | 7.0.1 | 8.0.0 |
| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2015 (14.0 update 1) | 2015 (14.0 update 3) | 2017 (15.5.7) |
| [XCode](https://developer.apple.com/downloads/) (macOS) | 7.3.1 | 9.2 | 9.2 |
| [CMake](https://cmake.org/download/) | 2.8.6 | 3.4.1 | 3.11.0 |
| [Boost](https://www.boost.org/users/download/) | 1.56 | 1.60 | 1.66 |
| [Qt](https://download.qt.io/archive/qt/) (only for GUI) | 5.8.0 | 5.9.1 | 5.10.1 |
| [CMake](https://cmake.org/download/) | 2.8.6 | 3.15.5 | 3.15.5 |
| [Boost](https://www.boost.org/users/download/) | 1.56 | 1.68 | 1.68 |
| [Qt](https://download.qt.io/archive/qt/) (only for GUI) | 5.8.0 | 5.11.2 | 5.13.2 |
### Linux
Recommended OS version: Ubuntu 17.04 LTS.
Recommended OS version: Ubuntu 18.04 LTS.
1. For server version: \
`$ sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git libboost-all-dev screen`\
For GUI version:\
`$ sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git libboost-all-dev screen mesa-common-dev libglu1-mesa-dev qt5-default qtwebengine5-dev`
1. Prerequisites
1. Prerequisites for server version:
sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen
1. Prerequisites for GUI version:
2. Building binaries \
2.1. Building daemon and simplewallet: \
  `$ cd zano/ && make -j` \
  or \
  `$ cd zano && mkdir build && cd build `\
  `$ cmake .. `\
  `$ make -j daemon simplewallet` \
2.2. Building GUI: \
  `$ cd zano/ && make -j gui ` \
  or \
  `$ cd zano && mkdir build && cd build `\
  `$ cmake -D BUILD_GUI=ON .. `\
  `$ make -j Zano` \
  `$ rsync -haP ~/zano/src/gui/qt-daemon/html ~/zano/build/src` \
NOTICE: If you are building on machine with relatively small anount of RAM(small VPS for example, less then 16GB) and without proper setting of virtual memory, then be careful with setting `-j` option, this may cause compiller crashes.
3. Look for the binaries, including the `Zano` GUI, in the build directory
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`
2. Download and build Boost
wget https://dl.bintray.com/boostorg/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
./b2
3. Install Qt
wget https://download.qt.io/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 WebEngine module!
4. Set `BOOST_ROOT` and `QT_PREFIX_PATH` envinorment variables\
For instance, by adding these lines to `~/.bashrc`:
export BOOST_ROOT=/home/user/boost_1_68_0
export QT_PREFIX_PATH=/home/user/Qt5.11.2/5.11.2/gcc_64
5. Building binaries
1. Building daemon and simplewallet:
cd zano/ && make -j1
or
cd zano && mkdir build && cd build
cmake ..
make -j1 daemon simplewallet
**NOTICE**: If you are building on machine with relatively high anount of RAM or with proper setting of virtual memory, then you can use `-j2` or `-j` option to speed up the building process. Use with caution.
1. Building GUI:
cd zano
utils/build_sript_linux.sh
7. Look for the binaries in `build` folder
### Windows
Recommended OS version: Windows 7 x64.
1. Install required prerequisites.
1. Install required prerequisites (Boost, Qt, CMake).
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.
4. Go to the build folder and open generated Zano.sln in MSVC.
@ -80,3 +107,4 @@ To build GUI application:
h. Unfold the certificate in Keychain Access window and double click underlying private key "Zano". Select "Access Control" tab, then select "Allow all applications to access this item". Click "Save Changes".
2. Revise building script, comment out unwanted steps and run it: `utils/build_script_mac_osx.sh`
3. The application should be here: `/buid_mac_osx_64/release/src`

View file

@ -1,17 +1,24 @@
set(UPNPC_BUILD_STATIC ON CACHE BOOL "Build static library")
set(UPNPC_BUILD_SHARED OFF CACHE BOOL "Build shared library")
set(UPNPC_BUILD_TESTS OFF CACHE BOOL "Build test executables")
add_subdirectory(miniupnp/miniupnpc)
add_subdirectory(zlib)
add_subdirectory(db)
add_subdirectory(ethereum)
if(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
message("excluded upnp support for IOS build")
return()
endif()
add_subdirectory(miniupnp/miniupnpc)
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")
set_property(TARGET upnpc-static mdbx_chk mdbx_copy mdbx_dump mdbx_load mdbx_stat minigzip zlib example PROPERTY FOLDER "unused")
set_property(TARGET upnpc-static mdbx_chk mdbx_copy mdbx_dump mdbx_load mdbx_stat PROPERTY FOLDER "unused")
if(MSVC)
set_property(TARGET ntdll_extra_target PROPERTY FOLDER "unused")
endif()

View file

@ -1,4 +1,11 @@
if(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
message("excluded db support for IOS build")
return()
endif()
message("DB ENGINE: lmdb")
add_subdirectory(liblmdb)
if(MSVC)

View file

@ -51,7 +51,7 @@
#include <sys/file.h>
#endif
#include "include_base_utils.h"
//#include "include_base_utils.h"
#include "string_coding.h"
namespace epee

View file

@ -29,9 +29,9 @@
#ifndef _GZIP_ENCODING_H_
#define _GZIP_ENCODING_H_
#include "boost/core/ignore_unused.hpp"
#include "net/http_client_base.h"
#include "zlib/zlib.h"
//#include "http.h"
namespace epee
@ -41,186 +41,329 @@ namespace net_utils
class content_encoding_gzip: public i_sub_handler
{
public:
/*! \brief
* Function content_encoding_gzip : Constructor
*
*/
inline
content_encoding_gzip(i_target_handler* powner_filter, bool is_deflate_mode = false):m_powner_filter(powner_filter),
m_is_stream_ended(false),
m_is_deflate_mode(is_deflate_mode),
m_is_first_update_in(true)
{
memset(&m_zstream_in, 0, sizeof(m_zstream_in));
memset(&m_zstream_out, 0, sizeof(m_zstream_out));
int ret = 0;
if(is_deflate_mode)
{
ret = inflateInit(&m_zstream_in);
ret = deflateInit(&m_zstream_out, Z_DEFAULT_COMPRESSION);
}else
{
ret = inflateInit2(&m_zstream_in, 0x1F);
ret = deflateInit2(&m_zstream_out, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8, Z_DEFAULT_STRATEGY);
}
}
/*! \brief
* Function content_encoding_gzip : Destructor
*
*/
inline
~content_encoding_gzip()
{
inflateEnd(& m_zstream_in );
deflateEnd(& m_zstream_out );
}
/*! \brief
* Function update_in : Entry point for income data
*
*/
inline
virtual bool update_in( std::string& piece_of_transfer)
{
class content_encoding_gzip: public i_sub_handler
{
public:
/*! \brief
* Function content_encoding_gzip : Constructor
*
*/
inline
content_encoding_gzip(i_target_handler* powner_filter, bool is_deflate_mode = false, int compression_level = Z_DEFAULT_COMPRESSION) :m_powner_filter(powner_filter),
m_is_stream_ended(false),
m_is_deflate_mode(is_deflate_mode),
m_is_first_update_in(true)
{
memset(&m_zstream_in, 0, sizeof(m_zstream_in));
memset(&m_zstream_out, 0, sizeof(m_zstream_out));
int ret = 0;
boost::ignore_unused(ret);
if(is_deflate_mode)
{
ret = inflateInit(&m_zstream_in);
ret = deflateInit(&m_zstream_out, compression_level);
}else
{
ret = inflateInit2(&m_zstream_in, 0x1F);
ret = deflateInit2(&m_zstream_out, compression_level, Z_DEFLATED, 0x1F, 8, Z_DEFAULT_STRATEGY);
}
}
/*! \brief
* Function content_encoding_gzip : Destructor
*
*/
inline
~content_encoding_gzip()
{
inflateEnd(& m_zstream_in );
deflateEnd(& m_zstream_out );
}
/*! \brief
* Function update_in : Entry point for income data
*
*/
inline
virtual bool update_in( std::string& piece_of_transfer)
{
bool is_first_time_here = m_is_first_update_in;
m_is_first_update_in = false;
bool is_first_time_here = m_is_first_update_in;
m_is_first_update_in = false;
if(m_pre_decode.size())
m_pre_decode += piece_of_transfer;
else
m_pre_decode.swap(piece_of_transfer);
piece_of_transfer.clear();
if(m_pre_decode.size())
m_pre_decode += piece_of_transfer;
else
m_pre_decode.swap(piece_of_transfer);
piece_of_transfer.clear();
std::string decode_summary_buff;
std::string decode_summary_buff;
size_t ungzip_size = m_pre_decode.size() * 0x30;
std::string current_decode_buff(ungzip_size, 'X');
size_t ungzip_size = m_pre_decode.size() * 0x30;
std::string current_decode_buff(ungzip_size, 'X');
auto slh = misc_utils::create_scope_leave_handler([&]() { m_zstream_in.next_out = nullptr; } ); // make sure local pointer to current_decode_buff.data() won't be used out of this scope
//Here the cycle is introduced where we unpack the buffer, the cycle is required
//because of the case where if after unpacking the data will exceed the awaited size, we will not halt with error
bool continue_unpacking = true;
bool first_step = true;
while(m_pre_decode.size() && continue_unpacking)
{
//Here the cycle is introduced where we unpack the buffer, the cycle is required
//because of the case where if after unpacking the data will exceed the awaited size, we will not halt with error
bool continue_unpacking = true;
bool first_step = true;
while(m_pre_decode.size() && continue_unpacking)
{
//fill buffers
m_zstream_in.next_in = (Bytef*)m_pre_decode.data();
m_zstream_in.avail_in = (uInt)m_pre_decode.size();
m_zstream_in.next_out = (Bytef*)current_decode_buff.data();
m_zstream_in.avail_out = (uInt)ungzip_size;
//fill buffers
m_zstream_in.next_in = (Bytef*)m_pre_decode.data();
m_zstream_in.avail_in = (uInt)m_pre_decode.size();
m_zstream_in.next_out = (Bytef*)current_decode_buff.data();
m_zstream_in.avail_out = (uInt)ungzip_size;
int flag = Z_SYNC_FLUSH;
int ret = inflate(&m_zstream_in, flag);
CHECK_AND_ASSERT_MES(ret>=0 || m_zstream_in.avail_out ||m_is_deflate_mode, false, "content_encoding_gzip::update_in() Failed to inflate. err = " << ret);
int flag = Z_NO_FLUSH;
int ret = inflate(&m_zstream_in, flag);
CHECK_AND_ASSERT_MES(ret>=0 || m_zstream_in.avail_out ||m_is_deflate_mode, false, "content_encoding_gzip::update_in() Failed to inflate. ret = " << ret << ", msg: " << (m_zstream_in.msg ? m_zstream_in.msg : ""));
if(Z_STREAM_END == ret)
m_is_stream_ended = true;
else if(Z_DATA_ERROR == ret && is_first_time_here && m_is_deflate_mode&& first_step)
{
// some servers (notably Apache with mod_deflate) don't generate zlib headers
// insert a dummy header and try again
static char dummy_head[2] =
{
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
inflateReset(&m_zstream_in);
m_zstream_in.next_in = (Bytef*) dummy_head;
m_zstream_in.avail_in = sizeof(dummy_head);
if(Z_STREAM_END == ret)
m_is_stream_ended = true;
else if(Z_DATA_ERROR == ret && is_first_time_here && m_is_deflate_mode&& first_step)
{
// some servers (notably Apache with mod_deflate) don't generate zlib headers
// insert a dummy header and try again
static char dummy_head[2] =
{
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
inflateReset(&m_zstream_in);
m_zstream_in.next_in = (Bytef*) dummy_head;
m_zstream_in.avail_in = sizeof(dummy_head);
ret = inflate(&m_zstream_in, Z_NO_FLUSH);
if (ret != Z_OK)
{
LOCAL_ASSERT(0);
m_pre_decode.swap(piece_of_transfer);
return false;
}
m_zstream_in.next_in = (Bytef*)m_pre_decode.data();
m_zstream_in.avail_in = (uInt)m_pre_decode.size();
ret = inflate(&m_zstream_in, Z_NO_FLUSH);
if (ret != Z_OK)
{
LOCAL_ASSERT(0);
m_pre_decode.swap(piece_of_transfer);
return false;
}
m_zstream_in.next_in = (Bytef*)m_pre_decode.data();
m_zstream_in.avail_in = (uInt)m_pre_decode.size();
ret = inflate(&m_zstream_in, Z_NO_FLUSH);
if (ret != Z_OK)
{
LOCAL_ASSERT(0);
m_pre_decode.swap(piece_of_transfer);
return false;
}
}
ret = inflate(&m_zstream_in, Z_NO_FLUSH);
if (ret != Z_OK)
{
LOCAL_ASSERT(0);
m_pre_decode.swap(piece_of_transfer);
return false;
}
}
else
{
CHECK_AND_ASSERT_MES(Z_DATA_ERROR != ret, false, "content_encoding_gzip::update_in() Failed to inflate. err = Z_DATA_ERROR");
}
//leave only unpacked part in the output buffer to start with it the next time
m_pre_decode.erase(0, m_pre_decode.size()-m_zstream_in.avail_in);
//if decoder gave nothing to return, then everything is ahead, now simply break
if(ungzip_size == m_zstream_in.avail_out)
break;
//leave only unpacked part in the output buffer to start with it the next time
m_pre_decode.erase(0, m_pre_decode.size()-m_zstream_in.avail_in);
//if decoder gave nothing to return, then everything is ahead, now simply break
if(ungzip_size == m_zstream_in.avail_out)
break;
//decode_buff currently stores data parts that were unpacked, fix this size
current_decode_buff.resize(ungzip_size - m_zstream_in.avail_out);
if(decode_summary_buff.size())
decode_summary_buff += current_decode_buff;
else
current_decode_buff.swap(decode_summary_buff);
//decode_buff currently stores data parts that were unpacked, fix this size
current_decode_buff.resize(ungzip_size - m_zstream_in.avail_out);
if(decode_summary_buff.size())
decode_summary_buff += current_decode_buff;
else
current_decode_buff.swap(decode_summary_buff);
current_decode_buff.resize(ungzip_size);
first_step = false;
}
current_decode_buff.resize(ungzip_size);
first_step = false;
}
//Process these data if required
bool res = true;
//Process these data if required
return m_powner_filter->handle_target_data(decode_summary_buff);
}
/*! \brief
* Function stop : Entry point for stop signal and flushing cached data buffer.
*
*/
inline
virtual void stop(std::string& OUT collect_remains)
{
}
protected:
private:
/*! \brief
* Pointer to parent HTTP-parser
*/
i_target_handler* m_powner_filter;
/*! \brief
* ZLIB object for income stream
*/
z_stream m_zstream_in;
/*! \brief
* ZLIB object for outcome stream
*/
z_stream m_zstream_out;
/*! \brief
* Data that could not be unpacked immediately, left to wait for the next packet of data
*/
std::string m_pre_decode;
/*! \brief
* The data are accumulated for a package in the buffer to send the web client
*/
std::string m_pre_encode;
/*! \brief
* Signals that stream looks like ended
*/
bool m_is_stream_ended;
/*! \brief
* If this flag is set, income data is in HTTP-deflate mode
*/
bool m_is_deflate_mode;
/*! \brief
* Marks that it is a first data packet
*/
bool m_is_first_update_in;
}; // class content_encoding_gzip
res = m_powner_filter->handle_target_data(decode_summary_buff);
struct abstract_callback_base
{
virtual bool do_call(const std::string& piece_of_transfer) = 0;
virtual ~abstract_callback_base() {}
};
return true;
template <typename callback_t>
struct abstract_callback : public abstract_callback_base
{
callback_t m_cb;
}
/*! \brief
* Function stop : Entry point for stop signal and flushing cached data buffer.
*
*/
inline
virtual void stop(std::string& OUT collect_remains)
{
}
protected:
private:
/*! \brief
* Pointer to parent HTTP-parser
*/
i_target_handler* m_powner_filter;
/*! \brief
* ZLIB object for income stream
*/
z_stream m_zstream_in;
/*! \brief
* ZLIB object for outcome stream
*/
z_stream m_zstream_out;
/*! \brief
* Data that could not be unpacked immediately, left to wait for the next packet of data
*/
std::string m_pre_decode;
/*! \brief
* The data are accumulated for a package in the buffer to send the web client
*/
std::string m_pre_encode;
/*! \brief
* Signals that stream looks like ended
*/
bool m_is_stream_ended;
/*! \brief
* If this flag is set, income data is in HTTP-deflate mode
*/
bool m_is_deflate_mode;
/*! \brief
* Marks that it is a first data packet
*/
bool m_is_first_update_in;
};
}
}
abstract_callback(callback_t cb) : m_cb(cb){}
virtual bool do_call(const std::string& piece_of_transfer)
{
return m_cb(piece_of_transfer);
}
};
class gzip_decoder_lambda : public content_encoding_gzip,
public i_target_handler
{
std::shared_ptr<abstract_callback_base> m_pcb;
virtual bool handle_target_data(std::string& piece_of_transfer)
{
bool r = m_pcb->do_call(piece_of_transfer);
piece_of_transfer.clear();
return r;
}
public:
gzip_decoder_lambda() : content_encoding_gzip(this, true, Z_BEST_COMPRESSION)
{}
template<class callback_t>
bool update_in(std::string& piece_of_transfer, callback_t cb)
{
m_pcb.reset(new abstract_callback<callback_t>(cb));
return content_encoding_gzip::update_in(piece_of_transfer);
}
template<class callback_t>
bool stop(callback_t cb)
{return true;}
}; // class gzip_decoder_lambda
class gzip_encoder_lyambda
{
bool m_initialized;
z_stream m_zstream;
public:
gzip_encoder_lyambda(int compression_level = Z_DEFAULT_COMPRESSION) :m_initialized(false), m_zstream(AUTO_VAL_INIT(m_zstream))
{
int ret = deflateInit(&m_zstream, compression_level);
if (ret == Z_OK)
m_initialized = true;
}
~gzip_encoder_lyambda()
{
deflateEnd(&m_zstream);
}
template<typename callback_t>
bool update_in(const std::string& target, callback_t cb)
{
if (!m_initialized)
{
return false;
}
if (!target.size())
{
return true;
}
std::string result_packed_buff;
auto slh = misc_utils::create_scope_leave_handler([&]() { m_zstream.next_out = nullptr; } ); // make sure local pointer to result_packed_buff.data() won't be used out of this scope
//theoretically it supposed to be smaller
result_packed_buff.resize(target.size(), 'X');
while (true)
{
m_zstream.next_in = (Bytef*)target.data();
m_zstream.avail_in = (uInt)target.size();
m_zstream.next_out = (Bytef*)result_packed_buff.data();
m_zstream.avail_out = (uInt)result_packed_buff.size();
int ret = deflate(&m_zstream, Z_NO_FLUSH);
CHECK_AND_ASSERT_MES(ret >= 0, false, "Failed to deflate. err = " << ret);
if (m_zstream.avail_out == 0)
{
//twice bigger buffer
result_packed_buff.resize(result_packed_buff.size()*2);
continue;
}
CHECK_AND_ASSERT_MES(result_packed_buff.size() >= m_zstream.avail_out, false, "result_packed_buff.size()=" << result_packed_buff.size() << " >= m_zstream.avail_out=" << m_zstream.avail_out);
result_packed_buff.resize(result_packed_buff.size() - m_zstream.avail_out);
break;
}
return cb(result_packed_buff);
}
template<typename callback_t>
bool stop(callback_t cb)
{
if (!m_initialized)
{
return false;
}
std::string result_packed_buff;
//theoretically it supposed to be smaller
result_packed_buff.resize(1000000, 'X');
while (true)
{
m_zstream.next_in = nullptr;
m_zstream.avail_in = 0;
m_zstream.next_out = (Bytef*)result_packed_buff.data();
m_zstream.avail_out = (uInt)result_packed_buff.size();
int ret = deflate(&m_zstream, Z_FINISH);
CHECK_AND_ASSERT_MES(ret >= 0, false, "Failed to deflate at finish. err = " << ret);
if (ret != Z_STREAM_END)
{
//twice bigger buffer
result_packed_buff.resize(result_packed_buff.size() * 2);
continue;
}
CHECK_AND_ASSERT_MES(result_packed_buff.size() >= m_zstream.avail_out, false, "result_packed_buff.size()=" << result_packed_buff.size() << " >= m_zstream.avail_out=" << m_zstream.avail_out);
result_packed_buff.resize(result_packed_buff.size() - m_zstream.avail_out);
m_initialized = false;
break;
}
return cb(result_packed_buff);
}
}; // class gzip_encoder_lyambda
} // namespace net_utils
} // namespace epee

View file

@ -69,7 +69,7 @@ DISABLE_VS_WARNINGS(4100)
#include "syncobj.h"
#include "sync_locked_object.h"
#include "string_coding.h"
#include "file_io_utils.h"
#define LOG_LEVEL_SILENT -1
#define LOG_LEVEL_0 0
@ -113,12 +113,14 @@ DISABLE_VS_WARNINGS(4100)
#endif
#define LOG_DEFAULT_CHANNEL NULL
#define ENABLE_CHANNEL_BY_DEFAULT(ch_name) \
static bool COMBINE(init_channel, __LINE__) UNUSED_ATTRIBUTE = epee::misc_utils::static_initializer([](){ \
epee::log_space::log_singletone::enable_channel(ch_name); return true; \
});
#if defined(ENABLE_LOGGING_INTERNAL)
#define LOG_PRINT_CHANNEL_NO_PREFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
@ -288,6 +290,8 @@ namespace log_space
virtual bool set_max_logfile_size(uint64_t max_size){return true;};
virtual bool set_log_rotate_cmd(const std::string& cmd){return true;};
virtual bool truncate_log_files() { return true; }
virtual std::string copy_logs_to_buffer() { return ""; }
};
/************************************************************************/
@ -365,6 +369,7 @@ namespace log_space
inline bool is_stdout_a_tty()
{
#ifndef ANDROID_BUILD
static std::atomic<bool> initialized(false);
static std::atomic<bool> is_a_tty(false);
@ -379,6 +384,9 @@ namespace log_space
}
return is_a_tty.load(std::memory_order_relaxed);
#else
return false;
#endif
}
inline void set_console_color(int color, bool bright)
@ -584,7 +592,7 @@ namespace log_space
std::string buf(buffer, buffer_len);
for(size_t i = 0; i!= buf.size(); i++)
{
if(buf[i] == 7 || buf[i] == -107)
if(static_cast<unsigned char>(buf[i]) == 0x7 || static_cast<unsigned char>(buf[i]) == 0x95)
buf[i] = '^';
}
@ -623,7 +631,7 @@ namespace log_space
class file_output_stream : public ibase_log_stream
{
public:
typedef std::map<std::string, boost::filesystem::ofstream*> named_log_streams;
typedef std::map<std::string, std::pair< boost::filesystem::ofstream*, std::wstring> > named_log_streams;
file_output_stream( const std::string& default_log_file_name, const std::string& log_path )
{
@ -637,12 +645,12 @@ namespace log_space
{
for(named_log_streams::iterator it = m_log_file_names.begin(); it!=m_log_file_names.end(); it++)
{
if ( it->second->is_open() )
if ( it->second.first->is_open() )
{
it->second->flush();
it->second->close();
it->second.first->flush();
it->second.first->close();
}
delete it->second;
delete it->second.first;
}
}
private:
@ -660,12 +668,14 @@ namespace log_space
//log_space::rotate_log_file((m_default_log_path + "\\" + pstream_name).c_str());
boost::system::error_code ec;
boost::filesystem::create_directories(m_default_log_path_w, ec);
boost::filesystem::ofstream* pstream = (m_log_file_names[pstream_name] = new boost::filesystem::ofstream);
boost::filesystem::ofstream* pstream = new boost::filesystem::ofstream;
std::wstring target_path = m_default_log_path_w + L"/" + epee::string_encoding::utf8_to_wstring(pstream_name);
pstream->open( target_path.c_str(), std::ios_base::out | std::ios::app /*ios_base::trunc */);
if(pstream->fail())
return NULL;
m_log_file_names[pstream_name] = std::pair<boost::filesystem::ofstream*, std::wstring>(pstream, target_path);
return pstream;
}
@ -681,6 +691,51 @@ namespace log_space
return true;
}
bool truncate_log_files()
{
for (named_log_streams::iterator it = m_log_file_names.begin(); it != m_log_file_names.end(); it++)
{
std::wstring target_path = it->second.second;
//close and delete current stream
if (it->second.first->is_open())
{
it->second.first->flush();
it->second.first->close();
}
delete it->second.first;
it->second.first = nullptr;
//reopen it with truncate
boost::filesystem::ofstream* pstream = new boost::filesystem::ofstream;
pstream->open(target_path.c_str(), std::ios_base::out | std::ios::trunc );
if (pstream->fail())
{
throw std::runtime_error("Unexpected error: failed to re-open log stream on truncate");
}
it->second.first = pstream;
}
return true;
}
std::string copy_logs_to_buffer()
{
std::stringstream res;
for (named_log_streams::iterator it = m_log_file_names.begin(); it != m_log_file_names.end(); it++)
{
std::wstring target_path = it->second.second;
res << "[" << epee::string_encoding::convert_to_ansii(target_path) << "]" << ENDL;
std::string res_buf;
if (!epee::file_io_utils::load_file_to_string(target_path, res_buf))
{
res << "ERROR";
}
else
{
res << res_buf;
}
}
return res.str();
}
virtual bool out_buffer( const char* buffer, int buffer_len, int log_level, int color, const char* plog_name = NULL )
@ -692,7 +747,7 @@ namespace log_space
if(it == m_log_file_names.end())
m_target_file_stream = add_new_stream_and_open(plog_name);
else
m_target_file_stream = it->second;
m_target_file_stream = it->second.first;
}
if(!m_target_file_stream || !m_target_file_stream->is_open())
return false;//TODO: add assert here
@ -790,6 +845,22 @@ namespace log_space
return true;
}
bool truncate_log_files()
{
for (streams_container::iterator it = m_log_streams.begin(); it != m_log_streams.end(); it++)
it->first->truncate_log_files();
return true;
}
std::string copy_logs_to_buffer()
{
std::string res;
for (streams_container::iterator it = m_log_streams.begin(); it != m_log_streams.end(); it++)
res += it->first->copy_logs_to_buffer();
return res;
}
bool do_log_message(const std::string& rlog_mes, int log_level, int color, const char* plog_name = NULL)
{
std::string str_mess = rlog_mes;
@ -961,6 +1032,21 @@ namespace log_space
return true;
}
std::string copy_logs_to_buffer()
{
FAST_CRITICAL_REGION_BEGIN(m_critical_sec);
return m_log_target.copy_logs_to_buffer();
FAST_CRITICAL_REGION_END();
}
bool truncate_log_files()
{
FAST_CRITICAL_REGION_BEGIN(m_critical_sec);
return m_log_target.truncate_log_files();
FAST_CRITICAL_REGION_END();
}
bool take_away_journal(std::list<std::string>& journal)
{
FAST_CRITICAL_REGION_BEGIN(m_critical_sec);
@ -1150,7 +1236,9 @@ namespace log_space
std::set<std::string> enabled_channels_local = genabled_channels;
enabled_channels_local.insert(ch_name);
genabled_channels.swap(enabled_channels_local);
#ifndef ANDROID_BUILD
std::cout << "log channel '" << ch_name << "' enabled" << std::endl;
#endif
}
static void disable_channels(const std::string& channels_set)
@ -1246,6 +1334,23 @@ namespace log_space
return plogger->set_log_rotate_cmd(cmd);
}
static std::string copy_logs_to_buffer()
{
logger* plogger = get_or_create_instance();
if (!plogger) return "";
return plogger->copy_logs_to_buffer();
}
static bool truncate_log_files()
{
logger* plogger = get_or_create_instance();
if (!plogger) return false;
return plogger->truncate_log_files();
}
static bool add_logger( int type, const char* pdefault_file_name, const char* pdefault_log_folder, int log_level_limit = LOG_LEVEL_4)
{

View file

@ -109,14 +109,15 @@ namespace misc_utils
#endif
}
#if defined(__GNUC__)
#if defined(__GNUC__) && !defined(__ANDROID__)
#include <execinfo.h>
#include <boost/core/demangle.hpp>
#endif
inline std::string print_trace_default()
{
std::stringstream ss;
#if defined(__GNUC__)
#if defined(__GNUC__) && !defined(__ANDROID__)
ss << std::endl << "STACK" << std::endl;
const size_t max_depth = 100;
size_t stack_depth;

View file

@ -38,9 +38,9 @@
#include "net_helper.h"
#include "http_client_base.h"
#ifdef HTTP_ENABLE_GZIP
//#ifdef HTTP_ENABLE_GZIP
#include "gzip_encoding.h"
#endif
//#endif
#include "string_tools.h"
#include "reg_exp_definer.h"
@ -230,11 +230,11 @@ using namespace std;
blocked_mode_client m_net_client;
std::string m_host_buff;
std::string m_port;
unsigned int m_timeout;
//unsigned int m_timeout;
unsigned int m_connection_timeout;
unsigned int m_recv_timeout;
std::string m_header_cache;
http_response_info m_response_info;
size_t m_len_in_summary;
size_t m_len_in_remain;
//std::string* m_ptarget_buffer;
boost::shared_ptr<i_sub_handler> m_pcontent_encoding_handler;
reciev_machine_state m_state;
@ -242,6 +242,10 @@ using namespace std;
std::string m_chunked_cache;
critical_section m_lock;
protected:
uint64_t m_len_in_summary;
uint64_t m_len_in_remain;
public:
void set_host_name(const std::string& name)
{
@ -259,14 +263,27 @@ using namespace std;
{
return connect(host, std::to_string(port), timeout);
}
bool connect(const std::string& host, const std::string& port, unsigned int timeout)
bool set_timeouts(unsigned int connection_timeout, unsigned int recv_timeout)
{
m_connection_timeout = connection_timeout;
m_recv_timeout = recv_timeout;
return true;
}
bool connect(const std::string& host, std::string port)
{
CRITICAL_REGION_LOCAL(m_lock);
m_host_buff = host;
m_port = port;
m_timeout = timeout;
return m_net_client.connect(host, port, timeout, timeout);
return m_net_client.connect(host, port, m_connection_timeout, m_recv_timeout);
}
bool connect(const std::string& host, const std::string& port, unsigned int timeout)
{
m_connection_timeout = m_recv_timeout = timeout;
return connect(host, port);
}
//---------------------------------------------------------------------------
bool disconnect()
@ -303,7 +320,7 @@ using namespace std;
if(!is_connected())
{
LOG_PRINT("Reconnecting...", LOG_LEVEL_3);
if(!connect(m_host_buff, m_port, m_timeout))
if(!connect(m_host_buff, m_port))
{
LOG_PRINT("Failed to connect to " << m_host_buff << ":" << m_port, LOG_LEVEL_3);
return false;
@ -447,7 +464,14 @@ using namespace std;
}
CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_len_in_remain >= recv_buff.size()");
m_len_in_remain -= recv_buff.size();
m_pcontent_encoding_handler->update_in(recv_buff);
bool r = m_pcontent_encoding_handler->update_in(recv_buff);
//CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_pcontent_encoding_handler->update_in returned false");
if (!r)
{
m_state = reciev_machine_state_error;
disconnect();
return false;
}
if(m_len_in_remain == 0)
m_state = reciev_machine_state_done;
@ -483,7 +507,7 @@ using namespace std;
}
//---------------------------------------------------------------------------
inline
bool get_len_from_chunk_head(const std::string &chunk_head, size_t& result_size)
bool get_len_from_chunk_head(const std::string &chunk_head, uint64_t& result_size)
{
std::stringstream str_stream;
str_stream << std::hex;
@ -494,7 +518,7 @@ using namespace std;
}
//---------------------------------------------------------------------------
inline
bool get_chunk_head(std::string& buff, size_t& chunk_size, bool& is_matched)
bool get_chunk_head(std::string& buff, uint64_t& chunk_size, bool& is_matched)
{
is_matched = false;
size_t offset = 0;
@ -850,13 +874,13 @@ using namespace std;
return true;
}
};
// class http_simple_client
/************************************************************************/
/* */
/************************************************************************/
//inline
template<class t_transport>
bool invoke_request(const std::string& url, t_transport& tr, unsigned int timeout, const http_response_info** ppresponse_info, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list())
{
@ -873,12 +897,136 @@ using namespace std;
if (!tr.connect(u_c.host, static_cast<int>(u_c.port), timeout))
{
LOG_PRINT_L2("invoke_request: cannot connect to " << u_c.host << ":" << u_c.port);
return false;
}
}
return tr.invoke(u_c.uri, method, body, ppresponse_info, additional_params);
}
}
}
}
struct idle_handler_base
{
virtual bool do_call(const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes) = 0;
virtual ~idle_handler_base() {}
};
template <typename callback_t>
struct idle_handler : public idle_handler_base
{
callback_t m_cb;
idle_handler(callback_t cb) : m_cb(cb) {}
virtual bool do_call(const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes)
{
return m_cb(piece_of_data, total_bytes, received_bytes);
}
};
class interruptible_http_client : public http_simple_client
{
std::shared_ptr<idle_handler_base> m_pcb;
virtual bool handle_target_data(std::string& piece_of_transfer)
{
bool r = m_pcb->do_call(piece_of_transfer, m_len_in_summary, m_len_in_summary - m_len_in_remain);
piece_of_transfer.clear();
return r;
}
public:
template<typename callback_t>
bool invoke_cb(callback_t cb, const std::string& url, uint64_t timeout, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list())
{
m_pcb.reset(new idle_handler<callback_t>(cb));
const http_response_info* p_hri = nullptr;
bool r = invoke_request(url, *this, timeout, &p_hri, method, body, additional_params);
if (p_hri && !(p_hri->m_response_code >= 200 && p_hri->m_response_code < 300))
{
LOG_PRINT_L0("HTTP request to " << url << " failed with code: " << p_hri->m_response_code);
return false;
}
return r;
}
template<typename callback_t>
bool download(callback_t cb, const std::string& path_for_file, const std::string& url, uint64_t timeout, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list())
{
std::ofstream fs;
fs.open(path_for_file, std::ios::binary | std::ios::out | std::ios::trunc);
if (!fs.is_open())
{
LOG_ERROR("Fsiled to open " << path_for_file);
return false;
}
auto local_cb = [&](const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes)
{
fs.write(piece_of_data.data(), piece_of_data.size());
return cb(total_bytes, received_bytes);
};
bool r = this->invoke_cb(local_cb, url, timeout, method, body, additional_params);
fs.close();
return r;
}
//
template<typename callback_t>
bool download_and_unzip(callback_t cb, const std::string& path_for_file, const std::string& url, uint64_t timeout, const std::string& method = "GET", const std::string& body = std::string(), uint64_t fails_count = 1000, const fields_list& additional_params = fields_list())
{
std::ofstream fs;
fs.open(path_for_file, std::ios::binary | std::ios::out | std::ios::trunc);
if (!fs.is_open())
{
LOG_ERROR("Fsiled to open " << path_for_file);
return false;
}
std::string buff;
gzip_decoder_lambda zip_decoder;
uint64_t state_total_bytes = 0;
uint64_t state_received_bytes_base = 0;
uint64_t state_received_bytes_current = 0;
bool stopped = false;
auto local_cb = [&](const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes)
{
//remember total_bytes only for first attempt, where fetched full lenght of the file
if (!state_total_bytes)
state_total_bytes = total_bytes;
buff += piece_of_data;
return zip_decoder.update_in(buff, [&](const std::string& unpacked_buff)
{
state_received_bytes_current = received_bytes;
fs.write(unpacked_buff.data(), unpacked_buff.size());
stopped = !cb(unpacked_buff, state_total_bytes, state_received_bytes_base + received_bytes);
return !stopped;
});
};
uint64_t current_err_count = 0;
bool r = false;
while (!r && current_err_count < fails_count)
{
LOG_PRINT_L0("Attempt to invoke http: " << url << " (offset:" << state_received_bytes_base << ")");
fields_list additional_params_local = additional_params;
additional_params_local.push_back(std::make_pair<std::string, std::string>("Range", std::string("bytes=") + std::to_string(state_received_bytes_base) + "-"));
r = this->invoke_cb(local_cb, url, timeout, method, body, additional_params_local);
if (!r)
{
if (stopped)
break;
current_err_count++;
state_received_bytes_base += state_received_bytes_current;
state_received_bytes_current = 0;
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
}
}
fs.close();
return r;
}
};
} // namespace http
} // namespace net_utils
} // namespace epee

View file

@ -198,10 +198,12 @@ namespace epee
struct response<dummy_result, t_error>
{
std::string jsonrpc;
std::string method;
t_error error;
epee::serialization::storage_entry id;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(jsonrpc)
KV_SERIALIZE(method)
KV_SERIALIZE(id)
KV_SERIALIZE(error)
END_KV_SERIALIZE_MAP()
@ -288,6 +290,7 @@ struct json_command_type_t
PREPARE_OBJECTS_FROM_JSON(command_type) \
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
fail_resp.jsonrpc = "2.0"; \
fail_resp.method = req.method; \
fail_resp.id = req.id; \
if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context)) \
{ \
@ -304,6 +307,7 @@ struct json_command_type_t
PREPARE_OBJECTS_FROM_JSON(command_type) \
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
fail_resp.jsonrpc = "2.0"; \
fail_resp.method = req.method; \
fail_resp.id = req.id; \
if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context, response_info)) \
{ \
@ -322,6 +326,7 @@ struct json_command_type_t
{ \
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
fail_resp.jsonrpc = "2.0"; \
fail_resp.method = req.method; \
fail_resp.id = req.id; \
fail_resp.error.code = -32603; \
fail_resp.error.message = "Internal error"; \
@ -338,6 +343,7 @@ struct json_command_type_t
epee::json_rpc::error_response rsp; \
rsp.id = id_; \
rsp.jsonrpc = "2.0"; \
rsp.method = callback_name; \
rsp.error.code = -32601; \
rsp.error.message = "Method not found"; \
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \

View file

@ -37,7 +37,7 @@ namespace epee
{
template<class pack_value, class t_stream>
size_t pack_varint_t(t_stream& strm, uint8_t type_or, size_t& pv)
size_t pack_varint_t(t_stream& strm, uint8_t type_or, const uint64_t& pv)
{
pack_value v = (*((pack_value*)&pv)) << 2;
v |= type_or;
@ -48,7 +48,7 @@ namespace epee
PUSH_GCC_WARNINGS
DISABLE_GCC_WARNING(strict-aliasing)
template<class t_stream>
size_t pack_varint(t_stream& strm, size_t val)
size_t pack_varint(t_stream& strm, uint64_t val)
{ //the first two bits always reserved for size information
if(val <= 63)

View file

@ -157,6 +157,7 @@ namespace epee
template<class t_stream>
void dump_as_json(t_stream& strm, const double& v, size_t indent, end_of_line_t eol)
{
boost::io::ios_flags_saver ifs(strm);
strm.precision(8);
strm << std::fixed << v;
}

View file

@ -54,8 +54,10 @@ namespace epee
{}
~locked_object_proxy()
{
TRY_ENTRY();
uint64_t lock_time = epee::misc_utils::get_tick_count() - start_lock_time;
lock_time_watching_policy::watch_lock_time(lock_time);
CATCH_ALL_DO_NOTHING();
}
/*
@ -82,6 +84,13 @@ namespace epee
template<typename t_proxy_object, typename t_proxy_lock_time_watching_policy>
friend class locked_object_proxy;
public:
std::shared_ptr<locked_object_proxy<t_object, lock_time_watching_policy>> lock()
{
std::shared_ptr<locked_object_proxy<t_object, lock_time_watching_policy>> res;
res.reset(new locked_object_proxy<t_object, lock_time_watching_policy>(t, m));
return res;
}
std::shared_ptr<locked_object_proxy<t_object, lock_time_watching_policy>> try_lock()
{
std::shared_ptr<locked_object_proxy<t_object, lock_time_watching_policy>> res;

View file

@ -183,10 +183,10 @@ if(MINGW)
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
endif(MINGW)
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
#add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
set_target_properties(zlib PROPERTIES SOVERSION 1)
# set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
# set_target_properties(zlib PROPERTIES SOVERSION 1)
if(NOT CYGWIN)
# This property causes shared libraries on Linux to have the full version
@ -196,22 +196,22 @@ if(NOT CYGWIN)
#
# This has no effect with MSVC, on that platform the version info for
# the DLL comes from the resource file win32/zlib1.rc
set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
# set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
endif()
if(UNIX)
# On unix-like platforms the library is almost always called libz
set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
set_target_properties( zlibstatic PROPERTIES OUTPUT_NAME z)
if(NOT APPLE)
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
#set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
endif()
elseif(BUILD_SHARED_LIBS AND WIN32)
# Creates zlib1.dll when building shared library version
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
# set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
endif()
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
install(TARGETS zlib zlibstatic
install(TARGETS zlibstatic
RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
@ -230,20 +230,20 @@ endif()
# Example binaries
#============================================================================
add_executable(example test/example.c)
target_link_libraries(example zlib)
add_test(example example)
#add_executable(example test/example.c)
#target_link_libraries(example zlib)
#add_test(example example)
add_executable(minigzip test/minigzip.c)
target_link_libraries(minigzip zlib)
#add_executable(minigzip test/minigzip.c)
#target_link_libraries(minigzip zlib)
if(HAVE_OFF64_T)
add_executable(example64 test/example.c)
target_link_libraries(example64 zlib)
set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
add_test(example64 example64)
# add_executable(example64 test/example.c)
# target_link_libraries(example64 zlib)
# set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
# add_test(example64 example64)
add_executable(minigzip64 test/minigzip.c)
target_link_libraries(minigzip64 zlib)
set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
# add_executable(minigzip64 test/minigzip.c)
# target_link_libraries(minigzip64 zlib)
# set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
endif()

View file

@ -1,7 +1,6 @@
if(POLICY CMP0043)
cmake_policy(SET CMP0043 OLD)
endif()
# if(POLICY CMP0043)
# cmake_policy(SET CMP0043 OLD)
# endif()
###########
# using shared PCH -- this is unusual case for MSVC... so mystery, such hack, many wow. See also: https://stackoverflow.com/questions/645747/sharing-precompiled-headers-between-projects-in-visual-studio/4170902#4170902
@ -100,9 +99,34 @@ endif()
add_library(crypto ${CRYPTO})
add_library(currency_core ${CURRENCY_CORE})
add_dependencies(currency_core version rpc ${PCH_LIB_NAME})
add_dependencies(currency_core version ${PCH_LIB_NAME})
ENABLE_SHARED_PCH(CURRENCY_CORE)
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})
else()
add_library(wallet ${WALLET})
add_dependencies(wallet version ${PCH_LIB_NAME})
ENABLE_SHARED_PCH(WALLET)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
install(TARGETS wallet currency_core crypto common DESTINATION lib)
message("Generating install for iOS")
return()
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
install(TARGETS wallet currency_core crypto common zlibstatic DESTINATION "${CMAKE_ANDROID_ARCH_ABI}/lib")
message("Generating install for Android")
return()
endif()
add_library(rpc ${RPC})
add_dependencies(rpc version ${PCH_LIB_NAME})
ENABLE_SHARED_PCH(RPC)
@ -111,15 +135,12 @@ add_library(stratum ${STRATUM})
add_dependencies(stratum version ${PCH_LIB_NAME})
ENABLE_SHARED_PCH(STRATUM)
add_library(wallet ${WALLET})
add_dependencies(wallet version ${PCH_LIB_NAME})
ENABLE_SHARED_PCH(WALLET)
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)
ENABLE_SHARED_PCH_EXECUTABLE(daemon)

View file

@ -12,7 +12,7 @@ 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<std::string> arg_data_dir = {"data-dir", "Specify data directory", ""};
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", "" };
@ -31,4 +31,10 @@ namespace command_line
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_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 };
}

View file

@ -23,6 +23,25 @@ namespace command_line
struct arg_descriptor<T, false>
{
typedef T value_type;
arg_descriptor(const char* _name, const char* _description):
name(_name),
description(_description),
not_use_default(true),
default_value(T())
{}
arg_descriptor(const char* _name, const char* _description, const T& default_val) :
name(_name),
description(_description),
not_use_default(false),
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)
{}
const char* name;
const char* description;
@ -192,4 +211,8 @@ namespace command_line
extern const arg_descriptor<bool> arg_disable_stop_on_low_free_space;
extern const arg_descriptor<bool> arg_enable_offers_service;
extern const arg_descriptor<std::string> arg_db_engine;
extern const arg_descriptor<bool> arg_no_predownload;
extern const arg_descriptor<bool> arg_force_predownload;
extern const arg_descriptor<bool> arg_validate_predownload;
extern const arg_descriptor<std::string> arg_predownload_link;
}

View file

@ -0,0 +1,66 @@
// Copyright (c) 2014-2020 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 <string>
#include "wallet/view_iface.h"
namespace tools
{
#pragma pack(push, 1)
struct app_data_file_binary_header
{
uint64_t m_signature;
uint64_t m_cb_body;
};
#pragma pack (pop)
inline
std::string load_encrypted_file(const std::string& path, const std::string& key, std::string& body, uint64_t signature)
{
std::string app_data_buff;
bool r = epee::file_io_utils::load_file_to_string(path, app_data_buff);
if (!r)
{
return API_RETURN_CODE_NOT_FOUND;
}
if (app_data_buff.size() < sizeof(app_data_file_binary_header))
{
LOG_ERROR("app_data_buff.size()(" << app_data_buff.size() << ") < sizeof(app_data_file_binary_header) (" << sizeof(app_data_file_binary_header) << ") check failed while loading from " << path);
return API_RETURN_CODE_INVALID_FILE;
}
crypto::chacha_crypt(app_data_buff, key);
const app_data_file_binary_header* phdr = reinterpret_cast<const app_data_file_binary_header*>(app_data_buff.data());
if (phdr->m_signature != signature)
{
return API_RETURN_CODE_WRONG_PASSWORD;
}
body = app_data_buff.substr(sizeof(app_data_file_binary_header)).c_str();
return API_RETURN_CODE_OK;
}
inline
std::string store_encrypted_file(const std::string& path, const std::string& key, const std::string& body, uint64_t signature)
{
std::string buff(sizeof(app_data_file_binary_header), 0);
app_data_file_binary_header* phdr = (app_data_file_binary_header*)buff.data();
phdr->m_signature = signature;
phdr->m_cb_body = 0; // for future use
buff.append(body);
crypto::chacha_crypt(buff, key);
bool r = epee::file_io_utils::save_string_to_file(path, buff);
if (r)
return API_RETURN_CODE_OK;
else
return API_RETURN_CODE_FAIL;
}
}

View file

@ -315,13 +315,13 @@ namespace tools
PROFILE_FUNC("lmdb_db_backend::set");
int res = 0;
MDB_val key = AUTO_VAL_INIT(key);
MDB_val data = AUTO_VAL_INIT(data);
MDB_val data[2] = {}; // mdb_put may access data[1] if some flags are set, this may trigger static code analizers, so here we allocate two elements to avoid it
key.mv_data = (void*)k;
key.mv_size = ks;
data.mv_data = (void*)v;
data.mv_size = vs;
data[0].mv_data = (void*)v;
data[0].mv_size = vs;
res = mdb_put(get_current_tx(), static_cast<MDB_dbi>(h), &key, &data, 0);
res = mdb_put(get_current_tx(), static_cast<MDB_dbi>(h), &key, data, 0);
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_put");
return true;
}

View file

@ -322,13 +322,13 @@ namespace tools
PROFILE_FUNC("mdbx_db_backend::set");
int res = 0;
MDBX_val key = AUTO_VAL_INIT(key);
MDBX_val data = AUTO_VAL_INIT(data);
MDBX_val data[2] = {}; // mdbx_put may access data[1] if some flags are set, this may trigger static code analizers, so here we allocate two elements to avoid it
key.iov_base = (void*)k;
key.iov_len = ks;
data.iov_base = (void*)v;
data.iov_len = vs;
data[0].iov_base = (void*)v;
data[0].iov_len = vs;
res = mdbx_put(get_current_tx(), static_cast<MDBX_dbi>(h), &key, &data, 0);
res = mdbx_put(get_current_tx(), static_cast<MDBX_dbi>(h), &key, data, 0);
CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_put");
return true;
}

View file

@ -0,0 +1,132 @@
// Copyright (c) 2014-2020 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "db_backend_selector.h"
#include "currency_core/currency_config.h"
#include "command_line.h"
#include "db_backend_lmdb.h"
#include "db_backend_mdbx.h"
#define LMDB_MAIN_FILE_NAME "data.mdb"
#define MDBX_MAIN_FILE_NAME "mdbx.dat"
namespace tools
{
namespace db
{
db_backend_selector::db_backend_selector()
: m_engine_type(db_none)
{
}
void db_backend_selector::init_options(boost::program_options::options_description& desc)
{
command_line::add_arg(desc, command_line::arg_db_engine);
}
bool db_backend_selector::init(const boost::program_options::variables_map& vm)
{
try
{
m_config_folder = command_line::get_arg(vm, command_line::arg_data_dir);
if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_LMDB)
{
m_engine_type = db_lmdb;
}
else if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_MDBX)
{
#ifdef ENABLED_ENGINE_MDBX
m_engine_type = db_mdbx;
#else
LOG_PRINT_L0(" DB ENGINE: " << ARG_DB_ENGINE_MDBX << " is not suported by this build(see DISABLE_MDBX cmake option), STOPPING");
#endif
}
else
{
LOG_PRINT_RED_L0("UNKNOWN DB ENGINE: " << command_line::get_arg(vm, command_line::arg_db_engine) << ", STOPPING");
}
}
catch (std::exception& e)
{
LOG_ERROR("internal error: db_backend_selector::init failed on command-line parsing, exception: " << e.what());
return false;
}
if (m_engine_type == db_none)
return false;
return true;
}
std::string db_backend_selector::get_db_folder_path() const
{
//CHECK_AND_ASSERT_THROW_MES(m_engine_type != db_none, "db_backend_selector was no inited");
return m_config_folder + ("/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX) + get_engine_name() + CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX;
}
std::string db_backend_selector::get_temp_db_folder_path() const
{
//CHECK_AND_ASSERT_THROW_MES(m_engine_type != db_none, "db_backend_selector was no inited");
return get_temp_config_folder() + ("/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX) + get_engine_name() + CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX;
}
std::string db_backend_selector::get_pool_db_folder_path() const
{
return m_config_folder + ("/" CURRENCY_POOLDATA_FOLDERNAME_PREFIX) + get_engine_name() + CURRENCY_POOLDATA_FOLDERNAME_SUFFIX;
}
std::string db_backend_selector::get_db_main_file_name() const
{
switch (m_engine_type)
{
case db_lmdb:
return LMDB_MAIN_FILE_NAME;
case db_mdbx:
return MDBX_MAIN_FILE_NAME;
default:
return "";
}
}
std::string db_backend_selector::get_engine_name() const
{
switch (m_engine_type)
{
case db_lmdb:
return "lmdb";
case db_mdbx:
return "mdbx";
default:
return "unknown";
}
}
std::shared_ptr<tools::db::i_db_backend> db_backend_selector::create_backend()
{
switch (m_engine_type)
{
case db_lmdb:
return std::shared_ptr<tools::db::i_db_backend>(new tools::db::lmdb_db_backend);
case db_mdbx:
return std::shared_ptr<tools::db::i_db_backend>(new tools::db::mdbx_db_backend);
default:
LOG_ERROR("db_backend_selector was no inited");
return nullptr;
}
}
std::string db_backend_selector::get_temp_config_folder() const
{
return m_config_folder + "_TEMP";
}
} // namespace db
} // namespace tools

View file

@ -1,48 +1,43 @@
// Copyright (c) 2014-2019 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Copyright (c) 2014-2020 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 "db_backend_lmdb.h"
#include "db_backend_mdbx.h"
#include "common/command_line.h"
#include "common/db_abstract_accessor.h"
#include <boost/program_options.hpp>
#include "misc_language.h"
#include "db_backend_base.h"
namespace tools
{
namespace db
{
inline
bool select_db_engine_from_arg(const boost::program_options::variables_map& vm, tools::db::basic_db_accessor& rdb)
enum db_engine_type { db_none = 0, db_lmdb, db_mdbx };
class db_backend_selector
{
try
{
if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_LMDB)
{
rdb.reset_backend(std::shared_ptr<tools::db::i_db_backend>(new tools::db::lmdb_db_backend));
return true;
}
else if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_MDBX)
{
#ifdef ENABLED_ENGINE_MDBX
rdb.reset_backend(std::shared_ptr<tools::db::i_db_backend>(new tools::db::mdbx_db_backend));
return true;
#else
LOG_PRINT_L0(" DB ENGINE: " << ARG_DB_ENGINE_MDBX << " is not suported by this build(see DISABLE_MDBX cmake option), STOPPING");
return false;
#endif
}
}
catch (...)
{
LOG_ERROR("internal error: arg_db_engine command-line option could not be read (exception caught)");
return false;
}
public:
db_backend_selector();
LOG_PRINT_RED_L0(" UNKNOWN DB ENGINE: " << command_line::get_arg(vm, command_line::arg_db_engine) << ", STOPPING");
return false;
}
}
}
static void init_options(boost::program_options::options_description& desc);
bool init(const boost::program_options::variables_map& vm);
std::string get_db_folder_path() const;
std::string get_db_main_file_name() const;
db_engine_type get_engine_type() const { return m_engine_type; }
std::string get_engine_name() const;
std::string get_config_folder() const { return m_config_folder; }
std::string get_temp_config_folder() const;
std::string get_temp_db_folder_path() const;
std::string get_pool_db_folder_path() const;
std::shared_ptr<tools::db::i_db_backend> create_backend();
private:
db_engine_type m_engine_type;
std::string m_config_folder;
};
} // namespace db
} // namespace tools

View file

@ -16,6 +16,17 @@
#include <intrin.h>
#include <stdlib.h>
#if !defined(__ORDER_LITTLE_ENDIAN__)
#define __ORDER_LITTLE_ENDIAN__ 1011012001
#endif
#if !defined(__BYTE_ORDER__)
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
#endif
#if !defined(__ORDER_BIG_ENDIAN__)
#define __ORDER_BIG_ENDIAN__ 0
#endif
static inline uint32_t rol32(uint32_t x, int r) {
static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers");
@ -194,11 +205,11 @@ static inline void memcpy_swap64(void *dst, const void *src, size_t n) {
}
}
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || !defined(__ORDER_BIG_ENDIAN__)
static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled");
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define SWAP32LE IDENT32
#define SWAP32BE SWAP32
#define swap32le ident32
@ -217,7 +228,7 @@ static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not e
#define memcpy_swap64be memcpy_swap64
#endif
#if BYTE_ORDER == BIG_ENDIAN
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define SWAP32BE IDENT32
#define SWAP32LE SWAP32
#define swap32be ident32

View file

@ -30,13 +30,18 @@ namespace tools
char m_lanaddr[64];
int m_IGD;
boost::thread m_mapper_thread;
boost::thread m_initializer_thread;
uint32_t m_external_port;
uint32_t m_internal_port;
uint32_t m_period_ms;
public:
miniupnp_helper():m_devlist(nullptr),
m_urls(AUTO_VAL_INIT(m_urls)),
m_data(AUTO_VAL_INIT(m_data)),
m_IGD(0),
m_external_port{}
m_external_port(0),
m_internal_port(0),
m_period_ms(0)
{
m_lanaddr[0] = 0;
}
@ -52,9 +57,10 @@ namespace tools
bool start_regular_mapping(uint32_t internal_port, uint32_t external_port, uint32_t period_ms)
{
m_external_port = external_port;
m_internal_port = internal_port;
m_period_ms = period_ms;
if(!init())
return false;
m_mapper_thread = boost::thread([=](){run_port_mapping_loop(internal_port, external_port, period_ms);});
return true;
}
@ -77,27 +83,42 @@ namespace tools
bool init()
{
deinit();
m_initializer_thread = boost::thread([=]()
{
deinit();
int error = 0;
m_devlist = upnpDiscover(2000, nullptr, nullptr, 0, 0, 2, &error);
if(error)
{
LOG_PRINT_L0("Failed to call upnpDiscover");
return false;
}
m_IGD = UPNP_GetValidIGD(m_devlist, &m_urls, &m_data, m_lanaddr, sizeof(m_lanaddr));
if(m_IGD != 1)
{
LOG_PRINT_L2("IGD not found");
return false;
}
int error = 0;
m_devlist = upnpDiscover(2000, nullptr, nullptr, 0, 0, 2, &error);
if (error)
{
LOG_PRINT_L0("Failed to call upnpDiscover");
return false;
}
m_IGD = UPNP_GetValidIGD(m_devlist, &m_urls, &m_data, m_lanaddr, sizeof(m_lanaddr));
if (m_IGD != 1)
{
LOG_PRINT_L2("IGD not found");
return false;
}
m_mapper_thread = boost::thread([=]() {run_port_mapping_loop(m_internal_port, m_external_port, m_period_ms); });
return true;
});
return true;
}
bool deinit()
{
if(m_initializer_thread.get_id() != boost::this_thread::get_id())
{
if (m_initializer_thread.joinable())
{
m_initializer_thread.interrupt();
m_initializer_thread.join();
}
}
stop_mapping();
if(m_devlist)

225
src/common/pre_download.h Normal file
View file

@ -0,0 +1,225 @@
// Copyright (c) 2020 Zano Project
// Copyright (c) 2012-2018 The Boolberry developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <boost/program_options.hpp>
#include "net/http_client.h"
#include "db_backend_selector.h"
#include "crypto/crypto.h"
#include "currency_core/currency_core.h"
namespace tools
{
struct pre_download_entry
{
const char* url;
const char* hash;
uint64_t packed_size;
uint64_t unpacked_size;
};
#ifndef TESTNET
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_lmdb_94_425000.pak", "e6ac69dcf8e7a7017d032cb4326d661c541a3b6a328e6299e6d61c3acde5d49f", 684683820, 1021865984 };
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_mdbx_94_425000.pak", "e1f50efba1149a349eb626037dda30052c0233091693a00a10dd5363d5de1206", 535268266, 1073725440 };
#else
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_testnet_lmdb_96_99000.pak", "9e8522b287ac7637ca770970542e94702f9fbaa267633cfcaeee4383dfe15bd0", 83851119, 131493888 };
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_testnet_mdbx_96_99000.pak", "de33646711f2276e5b22db5741d7b2bf6a8e4c4231d393b730f9a4fce1d7ec03", 63257747, 268431360 };
#endif
static constexpr uint64_t pre_download_min_size_difference = 512 * 1024 * 1024; // minimum difference in size between local DB and the downloadable one to start downloading
template<class callback_t>
bool process_predownload(const boost::program_options::variables_map& vm, callback_t cb_should_stop)
{
tools::db::db_backend_selector dbbs;
bool r = dbbs.init(vm);
CHECK_AND_ASSERT_MES(r, false, "db_backend_selector failed to initialize");
std::string config_folder = dbbs.get_config_folder();
std::string working_folder = dbbs.get_db_folder_path();
std::string db_main_file_path = working_folder + "/" + dbbs.get_db_main_file_name();
pre_download_entry pre_download = dbbs.get_engine_type() == db::db_lmdb ? c_pre_download_lmdb : c_pre_download_mdbx;
// override pre-download link if necessary
std::string url = pre_download.url;
if (command_line::has_arg(vm, command_line::arg_predownload_link))
url = command_line::get_arg(vm, command_line::arg_predownload_link);
boost::system::error_code ec;
uint64_t sz = boost::filesystem::file_size(db_main_file_path, ec);
if (!(ec || (pre_download.unpacked_size > sz && pre_download.unpacked_size - sz > pre_download_min_size_difference) || command_line::has_arg(vm, command_line::arg_force_predownload)) )
{
LOG_PRINT_MAGENTA("Pre-downloading not needed (db file size = " << sz << ")", LOG_LEVEL_0);
return true;
}
// okay, let's download
std::string downloading_file_path = db_main_file_path + ".download";
LOG_PRINT_MAGENTA("Trying to download blockchain database from " << url << " ...", LOG_LEVEL_0);
epee::net_utils::http::interruptible_http_client cl;
crypto::stream_cn_hash hash_stream;
auto last_update = std::chrono::system_clock::now();
auto cb = [&hash_stream, &last_update, &cb_should_stop](const std::string& buff, uint64_t total_bytes, uint64_t received_bytes)
{
if (cb_should_stop(total_bytes, received_bytes))
{
LOG_PRINT_MAGENTA(ENDL << "Interrupting download", LOG_LEVEL_0);
return false;
}
hash_stream.update(buff.data(), buff.size());
auto dif = std::chrono::system_clock::now() - last_update;
if (dif >= std::chrono::milliseconds(300))
{
boost::io::ios_flags_saver ifs(std::cout);
std::cout << "Received " << received_bytes / 1048576 << " of " << total_bytes / 1048576 << " MiB ( " << std::fixed << std::setprecision(1) << 100.0 * received_bytes / total_bytes << " %)\r";
last_update = std::chrono::system_clock::now();
}
return true;
};
tools::create_directories_if_necessary(working_folder);
r = cl.download_and_unzip(cb, downloading_file_path, url, 1000 /* timout */, "GET", std::string(), 3 /* fails count */);
if (!r)
{
LOG_PRINT_RED("Download failed", LOG_LEVEL_0);
return false;
}
crypto::hash data_hash = hash_stream.calculate_hash();
if (epee::string_tools::pod_to_hex(data_hash) != pre_download.hash)
{
LOG_ERROR("hash missmatch in downloaded file, got: " << epee::string_tools::pod_to_hex(data_hash) << ", expected: " << pre_download.hash);
return false;
}
LOG_PRINT_GREEN("Download succeeded, hash " << pre_download.hash << " is correct" , LOG_LEVEL_0);
if (!command_line::has_arg(vm, command_line::arg_validate_predownload))
{
boost::filesystem::remove(db_main_file_path, ec);
if (ec)
{
LOG_ERROR("Failed to remove " << db_main_file_path);
return false;
}
LOG_PRINT_L1("Removed " << db_main_file_path);
boost::filesystem::rename(downloading_file_path, db_main_file_path, ec);
if (ec)
{
LOG_ERROR("Failed to rename " << downloading_file_path << " -> " << db_main_file_path);
return false;
}
LOG_PRINT_L1("Renamed " << downloading_file_path << " -> " << db_main_file_path);
LOG_PRINT_GREEN("Blockchain successfully replaced with the new pre-downloaded data file", LOG_LEVEL_0);
return true;
}
//
// paranoid mode
// move downloaded blockchain into a temporary folder
//
LOG_PRINT_MAGENTA(ENDL << "Downloaded blockchain database is about to be validated and added to the local database block-by-block" << ENDL, LOG_LEVEL_0);
std::string path_to_temp_datafolder = dbbs.get_temp_config_folder();
std::string path_to_temp_blockchain = dbbs.get_temp_db_folder_path();
std::string path_to_temp_blockchain_file = path_to_temp_blockchain + "/" + dbbs.get_db_main_file_name();
tools::create_directories_if_necessary(path_to_temp_blockchain);
boost::filesystem::rename(downloading_file_path, path_to_temp_blockchain_file, ec);
if (ec)
{
LOG_ERROR("Rename failed: " << downloading_file_path << " -> " << path_to_temp_blockchain_file);
return false;
}
// remove old blockchain database from disk
boost::filesystem::remove_all(working_folder, ec);
if (ec)
{
LOG_ERROR("Failed to remove all from " << working_folder);
return false;
}
std::string pool_db_path = dbbs.get_pool_db_folder_path();
boost::filesystem::remove_all(pool_db_path, ec);
if (ec)
{
LOG_ERROR("Failed to remove all from " << pool_db_path);
return false;
}
// source core
currency::core source_core(nullptr);
boost::program_options::variables_map source_core_vm;
source_core_vm.insert(std::make_pair("data-dir", boost::program_options::variable_value(path_to_temp_datafolder, false)));
source_core_vm.insert(std::make_pair("db-engine", boost::program_options::variable_value(dbbs.get_engine_name(), false)));
//source_core_vm.insert(std::make_pair("db-sync-mode", boost::program_options::variable_value(std::string("fast"), false)));
r = source_core.init(source_core_vm);
CHECK_AND_ASSERT_MES(r, false, "Failed to init source core");
// target core
currency::core target_core(nullptr);
boost::program_options::variables_map target_core_vm(vm);
target_core_vm.insert(std::make_pair("db-engine", boost::program_options::variable_value(dbbs.get_engine_name(), false)));
//vm_with_fast_sync.insert(std::make_pair("db-sync-mode", boost::program_options::variable_value(std::string("fast"), false)));
r = target_core.init(target_core_vm);
CHECK_AND_ASSERT_MES(r, false, "Failed to init target core");
CHECK_AND_ASSERT_MES(target_core.get_top_block_height() == 0, false, "Target blockchain initialized not empty");
uint64_t total_blocks = source_core.get_current_blockchain_size();
LOG_PRINT_GREEN("Manually processing blocks from 1 to " << total_blocks << "...", LOG_LEVEL_0);
for (uint64_t i = 1; i != total_blocks; i++)
{
std::list<currency::block> blocks;
std::list<currency::transaction> txs;
bool r = source_core.get_blocks(i, 1, blocks, txs);
CHECK_AND_ASSERT_MES(r && blocks.size()==1, false, "Filed to get block " << i << " from core");
currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
crypto::hash tx_hash = AUTO_VAL_INIT(tx_hash);
for (auto& tx : txs)
{
r = target_core.handle_incoming_tx(tx, tvc, true /* kept_by_block */);
CHECK_AND_ASSERT_MES(r && tvc.m_added_to_pool == true, false, "Failed to add a tx from block " << i << " from core");
}
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);
r = target_core.handle_incoming_block(*blocks.begin(), bvc);
CHECK_AND_ASSERT_MES(r && bvc.m_added_to_main_chain == true, false, "Failed to add block " << i << " to core");
if (!(i % 100))
std::cout << "Block " << i << "(" << (i * 100) / total_blocks << "%) \r";
if (cb_should_stop(total_blocks, i))
{
LOG_PRINT_MAGENTA(ENDL << "Interrupting updating db...", LOG_LEVEL_0);
return false;
}
}
LOG_PRINT_GREEN("Processing finished, " << total_blocks << " successfully added.", LOG_LEVEL_0);
target_core.deinit();
source_core.deinit();
boost::filesystem::remove_all(path_to_temp_datafolder, ec);
if (ec)
{
LOG_ERROR("Failed to remove all from " << path_to_temp_datafolder);
}
return true;
}
}

View file

@ -8,6 +8,7 @@
#include "include_base_utils.h"
#include "version.h"
#include "epee/include/gzip_encoding.h"
using namespace epee;
#include <boost/program_options.hpp>
@ -23,7 +24,6 @@ using namespace epee;
#include "storages/http_abstract_invoke.h"
#include "net/http_client.h"
#include "currency_core/genesis_acc.h"
#include <cstdlib>
namespace po = boost::program_options;
@ -59,6 +59,9 @@ namespace
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 };
}
typedef COMMAND_REQUEST_STAT_INFO_T<t_currency_protocol_handler<core>::stat_info> COMMAND_REQUEST_STAT_INFO;
@ -910,7 +913,6 @@ bool invoke_debug_command(po::variables_map& vm, const crypto::secret_key& sk, l
return net_utils::invoke_remote_command2(command_t::ID, req, rsp, transport);
}
//---------------------------------------------------------------------------------------------------------------
bool handle_set_peer_log_level(po::variables_map& vm)
{
@ -1101,6 +1103,121 @@ bool handle_generate_integrated_address(po::variables_map& vm)
return true;
}
//---------------------------------------------------------------------------------------------------------------
template<class archive_processor_t>
bool process_archive(archive_processor_t& arch_processor, bool is_packing, std::ifstream& source, std::ofstream& target)
{
source.seekg(0, std::ios::end);
uint64_t sz = source.tellg();
uint64_t remaining = sz;
uint64_t written_bytes = 0;
crypto::stream_cn_hash hash_stream;
source.seekg(0, std::ios::beg);
#define PACK_READ_BLOCKS_SIZE 1048576 // 1MB blocks
std::string buff;
auto writer_cb = [&](const std::string& piece_of_transfer)
{
target.write(piece_of_transfer.data(), piece_of_transfer.size());
written_bytes += piece_of_transfer.size();
if (!is_packing)
hash_stream.update(piece_of_transfer.data(), piece_of_transfer.size());
return true;
};
while (remaining)
{
uint64_t read_sz = remaining >= PACK_READ_BLOCKS_SIZE ? PACK_READ_BLOCKS_SIZE : remaining;
buff.resize(read_sz);
source.read(const_cast<char*>(buff.data()), buff.size());
if (!source)
{
std::cout << "Error on read from source" << ENDL;
return true;
}
if (is_packing)
hash_stream.update(buff.data(), buff.size());
bool r = arch_processor.update_in(buff, writer_cb);
CHECK_AND_ASSERT_MES(r, false, "arch_processor.update_in failed");
remaining -= read_sz;
std::cout << "Progress: " << ((sz - remaining) * 100) / sz << "%\r";
}
//flush gzip decoder
arch_processor.stop(writer_cb);
source.close();
target.close();
crypto::hash data_hash = hash_stream.calculate_hash();
std::cout << "\r\nFile " << (is_packing ? "packed" : "unpacked") << " from size " << sz << " to " << written_bytes <<
"\r\nhash of the data is " << epee::string_tools::pod_to_hex(data_hash) << "\r\n";
return true;
}
bool handle_pack_file(po::variables_map& vm)
{
bool do_pack = false;
std::string path_source;
std::string path_target;
if (command_line::has_arg(vm, arg_pack_file))
{
path_source = command_line::get_arg(vm, arg_pack_file);
do_pack = true;
}
else if (command_line::has_arg(vm, arg_unpack_file))
{
path_source = command_line::get_arg(vm, arg_unpack_file);
do_pack = false;
}
else
{
return false;
}
if (!command_line::has_arg(vm, arg_target_file))
std::cout << "Error: Parameter target_file is not set." << ENDL;
path_target = command_line::get_arg(vm, arg_target_file);
std::ifstream source;
source.open(path_source, std::ios::binary | std::ios::in );
if (!source.is_open())
{
std::cout << "Error: Unable to open " << path_source << ENDL;
return false;
}
std::ofstream target;
target.open(path_target, std::ios::binary | std::ios::out | std::ios::trunc);
if (!target.is_open())
{
std::cout << "Error: Unable to open " << path_target << ENDL;
return false;
}
if (do_pack)
{
epee::net_utils::gzip_encoder_lyambda gzip_encoder(Z_BEST_COMPRESSION);
return process_archive(gzip_encoder, true, source, target);
}
else
{
epee::net_utils::gzip_decoder_lambda gzip_decoder;
return process_archive(gzip_decoder, false, source, target);
}
}
//---------------------------------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
try
@ -1142,8 +1259,9 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_download_peer_log);
command_line::add_arg(desc_params, arg_do_consloe_log);
command_line::add_arg(desc_params, arg_generate_integrated_address);
command_line::add_arg(desc_params, arg_pack_file);
command_line::add_arg(desc_params, arg_unpack_file);
command_line::add_arg(desc_params, arg_target_file);
po::options_description desc_all;
desc_all.add(desc_general).add(desc_params);
@ -1216,6 +1334,10 @@ int main(int argc, char* argv[])
{
return handle_generate_integrated_address(vm) ? EXIT_SUCCESS : EXIT_FAILURE;
}
else if (command_line::has_arg(vm, arg_pack_file) || command_line::has_arg(vm, arg_unpack_file))
{
return handle_pack_file(vm) ? EXIT_SUCCESS : EXIT_FAILURE;
}
else
{
std::cerr << "Not enough arguments." << ENDL;

View file

@ -1976,6 +1976,72 @@ void ge_scalarmult(ge_p2 *r, const unsigned char *a, const ge_p3 *A) {
}
}
/* Assumes that a[31] <= 127 */
void ge_scalarmult_p3(ge_p3 *result, const unsigned char *a, const ge_p3 *A) {
signed char e[64];
int carry, carry2, i;
ge_cached Ai[8]; /* 1 * A, 2 * A, ..., 8 * A */
ge_p1p1 t;
ge_p3 u;
ge_p2 r_tmp;
ge_p2* r = &r_tmp;
carry = 0; /* 0..1 */
for (i = 0; i < 31; i++) {
carry += a[i]; /* 0..256 */
carry2 = (carry + 8) >> 4; /* 0..16 */
e[2 * i] = carry - (carry2 << 4); /* -8..7 */
carry = (carry2 + 8) >> 4; /* 0..1 */
e[2 * i + 1] = carry2 - (carry << 4); /* -8..7 */
}
carry += a[31]; /* 0..128 */
carry2 = (carry + 8) >> 4; /* 0..8 */
e[62] = carry - (carry2 << 4); /* -8..7 */
e[63] = carry2; /* 0..8 */
ge_p3_to_cached(&Ai[0], A);
for (i = 0; i < 7; i++) {
ge_add(&t, A, &Ai[i]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[i + 1], &u);
}
ge_p2_0(r);
for (i = 63; i >= 0; i--) {
signed char b = e[i];
unsigned char bnegative = negative(b);
unsigned char babs = b - (((-bnegative) & b) << 1);
ge_cached cur, minuscur;
ge_p2_dbl(&t, r);
ge_p1p1_to_p2(r, &t);
ge_p2_dbl(&t, r);
ge_p1p1_to_p2(r, &t);
ge_p2_dbl(&t, r);
ge_p1p1_to_p2(r, &t);
ge_p2_dbl(&t, r);
ge_p1p1_to_p3(&u, &t);
ge_cached_0(&cur);
ge_cached_cmov(&cur, &Ai[0], equal(babs, 1));
ge_cached_cmov(&cur, &Ai[1], equal(babs, 2));
ge_cached_cmov(&cur, &Ai[2], equal(babs, 3));
ge_cached_cmov(&cur, &Ai[3], equal(babs, 4));
ge_cached_cmov(&cur, &Ai[4], equal(babs, 5));
ge_cached_cmov(&cur, &Ai[5], equal(babs, 6));
ge_cached_cmov(&cur, &Ai[6], equal(babs, 7));
ge_cached_cmov(&cur, &Ai[7], equal(babs, 8));
fe_copy(minuscur.YplusX, cur.YminusX);
fe_copy(minuscur.YminusX, cur.YplusX);
fe_copy(minuscur.Z, cur.Z);
fe_neg(minuscur.T2d, cur.T2d);
ge_cached_cmov(&cur, &minuscur, bnegative);
ge_add(&t, &u, &cur);
if (i > 0)
ge_p1p1_to_p2(r, &t);
else
ge_p1p1_to_p3(result, &t); // last iteration
}
}
void ge_double_scalarmult_precomp_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b, const ge_dsmp Bi) {
signed char aslide[256];
signed char bslide[256];

View file

@ -101,6 +101,7 @@ void sc_reduce(unsigned char *);
/* New code */
void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *);
void ge_scalarmult_p3(ge_p3 *, const unsigned char *, const ge_p3 *);
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp);
void ge_mul8(ge_p1p1 *, const ge_p2 *);
extern const fe fe_ma2;

View file

@ -10,6 +10,7 @@
#include <mutex>
#include <vector>
#include <string>
#include <algorithm>
#include "common/pod-class.h"
#include "generic-ops.h"
@ -226,6 +227,69 @@ namespace crypto {
return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
}
class stream_cn_hash
{
public:
static constexpr size_t DATA_BLOCK_SIZE = 1024 * 1024;
stream_cn_hash()
: m_buffer(HASH_SIZE + DATA_BLOCK_SIZE, '\0')
, m_p_hash(const_cast<hash*>(reinterpret_cast<const hash*>(m_buffer.data())))
, m_p_data(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(m_buffer.data())) + HASH_SIZE)
, m_ready(false)
, m_data_used(0)
{
m_ready = true;
}
bool update(const void* data, size_t size)
{
if (!m_ready)
return false;
const uint8_t* p_source_data = reinterpret_cast<const uint8_t*>(data);
while(size > 0)
{
// fill the buffer up
size_t bytes_to_copy = std::min(size, DATA_BLOCK_SIZE - m_data_used);
memcpy(m_p_data + m_data_used, p_source_data, bytes_to_copy);
m_data_used += bytes_to_copy;
p_source_data += bytes_to_copy;
size -= bytes_to_copy;
if (m_data_used == DATA_BLOCK_SIZE)
{
// calc imtermediate hash of the whole buffer and put the result into the beginning of the buffer
*m_p_hash = cn_fast_hash(m_buffer.data(), HASH_SIZE + m_data_used);
// clear data buffer for new bytes
memset(m_p_data, 0, DATA_BLOCK_SIZE);
m_data_used = 0;
}
// repeat if there are source bytes left
}
return true;
}
hash calculate_hash()
{
if (m_data_used == 0)
return *m_p_hash;
m_ready = false;
return cn_fast_hash(m_buffer.data(), HASH_SIZE + m_data_used);
}
private:
const std::string m_buffer;
hash* const m_p_hash;
uint8_t* const m_p_data;
size_t m_data_used;
bool m_ready;
};
}

View file

@ -158,7 +158,10 @@ namespace currency
account_public_address transform_str_to_addr(const std::string& str)
{
account_public_address ad = AUTO_VAL_INIT(ad);
get_account_address_from_str(ad, str);
if (!get_account_address_from_str(ad, str))
{
LOG_ERROR("cannot parse address from string: " << str);
}
return ad;
}
}

View file

@ -70,7 +70,6 @@ using namespace currency;
#endif
#define BLOCK_POS_STRICT_SEQUENCE_LIMIT 20
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX "_v1"
DISABLE_VS_WARNINGS(4267)
@ -153,7 +152,6 @@ void blockchain_storage::init_options(boost::program_options::options_descriptio
{
command_line::add_arg(desc, arg_db_cache_l1);
command_line::add_arg(desc, arg_db_cache_l2);
command_line::add_arg(desc, command_line::arg_db_engine);
}
//------------------------------------------------------------------
uint64_t blockchain_storage::get_block_h_older_then(uint64_t timestamp) const
@ -207,11 +205,16 @@ bool blockchain_storage::validate_instance(const std::string& path)
bool blockchain_storage::init(const std::string& config_folder, const boost::program_options::variables_map& vm)
{
// CRITICAL_REGION_LOCAL(m_read_lock);
if (!select_db_engine_from_arg(vm, m_db))
tools::db::db_backend_selector dbbs;
dbbs.init(vm);
auto p_backend = dbbs.create_backend();
if (!p_backend)
{
LOG_PRINT_RED_L0("Failed to select db engine");
LOG_PRINT_RED_L0("Failed to create db engine");
return false;
}
m_db.reset_backend(p_backend);
LOG_PRINT_L0("DB ENGINE USED BY CORE: " << m_db.get_backend()->name());
if (!validate_instance(config_folder))
@ -236,8 +239,8 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
LOG_PRINT_YELLOW("Removing old DB in " << old_db_folder_path << "...", LOG_LEVEL_0);
boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(old_db_folder_path));
}
;
const std::string db_folder_path = m_config_folder + ("/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX) + m_db.get_backend()->name() + CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX;
const std::string db_folder_path = dbbs.get_db_folder_path();
LOG_PRINT_L0("Loading blockchain from " << db_folder_path);
bool db_opened_okay = false;
@ -293,14 +296,21 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
bool need_reinit = false;
if (m_db_blocks.size() != 0)
{
if (m_db_storage_major_compatibility_version != BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION)
if (m_db_storage_major_compatibility_version == 93 && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 94)
{
// do not reinit db if moving from version 93 to version 94
LOG_PRINT_MAGENTA("DB storage does not need reinit because moving from v93 to v94", LOG_LEVEL_0);
}
else if (m_db_storage_major_compatibility_version != BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION)
{
need_reinit = true;
LOG_PRINT_MAGENTA("DB storage needs reinit because it has major compatibility ver " << m_db_storage_major_compatibility_version << ", expected : " << BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION, LOG_LEVEL_0);
}
else if (m_db_storage_minor_compatibility_version != BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION)
else if (m_db_storage_minor_compatibility_version > BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION)
{
// nothing
// reinit db only if minor version in the DB is greather (i.e. newer) than minor version in the code
need_reinit = true;
LOG_PRINT_MAGENTA("DB storage needs reinit because it has minor compatibility ver " << m_db_storage_minor_compatibility_version << " that is greater than BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION: " << BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION, LOG_LEVEL_0);
}
}
@ -528,17 +538,22 @@ bool blockchain_storage::prune_ring_signatures_and_attachments_if_need()
{
CRITICAL_REGION_LOCAL(m_read_lock);
if(m_db_blocks.size() && m_checkpoints.get_top_checkpoint_height() && m_checkpoints.get_top_checkpoint_height() > m_db_current_pruned_rs_height)
if (m_db_blocks.size() > 1 && m_checkpoints.get_top_checkpoint_height() && m_checkpoints.get_top_checkpoint_height() > m_db_current_pruned_rs_height)
{
LOG_PRINT_CYAN("Starting pruning ring signatues and attachments...", LOG_LEVEL_0);
uint64_t tx_count = 0, sig_count = 0, attach_count = 0;
for(uint64_t height = m_db_current_pruned_rs_height; height < m_db_blocks.size() && height <= m_checkpoints.get_top_checkpoint_height(); height++)
uint64_t pruning_last_height = std::min(m_db_blocks.size() - 1, m_checkpoints.get_top_checkpoint_height());
if (pruning_last_height > m_db_current_pruned_rs_height)
{
bool res = prune_ring_signatures_and_attachments(height, tx_count, sig_count, attach_count);
CHECK_AND_ASSERT_MES(res, false, "failed to prune_ring_signatures_and_attachments for height = " << height);
LOG_PRINT_CYAN("Starting pruning ring signatues and attachments from height " << m_db_current_pruned_rs_height + 1 << " to height " << pruning_last_height
<< " (" << pruning_last_height - m_db_current_pruned_rs_height << " blocks)", LOG_LEVEL_0);
uint64_t tx_count = 0, sig_count = 0, attach_count = 0;
for(uint64_t height = m_db_current_pruned_rs_height + 1; height <= pruning_last_height; height++)
{
bool res = prune_ring_signatures_and_attachments(height, tx_count, sig_count, attach_count);
CHECK_AND_ASSERT_MES(res, false, "failed to prune_ring_signatures_and_attachments for height = " << height);
}
m_db_current_pruned_rs_height = pruning_last_height;
LOG_PRINT_CYAN("Transaction pruning finished: " << sig_count << " signatures and " << attach_count << " attachments released in " << tx_count << " transactions.", LOG_LEVEL_0);
}
m_db_current_pruned_rs_height = m_checkpoints.get_top_checkpoint_height();
LOG_PRINT_CYAN("Transaction pruning finished: " << sig_count << " signatures and " << attach_count << " attachments released in " << tx_count << " transactions.", LOG_LEVEL_0);
}
return true;
}
@ -641,7 +656,7 @@ bool blockchain_storage::purge_transaction_keyimages_from_blockchain(const trans
}
};
BOOST_FOREACH(const txin_v& in, tx.vin)
for(const txin_v& in : tx.vin)
{
bool r = boost::apply_visitor(purge_transaction_visitor(*this, m_db_spent_keys, strict_check), in);
CHECK_AND_ASSERT_MES(!strict_check || r, false, "failed to process purge_transaction_visitor");
@ -3909,7 +3924,7 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
const std::vector<crypto::signature>* psig = &sig_stub;
TIME_MEASURE_START_PD(tx_check_inputs_loop);
BOOST_FOREACH(const auto& txin, tx.vin)
for(const auto& txin : tx.vin)
{
if (!m_is_in_checkpoint_zone)
{

View file

@ -9,12 +9,22 @@
#include "checkpoints.h"
#include "misc_log_ex.h"
#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(checkpoints.add_checkpoint(h, hash), false);
#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(checkpoints.add_checkpoint(h, hash), false)
namespace currency
{
namespace currency {
inline bool create_checkpoints(currency::checkpoints& checkpoints)
{
#ifdef TESTNET
ADD_CHECKPOINT(50000, "cb05a7bdc7f78c5cdb6ef1048f85b27c569f44879233903ce5f5a4e5bd590a3d");
ADD_CHECKPOINT(100000, "6b8b54356a9d44f6c1ebdacb8593d8f5ab2e2e2ca4493e7ae7baf4b3755c5e16");
#else
// MAINNET
ADD_CHECKPOINT(425000, "46a6c36d5dec2d484d5e4845a8525ca322aafc06915ed9c8da2a241b51b7d1e8");
#endif
return true;
}
}
} // namespace currency

View file

@ -192,7 +192,9 @@
#define CURRENCY_POOLDATA_FOLDERNAME_PREFIX "poolstate_"
#define CURRENCY_POOLDATA_FOLDERNAME_SUFFIX "_v1"
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX "blockchain_"
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX "_v1"
#define P2P_NET_DATA_FILENAME "p2pstate.bin"
#define MINER_CONFIG_FILENAME "miner_conf.json"
@ -205,7 +207,7 @@
#define CURRENT_TRANSACTION_CHAIN_ENTRY_ARCHIVE_VER 3
#define CURRENT_BLOCK_EXTENDED_INFO_ARCHIVE_VER 1
#define BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION CURRENCY_FORMATION_VERSION + 9
#define BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION CURRENCY_FORMATION_VERSION + 10
#define BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION 1

View file

@ -184,6 +184,34 @@ namespace currency
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_tx(const transaction& tx, tx_verification_context& tvc, bool kept_by_block, const crypto::hash& tx_hash_ /* = null_hash */)
{
TIME_MEASURE_START_MS(wait_lock_time);
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
TIME_MEASURE_FINISH_MS(wait_lock_time);
crypto::hash tx_hash = tx_hash_;
if (tx_hash == null_hash)
tx_hash = get_transaction_hash(tx);
TIME_MEASURE_START_MS(add_new_tx_time);
bool r = add_new_tx(tx, tx_hash, get_object_blobsize(tx), tvc, kept_by_block);
TIME_MEASURE_FINISH_MS(add_new_tx_time);
if(tvc.m_verification_failed)
{LOG_PRINT_RED_L0("Transaction verification failed: " << tx_hash);}
else if(tvc.m_verification_impossible)
{LOG_PRINT_RED_L0("Transaction verification impossible: " << tx_hash);}
if (tvc.m_added_to_pool)
{
LOG_PRINT_L2("incoming tx " << tx_hash << " was added to the pool");
}
LOG_PRINT_L2("[CORE HANDLE_INCOMING_TX1]: timing " << wait_lock_time
<< "/" << add_new_tx_time);
return r;
}
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool kept_by_block)
{
CHECK_AND_ASSERT_MES(!kept_by_block, false, "Transaction associated with block came throw handle_incoming_tx!(not allowed anymore)");
@ -212,7 +240,6 @@ namespace currency
}
TIME_MEASURE_FINISH_MS(parse_tx_time);
TIME_MEASURE_START_MS(check_tx_semantic_time);
if(!validate_tx_semantic(tx, tx_blob.size()))
{
@ -222,23 +249,10 @@ namespace currency
}
TIME_MEASURE_FINISH_MS(check_tx_semantic_time);
TIME_MEASURE_START_MS(add_new_tx_time);
bool r = add_new_tx(tx, tx_hash, get_object_blobsize(tx), tvc, kept_by_block);
TIME_MEASURE_FINISH_MS(add_new_tx_time);
if(tvc.m_verification_failed)
{LOG_PRINT_RED_L0("Transaction verification failed: " << tx_hash);}
else if(tvc.m_verification_impossible)
{LOG_PRINT_RED_L0("Transaction verification impossible: " << tx_hash);}
if (tvc.m_added_to_pool)
{
LOG_PRINT_L2("incoming tx " << tx_hash << " was added to the pool");
}
LOG_PRINT_L2("[CORE HANDLE_INCOMING_TX]: timing " << wait_lock_time
bool r = handle_incoming_tx(tx, tvc, kept_by_block, tx_hash);
LOG_PRINT_L2("[CORE HANDLE_INCOMING_TX2]: timing " << wait_lock_time
<< "/" << parse_tx_time
<< "/" << check_tx_semantic_time
<< "/" << add_new_tx_time);
<< "/" << check_tx_semantic_time);
return r;
}
//-----------------------------------------------------------------------------------------------

View file

@ -41,6 +41,7 @@ namespace currency
core(i_currency_protocol* pprotocol);
bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp, currency_connection_context& context)const ;
bool on_idle();
bool handle_incoming_tx(const transaction& tx, tx_verification_context& tvc, bool kept_by_block, const crypto::hash& tx_hash_ = null_hash);
bool handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool kept_by_block);
bool handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate = true);
bool handle_incoming_block(const block& b, block_verification_context& bvc, bool update_miner_blocktemplate = true);

View file

@ -7,7 +7,9 @@
#include "include_base_utils.h"
#include <boost/foreach.hpp>
#include <boost/locale.hpp>
#ifndef ANDROID_BUILD
#include <boost/locale.hpp>
#endif
using namespace epee;
#include "print_fixed_point_helper.h"
@ -625,7 +627,8 @@ namespace currency
//put hash into extra
std::stringstream ss;
binary_archive<true> oar(ss);
::do_serialize(oar, const_cast<std::vector<attachment_v>&>(attachment));
if (!::do_serialize(oar, const_cast<std::vector<attachment_v>&>(attachment)))
return;
std::string buff = ss.str();
eai.sz = buff.size();
eai.hsh = get_blob_hash(buff);
@ -1605,7 +1608,7 @@ namespace currency
return true;
size_t i = 0;
BOOST_FOREACH(const tx_out& o, tx.vout)
for(const tx_out& o : tx.vout)
{
if (o.target.type() == typeid(txout_to_key))
{
@ -2677,6 +2680,7 @@ namespace currency
return o << "<" << r.n << ":" << r.tx_id << ">";
}
//--------------------------------------------------------------------------------
#ifndef ANDROID_BUILD
const std::locale& utf8_get_conversion_locale()
{
static std::locale loc = boost::locale::generator().generate("en_US.UTF-8");
@ -2696,6 +2700,7 @@ namespace currency
return true;
return utf8_to_lower(s).find(utf8_to_lower(match), 0) != std::string::npos;
}
#endif
//--------------------------------------------------------------------------------
bool operator ==(const currency::transaction& a, const currency::transaction& b) {
return currency::get_transaction_hash(a) == currency::get_transaction_hash(b);

View file

@ -595,9 +595,11 @@ namespace currency
//---------------------------------------------------------------
std::ostream& operator <<(std::ostream& o, const ref_by_id& r);
//---------------------------------------------------------------
#ifndef ANDROID_BUILD
std::string utf8_to_upper(const std::string& s);
std::string utf8_to_lower(const std::string& s);
bool utf8_substring_test_case_insensitive(const std::string& match, const std::string& s); // Returns true is 's' contains 'match' (case-insensitive)
#endif
struct difficulties
{

View file

@ -24,9 +24,9 @@ namespace currency {
using std::uint64_t;
using std::vector;
#if defined(_MSC_VER)
#include <windows.h>
#include <winnt.h>
//#if defined(_MSC_VER)
//#include <windows.h>
//#include <winnt.h>
static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) {
boost::multiprecision::uint128_t res = boost::multiprecision::uint128_t(a) * b;
@ -36,7 +36,7 @@ namespace currency {
//low = UnsignedMultiply128(a, b, &high);
}
#else
/* #else
static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) {
typedef unsigned __int128 uint128_t;
@ -45,7 +45,7 @@ namespace currency {
high = (uint64_t)(res >> 64);
}
#endif
#endif */
static inline bool cadd(uint64_t a, uint64_t b) {
return a + b < a;

View file

@ -56,7 +56,11 @@ namespace bc_services
//------------------------------------------------------------------
bool order_offers_by_name(const offer_details_ex* a, const offer_details_ex* b)
{
#ifndef ANDROID_BUILD
return currency::utf8_to_lower(a->target) < currency::utf8_to_lower(b->target);
#else
return false;
#endif
}
//------------------------------------------------------------------
std::vector<sort_offers_func_type> gsort_offers_predicates;
@ -146,14 +150,14 @@ namespace bc_services
//check category
if (!of.category.empty() && o.category.find(of.category) == std::string::npos)
return false;
#ifndef ANDROID_BUILD
//check target condition
if (of.target.size() && !currency::utf8_substring_test_case_insensitive(of.target, o.target))
return false;
if (of.primary.size() && !currency::utf8_substring_test_case_insensitive(of.primary, o.primary))
return false;
#endif
//check payment_types condition (TODO: add more complicated algo here)
if (of.payment_types.size())
@ -169,11 +173,11 @@ namespace bc_services
//check target condition
if (of.location_country.size() && (of.location_country != o.location_country))
return false;
#ifndef ANDROID_BUILD
//check target condition
if (of.location_city.size() && !currency::utf8_substring_test_case_insensitive(of.location_city, o.location_city))
return false;
#endif
//check amount
if (of.amount_low_limit && (of.amount_low_limit > o.amount_primary))
return false;
@ -217,12 +221,12 @@ namespace bc_services
//--------------------------------------------------------------------------------
bool filter_offers_list(std::list<bc_services::offer_details_ex>& offers, const bc_services::core_offers_filter& filter, uint64_t current_core_time)
{
#ifndef ANDROID_BUILD
//filter
offers.remove_if([&](bc_services::offer_details_ex& o) -> bool {
return !is_offer_matched_by_filter(o, filter, current_core_time);
});
#endif
//sort
CHECK_AND_ASSERT_MES(filter.order_by < gsort_offers_predicates.size(), false, "Wrong cof.order_by value");
auto cb = *gsort_offers_predicates[static_cast<size_t>(filter.order_by)];

View file

@ -191,8 +191,21 @@ namespace bc_services
inline double extract_rate(const odeh& v) { return calculate_offer_rate(v); }
inline size_t extract_payment_types(const odeh& v) { return v.payment_types.size(); }
inline std::string extract_contacts(const odeh& v) { return v.contacts; }
inline std::string extract_location(const odeh& v) { return currency::utf8_to_lower(v.location_country + v.location_city); }
inline std::string extract_name(const odeh& v) { return currency::utf8_to_lower(v.target); }
inline std::string extract_location(const odeh& v) {
#ifndef ANDROID_BUILD
return currency::utf8_to_lower(v.location_country + v.location_city);
#else
return "UNSUPORTED";
#endif
}
inline std::string extract_name(const odeh& v) {
#ifndef ANDROID_BUILD
return currency::utf8_to_lower(v.target);
#else
return "UNSUPORTED";
#endif
}
template<int sort_type>
struct sort_id_to_type

View file

@ -20,6 +20,7 @@
#include "warnings.h"
#include "crypto/hash.h"
#include "profile_tools.h"
#include "common/db_backend_selector.h"
DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated name length exceeded, name was truncated
@ -32,7 +33,6 @@ DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated
#define TRANSACTION_POOL_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION 92 // DON'T CHANGE THIS, if you need to resync db! Change TRANSACTION_POOL_MAJOR_COMPATIBILITY_VERSION instead!
#define TRANSACTION_POOL_MAJOR_COMPATIBILITY_VERSION BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION + 1
#define CURRENCY_POOLDATA_FOLDERNAME_SUFFIX "_v1"
#define CONFLICT_KEY_IMAGE_SPENT_DEPTH_TO_REMOVE_TX_FROM_POOL 50 // if there's a conflict in key images between tx in the pool and in the blockchain this much depth in required to remove correspongin tx from pool
@ -92,6 +92,16 @@ namespace currency
//---------------------------------------------------------------------------------
bool tx_memory_pool::add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core)
{
if (!kept_by_block && !from_core && m_blockchain.is_in_checkpoint_zone())
{
// BCS is in CP zone, tx verification is impossible until it gets synchronized
tvc.m_added_to_pool = false;
tvc.m_should_be_relayed = false;
tvc.m_verification_failed = false;
tvc.m_verification_impossible = true;
return false;
}
TIME_MEASURE_START_PD(tx_processing_time);
TIME_MEASURE_START_PD(check_inputs_types_supported_time);
if(!check_inputs_types_supported(tx))
@ -996,12 +1006,12 @@ namespace currency
std::vector<txv> txs_v;
txs_v.reserve(m_db_transactions.size());
std::vector<txv*> txs;
std::vector<size_t> txs; // selected transactions, vector of indices of txs_v
//keep getting it as a values cz db items cache will keep it as unserialised object stored by shared ptrs
m_db_transactions.enumerate_keys([&](uint64_t i, crypto::hash& k){txs_v.resize(i + 1); txs_v[i].first = k; return true;});
txs.resize(txs_v.size(), nullptr);
txs.resize(txs_v.size(), SIZE_MAX);
for (uint64_t i = 0; i != txs_v.size(); i++)
{
@ -1010,17 +1020,17 @@ namespace currency
if (!txs_v[i].second)
{
LOG_ERROR("Internal tx pool db error: key " << k << " was enumerated as key but couldn't get value");
continue;
return false;
}
txs[i] = &txs_v[i];
txs[i] = i;
}
std::sort(txs.begin(), txs.end(), [](txv *a, txv *b) -> bool {
std::sort(txs.begin(), txs.end(), [&txs_v](size_t a, size_t b) -> bool {
boost::multiprecision::uint128_t a_, b_;
a_ = boost::multiprecision::uint128_t(a->second->fee) * b->second->blob_size;
b_ = boost::multiprecision::uint128_t(b->second->fee) * a->second->blob_size;
a_ = boost::multiprecision::uint128_t(txs_v[a].second->fee) * txs_v[b].second->blob_size;
b_ = boost::multiprecision::uint128_t(txs_v[b].second->fee) * txs_v[a].second->blob_size;
return a_ > b_;
});
@ -1040,10 +1050,10 @@ namespace currency
// scan txs for alias reg requests - if there are such requests, don't process alias updates
bool alias_regs_exist = false;
for (auto txp : txs)
for (auto txi : txs)
{
tx_extra_info ei = AUTO_VAL_INIT(ei);
bool r = parse_and_validate_tx_extra(txp->second->tx, ei);
bool r = parse_and_validate_tx_extra(txs_v[txi].second->tx, ei);
CHECK_AND_ASSERT_MES(r, false, "parse_and_validate_tx_extra failed while looking up the tx pool");
if (!ei.m_alias.m_alias.empty() && !ei.m_alias.m_sign.size()) {
alias_regs_exist = true;
@ -1057,12 +1067,12 @@ namespace currency
for (size_t i = 0; i < txs.size(); i++)
{
txv &tx(*txs[i]);
txv &tx(txs_v[txs[i]]);
// expiration time check -- skip expired transactions
if (is_tx_expired(tx.second->tx, tx_expiration_ts_median))
{
txs[i] = nullptr;
txs[i] = SIZE_MAX;
continue;
}
@ -1076,7 +1086,7 @@ namespace currency
if ((alias_count >= MAX_ALIAS_PER_BLOCK) || // IF this tx registers/updates an alias AND alias per block threshold exceeded
(update_an_alias && alias_regs_exist)) // OR this tx updates an alias AND there are alias reg requests...
{
txs[i] = NULL; // ...skip this tx
txs[i] = SIZE_MAX; // ...skip this tx
continue;
}
}
@ -1094,7 +1104,7 @@ namespace currency
}
if (!is_tx_ready_to_go_result || have_key_images(k_images, tx.second->tx)) {
txs[i] = NULL;
txs[i] = SIZE_MAX;
continue;
}
append_key_images(k_images, tx.second->tx);
@ -1121,17 +1131,18 @@ namespace currency
for (size_t i = 0; i != txs.size(); i++)
{
if (txs[i])
if (txs[i] != SIZE_MAX)
{
txv &tx(txs_v[txs[i]]);
if (i < best_position)
{
bl.tx_hashes.push_back(txs[i]->first);
bl.tx_hashes.push_back(tx.first);
}
else if (have_attachment_service_in_container(txs[i]->second->tx.attachment, BC_OFFERS_SERVICE_ID, BC_OFFERS_SERVICE_INSTRUCTION_DEL))
else if (have_attachment_service_in_container(tx.second->tx.attachment, BC_OFFERS_SERVICE_ID, BC_OFFERS_SERVICE_INSTRUCTION_DEL))
{
// BC_OFFERS_SERVICE_INSTRUCTION_DEL transactions has zero fee, so include them here regardless of reward effectiveness
bl.tx_hashes.push_back(txs[i]->first);
total_size += txs[i]->second->blob_size;
bl.tx_hashes.push_back(tx.first);
total_size += tx.second->blob_size;
}
}
}
@ -1153,11 +1164,15 @@ namespace currency
//---------------------------------------------------------------------------------
bool tx_memory_pool::init(const std::string& config_folder, const boost::program_options::variables_map& vm)
{
if (!select_db_engine_from_arg(vm, m_db))
tools::db::db_backend_selector dbbs;
dbbs.init(vm);
auto p_backend = dbbs.create_backend();
if (!p_backend)
{
LOG_PRINT_RED_L0("Failed to select db engine");
LOG_PRINT_RED_L0("Failed to create db engine");
return false;
}
m_db.reset_backend(p_backend);
LOG_PRINT_L0("DB ENGINE USED BY POOL: " << m_db.get_backend()->name());
m_config_folder = config_folder;
@ -1165,7 +1180,7 @@ namespace currency
uint64_t cache_size_l1 = CACHE_SIZE;
LOG_PRINT_GREEN("Using pool db file cache size(L1): " << cache_size_l1, LOG_LEVEL_0);
// remove old incompartible DB
// remove old incompatible DB
const std::string old_db_folder_path = m_config_folder + "/" CURRENCY_POOLDATA_FOLDERNAME_OLD;
if (boost::filesystem::exists(epee::string_encoding::utf8_to_wstring(old_db_folder_path)))
{
@ -1173,7 +1188,7 @@ namespace currency
boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(old_db_folder_path));
}
const std::string db_folder_path = m_config_folder + ("/" CURRENCY_POOLDATA_FOLDERNAME_PREFIX) + m_db.get_backend()->name() + CURRENCY_POOLDATA_FOLDERNAME_SUFFIX;
const std::string db_folder_path = dbbs.get_pool_db_folder_path();
LOG_PRINT_L0("Loading blockchain from " << db_folder_path << "...");
@ -1192,8 +1207,6 @@ namespace currency
res = m_db_transactions.init(TRANSACTION_POOL_CONTAINER_TRANSACTIONS);
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
// res = m_db_key_images_set.init(TRANSACTION_POOL_CONTAINER_KEY_IMAGES);
// CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
res = m_db_black_tx_list.init(TRANSACTION_POOL_CONTAINER_BLACK_TX_LIST);
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
res = m_db_alias_names.init(TRANSACTION_POOL_CONTAINER_ALIAS_NAMES);

View file

@ -159,7 +159,6 @@ namespace currency
typedef tools::db::cached_key_value_accessor<crypto::hash, tx_details, true, false> transactions_container;
typedef tools::db::cached_key_value_accessor<crypto::hash, bool, false, false> hash_container;
//typedef tools::db::cached_key_value_accessor<crypto::key_image, uint64_t, false, false> key_images_container;
typedef tools::db::cached_key_value_accessor<uint64_t, uint64_t, false, true> solo_options_container;
typedef tools::db::cached_key_value_accessor<std::string, bool, false, false> aliases_container;
typedef tools::db::cached_key_value_accessor<account_public_address, bool, false, false> address_to_aliases_container;
@ -172,7 +171,6 @@ namespace currency
transactions_container m_db_transactions;
hash_container m_db_black_tx_list;
//key_images_container m_db_key_images_set;
aliases_container m_db_alias_names;
address_to_aliases_container m_db_alias_addresses;
solo_options_container m_db_solo_options;

View file

@ -96,7 +96,6 @@ namespace currency
nodetool::p2p_endpoint_stub<connection_context> m_p2p_stub;
nodetool::i_p2p_endpoint<connection_context>* m_p2p;
std::atomic<uint32_t> m_syncronized_connections_count;
std::atomic<bool> m_synchronized;
std::atomic<bool> m_have_been_synchronized;
std::atomic<uint64_t> m_max_height_seen;

View file

@ -15,7 +15,6 @@ namespace currency
t_currency_protocol_handler<t_core>::t_currency_protocol_handler(t_core& rcore, nodetool::i_p2p_endpoint<connection_context>* p_net_layout)
: m_core(rcore)
, m_p2p(p_net_layout)
, m_syncronized_connections_count(0)
, m_synchronized(false)
, m_have_been_synchronized(false)
, m_max_height_seen(0)
@ -179,17 +178,17 @@ namespace currency
&& m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() < hshd.last_checkpoint_height
&& m_core.get_current_blockchain_size() < hshd.last_checkpoint_height )
{
LOG_PRINT_RED("Remote node have longer checkpoints zone( " << hshd.last_checkpoint_height << ") " <<
"that local (" << m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() << ")" <<
"That means that current software is outdated, please updated it." <<
"Current heigh lay under checkpoints on remote host, so it is not possible validate this transactions on local host, disconnecting.", LOG_LEVEL_0);
LOG_PRINT_RED("Remote node has longer checkpoints zone (" << hshd.last_checkpoint_height << ") " <<
"than local (" << m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() << "). " <<
"It means that current software is outdated, please updated it! " <<
"Current height lays under checkpoints zone on remote host, so it's impossible to validate remote transactions locally, disconnecting.", LOG_LEVEL_0);
return false;
}
else if (m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() < hshd.last_checkpoint_height)
{
LOG_PRINT_MAGENTA("Remote node have longer checkpoints zone( " << hshd.last_checkpoint_height << ") " <<
"that local (" << m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() << ")" <<
"That means that current software is outdated, please updated it.", LOG_LEVEL_0);
LOG_PRINT_MAGENTA("Remote node has longer checkpoints zone (" << hshd.last_checkpoint_height << ") " <<
"than local (" << m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() << "). " <<
"It means that current software is outdated, please updated it!", LOG_LEVEL_0);
}
context.m_state = currency_connection_context::state_synchronizing;
@ -606,25 +605,19 @@ namespace currency
template<class t_core>
bool t_currency_protocol_handler<t_core>::on_idle()
{
bool have_synced_conn = false;
m_p2p->for_each_connection([&](currency_connection_context& context, nodetool::peerid_type peer_id)->bool{
if (context.m_state == currency_connection_context::state_normal)
{
have_synced_conn = true;
return false;
}
return true;
});
size_t synchronized_connections_count = get_synchronized_connections_count();
size_t total_connections_count = m_p2p->get_connections_count();
bool have_enough_synchronized_connections = synchronized_connections_count > total_connections_count / 2;
if (have_synced_conn && !m_synchronized)
if (have_enough_synchronized_connections && !m_synchronized)
{
on_connection_synchronized();
m_synchronized = true;
LOG_PRINT_MAGENTA("Synchronized set to TRUE (idle)", LOG_LEVEL_0);
LOG_PRINT_MAGENTA("Synchronized set to TRUE (" << synchronized_connections_count << " of " << total_connections_count << " conn. synced)", LOG_LEVEL_0);
}
else if (!have_synced_conn && m_synchronized)
else if (!have_enough_synchronized_connections && m_synchronized)
{
LOG_PRINT_MAGENTA("Synchronized set to FALSE (idle)", LOG_LEVEL_0);
LOG_PRINT_MAGENTA("Synchronized set to FALSE (" << synchronized_connections_count << " of " << total_connections_count << " conn. synced)", LOG_LEVEL_0);
m_synchronized = false;
}

View file

@ -27,6 +27,7 @@ using namespace epee;
#include "version.h"
#include "currency_core/core_tools.h"
#include "common/callstack_helper.h"
#include "common/pre_download.h"
#include <cstdlib>
@ -148,6 +149,11 @@ int main(int argc, char* argv[])
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);
command_line::add_arg(desc_cmd_sett, command_line::arg_no_predownload);
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);
arg_market_disable.default_value = true;
arg_market_disable.not_use_default = false;
@ -159,7 +165,7 @@ int main(int argc, char* argv[])
currency::miner::init_options(desc_cmd_sett);
bc_services::bc_offers_service::init_options(desc_cmd_sett);
currency::stratum_server::init_options(desc_cmd_sett);
tools::db::db_backend_selector::init_options(desc_cmd_sett);
po::options_description desc_options("Allowed options");
desc_options.add(desc_cmd_only).add(desc_cmd_sett);
@ -270,8 +276,25 @@ int main(int argc, char* argv[])
LOG_PRINT_L0(generate_reference << ENDL << "----------------------------------------" << ENDL << json_rpc_reference);
}
bool res = false;
//do pre_download if needed
if (!command_line::has_arg(vm, command_line::arg_no_predownload) || command_line::has_arg(vm, command_line::arg_force_predownload))
{
auto is_stop_signal_sent = [&p2psrv]() -> bool {
return static_cast<nodetool::i_p2p_endpoint<currency::t_currency_protocol_handler<currency::core>::connection_context>*>(&p2psrv)->is_stop_signal_sent();
};
if (!tools::process_predownload(vm, [&](uint64_t total_bytes, uint64_t received_bytes) { return is_stop_signal_sent(); }))
{
return EXIT_FAILURE;
}
if (is_stop_signal_sent())
return 1;
}
//initialize objects
LOG_PRINT_L0("Initializing p2p server...");
res = p2psrv.init(vm);

View file

@ -12,6 +12,7 @@
#include "string_coding.h"
#include "gui_utils.h"
#include "notification_helper.h"
#include "common/config_encrypt_helper.h"
#define PREPARE_ARG_FROM_JSON(arg_type, var_name) \
arg_type var_name = AUTO_VAL_INIT(var_name); \
@ -22,8 +23,23 @@ if (!epee::serialization::load_t_from_json(var_name, param.toStdString())) \
return MAKE_RESPONSE(default_ar); \
}
#define PREPARE_RESPONSE(rsp_type, var_name) view::api_response_t<rsp_type> var_name = AUTO_VAL_INIT(var_name);
#define MAKE_RESPONSE(r) epee::serialization::store_t_to_json(r).c_str();
template<typename T>
QString make_response(const T& r)
{
std::string str = epee::serialization::store_t_to_json(r);
return str.c_str();
}
template<typename T>
QString make_response_dbg(const T& r, const std::string& location)
{
std::string str = epee::serialization::store_t_to_json(r);
LOG_PRINT_YELLOW("***** API RESPONSE from " << location << " : " << ENDL << str, LOG_LEVEL_0);
return str.c_str();
}
#define PREPARE_RESPONSE(rsp_type, var_name) view::api_response_t<rsp_type> var_name = AUTO_VAL_INIT(var_name)
#define MAKE_RESPONSE(r) (r.error_code == API_RETURN_CODE_OK || r.error_code == API_RETURN_CODE_TRUE) ? make_response(r) : make_response_dbg(r, LOCATION_STR)
#define LOG_API_TIMING() const char* pfunc_call_name = LOCAL_FUNCTION_DEF__; LOG_PRINT_BLUE("[API:" << pfunc_call_name << "]-->>", LOG_LEVEL_0); uint64_t ticks_before_start = epee::misc_utils::get_tick_count(); \
auto cb_leave = epee::misc_utils::create_scope_leave_handler([&ticks_before_start, &pfunc_call_name](){ \
@ -304,7 +320,9 @@ bool MainWindow::store_app_config()
{
TRY_ENTRY();
std::string conf_path = m_backend.get_config_folder() + "/" + GUI_INTERNAL_CONFIG;
return tools::serialize_obj_to_file(m_config, conf_path);
LOG_PRINT_L0("storing gui internal config from " << conf_path);
CHECK_AND_ASSERT_MES(tools::serialize_obj_to_file(m_config, conf_path), false, "failed to store gui internal config");
return true;
CATCH_ENTRY2(false);
}
@ -312,7 +330,10 @@ bool MainWindow::load_app_config()
{
TRY_ENTRY();
std::string conf_path = m_backend.get_config_folder() + "/" + GUI_INTERNAL_CONFIG;
return tools::unserialize_obj_from_file(m_config, conf_path);
LOG_PRINT_L0("loading gui internal config from " << conf_path);
bool r = tools::unserialize_obj_from_file(m_config, conf_path);
LOG_PRINT_L0("gui internal config " << (r ? "loaded ok" : "was not loaded"));
return r;
CATCH_ENTRY2(false);
}
@ -1042,6 +1063,35 @@ void MainWindow::on_clear_events()
CATCH_ENTRY2(void());
}
QString MainWindow::store_secure_app_data(const QString& param)
{
TRY_ENTRY();
LOG_API_TIMING();
if (!tools::create_directories_if_necessary(m_backend.get_config_folder()))
{
view::api_response ar;
LOG_PRINT_L0("Failed to create data directory: " << m_backend.get_config_folder());
ar.error_code = API_RETURN_CODE_FAIL;
return MAKE_RESPONSE(ar);
}
view::api_response ar = AUTO_VAL_INIT(ar);
ar.error_code = tools::store_encrypted_file(m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME,
m_master_password, param.toStdString(), APP_DATA_FILE_BINARY_SIGNATURE);
if (ar.error_code != API_RETURN_CODE_OK)
{
return MAKE_RESPONSE(ar);
}
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
LOG_PRINT_L0("store_secure_app_data, r = " << ar.error_code << ", pass hash: " << master_password_hash);
return MAKE_RESPONSE(ar);
CATCH_ENTRY_FAIL_API_RESPONCE();
}
QString MainWindow::get_secure_app_data(const QString& param)
{
TRY_ENTRY();
@ -1055,41 +1105,21 @@ QString MainWindow::get_secure_app_data(const QString& param)
return MAKE_RESPONSE(ar);
}
std::string app_data_buff;
std::string filename = m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME;
bool r = file_io_utils::load_file_to_string(filename, app_data_buff);
if (!r)
std::string res_body;
std::string rsp_code = tools::load_encrypted_file(filename, pwd.pass, res_body, APP_DATA_FILE_BINARY_SIGNATURE);
if (rsp_code != API_RETURN_CODE_OK)
{
LOG_PRINT_L1("config file was not loaded: " << m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME);
return "";
}
if (app_data_buff.size() < sizeof(app_data_file_binary_header))
{
LOG_ERROR("app_data_buff.size() < sizeof(app_data_file_binary_header) check failed");
view::api_response ar;
ar.error_code = API_RETURN_CODE_FAIL;
ar.error_code = rsp_code;
return MAKE_RESPONSE(ar);
}
crypto::chacha_crypt(app_data_buff, pwd.pass);
const app_data_file_binary_header* phdr = reinterpret_cast<const app_data_file_binary_header*>(app_data_buff.data());
if (phdr->m_signature != APP_DATA_FILE_BINARY_SIGNATURE)
{
LOG_ERROR("password missmatch");
view::api_response ar;
ar.error_code = API_RETURN_CODE_WRONG_PASSWORD;
return MAKE_RESPONSE(ar);
}
m_master_password = pwd.pass;
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
LOG_PRINT_L0("get_secure_app_data, pass hash: " << master_password_hash);
LOG_PRINT_L0("gui secure config loaded ok from " << filename << ", pass hash: " << master_password_hash);
return app_data_buff.substr(sizeof(app_data_file_binary_header)).c_str();
return res_body.c_str();
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
}
@ -1161,10 +1191,6 @@ QString MainWindow::store_app_data(const QString& param)
return MAKE_RESPONSE(ar);
}
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
LOG_PRINT_L0("store_app_data, pass hash: " << master_password_hash);
std::string filename = m_backend.get_config_folder() + "/" + GUI_CONFIG_FILENAME;
bool r = file_io_utils::save_string_to_file(filename, param.toStdString());
if (r)
@ -1266,40 +1292,6 @@ QString MainWindow::get_app_data()
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
}
QString MainWindow::store_secure_app_data(const QString& param)
{
TRY_ENTRY();
LOG_API_TIMING();
if (!tools::create_directories_if_necessary(m_backend.get_config_folder()))
{
view::api_response ar;
LOG_PRINT_L0("Failed to create data directory: " << m_backend.get_config_folder());
return MAKE_RESPONSE(ar);
}
std::string buff(sizeof(app_data_file_binary_header), 0);
app_data_file_binary_header* phdr = (app_data_file_binary_header*)buff.data();
phdr->m_signature = APP_DATA_FILE_BINARY_SIGNATURE;
phdr->m_cb_body = 0; // for future use
buff.append(param.toStdString());
crypto::chacha_crypt(buff, m_master_password);
bool r = file_io_utils::save_string_to_file(m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME, buff);
view::api_response ar;
if (r)
ar.error_code = API_RETURN_CODE_OK;
else
ar.error_code = API_RETURN_CODE_FAIL;
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
LOG_PRINT_L0("store_secure_app_data, r = " << r << ", pass hash: " << master_password_hash);
return MAKE_RESPONSE(ar);
CATCH_ENTRY_FAIL_API_RESPONCE();
}
QString MainWindow::have_secure_app_data()
{
@ -1313,6 +1305,8 @@ QString MainWindow::have_secure_app_data()
else
ar.error_code = API_RETURN_CODE_FALSE;
LOG_PRINT_L0("have_secure_app_data, r = " << ar.error_code);
return MAKE_RESPONSE(ar);
CATCH_ENTRY_FAIL_API_RESPONCE();
}
@ -1328,6 +1322,9 @@ QString MainWindow::drop_secure_app_data()
ar.error_code = API_RETURN_CODE_TRUE;
else
ar.error_code = API_RETURN_CODE_FALSE;
LOG_PRINT_L0("drop_secure_app_data, r = " << ar.error_code);
return MAKE_RESPONSE(ar);
CATCH_ENTRY_FAIL_API_RESPONCE();
}

View file

@ -7,9 +7,10 @@
#include <QtWidgets>
#include <QWebChannel>
#include "view_iface.h"
#include "wallet/view_iface.h"
#ifndef Q_MOC_RUN
#include "daemon_backend.h"
#include "wallet/wallets_manager.h"
#include "currency_core/offers_services_helpers.h"
#endif
@ -18,13 +19,7 @@ class QWebEngineView;
class QLineEdit;
QT_END_NAMESPACE
#pragma pack(push, 1)
struct app_data_file_binary_header
{
uint64_t m_signature;
uint64_t m_cb_body;
};
#pragma pack (pop)
#define APP_DATA_FILE_BINARY_SIGNATURE 0x1000111101101021LL
@ -227,7 +222,7 @@ private:
QWebChannel* m_channel;
// DATA
daemon_backend m_backend;
wallets_manager m_backend;
//std::atomic<bool> m_quit_requested;
std::atomic<bool> m_gui_deinitialize_done_1;
std::atomic<bool> m_backend_stopped_2;

View file

@ -50,7 +50,9 @@
"COMPLETE": "Completion",
"SYNCING": "Syncing block",
"LOADING": "Loading blockchain data",
"SLASH": "/"
"DOWNLOADING": "Downloading",
"SLASH": "/",
"MB": "MB"
},
"UPDATE": {
"STANDARD": "Update available",

View file

@ -32,6 +32,13 @@ app-sidebar {
color: themed(mainTextColor);
}
.icon {
@include themify($themes) {
background-color: themed(blueTextColor);
}
}
.sidebar-account-row {
.text {
@ -220,6 +227,23 @@ app-sidebar {
}
}
}
&.downloading {
.progress-bar {
@include themify($themes) {
background-color: themed(progressBarBackgroundColor);
}
.fill {
@include themify($themes) {
background-color: themed(blueTextColor);
}
}
}
}
}
.loading {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -649,7 +649,7 @@ module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
/*! no static exports found */
/***/ (function(module, exports) {
var core = module.exports = { version: '2.6.10' };
var core = module.exports = { version: '2.6.11' };
if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef
@ -5800,8 +5800,8 @@ __webpack_require__.r(__webpack_exports__);
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
__webpack_require__(/*! c:\Users\Admin\Desktop\zano\src\gui\qt-daemon\html_source\src\polyfills.ts */"./src/polyfills.ts");
module.exports = __webpack_require__(/*! c:\Users\Admin\Desktop\zano\src\gui\qt-daemon\html_source\node_modules\@angular-devkit\build-angular\src\angular-cli-files\models\jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
__webpack_require__(/*! C:\Users\Admin\Desktop\zano\src\gui\qt-daemon\html_source\src\polyfills.ts */"./src/polyfills.ts");
module.exports = __webpack_require__(/*! C:\Users\Admin\Desktop\zano\src\gui\qt-daemon\html_source\node_modules\@angular-devkit\build-angular\src\angular-cli-files\models\jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
/***/ })

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -8,6 +8,7 @@
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.25);
z-index: 5;
}
.modal {
position: relative;

View file

@ -23,6 +23,8 @@ export class VariablesService {
public net_time_delta_median = 0;
public height_app = 0;
public height_max = 0;
public downloaded = 0;
public total = 0;
public last_build_available = '';
public last_build_displaymode = 0;
public daemon_state = 3;
@ -30,6 +32,10 @@ export class VariablesService {
progress_value: 0,
progress_value_text: '0'
};
public download = {
progress_value: 0,
progress_value_text: '0'
};
public default_fee = '0.010000000000';
public default_fee_big = new BigNumber('10000000000');
@ -66,6 +72,8 @@ export class VariablesService {
getExpMedTsEvent = new BehaviorSubject(null);
getHeightAppEvent = new BehaviorSubject(null);
getHeightMaxEvent = new BehaviorSubject(null);
getDownloadedAppEvent = new BehaviorSubject(null);
getTotalEvent = new BehaviorSubject(null);
getRefreshStackingEvent = new BehaviorSubject(null);
getAliasChangedEvent = new BehaviorSubject(null);
@ -112,6 +120,20 @@ export class VariablesService {
}
}
setDownloadedBytes(bytes: number) {
if (bytes !== this.downloaded) {
this.downloaded = this.bytesToMb(bytes);
this.getDownloadedAppEvent.next(bytes);
}
}
setTotalBytes(bytes: number) {
if (bytes !== this.total) {
this.total = this.bytesToMb(bytes);
this.getTotalEvent.next(bytes);
}
}
setRefreshStacking(wallet_id: number) {
this.getHeightAppEvent.next(wallet_id);
}
@ -149,6 +171,10 @@ export class VariablesService {
this.idle.within(this.settings.appLockTime).restart();
}
bytesToMb(bytes) {
return Number((bytes / Math.pow(1024, 2)).toFixed(1));
}
public onContextMenu($event: MouseEvent): void {
$event.target['contextSelectionStart'] = $event.target['selectionStart'];
$event.target['contextSelectionEnd'] = $event.target['selectionEnd'];

View file

@ -1,7 +1,7 @@
<app-sidebar *ngIf="variablesService.appLogin"></app-sidebar>
<div class="app-content scrolled-content">
<router-outlet *ngIf="[0, 1, 2].indexOf(variablesService.daemon_state) !== -1"></router-outlet>
<router-outlet *ngIf="[0, 1, 2, 6].indexOf(variablesService.daemon_state) !== -1"></router-outlet>
<div class="preloader" *ngIf="[3, 4, 5].indexOf(variablesService.daemon_state) !== -1">
<span *ngIf="variablesService.daemon_state === 3">{{ 'SIDEBAR.SYNCHRONIZATION.LOADING' | translate }}</span>
<span *ngIf="variablesService.daemon_state === 4">{{ 'SIDEBAR.SYNCHRONIZATION.ERROR' | translate }}</span>

View file

@ -185,6 +185,10 @@ export class AppComponent implements OnInit, OnDestroy {
this.variablesService.last_build_displaymode = data.last_build_displaymode;
this.variablesService.setHeightApp(data.height);
this.variablesService.setHeightMax(data.max_net_seen_height);
this.variablesService.setDownloadedBytes(data.downloaded_bytes);
this.variablesService.setTotalBytes(data.download_total_data_size);
this.backend.getContactAlias();
this.ngZone.run(() => {
this.variablesService.daemon_state = data['daemon_network_state'];
@ -203,6 +207,22 @@ export class AppComponent implements OnInit, OnDestroy {
this.variablesService.sync.progress_value_text = return_val.toFixed(2);
}
}
if (data['daemon_network_state'] === 6) {
const max = data['download_total_data_size'];
const current = data['downloaded_bytes'];
const return_val = Math.floor((current / max) * 100);
if (max === 0 || return_val < 0) {
this.variablesService.download.progress_value = 0;
this.variablesService.download.progress_value_text = '0.00';
} else if (return_val >= 100) {
this.variablesService.download.progress_value = 100;
this.variablesService.download.progress_value_text = '99.99';
} else {
this.variablesService.download.progress_value = return_val;
this.variablesService.download.progress_value_text = return_val.toFixed(2);
}
}
});
if (!this.firstOnlineState && data['daemon_network_state'] === 2) {
this.getAliases();
@ -245,13 +265,15 @@ export class AppComponent implements OnInit, OnDestroy {
let tr_exists = wallet.excluded_history.some(elem => elem.tx_hash === tr_info.tx_hash);
tr_exists = (!tr_exists) ? wallet.history.some(elem => elem.tx_hash === tr_info.tx_hash) : tr_exists;
wallet.prepareHistory([tr_info]);
if (wallet.restore) {
wallet.total_history_item = wallet.history.length;
wallet.totalPages = Math.ceil( wallet.total_history_item / this.variablesService.count);
wallet.totalPages > this.variablesService.maxPages
? wallet.pages = new Array(5).fill(1).map((value, index) => value + index)
: wallet.pages = new Array(wallet.totalPages).fill(1).map((value, index) => value + index);
if (wallet.currentPage === 1) {
wallet.prepareHistory([tr_info]);
if (wallet.restore) {
wallet.total_history_item = wallet.history.length;
wallet.totalPages = Math.ceil( wallet.total_history_item / this.variablesService.count);
wallet.totalPages > this.variablesService.maxPages
? wallet.pages = new Array(5).fill(1).map((value, index) => value + index)
: wallet.pages = new Array(wallet.totalPages).fill(1).map((value, index) => value + index);
}
}
if (tr_info.hasOwnProperty('contract')) {

View file

@ -4,6 +4,11 @@
</div>
<div class="sidebar-accounts-list scrolled-content">
<div class="sidebar-account" *ngFor="let wallet of variablesService.wallets" [class.active]="wallet?.wallet_id === walletActive" [routerLink]="['/wallet/' + wallet.wallet_id + '/history']">
<div class="close-wallet-wrapper">
<button type="button" (click)="showDialog(wallet.wallet_id)" tooltip="{{ 'WALLET.TOOLTIPS.CLOSE' | translate }}" placement="top-left" tooltipClass="table-tooltip account-tooltip" [delay]="500" [timeDelay]="500">
<i class="icon close-wallet"></i>
</button>
</div>
<div class="sidebar-account-row account-title-balance">
<span class="title" tooltip="{{ wallet.name }}" placement="top-left" tooltipClass="table-tooltip account-tooltip" [delay]="500" [showWhenNoOverflow]="false">{{wallet.name}}</span>
<span class="balance">{{wallet.balance | intToMoney : '3' }} {{variablesService.defaultCurrency}}</span>
@ -93,7 +98,7 @@
</div>
</ng-template>
</div>
<div class="sidebar-synchronization-status" [ngStyle]="{'align-items': variablesService.daemon_state === 1 ? 'flex-start' : 'center'}">
<div class="sidebar-synchronization-status" [ngStyle]="{'align-items': variablesService.daemon_state === 1 || variablesService.daemon_state === 6 ? 'flex-start' : 'center'}">
<div class="status-container">
<span class="offline" *ngIf="variablesService.daemon_state === 0">
{{ 'SIDEBAR.SYNCHRONIZATION.OFFLINE' | translate }}
@ -113,6 +118,9 @@
<span class="online" *ngIf="variablesService.daemon_state === 5">
{{ 'SIDEBAR.SYNCHRONIZATION.COMPLETE' | translate }}
</span>
<span class="syncing" *ngIf="variablesService.daemon_state === 6">
{{ 'SIDEBAR.SYNCHRONIZATION.DOWNLOADING' | translate }} {{ variablesService.downloaded }}{{ 'SIDEBAR.SYNCHRONIZATION.SLASH' | translate }}{{ variablesService.total }}{{ 'SIDEBAR.SYNCHRONIZATION.MB' | translate }}
</span>
<div class="progress-bar-container" *ngIf="variablesService.daemon_state === 1 || variablesService.daemon_state === 3">
<div class="syncing" *ngIf="variablesService.daemon_state === 1">
<div class="progress-bar">
@ -122,6 +130,15 @@
</div>
<div class="loading" *ngIf="variablesService.daemon_state === 3"></div>
</div>
<div class="progress-bar-container" *ngIf="variablesService.daemon_state === 6">
<div class="syncing downloading" *ngIf="variablesService.daemon_state === 6">
<div class="progress-bar">
<div class="fill" [style.width]="variablesService.download.progress_value + '%'"></div>
</div>
<div class="progress-percent">{{ variablesService.download.progress_value_text }}%</div>
</div>
</div>
</div>
<div class="update-container" *ngIf="(variablesService.daemon_state === 0 || variablesService.daemon_state === 2) && [2, 3, 4].indexOf(variablesService.last_build_displaymode) !== -1">
<ng-container *ngIf="variablesService.last_build_displaymode === 2">
@ -155,3 +172,4 @@
</div>
</div>
<app-confirm-modal *ngIf="isModalDialogVisible" [title]=" 'WALLET.CONFIRM.TITLE' | translate " [message]=" 'WALLET.CONFIRM.MESSAGE' | translate " (confirmed)="confirmed($event)"></app-confirm-modal>

View file

@ -62,6 +62,31 @@
flex-shrink: 0;
cursor: pointer;
padding: 2rem 3rem;
.close-wallet-wrapper {
display: flex;
justify-content: flex-end;
position: relative;
button {
display: flex;
position: absolute;
padding: 0;
height: auto;
background: transparent;
border: none;
margin: -1.3rem 1.6rem;
.icon {
width: 1.3rem;
height: 1.3rem;
&.close-wallet {
mask: url(../../assets/icons/close-wallet.svg) no-repeat center;
}
}
}
}
.sidebar-account-row {
display: flex;
@ -179,6 +204,8 @@
}
}
}
}
&:focus {

View file

@ -20,6 +20,9 @@ export class SidebarComponent implements OnInit, OnDestroy {
settings = icons.settings;
exit = icons.exit;
isModalDialogVisible = false;
closeWalletId: number;
constructor(
private route: ActivatedRoute,
private router: Router,
@ -68,6 +71,39 @@ export class SidebarComponent implements OnInit, OnDestroy {
}
}
showDialog(wallet_id) {
this.isModalDialogVisible = true;
this.closeWalletId = wallet_id;
}
confirmed(confirmed: boolean) {
if (confirmed) {
this.closeWallet(this.closeWalletId);
}
this.isModalDialogVisible = false;
}
closeWallet(wallet_id) {
this.backend.closeWallet(wallet_id, () => {
for (let i = this.variablesService.wallets.length - 1; i >= 0; i--) {
if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {
this.variablesService.wallets.splice(i, 1);
}
}
this.ngZone.run(() => {
if (this.variablesService.wallets.length) {
this.variablesService.currentWallet = this.variablesService.wallets[0];
this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);
} else {
this.router.navigate(['/']);
}
});
if (this.variablesService.appPass) {
this.backend.storeSecureAppData();
}
});
}
getUpdate() {
this.backend.openUrlInBrowser('zano.org/downloads.html');
}

View file

@ -16,7 +16,7 @@
</div>
</div>
<div class="selected" *ngIf="selectedDate && selectedDate.date">
<span>{{selectedDate.date | date : 'MMM. EEEE, dd, yyyy'}}</span>
<span>{{selectedDate.date | date : 'EEEE, MMMM d, y'}}</span>
<span>{{selectedDate.amount}} {{variablesService.defaultCurrency}}</span>
</div>
</div>

View file

@ -24,7 +24,7 @@
<label for="alias-comment">
{{ 'TRANSFER_ALIAS.COMMENT.LABEL' | translate }}
</label>
<textarea id="alias-comment" [value]="alias.comment" placeholder="{{ 'EDIT_ALIAS.COMMENT.PLACEHOLDER' | translate }}" readonly></textarea>
<textarea id="alias-comment" [value]="alias.comment" placeholder="{{ 'EDIT_ALIAS.COMMENT.PLACEHOLDER' | translate }}"></textarea>
</div>
<div class="input-block alias-transfer-address">

View file

@ -17,9 +17,6 @@
<button [routerLink]="['/details']" routerLinkActive="active" tooltip="{{ 'WALLET.TOOLTIPS.SETTINGS' | translate }}" placement="left" tooltipClass="table-tooltip account-tooltip" [delay]="500" [timeDelay]="500">
<i class="icon details"></i>
</button>
<button type="button" (click)="showDialog()" tooltip="{{ 'WALLET.TOOLTIPS.CLOSE' | translate }}" placement="bottom-right" tooltipClass="table-tooltip account-tooltip" [delay]="500" [timeDelay]="500">
<i class="icon close-wallet"></i>
</button>
</div>
</div>
<div class="address">
@ -57,5 +54,3 @@
</div>
</div>
</div>
<app-confirm-modal *ngIf="isModalDialogVisible" [title]=" 'WALLET.CONFIRM.TITLE' | translate " [message]=" 'WALLET.CONFIRM.MESSAGE' | translate " (confirmed)="confirmed($event)"></app-confirm-modal>

View file

@ -22,7 +22,6 @@ export class WalletComponent implements OnInit, OnDestroy {
copyAnimation = false;
copyAnimationTimeout;
balanceTooltip;
isModalDialogVisible = false;
activeTab = 'history';
public currentPage = 1;
@ -189,38 +188,6 @@ export class WalletComponent implements OnInit, OnDestroy {
this.backend.openUrlInBrowser(link);
}
showDialog() {
this.isModalDialogVisible = true;
}
confirmed(confirmed: boolean) {
if (confirmed) {
this.closeWallet();
}
this.isModalDialogVisible = false;
}
closeWallet() {
this.backend.closeWallet(this.variablesService.currentWallet.wallet_id, () => {
for (let i = this.variablesService.wallets.length - 1; i >= 0; i--) {
if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {
this.variablesService.wallets.splice(i, 1);
}
}
this.ngZone.run(() => {
if (this.variablesService.wallets.length) {
this.variablesService.currentWallet = this.variablesService.wallets[0];
this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);
} else {
this.router.navigate(['/']);
}
});
if (this.variablesService.appPass) {
this.backend.storeSecureAppData();
}
});
}
public setPage(pageNumber: number) {
if (pageNumber === this.variablesService.currentWallet.currentPage) {
return;
@ -238,6 +205,9 @@ export class WalletComponent implements OnInit, OnDestroy {
this.variablesService.currentWallet.restore = false;
this.variablesService.currentWallet.total_history_item = data.total_history_items;
this.variablesService.currentWallet.prepareHistory(data.history);
if (this.variablesService.currentWallet.currentPage === 1 && data.unconfirmed) {
this.variablesService.currentWallet.prepareHistory(data.unconfirmed);
}
}
});
}

View file

@ -50,7 +50,9 @@
"COMPLETE": "Completion",
"SYNCING": "Syncing block",
"LOADING": "Loading blockchain data",
"SLASH": "/"
"DOWNLOADING": "Downloading",
"SLASH": "/",
"MB": "MB"
},
"UPDATE": {
"STANDARD": "Update available",

View file

@ -32,6 +32,13 @@ app-sidebar {
color: themed(mainTextColor);
}
.icon {
@include themify($themes) {
background-color: themed(blueTextColor);
}
}
.sidebar-account-row {
.text {
@ -220,6 +227,23 @@ app-sidebar {
}
}
}
&.downloading {
.progress-bar {
@include themify($themes) {
background-color: themed(progressBarBackgroundColor);
}
.fill {
@include themify($themes) {
background-color: themed(blueTextColor);
}
}
}
}
}
.loading {

View file

@ -60,6 +60,11 @@ int main(int argc, char *argv[])
#endif
#endif
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_0);
log_space::get_set_need_thread_id(true, true);
log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,p2p,wallet");
QApplication app(argc, argv);
MainWindow viewer;
if (!viewer.init_backend(argc, argv))

View file

@ -100,7 +100,7 @@ namespace currency
res.current_max_allowed_block_size = m_core.get_blockchain_storage().get_current_comulative_blocksize_limit();
if (!res.outgoing_connections_count)
res.daemon_network_state = COMMAND_RPC_GET_INFO::daemon_network_state_connecting;
else if (res.synchronized_connections_count > total_conn/2 ) /* m_p2p.get_payload_object().is_synchronized()*/
else if (m_p2p.get_payload_object().is_synchronized())
res.daemon_network_state = COMMAND_RPC_GET_INFO::daemon_network_state_online;
else
res.daemon_network_state = COMMAND_RPC_GET_INFO::daemon_network_state_synchronizing;
@ -386,6 +386,9 @@ namespace currency
return true;
}
res.tx_expiration_ts_median = m_core.get_blockchain_storage().get_tx_expiration_median();
for(auto& tx: txs)
{
res.txs.push_back(t_serializable_object_to_blob(tx));
@ -393,6 +396,7 @@ namespace currency
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_scan_pos(const COMMAND_RPC_SCAN_POS::request& req, COMMAND_RPC_SCAN_POS::response& res, connection_context& cntx)
{
CHECK_CORE_READY();
@ -880,10 +884,10 @@ namespace currency
}
//@#@
//temporary double check timestamp
if (time(NULL) - get_actual_timestamp(b) > 5)
if (time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) > 5)
{
LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
<< ") is suspiciously less (" << time(NULL) - get_actual_timestamp(b) << ") then curren time( " << time(NULL) << ")");
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")");
//mark node to make it easier to find it via scanner
m_core.get_blockchain_storage().get_performnce_data().epic_failure_happend = true;
}
@ -937,10 +941,10 @@ namespace currency
}
//@#@
//temporary double check timestamp
if (time(NULL) - get_actual_timestamp(b) > 5)
if (time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) > 5)
{
LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
<< ") is suspiciously less (" << time(NULL) - get_actual_timestamp(b) << ") then curren time( " << time(NULL) << ")");
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")");
//mark node to make it easier to find it via scanner
m_core.get_blockchain_storage().get_performnce_data().epic_failure_happend = true;
}

View file

@ -155,7 +155,6 @@ namespace currency
MAP_JON_RPC ("get_current_core_tx_expiration_median", on_get_current_core_tx_expiration_median, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN)
//
MAP_JON_RPC_WE("marketplace_global_get_offers_ex", on_get_offers_ex, COMMAND_RPC_GET_OFFERS_EX)
//remote miner rpc
MAP_JON_RPC_N(on_login, mining::COMMAND_RPC_LOGIN)
MAP_JON_RPC_N(on_getjob, mining::COMMAND_RPC_GETJOB)

View file

@ -181,10 +181,12 @@ namespace currency
struct response
{
std::list<blobdata> txs; //transactions blobs
uint64_t tx_expiration_ts_median;
std::string status;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(txs)
KV_SERIALIZE(tx_expiration_ts_median)
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};
@ -614,7 +616,8 @@ namespace currency
daemon_network_state_online = 2,
daemon_network_state_loading_core = 3,
daemon_network_state_internal_error = 4,
daemon_network_state_unloading_core = 5
daemon_network_state_unloading_core = 5,
daemon_network_state_downloading_database = 6
};
struct response

View file

@ -198,9 +198,9 @@ simple_wallet::simple_wallet()
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)");
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_concole_logger", boost::bind(&simple_wallet::enable_concole_logger, this, _1), "Enables console logging");
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");
@ -226,16 +226,17 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("submit_transfer", boost::bind(&simple_wallet::submit_transfer, this, _1), "submit_transfer <signed_tx_file> - broadcast signed tx");
}
//----------------------------------------------------------------------------------------------------
simple_wallet::~simple_wallet()
{
}
bool simple_wallet::enable_concole_logger(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::enable_console_logger(const std::vector<std::string> &args)
{
log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_0);
LOG_PRINT_L0("Console logger enabled");
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::set_log(const std::vector<std::string> &args)
{
if(args.size() != 1)
@ -1141,26 +1142,31 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
local_args.erase(local_args.begin());
std::string payment_id;
currency::payment_id_t payment_id;
if (1 == local_args.size() % 2)
{
payment_id = local_args.back();
std::string payment_id_hex = local_args.back();
local_args.pop_back();
if (!payment_id_hex.empty() && !currency::parse_payment_id_from_hex_str(payment_id_hex, payment_id))
{
fail_msg_writer() << "unable to parse payment id: " << payment_id_hex << ", HEX-encoded string is expected";
return true;
}
}
if (!currency::is_payment_id_size_ok(payment_id))
{
fail_msg_writer() << "payment id is too long: " << payment_id.size() << " bytes, max allowed: " << BC_PAYMENT_ID_SERVICE_SIZE_MAX;
fail_msg_writer() << "decoded payment id is too long: " << payment_id.size() << " bytes, max allowed: " << BC_PAYMENT_ID_SERVICE_SIZE_MAX;
return true;
}
vector<currency::tx_destination_entry> dsts;
for (size_t i = 0; i < local_args.size(); i += 2)
{
std::string embedded_payment_id;
std::string integrated_payment_id;
currency::tx_destination_entry de;
de.addr.resize(1);
if(!(de.addr.size() == 1 && m_wallet->get_transfer_address(local_args[i], de.addr.front(), embedded_payment_id)))
if(!(de.addr.size() == 1 && m_wallet->get_transfer_address(local_args[i], de.addr.front(), integrated_payment_id)))
{
fail_msg_writer() << "wrong address: " << local_args[i];
return true;
@ -1180,14 +1186,14 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
return true;
}
if (embedded_payment_id.size() != 0)
if (integrated_payment_id.size() != 0)
{
if (payment_id.size() != 0)
{
fail_msg_writer() << "address " + local_args[i] + " has embedded payment id \"" + embedded_payment_id + "\" which conflicts with previously set payment id: \"" << payment_id << "\"";
fail_msg_writer() << "address " + local_args[i] + " has integrated payment id " + epee::string_tools::buff_to_hex_nodelimer(integrated_payment_id) + " which conflicts with previously set payment id: " << epee::string_tools::buff_to_hex_nodelimer(payment_id) << "";
return true;
}
payment_id = embedded_payment_id;
payment_id = integrated_payment_id;
}
dsts.push_back(de);
@ -1195,7 +1201,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
std::vector<currency::attachment_v> attachments;
if (!set_payment_id_to_tx(attachments, payment_id))
if (!payment_id.empty() && !set_payment_id_to_tx(attachments, payment_id))
{
fail_msg_writer() << "provided (or embedded) payment id can't be set: \"" << payment_id << "\"";
return true;

View file

@ -78,7 +78,7 @@ namespace currency
bool viewkey(const std::vector<std::string> &args);
bool save(const std::vector<std::string> &args);
bool set_log(const std::vector<std::string> &args);
bool enable_concole_logger(const std::vector<std::string> &args);
bool enable_console_logger(const std::vector<std::string> &args);
bool integrated_address(const std::vector<std::string> &args);
bool get_tx_key(const std::vector<std::string> &args_);
bool save_watch_only(const std::vector<std::string> &args);

View file

@ -5,9 +5,9 @@
#define PROJECT_MAJOR_VERSION "1"
#define PROJECT_MINOR_VERSION "1"
#define PROJECT_REVISION "4"
#define PROJECT_REVISION "5"
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
#define PROJECT_VERSION_BUILD_NO 77
#define PROJECT_VERSION_BUILD_NO 82
#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

@ -11,6 +11,11 @@ using namespace epee;
#include "currency_core/currency_format_utils.h"
#include "currency_core/alias_helper.h"
#undef LOG_DEFAULT_CHANNEL
#define LOG_DEFAULT_CHANNEL "rpc_proxy"
ENABLE_CHANNEL_BY_DEFAULT("rpc_proxy")
namespace tools
{
bool default_http_core_proxy::set_connection_addr(const std::string& url)
@ -131,7 +136,13 @@ namespace tools
epee::net_utils::parse_url(m_daemon_address, u);
if (!u.port)
u.port = 8081;
return m_http_client.connect(u.host, std::to_string(u.port), WALLET_RCP_CONNECTION_TIMEOUT);
bool r = m_http_client.connect(u.host, std::to_string(u.port), m_connection_timeout);
if (r)
{
*m_plast_daemon_is_disconnected = false;
m_last_success_interract_time = time(nullptr);
}
return r;
}
//------------------------------------------------------------------------------------------------------------------------------
bool default_http_core_proxy::call_COMMAND_RPC_GET_ALL_ALIASES(currency::COMMAND_RPC_GET_ALL_ALIASES::response& res)
@ -166,7 +177,17 @@ namespace tools
m_plast_daemon_is_disconnected = plast_daemon_is_disconnected ? plast_daemon_is_disconnected : &m_last_daemon_is_disconnected_stub;
}
//------------------------------------------------------------------------------------------------------------------------------
default_http_core_proxy::default_http_core_proxy():m_plast_daemon_is_disconnected(&m_last_daemon_is_disconnected_stub)
bool default_http_core_proxy::set_connectivity(unsigned int connection_timeout, size_t repeats_count)
{
m_connection_timeout = connection_timeout;
m_attempts_count = repeats_count;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
default_http_core_proxy::default_http_core_proxy() :m_plast_daemon_is_disconnected(&m_last_daemon_is_disconnected_stub),
m_last_success_interract_time(0),
m_connection_timeout(WALLET_RCP_CONNECTION_TIMEOUT),
m_attempts_count(WALLET_RCP_COUNT_ATTEMNTS)
{
}

View file

@ -11,9 +11,11 @@
#include "core_rpc_proxy.h"
#include "storages/http_abstract_invoke.h"
#define WALLET_RCP_CONNECTION_TIMEOUT 200000
#define WALLET_RCP_CONNECTION_TIMEOUT 3000
#define WALLET_RCP_COUNT_ATTEMNTS 3
namespace tools
{
class default_http_core_proxy final : public i_core_proxy
@ -22,6 +24,7 @@ namespace tools
bool set_connection_addr(const std::string& url) override;
bool set_connectivity(unsigned int connection_timeout, size_t repeats_count);
bool call_COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES(const currency::COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& rqt, currency::COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& rsp) override;
bool call_COMMAND_RPC_GET_BLOCKS_FAST(const currency::COMMAND_RPC_GET_BLOCKS_FAST::request& rqt, currency::COMMAND_RPC_GET_BLOCKS_FAST::response& rsp) override;
bool call_COMMAND_RPC_GET_BLOCKS_DIRECT(const currency::COMMAND_RPC_GET_BLOCKS_DIRECT::request& rqt, currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& rsp) override;
@ -58,12 +61,18 @@ namespace tools
CRITICAL_REGION_LOCAL(m_lock);
bool ret = false;
for(size_t i = WALLET_RCP_COUNT_ATTEMNTS; i && !ret; --i)
for(size_t i = m_attempts_count; i && !ret; --i)
{
ret = request();
}
m_plast_daemon_is_disconnected->store(!ret);
if (ret)
{
m_last_success_interract_time = time(nullptr);
*m_plast_daemon_is_disconnected = false;
}
else
*m_plast_daemon_is_disconnected = true;
return ret;
}
@ -71,7 +80,14 @@ namespace tools
inline bool invoke_http_json_rpc_update_is_disconnect(const std::string& method_name, const t_request& req, t_response& res)
{
return call_request([&](){
return epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, res, m_http_client);
#ifdef MOBILE_WALLET_BUILD
LOG_PRINT_L0("[INVOKE_JSON_METHOD] ---> " << method_name)
#endif
bool r = epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, res, m_http_client);
#ifdef MOBILE_WALLET_BUILD
LOG_PRINT_L0("[INVOKE_JSON_METHOD] <---" << method_name)
#endif
return r;
});
}
@ -79,7 +95,14 @@ namespace tools
inline bool invoke_http_bin_remote_command2_update_is_disconnect(const std::string& url, const t_request& req, t_response& res)
{
return call_request([&](){
return epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + url, req, res, m_http_client, WALLET_RCP_CONNECTION_TIMEOUT);
#ifdef MOBILE_WALLET_BUILD
LOG_PRINT_L0("[INVOKE_BIN] --->" << typeid(t_request).name())
#endif
bool r = epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + url, req, res, m_http_client, m_connection_timeout);
#ifdef MOBILE_WALLET_BUILD
LOG_PRINT_L0("[INVOKE_BIN] <---" << typeid(t_request).name())
#endif
return r;
});
}
@ -87,15 +110,30 @@ namespace tools
inline bool invoke_http_json_remote_command2_update_is_disconnect(const std::string& url, const t_request& req, t_response& res)
{
return call_request([&](){
return epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + url, req, res, m_http_client, WALLET_RCP_CONNECTION_TIMEOUT);
#ifdef MOBILE_WALLET_BUILD
LOG_PRINT_L0("[INVOKE_JSON_URL] --->" << typeid(t_request).name() )
#endif
bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + url, req, res, m_http_client, m_connection_timeout);
#ifdef MOBILE_WALLET_BUILD
LOG_PRINT_L0("[INVOKE_JSON_URL] <---" << typeid(t_request).name())
#endif
return r;
});
}
//------------------------------------------------------------------------------------------------------------------------------
virtual time_t get_last_success_interract_time() override
{
return m_last_success_interract_time;
}
epee::critical_section m_lock;
epee::net_utils::http::http_simple_client m_http_client;
std::string m_daemon_address;
std::atomic<time_t> m_last_success_interract_time;
std::atomic<bool> *m_plast_daemon_is_disconnected;
std::atomic<bool> m_last_daemon_is_disconnected_stub;
unsigned int m_connection_timeout;
size_t m_attempts_count;
};
}

View file

@ -138,6 +138,11 @@ namespace tools
{
return tools::get_transfer_address(adr_str, addr, payment_id, this);
}
//------------------------------------------------------------------------------------------------------------------------------
virtual time_t get_last_success_interract_time() override
{
return time(nullptr);
}
private:
currency::core_rpc_server& m_rpc;

View file

@ -45,6 +45,7 @@ namespace tools
virtual bool check_connection(){ return false; }
virtual time_t get_last_success_interract_time() { return 0; }
virtual bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id){ return false; }
};
}

View file

@ -0,0 +1,419 @@
// Copyright (c) 2014-2020 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "plain_wallet_api.h"
#include "plain_wallet_api_defs.h"
#include "currency_core/currency_config.h"
#include "version.h"
#include "string_tools.h"
#include "currency_core/currency_format_utils.h"
#include "wallets_manager.h"
#include "common/base58.h"
#include "common/config_encrypt_helper.h"
#define ANDROID_PACKAGE_NAME "com.zano_mobile"
#define LOGS_FOLDER "logs"
#define WALLETS_FOLDER_NAME "wallets"
#define APP_CONFIG_FOLDER "app_config"
#define APP_CONFIG_FILENAME "app_cfg.bin"
#define MOBILE_APP_DATA_FILE_BINARY_SIGNATURE 0x1000111201101011LL //Bender's nightmare
#define GENERAL_INTERNAL_ERRROR_INSTANCE "GENERAL_INTERNAL_ERROR: WALLET INSTNACE NOT FOUND"
#define GENERAL_INTERNAL_ERRROR_INIT "Failed to intialize library"
//TODO: global objects, subject to refactoring
wallets_manager gwm;
std::atomic<bool> initialized(false);
std::atomic<uint64_t> gjobs_counter(1);
std::map<uint64_t, std::string> gjobs;
epee::critical_section gjobs_lock;
std::string gconfig_folder;
namespace plain_wallet
{
typedef epee::json_rpc::response<epee::json_rpc::dummy_result, error> error_response;
std::string get_bundle_working_dir()
{
return gconfig_folder;
// #ifdef WIN32
// return boost::dll::program_location().parent_path().string();
// #elif IOS_BUILD
// char* env = getenv("HOME");
// return env ? env : "";
// #elif ANDROID_BUILD
// /// data/data/com.zano_mobile/files
// return "/data/data/" ANDROID_PACKAGE_NAME;
// #else
// return "";
// #endif
}
void set_bundle_working_dir(const std::string& dir)
{
gconfig_folder = dir;
}
std::string get_wallets_folder()
{
#ifdef WIN32
return "";
#else
std::string path = get_bundle_working_dir() + "/" + WALLETS_FOLDER_NAME + "/";
return path;
#endif // WIN32
}
std::string get_app_config_folder()
{
#ifdef WIN32
return "";
#else
std::string path = get_bundle_working_dir() + "/" + APP_CONFIG_FOLDER + "/";
return path;
#endif // WIN32
}
void initialize_logs(int log_level)
{
std::string log_dir = get_bundle_working_dir();
log_dir += "/" LOGS_FOLDER;
log_space::get_set_need_thread_id(true, true);
log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,p2p,wallet");
epee::log_space::get_set_log_detalisation_level(true, log_level);
epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL);
epee::log_space::log_singletone::add_logger(LOGGER_FILE, "plain_wallet.log", log_dir.c_str());
LOG_PRINT_L0("Plain wallet initialized: " << CURRENCY_NAME << " v" << PROJECT_VERSION_LONG << ", log location: " << log_dir + "/plain_wallet.log");
//glogs_initialized = true;
}
std::string set_log_level(int log_level)
{
epee::log_space::get_set_log_detalisation_level(true, log_level);
return "{}";
}
std::string init(const std::string& ip, const std::string& port, const std::string& working_dir, int log_level)
{
if (initialized)
{
LOG_ERROR("Double-initialization in plain_wallet detected.");
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
ok_response.result.return_code = API_RETURN_CODE_ALREADY_EXISTS;
return epee::serialization::store_t_to_json(ok_response);
}
set_bundle_working_dir(working_dir);
initialize_logs(log_level);
std::string argss_1 = std::string("--remote-node=") + ip + ":" + port;
std::string argss_2 = std::string("--disable-logs-init");
char * args[4];
static const char* arg0_stub = "stub";
args[0] = const_cast<char*>(arg0_stub);
args[1] = const_cast<char*>(argss_1.c_str());
args[2] = const_cast<char*>(argss_2.c_str());
args[3] = nullptr;
if (!gwm.init(3, args, nullptr))
{
LOG_ERROR("Failed to init wallets_manager");
return GENERAL_INTERNAL_ERRROR_INIT;
}
if(!gwm.start())
{
LOG_ERROR("Failed to start wallets_manager");
return GENERAL_INTERNAL_ERRROR_INIT;
}
std::string wallets_folder = get_wallets_folder();
boost::system::error_code ec;
boost::filesystem::create_directories(wallets_folder, ec);
if (ec)
{
error_response err_result = AUTO_VAL_INIT(err_result);
err_result.error.code = API_RETURN_CODE_INTERNAL_ERROR;
err_result.error.message = LOCATION_STR + " \nmessage:" + ec.message();
return epee::serialization::store_t_to_json(err_result);
}
std::string app_config_folder = get_app_config_folder();
boost::filesystem::create_directories(app_config_folder, ec);
if (ec)
{
error_response err_result = AUTO_VAL_INIT(err_result);
err_result.error.code = API_RETURN_CODE_INTERNAL_ERROR;
err_result.error.message = LOCATION_STR + " \nmessage:" + ec.message();
return epee::serialization::store_t_to_json(err_result);
}
initialized = true;
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
ok_response.result.return_code = API_RETURN_CODE_OK;
return epee::serialization::store_t_to_json(ok_response);
}
std::string get_appconfig(const std::string& encryption_key)
{
std::string res_str;
std::string app_config_config_path = get_app_config_folder() + APP_CONFIG_FILENAME;
std::string ret_code = tools::load_encrypted_file(app_config_config_path, encryption_key, res_str, MOBILE_APP_DATA_FILE_BINARY_SIGNATURE);
if (ret_code != API_RETURN_CODE_OK)
{
error_response err_result = AUTO_VAL_INIT(err_result);
err_result.error.code = ret_code;
return epee::serialization::store_t_to_json(err_result);
}
return res_str;
}
std::string set_appconfig(const std::string& conf_str, const std::string& encryption_key)
{
std::string app_config_config_path = get_app_config_folder() + APP_CONFIG_FILENAME;
std::string ret_code = tools::store_encrypted_file(app_config_config_path, encryption_key, conf_str, MOBILE_APP_DATA_FILE_BINARY_SIGNATURE);
if (ret_code != API_RETURN_CODE_OK)
{
error_response err_result = AUTO_VAL_INIT(err_result);
err_result.error.code = ret_code;
return epee::serialization::store_t_to_json(err_result);
}
else
{
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
ok_response.result.return_code = API_RETURN_CODE_OK;
return epee::serialization::store_t_to_json(ok_response);
}
}
std::string generate_random_key(uint64_t lenght)
{
std::string buff;
buff.resize(lenght);
crypto::generate_random_bytes(lenght, const_cast<char*>(buff.data()));
return tools::base58::encode(buff);
}
std::string get_logs_buffer()
{
return epee::log_space::log_singletone::copy_logs_to_buffer();
}
std::string truncate_log()
{
epee::log_space::log_singletone::truncate_log_files();
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
ok_response.result.return_code = API_RETURN_CODE_OK;
return epee::serialization::store_t_to_json(ok_response);
}
std::string get_connectivity_status()
{
return gwm.get_connectivity_status();
}
std::string get_version()
{
return PROJECT_VERSION_LONG;
}
struct strings_list
{
std::list<std::string> items;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(items)
END_KV_SERIALIZE_MAP()
};
std::string get_wallet_files()
{
std::string wallet_files_path = get_wallets_folder();
strings_list sl = AUTO_VAL_INIT(sl);
epee::file_io_utils::get_folder_content(wallet_files_path, sl.items, true);
return epee::serialization::store_t_to_json(sl);
}
std::string open(const std::string& path, const std::string& password)
{
std::string full_path = get_wallets_folder() + path;
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
std::string rsp = gwm.open_wallet(epee::string_encoding::convert_to_unicode(full_path), password, 20, ok_response.result);
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
{
if (rsp == API_RETURN_CODE_FILE_RESTORED)
{
ok_response.result.recovered = true;
}
gwm.run_wallet(ok_response.result.wallet_id);
return epee::serialization::store_t_to_json(ok_response);
}
error_response err_result = AUTO_VAL_INIT(err_result);
err_result.error.code = rsp;
return epee::serialization::store_t_to_json(err_result);
}
std::string restore(const std::string& seed, const std::string& path, const std::string& password)
{
std::string full_path = get_wallets_folder() + path;
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
std::string rsp = gwm.restore_wallet(epee::string_encoding::convert_to_unicode(full_path), password, seed, ok_response.result);
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
{
if (rsp == API_RETURN_CODE_FILE_RESTORED)
{
ok_response.result.recovered = true;
}
gwm.run_wallet(ok_response.result.wallet_id);
return epee::serialization::store_t_to_json(ok_response);
}
error_response err_result = AUTO_VAL_INIT(err_result);
err_result.error.code = rsp;
return epee::serialization::store_t_to_json(err_result);
}
std::string generate(const std::string& path, const std::string& password)
{
std::string full_path = get_wallets_folder() + path;
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
std::string rsp = gwm.generate_wallet(epee::string_encoding::convert_to_unicode(full_path), password, ok_response.result);
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
{
if (rsp == API_RETURN_CODE_FILE_RESTORED)
{
ok_response.result.recovered = true;
}
gwm.run_wallet(ok_response.result.wallet_id);
return epee::serialization::store_t_to_json(ok_response);
}
error_response err_result = AUTO_VAL_INIT(err_result);
err_result.error.code = rsp;
return epee::serialization::store_t_to_json(err_result);
}
std::string close_wallet(hwallet h)
{
std::string r = "{\"response\": \"";
r += gwm.close_wallet(h);
r += "\"}";
return r;
}
std::string get_wallet_status(hwallet h)
{
return gwm.get_wallet_status(h);
}
std::string invoke(hwallet h, const std::string& params)
{
return gwm.invoke(h, params);
}
void put_result(uint64_t job_id, const std::string& res)
{
CRITICAL_REGION_LOCAL(gjobs_lock);
gjobs[job_id] = res;
LOG_PRINT_L0("[ASYNC_CALL]: Finished(result put), job id: " << job_id);
}
std::string async_call(const std::string& method_name, uint64_t instance_id, const std::string& params)
{
std::function<void()> async_callback;
uint64_t job_id = gjobs_counter++;
if (method_name == "close")
{
async_callback = [job_id, instance_id]()
{
close_wallet(instance_id);
view::api_responce_return_code rc = AUTO_VAL_INIT(rc);
rc.return_code = API_RETURN_CODE_OK;
put_result(job_id, epee::serialization::store_t_to_json(rc));
};
}
else if (method_name == "open")
{
view::open_wallet_request owr = AUTO_VAL_INIT(owr);
if (!epee::serialization::load_t_from_json(owr, params))
{
view::api_response ar = AUTO_VAL_INIT(ar);
ar.error_code = "Wrong parameter";
put_result(job_id, epee::serialization::store_t_to_json(ar));
}
async_callback = [job_id, owr]()
{
std::string res = open(owr.path, owr.pass);
put_result(job_id, res);
};
}
else if (method_name == "restore")
{
view::restore_wallet_request rwr = AUTO_VAL_INIT(rwr);
if (!epee::serialization::load_t_from_json(rwr, params))
{
view::api_response ar = AUTO_VAL_INIT(ar);
ar.error_code = "Wrong parameter";
put_result(job_id, epee::serialization::store_t_to_json(ar));
}
async_callback = [job_id, rwr]()
{
std::string res = restore(rwr.restore_key, rwr.path, rwr.pass);
put_result(job_id, res);
};
}
else if (method_name == "invoke")
{
std::string local_params = params;
async_callback = [job_id, local_params, instance_id]()
{
std::string res = invoke(instance_id, local_params);
put_result(job_id, res);
};
}
else if (method_name == "get_wallet_status")
{
std::string local_params = params;
async_callback = [job_id, local_params, instance_id]()
{
std::string res = get_wallet_status(instance_id);
put_result(job_id, res);
};
}else
{
view::api_response ar = AUTO_VAL_INIT(ar);
ar.error_code = "UNKNOWN METHOD";
put_result(job_id, epee::serialization::store_t_to_json(ar));
return std::string("{ \"job_id\": ") + std::to_string(job_id) + "}";;
}
std::thread t([async_callback]() {async_callback(); });
t.detach();
LOG_PRINT_L0("[ASYNC_CALL]: started " << method_name << ", job id: " << job_id);
return std::string("{ \"job_id\": ") + std::to_string(job_id) + "}";
}
std::string try_pull_result(uint64_t job_id)
{
//TODO: need refactoring
CRITICAL_REGION_LOCAL(gjobs_lock);
auto it = gjobs.find(job_id);
if (it == gjobs.end())
{
return "{\"delivered\": false}";
}
std::string res = "{\"delivered\": true, \"result\": ";
res += it->second;
res += " }";
gjobs.erase(it);
return res;
}
}

View file

@ -0,0 +1,36 @@
// Copyright (c) 2014-2020 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 <string>
namespace plain_wallet
{
typedef int64_t hwallet;
std::string init(const std::string& ip, const std::string& port, const std::string& working_dir, int log_level);
std::string set_log_level(int log_level);
std::string get_version();
std::string get_wallet_files();
std::string get_appconfig(const std::string& encryption_key);
std::string set_appconfig(const std::string& conf_str, const std::string& encryption_key);
std::string generate_random_key(uint64_t lenght);
std::string get_logs_buffer();
std::string truncate_log();
std::string get_connectivity_status();
std::string open(const std::string& path, const std::string& password);
std::string restore(const std::string& seed, const std::string& path, const std::string& password);
std::string generate(const std::string& path, const std::string& password);
std::string get_wallet_status(hwallet h);
std::string close_wallet(hwallet h);
std::string invoke(hwallet h, const std::string& params);
//async api
std::string async_call(const std::string& method_name, uint64_t instance_id, const std::string& params);
std::string try_pull_result(uint64_t);
}

View file

@ -0,0 +1,50 @@
// Copyright (c) 2014-2020 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 "net/http_server_handlers_map2.h"
#include "view_iface.h"
namespace plain_wallet
{
struct error
{
std::string code;
std::string message;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(code)
KV_SERIALIZE(message)
END_KV_SERIALIZE_MAP()
};
struct open_wallet_response
{
view::transfers_array recent_history;
view::wallet_info wi;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(recent_history)
KV_SERIALIZE(wi)
END_KV_SERIALIZE_MAP()
};
struct sync_status_response
{
bool finished;
uint64_t progress;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(finished)
KV_SERIALIZE(progress)
END_KV_SERIALIZE_MAP()
};
struct basic_status_response
{
std::string status;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};
} // namespace tools

View file

@ -6,9 +6,9 @@
#pragma once
#include <stdint.h>
#include <QObject>
#ifndef Q_MOC_RUN
// #include <stdint.h>
// #include <QObject>
// #ifndef Q_MOC_RUN
#include "warnings.h"
PUSH_VS_WARNINGS
@ -22,7 +22,7 @@ DISABLE_VS_WARNINGS(4503)
#include "currency_core/basic_api_response_codes.h"
POP_VS_WARNINGS
#endif
//#endif
namespace view
{
@ -139,6 +139,8 @@ public:
uint64_t last_build_displaymode;
uint64_t alias_count;
std::string last_build_available;
uint64_t downloaded_bytes;
uint64_t download_total_data_size;
//std::list<block_info> last_blocks;
bool is_pos_allowed;
uint64_t expiration_median_timestamp;
@ -160,6 +162,8 @@ public:
KV_SERIALIZE(last_build_available)
//KV_SERIALIZE(last_blocks)
KV_SERIALIZE(alias_count)
KV_SERIALIZE(downloaded_bytes)
KV_SERIALIZE(download_total_data_size)
KV_SERIALIZE(is_pos_allowed)
KV_SERIALIZE(expiration_median_timestamp)
KV_SERIALIZE(is_disconnected)
@ -424,11 +428,15 @@ public:
uint64_t wallet_id;
transfers_array recent_history;
wallet_info wi;
std::string seed;
bool recovered;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(wallet_id)
KV_SERIALIZE(recent_history)
KV_SERIALIZE(wi)
KV_SERIALIZE(seed)
KV_SERIALIZE(recovered)
END_KV_SERIALIZE_MAP()
};
@ -440,6 +448,19 @@ public:
END_KV_SERIALIZE_MAP()
};
struct general_connectivity_info
{
bool is_online;
bool last_daemon_is_disconnected;
uint64_t last_proxy_communicate_timestamp;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(is_online)
KV_SERIALIZE(last_daemon_is_disconnected)
KV_SERIALIZE(last_proxy_communicate_timestamp)
END_KV_SERIALIZE_MAP()
};
struct header_entry
{
@ -518,6 +539,23 @@ public:
END_KV_SERIALIZE_MAP()
};
struct wallet_sync_status_info
{
bool is_daemon_connected;
uint64_t wallet_state;
bool is_in_long_refresh;
uint64_t progress;
uint64_t current_daemon_height;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(is_daemon_connected)
KV_SERIALIZE(wallet_state)
KV_SERIALIZE(is_in_long_refresh)
KV_SERIALIZE(progress)
KV_SERIALIZE(current_daemon_height)
END_KV_SERIALIZE_MAP()
};
struct get_restore_info_response
{
std::string restore_key;
@ -700,6 +738,14 @@ public:
};
struct api_responce_return_code
{
std::string return_code;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(return_code)
END_KV_SERIALIZE_MAP()
};
struct api_void
@ -745,6 +791,8 @@ public:
#define API_RETURN_CODE_FALSE "FALSE"
#define API_RETURN_CODE_CORE_BUSY "CORE_BUSY"
#define API_RETURN_CODE_OVERFLOW "OVERFLOW"
#define API_RETURN_CODE_BUSY "BUSY"
#define API_RETURN_CODE_INVALID_FILE "INVALID_FILE"
#define API_MAX_ALIASES_COUNT 10000

View file

@ -1086,10 +1086,10 @@ void wallet2::process_new_blockchain_entry(const currency::block& b, const curre
process_new_transaction(tx_entry->tx, height, b);
}
TIME_MEASURE_FINISH(txs_handle_time);
WLT_LOG_L2("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms");
WLT_LOG_L3("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms");
}else
{
WLT_LOG_L2( "Skipped block by timestamp, height: " << height << ", block time " << b.timestamp << ", account time " << m_account.get_createtime());
WLT_LOG_L3( "Skipped block by timestamp, height: " << height << ", block time " << b.timestamp << ", account time " << m_account.get_createtime());
}
m_blockchain.push_back(bl_id);
++m_local_bc_height;
@ -1236,6 +1236,11 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop
WLT_LOG_L1("[PULL BLOCKS] " << res.start_height << " --> " << m_blockchain.size());
}
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::get_sync_progress()
{
return m_last_sync_percent;
}
//----------------------------------------------------------------------------------------------------
void wallet2::refresh()
{
size_t blocks_fetched = 0;
@ -1351,7 +1356,7 @@ void wallet2::scan_tx_pool(bool& has_related_alias_in_unconfirmed)
std::unordered_map<crypto::hash, std::pair<currency::transaction, money_transfer2_details>> unconfirmed_multisig_transfers_from_tx_pool;
has_related_alias_in_unconfirmed = false;
uint64_t tx_expiration_ts_median = get_tx_expiration_median();
uint64_t tx_expiration_ts_median = res.tx_expiration_ts_median; //get_tx_expiration_median();
for (const auto &tx_blob : res.txs)
{
currency::transaction tx;
@ -2203,7 +2208,7 @@ void wallet2::store_watch_only(const std::wstring& path_to_save, const std::stri
continue;
const crypto::public_key& out_key = boost::get<txout_to_key>(out_t).key;
wo.m_pending_key_images.insert(std::make_pair(out_key, td.m_key_image));
wo.m_pending_key_images_file_container.push_back(tools::out_key_to_ki(out_key, td.m_key_image));
wo.m_pending_key_images_file_container.push_back(tools::out_key_to_ki{ out_key, td.m_key_image });
WLT_LOG_L1("preparing watch-only wallet: added pending ki (" << out_key << ", " << td.m_key_image << ")");
}
@ -2329,7 +2334,7 @@ bool wallet2::generate_packing_transaction_if_needed(currency::transaction& tx,
//let's check if we have at least WALLET_POS_MINT_PACKING_SIZE transactions which is ready to go
size_t count = 0;
for (auto it_ind = it->second.begin(); it_ind != it->second.end() && count < m_pos_mint_packing_size; it_ind++)
for (auto it_ind = it->second.begin(); it_ind != it->second.end() && count <= m_pos_mint_packing_size; it_ind++)
{
if (is_transfer_ready_to_go(m_transfers[*it_ind], fake_outputs_number))
++count;
@ -2547,7 +2552,7 @@ void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::trans
else
{
m_pending_key_images[p.first] = p.second;
m_pending_key_images_file_container.push_back(tools::out_key_to_ki(p.first, p.second));
m_pending_key_images_file_container.push_back(tools::out_key_to_ki{ p.first, p.second });
LOG_PRINT_L2("for tx " << tx_hash << " pending key image added (" << p.first << ", " << p.second << ")");
}
}
@ -2584,6 +2589,11 @@ uint64_t wallet2::get_recent_transfers_total_count()
return m_transfer_history.size();
}
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::get_transfer_entries_count()
{
return m_transfers.size();
}
//----------------------------------------------------------------------------------------------------
void wallet2::get_recent_transfers_history(std::vector<wallet_public::wallet_transfer_info>& trs, size_t offset, size_t count, uint64_t& total)
{
if (offset >= m_transfer_history.size())
@ -2838,7 +2848,7 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
if (generate_packing_transaction_if_needed(pack_tx, 0))
{
tx_to_blob(pack_tx, tmpl_req.explicit_transaction);
WLT_LOG_GREEN("Pacling inputs: " << pack_tx.vin.size() << " inputs consolidated", LOG_LEVEL_0);
WLT_LOG_GREEN("Packing inputs: " << pack_tx.vin.size() << " inputs consolidated in tx " << get_transaction_hash(pack_tx), LOG_LEVEL_0);
}
m_core_proxy->call_COMMAND_RPC_GETBLOCKTEMPLATE(tmpl_req, tmpl_rsp);
WLT_CHECK_AND_ASSERT_MES(tmpl_rsp.status == CORE_RPC_STATUS_OK, false, "Failed to create block template after kernel hash found!");
@ -2899,10 +2909,10 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
m_wcallback->on_pos_block_found(b);
//@#@
//double check timestamp
if (time(NULL) - get_actual_timestamp(b) > 5)
if (time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) > 5)
{
WLT_LOG_RED("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
<< ") is suspiciously less (" << time(NULL) - get_actual_timestamp(b) << ") then curren time( " << time(NULL) << ")", LOG_LEVEL_0);
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")", LOG_LEVEL_0);
}
//
return true;
@ -4348,11 +4358,38 @@ bool wallet2::store_unsigned_tx_to_file_and_reserve_transfers(const finalize_tx_
return true;
}
//----------------------------------------------------------------------------------------------------
void wallet2::check_and_throw_if_self_directed_tx_with_payment_id_requested(const construct_tx_param& ctp)
{
// If someone sends coins to his own address, all tx outputs will be detected as own outputs.
// It's totally okay unless payment id is used, because it would be impossible to distinguish
// between change outs and transfer outs. Thus, such tx with a payment id can't be correctly
// obtained via RPC by the given payment id. It could be a problem for an exchange or other
// service when a user, identifyied by payment id sends coins to another user on the same
// exchange/service. Coins will be received but RPCs like get_payments won't give the transfer.
// To avoid such issues we prohibit such txs with a soft rule on sender side.
for (auto& d : ctp.dsts)
{
for (auto& addr : d.addr)
{
if (addr != m_account.get_public_address())
return; // at least one destination address is not our address -- it's not self-directed tx
}
}
// it's self-directed tx
payment_id_t pid;
bool has_payment_id = get_payment_id_from_tx(ctp.attachments, pid) && !pid.empty();
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(!has_payment_id, "sending funds to yourself with payment id is not allowed");
}
//----------------------------------------------------------------------------------------------------
void wallet2::transfer(const construct_tx_param& ctp,
currency::transaction &tx,
bool send_to_network,
std::string* p_signed_tx_blob_str)
{
check_and_throw_if_self_directed_tx_with_payment_id_requested(ctp);
TIME_MEASURE_START(prepare_transaction_time);
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
prepare_transaction(ctp, ftp);
@ -4545,7 +4582,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
{
finalize_transaction(ftp, tx, tx_key, false, false);
}
catch (error::tx_too_big)
catch (error::tx_too_big&)
{
return rc_too_many_outputs;
}

View file

@ -46,7 +46,6 @@
#undef LOG_DEFAULT_CHANNEL
#define LOG_DEFAULT_CHANNEL "wallet"
ENABLE_CHANNEL_BY_DEFAULT("wallet");
// wallet-specific logging functions
#define WLT_LOG_L0(msg) LOG_PRINT_L0("[W:" << m_log_prefix << "] " << msg)
@ -124,8 +123,6 @@ namespace tools
#pragma pack(push, 1)
struct out_key_to_ki
{
out_key_to_ki() {}
out_key_to_ki(const crypto::public_key& out_key, const crypto::key_image& key_image) : out_key(out_key), key_image(key_image) {}
crypto::public_key out_key;
crypto::key_image key_image;
};
@ -452,9 +449,9 @@ namespace tools
END_SERIALIZE()
};
void assign_account(const currency::account_base& acc);
void generate(const std::wstring& wallet, const std::string& password);
void generate(const std::wstring& path, const std::string& password);
void restore(const std::wstring& path, const std::string& pass, const std::string& restore_key);
void load(const std::wstring& wallet, const std::string& password);
void load(const std::wstring& path, const std::string& password);
void store();
void store(const std::wstring& path);
void store(const std::wstring& path, const std::string& password);
@ -466,6 +463,7 @@ namespace tools
void get_recent_transfers_history(std::vector<wallet_public::wallet_transfer_info>& trs, size_t offset, size_t count, uint64_t& total);
uint64_t get_recent_transfers_total_count();
uint64_t get_transfer_entries_count();
void get_unconfirmed_transfers(std::vector<wallet_public::wallet_transfer_info>& trs);
void init(const std::string& daemon_address = "http://localhost:8080");
bool deinit();
@ -616,6 +614,14 @@ namespace tools
// Returns all payments by given id in unspecified order
void get_payments(const std::string& payment_id, std::list<payment_details>& payments, uint64_t min_height = 0) const;
// callback: (const wallet_public::wallet_transfer_info& wti) -> bool, true -- continue, false -- stop
template<typename callback_t>
void enumerate_transfers_history(callback_t cb, bool enumerate_forward) const;
// callback: (const wallet_public::wallet_transfer_info& wti) -> bool, true -- continue, false -- stop
template<typename callback_t>
void enumerate_unconfirmed_transfers(callback_t cb) const;
bool is_watch_only() const { return m_watch_only; }
void sign_transfer(const std::string& tx_sources_blob, std::string& signed_tx_blob, currency::transaction& tx);
void sign_transfer_files(const std::string& tx_sources_file, const std::string& signed_tx_file, currency::transaction& tx);
@ -744,7 +750,7 @@ namespace tools
std::string get_log_prefix() const { return m_log_prefix; }
static uint64_t get_max_unlock_time_from_receive_indices(const currency::transaction& tx, const money_transfer2_details& td);
bool get_utxo_distribution(std::map<uint64_t, uint64_t>& distribution);
uint64_t get_sync_progress();
private:
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);
@ -863,7 +869,7 @@ private:
void check_for_free_space_and_throw_if_it_lacks(const std::wstring& path, uint64_t exact_size_needed_if_known = UINT64_MAX);
bool generate_packing_transaction_if_needed(currency::transaction& tx, uint64_t fake_outputs_number);
bool store_unsigned_tx_to_file_and_reserve_transfers(const finalize_tx_param& ftp, const std::string& filename, std::string* p_unsigned_tx_blob_str = nullptr);
void check_and_throw_if_self_directed_tx_with_payment_id_requested(const construct_tx_param& ctp);
currency::account_base m_account;
bool m_watch_only;
@ -895,7 +901,7 @@ private:
std::shared_ptr<i_core_proxy> m_core_proxy;
std::shared_ptr<i_wallet2_callback> m_wcallback;
uint64_t m_height_of_start_sync;
uint64_t m_last_sync_percent;
std::atomic<uint64_t> m_last_sync_percent;
uint64_t m_last_pow_block_h;
currency::core_runtime_config m_core_runtime_config;
escrow_contracts_container m_contracts;
@ -1145,6 +1151,31 @@ namespace tools
return false;
}
template<typename callback_t>
void wallet2::enumerate_transfers_history(callback_t cb, bool enumerate_forward) const
{
if (enumerate_forward)
{
for(auto it = m_transfer_history.begin(); it != m_transfer_history.end(); ++it)
if (!cb(*it))
break;
}
else
{
for(auto it = m_transfer_history.rbegin(); it != m_transfer_history.rend(); ++it)
if (!cb(*it))
break;
}
}
template<typename callback_t>
void wallet2::enumerate_unconfirmed_transfers(callback_t cb) const
{
for (auto& el : m_unconfirmed_txs)
if (!cb(el.second))
break;
}
} // namespace tools
#if !defined(KEEP_WALLET_LOG_MACROS)

View file

@ -0,0 +1,24 @@
// Copyright (c) 2014-2020 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 "wallet2.h"
#include "view_iface.h"
namespace tools
{
inline bool get_wallet_info(wallet2& w, view::wallet_info& wi)
{
wi = AUTO_VAL_INIT_T(view::wallet_info);
wi.address = w.get_account().get_public_address_str();
wi.tracking_hey = epee::string_tools::pod_to_hex(w.get_account().get_keys().m_view_secret_key);
uint64_t fake = 0;
wi.balance = w.balance(wi.unlocked_balance, fake, fake, wi.mined_total);
wi.path = epee::string_encoding::wstring_to_utf8(w.get_wallet_path());
return true;
}
}

View file

@ -5,6 +5,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <vector>
#include "currency_protocol/currency_protocol_defs.h"
#include "currency_core/currency_basic.h"
#include "crypto/hash.h"
@ -206,6 +207,99 @@ namespace wallet_public
};
};
struct COMMAND_RPC_GET_WALLET_INFO
{
struct request
{
BEGIN_KV_SERIALIZE_MAP()
END_KV_SERIALIZE_MAP()
};
struct response
{
std::string address;
std::string path;
std::string seed;
uint64_t transfers_count;
uint64_t transfer_entries_count;
bool is_whatch_only;
std::vector<std::string> utxo_distribution;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(address)
KV_SERIALIZE(path)
KV_SERIALIZE(seed)
KV_SERIALIZE(transfers_count)
KV_SERIALIZE(transfer_entries_count)
KV_SERIALIZE(is_whatch_only)
KV_SERIALIZE(utxo_distribution)
END_KV_SERIALIZE_MAP()
};
};
struct wallet_provision_info
{
uint64_t transfers_count;
uint64_t transfer_entries_count;
uint64_t balance;
uint64_t unlocked_balance;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(transfers_count)
KV_SERIALIZE(transfer_entries_count)
KV_SERIALIZE(balance)
KV_SERIALIZE(unlocked_balance)
END_KV_SERIALIZE_MAP()
};
struct COMMAND_RPC_GET_RECENT_TXS_AND_INFO
{
struct request
{
/*
if offset is 0, then GET_RECENT_TXS_AND_INFO return
unconfirmed transactions as the first first items of "transfers",
this unconfirmed transactions is not counted regarding "count" parameter
*/
uint64_t offset;
uint64_t count;
/*
need_to_get_info - should backend re-calculate balance(could be relatively heavy,
and not needed when getting long tx history with multiple calls
of GET_RECENT_TXS_AND_INFO with offsets)
*/
bool update_provision_info;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(offset)
KV_SERIALIZE(count)
KV_SERIALIZE(update_provision_info)
END_KV_SERIALIZE_MAP()
};
struct response
{
wallet_provision_info pi;
std::vector<wallet_transfer_info> transfers;
uint64_t total_transfers;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(pi)
KV_SERIALIZE(transfers)
KV_SERIALIZE(total_transfers)
END_KV_SERIALIZE_MAP()
};
};
struct trnsfer_destination
{
uint64_t amount;
@ -241,10 +335,12 @@ namespace wallet_public
{
std::string tx_hash;
std::string tx_unsigned_hex; // for cold-signing process
uint64_t tx_size;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash)
KV_SERIALIZE(tx_unsigned_hex)
KV_SERIALIZE(tx_size)
END_KV_SERIALIZE_MAP()
};
};
@ -775,6 +871,52 @@ namespace wallet_public
};
};
struct COMMAND_RPC_SEARCH_FOR_TRANSACTIONS
{
struct request
{
crypto::hash tx_id;
bool in;
bool out;
//bool pending;
//bool failed;
bool pool;
bool filter_by_height;
uint64_t min_height;
uint64_t max_height;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_POD_AS_HEX_STRING(tx_id)
KV_SERIALIZE(in)
KV_SERIALIZE(out)
//KV_SERIALIZE(pending)
//KV_SERIALIZE(failed)
KV_SERIALIZE(pool)
KV_SERIALIZE(filter_by_height)
KV_SERIALIZE(min_height)
KV_SERIALIZE(max_height)
END_KV_SERIALIZE_MAP()
};
struct response
{
std::list<wallet_transfer_info> in;
std::list<wallet_transfer_info> out;
//std::list<wallet_transfer_info> pending;
//std::list<wallet_transfer_info> failed;
std::list<wallet_transfer_info> pool;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(in)
KV_SERIALIZE(out)
//KV_SERIALIZE(pending)
//KV_SERIALIZE(failed)
KV_SERIALIZE(pool)
END_KV_SERIALIZE_MAP()
};
};
inline std::string get_escrow_contract_state_name(uint32_t state)
{

View file

@ -53,7 +53,7 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::run(bool do_mint, bool offline_mode, const currency::account_public_address& miner_address)
{
static const uint64_t wallet_rpt_idle_work_period_ms = 2000;
static const uint64_t wallet_rpc_idle_work_period_ms = 2000;
m_do_mint = do_mint;
@ -74,11 +74,12 @@ namespace tools
return true;
}
bool has_related_alias_in_unconfirmed = false;
LOG_PRINT_L2("wallet RPC idle: scanning tx pool...");
m_wallet.scan_tx_pool(has_related_alias_in_unconfirmed);
if (m_do_mint)
{
bool has_related_alias_in_unconfirmed = false;
LOG_PRINT_L2("wallet RPC idle: scanning tx pool...");
m_wallet.scan_tx_pool(has_related_alias_in_unconfirmed);
LOG_PRINT_L2("wallet RPC idle: trying to do PoS iteration...");
m_wallet.try_mint_pos(miner_address);
}
@ -97,7 +98,7 @@ namespace tools
}
return true;
}, wallet_rpt_idle_work_period_ms);
}, wallet_rpc_idle_work_period_ms);
}
//DO NOT START THIS SERVER IN MORE THEN 1 THREADS WITHOUT REFACTORING
@ -186,6 +187,55 @@ namespace tools
}
return true;
}
bool wallet_rpc_server::on_getwallet_info(const wallet_public::COMMAND_RPC_GET_WALLET_INFO::request& req, wallet_public::COMMAND_RPC_GET_WALLET_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx)
{
try
{
res.address = m_wallet.get_account().get_public_address_str();
res.is_whatch_only = m_wallet.is_watch_only();
res.path = epee::string_encoding::convert_to_ansii(m_wallet.get_wallet_path());
res.transfers_count = m_wallet.get_recent_transfers_total_count();
res.transfer_entries_count = m_wallet.get_transfer_entries_count();
res.seed = m_wallet.get_account().get_restore_braindata();
std::map<uint64_t, uint64_t> distribution;
m_wallet.get_utxo_distribution(distribution);
for (const auto& ent : distribution)
res.utxo_distribution.push_back(currency::print_money_brief(ent.first) + ":" + std::to_string(ent.second));
return true;
}
catch (std::exception& e)
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
er.message = e.what();
return false;
}
}
bool wallet_rpc_server::on_get_recent_txs_and_info(const wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::request& req, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx)
{
try
{
if (req.update_provision_info)
{
res.pi.balance = m_wallet.balance(res.pi.unlocked_balance);
res.pi.transfer_entries_count = m_wallet.get_transfer_entries_count();
res.pi.transfers_count = m_wallet.get_recent_transfers_total_count();
}
if (req.offset == 0)
m_wallet.get_unconfirmed_transfers(res.transfers);
m_wallet.get_recent_transfers_history(res.transfers, req.offset, req.count, res.total_transfers);
return true;
}
catch (std::exception& e)
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
er.message = e.what();
return false;
}
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_transfer(const wallet_public::COMMAND_RPC_TRANSFER::request& req, wallet_public::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx)
{
@ -251,6 +301,7 @@ namespace tools
else
{
res.tx_hash = epee::string_tools::pod_to_hex(currency::get_transaction_hash(tx));
res.tx_size = get_object_blobsize(tx);
}
return true;
}
@ -528,6 +579,57 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_search_for_transactions(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response& res, epee::json_rpc::error& er, connection_context& cntx)
{
bool tx_id_specified = req.tx_id != currency::null_hash;
// process confirmed txs
m_wallet.enumerate_transfers_history([&](const wallet_public::wallet_transfer_info& wti) -> bool {
if (tx_id_specified)
{
if (wti.tx_hash != req.tx_id)
return true; // continue
}
if (req.filter_by_height)
{
if (!wti.height) // unconfirmed
return true; // continue
if (wti.height < req.min_height)
{
// no need to scan more
return false; // stop
}
if (wti.height > req.max_height)
{
return true; // continue
}
}
if (wti.is_income && req.in)
res.in.push_back(wti);
if (!wti.is_income && req.out)
res.out.push_back(wti);
return true; // continue
}, false /* enumerate_forward */);
// process unconfirmed txs
if (req.pool)
{
m_wallet.enumerate_unconfirmed_transfers([&](const wallet_public::wallet_transfer_info& wti) -> bool {
if ((wti.is_income && req.in) || (!wti.is_income && req.out))
res.pool.push_back(wti);
return true; // continue
});
}
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_contracts_send_proposal(const wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx)
{
WALLET_RPC_BEGIN_TRY_ENTRY();

View file

@ -33,14 +33,14 @@ namespace tools
static void init_options(boost::program_options::options_description& desc);
bool init(const boost::program_options::variables_map& vm);
bool run(bool do_mint, bool offline_mode, const currency::account_public_address& miner_address);
bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response, connection_context& m_conn_context);
BEGIN_URI_MAP2()
BEGIN_JSON_RPC_MAP("/json_rpc")
MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_public::COMMAND_RPC_GET_BALANCE)
MAP_JON_RPC_WE("getaddress", on_getaddress, wallet_public::COMMAND_RPC_GET_ADDRESS)
MAP_JON_RPC_WE("get_wallet_info", on_getwallet_info, wallet_public::COMMAND_RPC_GET_WALLET_INFO)
MAP_JON_RPC_WE("get_recent_txs_and_info", on_get_recent_txs_and_info, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO)
MAP_JON_RPC_WE("transfer", on_transfer, wallet_public::COMMAND_RPC_TRANSFER)
MAP_JON_RPC_WE("store", on_store, wallet_public::COMMAND_RPC_STORE)
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_public::COMMAND_RPC_GET_PAYMENTS)
@ -50,7 +50,8 @@ namespace tools
MAP_JON_RPC_WE("sweep_below", on_sweep_below, wallet_public::COMMAND_SWEEP_BELOW)
MAP_JON_RPC_WE("sign_transfer", on_sign_transfer, wallet_public::COMMAND_SIGN_TRANSFER)
MAP_JON_RPC_WE("submit_transfer", on_submit_transfer, wallet_public::COMMAND_SUBMIT_TRANSFER)
//contracts API
MAP_JON_RPC_WE("search_for_transactions", on_search_for_transactions, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS)
//contracts API
MAP_JON_RPC_WE("contracts_send_proposal", on_contracts_send_proposal, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL)
MAP_JON_RPC_WE("contracts_accept_proposal", on_contracts_accept_proposal, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL)
MAP_JON_RPC_WE("contracts_get_all", on_contracts_get_all, wallet_public::COMMAND_CONTRACTS_GET_ALL)
@ -68,6 +69,8 @@ namespace tools
//json_rpc
bool on_getbalance(const wallet_public::COMMAND_RPC_GET_BALANCE::request& req, wallet_public::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_getaddress(const wallet_public::COMMAND_RPC_GET_ADDRESS::request& req, wallet_public::COMMAND_RPC_GET_ADDRESS::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_getwallet_info(const wallet_public::COMMAND_RPC_GET_WALLET_INFO::request& req, wallet_public::COMMAND_RPC_GET_WALLET_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_get_recent_txs_and_info(const wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::request& req, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_transfer(const wallet_public::COMMAND_RPC_TRANSFER::request& req, wallet_public::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_store(const wallet_public::COMMAND_RPC_STORE::request& req, wallet_public::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_get_payments(const wallet_public::COMMAND_RPC_GET_PAYMENTS::request& req, wallet_public::COMMAND_RPC_GET_PAYMENTS::response& res, epee::json_rpc::error& er, connection_context& cntx);
@ -77,6 +80,7 @@ namespace tools
bool on_sweep_below(const wallet_public::COMMAND_SWEEP_BELOW::request& req, wallet_public::COMMAND_SWEEP_BELOW::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_sign_transfer(const wallet_public::COMMAND_SIGN_TRANSFER::request& req, wallet_public::COMMAND_SIGN_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_submit_transfer(const wallet_public::COMMAND_SUBMIT_TRANSFER::request& req, wallet_public::COMMAND_SUBMIT_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_search_for_transactions(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_contracts_send_proposal(const wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_contracts_accept_proposal(const wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx);

View file

@ -6,6 +6,7 @@
#pragma once
#include <boost/thread/shared_mutex.hpp>
#include <boost/program_options.hpp>
#include "warnings.h"
PUSH_VS_WARNINGS
@ -19,16 +20,19 @@ using namespace epee;
#include "console_handler.h"
#include "p2p/net_node.h"
#include "currency_core/checkpoints_create.h"
#include "currency_core/currency_core.h"
#include "currency_core/bc_offers_service.h"
#include "rpc/core_rpc_server.h"
#include "currency_protocol/currency_protocol_handler.h"
#include "daemon/daemon_commands_handler.h"
#ifndef MOBILE_WALLET_BUILD
#include "currency_core/currency_core.h"
#include "currency_core/bc_offers_service.h"
#include "rpc/core_rpc_server.h"
#include "currency_protocol/currency_protocol_handler.h"
#include "core_fast_rpc_proxy.h"
#endif
//#include "daemon/daemon_commands_handler.h"
//#include "common/miniupnp_helper.h"
#include "view_iface.h"
#include "core_fast_rpc_proxy.h"
#include "wallet/wallet2.h"
#include "wallet2.h"
#include "wallet_id_adapter.h"
#include "wallet_rpc_server.h"
POP_VS_WARNINGS
@ -38,8 +42,6 @@ namespace po = boost::program_options;
#include <crtdbg.h>
#endif
//TODO: need refactoring here. (template classes can't be used in BOOST_CLASS_VERSION)
BOOST_CLASS_VERSION(nodetool::node_server<currency::t_currency_protocol_handler<currency::core> >, CURRENT_P2P_STORAGE_ARCHIVE_VER);
struct wallet_lock_time_watching_policy
{
@ -47,7 +49,7 @@ struct wallet_lock_time_watching_policy
};
class daemon_backend : public i_backend_wallet_callback
class wallets_manager : public i_backend_wallet_callback
{
public:
@ -55,6 +57,7 @@ public:
{
currency::core_runtime_config core_conf;
epee::locked_object<std::shared_ptr<tools::wallet2>, wallet_lock_time_watching_policy> w;
std::shared_ptr<tools::wallet_rpc_server> rpc_wrapper; //500 bytes of extra data, we can afford it, to have rpc-like invoke map
std::atomic<bool> do_mining;
std::atomic<bool> major_stop;
std::atomic<bool> stop_for_refresh; //use separate var for passing to "refresh" member function,
@ -68,6 +71,10 @@ public:
std::atomic<bool>* plast_daemon_is_disconnected;
std::atomic<bool> has_related_alias_in_unconfirmed;
std::atomic<bool> need_to_update_wallet_info;
std::atomic<bool> long_refresh_in_progress;
epee::critical_section long_refresh_in_progress_lock; //secure wallet state and prevent from long wait while long refresh is in work
view::i_view* pview;
uint64_t wallet_id;
epee::locked_object<std::list<bc_services::offer_details_ex>> offers;
@ -78,8 +85,8 @@ public:
~wallet_vs_options();
};
daemon_backend();
~daemon_backend();
wallets_manager();
~wallets_manager();
bool init(int argc, char* argv[], view::i_view* pview_handler);
bool start();
bool stop();
@ -87,6 +94,8 @@ public:
std::string open_wallet(const std::wstring& path, const std::string& password, uint64_t txs_to_return, view::open_wallet_response& owr);
std::string generate_wallet(const std::wstring& path, const std::string& password, view::open_wallet_response& owr);
std::string restore_wallet(const std::wstring& path, const std::string& password, const std::string& restore_key, view::open_wallet_response& owr);
std::string invoke(uint64_t wallet_id, std::string params);
std::string get_wallet_status(uint64_t wallet_id);
std::string run_wallet(uint64_t wallet_id);
std::string get_recent_transfers(size_t wallet_id, uint64_t offset, uint64_t count, view::transfers_array& tr_hist);
std::string get_wallet_info(size_t wallet_id, view::wallet_info& wi);
@ -97,6 +106,7 @@ public:
std::string request_cancel_contract(size_t wallet_id, const crypto::hash& contract_id, uint64_t fee, uint64_t expiration_period);
std::string accept_cancel_contract(size_t wallet_id, const crypto::hash& contract_id);
std::string get_connectivity_status();
std::string get_wallet_info(wallet_vs_options& w, view::wallet_info& wi);
std::string close_wallet(size_t wallet_id);
std::string push_offer(size_t wallet_id, const bc_services::offer_details_ex& od, currency::transaction& res_tx);
@ -134,8 +144,10 @@ public:
std::string transfer(size_t wallet_id, const view::transfer_params& tp, currency::transaction& res_tx);
std::string get_config_folder();
std::string is_valid_brain_restore_data(const std::string& brain_text);
#ifndef MOBILE_WALLET_BUILD
void subscribe_to_core_events(currency::i_core_event_handler* pevents_handler);
void unsubscribe_to_core_events();
//void unsubscribe_to_core_events();
#endif
void get_gui_options(view::gui_options& opt);
std::string get_wallet_log_prefix(size_t wallet_id) const;
bool is_qt_logs_enabled() const { return m_qt_logs_enbaled; }
@ -152,6 +164,7 @@ private:
void update_wallets_info();
void init_wallet_entry(wallet_vs_options& wo, uint64_t id);
static void prepare_wallet_status_info(wallet_vs_options& wo, view::wallet_status_info& wsi);
bool get_is_remote_daemon_connected();
//----- i_backend_wallet_callback ------
virtual void on_new_block(size_t wallet_id, uint64_t height, const currency::block& block);
virtual void on_transfer2(size_t wallet_id, const tools::wallet_public::wallet_transfer_info& wti, uint64_t balance, uint64_t unlocked_balance, uint64_t total_mined);
@ -164,7 +177,6 @@ private:
view::i_view m_view_stub;
view::i_view* m_pview;
std::shared_ptr<tools::i_core_proxy> m_rpc_proxy;
mutable critical_section m_wallets_lock;
po::variables_map m_vm;
std::atomic<uint64_t> m_last_daemon_height;
@ -176,12 +188,14 @@ private:
std::string m_data_dir;
view::gui_options m_ui_opt;
#ifndef MOBILE_WALLET_BUILD
//daemon stuff
bc_services::bc_offers_service m_offers_service;
currency::core m_ccore;
currency::t_currency_protocol_handler<currency::core> m_cprotocol;
nodetool::node_server<currency::t_currency_protocol_handler<currency::core> > m_p2psrv;
currency::core_rpc_server m_rpc_server;
#endif
bool m_remote_node_mode;
bool m_qt_logs_enbaled;
@ -189,6 +203,9 @@ private:
std::map<size_t, wallet_vs_options> m_wallets;
//mutable critical_section m_wallets_lock;
mutable boost::shared_mutex m_wallets_lock;
std::vector<std::string> m_wallet_log_prefixes;
mutable critical_section m_wallet_log_prefixes_lock;
};

View file

@ -2047,9 +2047,11 @@ test_chain_unit_enchanced::test_chain_unit_enchanced()
: m_invalid_block_index(std::numeric_limits<size_t>::max())
, m_orphan_block_index(std::numeric_limits<size_t>::max())
, m_invalid_tx_index(std::numeric_limits<size_t>::max())
, m_unverifiable_tx_index(std::numeric_limits<size_t>::max())
{
REGISTER_CALLBACK_METHOD(test_chain_unit_enchanced, configure_core);
REGISTER_CALLBACK_METHOD(test_chain_unit_enchanced, mark_invalid_tx);
REGISTER_CALLBACK_METHOD(test_chain_unit_enchanced, mark_unverifiable_tx);
REGISTER_CALLBACK_METHOD(test_chain_unit_enchanced, mark_invalid_block);
REGISTER_CALLBACK_METHOD(test_chain_unit_enchanced, mark_orphan_block);
REGISTER_CALLBACK_METHOD(test_chain_unit_enchanced, check_top_block);

View file

@ -258,6 +258,9 @@ public:
{
if (m_invalid_tx_index == event_idx)
return tvc.m_verification_failed;
if (m_unverifiable_tx_index == event_idx)
return tvc.m_verification_impossible;
return !tvc.m_verification_failed && tx_added;
}
@ -291,6 +294,12 @@ public:
return true;
}
bool mark_unverifiable_tx(currency::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/)
{
m_unverifiable_tx_index = ev_index + 1;
return true;
}
bool configure_core(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
bool check_top_block(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
bool clear_tx_pool(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
@ -310,6 +319,7 @@ protected:
};
size_t m_invalid_block_index;
size_t m_invalid_tx_index;
size_t m_unverifiable_tx_index;
size_t m_orphan_block_index;
};

View file

@ -8,11 +8,12 @@
#include "chaingen_tests_list.h"
#include "common/command_line.h"
#include "transaction_tests.h"
#include "../../src/gui/qt-daemon/application/core_fast_rpc_proxy.h"
#include "../../src/wallet/core_fast_rpc_proxy.h"
#include "test_core_proxy.h"
#include "currency_core/bc_offers_service.h"
#include "random_helper.h"
#include "core_state_helper.h"
#include "common/db_backend_selector.h"
#define TX_BLOBSIZE_CHECKER_LOG_FILENAME "get_object_blobsize(tx).log"
@ -666,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("."));
currency::core::init_options(desc_options);
tools::db::db_backend_selector::init_options(desc_options);
bool r = command_line::handle_error_helper(desc_options, [&]()
{
@ -809,6 +811,7 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(gen_checkpoints_prun_txs_after_blockchain_load);
GENERATE_AND_PLAY(gen_checkpoints_reorganize);
GENERATE_AND_PLAY(gen_checkpoints_pos_validation_on_altchain);
GENERATE_AND_PLAY(gen_checkpoints_and_invalid_tx_to_pool);
GENERATE_AND_PLAY(gen_no_attchments_in_coinbase);
GENERATE_AND_PLAY(gen_no_attchments_in_coinbase_gentime);

View file

@ -81,7 +81,9 @@ bool gen_checkpoints_attachments_basic::generate(std::vector<test_event_entry>&
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
// 0 ... N N+1 N+2 <- height (N = CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
// CP checkpoint
// (0 )- (0r)- (1 )- (2 )
// tx_0 txs
DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2));
@ -94,10 +96,13 @@ bool gen_checkpoints_attachments_basic::generate(std::vector<test_event_entry>&
attachments.push_back(cm);
attachments.push_back(ms);
MAKE_TX_LIST_START_WITH_ATTACHS(events, txs, miner_acc, miner_acc, MK_TEST_COINS(1), blk_0r, attachments);
m_tx_hash = get_transaction_hash(txs.front());
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, true)); // tx_0 goes with the block blk_1
MAKE_TX_ATTACH(events, tx_0, miner_acc, miner_acc, MK_TEST_COINS(1), blk_0r, attachments);
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, false));
m_tx_hash = get_transaction_hash(tx_0);
MAKE_NEXT_BLOCK_TX_LIST(events, blk_1, blk_0r, miner_acc, txs);
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0);
MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner_acc);
@ -150,7 +155,10 @@ bool gen_checkpoints_invalid_keyimage::generate(std::vector<test_event_entry>& e
// don't sign at all
// tb.step5_sign();
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, true)); // tb.m_tx goes with block blk_1
events.push_back(tb.m_tx);
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, false));
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tb.m_tx);
MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner_acc);
@ -376,33 +384,40 @@ bool gen_checkpoints_prun_txs_after_blockchain_load::generate(std::vector<test_e
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
// 0 ... N N+1 N+2 N+3 N+4 N+5 N+6 <- height (N = CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
// +------->CP1 +------->CP2 <- checkpoints
// | | <- when CP are set up
// (0 )- (0r)- (1 )- (2 )- (3 )- (4 )- (5 )- (6 ) <- main chain
// tx_0 tx_1 <- txs included in blocks
// 0 ... N N+1 N+2 N+3 N+4 N+5 N+6 N+7 <- height (N = CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
// +------->CP1 +------->CP2 <- checkpoints
// | | <- when CP are set up
// (0 )- (0r)- (1 )- (2 )- (3 )- (4 )- (5 )- (6 )- (7 ) <- main chain
// tx_0 tx_1 <- txs included in blocks
//
// Expected: tx_0 and tx_1 are both pruned
DO_CALLBACK(events, "check_not_being_in_cp_zone");
DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2));
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, true)); // tx_0 goes with blk_1_bad
MAKE_TX(events, tx_0, miner_acc, alice, MK_TEST_COINS(1), blk_0r);
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, false));
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0);
DO_CALLBACK(events, "check_being_in_cp_zone");
MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner_acc);
MAKE_TX(events, tx_1, miner_acc, alice, MK_TEST_COINS(1), blk_2);
MAKE_NEXT_BLOCK_TX1(events, blk_3, blk_2, miner_acc, tx_1);
MAKE_NEXT_BLOCK(events, blk_3, blk_2, miner_acc);
DO_CALLBACK(events, "check_not_being_in_cp_zone");
DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5));
MAKE_NEXT_BLOCK(events, blk_4, blk_3, miner_acc);
MAKE_TX(events, tx_1, miner_acc, alice, MK_TEST_COINS(1), blk_3);
MAKE_NEXT_BLOCK_TX1(events, blk_4, blk_3, miner_acc, tx_1);
DO_CALLBACK(events, "check_not_being_in_cp_zone");
DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 6));
MAKE_NEXT_BLOCK(events, blk_5, blk_4, miner_acc);
DO_CALLBACK(events, "check_being_in_cp_zone");
MAKE_NEXT_BLOCK(events, blk_6, blk_5, miner_acc);
MAKE_NEXT_BLOCK(events, blk_7, blk_6, miner_acc);
DO_CALLBACK(events, "check_not_being_in_cp_zone");
m_tx0_id = get_transaction_hash(tx_0);
@ -813,3 +828,70 @@ bool gen_no_attchments_in_coinbase_gentime::generate(std::vector<test_event_entr
return true;
}
//------------------------------------------------------------------------------
gen_checkpoints_and_invalid_tx_to_pool::gen_checkpoints_and_invalid_tx_to_pool()
{
REGISTER_CALLBACK_METHOD(gen_checkpoints_and_invalid_tx_to_pool, c1);
}
bool gen_checkpoints_and_invalid_tx_to_pool::generate(std::vector<test_event_entry>& events) const
{
// Test idea: make sure txs with invalid signatures rejected by the pool when the core is in CP zone
// Mine a block aftewards to make sure everything is okay.
// 0 ... N N+1 N+2 <- height (N = CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
// +------->CP1 <- checkpoint
// | <- when CP is set up
// (0 )- (0r)- (1 )- (2 )- <- main chain
// tx_0 CB
bool r = false;
GENERATE_ACCOUNT(miner_acc);
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1));
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
std::vector<tx_source_entry> sources;
std::vector<tx_destination_entry> destinations;
r = fill_tx_sources_and_destinations(events, blk_0r, miner_acc, miner_acc, MK_TEST_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations);
CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources_and_destinations failed");
transaction tx_0 = AUTO_VAL_INIT(tx_0);
r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_attachment, tx_0, 0);
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
// invalidate tx_0 signature
tx_0.signatures.clear();
DO_CALLBACK(events, "mark_unverifiable_tx");
events.push_back(tx_0);
MAKE_NEXT_BLOCK(events, blk_1, blk_0r, miner_acc); // <-- CHECKPOINT
MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner_acc);
DO_CALLBACK(events, "check_not_being_in_cp_zone");
DO_CALLBACK(events, "check_tx_pool_empty");
// try to mine a block using default blocktemplate (all txs from the pool)
DO_CALLBACK(events, "c1");
DO_CALLBACK(events, "check_tx_pool_empty");
return true;
}
bool gen_checkpoints_and_invalid_tx_to_pool::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
account_base acc;
acc.generate();
bool r = mine_next_pow_block_in_playtime(acc.get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
return true;
}

View file

@ -102,3 +102,10 @@ struct gen_no_attchments_in_coinbase_gentime : public checkpoints_test
{
bool generate(std::vector<test_event_entry>& events) const;
};
struct gen_checkpoints_and_invalid_tx_to_pool : public checkpoints_test
{
gen_checkpoints_and_invalid_tx_to_pool();
bool generate(std::vector<test_event_entry>& events) const;
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};

Some files were not shown because too many files have changed in this diff Show more