Merge branch 'release'
This commit is contained in:
commit
cc79aa87b3
85 changed files with 4232 additions and 1474 deletions
5
.gitmodules
vendored
5
.gitmodules
vendored
|
|
@ -8,4 +8,7 @@
|
|||
[submodule "contrib/tor-connect"]
|
||||
path = contrib/tor-connect
|
||||
url = https://github.com/hyle-team/tor-connect.git
|
||||
branch = main
|
||||
branch = main
|
||||
[submodule "contrib/jwt-cpp"]
|
||||
path = contrib/jwt-cpp
|
||||
url = https://github.com/Thalhammer/jwt-cpp.git
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
PROJECT(Zano)
|
||||
|
||||
|
|
@ -18,6 +18,9 @@ endif()
|
|||
if(POLICY CMP0043)
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
endif()
|
||||
if(POLICY CMP0144)
|
||||
cmake_policy(SET CMP0144 NEW)
|
||||
endif()
|
||||
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
|
@ -50,7 +53,7 @@ if (UNIX AND NOT APPLE)
|
|||
else()
|
||||
# multi configurations for MSVC and XCode
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
set(CMAKE_CONFIGURATION_TYPES "Release")
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
|
||||
else()
|
||||
|
|
@ -58,7 +61,7 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
message("Generated with config types: ${CMAKE_CONFIGURATION_TYPES}, and built type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(OPENSSL_USE_STATIC_LIBS TRUE) # link statically
|
||||
|
|
@ -66,7 +69,7 @@ find_package(OpenSSL REQUIRED)
|
|||
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15)
|
||||
endif()
|
||||
|
||||
set(USE_PCH FALSE CACHE BOOL "Use shared precompiled headers")
|
||||
|
|
@ -74,7 +77,7 @@ set(DISABLE_TOR FALSE CACHE BOOL "Disable TOR library(and related tor-connect su
|
|||
set(TESTNET FALSE CACHE BOOL "Compile for testnet")
|
||||
set(BUILD_GUI FALSE CACHE BOOL "Build qt-daemon")
|
||||
|
||||
include_directories(src contrib/eos_portable_archive contrib contrib/epee/include ${OPENSSL_INCLUDE_DIR} "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib")
|
||||
include_directories(src contrib/eos_portable_archive contrib contrib/epee/include contrib/jwt-cpp/include ${OPENSSL_INCLUDE_DIR} "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib")
|
||||
|
||||
add_definitions(-DSTATICLIB)
|
||||
|
||||
|
|
@ -122,6 +125,7 @@ if(MSVC)
|
|||
endforeach()
|
||||
endif()
|
||||
include_directories(SYSTEM src/platform/msc)
|
||||
configure_file(utils/Directory.Build.props.in ${CMAKE_BINARY_DIR}/Directory.Build.props)
|
||||
else()
|
||||
set(ARCH default CACHE STRING "CPU to build for: -march value or default")
|
||||
if("${ARCH}" STREQUAL "default")
|
||||
|
|
@ -225,11 +229,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
|||
set(Boost_LIBRARIES "libboost.a")
|
||||
#workaround for new XCode 12 policy for builds(now it includes a slice for the "arm64" when builds for simulator)
|
||||
set(__iphoneos_archs "arm64")
|
||||
set(__iphonesimulator_archs "x86_64")
|
||||
#set(__iphonesimulator_archs "arm64,x86_64")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "${__iphoneos_archs}")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "${__iphoneos_archs}")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "${__iphonesimulator_archs}")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "${__iphonesimulator_archs}")
|
||||
#set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "${__iphonesimulator_archs}")
|
||||
#set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "${__iphonesimulator_archs}")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(Boost_LIBRARY_DIRS "${Boost_LIBRARY_DIRS}/${CMAKE_ANDROID_ARCH_ABI}/")
|
||||
set(Boost_LIBRARIES "${Boost_LIBRARY_DIRS}libboost_system.a;${Boost_LIBRARY_DIRS}libboost_filesystem.a;${Boost_LIBRARY_DIRS}libboost_thread.a;${Boost_LIBRARY_DIRS}libboost_timer.a;${Boost_LIBRARY_DIRS}libboost_date_time.a;${Boost_LIBRARY_DIRS}libboost_chrono.a;${Boost_LIBRARY_DIRS}libboost_regex.a;${Boost_LIBRARY_DIRS}libboost_serialization.a;${Boost_LIBRARY_DIRS}libboost_atomic.a;${Boost_LIBRARY_DIRS}libboost_program_options.a")
|
||||
|
|
@ -260,8 +264,10 @@ elseif(NOT MSVC)
|
|||
endif()
|
||||
|
||||
if(BUILD_GUI)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_minimum_required(VERSION 3.1) # <-- this is important for Linux GUI build, don't touch it -- sowle
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5WebEngineWidgets REQUIRED)
|
||||
find_package(Qt5WebChannel REQUIRED)
|
||||
endif()
|
||||
|
||||
set(COMMIT_ID_IN_VERSION ON CACHE BOOL "Include commit ID in version")
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ Be sure to clone the repository properly:\
|
|||
|--|--|--|--|
|
||||
| gcc (Linux) | 5.4.0 | 9.4.0 | 12.3.0 |
|
||||
| llvm/clang (Linux) | UNKNOWN | 7.0.1 | 8.0.0 |
|
||||
| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2017 (15.9.30) | 2017 (15.9.30) | 2022 (17.7.5) |
|
||||
| [XCode](https://developer.apple.com/downloads/) (macOS) | 12.3 | 14.3 | 14.3 |
|
||||
| [CMake](https://cmake.org/download/) | 3.15.5 | 3.22.1 | 3.26.3 |
|
||||
| [Boost](https://www.boost.org/users/download/) | 1.70 | 1.70 | 1.76 |
|
||||
| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2017 (15.9.30) | 2019 (16.11.34) | 2022 (17.9.5) |
|
||||
| [XCode](https://developer.apple.com/downloads/) (macOS) | 12.3 | 14.3 | 15.2 |
|
||||
| [CMake](https://cmake.org/download/) | 3.15.5 | 3.26.3 | 3.29.0 |
|
||||
| [Boost](https://www.boost.org/users/download/) | 1.70 | 1.70 | 1.84 |
|
||||
| [OpenSSL](https://www.openssl.org/source/) [(win)](https://slproweb.com/products/Win32OpenSSL.html) | 1.1.1n | 1.1.1w | 1.1.1w |
|
||||
| [Qt](https://download.qt.io/archive/qt/) (*only for GUI*) | 5.8.0 | 5.11.2 | 5.15.2 |
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ 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")
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <iostream>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
#ifndef MAKE64
|
||||
#define MAKE64(low,high) ((__int64)(((DWORD)(low)) | ((__int64)((DWORD)(high))) << 32))
|
||||
|
|
@ -561,16 +562,15 @@ namespace file_io_utils
|
|||
try
|
||||
{
|
||||
|
||||
boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end
|
||||
for ( boost::filesystem::directory_iterator itr( epee::string_encoding::utf8_to_wstring(path) ); itr != end_itr; ++itr )
|
||||
std::filesystem::directory_iterator end_itr; // default construction yields past-the-end
|
||||
for ( std::filesystem::directory_iterator itr( epee::string_encoding::utf8_to_wstring(path) ); itr != end_itr; ++itr )
|
||||
{
|
||||
if ( only_files && boost::filesystem::is_directory(itr->status()) )
|
||||
if ( only_files && std::filesystem::is_directory(itr->status()) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
target_list.push_back(itr->path().filename().string());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
catch(...)
|
||||
|
|
|
|||
|
|
@ -82,6 +82,13 @@ namespace epee
|
|||
|
||||
namespace misc_utils
|
||||
{
|
||||
|
||||
template<typename t_type_a, typename t_type_b>
|
||||
void cast_assign_a_to_b(t_type_a& a, const t_type_b& b)
|
||||
{
|
||||
*static_cast<t_type_b*>(&a) = b;
|
||||
}
|
||||
|
||||
template<class _Ty1,
|
||||
class _Ty2,
|
||||
class _Ty3>
|
||||
|
|
@ -532,6 +539,92 @@ namespace misc_utils
|
|||
|
||||
};
|
||||
|
||||
template<typename key, typename expiration_type>
|
||||
struct expirating_set
|
||||
{
|
||||
typedef std::set<key> main_set;
|
||||
main_set m_set;
|
||||
std::multimap<expiration_type, typename main_set::iterator> m_expirations;
|
||||
|
||||
const main_set& get_set()
|
||||
{
|
||||
return m_set;
|
||||
}
|
||||
void add(const key& k, const expiration_type& e)
|
||||
{
|
||||
auto res = m_set.insert(k);
|
||||
m_expirations.insert({ e, res.first });
|
||||
}
|
||||
|
||||
void remove_if_expiration_less_than(const expiration_type& e)
|
||||
{
|
||||
while(m_expirations.size() && m_expirations.begin()->first < e)
|
||||
{
|
||||
m_set.erase(m_expirations.begin()->second);
|
||||
m_expirations.erase(m_expirations.begin());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename key, typename expiration_type, typename value_type>
|
||||
struct expirating_map
|
||||
{
|
||||
typedef std::map<key, value_type> main_map;
|
||||
main_map m_map;
|
||||
std::multimap<expiration_type, typename main_map::iterator> m_expirations;
|
||||
|
||||
const main_map& get_map()
|
||||
{
|
||||
return m_map;
|
||||
}
|
||||
void add(const key& k, const value_type& v, const expiration_type& e)
|
||||
{
|
||||
auto res = m_map.insert(k, v);
|
||||
m_expirations.insert({ e, res.first });
|
||||
}
|
||||
|
||||
void remove_if_expiration_less_than(const expiration_type& e)
|
||||
{
|
||||
while (m_expirations.size() && m_expirations.begin()->first < e)
|
||||
{
|
||||
m_map.erase(m_expirations.begin()->second);
|
||||
m_expirations.erase(m_expirations.begin());
|
||||
}
|
||||
}
|
||||
|
||||
template <class t_archive>
|
||||
inline void serialize(t_archive& a, const unsigned int ver)
|
||||
{
|
||||
std::vector<std::tuple<key, value_type, expiration_type> > items;
|
||||
if constexpr (t_archive::is_saving::value)
|
||||
{
|
||||
for (const auto& item: m_expirations)
|
||||
{
|
||||
items.resize(items.size + 1);
|
||||
std::get<2>(items.back()) = item.first;
|
||||
std::get<0>(items.back()) = item.second.first;
|
||||
std::get<1>(items.back()) = item.second.second;
|
||||
}
|
||||
}
|
||||
a & items;
|
||||
|
||||
if constexpr (!t_archive::is_saving::value)
|
||||
{
|
||||
for (const auto& item : items)
|
||||
{
|
||||
this->add(std::get<0>(item), std::get<1>(item), std::get<2>(item));
|
||||
|
||||
|
||||
items.resize(items.size + 1);
|
||||
std::get<2>(items.back()) = item.first;
|
||||
std::get<0>(items.back()) = item.second.first;
|
||||
std::get<1>(items.back()) = item.second.second;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace misc_utils
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ namespace net_utils
|
|||
std::string m_transfer_encoding;//"Transfer-Encoding:"
|
||||
std::string m_content_encoding; //"Content-Encoding:"
|
||||
std::string m_host; //"Host:"
|
||||
std::string m_cookie; //"Cookie:"
|
||||
std::string m_cookie; //"Cookie:"
|
||||
fields_list m_etc_fields;
|
||||
|
||||
void clear()
|
||||
|
|
@ -147,10 +147,10 @@ namespace net_utils
|
|||
std::string m_http_method_str;
|
||||
std::string m_full_request_str;
|
||||
std::string m_replace_html;
|
||||
std::string m_request_head;
|
||||
std::string m_request_head;
|
||||
int m_http_ver_hi;
|
||||
int m_http_ver_lo;
|
||||
bool m_have_to_block;
|
||||
bool m_have_to_block;
|
||||
http_header_info m_header_info;
|
||||
uri_content m_uri_content;
|
||||
size_t m_full_request_buf_size;
|
||||
|
|
@ -166,11 +166,11 @@ namespace net_utils
|
|||
|
||||
struct http_response_info
|
||||
{
|
||||
int m_response_code;
|
||||
std::string m_response_comment;
|
||||
int m_response_code;
|
||||
std::string m_response_comment;
|
||||
fields_list m_additional_fields;
|
||||
std::string m_body;
|
||||
std::string m_mime_tipe;
|
||||
std::string m_body;
|
||||
std::string m_mime_tipe;
|
||||
http_header_info m_header_info;
|
||||
int m_http_ver_hi;// OUT paramter only
|
||||
int m_http_ver_lo;// OUT paramter only
|
||||
|
|
|
|||
|
|
@ -30,133 +30,11 @@
|
|||
#include "storages/portable_storage_template_helper.h"
|
||||
#include "http_base.h"
|
||||
#include "net/net_utils_base.h"
|
||||
#include "storages/portable_storage_extended_for_doc.h"
|
||||
|
||||
|
||||
|
||||
template<typename typename_t>
|
||||
typename_t get_documentation_json_struct()
|
||||
{
|
||||
return AUTO_VAL_INIT_T(typename_t);
|
||||
}
|
||||
|
||||
template<typename request_t, typename response_t>
|
||||
bool auto_doc_t(const std::string& prefix_name, std::string& generate_reference)
|
||||
{
|
||||
if (!generate_reference.size()) return true;
|
||||
request_t req = get_documentation_json_struct<request_t>();
|
||||
response_t res = get_documentation_json_struct<response_t>();
|
||||
std::stringstream ss;
|
||||
ss << prefix_name << ENDL
|
||||
<< "REQUEST: " << ENDL << epee::serialization::store_t_to_json(req) << ENDL << "--------------------------------" << ENDL
|
||||
<< "RESPONSE: " << ENDL << epee::serialization::store_t_to_json(res) << ENDL << "################################" << ENDL;
|
||||
generate_reference += ss.str();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename command_type_t>
|
||||
bool auto_doc(const std::string& prefix_name, std::string& generate_reference)
|
||||
{
|
||||
return auto_doc_t<typename command_type_t::request, typename command_type_t::response>(prefix_name, generate_reference);
|
||||
}
|
||||
|
||||
namespace epee {
|
||||
namespace net_utils {
|
||||
namespace http {
|
||||
struct i_chain_handler
|
||||
{
|
||||
virtual bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response_info,
|
||||
epee::net_utils::connection_context_base& m_conn_context, bool& call_found, std::string& generate_reference) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \
|
||||
epee::net_utils::http::http_response_info& response, \
|
||||
context_type& m_conn_context) \
|
||||
{\
|
||||
response.m_response_code = 200; \
|
||||
response.m_response_comment = "Ok"; \
|
||||
std::string reference_stub; \
|
||||
bool call_found = false; \
|
||||
if(!handle_http_request_map(query_info, response, m_conn_context, call_found, reference_stub) && response.m_response_code == 200) \
|
||||
{ response.m_response_code = 500; response.m_response_comment = "Internal Server Error"; return true; } \
|
||||
if (!call_found) \
|
||||
{ response.m_response_code = 404; response.m_response_comment = "Not Found"; return true; } \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define BEGIN_URI_MAP2() template<class t_context> bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \
|
||||
epee::net_utils::http::http_response_info& response_info, \
|
||||
t_context& m_conn_context, bool& call_found, std::string& generate_reference) { \
|
||||
call_found = false; \
|
||||
if(false) return true; //just a stub to have "else if"
|
||||
|
||||
#define BEGIN_URI_MAP2_VIRTUAL() virtual bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \
|
||||
epee::net_utils::http::http_response_info& response_info, \
|
||||
epee::net_utils::connection_context_base& m_conn_context, bool& call_found, std::string& generate_reference) { \
|
||||
call_found = false; \
|
||||
if(false) return true; //just a stub to have "else if"
|
||||
|
||||
|
||||
#define MAP_URI2(pattern, callback) else if(std::string::npos != query_info.m_URI.find(pattern)) return callback(query_info, response_info, m_conn_context);
|
||||
|
||||
#define MAP_URI_AUTO_XML2(s_pattern, callback_f, command_type) //TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
|
||||
|
||||
#define MAP_URI_AUTO_JON2(s_pattern, callback_f, command_type) \
|
||||
else if(auto_doc<command_type>(s_pattern "[JSON]", generate_reference) && query_info.m_URI == s_pattern) \
|
||||
{ \
|
||||
call_found = true; \
|
||||
uint64_t ticks = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::request> req; \
|
||||
bool res = epee::serialization::load_t_from_json(static_cast<command_type::request&>(req), query_info.m_body); \
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to parse json: \r\n" << query_info.m_body); \
|
||||
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::response> resp;\
|
||||
res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), m_conn_context); \
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to call " << #callback_f << "() while handling " << s_pattern); \
|
||||
uint64_t ticks2 = epee::misc_utils::get_tick_count(); \
|
||||
epee::serialization::store_t_to_json(static_cast<command_type::response&>(resp), response_info.m_body); \
|
||||
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
|
||||
response_info.m_mime_tipe = "application/json"; \
|
||||
response_info.m_header_info.m_content_type = " application/json"; \
|
||||
LOG_PRINT("[HTTP/JSON][" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "][" << query_info.m_URI << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \
|
||||
}
|
||||
|
||||
#define MAP_URI_AUTO_BIN2(s_pattern, callback_f, command_type) \
|
||||
else if(auto_doc<command_type>(s_pattern "[BIN]", generate_reference) && query_info.m_URI == s_pattern) \
|
||||
{ \
|
||||
call_found = true; \
|
||||
uint64_t ticks = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::request> req; \
|
||||
bool res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), query_info.m_body); \
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \
|
||||
uint64_t ticks1 = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::response> resp;\
|
||||
res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), m_conn_context); \
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to call " << #callback_f << "() while handling " << s_pattern); \
|
||||
uint64_t ticks2 = misc_utils::get_tick_count(); \
|
||||
epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), response_info.m_body); \
|
||||
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
|
||||
response_info.m_mime_tipe = " application/octet-stream"; \
|
||||
response_info.m_header_info.m_content_type = " application/octet-stream"; \
|
||||
LOG_PRINT( "[HTTP/BIN][" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "][" << query_info.m_URI << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \
|
||||
}
|
||||
|
||||
#define CHAIN_TO_PHANDLER(pi_chain_handler) else if (pi_chain_handler && pi_chain_handler->handle_http_request_map(query_info, response_info, m_conn_context, call_found, generate_reference) && call_found) { return true;}
|
||||
|
||||
#define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);call_found = true;}
|
||||
|
||||
#define END_URI_MAP2() return true;}
|
||||
|
||||
|
||||
|
||||
|
||||
namespace epee
|
||||
namespace epee
|
||||
{
|
||||
namespace json_rpc
|
||||
{
|
||||
|
|
@ -169,7 +47,7 @@ namespace epee
|
|||
t_param params;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(jsonrpc)
|
||||
KV_SERIALIZE(jsonrpc) DOC_DSCR("") DOC_EXMP("2.0") DOC_END
|
||||
KV_SERIALIZE(id)
|
||||
KV_SERIALIZE(method)
|
||||
KV_SERIALIZE(params)
|
||||
|
|
@ -185,7 +63,7 @@ namespace epee
|
|||
KV_SERIALIZE(message)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct dummy_error
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
|
|
@ -220,7 +98,7 @@ namespace epee
|
|||
t_param result;
|
||||
epee::serialization::storage_entry id;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(jsonrpc)
|
||||
KV_SERIALIZE(jsonrpc) DOC_DSCR("") DOC_EXMP("2.0") DOC_END
|
||||
KV_SERIALIZE(id)
|
||||
KV_SERIALIZE(result)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
|
@ -245,20 +123,270 @@ namespace epee
|
|||
}
|
||||
}
|
||||
|
||||
template<typename command_type_t>
|
||||
struct json_command_type_t
|
||||
|
||||
template<typename typename_t>
|
||||
typename_t get_documentation_json_struct()
|
||||
{
|
||||
typedef typename epee::json_rpc::request<typename command_type_t::request> request;
|
||||
typedef typename epee::json_rpc::request<typename command_type_t::response> response;
|
||||
return AUTO_VAL_INIT_T(typename_t);
|
||||
}
|
||||
|
||||
struct documentation_entry
|
||||
{
|
||||
std::string uri;
|
||||
bool is_binary = false; //if not - then it's JSON
|
||||
std::string json_method_name;
|
||||
std::string request_json_example;
|
||||
std::string request_json_descriptions;
|
||||
|
||||
std::string response_json_example;
|
||||
std::string response_json_descriptions;
|
||||
|
||||
std::string method_general_decription;
|
||||
};
|
||||
|
||||
#define JSON_RPC_REFERENCE_MARKER "JSON_RPC"
|
||||
struct documentation
|
||||
{
|
||||
bool do_generate_documentation = false;
|
||||
std::list<documentation_entry> entries;
|
||||
};
|
||||
|
||||
// Primary template
|
||||
template<typename T>
|
||||
struct has_static_member_description {
|
||||
private:
|
||||
// SFINAE test function
|
||||
template<typename U>
|
||||
static auto test(int) -> decltype(U::description, std::true_type{});
|
||||
|
||||
// Fallback function
|
||||
template<typename>
|
||||
static auto test(...) -> std::false_type;
|
||||
|
||||
public:
|
||||
// Member constant indicating whether T has a static member
|
||||
static constexpr bool value = decltype(test<T>(0))::value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == JSON_RPC_REFERENCE_MARKER || query_info.m_URI == uri) \
|
||||
|
||||
template <typename T>
|
||||
const char* get_command_description()
|
||||
{
|
||||
if constexpr (has_static_member_description<T>::value)
|
||||
{
|
||||
return T::description;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "NO DESCRIPTION";
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void f(T) {} // Definition #2
|
||||
|
||||
|
||||
// Base template
|
||||
template<typename T>
|
||||
struct is_std_simple_container : std::false_type {};
|
||||
|
||||
// Specializations for each container
|
||||
template<typename T, typename Alloc>
|
||||
struct is_std_simple_container<std::vector<T, Alloc>> : std::true_type {};
|
||||
|
||||
template<typename T, typename Alloc>
|
||||
struct is_std_simple_container<std::deque<T, Alloc>> : std::true_type {};
|
||||
|
||||
template<typename T, typename Alloc>
|
||||
struct is_std_simple_container<std::list<T, Alloc>> : std::true_type {};
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
struct is_std_simple_container<std::array<T, N>> : std::true_type {};
|
||||
|
||||
|
||||
template<typename command_type_t, bool is_json_rpc_method>
|
||||
bool auto_doc(const std::string& uri, const std::string& method, bool is_json, documentation& docs)
|
||||
{
|
||||
if (!docs.do_generate_documentation) return true;
|
||||
|
||||
docs.entries.resize(docs.entries.size()+1);
|
||||
docs.entries.back().is_binary = !is_json;
|
||||
docs.entries.back().uri = uri;
|
||||
docs.entries.back().json_method_name = method;
|
||||
docs.entries.back().method_general_decription = get_command_description<command_type_t>();
|
||||
|
||||
if constexpr (is_json_rpc_method)
|
||||
{
|
||||
//json rpc-like call
|
||||
typedef typename epee::json_rpc::request<typename command_type_t::request> request_t;
|
||||
typedef typename epee::json_rpc::response<typename command_type_t::response, typename epee::json_rpc::dummy_error> response_t;
|
||||
request_t req = AUTO_VAL_INIT(req); //get_documentation_json_struct<request_t>();
|
||||
if constexpr (is_std_simple_container<typename command_type_t::request>::value)
|
||||
{
|
||||
req.params.resize(1);
|
||||
}
|
||||
|
||||
response_t res = AUTO_VAL_INIT(res);
|
||||
if constexpr (is_std_simple_container<typename command_type_t::response>::value)
|
||||
{
|
||||
req.result.resize(1);
|
||||
}
|
||||
|
||||
req.method = method;
|
||||
epee::serialization::portable_storage_extended_doc ps;
|
||||
req.store(ps, nullptr);
|
||||
ps.dump_as_json(docs.entries.back().request_json_example);
|
||||
ps.dump_as_decriptions(docs.entries.back().request_json_descriptions);
|
||||
|
||||
epee::serialization::portable_storage_extended_doc ps_res;
|
||||
res.store(ps_res, nullptr);
|
||||
ps_res.dump_as_json(docs.entries.back().response_json_example);
|
||||
ps_res.dump_as_decriptions(docs.entries.back().response_json_descriptions);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//json/bin uri/based
|
||||
typedef typename command_type_t::request request_t;
|
||||
typedef typename command_type_t::response response_t;
|
||||
|
||||
request_t req = AUTO_VAL_INIT(req); //get_documentation_json_struct<request_t>();
|
||||
response_t res = AUTO_VAL_INIT(res); //get_documentation_json_struct<response_t>();
|
||||
|
||||
|
||||
epee::serialization::portable_storage_extended_doc ps;
|
||||
req.store(ps, nullptr);
|
||||
ps.dump_as_json(docs.entries.back().request_json_example);
|
||||
ps.dump_as_decriptions(docs.entries.back().request_json_descriptions);
|
||||
|
||||
epee::serialization::portable_storage_extended_doc ps_res;
|
||||
res.store(ps_res, nullptr);
|
||||
ps_res.dump_as_json(docs.entries.back().response_json_example);
|
||||
ps_res.dump_as_decriptions(docs.entries.back().response_json_descriptions);
|
||||
}
|
||||
|
||||
|
||||
// std::stringstream ss;
|
||||
// ss << prefix_name << ENDL
|
||||
// << "REQUEST: " << ENDL << req_str << ENDL << req_str_descr << "--------------------------------" << ENDL
|
||||
// << "RESPONSE: " << ENDL << res_str << ENDL << res_str_descr << "################################" << ENDL;
|
||||
// generate_reference += ss.str();
|
||||
return true;
|
||||
|
||||
//return auto_doc_t<typename command_type_t::request, typename command_type_t::response>(prefix_name, generate_reference);
|
||||
}
|
||||
|
||||
namespace epee {
|
||||
namespace net_utils {
|
||||
namespace http {
|
||||
struct i_chain_handler
|
||||
{
|
||||
virtual bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response_info,
|
||||
epee::net_utils::connection_context_base& m_conn_context, bool& call_found, documentation& docs = epee::net_utils::http::i_chain_handler::m_empty_documentation) = 0;
|
||||
|
||||
static inline documentation m_empty_documentation;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \
|
||||
epee::net_utils::http::http_response_info& response, \
|
||||
context_type& m_conn_context) \
|
||||
{\
|
||||
response.m_response_code = 200; \
|
||||
response.m_response_comment = "Ok"; \
|
||||
bool call_found = false; \
|
||||
if(!handle_http_request_map(query_info, response, m_conn_context, call_found) && response.m_response_code == 200) \
|
||||
{ response.m_response_code = 500; response.m_response_comment = "Internal Server Error"; return true; } \
|
||||
if (!call_found) \
|
||||
{ response.m_response_code = 404; response.m_response_comment = "Not Found"; return true; } \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define BEGIN_URI_MAP2() template<class t_context> bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \
|
||||
epee::net_utils::http::http_response_info& response_info, \
|
||||
t_context& m_conn_context, bool& call_found, documentation& docs = epee::net_utils::http::i_chain_handler::m_empty_documentation) { \
|
||||
call_found = false; \
|
||||
if(false) return true; //just a stub to have "else if"
|
||||
|
||||
#define BEGIN_URI_MAP2_VIRTUAL() virtual bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \
|
||||
epee::net_utils::http::http_response_info& response_info, \
|
||||
epee::net_utils::connection_context_base& m_conn_context, bool& call_found, documentation& docs = epee::net_utils::http::i_chain_handler::m_empty_documentation) { \
|
||||
call_found = false; \
|
||||
if(false) return true; //just a stub to have "else if"
|
||||
|
||||
|
||||
#define MAP_URI2(pattern, callback) else if(std::string::npos != query_info.m_URI.find(pattern)) return callback(query_info, response_info, m_conn_context);
|
||||
|
||||
#define MAP_URI_AUTO_XML2(s_pattern, callback_f, command_type) //TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
|
||||
|
||||
#define MAP_URI_AUTO_JON2(s_pattern, callback_f, command_type) \
|
||||
else if(auto_doc<command_type, false>(s_pattern, "", true, docs) && query_info.m_URI == s_pattern) \
|
||||
{ \
|
||||
if(query_info.m_URI == JSON_RPC_REFERENCE_MARKER) {generate_reference = "JSON RPC URL: " uri "\n";} \
|
||||
call_found = true; \
|
||||
uint64_t ticks = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::request> req; \
|
||||
bool res = epee::serialization::load_t_from_json(static_cast<command_type::request&>(req), query_info.m_body); \
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to parse json: \r\n" << query_info.m_body); \
|
||||
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::response> resp;\
|
||||
res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), m_conn_context); \
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to call " << #callback_f << "() while handling " << s_pattern); \
|
||||
uint64_t ticks2 = epee::misc_utils::get_tick_count(); \
|
||||
epee::serialization::store_t_to_json(static_cast<command_type::response&>(resp), response_info.m_body); \
|
||||
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
|
||||
response_info.m_mime_tipe = "application/json"; \
|
||||
response_info.m_header_info.m_content_type = " application/json"; \
|
||||
LOG_PRINT("[HTTP/JSON][" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "][" << query_info.m_URI << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \
|
||||
}
|
||||
|
||||
#define MAP_URI_AUTO_BIN2(s_pattern, callback_f, command_type) \
|
||||
else if(auto_doc<command_type, false>(s_pattern, "", false, docs) && query_info.m_URI == s_pattern) \
|
||||
{ \
|
||||
call_found = true; \
|
||||
uint64_t ticks = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::request> req; \
|
||||
bool res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), query_info.m_body); \
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \
|
||||
uint64_t ticks1 = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::response> resp;\
|
||||
res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), m_conn_context); \
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to call " << #callback_f << "() while handling " << s_pattern); \
|
||||
uint64_t ticks2 = misc_utils::get_tick_count(); \
|
||||
epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), response_info.m_body); \
|
||||
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
|
||||
response_info.m_mime_tipe = " application/octet-stream"; \
|
||||
response_info.m_header_info.m_content_type = " application/octet-stream"; \
|
||||
LOG_PRINT( "[HTTP/BIN][" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "][" << query_info.m_URI << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \
|
||||
}
|
||||
|
||||
#define CHAIN_TO_PHANDLER(pi_chain_handler) else if (pi_chain_handler && pi_chain_handler->handle_http_request_map(query_info, response_info, m_conn_context, call_found, docs) && call_found) { return true;}
|
||||
|
||||
#define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);call_found = true;}
|
||||
|
||||
#define END_URI_MAP2() return true;}
|
||||
|
||||
|
||||
|
||||
//template<typename command_type_t>
|
||||
//struct json_command_type_t
|
||||
//{
|
||||
// typedef typename epee::json_rpc::request<typename command_type_t::request> request;
|
||||
// typedef typename epee::json_rpc::request<typename command_type_t::response> response;
|
||||
//};
|
||||
|
||||
//#define JSON_RPC_REFERENCE_MARKER "JSON_RPC"
|
||||
|
||||
// if(query_info.m_URI == JSON_RPC_REFERENCE_MARKER) {generate_reference = "JSON RPC URL: " uri "\n";} \
|
||||
|
||||
#define BEGIN_JSON_RPC_MAP(uri) else if(docs.do_generate_documentation || query_info.m_URI == uri) \
|
||||
{ \
|
||||
const char* current_zone_json_uri = uri;\
|
||||
LOG_PRINT_L4("[JSON_REQUEST_BODY]: " << ENDL << query_info.m_body); \
|
||||
uint64_t ticks = epee::misc_utils::get_tick_count(); \
|
||||
epee::serialization::portable_storage ps; \
|
||||
|
|
@ -317,7 +445,7 @@ struct json_command_type_t
|
|||
LOG_PRINT( query_info.m_URI << "[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2);
|
||||
|
||||
#define MAP_JON_RPC_WE(method_name, callback_f, command_type) \
|
||||
else if(auto_doc<json_command_type_t<command_type>>("[" method_name "]", generate_reference) && callback_name == method_name) \
|
||||
else if(auto_doc<command_type, true>(current_zone_json_uri, method_name, true, docs) && callback_name == method_name) \
|
||||
{ \
|
||||
call_found = true; \
|
||||
PREPARE_OBJECTS_FROM_JSON(command_type) \
|
||||
|
|
@ -335,7 +463,7 @@ struct json_command_type_t
|
|||
}
|
||||
|
||||
#define MAP_JON_RPC_WERI(method_name, callback_f, command_type) \
|
||||
else if(auto_doc<json_command_type_t<command_type>>("[" method_name "]", generate_reference) && callback_name == method_name) \
|
||||
else if(auto_doc<command_type, true>(current_zone_json_uri, method_name, true, docs) && callback_name == method_name) \
|
||||
{ \
|
||||
call_found = true; \
|
||||
PREPARE_OBJECTS_FROM_JSON(command_type) \
|
||||
|
|
@ -353,7 +481,7 @@ struct json_command_type_t
|
|||
}
|
||||
|
||||
#define MAP_JON_RPC(method_name, callback_f, command_type) \
|
||||
else if(auto_doc<json_command_type_t<command_type>>(std::string("[") + method_name + "]", generate_reference) && callback_name == method_name) \
|
||||
else if(auto_doc<command_type, true>(current_zone_json_uri, method_name, true, docs) && callback_name == method_name) \
|
||||
{ \
|
||||
call_found = true; \
|
||||
PREPARE_OBJECTS_FROM_JSON(command_type) \
|
||||
|
|
@ -386,4 +514,51 @@ struct json_command_type_t
|
|||
return true; \
|
||||
}
|
||||
|
||||
namespace epee
|
||||
{
|
||||
template<typename t_rpc_server>
|
||||
bool generate_doc_as_md_files(const std::string& folder, t_rpc_server& server)
|
||||
{
|
||||
LOG_PRINT_L0("Dumping RPC auto-generated documents!");
|
||||
epee::net_utils::http::http_request_info query_info;
|
||||
epee::net_utils::http::http_response_info response_info;
|
||||
epee::net_utils::connection_context_base conn_context;
|
||||
//std::string generate_reference = std::string("WALLET_RPC_COMMANDS_LIST:\n");
|
||||
bool call_found = false;
|
||||
|
||||
documentation docs;
|
||||
docs.do_generate_documentation = true;
|
||||
// query_info.m_URI = JSON_RPC_REFERENCE_MARKER;
|
||||
query_info.m_body = "{\"jsonrpc\": \"2.0\", \"method\": \"nonexisting_method\", \"params\": {}},";
|
||||
server.handle_http_request_map(query_info, response_info, conn_context, call_found, docs);
|
||||
|
||||
for (const auto& de : docs.entries)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << de.method_general_decription << ENDL << ENDL;;
|
||||
|
||||
ss << "URL: ```http:://127.0.0.1:11211" << de.uri << "```" << ENDL;
|
||||
|
||||
ss << "### Request: " << ENDL << "```json" << ENDL << de.request_json_example << ENDL << "```" << ENDL;
|
||||
ss << "### Request description: " << ENDL << "```" << ENDL << de.request_json_descriptions << ENDL << "```" << ENDL;
|
||||
ss << "### Response: " << ENDL << "```json" << ENDL << de.response_json_example << ENDL << "```" << ENDL;
|
||||
ss << "### Response description: " << ENDL << "```" << ENDL << de.response_json_descriptions << ENDL << "```" << ENDL;
|
||||
|
||||
std::string filename = de.json_method_name;
|
||||
if (!filename.size())
|
||||
{
|
||||
filename = de.uri;
|
||||
if (filename.front() == '/')
|
||||
filename.erase(filename.begin());
|
||||
}
|
||||
filename += ".md";
|
||||
bool r = epee::file_io_utils::save_string_to_file(folder + "/" + filename, ss.str());
|
||||
if (!r)
|
||||
{
|
||||
LOG_ERROR("Failed to save file " << filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2019, anonimal, <anonimal@zano.org>
|
||||
// Copyright (c) 2019, anonimal, <anonimal@zano.org>
|
||||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -97,6 +97,40 @@ namespace epee
|
|||
return epee::string_encoding::base64_decode(a);
|
||||
}
|
||||
|
||||
|
||||
//basic helpers for pod-to-hex serialization
|
||||
template<class t_pod_container_type>
|
||||
std::string transform_t_pod_array_to_hex_str_array(const t_pod_container_type& a)
|
||||
{
|
||||
std::string res;
|
||||
for (const auto& item : a)
|
||||
{
|
||||
res += epee::string_tools::pod_to_hex(a) + ", ";
|
||||
}
|
||||
if (a.size())
|
||||
{
|
||||
res.erase(res.size() - 2);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
template<class t_pod_container_type>
|
||||
t_pod_container_type transform_hex_str_array_to_t_pod_array(const std::string& a)
|
||||
{
|
||||
std::vector<std::string> pod_items;
|
||||
boost::split(pod_items, a, boost::is_any_of(", ][\""));
|
||||
|
||||
t_pod_container_type res;
|
||||
for (const auto& item : pod_items)
|
||||
{
|
||||
res.resize(res.size() + 1);
|
||||
typename t_pod_container_type::value_type& pod_val = res.back();
|
||||
|
||||
if (!epee::string_tools::hex_to_pod(item, pod_val))
|
||||
throw std::runtime_error(std::string("Unable to transform \"") + item + "\" to pod type " + typeid(typename t_pod_container_type::value_type).name());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
#pragma pack(push, 1)
|
||||
template<class first_t, class second_t>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include "keyvalue_helpers.h"
|
||||
#include "keyvalue_serialization_overloads.h"
|
||||
namespace epee
|
||||
{
|
||||
{
|
||||
/************************************************************************/
|
||||
/* Serialize map declarations */
|
||||
/************************************************************************/
|
||||
|
|
@ -65,13 +65,71 @@ public: \
|
|||
static bool serialize_map(this_type& this_ref, t_storage& stg, typename t_storage::hsection hparent_section) \
|
||||
{
|
||||
|
||||
|
||||
#define KV_CAT_(a, b) a ## b
|
||||
#define KV_CAT(a, b) KV_CAT_(a, b)
|
||||
#define VARNAME(Var) KV_CAT(Var, __LINE__)
|
||||
|
||||
#define KV_MAKE_ALIAS_NAME() VARNAME(alias_tmp_name)
|
||||
#define KV_MAKE_VAR_NAME() VARNAME(val_tmp_name)
|
||||
|
||||
#define KV_SERIALIZE_N(varialble, val_name) \
|
||||
using KV_MAKE_ALIAS_NAME() [[maybe_unused]] = decltype(this_ref.varialble); \
|
||||
[[maybe_unused]] const char* KV_MAKE_VAR_NAME() = val_name;\
|
||||
epee::serialization::selector<is_store>::serialize(this_ref.varialble, stg, hparent_section, val_name);
|
||||
|
||||
//#define KV_SERIALIZE_N_DOC(varialble, val_name) \
|
||||
// using KV_MAKE_ALIAS_NAME() = decltype(this_ref.varialble); \
|
||||
// epee::serialization::selector<is_store>::serialize(this_ref.varialble, stg, hparent_section, val_name); \
|
||||
// if constexpr (t_storage::use_descriptions::value) \
|
||||
// { \
|
||||
// epee::serialization::selector<is_store>::template serialize_and_doc<KV_MAKE_ALIAS_NAME()>(stg, hparent_section, val_name
|
||||
|
||||
|
||||
#define DOC_DSCR(description) if constexpr (t_storage::use_descriptions::value) \
|
||||
{ \
|
||||
epee::serialization::selector<is_store>::template serialize_and_doc<KV_MAKE_ALIAS_NAME()>(stg, hparent_section, KV_MAKE_VAR_NAME(), description
|
||||
|
||||
|
||||
/*
|
||||
{using var_type = decltype(this_ref.varialble); \
|
||||
epee::serialization::selector<is_store>::serialize(this_ref.varialble, stg, hparent_section, val_name); \
|
||||
if constexpr (t_storage::use_descriptions::value) \
|
||||
{ \
|
||||
epee::serialization::selector<is_store>::set_descr<var_type>(stg, hparent_section, val_name, description, default = var_type()); \
|
||||
} \
|
||||
}
|
||||
*/
|
||||
|
||||
//#define DOC_DSCR(description) , description
|
||||
#define DOC_EXMP(substitute) , substitute
|
||||
//#define DOC_EXMP_AUTO_1(arg_1) , KV_MAKE_ALIAS_NAME() (arg_1)
|
||||
//#define DOC_EXMP_AUTO_2(arg_1, arg_2) , KV_MAKE_ALIAS_NAME() (arg_1, arg_2)
|
||||
#define DOC_END ); }
|
||||
#define DOC_EXMP_AUTO(...) , epee::create_t_object<KV_MAKE_ALIAS_NAME() >(__VA_ARGS__)
|
||||
|
||||
|
||||
// Function template to create an object with forwarded constructor arguments
|
||||
template<typename T, typename... Args>
|
||||
T create_t_object(Args&&... args) {
|
||||
return T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
//substitute, description);
|
||||
//#define DOC_EXAMPLE(substitute) substitute,
|
||||
//#define DOC_EX(substitute__) var_type(substitute__),
|
||||
|
||||
//#define DOC_COMMAND(command_general_description) static const char* explain_yourseflf = command_general_description;
|
||||
|
||||
|
||||
#define KV_SERIALIZE_CUSTOM_N(varialble, stored_type, from_v_to_stored, from_stored_to_v, val_name) \
|
||||
using KV_MAKE_ALIAS_NAME() [[maybe_unused]] = stored_type; \
|
||||
[[maybe_unused]] const char* VARNAME(val_tmp_name) = val_name;\
|
||||
epee::serialization::selector<is_store>::template serialize_custom<stored_type>(this_ref.varialble, stg, hparent_section, val_name, from_v_to_stored, from_stored_to_v);
|
||||
|
||||
#define KV_SERIALIZE_EPHEMERAL_N(stored_type, from_v_to_stored, val_name) \
|
||||
using KV_MAKE_ALIAS_NAME() [[maybe_unused]] = stored_type; \
|
||||
[[maybe_unused]] const char* VARNAME(val_tmp_name) = val_name;\
|
||||
epee::serialization::selector<is_store>::template serialize_ephemeral<stored_type>(this_ref, stg, hparent_section, val_name, from_v_to_stored);
|
||||
|
||||
|
||||
|
|
@ -91,20 +149,30 @@ public: \
|
|||
static_assert(std::is_pod<decltype(this_ref.varialble)>::value, "t_type must be a POD type."); \
|
||||
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name)
|
||||
|
||||
#define KV_SERIALIZE_CONTAINER_POD_AS_HEX_N(varialble, val_name) \
|
||||
KV_SERIALIZE_CUSTOM_N(varialble, std::string, epee::transform_t_pod_array_to_hex_str_array<decltype(varialble)>, epee::transform_hex_str_array_to_t_pod_array<decltype(varialble)>, val_name)
|
||||
|
||||
|
||||
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, val_name) \
|
||||
epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(this_ref.varialble, stg, hparent_section, val_name);
|
||||
|
||||
#define END_KV_SERIALIZE_MAP() return true;}
|
||||
|
||||
#define KV_SERIALIZE(varialble) KV_SERIALIZE_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_pod compile time check
|
||||
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_CUSTOM(varialble, stored_type, from_v_to_stored, from_stored_to_v) KV_SERIALIZE_CUSTOM_N(varialble, stored_type, from_v_to_stored, from_stored_to_v, #varialble)
|
||||
#define KV_SERIALIZE_POD_AS_HEX_STRING(varialble) KV_SERIALIZE_POD_AS_HEX_STRING_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_BLOB_AS_HEX_STRING(varialble) KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_BLOB_AS_BASE64_STRING(variable) KV_SERIALIZE_BLOB_AS_BASE64_STRING_N(variable, #variable)
|
||||
#define KV_SERIALIZE(varialble) KV_SERIALIZE_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_DOC(varialble) KV_SERIALIZE_N_DOC( varialble, #varialble)
|
||||
|
||||
#define DOC_COMMAND(desciption_text) inline static const char* description = desciption_text;
|
||||
|
||||
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_pod compile time check
|
||||
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_CONTAINER_POD_AS_HEX(varialble) KV_SERIALIZE_CONTAINER_POD_AS_HEX_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_CUSTOM(varialble, stored_type, from_v_to_stored, from_stored_to_v) KV_SERIALIZE_CUSTOM_N(varialble, stored_type, from_v_to_stored, from_stored_to_v, #varialble)
|
||||
#define KV_SERIALIZE_POD_AS_HEX_STRING(varialble) KV_SERIALIZE_POD_AS_HEX_STRING_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_BLOB_AS_HEX_STRING(varialble) KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_BLOB_AS_BASE64_STRING(variable) KV_SERIALIZE_BLOB_AS_BASE64_STRING_N(variable, #variable)
|
||||
|
||||
|
||||
|
||||
#define KV_CHAIN_MAP(variable_obj) epee::namespace_accessor<decltype(this_ref.variable_obj)>::template serialize_map<is_store>(this_ref.variable_obj, stg, hparent_section);
|
||||
|
|
|
|||
|
|
@ -315,9 +315,28 @@ namespace epee
|
|||
struct selector<true>
|
||||
{
|
||||
template<class t_type, class t_storage>
|
||||
static bool serialize(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname)
|
||||
static bool serialize(const t_type& d, t_storage& stg, [[maybe_unused]] typename t_storage::hsection hparent_section, [[maybe_unused]] const char* pname)
|
||||
{
|
||||
return kv_serialize(d, stg, hparent_section, pname);
|
||||
//if constexpr (!t_storage::use_descriptions::value)
|
||||
//{
|
||||
return kv_serialize(d, stg, hparent_section, pname);
|
||||
//}
|
||||
//else
|
||||
// return false;
|
||||
|
||||
}
|
||||
//const t_type& doc_substitute = t_type(), const std::string& description = std::string()
|
||||
template<class t_type, class t_storage>
|
||||
static bool serialize_and_doc(t_storage& stg, typename t_storage::hsection hparent_section, const char* pname, const std::string& description = std::string(), const t_type& doc_substitute = t_type())
|
||||
{
|
||||
if constexpr (t_storage::use_descriptions::value)
|
||||
{
|
||||
stg.set_entry_description(hparent_section, pname, description);
|
||||
return kv_serialize(doc_substitute, stg, hparent_section, pname);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
template<class t_type, class t_storage>
|
||||
|
|
@ -478,6 +497,5 @@ namespace epee
|
|||
return r;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -44,15 +44,20 @@ namespace epee
|
|||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
class portable_storage
|
||||
template<typename t_section>
|
||||
class portable_storage_base
|
||||
{
|
||||
public:
|
||||
typedef epee::serialization::hsection hsection;
|
||||
//typedef epee::serialization::hsection hsection;
|
||||
using use_descriptions = std::false_type;
|
||||
typedef t_section* hsection;
|
||||
typedef epee::serialization::harray harray;
|
||||
typedef storage_entry meta_entry;
|
||||
|
||||
portable_storage(){}
|
||||
virtual ~portable_storage(){}
|
||||
portable_storage_base
|
||||
(){}
|
||||
virtual ~portable_storage_base
|
||||
(){}
|
||||
hsection open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist = false);
|
||||
template<class t_value>
|
||||
bool get_value(const std::string& value_name, t_value& val, hsection hparent_section);
|
||||
|
|
@ -63,18 +68,18 @@ namespace epee
|
|||
//serial access for arrays of values --------------------------------------
|
||||
//values
|
||||
template<class t_value>
|
||||
harray get_first_value(const std::string& value_name, t_value& target, hsection hparent_section);
|
||||
harray get_first_value(const std::string& value_name, t_value& target, hsection hparent_section);
|
||||
template<class t_value>
|
||||
bool get_next_value(harray hval_array, t_value& target);
|
||||
template<class t_value>
|
||||
harray insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section);
|
||||
harray insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section);
|
||||
template<class t_value>
|
||||
bool insert_next_value(harray hval_array, const t_value& target);
|
||||
//sections
|
||||
harray get_first_section(const std::string& pSectionName, hsection& h_child_section, hsection hparent_section);
|
||||
bool get_next_section(harray hSecArray, hsection& h_child_section);
|
||||
harray insert_first_section(const std::string& pSectionName, hsection& hinserted_childsection, hsection hparent_section);
|
||||
bool insert_next_section(harray hSecArray, hsection& hinserted_childsection);
|
||||
harray get_first_section(const std::string& pSectionName, hsection& h_child_section, hsection hparent_section);
|
||||
bool get_next_section(harray hSecArray, hsection& h_child_section);
|
||||
harray insert_first_section(const std::string& pSectionName, hsection& hinserted_childsection, hsection hparent_section);
|
||||
bool insert_next_section(harray hSecArray, hsection& hinserted_childsection);
|
||||
//------------------------------------------------------------------------
|
||||
//delete entry (section, value or array)
|
||||
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
|
||||
|
|
@ -83,12 +88,13 @@ namespace epee
|
|||
bool load_from_binary(const binarybuffer& target);
|
||||
template<class trace_policy>
|
||||
bool dump_as_xml(std::string& targetObj, const std::string& root_name = "");
|
||||
bool dump_as_json(std::string& targetObj, size_t indent = 0, end_of_line_t eol = eol_crlf);
|
||||
bool dump_as_json(std::string& targetObj, size_t indent = 0/*, end_of_line_t eol = eol_crlf*/);
|
||||
bool load_from_json(const std::string& source);
|
||||
void set_entry_description(hsection hparent_section, const std::string& name, const std::string& description) {}
|
||||
|
||||
template<typename cb_t>
|
||||
bool enum_entries(hsection hparent_section, cb_t cb);
|
||||
private:
|
||||
protected:
|
||||
section m_root;
|
||||
hsection get_root_section() {return &m_root;}
|
||||
storage_entry* find_storage_entry(const std::string& pentry_name, hsection psection);
|
||||
|
|
@ -107,32 +113,36 @@ namespace epee
|
|||
};
|
||||
#pragma pack(pop)
|
||||
};
|
||||
inline
|
||||
bool portable_storage::dump_as_json(std::string& buff, size_t indent /* = 0 */, end_of_line_t eol /* = eol_crlf */)
|
||||
|
||||
|
||||
template<typename t_section>
|
||||
bool portable_storage_base<t_section>::dump_as_json(std::string& buff, size_t indent /* = 0 *//*, end_of_line_t eol *//* = eol_crlf */)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::stringstream ss;
|
||||
epee::serialization::dump_as_json(ss, m_root, indent, eol);
|
||||
epee::serialization::recursive_visitor<strategy_json>::dump_as_(ss, m_root, indent/*, eol*/);
|
||||
buff = ss.str();
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::dump_as_json", false)
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::dump_as_json", false)
|
||||
}
|
||||
inline
|
||||
bool portable_storage::load_from_json(const std::string& source)
|
||||
|
||||
template<typename t_section>
|
||||
bool portable_storage_base<t_section>::load_from_json(const std::string& source)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
return json::load_from_json(source, *this);
|
||||
CATCH_ENTRY("portable_storage::load_from_json", false)
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::load_from_json", false)
|
||||
}
|
||||
|
||||
template<typename t_section>
|
||||
template<class trace_policy>
|
||||
bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name)
|
||||
bool portable_storage_base<t_section>::dump_as_xml(std::string& targetObj, const std::string& root_name)
|
||||
{
|
||||
return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
|
||||
}
|
||||
|
||||
inline
|
||||
bool portable_storage::store_to_binary(binarybuffer& target)
|
||||
template<typename t_section>
|
||||
bool portable_storage_base<t_section>::store_to_binary(binarybuffer& target)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::stringstream ss;
|
||||
|
|
@ -144,10 +154,10 @@ namespace epee
|
|||
pack_entry_to_buff(ss, m_root);
|
||||
target = ss.str();
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::store_to_binary", false)
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::store_to_binary", false)
|
||||
}
|
||||
inline
|
||||
bool portable_storage::load_from_binary(const binarybuffer& source)
|
||||
template<typename t_section>
|
||||
bool portable_storage_base<t_section>::load_from_binary(const binarybuffer& source)
|
||||
{
|
||||
m_root.m_entries.clear();
|
||||
if(source.size() < sizeof(storage_block_header))
|
||||
|
|
@ -172,11 +182,11 @@ namespace epee
|
|||
throwable_buffer_reader buf_reader(source.data()+sizeof(storage_block_header), source.size()-sizeof(storage_block_header));
|
||||
buf_reader.read(m_root);
|
||||
return true;//TODO:
|
||||
CATCH_ENTRY("portable_storage::load_from_binary", false);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::load_from_binary", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist)
|
||||
template<typename t_section>
|
||||
typename portable_storage_base<t_section>::hsection portable_storage_base<t_section>::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
hparent_section = hparent_section ? hparent_section:&m_root;
|
||||
|
|
@ -197,7 +207,7 @@ namespace epee
|
|||
return nullptr;
|
||||
}
|
||||
return &boost::get<section>(*pentry);
|
||||
CATCH_ENTRY("portable_storage::open_section", nullptr);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::open_section", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<class to_type>
|
||||
|
|
@ -209,8 +219,9 @@ namespace epee
|
|||
void operator()(const from_type& v){convert_t(v, m_target);}
|
||||
};
|
||||
|
||||
template<typename t_section>
|
||||
template<class t_value>
|
||||
bool portable_storage::get_value(const std::string& value_name, t_value& val, hsection hparent_section)
|
||||
bool portable_storage_base<t_section>::get_value(const std::string& value_name, t_value& val, hsection hparent_section)
|
||||
{
|
||||
BOOST_MPL_ASSERT(( boost::mpl::contains<storage_entry::types, t_value> ));
|
||||
//TRY_ENTRY();
|
||||
|
|
@ -222,11 +233,11 @@ namespace epee
|
|||
get_value_visitor<t_value> gvv(val);
|
||||
boost::apply_visitor(gvv, *pentry);
|
||||
return true;
|
||||
//CATCH_ENTRY("portable_storage::template<>get_value", false);
|
||||
//CATCH_ENTRY("portable_storage_base<t_section>::template<>get_value", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
bool portable_storage::get_value(const std::string& value_name, storage_entry& val, hsection hparent_section)
|
||||
template<typename t_section>
|
||||
bool portable_storage_base<t_section>::get_value(const std::string& value_name, storage_entry& val, hsection hparent_section)
|
||||
{
|
||||
//TRY_ENTRY();
|
||||
if(!hparent_section) hparent_section = &m_root;
|
||||
|
|
@ -236,11 +247,12 @@ namespace epee
|
|||
|
||||
val = *pentry;
|
||||
return true;
|
||||
//CATCH_ENTRY("portable_storage::template<>get_value", false);
|
||||
//CATCH_ENTRY("portable_storage_base<t_section>::template<>get_value", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<typename t_section>
|
||||
template<class t_value>
|
||||
bool portable_storage::set_value(const std::string& value_name, const t_value& v, hsection hparent_section)
|
||||
bool portable_storage_base<t_section>::set_value(const std::string& value_name, const t_value& v, hsection hparent_section)
|
||||
{
|
||||
BOOST_MPL_ASSERT(( boost::mpl::contains<boost::mpl::push_front<storage_entry::types, storage_entry>::type, t_value> ));
|
||||
TRY_ENTRY();
|
||||
|
|
@ -256,11 +268,11 @@ namespace epee
|
|||
}
|
||||
*pentry = storage_entry(v);
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::template<>set_value", false);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::template<>set_value", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
storage_entry* portable_storage::find_storage_entry(const std::string& pentry_name, hsection psection)
|
||||
template<typename t_section>
|
||||
storage_entry* portable_storage_base<t_section>::find_storage_entry(const std::string& pentry_name, hsection psection)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
CHECK_AND_ASSERT(psection, nullptr);
|
||||
|
|
@ -269,27 +281,28 @@ namespace epee
|
|||
return nullptr;
|
||||
|
||||
return &it->second;
|
||||
CATCH_ENTRY("portable_storage::find_storage_entry", nullptr);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::find_storage_entry", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<typename t_section>
|
||||
template<class entry_type>
|
||||
storage_entry* portable_storage::insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, const entry_type& entry)
|
||||
storage_entry* portable_storage_base<t_section>::insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, const entry_type& entry)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
CHECK_AND_ASSERT(psection, nullptr);
|
||||
auto ins_res = psection->m_entries.insert(std::pair<std::string, storage_entry>(pentry_name, entry));
|
||||
return &ins_res.first->second;
|
||||
CATCH_ENTRY("portable_storage::insert_new_entry_get_storage_entry", nullptr);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::insert_new_entry_get_storage_entry", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
hsection portable_storage::insert_new_section(const std::string& pentry_name, hsection psection)
|
||||
template<typename t_section>
|
||||
typename portable_storage_base<t_section>::hsection portable_storage_base<t_section>::insert_new_section(const std::string& pentry_name, hsection psection)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
storage_entry* pse = insert_new_entry_get_storage_entry(pentry_name, psection, section());
|
||||
if(!pse) return nullptr;
|
||||
return &boost::get<section>(*pse);
|
||||
CATCH_ENTRY("portable_storage::insert_new_section", nullptr);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::insert_new_section", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<class to_type>
|
||||
|
|
@ -308,8 +321,9 @@ namespace epee
|
|||
}
|
||||
};
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<typename t_section>
|
||||
template<class t_value>
|
||||
harray portable_storage::get_first_value(const std::string& value_name, t_value& target, hsection hparent_section)
|
||||
harray portable_storage_base<t_section>::get_first_value(const std::string& value_name, t_value& target, hsection hparent_section)
|
||||
{
|
||||
BOOST_MPL_ASSERT(( boost::mpl::contains<storage_entry::types, t_value> ));
|
||||
//TRY_ENTRY();
|
||||
|
|
@ -325,7 +339,7 @@ namespace epee
|
|||
if(!boost::apply_visitor(gfv, ar_entry))
|
||||
return nullptr;
|
||||
return &ar_entry;
|
||||
//CATCH_ENTRY("portable_storage::get_first_value", nullptr);
|
||||
//CATCH_ENTRY("portable_storage_base<t_section>::get_first_value", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<class to_type>
|
||||
|
|
@ -344,10 +358,10 @@ namespace epee
|
|||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<typename t_section>
|
||||
template<class t_value>
|
||||
bool portable_storage::get_next_value(harray hval_array, t_value& target)
|
||||
bool portable_storage_base<t_section>::get_next_value(harray hval_array, t_value& target)
|
||||
{
|
||||
BOOST_MPL_ASSERT(( boost::mpl::contains<storage_entry::types, t_value> ));
|
||||
//TRY_ENTRY();
|
||||
|
|
@ -357,11 +371,12 @@ namespace epee
|
|||
if(!boost::apply_visitor(gnv, ar_entry))
|
||||
return false;
|
||||
return true;
|
||||
//CATCH_ENTRY("portable_storage::get_next_value", false);
|
||||
//CATCH_ENTRY("portable_storage_base<t_section>::get_next_value", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<typename t_section>
|
||||
template<class t_value>
|
||||
harray portable_storage::insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section)
|
||||
harray portable_storage_base<t_section>::insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if(!hparent_section) hparent_section = &m_root;
|
||||
|
|
@ -382,11 +397,12 @@ namespace epee
|
|||
array_entry_t<t_value>& arr_typed = boost::get<array_entry_t<t_value> >(arr);
|
||||
arr_typed.insert_first_val(target);
|
||||
return &arr;
|
||||
CATCH_ENTRY("portable_storage::insert_first_value", nullptr);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::insert_first_value", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<typename t_section>
|
||||
template<typename cb_t>
|
||||
bool portable_storage::enum_entries(hsection hparent_section, cb_t cb)
|
||||
bool portable_storage_base<t_section>::enum_entries(hsection hparent_section, cb_t cb)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if (!hparent_section) hparent_section = &m_root;
|
||||
|
|
@ -396,11 +412,12 @@ namespace epee
|
|||
break;
|
||||
}
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::enum_entries", false);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::enum_entries", false);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<typename t_section>
|
||||
template<class t_value>
|
||||
bool portable_storage::insert_next_value(harray hval_array, const t_value& target)
|
||||
bool portable_storage_base<t_section>::insert_next_value(harray hval_array, const t_value& target)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
CHECK_AND_ASSERT(hval_array, false);
|
||||
|
|
@ -411,12 +428,12 @@ namespace epee
|
|||
array_entry_t<t_value>& arr_typed = boost::get<array_entry_t<t_value> >(*hval_array);
|
||||
arr_typed.insert_next_value(target);
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::insert_next_value", false);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::insert_next_value", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
//sections
|
||||
inline
|
||||
harray portable_storage::get_first_section(const std::string& sec_name, hsection& h_child_section, hsection hparent_section)
|
||||
template<typename t_section>
|
||||
harray portable_storage_base<t_section>::get_first_section(const std::string& sec_name, hsection& h_child_section, hsection hparent_section)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if(!hparent_section) hparent_section = &m_root;
|
||||
|
|
@ -434,11 +451,11 @@ namespace epee
|
|||
return nullptr;
|
||||
h_child_section = psec;
|
||||
return &ar_entry;
|
||||
CATCH_ENTRY("portable_storage::get_first_section", nullptr);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::get_first_section", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
bool portable_storage::get_next_section(harray hsec_array, hsection& h_child_section)
|
||||
template<typename t_section>
|
||||
bool portable_storage_base<t_section>::get_next_section(harray hsec_array, hsection& h_child_section)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
CHECK_AND_ASSERT(hsec_array, false);
|
||||
|
|
@ -449,11 +466,11 @@ namespace epee
|
|||
if(!h_child_section)
|
||||
return false;
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::get_next_section", false);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::get_next_section", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
harray portable_storage::insert_first_section(const std::string& sec_name, hsection& hinserted_childsection, hsection hparent_section)
|
||||
template<typename t_section>
|
||||
harray portable_storage_base<t_section>::insert_first_section(const std::string& sec_name, hsection& hinserted_childsection, hsection hparent_section)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if(!hparent_section) hparent_section = &m_root;
|
||||
|
|
@ -474,11 +491,11 @@ namespace epee
|
|||
array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(ar_entry);
|
||||
hinserted_childsection = &sec_array.insert_first_val(section());
|
||||
return &ar_entry;
|
||||
CATCH_ENTRY("portable_storage::insert_first_section", nullptr);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::insert_first_section", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection)
|
||||
template<typename t_section>
|
||||
bool portable_storage_base<t_section>::insert_next_section(harray hsec_array, hsection& hinserted_childsection)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
CHECK_AND_ASSERT(hsec_array, false);
|
||||
|
|
@ -488,8 +505,9 @@ namespace epee
|
|||
array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(*hsec_array);
|
||||
hinserted_childsection = &sec_array.insert_next_value(section());
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::insert_next_section", false);
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::insert_next_section", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
typedef portable_storage_base<section> portable_storage;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ namespace epee
|
|||
/************************************************************************/
|
||||
struct section
|
||||
{
|
||||
std::map<std::string, std::string> m_descriptions;
|
||||
std::map<std::string, storage_entry> m_entries;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "portable_storage.h"
|
||||
#include "portable_storage_to_description.h"
|
||||
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
class portable_storage_extended_doc: public portable_storage
|
||||
{
|
||||
public:
|
||||
using use_descriptions = std::true_type;
|
||||
|
||||
void set_entry_description(hsection hparent_section, const std::string& name, const std::string& description)
|
||||
{
|
||||
if (!hparent_section)
|
||||
hparent_section = &m_root;
|
||||
hparent_section->m_descriptions[name] = description;
|
||||
}
|
||||
|
||||
bool dump_as_decriptions(std::string& buff, size_t indent = 0 , end_of_line_t eol = eol_crlf)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::stringstream ss;
|
||||
recursive_visitor<strategy_descriptin>::dump_as_(ss, m_root, indent);
|
||||
buff = ss.str();
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage_base<t_section>::dump_as_json", false)
|
||||
}
|
||||
|
||||
};
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
|
@ -56,16 +56,16 @@ namespace epee
|
|||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
bool store_t_to_json(const t_struct& str_in, std::string& json_buff, size_t indent = 0, end_of_line_t eol = eol_crlf)
|
||||
bool store_t_to_json(const t_struct& str_in, std::string& json_buff, size_t indent = 0)
|
||||
{
|
||||
portable_storage ps;
|
||||
str_in.store(ps);
|
||||
ps.dump_as_json(json_buff, indent, eol);
|
||||
ps.dump_as_json(json_buff, indent);
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
std::string store_t_to_json(const t_struct& str_in, size_t indent = 0, end_of_line_t eol = eol_crlf)
|
||||
std::string store_t_to_json(const t_struct& str_in, size_t indent = 0)
|
||||
{
|
||||
std::string json_buff;
|
||||
store_t_to_json(str_in, json_buff, indent);
|
||||
|
|
|
|||
149
contrib/epee/include/storages/portable_storage_to_.h
Normal file
149
contrib/epee/include/storages/portable_storage_to_.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
template <typename t_strategy_layout_strategy>
|
||||
class recursive_visitor
|
||||
{
|
||||
public:
|
||||
template<class t_stream>
|
||||
struct array_entry_store_to_json_visitor : public boost::static_visitor<void>
|
||||
{
|
||||
t_stream& m_strm;
|
||||
size_t m_indent;
|
||||
|
||||
array_entry_store_to_json_visitor(t_stream& strm, size_t indent)
|
||||
: m_strm(strm)
|
||||
, m_indent(indent)
|
||||
{}
|
||||
|
||||
template<class t_type>
|
||||
void operator()(const array_entry_t<t_type>& a)
|
||||
{
|
||||
|
||||
t_strategy_layout_strategy::handle_array_start(m_strm, m_indent);
|
||||
if (a.m_array.size())
|
||||
{
|
||||
auto last_it = --a.m_array.end();
|
||||
for (auto it = a.m_array.begin(); it != a.m_array.end(); it++)
|
||||
{
|
||||
dump_as_(m_strm, *it, m_indent);
|
||||
if (it != last_it)
|
||||
t_strategy_layout_strategy::handle_array_entry_separator(m_strm, m_indent);
|
||||
}
|
||||
}
|
||||
t_strategy_layout_strategy::handle_array_end(m_strm, m_indent);
|
||||
}
|
||||
};
|
||||
|
||||
template<class t_stream>
|
||||
struct storage_entry_store_to_json_visitor : public boost::static_visitor<void>
|
||||
{
|
||||
t_stream& m_strm;
|
||||
size_t m_indent;
|
||||
|
||||
storage_entry_store_to_json_visitor(t_stream& strm, size_t indent)
|
||||
: m_strm(strm)
|
||||
, m_indent(indent)
|
||||
{}
|
||||
|
||||
//section, array_entry
|
||||
template<class visited_type>
|
||||
void operator()(const visited_type& v)
|
||||
{
|
||||
dump_as_(m_strm, v, m_indent);
|
||||
}
|
||||
};
|
||||
|
||||
template<class t_stream>
|
||||
void static dump_as_(t_stream& strm, const array_entry& ae, size_t indent)
|
||||
{
|
||||
array_entry_store_to_json_visitor<t_stream> aesv(strm, indent);
|
||||
boost::apply_visitor(aesv, ae);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void static dump_as_(t_stream& strm, const storage_entry& se, size_t indent)
|
||||
{
|
||||
storage_entry_store_to_json_visitor<t_stream> sv(strm, indent);
|
||||
boost::apply_visitor(sv, se);
|
||||
}
|
||||
|
||||
template<class t_stream, class t_type>
|
||||
void static dump_as_(t_stream& strm, const t_type& v, size_t indent)
|
||||
{
|
||||
t_strategy_layout_strategy::handle_value(strm, v, indent);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void static dump_as_(t_stream& strm, const section& sec, size_t indent)
|
||||
{
|
||||
size_t local_indent = indent + 1;
|
||||
t_strategy_layout_strategy::handle_obj_begin(strm, indent);
|
||||
t_strategy_layout_strategy::handle_line_break(strm, indent);
|
||||
|
||||
if (sec.m_entries.size())
|
||||
{
|
||||
auto it_last = --sec.m_entries.end();
|
||||
for (auto it = sec.m_entries.begin(); it != sec.m_entries.end(); it++)
|
||||
{
|
||||
if constexpr (t_strategy_layout_strategy::use_descriptions::value)
|
||||
{
|
||||
std::string descr;
|
||||
auto it_descr = sec.m_descriptions.find(it->first);
|
||||
if (it_descr != sec.m_descriptions.end())
|
||||
descr = it_descr->second;
|
||||
|
||||
t_strategy_layout_strategy::handle_print_key(strm, it->first, descr, local_indent);
|
||||
}
|
||||
else
|
||||
{
|
||||
t_strategy_layout_strategy::handle_print_key(strm, it->first, local_indent);
|
||||
}
|
||||
|
||||
dump_as_(strm, it->second, local_indent);
|
||||
if (it_last != it)
|
||||
t_strategy_layout_strategy::handle_section_entry_separator(strm, indent);
|
||||
|
||||
t_strategy_layout_strategy::handle_line_break(strm, indent);
|
||||
}
|
||||
}
|
||||
t_strategy_layout_strategy::handle_obj_end(strm, indent);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
107
contrib/epee/include/storages/portable_storage_to_description.h
Normal file
107
contrib/epee/include/storages/portable_storage_to_description.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
// Copyright (c) 2006-2024, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "portable_storage_to_.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
class strategy_descriptin
|
||||
{
|
||||
public:
|
||||
using use_descriptions = std::true_type;
|
||||
|
||||
inline static const char* eol = get_endline(eol_crlf);
|
||||
//static const end_of_line_t eol = eol_crlf;
|
||||
|
||||
template<class t_stream, class t_type>
|
||||
static void handle_value(t_stream& strm, const t_type& v, size_t indent)
|
||||
{}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_array_start(t_stream& strm, size_t indent)
|
||||
{
|
||||
//strm << "[";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_array_end(t_stream& strm, size_t indent)
|
||||
{
|
||||
//strm << "]";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_obj_begin(t_stream& strm, size_t indent)
|
||||
{}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_obj_end(t_stream& strm, size_t indent)
|
||||
{}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_print_key(t_stream& strm, const std::string& key, const std::string& description, size_t indent)
|
||||
{
|
||||
if (description.size())
|
||||
{
|
||||
const std::string indent_str = make_indent(indent);
|
||||
strm << indent_str << "\"" << key << "\"" << ": " << description << eol;
|
||||
}
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_print_description(t_stream& strm, const std::string& description, size_t indent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_section_entry_separator(t_stream& strm, size_t indent)
|
||||
{
|
||||
//strm << ",";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_array_entry_separator(t_stream& strm, size_t indent)
|
||||
{
|
||||
//strm << ",";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_line_break(t_stream& strm, size_t indent)
|
||||
{
|
||||
//strm << eol;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -30,174 +30,121 @@
|
|||
|
||||
#include "misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "portable_storage_to_.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const std::string& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const bool& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const double& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream, class t_type>
|
||||
void dump_as_json(t_stream& strm, const t_type& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const section& sec, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
|
||||
inline const char* get_endline(end_of_line_t eol)
|
||||
{
|
||||
switch (eol)
|
||||
{
|
||||
case eol_lf: return "\n";
|
||||
case eol_cr: return "\r";
|
||||
case eol_space: return " ";
|
||||
default: return "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string make_indent(size_t indent)
|
||||
{
|
||||
return std::string(indent*2, ' ');
|
||||
return std::string(indent * 2, ' ');
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
struct array_entry_store_to_json_visitor: public boost::static_visitor<void>
|
||||
class strategy_json
|
||||
{
|
||||
t_stream& m_strm;
|
||||
size_t m_indent;
|
||||
end_of_line_t m_eol;
|
||||
public:
|
||||
using use_descriptions = std::false_type;
|
||||
|
||||
array_entry_store_to_json_visitor(t_stream& strm, size_t indent, end_of_line_t eol)
|
||||
: m_strm(strm)
|
||||
, m_indent(indent)
|
||||
, m_eol(eol)
|
||||
{}
|
||||
|
||||
template<class t_type>
|
||||
void operator()(const array_entry_t<t_type>& a)
|
||||
inline static const char* eol = get_endline(eol_crlf);
|
||||
//static const end_of_line_t eol = eol_crlf;
|
||||
template<class t_stream>
|
||||
static void handle_value(t_stream& strm, const std::string& v, size_t indent)
|
||||
{
|
||||
m_strm << "[";
|
||||
if(a.m_array.size())
|
||||
{
|
||||
auto last_it = --a.m_array.end();
|
||||
for(auto it = a.m_array.begin(); it != a.m_array.end(); it++)
|
||||
{
|
||||
dump_as_json(m_strm, *it, m_indent, m_eol);
|
||||
if(it != last_it)
|
||||
m_strm << ",";
|
||||
}
|
||||
}
|
||||
m_strm << "]";
|
||||
strm << "\"" << misc_utils::parse::transform_to_json_escape_sequence(v) << "\"";
|
||||
}
|
||||
template<class t_stream>
|
||||
static void handle_value(t_stream& strm, const int8_t& v, size_t indent)
|
||||
{
|
||||
strm << static_cast<int32_t>(v);
|
||||
}
|
||||
template<class t_stream>
|
||||
static void handle_value(t_stream& strm, const uint8_t& v, size_t indent)
|
||||
{
|
||||
strm << static_cast<int32_t>(v);
|
||||
}
|
||||
template<class t_stream>
|
||||
static void handle_value(t_stream& strm, const bool& v, size_t indent)
|
||||
{
|
||||
if (v)
|
||||
strm << "true";
|
||||
else
|
||||
strm << "false";
|
||||
}
|
||||
template<class t_stream>
|
||||
static void handle_value(t_stream& strm, const double& v, size_t indent)
|
||||
{
|
||||
boost::io::ios_flags_saver ifs(strm);
|
||||
strm.precision(8);
|
||||
strm << std::fixed << v;
|
||||
}
|
||||
template<class t_stream, class t_type>
|
||||
static void handle_value(t_stream& strm, const t_type& v, size_t indent)
|
||||
{
|
||||
strm << v;
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_array_start(t_stream& strm, size_t indent)
|
||||
{
|
||||
strm << "[";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_array_end(t_stream& strm, size_t indent)
|
||||
{
|
||||
strm << "]";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_obj_begin(t_stream& strm, size_t indent)
|
||||
{
|
||||
strm << "{";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_obj_end(t_stream& strm, size_t indent)
|
||||
{
|
||||
strm << "}";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_print_key(t_stream& strm, const std::string& key, size_t indent)
|
||||
{
|
||||
const std::string indent_str = make_indent(indent);
|
||||
strm << indent_str << "\"" << misc_utils::parse::transform_to_json_escape_sequence(key) << "\"" << ": ";
|
||||
}
|
||||
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_section_entry_separator(t_stream& strm, size_t indent)
|
||||
{
|
||||
strm << ",";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_array_entry_separator(t_stream& strm, size_t indent)
|
||||
{
|
||||
strm << ",";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
static void handle_line_break(t_stream& strm, size_t indent)
|
||||
{
|
||||
strm << eol;
|
||||
}
|
||||
};
|
||||
|
||||
template<class t_stream>
|
||||
struct storage_entry_store_to_json_visitor: public boost::static_visitor<void>
|
||||
{
|
||||
t_stream& m_strm;
|
||||
size_t m_indent;
|
||||
end_of_line_t m_eol;
|
||||
|
||||
storage_entry_store_to_json_visitor(t_stream& strm, size_t indent, end_of_line_t eol)
|
||||
: m_strm(strm)
|
||||
, m_indent(indent)
|
||||
, m_eol(eol)
|
||||
{}
|
||||
|
||||
//section, array_entry
|
||||
template<class visited_type>
|
||||
void operator()(const visited_type& v)
|
||||
{
|
||||
dump_as_json(m_strm, v, m_indent, m_eol);
|
||||
}
|
||||
};
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
array_entry_store_to_json_visitor<t_stream> aesv(strm, indent, eol);
|
||||
boost::apply_visitor(aesv, ae);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
storage_entry_store_to_json_visitor<t_stream> sv(strm, indent, eol);
|
||||
boost::apply_visitor(sv, se);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const std::string& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
strm << "\"" << misc_utils::parse::transform_to_json_escape_sequence(v) << "\"";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
strm << static_cast<int32_t>(v);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
strm << static_cast<int32_t>(v);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const bool& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
if(v)
|
||||
strm << "true";
|
||||
else
|
||||
strm << "false";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template<class t_stream, class t_type>
|
||||
void dump_as_json(t_stream& strm, const t_type& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
strm << v;
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const section& sec, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
auto put_eol = [&]() {
|
||||
switch (eol)
|
||||
{
|
||||
case eol_lf: strm << "\n"; break;
|
||||
case eol_cr: strm << "\r"; break;
|
||||
case eol_space: strm << " "; break;
|
||||
default: strm << "\r\n"; break;
|
||||
}
|
||||
};
|
||||
|
||||
size_t local_indent = indent + 1;
|
||||
strm << "{";
|
||||
put_eol();
|
||||
std::string indent_str = make_indent(local_indent);
|
||||
if(sec.m_entries.size())
|
||||
{
|
||||
auto it_last = --sec.m_entries.end();
|
||||
for(auto it = sec.m_entries.begin(); it!= sec.m_entries.end();it++)
|
||||
{
|
||||
strm << indent_str << "\"" << misc_utils::parse::transform_to_json_escape_sequence(it->first) << "\"" << ": ";
|
||||
dump_as_json(strm, it->second, local_indent, eol);
|
||||
if(it_last != it)
|
||||
strm << ",";
|
||||
put_eol();
|
||||
}
|
||||
}
|
||||
strm << make_indent(indent) << "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
contrib/jwt-cpp
Submodule
1
contrib/jwt-cpp
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 364a5572f4b46bb9f4304cb1c92acec8ddb2c620
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
cmake_minimum_required(VERSION 2.4.4)
|
||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
|
||||
|
||||
project(zlib C)
|
||||
|
|
|
|||
|
|
@ -196,10 +196,10 @@ if(BUILD_GUI)
|
|||
ENABLE_SHARED_PCH(Zano QTDAEMON)
|
||||
ENABLE_SHARED_PCH_EXECUTABLE(Zano)
|
||||
|
||||
QT5_USE_MODULES(Zano WebEngineWidgets WebChannel)
|
||||
#QT5_USE_MODULES(Zano WebEngineWidgets WebChannel)
|
||||
find_package(Qt5PrintSupport REQUIRED)
|
||||
|
||||
target_link_libraries(Zano wallet rpc currency_core crypto common zlibstatic ethash Qt5::WebEngineWidgets Qt5::PrintSupport ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
target_link_libraries(Zano wallet rpc currency_core crypto common zlibstatic ethash Qt5::WebChannel Qt5::WebEngineWidgets Qt5::PrintSupport ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(Zano rt)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace command_line
|
|||
|
||||
const arg_descriptor<bool> arg_console ( "no-console", "Disable daemon console commands" );
|
||||
const arg_descriptor<bool> arg_show_details ( "currency-details", "Display currency details" );
|
||||
const arg_descriptor<bool> arg_show_rpc_autodoc ( "show_rpc_autodoc", "Display rpc auto-generated documentation template" );
|
||||
const arg_descriptor<std::string> arg_generate_rpc_autodoc ( "generate-rpc-autodoc", "Make auto-generated RPC API documentation documents at the given path" );
|
||||
|
||||
const arg_descriptor<bool> arg_disable_upnp ( "disable-upnp", "Disable UPnP (enhances local network privacy)");
|
||||
const arg_descriptor<bool> arg_disable_ntp ( "disable-ntp", "Disable NTP, could enhance to time synchronization issue but increase network privacy, consider using disable-stop-if-time-out-of-sync with it");
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ namespace command_line
|
|||
extern const arg_descriptor<int> arg_log_level;
|
||||
extern const arg_descriptor<bool> arg_console;
|
||||
extern const arg_descriptor<bool> arg_show_details;
|
||||
extern const arg_descriptor<bool> arg_show_rpc_autodoc;
|
||||
//extern const arg_descriptor<bool> arg_show_rpc_autodoc;
|
||||
extern const arg_descriptor<bool> arg_disable_upnp;
|
||||
extern const arg_descriptor<bool> arg_disable_ntp;
|
||||
extern const arg_descriptor<bool> arg_disable_stop_if_time_out_of_sync;
|
||||
|
|
@ -233,4 +233,6 @@ namespace command_line
|
|||
extern const arg_descriptor<bool> arg_validate_predownload;
|
||||
extern const arg_descriptor<std::string> arg_predownload_link;
|
||||
extern const arg_descriptor<std::string> arg_deeplink;
|
||||
extern const arg_descriptor<std::string> arg_generate_rpc_autodoc;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#define VARIANT_SWITCH_END() } }
|
||||
|
||||
#define VARIANT_OBJ_TYPENAME local_reference_eokcmeokmeokcm.type().name()
|
||||
|
||||
/*
|
||||
|
||||
|
|
|
|||
|
|
@ -1043,7 +1043,7 @@ namespace crypto
|
|||
void zero()
|
||||
{
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_GCC_AND_CLANG_WARNING(class-memaccess)
|
||||
DISABLE_GCC_WARNING(class-memaccess)
|
||||
size_t size_bytes = sizeof(scalar_t) * size();
|
||||
memset(data(), 0, size_bytes);
|
||||
POP_GCC_WARNINGS
|
||||
|
|
@ -1202,15 +1202,6 @@ namespace crypto
|
|||
void add_point(const point_t& point)
|
||||
{
|
||||
m_elements.emplace_back(point.to_public_key());
|
||||
|
||||
// faster?
|
||||
/* static_assert(sizeof point.m_p3 == 5 * sizeof(item_t), "size missmatch");
|
||||
const item_t *p = (item_t*)&point.m_p3;
|
||||
m_elements.emplace_back(p[0]);
|
||||
m_elements.emplace_back(p[1]);
|
||||
m_elements.emplace_back(p[2]);
|
||||
m_elements.emplace_back(p[3]);
|
||||
m_elements.emplace_back(p[4]); */
|
||||
}
|
||||
|
||||
void add_pub_key(const crypto::public_key& pk)
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ namespace crypto
|
|||
}
|
||||
|
||||
// TODO: refactor with proper OOB handling
|
||||
// TODO: @#@# add domain separation
|
||||
static const point_t& get_generator(bool select_H, size_t index)
|
||||
{
|
||||
if (index >= c_bpp_mn_max)
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ using namespace currency;
|
|||
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_LAST_WORKED_VERSION 2
|
||||
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION 3 //DON'T CHANGE THIS, if you need to resync db change BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION
|
||||
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MINOR_COMPATIBILITY_VERSION 4 //mismatch here means some reinitializations
|
||||
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_MAJOR_FAILURE 5 //if not blocks should ever be added with this condition
|
||||
|
||||
|
||||
#define TARGETDATA_CACHE_SIZE DIFFICULTY_WINDOW + 10
|
||||
|
||||
|
|
@ -96,6 +98,7 @@ blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(nullptr, m
|
|||
m_db_last_worked_version(BLOCKCHAIN_STORAGE_OPTIONS_ID_LAST_WORKED_VERSION, m_db_solo_options),
|
||||
m_db_storage_major_compatibility_version(BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION, m_db_solo_options),
|
||||
m_db_storage_minor_compatibility_version(BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MINOR_COMPATIBILITY_VERSION, m_db_solo_options),
|
||||
m_db_major_failure(BLOCKCHAIN_STORAGE_OPTIONS_ID_MAJOR_FAILURE, m_db_solo_options),
|
||||
m_db_per_block_gindex_incs(m_db),
|
||||
m_tx_pool(tx_pool),
|
||||
m_is_in_checkpoint_zone(false),
|
||||
|
|
@ -297,10 +300,13 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
|
|||
m_db_addr_to_alias.set_cache_size(cache_size);
|
||||
}
|
||||
|
||||
LOG_PRINT_L0("Opened DB ver " << m_db_storage_major_compatibility_version << "." << m_db_storage_minor_compatibility_version);
|
||||
|
||||
bool need_reinit = false;
|
||||
if (m_db_blocks.size() != 0)
|
||||
{
|
||||
#ifndef TESTNET
|
||||
// MAINNET ONLY
|
||||
if ((m_db_storage_major_compatibility_version == 93 || m_db_storage_major_compatibility_version == 94) && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 95)
|
||||
{
|
||||
// migrate DB to rebuild aliases container
|
||||
|
|
@ -379,14 +385,21 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
|
|||
// 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);
|
||||
}
|
||||
|
||||
#define DB_MAJ_VERSION_FOR_PER_BLOCK_GINDEX_FIX 95
|
||||
|
||||
#else
|
||||
// TESTNET
|
||||
// TESTNET ONLY
|
||||
if (m_db_storage_major_compatibility_version == 95 && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 96)
|
||||
{
|
||||
// do not reinit TESTNET db if moving from version 95 to version 96
|
||||
LOG_PRINT_MAGENTA("DB storage does not need reinit because moving from v95 to v96", LOG_LEVEL_0);
|
||||
}
|
||||
|
||||
#define DB_MAJ_VERSION_FOR_PER_BLOCK_GINDEX_FIX 109
|
||||
|
||||
#endif
|
||||
// MAINNET and TESTNET
|
||||
else if (m_db_storage_major_compatibility_version != BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION)
|
||||
{
|
||||
need_reinit = true;
|
||||
|
|
@ -398,6 +411,46 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
|
|||
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);
|
||||
}
|
||||
|
||||
if (!need_reinit && m_db_storage_major_compatibility_version == DB_MAJ_VERSION_FOR_PER_BLOCK_GINDEX_FIX && m_db_storage_minor_compatibility_version == 1)
|
||||
{
|
||||
// such version means that DB has unpopulated container m_db_per_block_gindex_incs, fix it now
|
||||
LOG_PRINT_MAGENTA("DB version is " << DB_MAJ_VERSION_FOR_PER_BLOCK_GINDEX_FIX << ".1, migrating m_db_per_block_gindex_incs to ver. " << DB_MAJ_VERSION_FOR_PER_BLOCK_GINDEX_FIX << ".2...", LOG_LEVEL_0);
|
||||
|
||||
// temporary set db compatibility version to zero during migration in order to trigger db reinit on the next lanunch in case the process stops in the middle
|
||||
m_db.begin_transaction();
|
||||
uint64_t tmp_db_maj_version = m_db_storage_major_compatibility_version;
|
||||
m_db_storage_major_compatibility_version = 0;
|
||||
m_db.commit_transaction();
|
||||
|
||||
m_db.begin_transaction();
|
||||
std::unordered_map<uint64_t, uint32_t> gindices;
|
||||
for(size_t height = ZANO_HARDFORK_04_AFTER_HEIGHT + 1, size = m_db_blocks.size(); height < size; ++height)
|
||||
{
|
||||
auto block_ptr = m_db_blocks[height];
|
||||
gindices.clear();
|
||||
append_per_block_increments_for_tx(block_ptr->bl.miner_tx, gindices);
|
||||
for(const crypto::hash& tx_id : block_ptr->bl.tx_hashes)
|
||||
{
|
||||
auto tx_ptr = m_db_transactions.get(tx_id);
|
||||
if (!tx_ptr)
|
||||
{
|
||||
LOG_ERROR("Internal error: couldn't find a transactions with id " << tx_id << ", migration stops now and full resync is triggered in attempt to fix this.");
|
||||
need_reinit = true;
|
||||
break;
|
||||
}
|
||||
append_per_block_increments_for_tx(tx_ptr->tx, gindices);
|
||||
}
|
||||
push_block_to_per_block_increments(height, gindices);
|
||||
}
|
||||
m_db.commit_transaction();
|
||||
|
||||
// restore db maj compatibility
|
||||
m_db.begin_transaction();
|
||||
m_db_storage_major_compatibility_version = tmp_db_maj_version;
|
||||
m_db.commit_transaction();
|
||||
LOG_PRINT_MAGENTA("migration of m_db_per_block_gindex_incs completed successfully", LOG_LEVEL_0);
|
||||
}
|
||||
}
|
||||
|
||||
if (need_reinit)
|
||||
|
|
@ -452,12 +505,13 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
|
|||
set_lost_tx_unmixable();
|
||||
m_db.commit_transaction();
|
||||
|
||||
LOG_PRINT_GREEN("Blockchain initialized. (v:" << m_db_storage_major_compatibility_version << ") last block: " << m_db_blocks.size() - 1 << ENDL
|
||||
<< "genesis: " << get_block_hash(m_db_blocks[0]->bl) << ENDL
|
||||
<< "last block: " << m_db_blocks.size() - 1 << ", " << misc_utils::get_time_interval_string(timestamp_diff) << " time ago" << ENDL
|
||||
<< "current pos difficulty: " << get_next_diff_conditional(true) << ENDL
|
||||
<< "current pow difficulty: " << get_next_diff_conditional(false) << ENDL
|
||||
<< "total transactions: " << m_db_transactions.size(),
|
||||
LOG_PRINT_GREEN("Blockchain initialized, ver: " << m_db_storage_major_compatibility_version << "." << m_db_storage_minor_compatibility_version << ", last block: " << m_db_blocks.size() - 1 << ENDL
|
||||
<< " genesis: " << get_block_hash(m_db_blocks[0]->bl) << ENDL
|
||||
<< " last block: " << m_db_blocks.size() - 1 << ", " << misc_utils::get_time_interval_string(timestamp_diff) << " ago" << ENDL
|
||||
<< " current pos difficulty: " << get_next_diff_conditional(true) << ENDL
|
||||
<< " current pow difficulty: " << get_next_diff_conditional(false) << ENDL
|
||||
<< " total transactions: " << m_db_transactions.size() << ENDL
|
||||
<< " major failure: " << (m_db_major_failure ? "true" : "false"),
|
||||
LOG_LEVEL_0);
|
||||
|
||||
return true;
|
||||
|
|
@ -1131,14 +1185,9 @@ bool blockchain_storage::switch_to_alternative_blockchain(alt_chain_type& alt_ch
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
wide_difficulty_type blockchain_storage::get_next_diff_conditional(bool pos) const
|
||||
void blockchain_storage::collect_timestamps_and_c_difficulties_main(std::vector<uint64_t>& timestamps, std::vector<wide_difficulty_type>& commulative_difficulties, bool pos) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
std::vector<uint64_t> timestamps;
|
||||
std::vector<wide_difficulty_type> commulative_difficulties;
|
||||
if (!m_db_blocks.size())
|
||||
return DIFFICULTY_POW_STARTER;
|
||||
//skip genesis timestamp
|
||||
TIME_MEASURE_START_PD(target_calculating_enum_blocks);
|
||||
CRITICAL_REGION_BEGIN(m_targetdata_cache_lock);
|
||||
std::list<std::pair<wide_difficulty_type, uint64_t>>& targetdata_cache = pos ? m_pos_targetdata_cache : m_pow_targetdata_cache;
|
||||
|
|
@ -1153,11 +1202,14 @@ wide_difficulty_type blockchain_storage::get_next_diff_conditional(bool pos) con
|
|||
++count;
|
||||
}
|
||||
CRITICAL_REGION_END();
|
||||
|
||||
wide_difficulty_type& dif = pos ? m_cached_next_pos_difficulty : m_cached_next_pow_difficulty;
|
||||
TIME_MEASURE_FINISH_PD(target_calculating_enum_blocks);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
wide_difficulty_type blockchain_storage::calc_diff_at_h_from_timestamps(std::vector<uint64_t>& timestamps, std::vector<wide_difficulty_type>& commulative_difficulties, uint64_t h, bool pos) const
|
||||
{
|
||||
wide_difficulty_type dif;
|
||||
TIME_MEASURE_START_PD(target_calculating_calc);
|
||||
if (m_core_runtime_config.is_hardfork_active_for_height(1, m_db_blocks.size()))
|
||||
if (m_core_runtime_config.is_hardfork_active_for_height(1, h))
|
||||
{
|
||||
dif = next_difficulty_2(timestamps, commulative_difficulties, pos ? global_difficulty_pos_target : global_difficulty_pow_target, pos ? global_difficulty_pos_starter : global_difficulty_pow_starter);
|
||||
}
|
||||
|
|
@ -1165,22 +1217,36 @@ wide_difficulty_type blockchain_storage::get_next_diff_conditional(bool pos) con
|
|||
{
|
||||
dif = next_difficulty_1(timestamps, commulative_difficulties, pos ? global_difficulty_pos_target : global_difficulty_pow_target, pos ? global_difficulty_pos_starter : global_difficulty_pow_starter);
|
||||
}
|
||||
|
||||
|
||||
TIME_MEASURE_FINISH_PD(target_calculating_calc);
|
||||
return dif;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
wide_difficulty_type blockchain_storage::get_next_diff_conditional2(bool pos, const alt_chain_type& alt_chain, uint64_t split_height, const alt_block_extended_info& abei) const
|
||||
wide_difficulty_type blockchain_storage::get_next_diff_conditional(bool pos) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
{
|
||||
//skip genesis timestamp
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
if (!m_db_blocks.size())
|
||||
return DIFFICULTY_POW_STARTER;
|
||||
}
|
||||
|
||||
std::vector<uint64_t> timestamps;
|
||||
std::vector<wide_difficulty_type> commulative_difficulties;
|
||||
size_t count = 0;
|
||||
if (!m_db_blocks.size())
|
||||
return DIFFICULTY_POW_STARTER;
|
||||
collect_timestamps_and_c_difficulties_main(timestamps, commulative_difficulties, pos);
|
||||
|
||||
auto cb = [&](const block_extended_info& bei, bool is_main){
|
||||
|
||||
wide_difficulty_type& dif = pos ? m_cached_next_pos_difficulty : m_cached_next_pow_difficulty;
|
||||
dif = calc_diff_at_h_from_timestamps(timestamps, commulative_difficulties, m_db_blocks.size(), pos);
|
||||
|
||||
return dif;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::collect_timestamps_and_c_difficulties_alt(std::vector<uint64_t>& timestamps, std::vector<wide_difficulty_type>& commulative_difficulties, bool pos, const alt_chain_type& alt_chain, uint64_t split_height) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
size_t count = 0;
|
||||
|
||||
auto cb = [&](const block_extended_info& bei, bool is_main) {
|
||||
if (!bei.height)
|
||||
return false;
|
||||
bool is_pos_bl = is_pos_block(bei.bl);
|
||||
|
|
@ -1192,15 +1258,22 @@ wide_difficulty_type blockchain_storage::get_next_diff_conditional2(bool pos, co
|
|||
if (count >= DIFFICULTY_WINDOW)
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
};
|
||||
enum_blockchain(cb, alt_chain, split_height);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
wide_difficulty_type blockchain_storage::get_next_diff_conditional_alt(bool pos, const alt_chain_type& alt_chain, uint64_t split_height, const alt_block_extended_info& abei) const
|
||||
{
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
if (!m_db_blocks.size())
|
||||
return DIFFICULTY_POW_STARTER;
|
||||
}
|
||||
std::vector<uint64_t> timestamps;
|
||||
std::vector<wide_difficulty_type> commulative_difficulties;
|
||||
collect_timestamps_and_c_difficulties_alt(timestamps, commulative_difficulties, pos, alt_chain, split_height);
|
||||
|
||||
wide_difficulty_type diff = 0;
|
||||
if(m_core_runtime_config.is_hardfork_active_for_height(1, abei.height))
|
||||
diff = next_difficulty_2(timestamps, commulative_difficulties, pos ? global_difficulty_pos_target : global_difficulty_pow_target, pos ? global_difficulty_pos_starter : global_difficulty_pow_starter);
|
||||
else
|
||||
diff = next_difficulty_1(timestamps, commulative_difficulties, pos ? global_difficulty_pos_target : global_difficulty_pow_target, pos ? global_difficulty_pos_starter : global_difficulty_pow_starter);
|
||||
return diff;
|
||||
return calc_diff_at_h_from_timestamps(timestamps, commulative_difficulties, abei.height, pos);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
wide_difficulty_type blockchain_storage::get_cached_next_difficulty(bool pos) const
|
||||
|
|
@ -1264,8 +1337,8 @@ wide_difficulty_type blockchain_storage::get_next_difficulty_for_alternative_cha
|
|||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::prevalidate_miner_transaction(const block& b, uint64_t height, bool pos) const
|
||||
{
|
||||
CHECK_AND_ASSERT_MES((pos ? (b.miner_tx.vin.size() == 2) : (b.miner_tx.vin.size() == 1)), false, "coinbase transaction in the block has no inputs");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type");
|
||||
CHECK_AND_ASSERT_MES((pos ? (b.miner_tx.vin.size() == 2) : (b.miner_tx.vin.size() == 1)), false, "coinbase transaction in the block has incorrect inputs number: " << b.miner_tx.vin.size());
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "input #0 of the coinbase transaction in the block has the wrong type : " << b.miner_tx.vin[0].type().name());
|
||||
if(boost::get<txin_gen>(b.miner_tx.vin[0]).height != height)
|
||||
{
|
||||
LOG_PRINT_RED_L0("The miner transaction in block has invalid height: " << boost::get<txin_gen>(b.miner_tx.vin[0]).height << ", expected: " << height);
|
||||
|
|
@ -1273,13 +1346,13 @@ bool blockchain_storage::prevalidate_miner_transaction(const block& b, uint64_t
|
|||
}
|
||||
if (pos)
|
||||
{
|
||||
if (is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM)) // TODO @#@# consider moving to validate_tx_for_hardfork_specific_terms
|
||||
if (is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, height)) // TODO @#@# consider moving to validate_tx_for_hardfork_specific_terms
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(txin_zc_input), false, "coinstake tx has incorrect type of input #1: " << b.miner_tx.vin[1].type().name());
|
||||
else
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(txin_to_key), false, "coinstake tx has incorrect type of input #1: " << b.miner_tx.vin[1].type().name());
|
||||
}
|
||||
|
||||
if (m_core_runtime_config.is_hardfork_active_for_height(1, height))
|
||||
if (is_hardfork_active_for_height(ZANO_HARDFORK_01, height))
|
||||
{
|
||||
// new rules that allow different unlock time in coinbase outputs
|
||||
uint64_t max_unlock_time = 0;
|
||||
|
|
@ -1287,12 +1360,10 @@ bool blockchain_storage::prevalidate_miner_transaction(const block& b, uint64_t
|
|||
bool r = get_tx_max_min_unlock_time(b.miner_tx, max_unlock_time, min_unlock_time);
|
||||
CHECK_AND_ASSERT_MES(r && min_unlock_time >= height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW,
|
||||
false,
|
||||
"coinbase transaction has wrong min_unlock_time: " << min_unlock_time << ", expected: " << height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
"coinbase transaction has wrong min_unlock_time: " << min_unlock_time << ", expected to be greater than or equal to " << height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
//------------------------------------------------------------------
|
||||
//bool blockchain_storage::
|
||||
// pre-hard fork rules that don't allow different unlock time in coinbase outputs
|
||||
uint64_t max_unlock_time = 0;
|
||||
uint64_t min_unlock_time = 0;
|
||||
|
|
@ -1304,14 +1375,7 @@ bool blockchain_storage::prevalidate_miner_transaction(const block& b, uint64_t
|
|||
}
|
||||
|
||||
|
||||
//check outs overflow
|
||||
if(!check_outs_overflow(b.miner_tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("miner transaction have money overflow in block " << get_block_hash(b));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM)) // TODO @#@# consider moving to validate_tx_for_hardfork_specific_terms
|
||||
if (is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, height)) // TODO @#@# consider moving to validate_tx_for_hardfork_specific_terms
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.attachment.empty(), false, "coinbase transaction has attachments; attachments are not allowed for coinbase transactions.");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.proofs.size() == 3, false, "coinbase transaction has incorrect number of proofs (" << b.miner_tx.proofs.size() << "), expected 3");
|
||||
|
|
@ -1321,6 +1385,12 @@ bool blockchain_storage::prevalidate_miner_transaction(const block& b, uint64_t
|
|||
}
|
||||
else
|
||||
{
|
||||
if(!check_bare_outs_overflow(b.miner_tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("miner transaction have money overflow in block " << get_block_hash(b));
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.attachment.empty(), false, "coinbase transaction has attachments; attachments are not allowed for coinbase transactions.");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.proofs.size() == 0, false, "pre-HF4 coinbase shoudn't have non-empty proofs containter");
|
||||
}
|
||||
|
|
@ -1328,50 +1398,44 @@ bool blockchain_storage::prevalidate_miner_transaction(const block& b, uint64_t
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_miner_transaction(const block& b,
|
||||
size_t cumulative_block_size,
|
||||
uint64_t fee,
|
||||
uint64_t& base_reward,
|
||||
const boost::multiprecision::uint128_t& already_generated_coins) const
|
||||
bool blockchain_storage::calculate_block_reward_for_next_top_block(size_t next_block_cumulative_size, uint64_t& block_reward_without_fee) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
std::vector<size_t> last_blocks_sizes;
|
||||
get_last_n_blocks_sizes(last_blocks_sizes, CURRENCY_REWARD_BLOCKS_WINDOW);
|
||||
size_t blocks_size_median = misc_utils::median(last_blocks_sizes);
|
||||
if (!get_block_reward(is_pos_block(b), blocks_size_median, cumulative_block_size, already_generated_coins, base_reward, get_block_height(b)))
|
||||
{
|
||||
LOG_PRINT_L0("block size " << cumulative_block_size << " is bigger than allowed for this blockchain");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t block_reward = base_reward;
|
||||
// before HF4: add tx fee to the block reward; after HF4: burn it
|
||||
if (b.miner_tx.version < TRANSACTION_VERSION_POST_HF4)
|
||||
LOG_PRINT_MAGENTA("blocks_size_median = " << blocks_size_median, LOG_LEVEL_2);
|
||||
block_reward_without_fee = get_block_reward(get_top_block_height() + 1, blocks_size_median, next_block_cumulative_size);
|
||||
CHECK_AND_ASSERT_MES(block_reward_without_fee != 0, false, "block size " << next_block_cumulative_size << " is bigger than allowed for this blockchain, blocks_size_median: " << blocks_size_median);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_miner_transaction(const transaction& miner_tx,
|
||||
uint64_t fee,
|
||||
uint64_t block_reward_without_fee) const
|
||||
{
|
||||
uint64_t block_reward = block_reward_without_fee;
|
||||
// before HF4: add tx fee to the block reward; after HF4: burn fees, so they don't count in block_reward
|
||||
if (miner_tx.version < TRANSACTION_VERSION_POST_HF4)
|
||||
{
|
||||
block_reward += fee;
|
||||
}
|
||||
|
||||
crypto::hash tx_id_for_post_hf4_era = b.miner_tx.version > TRANSACTION_VERSION_PRE_HF4 ? get_transaction_hash(b.miner_tx) : null_hash;
|
||||
if (!check_tx_balance(b.miner_tx, tx_id_for_post_hf4_era, block_reward))
|
||||
crypto::hash tx_id_for_post_hf4_era = miner_tx.version > TRANSACTION_VERSION_PRE_HF4 ? get_transaction_hash(miner_tx) : null_hash; // used in the input context for the proofs for txs ver >= 2
|
||||
if (!check_tx_balance(miner_tx, tx_id_for_post_hf4_era, block_reward))
|
||||
{
|
||||
LOG_ERROR("coinbase transaction balance check failed. Block reward is " << print_money_brief(block_reward) << "(" << print_money(base_reward) << "+" << print_money(fee)
|
||||
<< ", blocks_size_median = " << blocks_size_median
|
||||
<< ", cumulative_block_size = " << cumulative_block_size
|
||||
<< ", fee = " << fee
|
||||
<< ", already_generated_coins = " << already_generated_coins
|
||||
<< "), tx:");
|
||||
LOG_PRINT_L0(currency::obj_to_json_str(b.miner_tx));
|
||||
LOG_ERROR("coinbase transaction balance check failed. Block reward is " << print_money_brief(block_reward) << " (" << print_money(block_reward_without_fee) << "+" << print_money(fee) << "), tx:");
|
||||
LOG_PRINT_L0(currency::obj_to_json_str(miner_tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!verify_asset_surjection_proof(b.miner_tx, tx_id_for_post_hf4_era))
|
||||
if (!verify_asset_surjection_proof(miner_tx, tx_id_for_post_hf4_era))
|
||||
{
|
||||
LOG_ERROR("asset surjection proof verification failed for miner tx");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_PRINT_MAGENTA("Mining tx verification ok, blocks_size_median = " << blocks_size_median, LOG_LEVEL_2);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -1824,7 +1888,7 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
|||
}
|
||||
|
||||
// PoW / PoS validation (heavy checks)
|
||||
wide_difficulty_type current_diff = get_next_diff_conditional2(pos_block, alt_chain, connection_height, abei);
|
||||
wide_difficulty_type current_diff = get_next_diff_conditional_alt(pos_block, alt_chain, connection_height, abei);
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(current_diff, false, bvc.m_verification_failed = true, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
|
||||
|
||||
crypto::hash proof_of_work = null_hash;
|
||||
|
|
@ -1910,7 +1974,11 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
|||
std::stringstream ss_pow_pos_info;
|
||||
if (pos_block)
|
||||
{
|
||||
ss_pow_pos_info << "PoS:\t" << abei.stake_hash << ", stake amount: " << print_money(pos_amount) << ", final_difficulty: " << pos_diff_final;
|
||||
ss_pow_pos_info << "PoS:\t" << abei.stake_hash << ", stake amount: ";
|
||||
if (abei.bl.miner_tx.version >= TRANSACTION_VERSION_POST_HF4)
|
||||
ss_pow_pos_info << "hidden";
|
||||
else
|
||||
ss_pow_pos_info << print_money_brief(pos_amount) << ", final_difficulty: " << pos_diff_final;
|
||||
proof = abei.stake_hash;
|
||||
}
|
||||
else
|
||||
|
|
@ -3728,7 +3796,6 @@ bool blockchain_storage::pop_transaction_from_global_index(const transaction& tx
|
|||
CHECK_AND_ASSERT_MES(res, false, "Internal error: multisig out not found, multisig_out_id " << multisig_out_id << "in multisig outs index");
|
||||
}
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
|
||||
// TODO: @#@# temporary comment this section and make a test for the corresponding bug
|
||||
if (!do_pop_output(i, 0))
|
||||
return false;
|
||||
VARIANT_CASE_THROW_ON_OTHER();
|
||||
|
|
@ -3806,6 +3873,30 @@ bool blockchain_storage::get_asset_info(const crypto::public_key& asset_id, asse
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
uint64_t blockchain_storage::get_assets(uint64_t offset, uint64_t count, std::list<asset_descriptor_with_id>& assets) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
assets.clear();
|
||||
m_db_assets.enumerate_items([&](uint64_t i, const crypto::public_key& asset_id, const std::list<asset_descriptor_operation>& asset_descriptor_history)
|
||||
{
|
||||
if (i < offset)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(asset_descriptor_history.size(), "asset_descriptor_history unexpectedly have 0 size");
|
||||
assets.push_back(asset_descriptor_with_id());
|
||||
static_cast<asset_descriptor_base&>(assets.back()) = asset_descriptor_history.back().descriptor;
|
||||
assets.back().asset_id = asset_id;
|
||||
if (i + count > offset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return assets.size();
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
uint64_t blockchain_storage::get_assets_count() const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
|
@ -4222,16 +4313,17 @@ bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx, cons
|
|||
bool blockchain_storage::get_outs_index_stat(outs_index_stat& outs_stat) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
outs_stat.amount_0_001 = m_db_outputs.get_item_size(COIN / 1000);
|
||||
outs_stat.amount_0_01 = m_db_outputs.get_item_size(COIN / 100);
|
||||
outs_stat.amount_0_1 = m_db_outputs.get_item_size(COIN / 10);
|
||||
outs_stat.amount_1 = m_db_outputs.get_item_size(COIN);
|
||||
outs_stat.amount_10 = m_db_outputs.get_item_size(COIN * 10);
|
||||
outs_stat.amount_100 = m_db_outputs.get_item_size(COIN * 100);
|
||||
outs_stat.amount_1000 = m_db_outputs.get_item_size(COIN * 1000);
|
||||
outs_stat.amount_10000 = m_db_outputs.get_item_size(COIN * 10000);
|
||||
outs_stat.amount_100000 = m_db_outputs.get_item_size(COIN * 100000);
|
||||
outs_stat.amount_1000000 = m_db_outputs.get_item_size(COIN * 1000000);
|
||||
outs_stat.amount_0 = m_db_outputs.get_item_size(0);
|
||||
outs_stat.amount_0_001 = m_db_outputs.get_item_size(COIN / 1000);
|
||||
outs_stat.amount_0_01 = m_db_outputs.get_item_size(COIN / 100);
|
||||
outs_stat.amount_0_1 = m_db_outputs.get_item_size(COIN / 10);
|
||||
outs_stat.amount_1 = m_db_outputs.get_item_size(COIN);
|
||||
outs_stat.amount_10 = m_db_outputs.get_item_size(COIN * 10);
|
||||
outs_stat.amount_100 = m_db_outputs.get_item_size(COIN * 100);
|
||||
outs_stat.amount_1000 = m_db_outputs.get_item_size(COIN * 1000);
|
||||
outs_stat.amount_10000 = m_db_outputs.get_item_size(COIN * 10000);
|
||||
outs_stat.amount_100000 = m_db_outputs.get_item_size(COIN * 100000);
|
||||
outs_stat.amount_1000000 = m_db_outputs.get_item_size(COIN * 1000000);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -4480,7 +4572,6 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const
|
|||
<< " (fee: " << (is_coinbase(tx) ? "0 [coinbase]" : print_money_brief(get_tx_fee(tx))) << ")");
|
||||
TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_print_log);
|
||||
|
||||
//@#@ del me
|
||||
// LOG_PRINT_L0("APPEND_TX_TIME_INNER: " << m_performance_data.tx_append_rl_wait.get_last_val()
|
||||
// << " | " << m_performance_data.tx_append_is_expired.get_last_val()
|
||||
// << " | " << m_performance_data.tx_process_extra.get_last_val()
|
||||
|
|
@ -4676,7 +4767,8 @@ bool blockchain_storage::print_tx_outputs_lookup(const crypto::hash& tx_id)const
|
|||
continue;
|
||||
usage_stat[o.amount][tx_ptr->m_global_output_indexes[i]];
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
|
||||
//@#@
|
||||
strm_tx << "[" << i << "]: " << ENDL;
|
||||
usage_stat[0][tx_ptr->m_global_output_indexes[i]];
|
||||
VARIANT_SWITCH_END();
|
||||
}
|
||||
|
||||
|
|
@ -4839,12 +4931,6 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
|
|||
}
|
||||
VARIANT_CASE_CONST(txin_htlc, in_htlc)
|
||||
{
|
||||
if (!is_hardfork_active(3)) // @#@ CZ, consider removing this to validate_tx_for_hardfork_specific_terms
|
||||
{
|
||||
LOG_ERROR("Error: Transaction with txin_htlc before hardfork 3 (before height " << m_core_runtime_config.hard_forks.get_str_height_the_hardfork_active_after(3) << ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(in_htlc.key_offsets.size(), false, "Empty in_to_key.key_offsets for input #" << sig_index << " tx: " << tx_prefix_hash);
|
||||
if (!local_check_key_image(in_htlc.k_image))
|
||||
return false;
|
||||
|
|
@ -4939,7 +5025,7 @@ struct outputs_visitor
|
|||
//check tx unlock time
|
||||
uint64_t source_out_unlock_time = get_tx_unlock_time(source_tx, out_i);
|
||||
//let coinbase sources for PoS block to have locked inputs, the outputs supposed to be locked same way, except the reward
|
||||
if (is_coinbase(validated_tx) && is_pos_miner_tx(validated_tx)) // @#@ consider changing to one call to is_pos_coinbase()
|
||||
if (is_pos_miner_tx(validated_tx))
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(source_out_unlock_time), false, "source output #" << out_i << " is locked by time, not by height, which is not allowed for PoS coinbase");
|
||||
if (source_out_unlock_time > m_source_max_unlock_time_for_pos_coinbase)
|
||||
|
|
@ -5126,9 +5212,7 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index,
|
|||
|
||||
LOC_CHK(tx.signatures.size() > in_index, "ms input index is out of signatures container bounds, signatures.size() = " << tx.signatures.size());
|
||||
|
||||
//@#@
|
||||
VARIANT_SWITCH_BEGIN(tx.signatures[in_index]);
|
||||
VARIANT_CASE_CONST(void_sig, v);
|
||||
VARIANT_CASE_CONST(NLSAG_sig, sig)
|
||||
{
|
||||
const std::vector<crypto::signature>& input_signatures = sig.s;
|
||||
|
|
@ -5173,9 +5257,9 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index,
|
|||
LOC_CHK(r, "failed to check extra signature for last out with TX_FLAG_SIGNATURE_MODE_SEPARATE");
|
||||
}
|
||||
}
|
||||
VARIANT_CASE_CONST(ZC_sig, s);
|
||||
//@#@
|
||||
//TODO: don't forget about need_to_check_extra_sign
|
||||
VARIANT_CASE_OTHER()
|
||||
LOG_ERROR("Unexpected signature type: " << VARIANT_OBJ_TYPENAME);
|
||||
return false;
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
|
||||
|
|
@ -5272,7 +5356,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
// we need a list<tx_out_zarcanum> this input is referring to
|
||||
// and make sure that all of them are good (i.e. check 1) source tx unlock time validity; 2) mixin restrictions; 3) general gindex/ref_by_id corectness)
|
||||
// and make sure that all of them are good (i.e. check: 1) source tx unlock time validity; 2) mixin restrictions; 3) general gindex/ref_by_id corectness)
|
||||
// get_output_keys_for_input_with_checks is used for that
|
||||
//
|
||||
std::vector<crypto::public_key> dummy_output_keys; // won't be used
|
||||
|
|
@ -5448,7 +5532,7 @@ std::shared_ptr<const transaction_chain_entry> blockchain_storage::find_key_imag
|
|||
{
|
||||
if (k_image == ki)
|
||||
{
|
||||
id_result = get_transaction_hash(tx_chain_entry->tx); // ??? @#@# why not just use tx_id ?
|
||||
id_result = tx_id;
|
||||
return tx_chain_entry;
|
||||
}
|
||||
}
|
||||
|
|
@ -5690,6 +5774,12 @@ void blockchain_storage::get_pos_mining_estimate(uint64_t amount_coins,
|
|||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id) const
|
||||
{
|
||||
if (m_db_major_failure)
|
||||
{
|
||||
LOG_ERROR("MAJOR FAILURE: POS DIFFICULTY IS GOT TO HIGH! Contact the team immediately if you see this error in logs and watch them having panic attack.");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t block_height = m_db_blocks.size();
|
||||
return validate_tx_for_hardfork_specific_terms(tx, tx_id, block_height);
|
||||
}
|
||||
|
|
@ -5847,7 +5937,7 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const
|
||||
bool blockchain_storage::validate_pre_zarcanum_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const
|
||||
{
|
||||
uint64_t major_unlock_time = get_tx_x_detail<etc_tx_details_unlock_time>(miner_tx);
|
||||
if (major_unlock_time)
|
||||
|
|
@ -5874,7 +5964,7 @@ bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transactio
|
|||
for (uint64_t i = 0; i != miner_tx.vout.size(); i++)
|
||||
{
|
||||
uint64_t unlock_value = ut2.unlock_time_array[i];
|
||||
CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(unlock_value), false, "output #" << i << " is locked by time, not buy height, which is not allowed for PoS coinbase");
|
||||
CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(unlock_value), false, "output #" << i << " is locked by time, not by height, which is not allowed for PoS coinbase");
|
||||
if (unlock_value >= source_max_unlock_time)
|
||||
{
|
||||
VARIANT_SWITCH_BEGIN(miner_tx.vout[i]);
|
||||
|
|
@ -6051,8 +6141,8 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
uint64_t last_pow_h = get_last_x_block_height(false);
|
||||
CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")");
|
||||
//let's check that coinbase amount and unlock time
|
||||
r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b)
|
||||
r = validate_pre_zarcanum_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pre_zarcanum_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b)
|
||||
<< "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase);
|
||||
}
|
||||
else
|
||||
|
|
@ -6504,15 +6594,19 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
return false;
|
||||
}
|
||||
|
||||
boost::multiprecision::uint128_t already_generated_coins = m_db_blocks.size() ? m_db_blocks.back()->already_generated_coins:0;
|
||||
uint64_t base_reward = get_base_block_reward(is_pos_bl, already_generated_coins, height);
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
if (!calculate_block_reward_for_next_top_block(cumulative_block_size, block_reward_without_fee))
|
||||
{
|
||||
LOG_ERROR("calculate_block_reward_for_next_top_block filed");
|
||||
purge_block_data_from_blockchain(bl, tx_processed_count);
|
||||
bvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_is_in_checkpoint_zone)
|
||||
{
|
||||
// validate_miner_transaction will check balance proof and asset surjection proof
|
||||
// and, as a side effect, it MAY recalculate base_reward, consider redisign, TODO -- sowle
|
||||
TIME_MEASURE_START_PD(validate_miner_transaction_time);
|
||||
if (!validate_miner_transaction(bl, cumulative_block_size, fee_summary, base_reward, already_generated_coins)) // TODO @#@# base_reward will be calculated once again, consider refactoring
|
||||
if (!validate_miner_transaction(bl.miner_tx, fee_summary, block_reward_without_fee))
|
||||
{
|
||||
LOG_PRINT_L0("Block with id: " << id
|
||||
<< " have wrong miner transaction");
|
||||
|
|
@ -6603,6 +6697,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//etc
|
||||
boost::multiprecision::uint128_t already_generated_coins = m_db_blocks.size() ? m_db_blocks.back()->already_generated_coins : 0;
|
||||
if (already_generated_coins < burned_coins)
|
||||
{
|
||||
LOG_ERROR("Condition failed: already_generated_coins(" << already_generated_coins << ") >= burned_coins(" << burned_coins << ")");
|
||||
|
|
@ -6610,7 +6705,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
bvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
bei.already_generated_coins = already_generated_coins - burned_coins + base_reward;
|
||||
bei.already_generated_coins = already_generated_coins - burned_coins + block_reward_without_fee;
|
||||
if (bei.bl.miner_tx.version >= TRANSACTION_VERSION_POST_HF4)
|
||||
{
|
||||
bei.already_generated_coins -= fee_summary;
|
||||
|
|
@ -6665,7 +6760,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
TIME_MEASURE_FINISH_PD_MS(block_processing_time_0_ms);
|
||||
|
||||
//print result
|
||||
stringstream powpos_str_entry, timestamp_str_entry, pos_validation_str_entry;
|
||||
stringstream powpos_str_entry, timestamp_str_entry, pos_validation_str_entry, block_reward_entry;
|
||||
if (is_pos_bl)
|
||||
{ // PoS
|
||||
int64_t actual_ts = get_block_datetime(bei.bl); // signed int is intentionally used here
|
||||
|
|
@ -6687,6 +6782,10 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
powpos_str_entry << "PoW:\t" << proof_hash;
|
||||
timestamp_str_entry << ", block ts: " << bei.bl.timestamp << " (diff: " << std::showpos << ts_diff << "s)";
|
||||
}
|
||||
if(bei.bl.miner_tx.version >= TRANSACTION_VERSION_POST_HF4)
|
||||
block_reward_entry << "block reward: " << print_money_brief(block_reward_without_fee) << ", fee burnt: " << print_money_brief(fee_summary);
|
||||
else
|
||||
block_reward_entry << "block reward: " << print_money_brief(block_reward_without_fee + fee_summary) << " (" << print_money_brief(block_reward_without_fee) << " + " << print_money_brief(fee_summary) << ")";
|
||||
//explanation of this code will be provided later with public announce
|
||||
set_lost_tx_unmixable_for_height(bei.height);
|
||||
|
||||
|
|
@ -6695,8 +6794,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
<< ENDL << "id:\t" << id << timestamp_str_entry.str()
|
||||
<< ENDL << powpos_str_entry.str()
|
||||
<< ENDL << "HEIGHT " << bei.height << ", difficulty: " << current_diffic << ", cumul_diff_precise: " << bei.cumulative_diff_precise << ", cumul_diff_precise_adj: " << bei.cumulative_diff_precise_adjusted << " (+" << cumulative_diff_delta << ")"
|
||||
<< ENDL << "block reward: " << print_money_brief(base_reward + fee_summary) << " (" << print_money_brief(base_reward) << " + " << print_money_brief(fee_summary)
|
||||
<< ")" << ", coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", tx_count: " << bei.bl.tx_hashes.size()
|
||||
<< ENDL << block_reward_entry.str() << ", coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", tx_count: " << bei.bl.tx_hashes.size()
|
||||
<< ", timing: " << block_processing_time_0_ms << "ms"
|
||||
<< "(micrsec:" << block_processing_time_1
|
||||
<< "(" << target_calculating_time_2 << "(" << m_performance_data.target_calculating_enum_blocks.get_last_val() << "/" << m_performance_data.target_calculating_calc.get_last_val() << ")"
|
||||
|
|
@ -6711,6 +6809,13 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
<< range_proofs_agregated.size()
|
||||
<< ")"
|
||||
<< "))");
|
||||
if (is_pos_bl && current_diffic > m_core_runtime_config.max_pos_difficulty)
|
||||
{
|
||||
m_db_major_failure = true; //burn safety fuse
|
||||
LOG_ERROR("MAJOR FAILURE: POS DIFFICULTY IS GOT TO HIGH! Contact the team immediately if you see this error in logs and watch them having panic attack."
|
||||
<< ENDL << "Block id:" << id);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
static epee::math_helper::average<uint64_t, 30> blocks_processing_time_avg_pos, blocks_processing_time_avg_pow;
|
||||
|
|
@ -6823,6 +6928,11 @@ bool blockchain_storage::is_hardfork_active(size_t hardfork_id) const
|
|||
return m_core_runtime_config.is_hardfork_active_for_height(hardfork_id, m_db_blocks.size()); // note using m_db_blocks.size() ( == top_block_height + 1 )
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::is_hardfork_active_for_height(size_t hardfork_id, uint64_t height) const
|
||||
{
|
||||
return m_core_runtime_config.is_hardfork_active_for_height(hardfork_id, height);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::prevalidate_block(const block& bl)
|
||||
{
|
||||
|
||||
|
|
@ -6882,6 +6992,15 @@ bool blockchain_storage::add_new_block(const block& bl, block_verification_conte
|
|||
{
|
||||
try
|
||||
{
|
||||
|
||||
if (m_db_major_failure)
|
||||
{
|
||||
LOG_PRINT_RED_L0("Block processing is stoped due to MAJOR FAILURE fuse burned");
|
||||
bvc.m_added_to_main_chain = false;
|
||||
bvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db.begin_transaction();
|
||||
|
||||
//block bl = bl_;
|
||||
|
|
@ -6905,10 +7024,6 @@ bool blockchain_storage::add_new_block(const block& bl, block_verification_conte
|
|||
m_db.commit_transaction();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//check that block refers to chain tail
|
||||
|
||||
|
||||
if (!(bl.prev_id == get_top_block_id()))
|
||||
{
|
||||
|
|
@ -7358,7 +7473,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
if (!alt_chain.empty())
|
||||
{
|
||||
auto abg_it = alt_chain.back()->second.gindex_lookup_table.find(input_amount);
|
||||
if (abg_it != alt_chain.back()->second.gindex_lookup_table.end())
|
||||
if (input_amount != 0 /* <-- TODO @#@# remove this condition after ZC outs support is implemented*/ && abg_it != alt_chain.back()->second.gindex_lookup_table.end())
|
||||
{
|
||||
amount_touched_altchain = true;
|
||||
// local gindex lookup table contains last used gindex, so we can't get total number of outs
|
||||
|
|
|
|||
|
|
@ -266,8 +266,12 @@ namespace currency
|
|||
crypto::hash get_top_block_id(uint64_t& height) const;
|
||||
bool get_top_block(block& b) const;
|
||||
wide_difficulty_type get_next_diff_conditional(bool pos) const;
|
||||
wide_difficulty_type get_next_diff_conditional2(bool pos, const alt_chain_type& alt_chain, uint64_t split_height, const alt_block_extended_info& abei) const;
|
||||
wide_difficulty_type get_next_diff_conditional_alt(bool pos, const alt_chain_type& alt_chain, uint64_t split_height, const alt_block_extended_info& abei) const;
|
||||
wide_difficulty_type get_cached_next_difficulty(bool pos) const;
|
||||
wide_difficulty_type calc_diff_at_h_from_timestamps(std::vector<uint64_t>& timestamps, std::vector<wide_difficulty_type>& commulative_difficulties, uint64_t h, bool pos) const;
|
||||
void collect_timestamps_and_c_difficulties_main(std::vector<uint64_t>& timestamps, std::vector<wide_difficulty_type>& commulative_difficulties, bool pos) const;
|
||||
void collect_timestamps_and_c_difficulties_alt(std::vector<uint64_t>& timestamps, std::vector<wide_difficulty_type>& commulative_difficulties, bool pos, const alt_chain_type& alt_chain, uint64_t split_height) const;
|
||||
|
||||
|
||||
|
||||
bool create_block_template(const account_public_address& miner_address, const blobdata& ex_nonce, block& b, wide_difficulty_type& di, uint64_t& height) const;
|
||||
|
|
@ -302,6 +306,7 @@ namespace currency
|
|||
bool get_asset_history(const crypto::public_key& asset_id, std::list<asset_descriptor_operation>& result) const;
|
||||
bool get_asset_info(const crypto::public_key& asset_id, asset_descriptor_base& info)const;
|
||||
uint64_t get_assets_count() const;
|
||||
uint64_t get_assets(uint64_t offset, uint64_t count, std::list<asset_descriptor_with_id>& assets) const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
|
||||
|
|
@ -339,7 +344,8 @@ namespace currency
|
|||
uint64_t get_last_timestamps_check_window_median() const;
|
||||
uint64_t get_last_n_blocks_timestamps_median(size_t n) const;
|
||||
bool prevalidate_alias_info(const transaction& tx, const extra_alias_entry& eae);
|
||||
bool validate_miner_transaction(const block& b, size_t cumulative_block_size, uint64_t fee, uint64_t& base_reward, const boost::multiprecision::uint128_t& already_generated_coins) const;
|
||||
bool calculate_block_reward_for_next_top_block(size_t next_block_cumulative_size, uint64_t& block_reward_without_fee) const;
|
||||
bool validate_miner_transaction(const transaction& miner_tx, uint64_t fee, uint64_t block_reward_without_fee) const;
|
||||
performnce_data& get_performnce_data()const;
|
||||
bool validate_instance(const std::string& path);
|
||||
bool is_tx_expired(const transaction& tx) const;
|
||||
|
|
@ -347,6 +353,7 @@ namespace currency
|
|||
|
||||
// returns true as soon as the hardfork is active for the NEXT upcoming block (not for the top block in the blockchain storage)
|
||||
bool is_hardfork_active(size_t hardfork_id) const;
|
||||
bool is_hardfork_active_for_height(size_t hardfork_id, uint64_t height) const;
|
||||
bool fill_tx_rpc_inputs(tx_rpc_extended_info& tei, const transaction& tx) const;
|
||||
bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short = false) const;
|
||||
|
||||
|
|
@ -363,7 +370,7 @@ namespace currency
|
|||
uint64_t timestamp) const;
|
||||
bool build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0, crypto::hash* p_last_block_hash = nullptr, uint64_t* p_last_pow_block_height = nullptr) const;
|
||||
|
||||
bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const;
|
||||
bool validate_pre_zarcanum_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const;
|
||||
bool validate_pos_block(const block& b, const crypto::hash& id, bool for_altchain)const;
|
||||
bool validate_pos_block(const block& b, wide_difficulty_type basic_diff, const crypto::hash& id, bool for_altchain)const;
|
||||
bool validate_pos_block(const block& b,
|
||||
|
|
@ -548,6 +555,8 @@ namespace currency
|
|||
tools::db::solo_db_value<uint64_t, std::string, solo_options_container, true> m_db_last_worked_version;
|
||||
tools::db::solo_db_value<uint64_t, uint64_t, solo_options_container> m_db_storage_major_compatibility_version;
|
||||
tools::db::solo_db_value<uint64_t, uint64_t, solo_options_container> m_db_storage_minor_compatibility_version;
|
||||
tools::db::solo_db_value<uint64_t, bool, solo_options_container> m_db_major_failure; //safety fuse
|
||||
|
||||
outputs_container m_db_outputs;
|
||||
multisig_outs_container m_db_multisig_outs;
|
||||
aliases_container m_db_aliases;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2023 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Copyright (c) 2012-2013 The Boolberry developers
|
||||
|
|
@ -167,9 +167,9 @@ namespace currency
|
|||
uint64_t no;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(proposal_id)
|
||||
KV_SERIALIZE(yes)
|
||||
KV_SERIALIZE(no)
|
||||
KV_SERIALIZE(proposal_id) DOC_DSCR("ID of the proposal.") DOC_EXMP("ZAP999") DOC_END
|
||||
KV_SERIALIZE(yes) DOC_DSCR("Nubmer of positve votes.") DOC_EXMP(42) DOC_END
|
||||
KV_SERIALIZE(no) DOC_DSCR("Number of negative votes.") DOC_EXMP(37) DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
@ -179,8 +179,8 @@ namespace currency
|
|||
std::list<vote_on_proposal> votes;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(total_pos_blocks)
|
||||
KV_SERIALIZE(votes)
|
||||
KV_SERIALIZE(total_pos_blocks) DOC_DSCR("Number of blocks in a given range.") DOC_EXMP(87482) DOC_END
|
||||
KV_SERIALIZE(votes) DOC_DSCR("Result of votes in a given range.") DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ namespace currency
|
|||
crypto::public_key alias_validation_pubkey;
|
||||
core_time_func_t get_core_time;
|
||||
uint64_t hf4_minimum_mixins;
|
||||
wide_difficulty_type max_pos_difficulty;
|
||||
|
||||
hard_forks_descriptor hard_forks;
|
||||
|
||||
|
|
@ -129,6 +130,7 @@ namespace currency
|
|||
pc.tx_default_fee = TX_DEFAULT_FEE;
|
||||
pc.max_alt_blocks = CURRENCY_ALT_BLOCK_MAX_COUNT;
|
||||
pc.hf4_minimum_mixins = CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE;
|
||||
pc.max_pos_difficulty = wide_difficulty_type(POS_MAX_DIFFICULTY_ALLOWED);
|
||||
|
||||
// TODO: refactor the following
|
||||
pc.hard_forks.set_hardfork_height(1, ZANO_HARDFORK_01_AFTER_HEIGHT);
|
||||
|
|
|
|||
|
|
@ -589,11 +589,11 @@ namespace currency
|
|||
END_SERIALIZE()
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(service_id)
|
||||
KV_SERIALIZE(instruction)
|
||||
KV_SERIALIZE_BLOB_AS_HEX_STRING(body)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(security)
|
||||
KV_SERIALIZE(flags)
|
||||
KV_SERIALIZE(service_id) DOC_DSCR("Service ID, identificator that diferent one service from another") DOC_EXMP("C") DOC_END
|
||||
KV_SERIALIZE(instruction) DOC_DSCR("Instruction that make sence for this particular service") DOC_EXMP("K") DOC_END
|
||||
KV_SERIALIZE_BLOB_AS_HEX_STRING(body) DOC_DSCR("Hex-encoded body of the attachment") DOC_EXMP("dcfd7e055a6a3043ea3541a571a57a63e25dcc64e4a270f14fa9a58ac5dbec85dcfd7e055a6a3043ea3541a571a57a63e25dcc64e4a270f14fa9a58ac5dbec85") DOC_END
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_HEX(security) DOC_DSCR("Hex-encoded public key of the owner, optional") DOC_EXMP("d8f6e37f28a632c06b0b3466db1b9d2d1b36a580ee35edfd971dc1423bc412a5") DOC_END
|
||||
KV_SERIALIZE(flags) DOC_DSCR("Flags that help wallet to automatically process some properties of the attachment(combination of TX_SERVICE_ATTACHMENT_ENCRYPT_BODY=1, TX_SERVICE_ATTACHMENT_DEFLATE_BODY=2, TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE=4,TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF=8 )") DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
@ -732,14 +732,14 @@ namespace currency
|
|||
END_BOOST_SERIALIZATION()
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(total_max_supply)
|
||||
KV_SERIALIZE(current_supply)
|
||||
KV_SERIALIZE(decimal_point)
|
||||
KV_SERIALIZE(ticker)
|
||||
KV_SERIALIZE(full_name)
|
||||
KV_SERIALIZE(meta_info)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(owner)
|
||||
KV_SERIALIZE(hidden_supply)
|
||||
KV_SERIALIZE(total_max_supply) DOC_DSCR("Maximum possible supply for given asset, can't be changed after deployment") DOC_EXMP(1000000000000000000) DOC_END
|
||||
KV_SERIALIZE(current_supply) DOC_DSCR("Currently emitted supply for given asset") DOC_EXMP(500000000000000000) DOC_END
|
||||
KV_SERIALIZE(decimal_point) DOC_DSCR("Decimal point") DOC_EXMP(12) DOC_END
|
||||
KV_SERIALIZE(ticker) DOC_DSCR("Ticker associated with asset") DOC_EXMP("ZUSD") DOC_END
|
||||
KV_SERIALIZE(full_name) DOC_DSCR("Full name of the asset") DOC_EXMP("Zano wrapped USD") DOC_END
|
||||
KV_SERIALIZE(meta_info) DOC_DSCR("Any other information assetiaded with asset in a free form") DOC_EXMP("Stable and private") DOC_END
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(owner) DOC_DSCR("Owner's key, used to validate any operations on the asset altering, could be changed in case of transfer ownership") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
|
||||
KV_SERIALIZE(hidden_supply) DOC_DSCR("This one reserved for future use, will be documented later") DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
@ -757,7 +757,7 @@ namespace currency
|
|||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_CHAIN_BASE(asset_descriptor_base)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) DOC_DSCR("Asset ID") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@
|
|||
#define POS_MODFIFIER_INTERVAL 10
|
||||
#define POS_WALLET_MINING_SCAN_INTERVAL POS_SCAN_STEP //seconds
|
||||
#define POS_MINIMUM_COINSTAKE_AGE 10 // blocks count
|
||||
#define POS_MAX_DIFFICULTY_ALLOWED "25000000000000000000000" // maximum expected PoS difficuty (need to change it probaly in 20 years)
|
||||
|
||||
|
||||
#ifndef TESTNET
|
||||
# define BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION 57000
|
||||
|
|
@ -243,14 +245,14 @@
|
|||
#define CURRENT_BLOCK_EXTENDED_INFO_ARCHIVE_VER 1
|
||||
|
||||
#define BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION CURRENCY_FORMATION_VERSION + 11
|
||||
#define BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION 1
|
||||
#define BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION 2
|
||||
|
||||
|
||||
#define BC_OFFERS_CURRENT_OFFERS_SERVICE_ARCHIVE_VER CURRENCY_FORMATION_VERSION + BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION + 9
|
||||
#define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin"
|
||||
|
||||
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 165
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 167
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION 165
|
||||
|
||||
#define CURRENT_MEMPOOL_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+31)
|
||||
|
|
@ -265,6 +267,7 @@
|
|||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 1082577 // 2021-06-01 23:28:10
|
||||
#define ZANO_HARDFORK_04_AFTER_HEIGHT 2555000 // 2024-03-21 11:49:55
|
||||
#define ZANO_HARDFORK_05_AFTER_HEIGHT 999999999999999999
|
||||
#define ZANO_HARDFORK_04_TIMESTAMP_ACTUAL 1711021795ull // block 2555000, 2024-03-21 11:49:55 UTC
|
||||
#else
|
||||
/////// Zarcanum Testnet //////////////////////////////
|
||||
#define ZANO_HARDFORK_01_AFTER_HEIGHT 0
|
||||
|
|
@ -272,6 +275,7 @@
|
|||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 0
|
||||
#define ZANO_HARDFORK_04_AFTER_HEIGHT 200
|
||||
#define ZANO_HARDFORK_05_AFTER_HEIGHT 200
|
||||
#define ZANO_HARDFORK_04_TIMESTAMP_ACTUAL 1712785801ull // block 200, 2024-04-10 21:50:01 UTC
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -261,6 +261,34 @@ namespace currency
|
|||
return diff;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool add_random_derivation_hints_and_put_them_to_tx(uint8_t tx_flags, const std::set<uint16_t>& existing_derivation_hints, std::set<uint16_t>& new_derivation_hints, transaction& tx)
|
||||
{
|
||||
if (existing_derivation_hints.size() > tx.vout.size())
|
||||
{
|
||||
if (tx.version < TRANSACTION_VERSION_POST_HF4 && (tx_flags & TX_FLAG_SIGNATURE_MODE_SEPARATE)) // for pre-HF4 consolidated txs just skip if all hints are already added
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t hints_to_be_added = tx.vout.size() - existing_derivation_hints.size();
|
||||
|
||||
size_t attempts_cnt = 0, attempts_max = 4096;
|
||||
while(new_derivation_hints.size() < hints_to_be_added && ++attempts_cnt < attempts_max)
|
||||
{
|
||||
uint16_t hint = crypto::rand<uint16_t>();
|
||||
if (existing_derivation_hints.count(hint) == 0)
|
||||
new_derivation_hints.insert(hint);
|
||||
}
|
||||
|
||||
if (attempts_cnt == attempts_max)
|
||||
return false;
|
||||
|
||||
for(auto& el : new_derivation_hints) // iterating in sorted sequence
|
||||
tx.extra.push_back(make_tx_derivation_hint_from_uint16(el));
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool generate_tx_balance_proof(const transaction &tx, const crypto::hash& tx_id, const tx_generation_context& ogc, uint64_t block_reward_for_miner_tx, currency::zc_balance_proof& proof)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(tx.version > TRANSACTION_VERSION_PRE_HF4, false, "unsupported tx.version: " << tx.version);
|
||||
|
|
@ -488,12 +516,12 @@ namespace currency
|
|||
// fill outputs
|
||||
tx_gen_context.resize(zc_ins_count, destinations.size()); // auxiliary data for each output
|
||||
uint64_t output_index = 0;
|
||||
std::set<uint16_t> deriv_cache;
|
||||
std::set<uint16_t> derivation_hints;
|
||||
for (auto& d : destinations)
|
||||
{
|
||||
finalized_tx result = AUTO_VAL_INIT(result);
|
||||
uint8_t tx_outs_attr = 0;
|
||||
r = construct_tx_out(d, tx_gen_context.tx_key.sec, output_index, tx, deriv_cache, account_keys(),
|
||||
r = construct_tx_out(d, tx_gen_context.tx_key.sec, output_index, tx, derivation_hints, account_keys(),
|
||||
tx_gen_context.asset_id_blinding_masks[output_index], tx_gen_context.amount_blinding_masks[output_index],
|
||||
tx_gen_context.blinded_asset_ids[output_index], tx_gen_context.amount_commitments[output_index], result, tx_outs_attr);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx_out failed, output #" << output_index << ", amount: " << print_money_brief(d.amount));
|
||||
|
|
@ -504,6 +532,7 @@ namespace currency
|
|||
tx_gen_context.amount_commitments_sum += tx_gen_context.amount_commitments[output_index];
|
||||
++output_index;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(add_random_derivation_hints_and_put_them_to_tx(0, std::set<uint16_t>(), derivation_hints, tx), false, "add_random_derivation_hints_and_put_them_to_tx failed");
|
||||
|
||||
if (tx.attachment.size())
|
||||
add_attachments_info_to_extra(tx.extra, tx.attachment);
|
||||
|
|
@ -1117,14 +1146,13 @@ namespace currency
|
|||
return dh;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// bool get_uint16_from_tx_derivation_hint(const tx_derivation_hint& dh, uint16_t& hint)
|
||||
// {
|
||||
// tx_derivation_hint dh;
|
||||
// if (dh.msg.size() != sizeof(hint))
|
||||
// return false;
|
||||
// hint = *((uint16_t*)dh.msg.data());
|
||||
// return true;
|
||||
// }
|
||||
bool get_uint16_from_tx_derivation_hint(const tx_derivation_hint& dh, uint16_t& hint)
|
||||
{
|
||||
if (dh.msg.size() != sizeof(hint))
|
||||
return false;
|
||||
hint = *((uint16_t*)dh.msg.data());
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys)
|
||||
{
|
||||
|
|
@ -1257,11 +1285,7 @@ namespace currency
|
|||
out.mix_attr = tx_outs_attr;
|
||||
|
||||
uint16_t hint = get_derivation_hint(reinterpret_cast<crypto::key_derivation&>(derivation));
|
||||
if (deriv_cache.count(hint) == 0)
|
||||
{
|
||||
tx.extra.push_back(make_tx_derivation_hint_from_uint16(hint));
|
||||
deriv_cache.insert(hint);
|
||||
}
|
||||
deriv_cache.insert(hint); // won't be inserted if such hint already exists
|
||||
}
|
||||
|
||||
tx.vout.push_back(out);
|
||||
|
|
@ -1289,11 +1313,7 @@ namespace currency
|
|||
CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key_from_target_address");
|
||||
|
||||
uint16_t hint = get_derivation_hint(derivation);
|
||||
if (deriv_cache.count(hint) == 0)
|
||||
{
|
||||
tx.extra.push_back(make_tx_derivation_hint_from_uint16(hint));
|
||||
deriv_cache.insert(hint);
|
||||
}
|
||||
deriv_cache.insert(hint); // won't be inserted if such hint already exists
|
||||
}
|
||||
target_keys.push_back(out_eph_public_key);
|
||||
}
|
||||
|
|
@ -1318,11 +1338,7 @@ namespace currency
|
|||
htlc.pkey_refund = out_eph_public_key;
|
||||
//add derivation hint for refund address
|
||||
uint16_t hint = get_derivation_hint(derivation);
|
||||
if (deriv_cache.count(hint) == 0)
|
||||
{
|
||||
tx.extra.push_back(make_tx_derivation_hint_from_uint16(hint));
|
||||
deriv_cache.insert(hint);
|
||||
}
|
||||
deriv_cache.insert(hint); // won't be inserted if such hint already exists
|
||||
|
||||
|
||||
if (htlc_dest.htlc_hash == null_hash)
|
||||
|
|
@ -1912,7 +1928,22 @@ namespace currency
|
|||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool copy_all_derivation_hints_from_tx_to_container(transaction& tx, std::set<uint16_t>& derivation_hints)
|
||||
{
|
||||
for(auto it = tx.extra.begin(); it != tx.extra.end(); ++it)
|
||||
{
|
||||
if (it->type() == typeid(tx_derivation_hint))
|
||||
{
|
||||
uint16_t hint = 0;
|
||||
if (!get_uint16_from_tx_derivation_hint(boost::get<tx_derivation_hint>(*it), hint))
|
||||
return false;
|
||||
if (!derivation_hints.insert(hint).second)
|
||||
return false; // maybe we need to skip this?
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool construct_tx(const account_keys& sender_account_keys,
|
||||
const std::vector<tx_source_entry>& sources,
|
||||
|
|
@ -2582,14 +2613,15 @@ namespace currency
|
|||
uint64_t native_coins_output_sum = 0;
|
||||
size_t output_index = tx.vout.size(); // in case of append mode we need to start output indexing from the last one + 1
|
||||
uint64_t range_proof_start_index = 0;
|
||||
std::set<uint16_t> deriv_cache;
|
||||
std::set<uint16_t> existing_derivation_hints, new_derivation_hints;
|
||||
CHECK_AND_ASSERT_MES(copy_all_derivation_hints_from_tx_to_container(tx, existing_derivation_hints), false, "move_all_derivation_hints_from_tx_to_container failed");
|
||||
for(size_t destination_index = 0; destination_index < shuffled_dsts.size(); ++destination_index, ++output_index)
|
||||
{
|
||||
tx_destination_entry& dst_entr = shuffled_dsts[destination_index];
|
||||
if (!(flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) && all_inputs_are_obviously_native_coins && gen_context.ao_asset_id == currency::null_pkey)
|
||||
dst_entr.flags |= tx_destination_entry_flags::tdef_explicit_native_asset_id; // all inputs are obviously native coins -- all outputs must have explicit asset ids (unless there's an asset emission)
|
||||
|
||||
r = construct_tx_out(dst_entr, gen_context.tx_key.sec, output_index, tx, deriv_cache, sender_account_keys,
|
||||
r = construct_tx_out(dst_entr, gen_context.tx_key.sec, output_index, tx, new_derivation_hints, sender_account_keys,
|
||||
gen_context.asset_id_blinding_masks[output_index], gen_context.amount_blinding_masks[output_index],
|
||||
gen_context.blinded_asset_ids[output_index], gen_context.amount_commitments[output_index], result, tx_outs_attr);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct tx out");
|
||||
|
|
@ -2602,6 +2634,8 @@ namespace currency
|
|||
native_coins_output_sum += dst_entr.amount;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(add_random_derivation_hints_and_put_them_to_tx(flags, existing_derivation_hints, new_derivation_hints, tx), false, "add_random_derivation_hints_and_put_them_to_tx failed");
|
||||
|
||||
//process offers and put there offers derived keys
|
||||
uint64_t att_count = 0;
|
||||
for (auto& o : tx.attachment)
|
||||
|
|
@ -2780,6 +2814,7 @@ namespace currency
|
|||
return CURRENT_TRANSACTION_VERSION;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// TODO @#@# this function is obsolete and needs to be re-written
|
||||
uint64_t get_reward_from_miner_tx(const transaction& tx)
|
||||
{
|
||||
uint64_t income = 0;
|
||||
|
|
@ -3083,12 +3118,12 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool check_money_overflow(const transaction& tx)
|
||||
bool check_bare_money_overflow(const transaction& tx)
|
||||
{
|
||||
return check_inputs_overflow(tx) && check_outs_overflow(tx);
|
||||
return check_bare_inputs_overflow(tx) && check_bare_outs_overflow(tx);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool check_inputs_overflow(const transaction& tx)
|
||||
bool check_bare_inputs_overflow(const transaction& tx)
|
||||
{
|
||||
uint64_t money = 0;
|
||||
for(const auto& in : tx.vin)
|
||||
|
|
@ -3125,7 +3160,7 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool check_outs_overflow(const transaction& tx)
|
||||
bool check_bare_outs_overflow(const transaction& tx)
|
||||
{
|
||||
uint64_t money = 0;
|
||||
for(const auto& o : tx.vout)
|
||||
|
|
@ -4022,7 +4057,7 @@ namespace currency
|
|||
pei_rpc.miner_text_info = eud.buff;
|
||||
}
|
||||
|
||||
pei_rpc.base_reward = get_base_block_reward(is_pos_block(bei_chain.bl), bei_chain.already_generated_coins, bei_chain.height);
|
||||
pei_rpc.base_reward = get_base_block_reward(bei_chain.height);
|
||||
pei_rpc.summary_reward = get_reward_from_miner_tx(bei_chain.bl.miner_tx);
|
||||
pei_rpc.penalty = (pei_rpc.base_reward + pei_rpc.total_fee) - pei_rpc.summary_reward;
|
||||
return true;
|
||||
|
|
@ -4041,7 +4076,7 @@ namespace currency
|
|||
gindices[amount] += 1;
|
||||
}
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, o)
|
||||
//@#@
|
||||
gindices[0] += 1;
|
||||
VARIANT_SWITCH_END();
|
||||
}
|
||||
}
|
||||
|
|
@ -4075,7 +4110,7 @@ namespace currency
|
|||
return CURRENCY_MAX_BLOCK_SIZE;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
uint64_t get_base_block_reward(bool is_pos, const boost::multiprecision::uint128_t& already_generated_coins, uint64_t height)
|
||||
uint64_t get_base_block_reward(uint64_t height)
|
||||
{
|
||||
if (!height)
|
||||
return PREMINE_AMOUNT;
|
||||
|
|
@ -4083,9 +4118,18 @@ namespace currency
|
|||
return CURRENCY_BLOCK_REWARD;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// Modern version, requires only necessary arguments. Returns 0 if block is too big (current_block_size > 2 * median_block_size)
|
||||
uint64_t get_block_reward(uint64_t height, size_t median_block_size, size_t current_block_size)
|
||||
{
|
||||
uint64_t reward = 0;
|
||||
get_block_reward(/* is_pos - doesn't matter */ false, median_block_size, current_block_size, /* boost::multiprecision::uint128_t -- doesn't matter*/ boost::multiprecision::uint128_t(0), reward, height);
|
||||
return reward;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// legacy version, some arguments are unnecessary now
|
||||
bool get_block_reward(bool is_pos, size_t median_size, size_t current_block_size, const boost::multiprecision::uint128_t& already_generated_coins, uint64_t &reward, uint64_t height)
|
||||
{
|
||||
uint64_t base_reward = get_base_block_reward(is_pos, already_generated_coins, height);
|
||||
uint64_t base_reward = get_base_block_reward(height);
|
||||
|
||||
//make it soft
|
||||
if (median_size < CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE)
|
||||
|
|
|
|||
|
|
@ -414,9 +414,9 @@ namespace currency
|
|||
uint64_t get_alias_coast_from_fee(const std::string& alias, uint64_t fee_median);
|
||||
//const crypto::public_key get_offer_secure_key_by_index_from_tx(const transaction& tx, size_t index);
|
||||
|
||||
bool check_money_overflow(const transaction& tx);
|
||||
bool check_outs_overflow(const transaction& tx);
|
||||
bool check_inputs_overflow(const transaction& tx);
|
||||
bool check_bare_money_overflow(const transaction& tx);
|
||||
bool check_bare_outs_overflow(const transaction& tx);
|
||||
bool check_bare_inputs_overflow(const transaction& tx);
|
||||
uint64_t get_block_height(const transaction& coinbase);
|
||||
uint64_t get_block_height(const block& b);
|
||||
std::vector<txout_ref_v> relative_output_offsets_to_absolute(const std::vector<txout_ref_v>& off);
|
||||
|
|
@ -522,8 +522,9 @@ namespace currency
|
|||
/************************************************************************/
|
||||
size_t get_max_block_size();
|
||||
size_t get_max_tx_size();
|
||||
uint64_t get_block_reward(uint64_t height, size_t median_block_size, size_t current_block_size);
|
||||
bool get_block_reward(bool is_pos, size_t median_size, size_t current_block_size, const boost::multiprecision::uint128_t& already_generated_coins, uint64_t &reward, uint64_t height);
|
||||
uint64_t get_base_block_reward(bool is_pos, const boost::multiprecision::uint128_t& already_generated_coins, uint64_t height);
|
||||
uint64_t get_base_block_reward(uint64_t height);
|
||||
bool is_payment_id_size_ok(const payment_id_t& payment_id);
|
||||
std::string get_account_address_as_str(const account_public_address& addr);
|
||||
std::string get_account_address_and_payment_id_as_str(const account_public_address& addr, const payment_id_t& payment_id);
|
||||
|
|
@ -535,6 +536,20 @@ namespace currency
|
|||
bool is_pos_coinbase(const transaction& tx);
|
||||
bool have_attachment_service_in_container(const std::vector<attachment_v>& av, const std::string& service_id, const std::string& instruction);
|
||||
crypto::hash prepare_prefix_hash_for_sign(const transaction& tx, uint64_t in_index, const crypto::hash& tx_id);
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<typename t_assets_map>
|
||||
void assets_map_to_assets_list(std::list<currency::asset_descriptor_with_id>& assets_list, const t_assets_map& assets_map)
|
||||
{
|
||||
for (const auto& pr : assets_map)
|
||||
{
|
||||
assets_list.push_back(currency::asset_descriptor_with_id());
|
||||
assets_list.back().asset_id = pr.first;
|
||||
epee::misc_utils::cast_assign_a_to_b(assets_list.back(), static_cast<currency::asset_descriptor_base>(pr.second));
|
||||
//*static_cast<currency::asset_descriptor_base*>(&assets_list.back()) = pr.second;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class tx_out_t>
|
||||
|
|
|
|||
|
|
@ -37,21 +37,21 @@ namespace bc_services
|
|||
//-----------------
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_N(offer_type, "ot")
|
||||
KV_SERIALIZE_CUSTOM_N(amount_primary, std::string, bc_services::transform_amount_to_string, bc_services::transform_string_to_amount, "ap")
|
||||
KV_SERIALIZE_CUSTOM_N(amount_target, std::string, bc_services::transform_amount_to_string, bc_services::transform_string_to_amount, "at")
|
||||
KV_SERIALIZE_N(bonus, "b")
|
||||
KV_SERIALIZE_N(target, "t")
|
||||
KV_SERIALIZE_N(primary, "p")
|
||||
KV_SERIALIZE_N(location_country, "lco")
|
||||
KV_SERIALIZE_N(location_city, "lci")
|
||||
KV_SERIALIZE_N(contacts, "cnt")
|
||||
KV_SERIALIZE_N(comment, "com")
|
||||
KV_SERIALIZE_N(payment_types, "pt")
|
||||
KV_SERIALIZE_N(deal_option, "do")
|
||||
KV_SERIALIZE_N(category, "cat")
|
||||
KV_SERIALIZE_N(expiration_time, "et")
|
||||
KV_SERIALIZE_N(preview_url, "url")
|
||||
KV_SERIALIZE_N(offer_type, "ot") DOC_DSCR("Type of the offer: OFFER_TYPE_PRIMARY_TO_TARGET(SELL ORDER) - 0, OFFER_TYPE_TARGET_TO_PRIMARY(BUY ORDER) - 1 etc.") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE_CUSTOM_N(amount_primary, std::string, bc_services::transform_amount_to_string, bc_services::transform_string_to_amount, "ap") DOC_DSCR("Amount of the currency") DOC_EXMP("100000") DOC_END
|
||||
KV_SERIALIZE_CUSTOM_N(amount_target, std::string, bc_services::transform_amount_to_string, bc_services::transform_string_to_amount, "at") DOC_DSCR("Smount of other currency or goods") DOC_EXMP("10000000") DOC_END
|
||||
KV_SERIALIZE_N(bonus, "b") DOC_DSCR("Bonus associated with the offer") DOC_EXMP("") DOC_END
|
||||
KV_SERIALIZE_N(target, "t") DOC_DSCR("Target: currency / goods") DOC_EXMP("USDT") DOC_END
|
||||
KV_SERIALIZE_N(primary, "p") DOC_DSCR("Currency for goods") DOC_EXMP("ZANO") DOC_END
|
||||
KV_SERIALIZE_N(location_country, "lco") DOC_DSCR("Country of the offer location") DOC_EXMP("Montenegro") DOC_END
|
||||
KV_SERIALIZE_N(location_city, "lci") DOC_DSCR("City of the offer location") DOC_EXMP("Kolasin") DOC_END
|
||||
KV_SERIALIZE_N(contacts, "cnt") DOC_DSCR("Contacts related to the offer") DOC_EXMP("Ranko +38211111111") DOC_END
|
||||
KV_SERIALIZE_N(comment, "com") DOC_DSCR("Comment associated with the offer") DOC_EXMP("Dobr dan") DOC_END
|
||||
KV_SERIALIZE_N(payment_types, "pt") DOC_DSCR("Types of payment accepted for the offer") DOC_EXMP("zano") DOC_END
|
||||
KV_SERIALIZE_N(deal_option, "do") DOC_DSCR("Deal option for the offer") DOC_EXMP("full amount, by parts") DOC_END
|
||||
KV_SERIALIZE_N(category, "cat") DOC_DSCR("Category of the offer") DOC_EXMP("") DOC_END
|
||||
KV_SERIALIZE_N(expiration_time, "et") DOC_DSCR("Expiration time of the offer") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE_N(preview_url, "url") DOC_DSCR("URL for previewing the offer") DOC_EXMP("") DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
@ -69,12 +69,12 @@ namespace bc_services
|
|||
mutable bool stopped;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_hash)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_original_hash)
|
||||
KV_SERIALIZE(index_in_tx)
|
||||
KV_SERIALIZE(timestamp)
|
||||
KV_SERIALIZE(fee)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(security)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_hash) DOC_DSCR("Transaction hash represented as a hexadecimal string") DOC_EXMP("cc608f59f8080e2fbfe3c8c80eb6e6a953d47cf2d6aebd345bada3a1cab99852") DOC_END
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_original_hash) DOC_DSCR("Origin transaction hash represented as a hexadecimal string(if offer updated)") DOC_EXMP("cc608f59f8080e2fbfe3c8c80eb6e6a953d47cf2d6aebd345bada3a1cab99852") DOC_END
|
||||
KV_SERIALIZE(index_in_tx) DOC_DSCR("Index of the tx_service_attachment entrie in transaction") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE(timestamp) DOC_DSCR("Timestamp of the transaction") DOC_EXMP(1712683857) DOC_END
|
||||
KV_SERIALIZE(fee) DOC_DSCR("Fee associated with the transaction") DOC_EXMP(10000000000) DOC_END
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(security) DOC_DSCR("Onwer's public key for access control") DOC_EXMP("40fa6db923728b38962718c61b4dc3af1acaa1967479c73703e260dc3609c58d") DOC_END
|
||||
KV_CHAIN_BASE(offer_details)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
|
@ -163,32 +163,33 @@ namespace bc_services
|
|||
bool bonus;
|
||||
std::string category;
|
||||
std::string keyword;
|
||||
bool fake;
|
||||
//bool fake;
|
||||
uint64_t current_time;
|
||||
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(order_by)
|
||||
KV_SERIALIZE(reverse)
|
||||
KV_SERIALIZE(offset)
|
||||
KV_SERIALIZE(limit)
|
||||
KV_SERIALIZE(timestamp_start)
|
||||
KV_SERIALIZE(timestamp_stop)
|
||||
KV_SERIALIZE(offer_type_mask)
|
||||
KV_SERIALIZE(amount_low_limit)
|
||||
KV_SERIALIZE(amount_up_limit)
|
||||
KV_SERIALIZE_CUSTOM(rate_low_limit, std::string, bc_services::transform_double_to_string, bc_services::transform_string_to_double)
|
||||
KV_SERIALIZE_CUSTOM(rate_up_limit, std::string, bc_services::transform_double_to_string, bc_services::transform_string_to_double)
|
||||
KV_SERIALIZE(payment_types)
|
||||
KV_SERIALIZE(location_country)
|
||||
KV_SERIALIZE(location_city)
|
||||
KV_SERIALIZE(target)
|
||||
KV_SERIALIZE(primary)
|
||||
KV_SERIALIZE(bonus)
|
||||
KV_SERIALIZE(category)
|
||||
KV_SERIALIZE(keyword)
|
||||
KV_SERIALIZE(fake)
|
||||
KV_SERIALIZE(order_by) DOC_DSCR("Field to order the results by one on this: ORDER_BY_TIMESTAMP=0,ORDER_BY_AMOUNT_PRIMARY=1,ORDER_BY_AMOUNT_TARGET=2,ORDER_BY_AMOUNT_RATE=3,ORDER_BY_PAYMENT_TYPES=4,ORDER_BY_CONTACTS=5,ORDER_BY_LOCATION=6,ORDER_BY_NAME=7") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE(reverse) DOC_DSCR("Flag to indicate whether the results should be sorted in reverse order") DOC_EXMP(false) DOC_END
|
||||
KV_SERIALIZE(offset) DOC_DSCR("Offset for pagination") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE(limit) DOC_DSCR("Maximum number of results to return") DOC_EXMP(100) DOC_END
|
||||
KV_SERIALIZE(timestamp_start) DOC_DSCR("Start timestamp for filtering results") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE(timestamp_stop) DOC_DSCR("Stop timestamp for filtering results") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE(offer_type_mask) DOC_DSCR("Mask representing the types of offers to include in the results, conbination of this: OFFER_TYPE_MASK_PRIMARY_TO_TARGET 0x00000001, OFFER_TYPE_MASK_TARGET_TO_PRIMARY 0x00000002, OFFER_TYPE_MASK_GOODS_TO_PRIMARY 0x00000004, OFFER_TYPE_MASK_PRIMARY_TO_GOODS 0x00000008") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE(amount_low_limit) DOC_DSCR("Lower limit for the amount of offers") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE(amount_up_limit) DOC_DSCR("Upper limit for the amount of offers") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE_CUSTOM(rate_low_limit, std::string, bc_services::transform_double_to_string, bc_services::transform_string_to_double) DOC_DSCR("Lower limit for the rate") DOC_EXMP("0.1") DOC_END
|
||||
KV_SERIALIZE_CUSTOM(rate_up_limit, std::string, bc_services::transform_double_to_string, bc_services::transform_string_to_double) DOC_DSCR("Upper limit for the rate") DOC_EXMP("0.1") DOC_END
|
||||
KV_SERIALIZE(payment_types) DOC_DSCR("Types of payment accepted for the offers(in a free form as it is in contract)") DOC_END
|
||||
KV_SERIALIZE(location_country) DOC_DSCR("Country of the location for the offers") DOC_END
|
||||
KV_SERIALIZE(location_city) DOC_DSCR("City of the location for the offers") DOC_END
|
||||
KV_SERIALIZE(target) DOC_DSCR("Target entity of the offers") DOC_END
|
||||
KV_SERIALIZE(primary) DOC_DSCR("Primary field for the offers") DOC_END
|
||||
KV_SERIALIZE(bonus) DOC_DSCR("Bonus associated with the offers") DOC_EXMP(false) DOC_END
|
||||
KV_SERIALIZE(category) DOC_DSCR("Category of the offers") DOC_END
|
||||
KV_SERIALIZE(keyword) DOC_DSCR("Keyword for searching offers") DOC_EXMP("tubes") DOC_END
|
||||
//KV_SERIALIZE(fake) DOC_DSCR("Flag indicating whether the offer is fake") DOC_EXMP() DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2022 Zano Project
|
||||
// Copyright (c) 2022-2024 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
|
|
@ -56,7 +56,7 @@ namespace currency
|
|||
|
||||
bool found = false;
|
||||
|
||||
if (this->zarcanum /* && td.is_zc() */)
|
||||
if (this->zarcanum)
|
||||
{
|
||||
crypto::mp::uint256_t lhs;
|
||||
crypto::mp::uint512_t rhs;
|
||||
|
|
@ -70,7 +70,7 @@ namespace currency
|
|||
const boost::multiprecision::uint256_t d_mp = lhs / (crypto::c_zarcanum_z_coeff_mp * this->stake_amount) + 1;
|
||||
const boost::multiprecision::uint256_t ba = d_mp * crypto::c_zarcanum_z_coeff_mp * this->stake_amount - lhs;
|
||||
const boost::multiprecision::uint256_t l_div_z_D = this->z_l_div_z_D / crypto::c_zarcanum_z_coeff_mp;
|
||||
LOG_PRINT_GREEN("Found Zarcanum kernel: amount: " << currency::print_money_brief(this->stake_amount) << /* ", gindex: " << td.m_global_output_index << */ ENDL
|
||||
LOG_PRINT_GREEN("Found Zarcanum kernel: amount: " << currency::print_money_brief(this->stake_amount) << ENDL
|
||||
<< "difficulty: " << this->basic_diff << ENDL
|
||||
<< "kernel info: " << ENDL
|
||||
<< print_stake_kernel_info(this->sk)
|
||||
|
|
@ -78,9 +78,8 @@ namespace currency
|
|||
<< "lhs: 0x" << crypto::scalar_t(lhs).to_string_as_hex_number() << " = 0x" << std::hex << d_mp << " * 2^64 * " << this->stake_amount << " - 0x" << std::hex << ba << ENDL
|
||||
<< "rhs: 0x" << crypto::scalar_t(rhs).to_string_as_hex_number() << ENDL
|
||||
<< "d: 0x" << std::hex << d_mp << ENDL
|
||||
<< "l / floor(z * D): 0x" << std::hex << l_div_z_D
|
||||
<< "floor(l / z * D): 0x" << std::hex << l_div_z_D
|
||||
, LOG_LEVEL_0);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!check_money_overflow(tx))
|
||||
if (!check_bare_money_overflow(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx has money overflow, rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ namespace currency
|
|||
std::stringstream ss;
|
||||
ss << "\"blocks\":{" << ENDL << print_complete_block_entry_list(v.blocks) << ENDL << "}, " << ENDL;
|
||||
ss << "\"missed_ids\":" << ENDL;
|
||||
::epee::serialization::dump_as_json(ss, v.missed_ids, 2);
|
||||
::epee::serialization::recursive_visitor<::epee::serialization::strategy_json>::dump_as_(ss, v.missed_ids, 2);
|
||||
ss << ENDL << "\"current_blockchain_height\":" << v.current_blockchain_height;
|
||||
return ss.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,6 +171,11 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
|
||||
if(hshd.top_id == currency::null_hash)
|
||||
{
|
||||
LOG_PRINT_L0("wtf");
|
||||
}
|
||||
|
||||
int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_size());
|
||||
LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, (is_inital ? "Inital ":"Idle ") << "sync data returned unknown top block (" << hshd.top_id << "): " << m_core.get_top_block_height() << " -> " << hshd.current_height - 1
|
||||
<< " [" << std::abs(diff) << " blocks (" << diff / (24 * 60 * 60 / DIFFICULTY_TOTAL_TARGET ) << " days) "
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ int main(int argc, char* argv[])
|
|||
command_line::add_arg(desc_cmd_sett, command_line::arg_log_level);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_console);
|
||||
command_line::add_arg(desc_cmd_only, command_line::arg_show_details);
|
||||
command_line::add_arg(desc_cmd_only, command_line::arg_show_rpc_autodoc);
|
||||
command_line::add_arg(desc_cmd_only, command_line::arg_generate_rpc_autodoc);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_disable_stop_if_time_out_of_sync);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_disable_stop_on_low_free_space);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_enable_offers_service);
|
||||
|
|
@ -272,21 +272,15 @@ int main(int argc, char* argv[])
|
|||
if (stratum_enabled)
|
||||
stratum_server_ptr = std::make_shared<currency::stratum_server>(&ccore);
|
||||
|
||||
if (command_line::get_arg(vm, command_line::arg_show_rpc_autodoc))
|
||||
{
|
||||
LOG_PRINT_L0("Dumping RPC auto-generated documents!");
|
||||
epee::net_utils::http::http_request_info query_info;
|
||||
epee::net_utils::http::http_response_info response_info;
|
||||
epee::net_utils::connection_context_base conn_context;
|
||||
std::string generate_reference = std::string("RPC_COMMANDS_LIST:\n");
|
||||
bool call_found = false;
|
||||
rpc_server.handle_http_request_map(query_info, response_info, conn_context, call_found, generate_reference);
|
||||
std::string json_rpc_reference;
|
||||
query_info.m_URI = JSON_RPC_REFERENCE_MARKER;
|
||||
query_info.m_body = "{\"jsonrpc\": \"2.0\", \"method\": \"nonexisting_method\", \"params\": {}},";
|
||||
rpc_server.handle_http_request_map(query_info, response_info, conn_context, call_found, json_rpc_reference);
|
||||
|
||||
LOG_PRINT_L0(generate_reference << ENDL << "----------------------------------------" << ENDL << json_rpc_reference);
|
||||
|
||||
if (command_line::has_arg(vm, command_line::arg_generate_rpc_autodoc))
|
||||
{
|
||||
std::string path_to_generate = command_line::get_arg(vm, command_line::arg_generate_rpc_autodoc);
|
||||
|
||||
if (!generate_doc_as_md_files(path_to_generate, rpc_server))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool res = false;
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ QString MainWindow::get_default_user_dir(const QString& param)
|
|||
}
|
||||
|
||||
|
||||
bool MainWindow::toggle_mining()
|
||||
bool MainWindow::toggle_mining(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
m_backend.toggle_pos_mining();
|
||||
|
|
@ -238,7 +238,7 @@ QString MainWindow::get_exchange_last_top(const QString& params)
|
|||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::get_tx_pool_info()
|
||||
QString MainWindow::get_tx_pool_info(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -248,7 +248,7 @@ QString MainWindow::get_tx_pool_info()
|
|||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::request_dummy()
|
||||
QString MainWindow::request_dummy(const QString& param)
|
||||
{
|
||||
static int code_ = 0;
|
||||
TRY_ENTRY();
|
||||
|
|
@ -284,7 +284,7 @@ QString MainWindow::call_rpc(const QString& params)
|
|||
|
||||
epee::net_utils::http::http_request_info query_info = AUTO_VAL_INIT(query_info);
|
||||
epee::net_utils::http::http_response_info response_info = AUTO_VAL_INIT(response_info);
|
||||
currency::core_rpc_server::connection_context dummy_context = AUTO_VAL_INIT(dummy_context);
|
||||
currency::core_rpc_server::connection_context dummy_context(RPC_INTERNAL_UI_CONTEXT, 0, 0, true);
|
||||
|
||||
query_info.m_URI = "/json_rpc";
|
||||
query_info.m_body = params.toStdString();
|
||||
|
|
@ -301,14 +301,34 @@ QString MainWindow::call_rpc(const QString& params)
|
|||
return QString::fromStdString(response_info.m_body);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::get_default_fee()
|
||||
|
||||
QString MainWindow::call_wallet_rpc(const QString& wallet_id_str, const QString& params)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
||||
if (!m_backend.is_core_initialized())
|
||||
{
|
||||
epee::json_rpc::error_response rsp;
|
||||
rsp.jsonrpc = "2.0";
|
||||
rsp.error.code = -1;
|
||||
rsp.error.message = API_RETURN_CODE_CORE_BUSY;
|
||||
return QString::fromStdString(epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp)));
|
||||
}
|
||||
|
||||
uint64_t wallet_id = std::stoull(wallet_id_str.toStdString());
|
||||
|
||||
return QString::fromStdString(m_backend.invoke(wallet_id, params.toStdString()));
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::get_default_fee(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
return QString(std::to_string(m_backend.get_default_fee()).c_str());
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::get_options()
|
||||
QString MainWindow::get_options(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -319,7 +339,7 @@ QString MainWindow::get_options()
|
|||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
void MainWindow::tray_quit_requested()
|
||||
void MainWindow::tray_quit_requested(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_PRINT_MAGENTA("[GUI]->[HTML] tray_quit_requested", LOG_LEVEL_0);
|
||||
|
|
@ -350,10 +370,10 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
|||
}
|
||||
else
|
||||
{
|
||||
event->ignore();
|
||||
//m_quit_requested = true;
|
||||
LOG_PRINT_L0("[GUI]->[HTML] quit_requested");
|
||||
emit quit_requested("{}");
|
||||
event->ignore();
|
||||
}
|
||||
CATCH_ENTRY2(void());
|
||||
}
|
||||
|
|
@ -474,7 +494,7 @@ bool MainWindow::init(const std::string& html_path)
|
|||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
||||
void MainWindow::on_menu_show()
|
||||
void MainWindow::on_menu_show(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
qDebug() << "Context menu: show()";
|
||||
|
|
@ -546,7 +566,7 @@ void MainWindow::bool_toggle_icon(const QString& param)
|
|||
CATCH_ENTRY2(void());
|
||||
}
|
||||
|
||||
QString MainWindow::get_log_file()
|
||||
QString MainWindow::get_log_file(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::string buff;
|
||||
|
|
@ -662,7 +682,7 @@ QString MainWindow::set_clipboard(const QString& param)
|
|||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
QString MainWindow::get_clipboard()
|
||||
QString MainWindow::get_clipboard(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -671,7 +691,7 @@ QString MainWindow::get_clipboard()
|
|||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
QString MainWindow::on_request_quit()
|
||||
QString MainWindow::on_request_quit(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_PRINT_MAGENTA("[HTML]->[GUI] on_request_quit", LOG_LEVEL_0);
|
||||
|
|
@ -933,7 +953,7 @@ bool MainWindow::init_backend(int argc, char* argv[])
|
|||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
||||
QString MainWindow::is_remnotenode_mode_preconfigured()
|
||||
QString MainWindow::is_remnotenode_mode_preconfigured(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
return API_RETURN_CODE_FALSE;
|
||||
|
|
@ -997,11 +1017,11 @@ bool MainWindow::update_wallet_status(const view::wallet_status_info& wsi)
|
|||
m_wallet_states->operator [](wsi.wallet_id) = wsi.wallet_state;
|
||||
|
||||
std::string json_str_pub;
|
||||
epee::serialization::store_t_to_json(static_cast<const view::wallet_status_info_base&>(wsi), json_str_pub, 0, epee::serialization::eol_lf);
|
||||
epee::serialization::store_t_to_json(static_cast<const view::wallet_status_info_base&>(wsi), json_str_pub, 0);
|
||||
LOG_PRINT_L0(get_wallet_log_prefix(wsi.wallet_id) + "SENDING SIGNAL -> [update_wallet_status]:" << std::endl << json_str_pub);
|
||||
|
||||
std::string json_str;
|
||||
epee::serialization::store_t_to_json(wsi, json_str, 0, epee::serialization::eol_lf);
|
||||
epee::serialization::store_t_to_json(wsi, json_str, 0);
|
||||
QMetaObject::invokeMethod(this, "update_wallet_status", Qt::QueuedConnection, Q_ARG(QString, json_str.c_str()));
|
||||
return true;
|
||||
CATCH_ENTRY2(false);
|
||||
|
|
@ -1011,7 +1031,7 @@ bool MainWindow::set_options(const view::gui_options& opt)
|
|||
{
|
||||
TRY_ENTRY();
|
||||
std::string json_str;
|
||||
epee::serialization::store_t_to_json(opt, json_str, 0, epee::serialization::eol_lf);
|
||||
epee::serialization::store_t_to_json(opt, json_str, 0);
|
||||
LOG_PRINT_L0("SENDING SIGNAL -> [set_options]:" << std::endl << json_str);
|
||||
QMetaObject::invokeMethod(this, "set_options", Qt::QueuedConnection, Q_ARG(QString, json_str.c_str()));
|
||||
return true;
|
||||
|
|
@ -1022,7 +1042,7 @@ bool MainWindow::update_tor_status(const view::current_action_status& opt)
|
|||
{
|
||||
TRY_ENTRY();
|
||||
std::string json_str;
|
||||
epee::serialization::store_t_to_json(opt, json_str, 0, epee::serialization::eol_lf);
|
||||
epee::serialization::store_t_to_json(opt, json_str, 0);
|
||||
LOG_PRINT_L0("SENDING SIGNAL -> [HANDLE_CURRENT_ACTION_STATE]:" << std::endl << json_str);
|
||||
QMetaObject::invokeMethod(this, "handle_current_action_state", Qt::QueuedConnection, Q_ARG(QString, json_str.c_str()));
|
||||
return true;
|
||||
|
|
@ -1044,7 +1064,7 @@ bool MainWindow::nativeEventFilter(const QByteArray &eventType, void *message, l
|
|||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
||||
bool MainWindow::get_is_disabled_notifications()
|
||||
bool MainWindow::get_is_disabled_notifications(const QString& param)
|
||||
{
|
||||
return m_config.disable_notifications;
|
||||
}
|
||||
|
|
@ -1067,7 +1087,7 @@ bool MainWindow::update_wallets_info(const view::wallets_summary_info& wsi)
|
|||
{
|
||||
TRY_ENTRY();
|
||||
std::string json_str;
|
||||
epee::serialization::store_t_to_json(wsi, json_str, 0, epee::serialization::eol_lf);
|
||||
epee::serialization::store_t_to_json(wsi, json_str, 0);
|
||||
LOG_PRINT_L0("SENDING SIGNAL -> [update_wallets_info]"<< std::endl << json_str );
|
||||
|
||||
QMetaObject::invokeMethod(this, "update_wallets_info", Qt::QueuedConnection, Q_ARG(QString, json_str.c_str()));
|
||||
|
|
@ -1079,7 +1099,7 @@ bool MainWindow::money_transfer(const view::transfer_event_info& tei)
|
|||
{
|
||||
TRY_ENTRY();
|
||||
std::string json_str;
|
||||
epee::serialization::store_t_to_json(tei, json_str, 0, epee::serialization::eol_lf);
|
||||
epee::serialization::store_t_to_json(tei, json_str, 0);
|
||||
|
||||
LOG_PRINT_L0(get_wallet_log_prefix(tei.wallet_id) + "SENDING SIGNAL -> [money_transfer]" << std::endl << json_str);
|
||||
//this->money_transfer(json_str.c_str());
|
||||
|
|
@ -1134,7 +1154,7 @@ bool MainWindow::money_transfer_cancel(const view::transfer_event_info& tei)
|
|||
{
|
||||
TRY_ENTRY();
|
||||
std::string json_str;
|
||||
epee::serialization::store_t_to_json(tei, json_str, 0, epee::serialization::eol_lf);
|
||||
epee::serialization::store_t_to_json(tei, json_str, 0);
|
||||
|
||||
LOG_PRINT_L0(get_wallet_log_prefix(tei.wallet_id) + "SENDING SIGNAL -> [money_transfer_cancel]");
|
||||
//this->money_transfer_cancel(json_str.c_str());
|
||||
|
|
@ -1149,7 +1169,7 @@ bool MainWindow::wallet_sync_progress(const view::wallet_sync_progres_param& p)
|
|||
TRY_ENTRY();
|
||||
LOG_PRINT_L2(get_wallet_log_prefix(p.wallet_id) + "SENDING SIGNAL -> [wallet_sync_progress]" << " wallet_id: " << p.wallet_id << ": " << p.progress << "%");
|
||||
//this->wallet_sync_progress(epee::serialization::store_t_to_json(p).c_str());
|
||||
QMetaObject::invokeMethod(this, "wallet_sync_progress", Qt::QueuedConnection, Q_ARG(QString, epee::serialization::store_t_to_json(p, 0, epee::serialization::eol_lf).c_str()));
|
||||
QMetaObject::invokeMethod(this, "wallet_sync_progress", Qt::QueuedConnection, Q_ARG(QString, epee::serialization::store_t_to_json(p, 0).c_str()));
|
||||
return true;
|
||||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
|
@ -1181,21 +1201,21 @@ bool MainWindow::pos_block_found(const currency::block& block_found)
|
|||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
||||
QString MainWindow::get_version()
|
||||
QString MainWindow::get_version(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
return PROJECT_VERSION_LONG;
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::get_os_version()
|
||||
QString MainWindow::get_os_version(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
return tools::get_os_version_string().c_str();
|
||||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
QString MainWindow::get_network_type()
|
||||
QString MainWindow::get_network_type(const QString& param)
|
||||
{
|
||||
#if defined(TESTNET)
|
||||
return "testnet";
|
||||
|
|
@ -1211,7 +1231,7 @@ QString MainWindow::get_alias_coast(const QString& param)
|
|||
PREPARE_ARG_FROM_JSON(currency::struct_with_one_t_type<std::string>, lvl);
|
||||
view::get_alias_coast_response resp;
|
||||
resp.error_code = m_backend.get_alias_coast(lvl.v, resp.coast);
|
||||
return epee::serialization::store_t_to_json(resp, 0, epee::serialization::eol_lf).c_str();
|
||||
return epee::serialization::store_t_to_json(resp, 0).c_str();
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
|
|
@ -1239,7 +1259,7 @@ QString MainWindow::set_localization_strings(const QString param)
|
|||
resp.error_code = API_RETURN_CODE_OK;
|
||||
LOG_PRINT_L0("New localization set, language title: " << lr.language_title << ", strings " << lr.strings.size());
|
||||
}
|
||||
return epee::serialization::store_t_to_json(resp, 0, epee::serialization::eol_lf).c_str();
|
||||
return epee::serialization::store_t_to_json(resp, 0).c_str();
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
|
|
@ -1408,7 +1428,7 @@ void MainWindow::on_clear_events()
|
|||
}
|
||||
|
||||
|
||||
QString MainWindow::store_secure_app_data(const QString& param)
|
||||
QString MainWindow::store_secure_app_data(const QString& param, const QString& password)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -1626,7 +1646,7 @@ QString MainWindow::load_from_file(const QString& path)
|
|||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
QString MainWindow::get_app_data()
|
||||
QString MainWindow::get_app_data(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -1637,7 +1657,7 @@ QString MainWindow::get_app_data()
|
|||
}
|
||||
|
||||
|
||||
QString MainWindow::have_secure_app_data()
|
||||
QString MainWindow::have_secure_app_data(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -1655,7 +1675,7 @@ QString MainWindow::have_secure_app_data()
|
|||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::drop_secure_app_data()
|
||||
QString MainWindow::drop_secure_app_data(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -1673,7 +1693,7 @@ QString MainWindow::drop_secure_app_data()
|
|||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::get_all_aliases()
|
||||
QString MainWindow::get_all_aliases(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -1779,7 +1799,7 @@ QString MainWindow::set_enable_tor(const QString& param)
|
|||
// return MAKE_RESPONSE(ar);
|
||||
// }
|
||||
|
||||
QString MainWindow::webkit_launched_script()
|
||||
QString MainWindow::webkit_launched_script(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
m_last_update_daemon_status_json.clear();
|
||||
|
|
@ -1795,7 +1815,7 @@ QString MainWindow::show_openfile_dialog(const QString& param)
|
|||
if (!epee::serialization::load_t_from_json(ofdr, param.toStdString()))
|
||||
{
|
||||
ofdres.error_code = API_RETURN_CODE_BAD_ARG;
|
||||
return epee::serialization::store_t_to_json(ofdres, 0, epee::serialization::eol_lf).c_str();
|
||||
return epee::serialization::store_t_to_json(ofdres, 0).c_str();
|
||||
}
|
||||
|
||||
QString path = QFileDialog::getOpenFileName(this, ofdr.caption.c_str(),
|
||||
|
|
@ -1805,7 +1825,7 @@ QString MainWindow::show_openfile_dialog(const QString& param)
|
|||
if (!path.length())
|
||||
{
|
||||
ofdres.error_code = API_RETURN_CODE_CANCELED;
|
||||
return epee::serialization::store_t_to_json(ofdres, 0, epee::serialization::eol_lf).c_str();
|
||||
return epee::serialization::store_t_to_json(ofdres, 0).c_str();
|
||||
}
|
||||
|
||||
ofdres.error_code = API_RETURN_CODE_OK;
|
||||
|
|
@ -1828,7 +1848,7 @@ QString MainWindow::show_savefile_dialog(const QString& param)
|
|||
if (!path.length())
|
||||
{
|
||||
ofdres.error_code = API_RETURN_CODE_CANCELED;
|
||||
return epee::serialization::store_t_to_json(ofdres, 0, epee::serialization::eol_lf).c_str();
|
||||
return epee::serialization::store_t_to_json(ofdres, 0).c_str();
|
||||
}
|
||||
|
||||
ofdres.error_code = API_RETURN_CODE_OK;
|
||||
|
|
@ -1993,7 +2013,7 @@ QString MainWindow::get_fav_offers(const QString& param)
|
|||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::is_pos_allowed()
|
||||
QString MainWindow::is_pos_allowed(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -2265,7 +2285,7 @@ QString MainWindow::is_wallet_password_valid(const QString& param)
|
|||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::is_autostart_enabled()
|
||||
QString MainWindow::is_autostart_enabled(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
|
|
@ -2319,6 +2339,16 @@ QString MainWindow::open_url_in_browser(const QString& param)
|
|||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
QString MainWindow::setup_jwt_wallet_rpc(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
||||
m_backend.setup_wallet_rpc(param.toStdString());
|
||||
|
||||
return API_RETURN_CODE_OK;
|
||||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
QString MainWindow::is_valid_restore_wallet_text(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -106,17 +106,18 @@ public:
|
|||
QString accept_cancel_contract(const QString& param);
|
||||
|
||||
|
||||
QString get_version();
|
||||
QString get_os_version();
|
||||
QString get_network_type();
|
||||
QString on_request_quit(const QString& param);
|
||||
QString get_version(const QString& param);
|
||||
QString get_os_version(const QString& param);
|
||||
QString get_network_type(const QString& param);
|
||||
QString transfer(const QString& json_transfer_object);
|
||||
QString have_secure_app_data();
|
||||
QString drop_secure_app_data();
|
||||
QString have_secure_app_data(const QString& param);
|
||||
QString drop_secure_app_data(const QString& param);
|
||||
QString get_secure_app_data(const QString& param);
|
||||
QString store_secure_app_data(const QString& param);
|
||||
QString store_secure_app_data(const QString& param, const QString& password);
|
||||
QString set_master_password(const QString& param);
|
||||
QString check_master_password(const QString& param);
|
||||
QString get_app_data();
|
||||
QString get_app_data(const QString& param);
|
||||
QString store_app_data(const QString& param);
|
||||
QString get_default_user_dir(const QString& param);
|
||||
// QString get_all_offers(const QString& param);
|
||||
|
|
@ -126,12 +127,11 @@ public:
|
|||
QString push_update_offer(const QString& param);
|
||||
QString get_alias_info_by_address(const QString& param);
|
||||
QString get_alias_info_by_name(const QString& param);
|
||||
QString get_all_aliases();
|
||||
QString get_all_aliases(const QString& param);
|
||||
QString request_alias_registration(const QString& param);
|
||||
QString request_alias_update(const QString& param);
|
||||
QString get_alias_coast(const QString& param);
|
||||
QString validate_address(const QString& param);
|
||||
QString on_request_quit();
|
||||
QString resync_wallet(const QString& param);
|
||||
QString get_recent_transfers(const QString& param);
|
||||
QString get_mining_history(const QString& param);
|
||||
|
|
@ -141,11 +141,11 @@ public:
|
|||
QString get_log_level(const QString& param);
|
||||
QString set_enable_tor(const QString& param);
|
||||
// QString dump_all_offers();
|
||||
QString webkit_launched_script();
|
||||
QString webkit_launched_script(const QString& param);
|
||||
QString get_smart_wallet_info(const QString& param);
|
||||
QString restore_wallet(const QString& param);
|
||||
QString use_whitelisting(const QString& param);
|
||||
QString is_pos_allowed();
|
||||
QString is_pos_allowed(const QString& param);
|
||||
QString store_to_file(const QString& path, const QString& buff);
|
||||
QString load_from_file(const QString& path);
|
||||
QString is_file_exist(const QString& path);
|
||||
|
|
@ -153,7 +153,7 @@ public:
|
|||
QString backup_wallet_keys(const QString& obj);
|
||||
QString reset_wallet_password(const QString& param);
|
||||
QString is_wallet_password_valid(const QString& param);
|
||||
QString is_autostart_enabled();
|
||||
QString is_autostart_enabled(const QString& param);
|
||||
QString toggle_autostart(const QString& param);
|
||||
QString is_valid_restore_wallet_text(const QString& param);
|
||||
QString get_seed_phrase_info(const QString& param);
|
||||
|
|
@ -161,13 +161,13 @@ public:
|
|||
QString print_log(const QString& param);
|
||||
QString set_clipboard(const QString& param);
|
||||
QString set_localization_strings(const QString str);
|
||||
QString get_clipboard();
|
||||
QString get_clipboard(const QString& param);
|
||||
void message_box(const QString& msg);
|
||||
bool toggle_mining();
|
||||
bool toggle_mining(const QString& param);
|
||||
QString get_exchange_last_top(const QString& params);
|
||||
QString get_tx_pool_info();
|
||||
QString get_default_fee();
|
||||
QString get_options();
|
||||
QString get_tx_pool_info(const QString& param);
|
||||
QString get_default_fee(const QString& param);
|
||||
QString get_options(const QString& param);
|
||||
void bool_toggle_icon(const QString& param);
|
||||
QString add_custom_asset_id(const QString& param);
|
||||
QString remove_custom_asset_id(const QString& param);
|
||||
|
|
@ -177,26 +177,28 @@ public:
|
|||
QString get_ionic_swap_proposal_info(const QString& param);
|
||||
QString accept_ionic_swap_proposal(const QString& param);
|
||||
|
||||
bool get_is_disabled_notifications();
|
||||
bool get_is_disabled_notifications(const QString& param);
|
||||
bool set_is_disabled_notifications(const bool& param);
|
||||
QString export_wallet_history(const QString& param);
|
||||
QString get_log_file();
|
||||
QString get_log_file(const QString& param);
|
||||
//QString check_available_sources(const QString& param);
|
||||
QString open_url_in_browser(const QString& param);
|
||||
QString setup_jwt_wallet_rpc(const QString& param);
|
||||
|
||||
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
void tray_quit_requested();
|
||||
void on_menu_show();
|
||||
QString is_remnotenode_mode_preconfigured();
|
||||
void tray_quit_requested(const QString& param);
|
||||
void on_menu_show(const QString& param);
|
||||
QString is_remnotenode_mode_preconfigured(const QString& param);
|
||||
QString start_backend(const QString& params);
|
||||
|
||||
QString async_call(const QString& func_name, const QString& params);
|
||||
QString sync_call(const QString& func_name, const QString& params);
|
||||
|
||||
//for test purposes onlys
|
||||
QString request_dummy();
|
||||
//for test purposes only
|
||||
QString request_dummy(const QString& param);
|
||||
|
||||
QString call_rpc(const QString& params);
|
||||
QString call_wallet_rpc(const QString& wallet_id, const QString& params);
|
||||
|
||||
signals:
|
||||
void quit_requested(const QString str);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit f8e9556fbaccd49841ce91afc3c90c8e3142ac95
|
||||
Subproject commit 9be6a53f757a17403ea5798d08b577d450eb620a
|
||||
|
|
@ -176,7 +176,7 @@ namespace currency
|
|||
res.pow_sequence_factor = m_core.get_blockchain_storage().get_current_sequence_factor(false);
|
||||
if (req.flags&(COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY | COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS))
|
||||
{
|
||||
res.block_reward = currency::get_base_block_reward(true, total_coins, res.height);
|
||||
res.block_reward = currency::get_base_block_reward(res.height);
|
||||
currency::block b = AUTO_VAL_INIT(b);
|
||||
m_core.get_blockchain_storage().get_top_block(b);
|
||||
res.last_block_total_reward = currency::get_reward_from_miner_tx(b.miner_tx);
|
||||
|
|
@ -738,6 +738,18 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_get_assets_list(const COMMAND_RPC_GET_ASSETS_LIST::request& req, COMMAND_RPC_GET_ASSETS_LIST::response& res, connection_context& cntx)
|
||||
{
|
||||
CHECK_CORE_READY();
|
||||
if (!m_core.get_blockchain_storage().get_assets(req.offset, req.count, res.assets))
|
||||
{
|
||||
res.status = API_RETURN_CODE_NOT_FOUND;
|
||||
return true;
|
||||
}
|
||||
res.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_get_main_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
|
||||
{
|
||||
if (!m_core.get_blockchain_storage().get_main_block_rpc_details(req.id, res.block_details))
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ namespace currency
|
|||
bool on_get_pool_info(const COMMAND_RPC_GET_POOL_INFO::request& req, COMMAND_RPC_GET_POOL_INFO::response& res, connection_context& cntx);
|
||||
bool on_get_votes(const COMMAND_RPC_GET_VOTES::request& req, COMMAND_RPC_GET_VOTES::response& res, connection_context& cntx);
|
||||
bool on_get_asset_info(const COMMAND_RPC_GET_ASSET_INFO::request& req, COMMAND_RPC_GET_ASSET_INFO::response& res, connection_context& cntx);
|
||||
bool on_get_assets_list(const COMMAND_RPC_GET_ASSETS_LIST::request& req, COMMAND_RPC_GET_ASSETS_LIST::response& res, connection_context& cntx);
|
||||
|
||||
bool on_get_main_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_alt_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
|
|
@ -150,7 +151,8 @@ namespace currency
|
|||
MAP_JON_RPC ("getrandom_outs3", on_get_random_outs3, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3)
|
||||
MAP_JON_RPC ("get_votes", on_get_votes, COMMAND_RPC_GET_VOTES)
|
||||
//assets api
|
||||
MAP_JON_RPC ("get_asset_info", on_get_asset_info, COMMAND_RPC_GET_ASSET_INFO)
|
||||
MAP_JON_RPC ("get_asset_info", on_get_asset_info, COMMAND_RPC_GET_ASSET_INFO)
|
||||
MAP_JON_RPC ("get_assets_list", on_get_assets_list, COMMAND_RPC_GET_ASSETS_LIST)
|
||||
|
||||
MAP_JON_RPC_WE("get_main_block_details", on_get_main_block_details, COMMAND_RPC_GET_BLOCK_DETAILS)
|
||||
MAP_JON_RPC_WE("get_alt_block_details", on_get_alt_block_details, COMMAND_RPC_GET_BLOCK_DETAILS)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -63,6 +63,11 @@ namespace tools
|
|||
}
|
||||
|
||||
bool password_container::read_password(const std::string& prompt_text)
|
||||
{
|
||||
return read_input(prompt_text, '*');
|
||||
}
|
||||
|
||||
bool password_container::read_input(const std::string& prompt_text, char char_to_replace_user_input /* = '\0' */)
|
||||
{
|
||||
clear();
|
||||
|
||||
|
|
@ -70,7 +75,7 @@ namespace tools
|
|||
if (is_cin_tty())
|
||||
{
|
||||
std::cout << prompt_text;
|
||||
r = read_from_tty();
|
||||
r = read_from_tty(char_to_replace_user_input);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -122,7 +127,7 @@ namespace tools
|
|||
}
|
||||
}
|
||||
|
||||
bool password_container::read_from_tty()
|
||||
bool password_container::read_from_tty(char char_to_replace_user_input)
|
||||
{
|
||||
const char BACKSPACE = 8;
|
||||
|
||||
|
|
@ -162,7 +167,7 @@ namespace tools
|
|||
else
|
||||
{
|
||||
m_password.push_back(ch);
|
||||
std::cout << '*';
|
||||
std::cout << (char_to_replace_user_input != '\0' ? char_to_replace_user_input : ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +203,7 @@ namespace tools
|
|||
}
|
||||
}
|
||||
|
||||
bool password_container::read_from_tty()
|
||||
bool password_container::read_from_tty(char char_to_replace_user_input)
|
||||
{
|
||||
const char BACKSPACE = 127;
|
||||
|
||||
|
|
@ -227,7 +232,7 @@ namespace tools
|
|||
else
|
||||
{
|
||||
m_password.push_back(ch);
|
||||
std::cout << '*';
|
||||
std::cout << (char_to_replace_user_input != '\0' ? char_to_replace_user_input : ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -24,13 +24,15 @@ namespace tools
|
|||
void clear();
|
||||
bool empty() const { return m_empty; }
|
||||
const std::string& password() const { return m_password; }
|
||||
const std::string& get_input() const { return m_password; } // TODO: refactor this
|
||||
void password(std::string&& val) { m_password = std::move(val); m_empty = false; }
|
||||
bool read_password();
|
||||
bool read_password(const std::string& prompt_text);
|
||||
bool read_input(const std::string& prompt_text, char char_to_replace_user_input = '\0');
|
||||
|
||||
private:
|
||||
bool read_from_file();
|
||||
bool read_from_tty();
|
||||
bool read_from_tty(char char_to_replace_user_input);
|
||||
|
||||
private:
|
||||
bool m_empty;
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ simple_wallet::simple_wallet()
|
|||
m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::start_mining, this, ph::_1), "start_mining <threads_count> - Start mining in daemon");
|
||||
m_cmd_binder.set_handler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, ph::_1), "Stop mining in daemon");
|
||||
m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, ph::_1), "Resynchronize transactions and balance");
|
||||
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, ph::_1), "Show current wallet balance");
|
||||
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, ph::_1), "[force_all] Show current wallet balance, with 'force_all' param it displays all assets without filtering against whitelists");
|
||||
m_cmd_binder.set_handler("show_staking_history", boost::bind(&simple_wallet::show_staking_history, this, ph::_1), "show_staking_history [2] - Show staking transfers, if option provided - number of days for history to display");
|
||||
m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, ph::_1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability");
|
||||
m_cmd_binder.set_handler("incoming_counts", boost::bind(&simple_wallet::show_incoming_transfers_counts, this, ph::_1), "incoming_transfers counts");
|
||||
|
|
@ -315,6 +315,7 @@ simple_wallet::simple_wallet()
|
|||
m_cmd_binder.set_handler("scan_transfers_for_ki", boost::bind(&simple_wallet::scan_transfers_for_ki, this,ph::_1), "Rescan transfers for key image");
|
||||
m_cmd_binder.set_handler("print_utxo_distribution", boost::bind(&simple_wallet::print_utxo_distribution, this,ph::_1), "Prints utxo distribution");
|
||||
m_cmd_binder.set_handler("sweep_below", boost::bind(&simple_wallet::sweep_below, this,ph::_1), "sweep_below <mixin_count> <address> <amount_lower_limit> [payment_id] - Tries to transfers all coins with amount below the given limit to the given address");
|
||||
m_cmd_binder.set_handler("sweep_bare_outs", boost::bind(&simple_wallet::sweep_bare_outs, this,ph::_1), "sweep_bare_outs - Transfers all bare unspent outputs to itself. Uses several txs if necessary.");
|
||||
|
||||
m_cmd_binder.set_handler("address", boost::bind(&simple_wallet::print_address, this,ph::_1), "Show current wallet public address");
|
||||
m_cmd_binder.set_handler("integrated_address", boost::bind(&simple_wallet::integrated_address, this,ph::_1), "integrated_address [<payment_id>|<integrated_address] - encodes given payment_id along with wallet's address into an integrated address (random payment_id will be used if none is provided). Decodes given integrated_address into standard address");
|
||||
|
|
@ -542,8 +543,7 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_
|
|||
m_restore_wallet = command_line::get_arg(vm, arg_restore_wallet);
|
||||
m_disable_tor = command_line::get_arg(vm, arg_disable_tor_relay);
|
||||
m_voting_config_file = command_line::get_arg(vm, arg_voting_config_file);
|
||||
m_no_password_confirmations = command_line::get_arg(vm, arg_no_password_confirmations);
|
||||
|
||||
m_no_password_confirmations = command_line::get_arg(vm, arg_no_password_confirmations);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -1001,9 +1001,16 @@ bool simple_wallet::refresh(const std::vector<std::string>& args)
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::show_balance(const std::vector<std::string>& args/* = std::vector<std::string>()*/)
|
||||
bool simple_wallet::show_balance(const std::vector<std::string>& args /* = std::vector<std::string>()*/)
|
||||
{
|
||||
success_msg_writer() << m_wallet->get_balance_str();
|
||||
if (args.size() == 1 && args[0] == "raw")
|
||||
{
|
||||
success_msg_writer() << m_wallet->get_balance_str_raw();
|
||||
}
|
||||
else
|
||||
{
|
||||
success_msg_writer() << m_wallet->get_balance_str();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -2511,8 +2518,129 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args)
|
|||
SIMPLE_WALLET_CATCH_TRY_ENTRY();
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::sweep_bare_outs(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
bool r = false;
|
||||
|
||||
if (args.size() > 1)
|
||||
{
|
||||
fail_msg_writer() << "Invalid number of agruments given";
|
||||
return true;
|
||||
}
|
||||
|
||||
currency::account_public_address target_address = m_wallet->get_account().get_public_address();
|
||||
currency::payment_id_t integrated_payment_id{};
|
||||
if (args.size() == 1)
|
||||
{
|
||||
if (!m_wallet->get_transfer_address(args[0], target_address, integrated_payment_id))
|
||||
{
|
||||
fail_msg_writer() << "Unable to parse address from " << args[1];
|
||||
return true;
|
||||
}
|
||||
if (!integrated_payment_id.empty())
|
||||
{
|
||||
fail_msg_writer() << "Payment id is not supported. Please, don't use integrated address with this command.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_wallet->has_bare_unspent_outputs())
|
||||
{
|
||||
success_msg_writer(true) << "This wallet doesn't have bare unspent outputs.\nNothing to do. Everything looks good.";
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<tools::wallet2::batch_of_bare_unspent_outs> groups;
|
||||
m_wallet->get_bare_unspent_outputs_stats(groups);
|
||||
if (groups.empty())
|
||||
{
|
||||
uint64_t unlocked_balance = 0;
|
||||
uint64_t balance = m_wallet->balance(unlocked_balance);
|
||||
if (balance < COIN)
|
||||
success_msg_writer(false) << "Looks like it's not enough coins to perform this operation. Transferring " << print_money_brief(TX_MINIMUM_FEE) << " ZANO or more to this wallet may help.";
|
||||
else if (unlocked_balance < COIN)
|
||||
success_msg_writer(false) << "Not enough spendable outputs to perform this operation. Please, try again later.";
|
||||
else
|
||||
{
|
||||
success_msg_writer(false) << "This operation couldn't be performed for some reason. Please, copy simplewallet's log file and ask for support. Nothing was done.";
|
||||
LOG_PRINT_L0("strange situation: balance: " << print_money_brief(balance) << ", unlocked_balance: " << print_money_brief(unlocked_balance) << " but get_bare_unspent_outputs_stats returned empty result");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t i = 0, total_bare_outs = 0;
|
||||
uint64_t total_amount = 0;
|
||||
std::stringstream details_ss;
|
||||
for(auto &g : groups)
|
||||
{
|
||||
details_ss << std::setw(2) << i << ": ";
|
||||
for (auto& tid: g.tids)
|
||||
{
|
||||
tools::transfer_details td{};
|
||||
CHECK_AND_ASSERT_THROW_MES(m_wallet->get_transfer_info_by_index(tid, td), "get_transfer_info_by_index failed with index " << tid);
|
||||
details_ss << tid << " (" << print_money_brief(td.m_amount) << "), ";
|
||||
total_amount += td.m_amount;
|
||||
}
|
||||
|
||||
if (g.additional_tid)
|
||||
details_ss << "additional tid: " << g.tids.back() << "( " << print_money_brief(g.additional_tid_amount) << ")";
|
||||
else
|
||||
details_ss.seekp(-2, std::ios_base::end);
|
||||
|
||||
details_ss << ENDL;
|
||||
++i;
|
||||
total_bare_outs += g.tids.size();
|
||||
}
|
||||
|
||||
LOG_PRINT_L1("bare UTXO:" << ENDL << details_ss.str());
|
||||
|
||||
success_msg_writer(true) << "This wallet contains " << total_bare_outs << " bare outputs with total amount of " << print_money_brief(total_amount) <<
|
||||
". They can be converted in " << groups.size() << " transaction" << (groups.size() > 1 ? "s" : "") << ", with total fee = " << print_money_brief(TX_DEFAULT_FEE * i) << ".";
|
||||
if (target_address != m_wallet->get_account().get_public_address())
|
||||
message_writer(epee::log_space::console_color_yellow, false) << print_money_brief(total_amount) << " coins will be sent to address " << get_account_address_as_str(target_address);
|
||||
|
||||
tools::password_container reader;
|
||||
if (!reader.read_input("Would you like to continue? (y/yes/n/no):\n") || (reader.get_input() != "y" && reader.get_input() != "yes"))
|
||||
{
|
||||
success_msg_writer(false) << "Operatation terminated as requested by user.";
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t total_tx_sent = 0;
|
||||
uint64_t total_fee_spent = 0;
|
||||
uint64_t total_amount_sent = 0;
|
||||
auto on_tx_sent_callback = [&](size_t batch_index, const currency::transaction& tx, uint64_t amount, uint64_t fee, bool sent_ok, const std::string& err) {
|
||||
auto mw = success_msg_writer(false);
|
||||
mw << std::setw(2) << batch_index << ": transaction ";
|
||||
if (!sent_ok)
|
||||
{
|
||||
mw << "failed (" << err << ")";
|
||||
return;
|
||||
}
|
||||
mw << get_transaction_hash(tx) << ", fee: " << print_money_brief(fee) << ", amount: " << print_money_brief(amount);
|
||||
++total_tx_sent;
|
||||
total_fee_spent += fee;
|
||||
total_amount_sent += amount;
|
||||
};
|
||||
|
||||
if (!m_wallet->sweep_bare_unspent_outputs(target_address, groups, on_tx_sent_callback))
|
||||
{
|
||||
auto mw = fail_msg_writer();
|
||||
mw << "Operatation failed.";
|
||||
if (total_tx_sent > 0)
|
||||
mw << " However, " << total_tx_sent << " transaction" << (total_tx_sent == 1 ? " was" : "s were") << " successfully sent, " << print_money_brief(total_amount_sent) << " coins transferred, and " << print_money_brief(total_fee_spent) << " was spent for fees.";
|
||||
}
|
||||
else
|
||||
{
|
||||
success_msg_writer(true) << "Operatation succeeded. " << ENDL << total_tx_sent << " transaction" << (total_tx_sent == 1 ? " was" : "s were") << " successfully sent, " << print_money_brief(total_amount_sent) << " coins transferred, and " << print_money_brief(total_fee_spent) << " was spent for fees.";
|
||||
}
|
||||
|
||||
SIMPLE_WALLET_CATCH_TRY_ENTRY();
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t
|
||||
get_tick_count__()
|
||||
|
|
@ -2679,9 +2807,7 @@ int main(int argc, char* argv[])
|
|||
command_line::add_arg(desc_params, arg_set_timeout);
|
||||
command_line::add_arg(desc_params, arg_voting_config_file);
|
||||
command_line::add_arg(desc_params, arg_no_password_confirmations);
|
||||
|
||||
|
||||
|
||||
command_line::add_arg(desc_params, command_line::arg_generate_rpc_autodoc);
|
||||
|
||||
tools::wallet_rpc_server::init_options(desc_params);
|
||||
|
||||
|
|
@ -2736,6 +2862,16 @@ int main(int argc, char* argv[])
|
|||
message_writer(epee::log_space::console_color_white, true) << "Log level changed: " << old_log_level << " -> " << new_log_level;
|
||||
}
|
||||
|
||||
if (command_line::has_arg(vm, command_line::arg_generate_rpc_autodoc))
|
||||
{
|
||||
tools::wallet_rpc_server wallet_rpc_server(std::shared_ptr<tools::wallet2>(new tools::wallet2()));
|
||||
std::string path_to_generate = command_line::get_arg(vm, command_line::arg_generate_rpc_autodoc);
|
||||
|
||||
if (!generate_doc_as_md_files(path_to_generate, wallet_rpc_server))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (command_line::has_arg(vm, arg_scan_for_wallet))
|
||||
{
|
||||
|
|
@ -2816,6 +2952,22 @@ int main(int argc, char* argv[])
|
|||
break;
|
||||
}
|
||||
//try to sync it
|
||||
struct wallet_rpc_local_callback : public tools::i_wallet2_callback
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> m_wlt_ptr;
|
||||
wallet_rpc_local_callback(std::shared_ptr<tools::wallet2> ptr): m_wlt_ptr(ptr)
|
||||
{}
|
||||
virtual void on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets)
|
||||
{
|
||||
wallets.push_back(tools::wallet_public::wallet_entry_info());
|
||||
wallets.back().wallet_id = 0;
|
||||
tools::get_wallet_info(*m_wlt_ptr, wallets.back().wi);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
std::shared_ptr<tools::i_wallet2_callback> callback(new wallet_rpc_local_callback(wallet_ptr));
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
|
|
@ -2828,6 +2980,7 @@ int main(int argc, char* argv[])
|
|||
return EXIT_FAILURE;
|
||||
|
||||
wal.set_use_assets_whitelisting(true);
|
||||
wal.callback(callback);
|
||||
|
||||
if (!offline_mode)
|
||||
wal.refresh();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -87,6 +87,7 @@ namespace currency
|
|||
bool sign_transfer(const std::vector<std::string> &args);
|
||||
bool submit_transfer(const std::vector<std::string> &args);
|
||||
bool sweep_below(const std::vector<std::string> &args);
|
||||
bool sweep_bare_outs(const std::vector<std::string> &args);
|
||||
bool tor_enable(const std::vector<std::string> &args);
|
||||
bool tor_disable(const std::vector<std::string> &args);
|
||||
bool deploy_new_asset(const std::vector<std::string> &args);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@
|
|||
#define PROJECT_REVISION "0"
|
||||
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
|
||||
|
||||
#define PROJECT_VERSION_BUILD_NO 300
|
||||
#define PROJECT_VERSION_BUILD_NO 317
|
||||
#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 "]"
|
||||
|
|
|
|||
|
|
@ -51,6 +51,27 @@ namespace tools
|
|||
return r;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool default_http_core_proxy::call_COMMAND_RPC_INVOKE(const std::string& uri, const std::string& body, int& response_code, std::string& response_body)
|
||||
{
|
||||
return call_request([&]() {
|
||||
#ifdef MOBILE_WALLET_BUILD
|
||||
LOG_PRINT_L0("[INVOKE_PROXY] ---> " << uri)
|
||||
#endif
|
||||
|
||||
const epee::net_utils::http::http_response_info* response = nullptr;
|
||||
bool res = m_http_client.invoke(uri, "POST", body, &response);
|
||||
if (response)
|
||||
{
|
||||
response_body = response->m_body;
|
||||
response_code = response->m_response_code;
|
||||
}
|
||||
#ifdef MOBILE_WALLET_BUILD
|
||||
LOG_PRINT_L0("[INVOKE_PROXY] <---" << uri)
|
||||
#endif
|
||||
return res;
|
||||
});
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool default_http_core_proxy::call_COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE(const currency::COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE::request& rqt, currency::COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE::response& rsp)
|
||||
{
|
||||
return invoke_http_json_rpc_update_is_disconnect("get_est_height_from_date", rqt, rsp);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace tools
|
|||
|
||||
|
||||
bool set_connection_addr(const std::string& url) override;
|
||||
void set_connectivity(unsigned int connection_timeout, size_t repeats_count);
|
||||
void set_connectivity(unsigned int connection_timeout, size_t repeats_count) override;
|
||||
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;
|
||||
|
|
@ -53,6 +53,7 @@ namespace tools
|
|||
bool call_COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN(const currency::COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::request& req, currency::COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::response& res) override;
|
||||
bool call_COMMAND_RPC_GET_POOL_INFO(const currency::COMMAND_RPC_GET_POOL_INFO::request& req, currency::COMMAND_RPC_GET_POOL_INFO::response& res) override;
|
||||
bool call_COMMAND_RPC_GET_ASSET_INFO(const currency::COMMAND_RPC_GET_ASSET_INFO::request& req, currency::COMMAND_RPC_GET_ASSET_INFO::response& res) override;
|
||||
bool call_COMMAND_RPC_INVOKE(const std::string& uri, const std::string& body, int& response_code, std::string& response_body) override;
|
||||
|
||||
bool check_connection() override;
|
||||
bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id) override;
|
||||
|
|
|
|||
|
|
@ -143,6 +143,22 @@ namespace tools
|
|||
return m_rpc.on_get_asset_info(req, res, m_cntxt_stub);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
virtual bool call_COMMAND_RPC_INVOKE(const std::string& uri, const std::string& body, int& response_code, std::string& response_body) override
|
||||
{
|
||||
epee::net_utils::http::http_request_info query_info = AUTO_VAL_INIT(query_info);
|
||||
query_info.m_URI = uri;
|
||||
query_info.m_http_method = epee::net_utils::http::http_method_get;
|
||||
query_info.m_body = body;
|
||||
|
||||
epee::net_utils::http::http_response_info response = AUTO_VAL_INIT(response);
|
||||
epee::net_utils::connection_context_base conn_context = AUTO_VAL_INIT(conn_context);
|
||||
|
||||
bool res = m_rpc.handle_http_request(query_info, response, conn_context);
|
||||
response_body = response.m_body;
|
||||
response_code = response.m_response_code;
|
||||
return res;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
virtual bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id) override
|
||||
{
|
||||
return tools::get_transfer_address(adr_str, addr, payment_id, this);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ namespace tools
|
|||
virtual bool call_COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN(const currency::COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::request& req, currency::COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::response& res){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_POOL_INFO(const currency::COMMAND_RPC_GET_POOL_INFO::request& req, currency::COMMAND_RPC_GET_POOL_INFO::response& res) { return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_ASSET_INFO(const currency::COMMAND_RPC_GET_ASSET_INFO::request& req, currency::COMMAND_RPC_GET_ASSET_INFO::response& res) { return false; }
|
||||
|
||||
virtual bool call_COMMAND_RPC_INVOKE(const std::string& uri, const std::string& body, int& response_code, std::string& response_body) { return false; }
|
||||
|
||||
i_core_proxy()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -201,11 +201,13 @@ public:
|
|||
|
||||
std::list<tools::wallet_public::asset_balance_entry> balances;
|
||||
uint64_t minied_total;
|
||||
bool has_bare_unspent_outputs;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_CHAIN_BASE(wallet_status_info_base)
|
||||
KV_SERIALIZE(balances)
|
||||
KV_SERIALIZE(minied_total)
|
||||
KV_SERIALIZE(has_bare_unspent_outputs)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
@ -729,12 +731,14 @@ public:
|
|||
|
||||
struct gui_options
|
||||
{
|
||||
bool use_debug_mode;
|
||||
bool disable_price_fetch;
|
||||
bool use_debug_mode = false;
|
||||
bool disable_price_fetch = false;
|
||||
int32_t rpc_port = 0;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(use_debug_mode)
|
||||
KV_SERIALIZE(disable_price_fetch)
|
||||
KV_SERIALIZE(rpc_port)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -352,31 +352,6 @@ const currency::txout_htlc& out_get_htlc(const currency::tx_out_v& out_t)
|
|||
return boost::get<currency::txout_htlc>(boost::get<currency::tx_out_bare>(out_t).target);
|
||||
}
|
||||
|
||||
uint8_t wallet2::out_get_mixin_attr(const currency::tx_out_v& out_t)
|
||||
{
|
||||
if (out_t.type() == typeid(currency::tx_out_bare))
|
||||
{
|
||||
if (boost::get<currency::tx_out_bare>(out_t).target.type() == typeid(currency::txout_to_key))
|
||||
{
|
||||
return boost::get<currency::txout_to_key>(boost::get<currency::tx_out_bare>(out_t).target).mix_attr;
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_WALLET_CMN_ERR_EX("Unexpected type in out_get_mixin_attr");
|
||||
}
|
||||
}
|
||||
else if (out_t.type() == typeid(currency::tx_out_zarcanum))
|
||||
{
|
||||
return boost::get<currency::tx_out_zarcanum>(out_t).mix_attr;
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_WALLET_CMN_ERR_EX("Unexpected type in out_get_mixin_attr");
|
||||
}
|
||||
THROW_WALLET_CMN_ERR_EX("Unexpected out type im wallet: " << out_t.type().name());
|
||||
return false;
|
||||
}
|
||||
|
||||
const crypto::public_key& wallet2::out_get_pub_key(const currency::tx_out_v& out_t, std::list<currency::htlc_info>& htlc_info_list)
|
||||
{
|
||||
if (out_t.type() == typeid(tx_out_bare))
|
||||
|
|
@ -424,16 +399,17 @@ void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_op
|
|||
|
||||
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(m_own_asset_descriptors.count(asset_id) == 0, "asset with asset_id " << asset_id << " has already been registered in the wallet as own asset");
|
||||
wallet_own_asset_context& asset_context = m_own_asset_descriptors[asset_id];
|
||||
asset_context.asset_descriptor = ado.descriptor;
|
||||
epee::misc_utils::cast_assign_a_to_b(asset_context, ado.descriptor);
|
||||
//*static_cast<asset_descriptor_base*>(&asset_context) = ado.descriptor;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "New Asset Registered:"
|
||||
<< ENDL << "asset id: " << asset_id
|
||||
<< ENDL << "Name: " << asset_context.asset_descriptor.full_name
|
||||
<< ENDL << "Ticker: " << asset_context.asset_descriptor.ticker
|
||||
<< ENDL << "Total Max Supply: " << print_asset_money(asset_context.asset_descriptor.total_max_supply, asset_context.asset_descriptor.decimal_point)
|
||||
<< ENDL << "Current Supply: " << print_asset_money(asset_context.asset_descriptor.current_supply, asset_context.asset_descriptor.decimal_point)
|
||||
<< ENDL << "Decimal Point: " << (int)asset_context.asset_descriptor.decimal_point;
|
||||
<< ENDL << "Name: " << asset_context.full_name
|
||||
<< ENDL << "Ticker: " << asset_context.ticker
|
||||
<< ENDL << "Total Max Supply: " << print_asset_money(asset_context.total_max_supply, asset_context.decimal_point)
|
||||
<< ENDL << "Current Supply: " << print_asset_money(asset_context.current_supply, asset_context.decimal_point)
|
||||
<< ENDL << "Decimal Point: " << (int)asset_context.decimal_point;
|
||||
|
||||
|
||||
add_rollback_event(ptc.height, asset_register_event{ asset_id });
|
||||
|
|
@ -448,7 +424,8 @@ void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_op
|
|||
break;
|
||||
//asset had been updated
|
||||
add_rollback_event(ptc.height, asset_update_event{ it->first, it->second });
|
||||
it->second.asset_descriptor = ado.descriptor;
|
||||
epee::misc_utils::cast_assign_a_to_b(it->second, ado.descriptor);
|
||||
|
||||
}
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE )
|
||||
{
|
||||
|
|
@ -460,7 +437,7 @@ void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_op
|
|||
// ownership of the asset acquired
|
||||
|
||||
wallet_own_asset_context& asset_context = m_own_asset_descriptors[asset_id];
|
||||
asset_context.asset_descriptor = ado.descriptor;
|
||||
epee::misc_utils::cast_assign_a_to_b(asset_context, ado.descriptor);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Asset ownership acquired:"
|
||||
|
|
@ -511,7 +488,8 @@ void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_op
|
|||
{
|
||||
//just an update of the asset
|
||||
add_rollback_event(ptc.height, asset_update_event{ it->first, it->second });
|
||||
it->second.asset_descriptor = ado.descriptor;
|
||||
epee::misc_utils::cast_assign_a_to_b(it->second, ado.descriptor);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -523,6 +501,64 @@ void wallet2::add_rollback_event(uint64_t h, const wallet_event_t& ev)
|
|||
m_rollback_events.emplace_back(h, ev);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
#define M_LAST_ZC_GLOBAL_INDEXS_MAX_SIZE 30
|
||||
void wallet2::add_to_last_zc_global_indexs(uint64_t h, uint64_t last_zc_output_index)
|
||||
{
|
||||
if (m_last_zc_global_indexs.size())
|
||||
{
|
||||
if (h > m_last_zc_global_indexs.begin()->first)
|
||||
{
|
||||
//new block added on top of last one, simply add new record
|
||||
m_last_zc_global_indexs.push_front(std::make_pair(h, last_zc_output_index));
|
||||
}
|
||||
else if (h < m_last_zc_global_indexs.begin()->first)
|
||||
{
|
||||
//looks like reorganize, pop all records before
|
||||
while (m_last_zc_global_indexs.size() && m_last_zc_global_indexs.begin()->first >= h)
|
||||
{
|
||||
m_last_zc_global_indexs.erase(m_last_zc_global_indexs.begin());
|
||||
}
|
||||
m_last_zc_global_indexs.push_front(std::make_pair(h, last_zc_output_index));
|
||||
}
|
||||
else
|
||||
{
|
||||
//@#@
|
||||
#ifdef _DEBUG
|
||||
if (m_last_zc_global_indexs.begin()->second > last_zc_output_index)
|
||||
{
|
||||
LOG_ERROR("!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
#endif
|
||||
//equals, same h but new last_zc_output_index, just update it, should be always bigger then prev
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(m_last_zc_global_indexs.begin()->second <= last_zc_output_index,
|
||||
"condition m_last_zc_global_indexs.begin()->second " << m_last_zc_global_indexs.begin()->second << " <= last_zc_output_index " << last_zc_output_index << " failed", API_RETURN_CODE_INTERNAL_ERROR);
|
||||
m_last_zc_global_indexs.begin()->second = last_zc_output_index;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//new block added on top of last one, simply add new record
|
||||
m_last_zc_global_indexs.push_front(std::make_pair(h, last_zc_output_index));
|
||||
}
|
||||
|
||||
if (m_last_zc_global_indexs.size() > M_LAST_ZC_GLOBAL_INDEXS_MAX_SIZE)
|
||||
m_last_zc_global_indexs.pop_back();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::get_actual_zc_global_index()
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(m_last_zc_global_indexs.size(), "m_last_zc_global_indexs is empty", API_RETURN_CODE_INTERNAL_ERROR);
|
||||
for (auto it = m_last_zc_global_indexs.begin(); it != m_last_zc_global_indexs.end(); it++)
|
||||
{
|
||||
if (it->first <= m_last_known_daemon_height - WALLET_DEFAULT_TX_SPENDABLE_AGE)
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(false, "doesn't have anything that match expected height = " << m_last_known_daemon_height - WALLET_DEFAULT_TX_SPENDABLE_AGE, API_RETURN_CODE_INTERNAL_ERROR);
|
||||
throw std::runtime_error(""); //mostly to suppress compiler warning
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t height, const currency::block& b, const std::vector<uint64_t>* pglobal_indexes)
|
||||
{
|
||||
//check for transaction spends
|
||||
|
|
@ -540,11 +576,9 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
{
|
||||
if (pglobal_indexes->size())
|
||||
{
|
||||
//store global index that is under coinage, so we can used in decoy selection algo
|
||||
if (ptc.height < m_last_known_daemon_height && m_last_known_daemon_height - ptc.height > WALLET_DEFAULT_TX_SPENDABLE_AGE)
|
||||
{
|
||||
m_last_zc_global_index = pglobal_indexes->back();
|
||||
}
|
||||
//@#@
|
||||
WLT_LOG_L2("add_to_last_zc_global_indexs: h: " << height << ", b: " << currency::get_block_hash(b) << " , tx: " << currency::get_transaction_hash(tx) << ", last_zc_output_index: " << pglobal_indexes->back());
|
||||
add_to_last_zc_global_indexs(ptc.height, pglobal_indexes->back());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -742,15 +776,16 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
}
|
||||
}
|
||||
|
||||
if (is_auditable() && (out_type_to_key || out_type_zc) &&
|
||||
out_get_mixin_attr(out_v) != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX)
|
||||
uint8_t mix_attr = CURRENCY_TO_KEY_OUT_RELAXED;
|
||||
[[maybe_unused]] bool mix_attr_r = get_mix_attr_from_tx_out_v(out_v, mix_attr);
|
||||
if (is_auditable() && (out_type_to_key || out_type_zc) && mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "output #" << o << " from tx " << ptc.tx_hash();
|
||||
if (!out.is_native_coin())
|
||||
ss << " asset_id: " << out.asset_id;
|
||||
ss << " with amount " << print_money_brief(out.amount)
|
||||
<< " is targeted to this auditable wallet and has INCORRECT mix_attr = " << (uint64_t)out_get_mixin_attr(out_v) << ". Output is IGNORED.";
|
||||
<< " is targeted to this auditable wallet and has INCORRECT mix_attr = " << (uint64_t)mix_attr << ". Output is IGNORED.";
|
||||
WLT_LOG_YELLOW(ss.str(), LOG_LEVEL_0);
|
||||
if (m_wcallback)
|
||||
m_wcallback->on_message(i_wallet2_callback::ms_red, ss.str());
|
||||
|
|
@ -1120,7 +1155,8 @@ void wallet2::accept_proposal(const crypto::hash& contract_id, uint64_t b_accept
|
|||
//---------------------------------------------------------------------------------
|
||||
uint64_t wallet2::get_current_tx_version()
|
||||
{
|
||||
return currency::get_tx_version(this->get_top_block_height(), this->m_core_runtime_config.hard_forks);
|
||||
uint64_t tx_expected_block_height = get_top_block_height() + 1;
|
||||
return currency::get_tx_version(tx_expected_block_height, this->m_core_runtime_config.hard_forks);
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
void wallet2::finish_contract(const crypto::hash& contract_id, const std::string& release_type, currency::transaction* p_release_tx /* = nullptr */)
|
||||
|
|
@ -1857,9 +1893,16 @@ void wallet2::process_new_blockchain_entry(const currency::block& b, const curre
|
|||
TIME_MEASURE_FINISH(miner_tx_handle_time);
|
||||
|
||||
TIME_MEASURE_START(txs_handle_time);
|
||||
size_t count = 0;
|
||||
for(const auto& tx_entry: bche.txs_ptr)
|
||||
{
|
||||
if (b.tx_hashes.size() < count || currency::get_transaction_hash(tx_entry->tx) != b.tx_hashes[count])
|
||||
{
|
||||
LOG_ERROR("Found tx order fail in process_new_blockchain_entry: count=" << count
|
||||
<< ", b.tx_hashes.size() = " << b.tx_hashes.size() << ", tx real id: " << currency::get_transaction_hash(tx_entry->tx) << ", bl_id: " << bl_id);
|
||||
}
|
||||
process_new_transaction(tx_entry->tx, height, b, &(tx_entry->m_global_output_indexes));
|
||||
count++;
|
||||
}
|
||||
TIME_MEASURE_FINISH(txs_handle_time);
|
||||
WLT_LOG_L3("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms");
|
||||
|
|
@ -2200,6 +2243,190 @@ bool wallet2::has_related_alias_entry_unconfirmed(const currency::transaction& t
|
|||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::has_bare_unspent_outputs() const
|
||||
{
|
||||
if (m_account.get_createtime() > ZANO_HARDFORK_04_TIMESTAMP_ACTUAL)
|
||||
return false;
|
||||
|
||||
[[maybe_unused]] uint64_t bal = 0;
|
||||
if (!m_has_bare_unspent_outputs.has_value())
|
||||
bal = balance();
|
||||
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(m_has_bare_unspent_outputs.has_value(), "m_has_bare_unspent_outputs has no value after balance()");
|
||||
|
||||
return m_has_bare_unspent_outputs.value();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
#define MAX_INPUTS_FOR_SIMPLE_TX_EURISTIC 20
|
||||
bool wallet2::get_bare_unspent_outputs_stats(std::vector<batch_of_bare_unspent_outs>& tids_grouped_by_txs) const
|
||||
{
|
||||
tids_grouped_by_txs.clear();
|
||||
|
||||
// 1/3. Populate a list of bare unspent outputs
|
||||
std::unordered_map<crypto::hash, std::vector<size_t>> buo_ids; // tx hash -> Bare Unspent Outs list
|
||||
for(size_t tid = 0; tid != m_transfers.size(); ++tid)
|
||||
{
|
||||
const auto& td = m_transfers[tid];
|
||||
if (!td.is_zc() && td.is_spendable())
|
||||
{
|
||||
buo_ids[td.tx_hash()].push_back(tid);
|
||||
}
|
||||
}
|
||||
|
||||
if (buo_ids.empty())
|
||||
return true;
|
||||
|
||||
// 2/3. Split them into groups
|
||||
tids_grouped_by_txs.emplace_back();
|
||||
for(auto& buo_el : buo_ids)
|
||||
{
|
||||
if (tids_grouped_by_txs.back().tids.size() + buo_el.second.size() > MAX_INPUTS_FOR_SIMPLE_TX_EURISTIC)
|
||||
tids_grouped_by_txs.emplace_back();
|
||||
|
||||
for(auto& tid : buo_el.second)
|
||||
{
|
||||
if (tids_grouped_by_txs.back().tids.size() >= MAX_INPUTS_FOR_SIMPLE_TX_EURISTIC)
|
||||
tids_grouped_by_txs.emplace_back();
|
||||
tids_grouped_by_txs.back().tids.push_back((uint64_t)tid);
|
||||
tids_grouped_by_txs.back().total_amount += m_transfers[tid].m_amount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 3/3. Iterate through groups and check whether total amount is big enough to cover min fee.
|
||||
// Add additional zc output if not.
|
||||
std::multimap<uint64_t, size_t> usable_zc_outs_tids; // grouped by amount
|
||||
bool usable_zc_outs_tids_precalculated = false;
|
||||
auto precalculate_usable_zc_outs_if_needed = [&](){
|
||||
if (usable_zc_outs_tids_precalculated)
|
||||
return;
|
||||
size_t decoys = is_auditable() ? 0 : m_core_runtime_config.hf4_minimum_mixins;
|
||||
for(size_t tid = 0; tid != m_transfers.size(); ++tid)
|
||||
{
|
||||
auto& td = m_transfers[tid];
|
||||
if (td.is_zc() && td.is_native_coin() && is_transfer_ready_to_go(td, decoys))
|
||||
usable_zc_outs_tids.insert(std::make_pair(td.m_amount, tid));
|
||||
}
|
||||
usable_zc_outs_tids_precalculated = true;
|
||||
};
|
||||
|
||||
std::unordered_set<size_t> used_zc_outs;
|
||||
for(auto it = tids_grouped_by_txs.begin(); it != tids_grouped_by_txs.end(); )
|
||||
{
|
||||
auto& group = *it;
|
||||
if (group.total_amount < TX_MINIMUM_FEE)
|
||||
{
|
||||
precalculate_usable_zc_outs_if_needed();
|
||||
|
||||
uint64_t min_required_amount = TX_MINIMUM_FEE - group.total_amount;
|
||||
auto jt = usable_zc_outs_tids.lower_bound(min_required_amount);
|
||||
bool found = false;
|
||||
while(jt != usable_zc_outs_tids.end())
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(jt->first >= min_required_amount, "jt->first=" << jt->first << ", min_required_amount=" << min_required_amount);
|
||||
if (used_zc_outs.count(jt->second) == 0)
|
||||
{
|
||||
group.tids.push_back((uint64_t)jt->second);
|
||||
used_zc_outs.insert(jt->second);
|
||||
group.additional_tid = true;
|
||||
group.additional_tid_amount = jt->first;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
++jt;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
// no usable outs for required amount, remove this group and go to the next
|
||||
it = tids_grouped_by_txs.erase(it);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::sweep_bare_unspent_outputs(const currency::account_public_address& target_address, const std::vector<batch_of_bare_unspent_outs>& tids_grouped_by_txs,
|
||||
std::function<void(size_t batch_index, const currency::transaction& tx, uint64_t amount, uint64_t fee, bool sent_ok, const std::string& err)> on_tx_sent)
|
||||
{
|
||||
if (m_watch_only)
|
||||
return false;
|
||||
|
||||
size_t decoys_count = is_auditable() ? 0 : CURRENCY_DEFAULT_DECOY_SET_SIZE;
|
||||
|
||||
bool send_to_network = true;
|
||||
|
||||
size_t batch_index = 0;
|
||||
for(const batch_of_bare_unspent_outs& group : tids_grouped_by_txs)
|
||||
{
|
||||
currency::finalized_tx ftx{};
|
||||
currency::finalize_tx_param ftp{};
|
||||
ftp.pevents_dispatcher = &m_debug_events_dispatcher;
|
||||
ftp.tx_version = this->get_current_tx_version();
|
||||
|
||||
if (!prepare_tx_sources(decoys_count, /*use_all_decoys_if_found_less_than_required*/ true, ftp.sources, group.tids))
|
||||
{
|
||||
on_tx_sent(batch_index, transaction{}, 0, 0, false, "sources for tx couldn't be prepared");
|
||||
LOG_PRINT_L0("prepare_tx_sources failed, batch_index = " << batch_index);
|
||||
return false;
|
||||
}
|
||||
uint64_t fee = TX_DEFAULT_FEE;
|
||||
std::vector<tx_destination_entry> destinations{tx_destination_entry(group.total_amount + group.additional_tid_amount - fee, target_address)};
|
||||
assets_selection_context needed_money_map{std::make_pair(native_coin_asset_id, selection_for_amount{group.total_amount + group.additional_tid_amount, group.total_amount + group.additional_tid_amount})};
|
||||
try
|
||||
{
|
||||
prepare_tx_destinations(needed_money_map, get_current_split_strategy(), tx_dust_policy{}, destinations, 0 /* tx_flags */, ftp.prepared_destinations);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
on_tx_sent(batch_index, transaction{}, 0, 0, false, "destinations for tx couldn't be prepared");
|
||||
LOG_PRINT_L0("prepare_tx_destinations failed, batch_index = " << batch_index);
|
||||
return false;
|
||||
}
|
||||
|
||||
mark_transfers_as_spent(ftp.selected_transfers, std::string("sweep bare UTXO, tx: ") + epee::string_tools::pod_to_hex(get_transaction_hash(ftx.tx)));
|
||||
try
|
||||
{
|
||||
finalize_transaction(ftp, ftx, send_to_network);
|
||||
on_tx_sent(batch_index, ftx.tx, group.total_amount + group.additional_tid_amount, fee, true, std::string());
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
clear_transfers_from_flag(ftp.selected_transfers, WALLET_TRANSFER_DETAIL_FLAG_SPENT, std::string("exception on sweep bare UTXO, tx: ") + epee::string_tools::pod_to_hex(get_transaction_hash(ftx.tx)));
|
||||
on_tx_sent(batch_index, transaction{}, 0, 0, false, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
++batch_index;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::sweep_bare_unspent_outputs(const currency::account_public_address& target_address, const std::vector<batch_of_bare_unspent_outs>& tids_grouped_by_txs,
|
||||
size_t& total_txs_sent, uint64_t& total_amount_sent, uint64_t& total_fee_spent, uint64_t& total_bare_outs_sent)
|
||||
{
|
||||
total_txs_sent = 0;
|
||||
total_amount_sent = 0;
|
||||
total_fee_spent = 0;
|
||||
total_bare_outs_sent = 0;
|
||||
auto on_tx_sent_callback = [&](size_t batch_index, const currency::transaction& tx, uint64_t amount, uint64_t fee, bool sent_ok, const std::string& err) {
|
||||
if (sent_ok)
|
||||
{
|
||||
total_bare_outs_sent += count_type_in_variant_container<txin_to_key>(tx.vin);
|
||||
++total_txs_sent;
|
||||
total_fee_spent += fee;
|
||||
total_amount_sent += amount;
|
||||
}
|
||||
};
|
||||
|
||||
return sweep_bare_unspent_outputs(target_address, tids_grouped_by_txs, on_tx_sent_callback);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::get_directly_spent_transfer_index_by_input_in_tracking_wallet(const currency::txin_to_key& intk)
|
||||
{
|
||||
return get_directly_spent_transfer_index_by_input_in_tracking_wallet(intk.amount, intk.key_offsets);
|
||||
|
|
@ -2861,6 +3088,12 @@ void wallet2::detach_blockchain(uint64_t including_height)
|
|||
++it;
|
||||
}
|
||||
|
||||
//detach in m_last_zc_global_indexs
|
||||
while (m_last_zc_global_indexs.size() && including_height <= m_last_zc_global_indexs.begin()->first )
|
||||
{
|
||||
m_last_zc_global_indexs.erase(m_last_zc_global_indexs.begin());
|
||||
}
|
||||
|
||||
//asset descriptors
|
||||
handle_rollback_events(including_height);
|
||||
|
||||
|
|
@ -3444,6 +3677,7 @@ uint64_t wallet2::balance(const crypto::public_key& asset_id) const
|
|||
bool wallet2::balance(std::unordered_map<crypto::public_key, wallet_public::asset_balance_entry_base>& balances, uint64_t& mined) const
|
||||
{
|
||||
mined = 0;
|
||||
m_has_bare_unspent_outputs = false;
|
||||
|
||||
for(auto& td : m_transfers)
|
||||
{
|
||||
|
|
@ -3464,6 +3698,9 @@ bool wallet2::balance(std::unordered_map<crypto::public_key, wallet_public::asse
|
|||
mined += CURRENCY_BLOCK_REWARD; //this code would work only for cases where block reward is full. For reduced block rewards might need more flexible code (TODO)
|
||||
}
|
||||
}
|
||||
|
||||
if (!td.is_zc())
|
||||
m_has_bare_unspent_outputs = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3519,7 +3756,7 @@ bool wallet2::balance(std::list<wallet_public::asset_balance_entry>& balances, u
|
|||
{
|
||||
if (m_whitelisted_assets.find(own_asset.first) == m_whitelisted_assets.end())
|
||||
{
|
||||
custom_assets_local[own_asset.first] = own_asset.second.asset_descriptor;
|
||||
custom_assets_local[own_asset.first] = own_asset.second;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3634,7 +3871,7 @@ bool wallet2::add_custom_asset_id(const crypto::public_key& asset_id, asset_desc
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::delete_custom_asset_id(const crypto::public_key& asset_id)
|
||||
{
|
||||
auto it = m_custom_assets.find(asset_id);
|
||||
const auto it = m_custom_assets.find(asset_id);
|
||||
if (it != m_custom_assets.end())
|
||||
{
|
||||
m_custom_assets.erase(it);
|
||||
|
|
@ -3643,6 +3880,21 @@ bool wallet2::delete_custom_asset_id(const crypto::public_key& asset_id)
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
const std::unordered_map<crypto::public_key, currency::asset_descriptor_base>& wallet2::get_local_whitelist() const
|
||||
{
|
||||
return m_custom_assets;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
const std::unordered_map<crypto::public_key, currency::asset_descriptor_base>& wallet2::get_global_whitelist() const
|
||||
{
|
||||
return m_whitelisted_assets;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
const std::unordered_map<crypto::public_key, tools::wallet_own_asset_context>& wallet2::get_own_assets() const
|
||||
{
|
||||
return m_own_asset_descriptors;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::load_whitelisted_tokens() const
|
||||
{
|
||||
if(!m_use_assets_whitelisting)
|
||||
|
|
@ -3656,9 +3908,10 @@ bool wallet2::load_whitelisted_tokens() const
|
|||
for (auto it = aw.assets.begin(); it != aw.assets.end(); it++)
|
||||
{
|
||||
m_whitelisted_assets[it->asset_id] = static_cast<currency::asset_descriptor_base>(*it);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::load_whitelisted_tokens_if_not_loaded() const
|
||||
|
|
@ -3778,6 +4031,59 @@ std::string wallet2::get_balance_str() const
|
|||
return ss.str();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::get_balance_str_raw() const
|
||||
{
|
||||
// balance unlocked / [balance total] ticker asset id
|
||||
// 1391306.970000000000 / 1391306.970000000000 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
|
||||
// 1391306.97 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
|
||||
// 106.971 / 206.4 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
|
||||
|
||||
static const char* header = " balance unlocked / [balance total] asset id";
|
||||
std::stringstream ss;
|
||||
ss << header << ENDL;
|
||||
|
||||
uint64_t dummy = 0;
|
||||
std::unordered_map<crypto::public_key, wallet_public::asset_balance_entry_base> balances_map;
|
||||
this->balance(balances_map, dummy);
|
||||
|
||||
for(const auto& entry : balances_map)
|
||||
{
|
||||
ss << " " << std::left << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(entry.second.unlocked, 12);
|
||||
if(entry.second.total == entry.second.unlocked)
|
||||
ss << " ";
|
||||
else
|
||||
ss << " / " << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(entry.second.total, 12);
|
||||
ss << " " << std::setw(8) << std::left << entry.first << ENDL;
|
||||
}
|
||||
|
||||
//print whitelist
|
||||
ss << "WHITELIST: " << ENDL;
|
||||
|
||||
|
||||
for(const auto& entry : m_whitelisted_assets)
|
||||
{
|
||||
ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL;
|
||||
}
|
||||
|
||||
// print whitelist
|
||||
ss << "CUSTOM LIST: " << ENDL;
|
||||
|
||||
|
||||
for(const auto& entry : m_custom_assets)
|
||||
{
|
||||
ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL;
|
||||
}
|
||||
|
||||
ss << "OWN DESCRIPTORS LIST: " << ENDL;
|
||||
|
||||
for(const auto& entry : m_own_asset_descriptors)
|
||||
{
|
||||
ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL;
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::get_payments(const std::string& payment_id, std::list<payment_details>& payments, uint64_t min_height) const
|
||||
{
|
||||
auto range = m_payments.equal_range(payment_id);
|
||||
|
|
@ -4249,6 +4555,11 @@ bool wallet2::is_in_hardfork_zone(uint64_t hardfork_index) const
|
|||
return m_core_runtime_config.is_hardfork_active_for_height(hardfork_index, get_blockchain_current_size());
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::proxy_to_daemon(const std::string& uri, const std::string& body, int& response_code, std::string& response_body)
|
||||
{
|
||||
return m_core_proxy->call_COMMAND_RPC_INVOKE(uri, body, response_code, response_body);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t full_block_reward, const currency::pos_entry& pe, currency::tx_generation_context& miner_tx_tgc, currency::block& b) const
|
||||
{
|
||||
bool r = false;
|
||||
|
|
@ -4291,7 +4602,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
|
|||
if (m_required_decoys_count > 0 && !is_auditable())
|
||||
{
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request decoys_req = AUTO_VAL_INIT(decoys_req);
|
||||
decoys_req.height_upper_limit = 0; // TODO @#@# maybe use m_last_pow_block_h like Zarcanum?
|
||||
decoys_req.height_upper_limit = std::min(m_last_pow_block_h, m_last_known_daemon_height > m_core_runtime_config.min_coinstake_age ? m_last_known_daemon_height - m_core_runtime_config.min_coinstake_age : m_last_pow_block_h);
|
||||
decoys_req.use_forced_mix_outs = false;
|
||||
decoys_req.decoys_count = m_required_decoys_count + 1; // one more to be able to skip a decoy in case it hits the real output
|
||||
decoys_req.amounts.push_back(pe.amount); // request one batch of decoys
|
||||
|
|
@ -4576,15 +4887,16 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
|
|||
return true;
|
||||
}, m_core_runtime_config);
|
||||
|
||||
bool res = true;
|
||||
if (ctx.status == API_RETURN_CODE_OK)
|
||||
{
|
||||
build_minted_block(ctx, miner_address);
|
||||
res = build_minted_block(ctx, miner_address);
|
||||
}
|
||||
TIME_MEASURE_FINISH_MS(mining_duration_ms);
|
||||
|
||||
WLT_LOG_L0("PoS mining: " << ctx.iterations_processed << " iterations finished (" << std::fixed << std::setprecision(2) << (mining_duration_ms / 1000.0f) << "s), status: " << ctx.status << ", " << ctx.total_items_checked << " entries with total amount: " << print_money_brief(ctx.total_amount_checked));
|
||||
|
||||
return true;
|
||||
return res;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void wallet2::do_pos_mining_prepare_entry(mining_context& context, size_t transfer_index)
|
||||
|
|
@ -5644,7 +5956,7 @@ bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal
|
|||
|
||||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
|
||||
ctp.fake_outputs_count = proposal_detais.mixins;
|
||||
//ctp.fake_outputs_count = proposal_detais.mixins;
|
||||
ctp.fee = proposal_detais.fee_paid_by_a;
|
||||
ctp.flags = TX_FLAG_SIGNATURE_MODE_SEPARATE;
|
||||
ctp.mark_tx_as_complete = false;
|
||||
|
|
@ -5789,10 +6101,10 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo
|
|||
}
|
||||
amounts_provided_by_a[in_asset_id] += amount;
|
||||
|
||||
if (proposal_info.mixins == 0 || proposal_info.mixins > mx)
|
||||
{
|
||||
proposal_info.mixins = mx;
|
||||
}
|
||||
//if (proposal_info.mixins == 0 || proposal_info.mixins > mx)
|
||||
//{
|
||||
// proposal_info.mixins = mx;
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -5991,10 +6303,18 @@ bool wallet2::prepare_tx_sources_for_defragmentation_tx(std::vector<currency::tx
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources(assets_selection_context& needed_money_map, size_t fake_outputs_count, uint64_t dust_threshold, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies)
|
||||
{
|
||||
bool r = select_transfers(needed_money_map, fake_outputs_count, dust_threshold, selected_indicies);
|
||||
if (!r)
|
||||
return r;
|
||||
return prepare_tx_sources(fake_outputs_count, sources, selected_indicies);
|
||||
try
|
||||
{
|
||||
select_transfers(needed_money_map, fake_outputs_count, dust_threshold, selected_indicies); // always returns true, TODO consider refactoring -- sowle
|
||||
return prepare_tx_sources(fake_outputs_count, sources, selected_indicies);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// if smth went wrong -- invalidate transfers cache to trigger its regeneration on the next use
|
||||
// it is necessary because it may be in invalid state (some items might be erased within select_indices_for_transfer() or expand_selection_with_zc_input())
|
||||
m_found_free_amounts.clear();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::prefetch_global_indicies_if_needed(const std::vector<uint64_t>& selected_indicies)
|
||||
|
|
@ -6024,7 +6344,12 @@ void wallet2::prefetch_global_indicies_if_needed(const std::vector<uint64_t>& se
|
|||
}*/
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currency::tx_source_entry>& sources, const std::vector<uint64_t>& selected_indicies)
|
||||
bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, const std::vector<uint64_t>& selected_indicies)
|
||||
{
|
||||
return prepare_tx_sources(fake_outputs_count, false, sources, selected_indicies);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys_if_found_less_than_required, std::vector<currency::tx_source_entry>& sources, const std::vector<uint64_t>& selected_indicies)
|
||||
{
|
||||
typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry;
|
||||
typedef currency::tx_source_entry::output_entry tx_output_entry;
|
||||
|
|
@ -6037,13 +6362,6 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
size_t fake_outputs_count = fake_outputs_count_;
|
||||
uint64_t zarcanum_start_from = m_core_runtime_config.hard_forks.m_height_the_hardfork_n_active_after[ZANO_HARDFORK_04_ZARCANUM];
|
||||
uint64_t current_size = m_chain.get_blockchain_current_size();
|
||||
decoy_selection_generator zarcanum_decoy_set_generator;
|
||||
if (current_size - 1 >= zarcanum_start_from)
|
||||
{
|
||||
//in Zarcanum era
|
||||
//const uint64_t test_scale_size = current_size - 1 - zarcanum_start_from;
|
||||
zarcanum_decoy_set_generator.init(m_last_zc_global_index);
|
||||
}
|
||||
|
||||
bool need_to_request = fake_outputs_count != 0;
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request req = AUTO_VAL_INIT(req);
|
||||
|
|
@ -6069,7 +6387,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
//Zarcanum era
|
||||
rdisttib.amount = 0;
|
||||
//generate distribution in Zarcanum hardfork
|
||||
build_distribution_for_input(zarcanum_decoy_set_generator, rdisttib.global_offsets, it->m_global_output_index);
|
||||
build_distribution_for_input(rdisttib.global_offsets, it->m_global_output_index);
|
||||
need_to_request = true;
|
||||
}
|
||||
else
|
||||
|
|
@ -6109,14 +6427,15 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
|
||||
std::vector<COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount> scanty_outs;
|
||||
THROW_IF_FALSE_WALLET_EX(daemon_resp.outs.size() == req.amounts.size(), error::not_enough_outs_to_mix, scanty_outs, fake_outputs_count);
|
||||
for(size_t i = 0; i != daemon_resp.outs.size(); i++)
|
||||
|
||||
if (!use_all_decoys_if_found_less_than_required)
|
||||
{
|
||||
if (req.amounts[i].amount != 0 && daemon_resp.outs[i].outs.size() != req.amounts[i].global_offsets.size())
|
||||
{
|
||||
scanty_outs.push_back(daemon_resp.outs[i]);
|
||||
}
|
||||
// make sure we have received the requested number of decoys
|
||||
for(size_t i = 0; i != daemon_resp.outs.size(); i++)
|
||||
if (req.amounts[i].amount != 0 && daemon_resp.outs[i].outs.size() != req.amounts[i].global_offsets.size())
|
||||
scanty_outs.push_back(daemon_resp.outs[i]);
|
||||
THROW_IF_FALSE_WALLET_EX(scanty_outs.empty(), error::not_enough_outs_to_mix, scanty_outs, fake_outputs_count);
|
||||
}
|
||||
THROW_IF_FALSE_WALLET_EX(scanty_outs.empty(), error::not_enough_outs_to_mix, scanty_outs, fake_outputs_count);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6287,12 +6606,16 @@ void wallet2::select_decoys(currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS
|
|||
amount_entry.outs = local_outs;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
void wallet2::build_distribution_for_input(decoy_selection_generator& zarcanum_decoy_set_generator, std::vector<uint64_t>& offsets, uint64_t own_index)
|
||||
void wallet2::build_distribution_for_input(std::vector<uint64_t>& offsets, uint64_t own_index)
|
||||
{
|
||||
decoy_selection_generator zarcanum_decoy_set_generator;
|
||||
zarcanum_decoy_set_generator.init(get_actual_zc_global_index());
|
||||
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(zarcanum_decoy_set_generator.is_initialized(), "zarcanum_decoy_set_generator are not initialized");
|
||||
if (m_core_runtime_config.hf4_minimum_mixins)
|
||||
{
|
||||
offsets = zarcanum_decoy_set_generator.generate_unique_reversed_distribution(m_last_zc_global_index - 1 > WALLET_FETCH_RANDOM_OUTS_SIZE ? WALLET_FETCH_RANDOM_OUTS_SIZE: m_last_zc_global_index - 1, own_index);
|
||||
uint64_t actual_zc_index = get_actual_zc_global_index();
|
||||
offsets = zarcanum_decoy_set_generator.generate_unique_reversed_distribution(actual_zc_index - 1 > WALLET_FETCH_RANDOM_OUTS_SIZE ? WALLET_FETCH_RANDOM_OUTS_SIZE : actual_zc_index - 1, own_index);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -6709,8 +7032,6 @@ bool wallet2::expand_selection_with_zc_input(assets_selection_context& needed_mo
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money_map, uint64_t fake_outputs_count, std::vector<uint64_t>& selected_indexes)
|
||||
{
|
||||
bool res = true;
|
||||
//
|
||||
for (auto& item : needed_money_map)
|
||||
{
|
||||
if(item.second.needed_amount == 0)
|
||||
|
|
@ -6737,8 +7058,7 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_indexes, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count_)
|
||||
|
|
@ -6777,7 +7097,7 @@ uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_in
|
|||
return found_money;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::is_transfer_ready_to_go(const transfer_details& td, uint64_t fake_outputs_count)
|
||||
bool wallet2::is_transfer_ready_to_go(const transfer_details& td, uint64_t fake_outputs_count) const
|
||||
{
|
||||
if (is_transfer_able_to_go(td, fake_outputs_count) && is_transfer_unlocked(td))
|
||||
{
|
||||
|
|
@ -6786,7 +7106,7 @@ bool wallet2::is_transfer_ready_to_go(const transfer_details& td, uint64_t fake_
|
|||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::is_transfer_able_to_go(const transfer_details& td, uint64_t fake_outputs_count)
|
||||
bool wallet2::is_transfer_able_to_go(const transfer_details& td, uint64_t fake_outputs_count) const
|
||||
{
|
||||
if (!td.is_spendable())
|
||||
return false;
|
||||
|
|
@ -6854,7 +7174,7 @@ void wallet2::add_transfer_to_transfers_cache(uint64_t amount, uint64_t index, c
|
|||
m_found_free_amounts[asset_id][amount].insert(index);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::select_transfers(assets_selection_context& needed_money_map, size_t fake_outputs_count, uint64_t dust, std::vector<uint64_t>& selected_indicies)
|
||||
bool wallet2::select_transfers(assets_selection_context& needed_money_map, size_t fake_outputs_count, uint64_t /*dust_threshold*/, std::vector<uint64_t>& selected_indicies)
|
||||
{
|
||||
prepare_free_transfers_cache(fake_outputs_count);
|
||||
return select_indices_for_transfer(needed_money_map, fake_outputs_count, selected_indicies);
|
||||
|
|
@ -7092,7 +7412,7 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money,
|
|||
const crypto::public_key& asset_id,
|
||||
std::vector<currency::tx_destination_entry>& final_destinations)
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(found_money >= needed_money, "needed_money==" << needed_money << " < found_money==" << found_money);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(found_money >= needed_money, "found_money = " << print_money_brief(found_money) << " is less than needed_money = " << print_money_brief(needed_money) << ", assed_id: " << asset_id);
|
||||
|
||||
if (is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM))
|
||||
{
|
||||
|
|
@ -7244,10 +7564,6 @@ void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::f
|
|||
// broadcasting tx without secret key storing is forbidden to avoid lost key issues
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(!broadcast_tx || store_tx_secret_key, "finalize_tx is requested to broadcast a tx without storing the key");
|
||||
|
||||
//overide mixins count for hardfork 4 outputs
|
||||
if (is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM))
|
||||
ftp.tx_outs_attr = m_core_runtime_config.hf4_minimum_mixins;
|
||||
|
||||
bool r = currency::construct_tx(m_account.get_keys(),
|
||||
ftp, result);
|
||||
//TIME_MEASURE_FINISH_MS(construct_tx_time);
|
||||
|
|
|
|||
|
|
@ -148,9 +148,7 @@ namespace tools
|
|||
std::unordered_map<crypto::public_key, crypto::key_image> m_pending_key_images; // (out_pk -> ki) pairs of change outputs to be added in watch-only wallet without spend sec key
|
||||
uint64_t m_last_pow_block_h = 0;
|
||||
std::list<std::pair<uint64_t, wallet_event_t>> m_rollback_events;
|
||||
uint64_t m_last_zc_global_index = 0;
|
||||
|
||||
|
||||
std::list<std::pair<uint64_t, uint64_t> > m_last_zc_global_indexs; // <height, last_zc_global_indexs>, biggest height comes in front
|
||||
|
||||
//variables that not being serialized
|
||||
std::atomic<uint64_t> m_last_bc_timestamp = 0;
|
||||
|
|
@ -158,8 +156,10 @@ namespace tools
|
|||
std::atomic<uint64_t> m_last_sync_percent = 0;
|
||||
mutable uint64_t m_current_wallet_file_size = 0;
|
||||
bool m_use_assets_whitelisting = true;
|
||||
mutable std::optional<bool> m_has_bare_unspent_outputs; // recalculated each time the balance() is called
|
||||
|
||||
|
||||
// variables that should be part of state data object but should not be stored during serialization
|
||||
mutable std::atomic<bool> m_whitelist_updated = false;
|
||||
//===============================================================
|
||||
template <class t_archive>
|
||||
inline void serialize(t_archive &a, const unsigned int ver)
|
||||
|
|
@ -222,7 +222,19 @@ namespace tools
|
|||
a & m_rollback_events;
|
||||
a & m_whitelisted_assets;
|
||||
a & m_use_assets_whitelisting;
|
||||
a & m_last_zc_global_index;
|
||||
if (ver <= 165)
|
||||
{
|
||||
uint64_t last_zc_global_index = 0;
|
||||
a& last_zc_global_index;
|
||||
m_last_zc_global_indexs.push_back(std::make_pair(uint64_t(0), last_zc_global_index));
|
||||
return;
|
||||
}
|
||||
a& m_last_zc_global_indexs;
|
||||
if (ver == 166 && m_last_zc_global_indexs.size())
|
||||
{
|
||||
//workaround for m_last_zc_global_indexs holding invalid index for last item
|
||||
m_last_zc_global_indexs.pop_front();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -232,6 +244,7 @@ namespace tools
|
|||
wallet2(const wallet2&) = delete;
|
||||
public:
|
||||
wallet2();
|
||||
virtual ~wallet2() {}
|
||||
|
||||
static std::string transfer_flags_to_str(uint32_t flags);
|
||||
|
||||
|
|
@ -342,6 +355,13 @@ namespace tools
|
|||
mutable crypto::hash tx_hash_ = currency::null_hash;
|
||||
};
|
||||
|
||||
struct batch_of_bare_unspent_outs
|
||||
{
|
||||
std::vector<uint64_t> tids;
|
||||
uint64_t total_amount = 0;
|
||||
bool additional_tid = false; // additional zc transfer if total_amount < min fee
|
||||
uint64_t additional_tid_amount = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
@ -377,6 +397,12 @@ namespace tools
|
|||
void set_do_rise_transfer(bool do_rise) { m_do_rise_transfer = do_rise; }
|
||||
|
||||
bool has_related_alias_entry_unconfirmed(const currency::transaction& tx);
|
||||
bool has_bare_unspent_outputs() const;
|
||||
bool get_bare_unspent_outputs_stats(std::vector<batch_of_bare_unspent_outs>& buo_txs) const;
|
||||
bool sweep_bare_unspent_outputs(const currency::account_public_address& target_address, const std::vector<batch_of_bare_unspent_outs>& tids_grouped_by_txs,
|
||||
std::function<void(size_t batch_index, const currency::transaction& tx, uint64_t amount, uint64_t fee, bool sent_ok, const std::string& err)> on_tx_sent);
|
||||
bool sweep_bare_unspent_outputs(const currency::account_public_address& target_address, const std::vector<batch_of_bare_unspent_outs>& tids_grouped_by_txs,
|
||||
size_t& total_txs_sent, uint64_t& total_amount_sent, uint64_t& total_fee, uint64_t& total_bare_outs_sent);
|
||||
void handle_unconfirmed_tx(process_transaction_context& ptc);
|
||||
void scan_tx_pool(bool& has_related_alias_in_unconfirmed);
|
||||
void refresh();
|
||||
|
|
@ -400,7 +426,6 @@ namespace tools
|
|||
void transfer_asset_ownership(const crypto::public_key asset_id, const crypto::public_key& new_owner, currency::transaction& result_tx);
|
||||
|
||||
bool daemon_get_asset_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& adb);
|
||||
const std::unordered_map<crypto::public_key, wallet_own_asset_context>& get_own_assets() const { return m_own_asset_descriptors; }
|
||||
bool set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy);
|
||||
void set_defragmentation_tx_settings(bool enabled, uint64_t min_outs, uint64_t max_outs, uint64_t max_allowed_amount = CURRENCY_BLOCK_REWARD, size_t decoys_count = SIZE_MAX);
|
||||
void set_pos_required_decoys_count(size_t v) { m_required_decoys_count = v; }
|
||||
|
|
@ -540,6 +565,7 @@ namespace tools
|
|||
void get_transfers(transfer_container& incoming_transfers) const;
|
||||
std::string get_transfers_str(bool include_spent = true, bool include_unspent = true, bool show_only_unknown = false, const std::string& filter_asset_ticker = std::string{}) const;
|
||||
std::string get_balance_str() const;
|
||||
std::string get_balance_str_raw() const;
|
||||
|
||||
// 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;
|
||||
|
|
@ -576,8 +602,8 @@ namespace tools
|
|||
wallet2_base_state::serialize(a, ver);
|
||||
}
|
||||
|
||||
bool is_transfer_ready_to_go(const transfer_details& td, uint64_t fake_outputs_count);
|
||||
bool is_transfer_able_to_go(const transfer_details& td, uint64_t fake_outputs_count);
|
||||
bool is_transfer_ready_to_go(const transfer_details& td, uint64_t fake_outputs_count) const;
|
||||
bool is_transfer_able_to_go(const transfer_details& td, uint64_t fake_outputs_count) const;
|
||||
uint64_t select_indices_for_transfer(std::vector<uint64_t>& ind, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count);
|
||||
bool select_indices_for_transfer(assets_selection_context& needed_money_map, uint64_t fake_outputs_count, std::vector<uint64_t>& selected_indexes);
|
||||
|
||||
|
|
@ -660,6 +686,10 @@ namespace tools
|
|||
|
||||
bool add_custom_asset_id(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_descriptor);
|
||||
bool delete_custom_asset_id(const crypto::public_key& asset_id);
|
||||
const std::unordered_map<crypto::public_key, currency::asset_descriptor_base>& get_local_whitelist() const;
|
||||
const std::unordered_map<crypto::public_key, currency::asset_descriptor_base>& get_global_whitelist() const;
|
||||
const std::unordered_map<crypto::public_key, tools::wallet_own_asset_context>& get_own_assets() const;
|
||||
|
||||
bool load_whitelisted_tokens_if_not_loaded() const;
|
||||
bool load_whitelisted_tokens() const;
|
||||
|
||||
|
|
@ -696,6 +726,8 @@ namespace tools
|
|||
bool encrypt_buffer(const std::string& buff, std::string& res_buff);
|
||||
bool decrypt_buffer(const std::string& buff, std::string& res_buff);
|
||||
bool is_in_hardfork_zone(uint64_t hardfork_index) const;
|
||||
//performance inefficient call, suitable only for rare ocasions or super lazy developers
|
||||
bool proxy_to_daemon(const std::string& uri, const std::string& body, int& response_code, std::string& response_body);
|
||||
|
||||
construct_tx_param get_default_construct_tx_param();
|
||||
|
||||
|
|
@ -748,7 +780,8 @@ private:
|
|||
void handle_money(const currency::block& b, const process_transaction_context& tx_process_context);
|
||||
void load_wti_from_process_transaction_context(wallet_public::wallet_transfer_info& wti, const process_transaction_context& tx_process_context);
|
||||
bool process_payment_id_for_wti(wallet_public::wallet_transfer_info& wti, const process_transaction_context& tx_process_context);
|
||||
|
||||
void add_to_last_zc_global_indexs(uint64_t h, uint64_t last_zc_output_index);
|
||||
uint64_t get_actual_zc_global_index();
|
||||
void handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop,
|
||||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks);
|
||||
std::string get_alias_for_address(const std::string& addr);
|
||||
|
|
@ -762,6 +795,7 @@ private:
|
|||
bool build_escrow_proposal(bc_services::contract_private_details& ecrow_details, uint64_t fee, uint64_t unlock_time, currency::tx_service_attachment& att, std::vector<uint64_t>& selected_indicies);
|
||||
bool prepare_tx_sources(assets_selection_context& needed_money_map, size_t fake_outputs_count, uint64_t dust_threshold, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies);
|
||||
bool prepare_tx_sources(size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, const std::vector<uint64_t>& selected_indicies);
|
||||
bool prepare_tx_sources(size_t fake_outputs_count, bool use_all_decoys_if_found_less_than_required, std::vector<currency::tx_source_entry>& sources, const std::vector<uint64_t>& selected_indicies);
|
||||
bool prepare_tx_sources(crypto::hash multisig_id, std::vector<currency::tx_source_entry>& sources, uint64_t& found_money);
|
||||
bool prepare_tx_sources_htlc(crypto::hash htlc_tx_id, const std::string& origin, std::vector<currency::tx_source_entry>& sources, uint64_t& found_money);
|
||||
bool prepare_tx_sources_for_defragmentation_tx(std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money);
|
||||
|
|
@ -854,7 +888,7 @@ private:
|
|||
void remove_transfer_from_amount_gindex_map(uint64_t tid);
|
||||
uint64_t get_alias_cost(const std::string& alias);
|
||||
detail::split_strategy_id_t get_current_split_strategy();
|
||||
void build_distribution_for_input(decoy_selection_generator& zarcanum_decoy_set_generator, std::vector<uint64_t>& offsets, uint64_t own_index);
|
||||
void build_distribution_for_input(std::vector<uint64_t>& offsets, uint64_t own_index);
|
||||
void select_decoys(currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount & amount_entry, uint64_t own_g_index);
|
||||
|
||||
static void wti_to_csv_entry(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index);
|
||||
|
|
@ -895,7 +929,6 @@ private:
|
|||
uint64_t m_upper_transaction_size_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value
|
||||
|
||||
std::atomic<bool> m_stop;
|
||||
mutable std::atomic<bool> m_whitelist_updated = false;
|
||||
std::shared_ptr<i_core_proxy> m_core_proxy;
|
||||
std::shared_ptr<i_wallet2_callback> m_wcallback;
|
||||
|
||||
|
|
@ -1076,7 +1109,6 @@ namespace tools
|
|||
ts_middle -= ts_middle % POS_SCAN_STEP;
|
||||
uint64_t ts_window = std::min(ts_middle - ts_from, ts_to - ts_middle);
|
||||
|
||||
size_t pos_entry_index = 0;
|
||||
for (size_t transfer_index = 0; transfer_index != m_transfers.size(); transfer_index++)
|
||||
{
|
||||
auto& tr = m_transfers[transfer_index];
|
||||
|
|
@ -1144,7 +1176,6 @@ namespace tools
|
|||
|
||||
next_turn();
|
||||
}
|
||||
++pos_entry_index;
|
||||
}
|
||||
cxt.status = API_RETURN_CODE_NOT_FOUND;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -251,19 +251,18 @@ namespace tools
|
|||
crypto::public_key asset_id = currency::null_pkey;
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(asset_id)
|
||||
END_BOOST_SERIALIZATION()
|
||||
END_BOOST_SERIALIZATION()
|
||||
|
||||
};
|
||||
|
||||
struct wallet_own_asset_context
|
||||
struct wallet_own_asset_context: public currency::asset_descriptor_base
|
||||
{
|
||||
currency::asset_descriptor_base asset_descriptor;
|
||||
bool thirdparty_custody = false;
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(asset_descriptor)
|
||||
BOOST_SERIALIZE_BASE_CLASS(currency::asset_descriptor_base)
|
||||
BOOST_SERIALIZE(thirdparty_custody)
|
||||
END_BOOST_SERIALIZATION()
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct asset_update_event
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ namespace tools
|
|||
wi.path = epee::string_encoding::wstring_to_utf8(w.get_wallet_path());
|
||||
wi.is_auditable = w.is_auditable();
|
||||
wi.is_watch_only = w.is_watch_only();
|
||||
wi.has_bare_unspent_outputs = w.has_bare_unspent_outputs();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -37,21 +38,40 @@ namespace tools
|
|||
result.hash_sum_matched = false;
|
||||
result.syntax_correct = acc.restore_from_tracking_seed(seed_phrase);
|
||||
if (result.syntax_correct)
|
||||
{
|
||||
result.tracking = true;
|
||||
result.address = acc.get_public_address_str();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.syntax_correct = currency::account_base::is_seed_password_protected(seed_phrase, result.require_password);
|
||||
if (result.syntax_correct && result.require_password)
|
||||
if (result.syntax_correct )
|
||||
{
|
||||
if (seed_password.size())
|
||||
if (result.require_password)
|
||||
{
|
||||
currency::account_base acc;
|
||||
result.hash_sum_matched = acc.restore_from_seed_phrase(seed_phrase, seed_password);
|
||||
if (seed_password.size())
|
||||
{
|
||||
currency::account_base acc;
|
||||
result.hash_sum_matched = acc.restore_from_seed_phrase(seed_phrase, seed_password);
|
||||
if (result.hash_sum_matched)
|
||||
{
|
||||
result.address = acc.get_public_address_str();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.hash_sum_matched = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.hash_sum_matched = false;
|
||||
currency::account_base acc;
|
||||
result.syntax_correct = acc.restore_from_seed_phrase(seed_phrase, "");
|
||||
if (result.syntax_correct)
|
||||
{
|
||||
result.address = acc.get_public_address_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -17,6 +17,19 @@ using namespace epee;
|
|||
#include "wallet_rpc_server_error_codes.h"
|
||||
#include "wallet_helpers.h"
|
||||
#include "wrap_service.h"
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4244)
|
||||
#include "jwt-cpp/jwt.h"
|
||||
POP_VS_WARNINGS
|
||||
#include "crypto/bitcoin/sha256_helper.h"
|
||||
|
||||
#define JWT_TOKEN_EXPIRATION_MAXIMUM (60 * 60)
|
||||
#define JWT_TOKEN_CLAIM_NAME_BODY_HASH "body_hash"
|
||||
#define JWT_TOKEN_CLAIM_NAME_SALT "salt"
|
||||
#define JWT_TOKEN_CLAIM_NAME_EXPIRATION "exp"
|
||||
#define JWT_TOKEN_OVERWHELM_LIMIT 100000 // if there are more records in m_jwt_used_salts then we consider it as an attack
|
||||
|
||||
|
||||
|
||||
#define GET_WALLET() wallet_rpc_locker w(m_pwallet_provider);
|
||||
|
||||
|
|
@ -37,7 +50,7 @@ using namespace epee;
|
|||
catch (const tools::error::wallet_error& e) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; \
|
||||
er.message = std::string("WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR") + e.error_code(); \
|
||||
er.message = e.error_code(); \
|
||||
return false; \
|
||||
} \
|
||||
catch (const std::exception& e) \
|
||||
|
|
@ -53,6 +66,10 @@ using namespace epee;
|
|||
return false; \
|
||||
}
|
||||
|
||||
|
||||
void exception_handler()
|
||||
{}
|
||||
|
||||
namespace tools
|
||||
{
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
|
@ -60,6 +77,7 @@ namespace tools
|
|||
const command_line::arg_descriptor<std::string> wallet_rpc_server::arg_rpc_bind_ip ("rpc-bind-ip", "Specify ip to bind rpc server", "127.0.0.1");
|
||||
const command_line::arg_descriptor<std::string> wallet_rpc_server::arg_miner_text_info ( "miner-text-info", "Wallet password");
|
||||
const command_line::arg_descriptor<bool> wallet_rpc_server::arg_deaf_mode ( "deaf", "Put wallet into 'deaf' mode make it ignore any rpc commands(usable for safe PoS mining)");
|
||||
const command_line::arg_descriptor<std::string> wallet_rpc_server::arg_jwt_secret("jwt-secret", "Enables JWT auth over secret string provided");
|
||||
|
||||
void wallet_rpc_server::init_options(boost::program_options::options_description& desc)
|
||||
{
|
||||
|
|
@ -67,6 +85,7 @@ namespace tools
|
|||
command_line::add_arg(desc, arg_rpc_bind_port);
|
||||
command_line::add_arg(desc, arg_miner_text_info);
|
||||
command_line::add_arg(desc, arg_deaf_mode);
|
||||
command_line::add_arg(desc, arg_jwt_secret);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
wallet_rpc_server::wallet_rpc_server(std::shared_ptr<wallet2> wptr):
|
||||
|
|
@ -184,11 +203,81 @@ namespace tools
|
|||
m_net_server.set_threads_prefix("RPC");
|
||||
bool r = handle_command_line(vm);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server");
|
||||
|
||||
|
||||
if(command_line::has_arg(vm, arg_jwt_secret))
|
||||
{
|
||||
m_jwt_secret = command_line::get_arg(vm, arg_jwt_secret);
|
||||
}
|
||||
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(m_port, m_bind_ip);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::auth_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)
|
||||
{
|
||||
|
||||
auto it = std::find_if(query_info.m_header_info.m_etc_fields.begin(), query_info.m_header_info.m_etc_fields.end(), [](const auto& element)
|
||||
{ return element.first == ZANO_ACCESS_TOKEN; });
|
||||
if(it == query_info.m_header_info.m_etc_fields.end())
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
if(m_jwt_used_salts.get_set().size() > JWT_TOKEN_OVERWHELM_LIMIT)
|
||||
{
|
||||
throw std::runtime_error("Salt is overwhelmed");
|
||||
}
|
||||
|
||||
auto decoded = jwt::decode(it->second, [](const std::string& str)
|
||||
{ return jwt::base::decode<jwt::alphabet::base64>(jwt::base::pad<jwt::alphabet::base64>(str)); });
|
||||
|
||||
|
||||
auto verifier = jwt::verify().allow_algorithm(jwt::algorithm::hs256 { m_jwt_secret });
|
||||
|
||||
verifier.verify(decoded);
|
||||
std::string body_hash = decoded.get_payload_claim(JWT_TOKEN_CLAIM_NAME_BODY_HASH).as_string();
|
||||
std::string salt = decoded.get_payload_claim(JWT_TOKEN_CLAIM_NAME_SALT).as_string();
|
||||
crypto::hash jwt_claim_sha256 = currency::null_hash;
|
||||
epee::string_tools::hex_to_pod(body_hash, jwt_claim_sha256);
|
||||
crypto::hash sha256 = crypto::sha256_hash(query_info.m_body.data(), query_info.m_body.size());
|
||||
if (sha256 != jwt_claim_sha256)
|
||||
{
|
||||
throw std::runtime_error("Body hash missmatch");
|
||||
}
|
||||
if(m_jwt_used_salts.get_set().find(salt) != m_jwt_used_salts.get_set().end())
|
||||
{
|
||||
throw std::runtime_error("Salt reused");
|
||||
}
|
||||
|
||||
uint64_t ticks_now = epee::misc_utils::get_tick_count();
|
||||
m_jwt_used_salts.add(salt, ticks_now + JWT_TOKEN_EXPIRATION_MAXIMUM);
|
||||
m_jwt_used_salts.remove_if_expiration_less_than(ticks_now);
|
||||
|
||||
LOG_PRINT_L0("JWT token OK");
|
||||
return true;
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
LOG_ERROR("Invalid JWT token: " << e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::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)
|
||||
{
|
||||
if (m_jwt_secret.size() && m_conn_context.m_connection_id != RPC_INTERNAL_UI_CONTEXT)
|
||||
{
|
||||
if (!auth_http_request(query_info, response, m_conn_context))
|
||||
{
|
||||
response.m_response_code = 401;
|
||||
response.m_response_comment = "Unauthorized";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
response.m_response_code = 200;
|
||||
response.m_response_comment = "Ok";
|
||||
std::string reference_stub;
|
||||
|
|
@ -199,7 +288,7 @@ namespace tools
|
|||
response.m_response_comment = "Internal Server Error";
|
||||
return true;
|
||||
}
|
||||
if (!handle_http_request_map(query_info, response, m_conn_context, call_found, reference_stub) && response.m_response_code == 200)
|
||||
if (!handle_http_request_map(query_info, response, m_conn_context, call_found) && response.m_response_code == 200)
|
||||
{
|
||||
response.m_response_code = 500;
|
||||
response.m_response_comment = "Internal Server Error";
|
||||
|
|
@ -214,6 +303,16 @@ namespace tools
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
void wallet_rpc_server::set_jwt_secret(const std::string& jwt)
|
||||
{
|
||||
m_jwt_secret = jwt;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
const std::string& wallet_rpc_server::get_jwt_secret()
|
||||
{
|
||||
return m_jwt_secret;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::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)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
@ -256,6 +355,7 @@ namespace tools
|
|||
res.utxo_distribution.push_back(currency::print_money_brief(ent.first) + ":" + std::to_string(ent.second));
|
||||
|
||||
res.current_height = w.get_wallet()->get_top_block_height();
|
||||
res.has_bare_unspent_outputs = w.get_wallet()->has_bare_unspent_outputs();
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
|
|
@ -325,7 +425,7 @@ namespace tools
|
|||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
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)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
@ -357,6 +457,7 @@ namespace tools
|
|||
}
|
||||
bool wrap = false;
|
||||
std::vector<currency::tx_destination_entry>& dsts = ctp.dsts;
|
||||
|
||||
for (auto it = req.destinations.begin(); it != req.destinations.end(); it++)
|
||||
{
|
||||
currency::tx_destination_entry de;
|
||||
|
|
@ -657,6 +758,78 @@ namespace tools
|
|||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_get_bare_outs_stats(const wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS ::request& req, wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
||||
if (w.get_wallet()->is_watch_only())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "operation cannot be performed in watch-only wallet";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<tools::wallet2::batch_of_bare_unspent_outs> groups;
|
||||
if (!w.get_wallet()->get_bare_unspent_outputs_stats(groups))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "get_bare_unspent_outputs_stats failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
res.total_amount = 0;
|
||||
res.total_bare_outs = 0;
|
||||
res.expected_total_fee = 0;
|
||||
res.txs_count = 0;
|
||||
|
||||
for(auto &g : groups)
|
||||
{
|
||||
for (auto& tid: g.tids)
|
||||
{
|
||||
tools::transfer_details td{};
|
||||
CHECK_AND_ASSERT_THROW_MES(w.get_wallet()->get_transfer_info_by_index(tid, td), "get_transfer_info_by_index failed with index " << tid);
|
||||
res.total_amount += td.m_amount;
|
||||
}
|
||||
++res.txs_count;
|
||||
res.total_bare_outs += g.tids.size();
|
||||
res.expected_total_fee += TX_DEFAULT_FEE;
|
||||
}
|
||||
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_sweep_bare_outs(const wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS::request& req, wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
||||
if (w.get_wallet()->is_watch_only())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "operation cannot be performed in watch-only wallet";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<tools::wallet2::batch_of_bare_unspent_outs> groups;
|
||||
if (!w.get_wallet()->get_bare_unspent_outputs_stats(groups))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "get_bare_unspent_outputs_stats failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
res.amount_swept = 0;
|
||||
res.bare_outs_swept = 0;
|
||||
res.fee_spent = 0;
|
||||
|
||||
size_t txs_sent = 0;
|
||||
w.get_wallet()->sweep_bare_unspent_outputs(w.get_wallet()->get_account().get_public_address(), groups, txs_sent, res.amount_swept, res.fee_spent, res.bare_outs_swept);
|
||||
res.txs_sent = txs_sent;
|
||||
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::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)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
@ -1018,6 +1191,106 @@ namespace tools
|
|||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_assets_whitelist_get(const wallet_public::COMMAND_ASSETS_WHITELIST_GET::request& req, wallet_public::COMMAND_ASSETS_WHITELIST_GET::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
||||
currency::assets_map_to_assets_list(res.local_whitelist, w.get_wallet()->get_local_whitelist());
|
||||
currency::assets_map_to_assets_list(res.global_whitelist, w.get_wallet()->get_global_whitelist());
|
||||
currency::assets_map_to_assets_list(res.own_assets, w.get_wallet()->get_own_assets());
|
||||
|
||||
const auto global_whitelist = w.get_wallet()->get_global_whitelist();
|
||||
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_assets_whitelist_add(const wallet_public::COMMAND_ASSETS_WHITELIST_ADD::request& req, wallet_public::COMMAND_ASSETS_WHITELIST_ADD::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
if(!w.get_wallet()->add_custom_asset_id(req.asset_id, res.asset_descriptor))
|
||||
{
|
||||
res.status = API_RETURN_CODE_NOT_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status = API_RETURN_CODE_OK;
|
||||
}
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_assets_whitelist_remove(const wallet_public::COMMAND_ASSETS_WHITELIST_REMOVE::request& req, wallet_public::COMMAND_ASSETS_WHITELIST_REMOVE::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
if(!w.get_wallet()->delete_custom_asset_id(req.asset_id))
|
||||
{
|
||||
res.status = API_RETURN_CODE_NOT_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status = API_RETURN_CODE_OK;
|
||||
}
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
void wallet_rpc_server::rpc_destinations_to_currency_destination(const std::list<wallet_public::transfer_destination>& rpc_destinations, std::vector<currency::tx_destination_entry>& currency_destinations)
|
||||
{
|
||||
GET_WALLET();
|
||||
std::vector<currency::tx_destination_entry>& dsts = currency_destinations;
|
||||
for (auto it = rpc_destinations.begin(); it != rpc_destinations.end(); it++)
|
||||
{
|
||||
currency::tx_destination_entry de;
|
||||
de.addr.resize(1);
|
||||
std::string embedded_payment_id;
|
||||
//check if address looks like wrapped address
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(!currency::is_address_like_wrapped(it->address), "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS", "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS");
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(!w.get_wallet()->get_transfer_address(it->address, de.addr.back(), embedded_payment_id), "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS", "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS");
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(embedded_payment_id.size() == 0, "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS", "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS");
|
||||
de.amount = it->amount;
|
||||
de.asset_id = it->asset_id;
|
||||
dsts.push_back(de);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_assets_deploy(const wallet_public::COMMAND_ASSETS_DEPLOY::request& req, wallet_public::COMMAND_ASSETS_DEPLOY::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction result_tx;
|
||||
std::vector<currency::tx_destination_entry> currency_destinations;
|
||||
rpc_destinations_to_currency_destination(req.destinations, currency_destinations);
|
||||
w.get_wallet()->deploy_new_asset(req.asset_descriptor, currency_destinations, result_tx, res.new_asset_id);
|
||||
res.result_tx = currency::get_transaction_hash(result_tx);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_assets_emit(const wallet_public::COMMAND_ASSETS_EMIT::request& req, wallet_public::COMMAND_ASSETS_EMIT::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction result_tx;
|
||||
std::vector<currency::tx_destination_entry> currency_destinations;
|
||||
rpc_destinations_to_currency_destination(req.destinations, currency_destinations);
|
||||
|
||||
w.get_wallet()->emit_asset(req.asset_id, currency_destinations, result_tx);
|
||||
res.result_tx = currency::get_transaction_hash(result_tx);
|
||||
return true;
|
||||
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_assets_update(const wallet_public::COMMAND_ASSETS_UPDATE::request& req, wallet_public::COMMAND_ASSETS_UPDATE::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction result_tx;
|
||||
w.get_wallet()->update_asset(req.asset_id, req.asset_descriptor, result_tx);
|
||||
res.result_tx = currency::get_transaction_hash(result_tx);
|
||||
return true;
|
||||
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_mw_get_wallets(const wallet_public::COMMAND_MW_GET_WALLETS::request& req, wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
@ -1068,6 +1341,18 @@ namespace tools
|
|||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_proxy_to_daemon(const wallet_public::COMMAND_PROXY_TO_DAEMON::request& req, wallet_public::COMMAND_PROXY_TO_DAEMON::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
std::string buff = epee::string_encoding::base64_decode(req.base64_body);
|
||||
|
||||
w.get_wallet()->proxy_to_daemon(req.uri, buff, res.response_code, res.base64_body);
|
||||
|
||||
res.base64_body = epee::string_encoding::base64_encode(res.base64_body);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_decrypt_data(const wallet_public::COMMAND_DECRYPT_DATA::request& req, wallet_public::COMMAND_DECRYPT_DATA::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@
|
|||
#include "wallet_public_structs_defs.h"
|
||||
#include "wallet2.h"
|
||||
#include "common/command_line.h"
|
||||
|
||||
#define ZANO_ACCESS_TOKEN "Zano-Access-Token"
|
||||
|
||||
namespace tools
|
||||
{
|
||||
|
||||
|
||||
|
||||
struct i_wallet_provider
|
||||
{
|
||||
virtual void lock() {};
|
||||
|
|
@ -82,12 +82,15 @@ namespace tools
|
|||
const static command_line::arg_descriptor<std::string> arg_rpc_bind_ip;
|
||||
const static command_line::arg_descriptor<std::string> arg_miner_text_info;
|
||||
const static command_line::arg_descriptor<bool> arg_deaf_mode;
|
||||
const static command_line::arg_descriptor<std::string> arg_jwt_secret;
|
||||
|
||||
|
||||
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);
|
||||
void set_jwt_secret(const std::string& jwt);
|
||||
const std::string& get_jwt_secret();
|
||||
|
||||
BEGIN_URI_MAP2_VIRTUAL()
|
||||
BEGIN_JSON_RPC_MAP("/json_rpc")
|
||||
|
|
@ -103,6 +106,8 @@ namespace tools
|
|||
MAP_JON_RPC_WE("make_integrated_address", on_make_integrated_address, wallet_public::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS)
|
||||
MAP_JON_RPC_WE("split_integrated_address", on_split_integrated_address, wallet_public::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS)
|
||||
MAP_JON_RPC_WE("sweep_below", on_sweep_below, wallet_public::COMMAND_SWEEP_BELOW)
|
||||
MAP_JON_RPC_WE("get_bare_outs_stats", on_get_bare_outs_stats, wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS)
|
||||
MAP_JON_RPC_WE("sweep_bare_outs", on_sweep_bare_outs, wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS)
|
||||
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)
|
||||
MAP_JON_RPC_WE("search_for_transactions", on_search_for_transactions, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY)
|
||||
|
|
@ -112,39 +117,52 @@ namespace tools
|
|||
MAP_JON_RPC_WE("get_mining_history", on_get_mining_history, wallet_public::COMMAND_RPC_GET_MINING_HISTORY)
|
||||
MAP_JON_RPC_WE("register_alias", on_register_alias, wallet_public::COMMAND_RPC_REGISTER_ALIAS)
|
||||
//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)
|
||||
MAP_JON_RPC_WE("contracts_release", on_contracts_release, wallet_public::COMMAND_CONTRACTS_RELEASE)
|
||||
MAP_JON_RPC_WE("contracts_request_cancel", on_contracts_request_cancel, wallet_public::COMMAND_CONTRACTS_REQUEST_CANCEL)
|
||||
MAP_JON_RPC_WE("contracts_accept_cancel", on_contracts_accept_cancel, wallet_public::COMMAND_CONTRACTS_ACCEPT_CANCEL)
|
||||
//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)
|
||||
//MAP_JON_RPC_WE("contracts_release", on_contracts_release, wallet_public::COMMAND_CONTRACTS_RELEASE)
|
||||
//MAP_JON_RPC_WE("contracts_request_cancel", on_contracts_request_cancel, wallet_public::COMMAND_CONTRACTS_REQUEST_CANCEL)
|
||||
//MAP_JON_RPC_WE("contracts_accept_cancel", on_contracts_accept_cancel, wallet_public::COMMAND_CONTRACTS_ACCEPT_CANCEL)
|
||||
//marketplace API
|
||||
MAP_JON_RPC_WE("marketplace_get_offers_ex", on_marketplace_get_my_offers, wallet_public::COMMAND_MARKETPLACE_GET_MY_OFFERS)
|
||||
MAP_JON_RPC_WE("marketplace_push_offer", on_marketplace_push_offer, wallet_public::COMMAND_MARKETPLACE_PUSH_OFFER)
|
||||
MAP_JON_RPC_WE("marketplace_push_update_offer", on_marketplace_push_update_offer, wallet_public::COMMAND_MARKETPLACE_PUSH_UPDATE_OFFER)
|
||||
MAP_JON_RPC_WE("marketplace_cancel_offer", on_marketplace_cancel_offer, wallet_public::COMMAND_MARKETPLACE_CANCEL_OFFER)
|
||||
//HTLC API
|
||||
MAP_JON_RPC_WE("atomics_create_htlc_proposal", on_create_htlc_proposal, wallet_public::COMMAND_CREATE_HTLC_PROPOSAL)
|
||||
MAP_JON_RPC_WE("atomics_get_list_of_active_htlc", on_get_list_of_active_htlc, wallet_public::COMMAND_GET_LIST_OF_ACTIVE_HTLC)
|
||||
MAP_JON_RPC_WE("atomics_redeem_htlc", on_redeem_htlc, wallet_public::COMMAND_REDEEM_HTLC)
|
||||
MAP_JON_RPC_WE("atomics_check_htlc_redeemed", on_check_htlc_redeemed, wallet_public::COMMAND_CHECK_HTLC_REDEEMED)
|
||||
//MAP_JON_RPC_WE("atomics_create_htlc_proposal", on_create_htlc_proposal, wallet_public::COMMAND_CREATE_HTLC_PROPOSAL)
|
||||
//MAP_JON_RPC_WE("atomics_get_list_of_active_htlc", on_get_list_of_active_htlc, wallet_public::COMMAND_GET_LIST_OF_ACTIVE_HTLC)
|
||||
//MAP_JON_RPC_WE("atomics_redeem_htlc", on_redeem_htlc, wallet_public::COMMAND_REDEEM_HTLC)
|
||||
//MAP_JON_RPC_WE("atomics_check_htlc_redeemed", on_check_htlc_redeemed, wallet_public::COMMAND_CHECK_HTLC_REDEEMED)
|
||||
|
||||
//IONIC_SWAPS API
|
||||
MAP_JON_RPC_WE("ionic_swap_generate_proposal", on_ionic_swap_generate_proposal, wallet_public::COMMAND_IONIC_SWAP_GENERATE_PROPOSAL)
|
||||
MAP_JON_RPC_WE("ionic_swap_get_proposal_info", on_ionic_swap_get_proposal_info, wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO)
|
||||
MAP_JON_RPC_WE("ionic_swap_accept_proposal", on_ionic_swap_accept_proposal, wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL)
|
||||
MAP_JON_RPC_WE("ionic_swap_generate_proposal", on_ionic_swap_generate_proposal, wallet_public::COMMAND_IONIC_SWAP_GENERATE_PROPOSAL)
|
||||
MAP_JON_RPC_WE("ionic_swap_get_proposal_info", on_ionic_swap_get_proposal_info, wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO)
|
||||
MAP_JON_RPC_WE("ionic_swap_accept_proposal", on_ionic_swap_accept_proposal, wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL)
|
||||
|
||||
// Assets API
|
||||
MAP_JON_RPC_WE("assets_whitelist_get", on_assets_whitelist_get, wallet_public::COMMAND_ASSETS_WHITELIST_GET)
|
||||
MAP_JON_RPC_WE("assets_whitelist_add", on_assets_whitelist_add, wallet_public::COMMAND_ASSETS_WHITELIST_ADD)
|
||||
MAP_JON_RPC_WE("assets_whitelist_remove", on_assets_whitelist_remove, wallet_public::COMMAND_ASSETS_WHITELIST_REMOVE)
|
||||
|
||||
MAP_JON_RPC_WE("deploy_asset", on_assets_deploy, wallet_public::COMMAND_ASSETS_DEPLOY)
|
||||
MAP_JON_RPC_WE("emit_asset", on_assets_emit, wallet_public::COMMAND_ASSETS_EMIT)
|
||||
MAP_JON_RPC_WE("update_asset", on_assets_update, wallet_public::COMMAND_ASSETS_UPDATE)
|
||||
|
||||
//MULTIWALLET APIs
|
||||
MAP_JON_RPC_WE("mw_get_wallets", on_mw_get_wallets, wallet_public::COMMAND_MW_GET_WALLETS)
|
||||
MAP_JON_RPC_WE("mw_select_wallet", on_mw_select_wallet, wallet_public::COMMAND_MW_SELECT_WALLET)
|
||||
MAP_JON_RPC_WE("mw_get_wallets", on_mw_get_wallets, wallet_public::COMMAND_MW_GET_WALLETS)
|
||||
MAP_JON_RPC_WE("mw_select_wallet", on_mw_select_wallet, wallet_public::COMMAND_MW_SELECT_WALLET)
|
||||
|
||||
//basic crypto operations
|
||||
MAP_JON_RPC_WE("sign_message", on_sign_message, wallet_public::COMMAND_SIGN_MESSAGE)
|
||||
MAP_JON_RPC_WE("encrypt_data", on_encrypt_data, wallet_public::COMMAND_ENCRYPT_DATA)
|
||||
MAP_JON_RPC_WE("decrypt_data", on_decrypt_data, wallet_public::COMMAND_DECRYPT_DATA)
|
||||
END_JSON_RPC_MAP()
|
||||
MAP_JON_RPC_WE("sign_message", on_sign_message, wallet_public::COMMAND_SIGN_MESSAGE)
|
||||
MAP_JON_RPC_WE("encrypt_data", on_encrypt_data, wallet_public::COMMAND_ENCRYPT_DATA)
|
||||
MAP_JON_RPC_WE("decrypt_data", on_decrypt_data, wallet_public::COMMAND_DECRYPT_DATA)
|
||||
|
||||
//utility call
|
||||
MAP_JON_RPC_WE("proxy_to_daemon", on_proxy_to_daemon, wallet_public::COMMAND_PROXY_TO_DAEMON)
|
||||
END_JSON_RPC_MAP()
|
||||
END_URI_MAP2()
|
||||
|
||||
bool auth_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);
|
||||
//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);
|
||||
|
|
@ -160,6 +178,8 @@ namespace tools
|
|||
bool on_make_integrated_address(const wallet_public::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::request& req, wallet_public::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_split_integrated_address(const wallet_public::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::request& req, wallet_public::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
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_get_bare_outs_stats(const wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS ::request& req, wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_sweep_bare_outs(const wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS::request& req, wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS::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_LEGACY::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
|
@ -189,6 +209,15 @@ namespace tools
|
|||
bool on_ionic_swap_get_proposal_info(const wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO::request& req, wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_ionic_swap_accept_proposal(const wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL::request& req, wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
bool on_assets_whitelist_get(const wallet_public::COMMAND_ASSETS_WHITELIST_GET::request& req, wallet_public::COMMAND_ASSETS_WHITELIST_GET::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_assets_whitelist_add(const wallet_public::COMMAND_ASSETS_WHITELIST_ADD::request& req, wallet_public::COMMAND_ASSETS_WHITELIST_ADD::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_assets_whitelist_remove(const wallet_public::COMMAND_ASSETS_WHITELIST_REMOVE::request& req, wallet_public::COMMAND_ASSETS_WHITELIST_REMOVE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
bool on_assets_deploy(const wallet_public::COMMAND_ASSETS_DEPLOY::request& req, wallet_public::COMMAND_ASSETS_DEPLOY::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_assets_emit(const wallet_public::COMMAND_ASSETS_EMIT::request& req, wallet_public::COMMAND_ASSETS_EMIT::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_assets_update(const wallet_public::COMMAND_ASSETS_UPDATE::request& req, wallet_public::COMMAND_ASSETS_UPDATE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
|
||||
bool on_mw_get_wallets(const wallet_public::COMMAND_MW_GET_WALLETS::request& req, wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_mw_select_wallet(const wallet_public::COMMAND_MW_SELECT_WALLET::request& req, wallet_public::COMMAND_MW_SELECT_WALLET::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
|
|
@ -196,6 +225,7 @@ namespace tools
|
|||
bool on_encrypt_data(const wallet_public::COMMAND_ENCRYPT_DATA::request& req, wallet_public::COMMAND_ENCRYPT_DATA::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_decrypt_data(const wallet_public::COMMAND_DECRYPT_DATA::request& req, wallet_public::COMMAND_DECRYPT_DATA::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
bool on_proxy_to_daemon(const wallet_public::COMMAND_PROXY_TO_DAEMON::request& req, wallet_public::COMMAND_PROXY_TO_DAEMON::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
|
||||
//std::shared_ptr<wallet2> get_wallet();
|
||||
|
|
@ -203,6 +233,7 @@ namespace tools
|
|||
//bool reset_active_wallet(std::shared_ptr<wallet2> w);
|
||||
|
||||
bool handle_command_line(const boost::program_options::variables_map& vm);
|
||||
void rpc_destinations_to_currency_destination(const std::list<wallet_public::transfer_destination>& rpc_destinations, std::vector<currency::tx_destination_entry>& currency_destinations);
|
||||
|
||||
private:
|
||||
std::shared_ptr<i_wallet_provider> m_pwallet_provider_sh_ptr;
|
||||
|
|
@ -212,6 +243,8 @@ namespace tools
|
|||
bool m_do_mint;
|
||||
bool m_deaf;
|
||||
uint64_t m_last_wallet_store_height;
|
||||
std::string m_jwt_secret;
|
||||
epee::misc_utils::expirating_set<std::string, uint64_t> m_jwt_used_salts;
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
|
|
|
|||
|
|
@ -546,13 +546,12 @@ bool wallets_manager::init_local_daemon()
|
|||
CHECK_AND_ASSERT_AND_SET_GUI(res, "Failed to initialize core rpc server.");
|
||||
LOG_PRINT_GREEN("Core rpc server initialized OK on port: " << m_rpc_server.get_binded_port(), LOG_LEVEL_0);
|
||||
|
||||
m_ui_opt.rpc_port = m_rpc_server.get_binded_port();
|
||||
|
||||
|
||||
//chain calls to rpc server
|
||||
m_prpc_chain_handler = &m_wallet_rpc_server;
|
||||
//disable this for main net until we get full support of authentication with network
|
||||
#ifdef TESTNET
|
||||
m_rpc_server.set_rpc_chain_handler(this);
|
||||
#endif
|
||||
|
||||
|
||||
LOG_PRINT_L0("Starting core rpc server...");
|
||||
//dsi.text_state = "Starting core rpc server";
|
||||
|
|
@ -572,6 +571,25 @@ bool wallets_manager::init_local_daemon()
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string wallets_manager::setup_wallet_rpc(const std::string& jwt_secret)
|
||||
{
|
||||
#ifndef MOBILE_WALLET_BUILD
|
||||
if (!jwt_secret.size())
|
||||
{
|
||||
//disabling wallet RPC
|
||||
m_rpc_server.set_rpc_chain_handler(nullptr);
|
||||
return WALLET_RPC_STATUS_OK;
|
||||
}
|
||||
|
||||
//we don't override command line JWT secret
|
||||
//if(!m_wallet_rpc_server.get_jwt_secret().size() )
|
||||
m_wallet_rpc_server.set_jwt_secret(jwt_secret);
|
||||
|
||||
m_rpc_server.set_rpc_chain_handler(this);
|
||||
#endif
|
||||
return WALLET_RPC_STATUS_OK;
|
||||
}
|
||||
|
||||
bool wallets_manager::deinit_local_daemon()
|
||||
{
|
||||
#ifndef MOBILE_WALLET_BUILD
|
||||
|
|
@ -1025,7 +1043,6 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
|
|||
|
||||
std::shared_ptr<tools::wallet2> w(new tools::wallet2());
|
||||
w->set_use_deffered_global_outputs(m_use_deffered_global_outputs);
|
||||
w->set_use_assets_whitelisting(true);
|
||||
owr.wallet_id = m_wallet_id_counter++;
|
||||
|
||||
w->callback(std::shared_ptr<tools::i_wallet2_callback>(new i_wallet_to_i_backend_adapter(this, owr.wallet_id)));
|
||||
|
|
@ -1057,10 +1074,11 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
|
|||
w->get_recent_transfers_history(owr.recent_history.history, 0, txs_to_return, owr.recent_history.total_history_items, owr.recent_history.last_item_index, exclude_mining_txs);
|
||||
//w->get_unconfirmed_transfers(owr.recent_history.unconfirmed);
|
||||
w->get_unconfirmed_transfers(owr.recent_history.history, exclude_mining_txs);
|
||||
w->set_use_assets_whitelisting(true);
|
||||
owr.wallet_local_bc_size = w->get_blockchain_current_size();
|
||||
|
||||
//workaround for missed fee
|
||||
//owr.seed = w->get_account().get_seed_phrase();
|
||||
owr.seed = w->get_account().get_seed_phrase("");
|
||||
break;
|
||||
}
|
||||
catch (const tools::error::file_not_found& /**/)
|
||||
|
|
@ -1170,7 +1188,7 @@ std::string wallets_manager::generate_wallet(const std::wstring& path, const std
|
|||
{
|
||||
w->generate(path, password, false);
|
||||
w->set_minimum_height(m_last_daemon_height-1);
|
||||
//owr.seed = w->get_account().get_seed_phrase();
|
||||
owr.seed = w->get_account().get_seed_phrase("");
|
||||
}
|
||||
catch (const tools::error::file_exists&)
|
||||
{
|
||||
|
|
@ -1279,7 +1297,7 @@ std::string wallets_manager::restore_wallet(const std::wstring& path, const std:
|
|||
{
|
||||
bool is_tracking = currency::account_base::is_seed_tracking(seed_phrase);
|
||||
w->restore(path, password, seed_phrase, is_tracking, seed_password);
|
||||
//owr.seed = w->get_account().get_seed_phrase();
|
||||
owr.seed = w->get_account().get_seed_phrase("");
|
||||
}
|
||||
catch (const tools::error::file_exists&)
|
||||
{
|
||||
|
|
@ -1645,11 +1663,10 @@ std::string wallets_manager::invoke(uint64_t wallet_id, std::string params)
|
|||
epee::net_utils::http::http_request_info query_info = AUTO_VAL_INIT(query_info);
|
||||
epee::net_utils::http::http_response_info response_info = AUTO_VAL_INIT(response_info);
|
||||
epee::net_utils::connection_context_base stub_conn_context = AUTO_VAL_INIT(stub_conn_context);
|
||||
std::string reference_stub;
|
||||
bool call_found = false;
|
||||
query_info.m_URI = "/json_rpc";
|
||||
query_info.m_body = params;
|
||||
wo.rpc_wrapper->handle_http_request_map(query_info, response_info, stub_conn_context, call_found, reference_stub);
|
||||
wo.rpc_wrapper->handle_http_request_map(query_info, response_info, stub_conn_context, call_found);
|
||||
return response_info.m_body;
|
||||
}
|
||||
|
||||
|
|
@ -1880,6 +1897,7 @@ void wallets_manager::prepare_wallet_status_info(wallet_vs_options& wo, view::wa
|
|||
wsi.wallet_id = wo.wallet_id;
|
||||
wsi.is_alias_operations_available = !wo.has_related_alias_in_unconfirmed;
|
||||
wo.w->get()->balance(wsi.balances, wsi.minied_total);
|
||||
wsi.has_bare_unspent_outputs = wo.w->get()->has_bare_unspent_outputs();
|
||||
}
|
||||
std::string wallets_manager::check_available_sources(uint64_t wallet_id, std::list<uint64_t>& amounts)
|
||||
{
|
||||
|
|
@ -2103,10 +2121,10 @@ bool wallets_manager::on_mw_select_wallet(const tools::wallet_public::COMMAND_MW
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void wallets_manager::lock()
|
||||
{
|
||||
#ifndef MOBILE_WALLET_BUILD
|
||||
m_select_wallet_rpc_lock.lock();
|
||||
{
|
||||
SHARED_CRITICAL_REGION_LOCAL(m_wallets_lock);
|
||||
auto it = m_wallets.find(m_rpc_selected_wallet_id);
|
||||
|
|
@ -2123,6 +2141,7 @@ void wallets_manager::unlock()
|
|||
{
|
||||
#ifndef MOBILE_WALLET_BUILD
|
||||
m_current_wallet_locked_object.reset();
|
||||
m_select_wallet_rpc_lock.unlock();
|
||||
#endif
|
||||
}
|
||||
std::shared_ptr<tools::wallet2> wallets_manager::get_wallet()
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ public:
|
|||
std::string get_fav_offers(const std::list<bc_services::offer_id>& hashes, const bc_services::core_offers_filter& filter, std::list<bc_services::offer_details_ex>& offers);
|
||||
std::string get_tx_pool_info(currency::COMMAND_RPC_GET_POOL_INFO::response& res);
|
||||
std::string export_wallet_history(const view::export_wallet_info& ewi);
|
||||
std::string setup_wallet_rpc(const std::string& jwt_secret);
|
||||
|
||||
#ifndef MOBILE_WALLET_BUILD
|
||||
currency::core_rpc_server& get_rpc_server() { return m_rpc_server; }
|
||||
#endif
|
||||
|
|
@ -193,12 +195,12 @@ private:
|
|||
bool do_exception_safe_call(guarded_code_t guarded_code, error_prefix_maker_t error_prefix_maker, std::string& api_return_code_result);
|
||||
|
||||
//----- 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, const std::list<tools::wallet_public::asset_balance_entry>& balances, uint64_t total_mined);
|
||||
virtual void on_pos_block_found(size_t wallet_id, const currency::block& /*block*/);
|
||||
virtual void on_sync_progress(size_t wallet_id, const uint64_t& /*percents*/);
|
||||
virtual void on_transfer_canceled(size_t wallet_id, const tools::wallet_public::wallet_transfer_info& wti);
|
||||
virtual void on_tor_status_change(size_t wallet_id, const std::string& state);
|
||||
virtual void on_new_block(size_t wallet_id, uint64_t height, const currency::block& block) override;
|
||||
virtual void on_transfer2(size_t wallet_id, const tools::wallet_public::wallet_transfer_info& wti, const std::list<tools::wallet_public::asset_balance_entry>& balances, uint64_t total_mined) override;
|
||||
virtual void on_pos_block_found(size_t wallet_id, const currency::block& /*block*/) override;
|
||||
virtual void on_sync_progress(size_t wallet_id, const uint64_t& /*percents*/) override;
|
||||
virtual void on_transfer_canceled(size_t wallet_id, const tools::wallet_public::wallet_transfer_info& wti) override;
|
||||
virtual void on_tor_status_change(size_t wallet_id, const std::string& state) override;
|
||||
|
||||
virtual void on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets) override;
|
||||
virtual bool on_mw_select_wallet(uint64_t wallet_id) override;
|
||||
|
|
@ -232,6 +234,8 @@ private:
|
|||
std::mutex m_stop_singal_sent_mutex;
|
||||
std::condition_variable m_stop_singal_sent_mutex_cv;
|
||||
|
||||
std::mutex m_select_wallet_rpc_lock;
|
||||
|
||||
view::i_view m_view_stub;
|
||||
view::i_view* m_pview;
|
||||
std::shared_ptr<tools::i_core_proxy> m_rpc_proxy;
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ bool block_template_against_txs_size::c1(currency::core& c, size_t ev_index, con
|
|||
|
||||
uint64_t top_block_height = bcs.get_top_block_height();
|
||||
uint64_t blocksize_limit = bcs.get_current_comulative_blocksize_limit();
|
||||
uint64_t base_block_reward_pow = get_base_block_reward(false, bcs.total_coins(), top_block_height + 1);
|
||||
uint64_t base_block_reward_pos = get_base_block_reward(true, bcs.total_coins(), top_block_height + 1);
|
||||
uint64_t base_block_reward_pow = get_base_block_reward(top_block_height + 1);
|
||||
uint64_t base_block_reward_pos = base_block_reward_pow;
|
||||
|
||||
g_block_txs_fee = TESTS_DEFAULT_FEE; // passing an argument to custom_fill_block_template_func via global variable (not perfect but works well)
|
||||
|
||||
|
|
@ -91,13 +91,16 @@ bool block_template_against_txs_size::c1(currency::core& c, size_t ev_index, con
|
|||
CHECK_AND_ASSERT_MES(r, false, "create_block_template failed, txs_total_size = " << txs_total_size);
|
||||
CHECK_AND_ASSERT_MES(height == top_block_height + 1, false, "Incorrect height: " << height << ", expected: " << top_block_height + 1 << ", txs_total_size = " << txs_total_size);
|
||||
|
||||
uint64_t base_reward = 0;
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
|
||||
size_t cumulative_block_size = txs_total_size;
|
||||
size_t coinbase_blob_size = get_object_blobsize(b.miner_tx);
|
||||
if (coinbase_blob_size > CURRENCY_COINBASE_BLOB_RESERVED_SIZE)
|
||||
cumulative_block_size += coinbase_blob_size;
|
||||
r = bcs.validate_miner_transaction(b, cumulative_block_size, g_block_txs_fee, base_reward, bcs.total_coins());
|
||||
|
||||
r = bcs.calculate_block_reward_for_next_top_block(cumulative_block_size, block_reward_without_fee);
|
||||
CHECK_AND_ASSERT_MES(r, false, "calculate_block_reward_for_next_top_block failed");
|
||||
r = bcs.validate_miner_transaction(b.miner_tx, g_block_txs_fee, block_reward_without_fee);
|
||||
CHECK_AND_ASSERT_MES(r, false, "validate_miner_transaction failed, txs_total_size = " << txs_total_size);
|
||||
|
||||
uint64_t generated_coins = get_outs_money_amount(b.miner_tx) - (is_pos != 0 ? boost::get<tx_out_bare>(b.miner_tx.vout.back()).amount : 0) - g_block_txs_fee / 2;
|
||||
|
|
|
|||
|
|
@ -828,7 +828,7 @@ uint64_t test_generator::get_base_reward_for_next_block(const crypto::hash& head
|
|||
auto it = m_blocks_info.find(head_id);
|
||||
if (it == m_blocks_info.end())
|
||||
return 0;
|
||||
return get_base_block_reward(!pow, it->second.already_generated_coins, get_block_height(it->second.b));
|
||||
return get_base_block_reward(get_block_height(it->second.b));
|
||||
}
|
||||
|
||||
bool test_generator::find_nounce(currency::block& blk, std::vector<const block_info*>& blocks, wide_difficulty_type dif, uint64_t height) const
|
||||
|
|
@ -2319,15 +2319,25 @@ bool check_ring_signature_at_gen_time(const std::vector<test_event_entry>& event
|
|||
|
||||
bool check_mixin_value_for_each_input(size_t mixin, const crypto::hash& tx_id, currency::core& c)
|
||||
{
|
||||
std::shared_ptr<const currency::transaction_chain_entry> ptce = c.get_blockchain_storage().get_tx_chain_entry(tx_id);
|
||||
if (!ptce)
|
||||
return false;
|
||||
transaction tx_local;
|
||||
const transaction* ptx = &tx_local;
|
||||
|
||||
for (size_t i = 0; i < ptce->tx.vin.size(); ++i)
|
||||
std::shared_ptr<const currency::transaction_chain_entry> ptce = c.get_blockchain_storage().get_tx_chain_entry(tx_id);
|
||||
if (ptce)
|
||||
{
|
||||
auto& input = ptce->tx.vin[i];
|
||||
ptx = &ptce->tx;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!c.get_tx_pool().get_transaction(tx_id, tx_local))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ptx->vin.size(); ++i)
|
||||
{
|
||||
auto& input = ptx->vin[i];
|
||||
const std::vector<currency::txout_ref_v>& key_offsets = get_key_offsets_from_txin_v(input);
|
||||
CHECK_AND_ASSERT_MES(key_offsets.size() == mixin + 1, false, "for input #" << i << " mixin count is " << key_offsets.size() - 1 << ", expected is " << mixin);
|
||||
CHECK_AND_ASSERT_MES(key_offsets.size() == mixin + 1, false, "for input #" << i << " ring size is " << key_offsets.size() << ", mixin count is " << key_offsets.size() - 1 << ", expected mixin count is " << mixin);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -977,6 +977,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(multisig_out_make_and_spent_in_altchain);
|
||||
GENERATE_AND_PLAY(multisig_unconfirmed_transfer_and_multiple_scan_pool_calls);
|
||||
GENERATE_AND_PLAY(multisig_out_spent_in_altchain_case_b4);
|
||||
GENERATE_AND_PLAY(multisig_n_participants_seq_signing);
|
||||
|
||||
GENERATE_AND_PLAY(ref_by_id_basics);
|
||||
GENERATE_AND_PLAY(ref_by_id_mixed_inputs_types);
|
||||
|
|
@ -1246,7 +1247,10 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(hard_fork_2_incorrect_alias_update<false>);
|
||||
|
||||
// HF4
|
||||
// GENERATE_AND_PLAY_HF(hard_fork_4_consolidated_txs, "4"); TODO, doesn't work atm -- sowle
|
||||
GENERATE_AND_PLAY_HF(hard_fork_4_consolidated_txs, "3-*");
|
||||
GENERATE_AND_PLAY_HF(hardfork_4_wallet_transfer_with_mandatory_mixins, "3-*");
|
||||
GENERATE_AND_PLAY(hardfork_4_wallet_sweep_bare_outs);
|
||||
GENERATE_AND_PLAY_HF(hardfork_4_pop_tx_from_global_index, "4-*");
|
||||
|
||||
// atomics
|
||||
GENERATE_AND_PLAY(atomic_simple_test);
|
||||
|
|
@ -1270,6 +1274,9 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(zarcanum_block_with_txs);
|
||||
GENERATE_AND_PLAY(asset_depoyment_and_few_zc_utxos);
|
||||
GENERATE_AND_PLAY_HF(assets_and_pos_mining, "4-*");
|
||||
|
||||
GENERATE_AND_PLAY_HF(pos_fuse_test, "4-*");
|
||||
|
||||
|
||||
|
||||
GENERATE_AND_PLAY_HF(attachment_isolation_test, "4-*");
|
||||
|
|
|
|||
|
|
@ -45,3 +45,4 @@
|
|||
#include "multiassets_test.h"
|
||||
#include "ionic_swap_tests.h"
|
||||
#include "attachment_isolation_encryption_test.h"
|
||||
#include "pos_fuse_test.h"
|
||||
|
|
@ -708,7 +708,7 @@ bool gen_no_attchments_in_coinbase::init_config_set_cp(currency::core& c, size_t
|
|||
// different checkpoints due to different block versions for different hardforks -> different hashes
|
||||
if (crc.is_hardfork_active_for_height(ZANO_HARDFORK_03, 11) && !crc.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, 11))
|
||||
{
|
||||
m_checkpoints.add_checkpoint(12, "4e6055dda442e04b2feb70bc7245584742604e8515b8d2e1c3d46c26f758d59f");
|
||||
m_checkpoints.add_checkpoint(12, "70fbbd33d88ccaa26f9fe64d102bcff2572494009339de9fab7158a40633fbb5");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1217,23 +1217,28 @@ bool hard_fork_2_alias_update_using_old_tx<before_hf_2>::c1(currency::core& c, s
|
|||
//
|
||||
// Send tx and print it's blob
|
||||
// this code was used to generate old-style tx in develop branch, commit 36eabb916b95c7db06bdfb5d34d9820bd94b82df
|
||||
// UPD: 2024-03-15 tx blob was updated as of commit f538fc3a7612e7ce86556a1cd2602400f6b4e9aa
|
||||
//
|
||||
transaction tx_upd = AUTO_VAL_INIT(tx_upd);
|
||||
alice_wlt->request_alias_update(ai_upd, tx_upd, TESTS_DEFAULT_FEE, 0);
|
||||
std::string tx_upd_hex = epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(tx_upd));
|
||||
LOG_PRINT_L0("tx upd: " << ENDL << tx_upd_hex);
|
||||
{
|
||||
transaction tx_upd = AUTO_VAL_INIT(tx_upd);
|
||||
alice_wlt->request_alias_update(ai_upd, tx_upd, TESTS_DEFAULT_FEE, 0);
|
||||
std::string tx_upd_hex = epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(tx_upd));
|
||||
LOG_PRINT_L0("tx upd: " << ENDL << tx_upd_hex);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// use prepared tx blob
|
||||
std::string tx_upd_hex("01010180988be49903011a0100000000000000ff593921b61d52e818058ef881764383fe9fb0cf4512da460daf477e3a216144000180d0dbc3f402037c2e68e9c60914d369dc53fcc91522dcec284e1b7c1604ccc3d8fcf67e2da0790003140a616c696365616c696365efdcf084d7af59e0d68e8bda3ff4514a02d812ccfd6a09f69811c5a6a1b035c9b1b2395fcd84283d02e2fc4f37395ac9d8f01ff3f1ad1b94a26aaf1c76bb39d00c48656c6c6f206d696e657221000118faf7b79730fd6c1ec5c918891e264e959749a0d8eebc7997b503bd185ef100fd9e0150c175e0f048ee729137ceed035e9145d7857eae9ab786dd319fe6520b16b0cc0d6a8766cd098fe5a42875243789cc3b4bf66ee0c12ff6ef2fc179d4cef50b0288360101f3012451b07e58e742c020d68e8ff6db2905fa3aad78806ba80b16f3c861ee09f79817ea1ec36b0e30c7be5412daf59bcbc34410461a0d126de4a2dd897ecf0200");
|
||||
std::string tx_upd_hex("01010180988be49903011a01000000000000007bdeaff6ac11597e9fe397349dd2ecfcd6880cda9bbedaa67f759a5b95ba2ed9000180d0dbc3f4020335db05c510daddcb82257be70789650007ad2d567092ec1eb2a38a93ef8fa0070004140a616c696365616c696365efdcf084d7af59e0d68e8bda3ff4514a02d812ccfd6a09f69811c5a6a1b035c9b1b2395fcd84283d02e2fc4f37395ac9d8f01ff3f1ad1b94a26aaf1c76bb39d00c48656c6c6f206d696e6572210001c2537b8203e9c9981b87a3c63cc0c63e4ccc14ddd0309fdcee94664e4b3bc307ee438e90bb5720b7ac7cbec38fcac9c7aa5b9df02abd2fa1a58c580f9b3eaf0516116e8d89a67440aad0922a7e5dd88870e6f0af792a7af201ee21effd90cc6c7f1700000b02f37101016ed0997a3fe0c6bc47ffde14599a77697ba95c5c1489b65e5e54854146079f06569313d921f19ed2848cdccc8bad7f75fb46fc1608912365f569b7690703010b00");
|
||||
std::string tx_upd_blob;
|
||||
r = epee::string_tools::parse_hexstr_to_binbuff(tx_upd_hex, tx_upd_blob);
|
||||
CHECK_AND_ASSERT_MES(r, false, "parse_hexstr_to_binbuff failed");
|
||||
//r = t_unserializable_object_from_blob(tx_upd, tx_upd_blob);
|
||||
//CHECK_AND_ASSERT_MES(r, false, "t_unserializable_object_from_blob failed");
|
||||
crypto::hash tx_upd_hash{};
|
||||
transaction tx_upd{};
|
||||
CHECK_AND_ASSERT_MES(parse_and_validate_tx_from_blob(tx_upd_blob, tx_upd, tx_upd_hash), false, "parse_tx_form_blob failed");
|
||||
//LOG_PRINT_L0("tx_upd: " << tx_upd_hash << ", json:" << ENDL << obj_to_json_str(tx_upd));
|
||||
tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
r = c.handle_incoming_tx(tx_upd_blob, tvc, false);
|
||||
r = c.handle_incoming_tx(tx_upd, tvc, false, tx_upd_hash);
|
||||
CHECK_AND_ASSERT_MES(r, false, "handle_incoming_tx failed");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -242,4 +242,257 @@ bool hardfork_4_explicit_native_ids_in_outs::c1(currency::core& c, size_t ev_ind
|
|||
{
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
hardfork_4_wallet_transfer_with_mandatory_mixins::hardfork_4_wallet_transfer_with_mandatory_mixins()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(hardfork_4_wallet_transfer_with_mandatory_mixins, c1);
|
||||
REGISTER_CALLBACK_METHOD(hardfork_4_wallet_transfer_with_mandatory_mixins, configure_core);
|
||||
}
|
||||
|
||||
bool hardfork_4_wallet_transfer_with_mandatory_mixins::configure_core(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
test_chain_unit_enchanced::configure_core(c, ev_index, events); // call default
|
||||
currency::core_runtime_config pc = c.get_blockchain_storage().get_core_runtime_config();
|
||||
pc.hf4_minimum_mixins = CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE;
|
||||
c.get_blockchain_storage().set_core_runtime_config(pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hardfork_4_wallet_transfer_with_mandatory_mixins::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
/* Test outline: make sure that after HF4 a normal transfer with CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE decoys goes normal.
|
||||
* (It should also work prior to HF4.)
|
||||
*/
|
||||
|
||||
bool r = false;
|
||||
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); bob_acc.set_createtime(ts);
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core"); // necessary for the test to be run by GENERATE_AND_PLAY_HF
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
MAKE_TX(events, tx_1, miner_acc, alice_acc, MK_TEST_COINS(10), blk_0r);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_1);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hardfork_4_wallet_transfer_with_mandatory_mixins::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
bool r = false;
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
|
||||
alice_wlt->refresh();
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "Alice", MK_TEST_COINS(10), 0, 0, 0, 0), false, "");
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
alice_wlt->refresh();
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "Alice", MK_TEST_COINS(10), 0, MK_TEST_COINS(10), 0, 0), false, "");
|
||||
|
||||
alice_wlt->transfer(MK_TEST_COINS(9), m_accounts[BOB_ACC_IDX].get_public_address());
|
||||
|
||||
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX);
|
||||
bob_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", MK_TEST_COINS(9), 0, 0, 0, 0), false, "");
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
alice_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "Alice", 0, 0, 0, 0, 0), false, "");
|
||||
bob_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", MK_TEST_COINS(9), 0, MK_TEST_COINS(9), 0, 0), false, "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
hardfork_4_wallet_sweep_bare_outs::hardfork_4_wallet_sweep_bare_outs()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(hardfork_4_wallet_sweep_bare_outs, c1);
|
||||
|
||||
m_hardforks.set_hardfork_height(ZANO_HARDFORK_04_ZARCANUM, 10);
|
||||
}
|
||||
|
||||
bool hardfork_4_wallet_sweep_bare_outs::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
// Test idea: make sure wallet2::sweep_bare_outs works well even if there's not enough outputs to mix
|
||||
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); bob_acc.set_createtime(ts);
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
|
||||
// rebuild genesis miner tx
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
destinations.emplace_back(MK_TEST_COINS(23), alice_acc.get_public_address());
|
||||
destinations.emplace_back(MK_TEST_COINS(23), bob_acc.get_public_address());
|
||||
destinations.emplace_back(MK_TEST_COINS(55), bob_acc.get_public_address()); // this output is unique and doesn't have decoys
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
destinations.emplace_back(MK_TEST_COINS(23), miner_acc.get_public_address()); // decoys (later Alice will spend her output using mixins)
|
||||
destinations.emplace_back(COIN, miner_acc.get_public_address()); // leftover amount will be also send to the last destination
|
||||
CHECK_AND_ASSERT_MES(replace_coinbase_in_genesis_block(destinations, generator, events, blk_0), false, "");
|
||||
|
||||
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_hardfork_active", static_cast<size_t>(ZANO_HARDFORK_04_ZARCANUM));
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hardfork_4_wallet_sweep_bare_outs::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
bool r = false;
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
|
||||
alice_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "Alice", MK_TEST_COINS(23), UINT64_MAX, MK_TEST_COINS(23), 0, 0), false, "");
|
||||
|
||||
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX);
|
||||
bob_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", MK_TEST_COINS(23 + 55), UINT64_MAX, MK_TEST_COINS(23 + 55), 0, 0), false, "");
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
// 1. Try to sweep bare out for Alice (enough decoys to mix with)
|
||||
std::vector<tools::wallet2::batch_of_bare_unspent_outs> tids_grouped_by_txs;
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->get_bare_unspent_outputs_stats(tids_grouped_by_txs), false, "");
|
||||
size_t total_txs_sent = 0;
|
||||
uint64_t total_amount_sent = 0;
|
||||
uint64_t total_fee_spent = 0;
|
||||
uint64_t total_bare_outs_sent = 0;
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->sweep_bare_unspent_outputs(m_accounts[ALICE_ACC_IDX].get_public_address(), tids_grouped_by_txs, total_txs_sent, total_amount_sent, total_fee_spent, total_bare_outs_sent), false, "");
|
||||
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(total_txs_sent, 1);
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(total_amount_sent, MK_TEST_COINS(23));
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(total_fee_spent, TESTS_DEFAULT_FEE);
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(total_bare_outs_sent, 1);
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
std::list<transaction> txs;
|
||||
c.get_pool_transactions(txs);
|
||||
auto& tx = txs.back();
|
||||
CHECK_AND_ASSERT_MES(check_mixin_value_for_each_input(CURRENCY_DEFAULT_DECOY_SET_SIZE, get_transaction_hash(tx), c), false, "");
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
alice_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "Alice", MK_TEST_COINS(23) - TESTS_DEFAULT_FEE, UINT64_MAX, MK_TEST_COINS(23) - TESTS_DEFAULT_FEE, 0, 0), false, "");
|
||||
|
||||
|
||||
// 2. Try to sweep bare out for Bob (not enough decoys to mix with)
|
||||
tids_grouped_by_txs.clear();
|
||||
CHECK_AND_ASSERT_MES(bob_wlt->get_bare_unspent_outputs_stats(tids_grouped_by_txs), false, "");
|
||||
CHECK_AND_ASSERT_MES(bob_wlt->sweep_bare_unspent_outputs(m_accounts[BOB_ACC_IDX].get_public_address(), tids_grouped_by_txs, total_txs_sent, total_amount_sent, total_fee_spent, total_bare_outs_sent), false, "");
|
||||
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(total_txs_sent, 1);
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(total_amount_sent, MK_TEST_COINS(23 + 55));
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(total_fee_spent, TESTS_DEFAULT_FEE);
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(total_bare_outs_sent, 2);
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
txs.clear();
|
||||
c.get_pool_transactions(txs);
|
||||
auto& tx2 = txs.back();
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(tx2.vin.size(), 2);
|
||||
|
||||
const txin_to_key &input_with_enough_decoys = boost::get<txin_to_key>(tx2.vin[0]).amount == MK_TEST_COINS(23) ? boost::get<txin_to_key>(tx2.vin[0]) : boost::get<txin_to_key>(tx2.vin[1]);
|
||||
const txin_to_key &input_with_not_enough_decoys = boost::get<txin_to_key>(tx2.vin[0]).amount == MK_TEST_COINS(23) ? boost::get<txin_to_key>(tx2.vin[1]) : boost::get<txin_to_key>(tx2.vin[0]);
|
||||
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(input_with_enough_decoys.key_offsets.size(), CURRENCY_DEFAULT_DECOY_SET_SIZE + 1);
|
||||
CHECK_V_EQ_EXPECTED_AND_ASSERT(input_with_not_enough_decoys.key_offsets.size(), 1);
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
bob_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", MK_TEST_COINS(23 + 55) - TESTS_DEFAULT_FEE, UINT64_MAX, MK_TEST_COINS(23 + 55) - TESTS_DEFAULT_FEE, 0, 0), false, "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
hardfork_4_pop_tx_from_global_index::hardfork_4_pop_tx_from_global_index()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(hardfork_4_pop_tx_from_global_index, c1);
|
||||
}
|
||||
|
||||
bool hardfork_4_pop_tx_from_global_index::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
// Test idea: make sure that pop_transaction_from_global_index works for tx_out_zarcanum as well (m_db_outputs is consistent after pop_transaction_from_global_index() call)
|
||||
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_hardfork_active", static_cast<size_t>(ZANO_HARDFORK_04_ZARCANUM));
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_1a, blk_0r, miner_acc); // blk_1a will be the alt chain
|
||||
DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(blk_1a)); // make sure now it's the main chain
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_1, blk_0r, miner_acc);
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner_acc); // this should trigger chain switching
|
||||
DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(blk_2)); // make sure it did
|
||||
|
||||
// during switching to the alternative chain pop_block_from_blockchain() -> ... -> pop_transaction_from_global_index() will be called
|
||||
// but abort_transaction() will not, meaning m_db_outputs will be in incorrect state, if pop_transaction_from_global_index() hasn't properly pop all outs
|
||||
// this will be checked later in c1
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hardfork_4_pop_tx_from_global_index::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
auto& bcs = c.get_blockchain_storage();
|
||||
bool r = false;
|
||||
|
||||
//currency::outs_index_stat outs_stat{};
|
||||
//bcs.get_outs_index_stat(outs_stat); // 24 - bad, 22 - good
|
||||
|
||||
COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::response res;
|
||||
COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::request req;
|
||||
req.amount = 0;
|
||||
req.i = 22;
|
||||
CHECK_AND_ASSERT_MES(!bcs.get_global_index_details(req, res), false, "gindex 22 exists which is unexpected");
|
||||
req.i = 21;
|
||||
CHECK_AND_ASSERT_MES(bcs.get_global_index_details(req, res), false, "gindex 21 does not exist which is unexpected");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,3 +25,27 @@ struct hardfork_4_explicit_native_ids_in_outs : public wallet_test
|
|||
|
||||
mutable uint64_t m_alice_initial_balance = 0;
|
||||
};
|
||||
|
||||
|
||||
struct hardfork_4_wallet_transfer_with_mandatory_mixins : public wallet_test
|
||||
{
|
||||
hardfork_4_wallet_transfer_with_mandatory_mixins();
|
||||
bool configure_core(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
struct hardfork_4_wallet_sweep_bare_outs : public wallet_test
|
||||
{
|
||||
hardfork_4_wallet_sweep_bare_outs();
|
||||
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);
|
||||
};
|
||||
|
||||
struct hardfork_4_pop_tx_from_global_index : public wallet_test
|
||||
{
|
||||
hardfork_4_pop_tx_from_global_index();
|
||||
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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -178,7 +178,6 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
|
|||
// Alice wants to trade with Bob, to exchange 10.0 TCT to 0.5 ZANO
|
||||
view::ionic_swap_proposal_info proposal_details = AUTO_VAL_INIT(proposal_details);
|
||||
proposal_details.fee_paid_by_a = TESTS_DEFAULT_FEE;
|
||||
proposal_details.mixins = c.get_blockchain_storage().get_core_runtime_config().hf4_minimum_mixins;
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ asset_id , assets_to_exchange });
|
||||
proposal_details.to_initiator.push_back(view::asset_funds{ currency::native_coin_asset_id , native_coins_to_exchange });
|
||||
|
||||
|
|
@ -192,7 +191,6 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
|
|||
if (proposal_decoded_info.to_finalizer != proposal_details.to_finalizer
|
||||
|| proposal_decoded_info.to_initiator != proposal_details.to_initiator
|
||||
|| proposal_decoded_info.fee_paid_by_a != proposal_details.fee_paid_by_a
|
||||
|| proposal_decoded_info.mixins != proposal_details.mixins
|
||||
)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(false, false, "proposal actual and proposals decoded mismatch");
|
||||
|
|
@ -233,7 +231,6 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
|
|||
//now Alice want to trade with Bob, to send 0.5 ZANO and get 10.0 TCT in exchange
|
||||
view::ionic_swap_proposal_info proposal_details = AUTO_VAL_INIT(proposal_details);
|
||||
proposal_details.fee_paid_by_a = TESTS_DEFAULT_FEE;
|
||||
proposal_details.mixins = c.get_blockchain_storage().get_core_runtime_config().hf4_minimum_mixins;
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ currency::native_coin_asset_id , native_coins_to_exchange });
|
||||
proposal_details.to_initiator.push_back(view::asset_funds{ asset_id , assets_to_exchange });
|
||||
|
||||
|
|
@ -247,7 +244,6 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
|
|||
if (proposal_decoded_info.to_finalizer != proposal_details.to_finalizer
|
||||
|| proposal_decoded_info.to_initiator != proposal_details.to_initiator
|
||||
|| proposal_decoded_info.fee_paid_by_a != proposal_details.fee_paid_by_a
|
||||
|| proposal_decoded_info.mixins != proposal_details.mixins
|
||||
)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(false, false, "proposal actual and proposals decoded mismatch");
|
||||
|
|
@ -387,7 +383,6 @@ bool ionic_swap_exact_amounts_test::c1(currency::core& c, size_t ev_index, const
|
|||
proposal_details.to_initiator.push_back(view::asset_funds{ asset_id, adb.total_max_supply });
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ native_coin_asset_id, MK_TEST_COINS(20) });
|
||||
proposal_details.fee_paid_by_a = MK_TEST_COINS(1);
|
||||
proposal_details.mixins = c.get_blockchain_storage().get_core_runtime_config().hf4_minimum_mixins;
|
||||
|
||||
tools::wallet_public::ionic_swap_proposal proposal{};
|
||||
alice_wlt->create_ionic_swap_proposal(proposal_details, m_accounts[BOB_ACC_IDX].get_public_address(), proposal);
|
||||
|
|
@ -397,8 +392,7 @@ bool ionic_swap_exact_amounts_test::c1(currency::core& c, size_t ev_index, const
|
|||
CHECK_AND_ASSERT_MES(
|
||||
proposal_decoded_info.to_finalizer == proposal_details.to_finalizer &&
|
||||
proposal_decoded_info.to_initiator == proposal_details.to_initiator &&
|
||||
proposal_decoded_info.fee_paid_by_a == proposal_details.fee_paid_by_a &&
|
||||
proposal_decoded_info.mixins == proposal_details.mixins,
|
||||
proposal_decoded_info.fee_paid_by_a == proposal_details.fee_paid_by_a,
|
||||
false, "actual and decoded proposal mismatch \nproposal_decoded_info: "
|
||||
<< epee::serialization::store_t_to_json(proposal_decoded_info) <<
|
||||
"\nproposal_details" << epee::serialization::store_t_to_json(proposal_details));
|
||||
|
|
@ -429,7 +423,6 @@ bool ionic_swap_exact_amounts_test::c1(currency::core& c, size_t ev_index, const
|
|||
proposal_details.to_initiator.push_back(view::asset_funds{ asset_id, adb.total_max_supply });
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ native_coin_asset_id, MK_TEST_COINS(20) });
|
||||
proposal_details.fee_paid_by_a = MK_TEST_COINS(1);
|
||||
proposal_details.mixins = c.get_blockchain_storage().get_core_runtime_config().hf4_minimum_mixins;
|
||||
|
||||
proposal = tools::wallet_public::ionic_swap_proposal{};
|
||||
carol_wlt->create_ionic_swap_proposal(proposal_details, m_accounts[ALICE_ACC_IDX].get_public_address(), proposal);
|
||||
|
|
@ -439,8 +432,7 @@ bool ionic_swap_exact_amounts_test::c1(currency::core& c, size_t ev_index, const
|
|||
CHECK_AND_ASSERT_MES(
|
||||
proposal_decoded_info.to_finalizer == proposal_details.to_finalizer &&
|
||||
proposal_decoded_info.to_initiator == proposal_details.to_initiator &&
|
||||
proposal_decoded_info.fee_paid_by_a == proposal_details.fee_paid_by_a &&
|
||||
proposal_decoded_info.mixins == proposal_details.mixins,
|
||||
proposal_decoded_info.fee_paid_by_a == proposal_details.fee_paid_by_a,
|
||||
false, "actual and decoded proposal mismatch");
|
||||
|
||||
currency::transaction tx_is2{};
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ using namespace currency;
|
|||
#define TMP_LOG_RESTORE
|
||||
#endif
|
||||
|
||||
void exception_handler(){}
|
||||
static void exception_handler(){}
|
||||
//==============================================================================================================================
|
||||
|
||||
// helper routine: creates multisig-spending tx using a wallet and keys of other ms-participants, then sends it to the core proxy
|
||||
|
|
@ -1638,7 +1638,7 @@ multisig_and_checkpoints::multisig_and_checkpoints()
|
|||
bool multisig_and_checkpoints::set_cp(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
currency::checkpoints checkpoints;
|
||||
checkpoints.add_checkpoint(15, "6f9194c144afd73077478e7f04e947c50160b5673558e6f696a4f662a3ca261e");
|
||||
checkpoints.add_checkpoint(15, "fda3e645fbfd0f4852aa68e6ad021c9005c9faf2d7ba6b1b3c8e24efb9c0e8d0");
|
||||
c.set_checkpoints(std::move(checkpoints));
|
||||
|
||||
return true;
|
||||
|
|
|
|||
98
tests/core_tests/pos_fuse_test.cpp
Normal file
98
tests/core_tests/pos_fuse_test.cpp
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "chaingen.h"
|
||||
#include "pos_fuse_test.h"
|
||||
#include "wallet_test_core_proxy.h"
|
||||
|
||||
#include "random_helper.h"
|
||||
#include "wallet/wallet_debug_events_definitions.h"
|
||||
using namespace currency;
|
||||
|
||||
|
||||
using namespace currency;
|
||||
pos_fuse_test::pos_fuse_test()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(pos_fuse_test, c1);
|
||||
REGISTER_CALLBACK_METHOD(pos_fuse_test, configure_core);
|
||||
}
|
||||
|
||||
bool pos_fuse_test::configure_core(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
wallet_test::configure_core(c, ev_index, events);
|
||||
currency::core_runtime_config pc = c.get_blockchain_storage().get_core_runtime_config();
|
||||
pc.max_pos_difficulty = wide_difficulty_type(1);
|
||||
//currency::core_runtime_config pc2;
|
||||
//pc2 = pc;
|
||||
c.get_blockchain_storage().set_core_runtime_config(pc);
|
||||
|
||||
|
||||
currency::core_runtime_config pc2 = c.get_blockchain_storage().get_core_runtime_config();
|
||||
LOG_PRINT_L1("Difficulty: " << pc2.max_pos_difficulty);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pos_fuse_test::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core"); // necessary to set m_hardforks
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 10);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pos_fuse_test::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
bool r = false;
|
||||
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
|
||||
miner_wlt->refresh();
|
||||
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
miner_wlt->refresh();
|
||||
wide_difficulty_type pos_diff = c.get_blockchain_storage().get_next_diff_conditional(true);
|
||||
|
||||
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
|
||||
|
||||
bool r = miner_wlt->try_mint_pos();
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed ot mint pos block");
|
||||
|
||||
currency::core_runtime_config pc = c.get_blockchain_storage().get_core_runtime_config();
|
||||
LOG_PRINT_MAGENTA("POS Difficulty: " << pos_diff << ", max allowed diff: " << pc.max_pos_difficulty, LOG_LEVEL_0);
|
||||
if (pos_diff > pc.max_pos_difficulty)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//check that PoW blocks not going
|
||||
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(!r, false, "PoW block unexpectedly generated");
|
||||
|
||||
//check that PoS blocks not going
|
||||
r = miner_wlt->try_mint_pos();
|
||||
CHECK_AND_ASSERT_MES(!r, false, "PoS block unexpectedly mined");
|
||||
|
||||
try
|
||||
{
|
||||
miner_wlt->transfer(1000000, m_accounts[ALICE_ACC_IDX].get_public_address());
|
||||
CHECK_AND_ASSERT_MES(false, false, "Transaction unexpectedly sent");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_PRINT_L0("Expected exception catched");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
14
tests/core_tests/pos_fuse_test.h
Normal file
14
tests/core_tests/pos_fuse_test.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2014-2024 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 "chaingen.h"
|
||||
#include "wallet_tests_basic.h"
|
||||
|
||||
struct pos_fuse_test : public wallet_test
|
||||
{
|
||||
pos_fuse_test();
|
||||
virtual bool configure_core(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
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);
|
||||
};
|
||||
|
|
@ -939,7 +939,25 @@ bool gen_crypted_attachments::check_crypted_tx(currency::core& c, size_t ev_inde
|
|||
std::vector<payload_items_v> at;
|
||||
bool r = currency::decrypt_payload_items(true, *ptx_from_bc, bob_acc.get_keys(), at);
|
||||
CHECK_EQ(r, true);
|
||||
CHECK_EQ(at.size(), 8); // custom attachments: 1) tx_payer, 2) tx_comment, 3) std::string; system attachments: 4) tx_crypto_checksum; system extra: 5) tx pub key, 6) extra_attachment_info, 7) etc_tx_flags16_t
|
||||
if (at.size() != 16)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for(auto& el : at)
|
||||
ss << " " << el.type().name() << ENDL;
|
||||
LOG_PRINT_RED("at.size() = " << at.size() << " : " << ENDL << ss.str(), LOG_LEVEL_0);
|
||||
|
||||
// expected items:
|
||||
// public_key
|
||||
// etc_tx_flags16_t
|
||||
// tx_derivation_hint x 10
|
||||
// extra_attachment_info
|
||||
// tx_payer
|
||||
// tx_comment
|
||||
// tx_crypto_checksum
|
||||
//
|
||||
// total: 16
|
||||
CHECK_AND_ASSERT_MES(false, false, "unexpected number of decrypted items");
|
||||
}
|
||||
|
||||
currency::tx_payer decrypted_pr = AUTO_VAL_INIT(decrypted_pr);
|
||||
r = get_type_in_variant_container(at, decrypted_pr);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@
|
|||
# make it prominent in the GUI.
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
|
||||
|
||||
if(POLICY CMP0148)
|
||||
cmake_policy(SET CMP0148 OLD)
|
||||
endif()
|
||||
|
||||
# When other libraries are using a shared version of runtime libraries,
|
||||
# Google Test also has to use one.
|
||||
option(
|
||||
|
|
@ -40,7 +44,6 @@ endif()
|
|||
# ${gtest_BINARY_DIR}.
|
||||
# Language "C" is required for find_package(Threads).
|
||||
project(gtest CXX C)
|
||||
cmake_minimum_required(VERSION 2.6.2)
|
||||
|
||||
if (COMMAND set_up_hermetic_build)
|
||||
set_up_hermetic_build()
|
||||
|
|
|
|||
|
|
@ -27,16 +27,24 @@
|
|||
#include "wallet/plain_wallet_api.h"
|
||||
#include "wallet/view_iface.h"
|
||||
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4244)
|
||||
#include "jwt-cpp/jwt.h"
|
||||
POP_VS_WARNINGS
|
||||
|
||||
void test_plain_wallet()
|
||||
{
|
||||
//std::string res = plain_wallet::init("195.201.107.230", "33336", "E:\\tmp\\", 0);
|
||||
std::string res = plain_wallet::init("127.0.0.1", "12111", "C:\\Users\\roky\\home\\", 0);
|
||||
std::string res = plain_wallet::init("127.0.0.1", "12111", "C:\\Users\\roky\\home22\\", 0);
|
||||
|
||||
|
||||
std::string res___ = plain_wallet::get_wallet_files();
|
||||
|
||||
|
||||
uint64_t instance_id = 0;
|
||||
res = plain_wallet::open("test_restored.zan", "111");
|
||||
//res = plain_wallet::restore("heart level clear fate sorrow childhood sent fate ceiling party third steel came ask mix neither message already almost vast date glide tumble color okay space",
|
||||
// "test_restored.zan", "111", "");
|
||||
res = plain_wallet::open("test_restored_2.zan", "111");
|
||||
//res = plain_wallet::restore("",
|
||||
// "test_restored_2.zan", "111", "");
|
||||
|
||||
|
||||
while(true)
|
||||
|
|
@ -49,24 +57,23 @@ void test_plain_wallet()
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
std::string invoke_body = "{\"method\":\"store\",\"params\":{}}";
|
||||
//std::string res1 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
std::string res1 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
invoke_body = "{\"method\":\"get_recent_txs_and_info\",\"params\":{\"offset\":0,\"count\":30,\"update_provision_info\":true}}";
|
||||
std::string res2 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
invoke_body = "{\"method\":\"get_recent_txs_and_info2\",\"params\":{\"offset\":0,\"count\":30,\"update_provision_info\":true}}";
|
||||
res2 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
|
||||
invoke_body = "{\"method\":\"getbalance\",\"params\":{}}";
|
||||
std::string res3 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
|
||||
invoke_body = "{\"method\":\"getbalance\",\"params\":{}}";
|
||||
invoke_body = "{\r\n \"method\": \"transfer\",\r\n \"params\": {\r\n \"destinations\": [\r\n {\r\n \"amount\": \"1000000000000\",\r\n \"address\": \"ZxD9oVwGwW6ULix9Pqttnr7JDpaoLvDVA1KJ9eA9KRxPMRZT5X7WwtU94XH1Z6q6XTMxNbHmbV2xfZ429XxV6fST2DxEg4BQV\",\r\n \"asset_id\": \"cc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6\"\r\n }\r\n ],\r\n \"fee\": 10000000000,\r\n \"mixin\": 10,\r\n \"payment_id\": \"\",\r\n \"comment\": \"\",\r\n \"push_payer\": false,\r\n \"hide_receiver\": true\r\n }\r\n}";
|
||||
std::string res4 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
|
||||
invoke_body = "{\r\n \"method\": \"transfer\",\r\n \"params\": {\r\n \"destinations\": [\r\n {\r\n \"amount\": \"1000000000000\",\r\n \"address\": \"ZxD9oVwGwW6ULix9Pqttnr7JDpaoLvDVA1KJ9eA9KRxPMRZT5X7WwtU94XH1Z6q6XTMxNbHmbV2xfZ429XxV6fST2DxEg4BQV\" }\r\n ],\r\n \"fee\": 10000000000,\r\n \"mixin\": 10,\r\n \"payment_id\": \"\",\r\n \"comment\": \"\",\r\n \"push_payer\": false,\r\n \"hide_receiver\": true\r\n }\r\n}";
|
||||
std::string res5 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
LOG_PRINT_L0(res);
|
||||
|
||||
}
|
||||
|
|
|
|||
8
utils/Directory.Build.props.in
Normal file
8
utils/Directory.Build.props.in
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<UseMultiToolTask>true</UseMultiToolTask>
|
||||
<EnforceProcessCountAcrossBuilds>true</EnforceProcessCountAcrossBuilds>
|
||||
<MultiProcMaxCount>11</MultiProcMaxCount>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
7
utils/configure_win64_msvs2022_gui.cmd
Normal file
7
utils/configure_win64_msvs2022_gui.cmd
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
call configure_local_paths_msvs2022.cmd
|
||||
|
||||
cd ..
|
||||
@mkdir build_msvc2022_64
|
||||
cd build_msvc2022_64
|
||||
|
||||
cmake -D TESTNET=FALSE -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2019_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.3" -G "Visual Studio 17 2022" -A x64 -T host=x64 ".."
|
||||
7
utils/configure_win64_msvs2022_gui_testnet.cmd
Normal file
7
utils/configure_win64_msvs2022_gui_testnet.cmd
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
call configure_local_paths_msvs2022.cmd
|
||||
|
||||
cd ..
|
||||
@mkdir build_msvc2022_64_tn
|
||||
cd build_msvc2022_64_tn
|
||||
|
||||
cmake -D TESTNET=TRUE -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2019_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.3" -G "Visual Studio 17 2022" -A x64 -T host=x64 ".."
|
||||
|
|
@ -27,7 +27,7 @@ function upload_build() # $1 - path to the file to be uploaded
|
|||
counter=0
|
||||
while [ ! -f DONE ]
|
||||
do
|
||||
if [ "$counter" -ge 150 ]
|
||||
if [ "$counter" -ge 500 ]
|
||||
then
|
||||
echo "ERROR: uploading is taking longer than expected"
|
||||
touch STOP
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue