forked from lthn/blockchain
Merge branch 'predevelop' into auditability
This commit is contained in:
commit
638768f31b
30 changed files with 561 additions and 196 deletions
|
|
@ -61,7 +61,7 @@ DISABLE_VS_WARNINGS(4100)
|
|||
|
||||
|
||||
#include "misc_helpers.h"
|
||||
#include "static_initializer.h"
|
||||
#include "static_helpers.h"
|
||||
#include "string_tools.h"
|
||||
#include "time_helper.h"
|
||||
#include "misc_os_dependent.h"
|
||||
|
|
@ -946,8 +946,8 @@ namespace log_space
|
|||
typedef std::map<std::string, uint64_t> channels_err_stat_container_type;
|
||||
inline epee::locked_object_proxy<channels_err_stat_container_type> get_channels_errors_stat_container()
|
||||
{
|
||||
static std::recursive_mutex cs;
|
||||
static channels_err_stat_container_type errors_by_channel;
|
||||
static epee::static_helpers::wrapper<std::recursive_mutex> cs;
|
||||
static epee::static_helpers::wrapper<channels_err_stat_container_type> errors_by_channel;
|
||||
epee::locked_object_proxy<channels_err_stat_container_type> res(errors_by_channel, cs);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1194,7 +1194,7 @@ namespace log_space
|
|||
class log_singletone
|
||||
{
|
||||
public:
|
||||
friend class initializer<log_singletone>;
|
||||
friend class static_helpers::initializer<log_singletone>;
|
||||
friend class logger;
|
||||
static int get_log_detalisation_level()
|
||||
{
|
||||
|
|
@ -1205,7 +1205,7 @@ namespace log_space
|
|||
//get_enabled_channels not thread-safe, at the moment leave it like this because it's configured in main, before other threads started
|
||||
static std::set<std::string>& get_enabled_channels()
|
||||
{
|
||||
static std::set<std::string> genabled_channels;
|
||||
static epee::static_helpers::wrapper<std::set<std::string>> genabled_channels;
|
||||
return genabled_channels;
|
||||
}
|
||||
|
||||
|
|
@ -1611,7 +1611,7 @@ POP_GCC_WARNINGS
|
|||
//static int get_set_error_filter(bool is_need_set = false)
|
||||
};
|
||||
|
||||
const static initializer<log_singletone> log_initializer;
|
||||
const static static_helpers::initializer<log_singletone> log_initializer;
|
||||
/************************************************************************/
|
||||
/* */
|
||||
// /************************************************************************/
|
||||
|
|
|
|||
|
|
@ -925,6 +925,7 @@ using namespace std;
|
|||
class interruptible_http_client : public http_simple_client
|
||||
{
|
||||
std::shared_ptr<idle_handler_base> m_pcb;
|
||||
bool m_permanent_error = false;
|
||||
|
||||
virtual bool handle_target_data(std::string& piece_of_transfer)
|
||||
{
|
||||
|
|
@ -943,6 +944,7 @@ using namespace std;
|
|||
if (p_hri && !(p_hri->m_response_code >= 200 && p_hri->m_response_code < 300))
|
||||
{
|
||||
LOG_PRINT_L0("HTTP request to " << url << " failed with code: " << p_hri->m_response_code);
|
||||
m_permanent_error = true;
|
||||
return false;
|
||||
}
|
||||
return r;
|
||||
|
|
@ -1002,24 +1004,33 @@ using namespace std;
|
|||
};
|
||||
uint64_t current_err_count = 0;
|
||||
bool r = false;
|
||||
|
||||
m_permanent_error = false;
|
||||
while (!r && current_err_count < fails_count)
|
||||
{
|
||||
LOG_PRINT_L0("Attempt to invoke http: " << url << " (offset:" << state_received_bytes_base << ")");
|
||||
LOG_PRINT_L0("Attempt " << current_err_count + 1 << "/" << fails_count << " to get " << url << " (offset:" << state_received_bytes_base << ")");
|
||||
fields_list additional_params_local = additional_params;
|
||||
additional_params_local.push_back(std::make_pair<std::string, std::string>("Range", std::string("bytes=") + std::to_string(state_received_bytes_base) + "-"));
|
||||
r = this->invoke_cb(local_cb, url, timeout, method, body, additional_params_local);
|
||||
if (!r)
|
||||
{
|
||||
if (stopped)
|
||||
if (stopped || m_permanent_error)
|
||||
break;
|
||||
current_err_count++;
|
||||
state_received_bytes_base += state_received_bytes_current;
|
||||
state_received_bytes_current = 0;
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(2000));
|
||||
}
|
||||
}
|
||||
|
||||
if (current_err_count >= fails_count)
|
||||
{
|
||||
LOG_PRINT_YELLOW("Downloading from " << url << " FAILED as it's reached maximum (" << fails_count << ") number of attempts. Downloaded " << state_received_bytes_base << " bytes.", LOG_LEVEL_0);
|
||||
}
|
||||
else if (m_permanent_error)
|
||||
{
|
||||
LOG_PRINT_YELLOW("Downloading from " << url << " FAILED due to permanent HTTP error. Downloaded " << state_received_bytes_base << " bytes.", LOG_LEVEL_0);
|
||||
}
|
||||
|
||||
fs.close();
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,12 +44,17 @@ namespace epee
|
|||
|
||||
const static global_regexp_critical_section gregexplock;
|
||||
|
||||
inline const boost::regex* build_regexp(const char* p, boost::regex::flag_type f)
|
||||
{
|
||||
return new boost::regex(p, f);
|
||||
}
|
||||
|
||||
#define STATIC_REGEXP_EXPR_1(var_name, xpr_text, reg_exp_flags) \
|
||||
static volatile uint32_t regexp_initialized_1 = 0;\
|
||||
volatile uint32_t local_is_initialized_1 = regexp_initialized_1;\
|
||||
if(!local_is_initialized_1)\
|
||||
gregexplock.get_lock().lock();\
|
||||
static const boost::regex var_name(xpr_text , reg_exp_flags);\
|
||||
static const boost::regex& var_name = *build_regexp(xpr_text, reg_exp_flags);\
|
||||
if(!local_is_initialized_1)\
|
||||
{\
|
||||
boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_1, 1);\
|
||||
|
|
@ -61,19 +66,32 @@ namespace epee
|
|||
volatile uint32_t local_is_initialized_2 = regexp_initialized_2;\
|
||||
if(!local_is_initialized_2)\
|
||||
gregexplock.get_lock().lock().lock();\
|
||||
static const boost::regex var_name(xpr_text , reg_exp_flags);\
|
||||
static const boost::regex& var_name = *build_regexp(xpr_text, reg_exp_flags);\
|
||||
if(!local_is_initialized_2)\
|
||||
{\
|
||||
boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_2, 1);\
|
||||
gregexplock.get_lock().lock().unlock();\
|
||||
}
|
||||
|
||||
// #define STATIC_REGEXP_EXPR_2(var_name, xpr_text, reg_exp_flags) \
|
||||
// static volatile uint32_t regexp_initialized_2 = 0;\
|
||||
// volatile uint32_t local_is_initialized_2 = regexp_initialized_2;\
|
||||
// if(!local_is_initialized_2)\
|
||||
// gregexplock.get_lock().lock().lock();\
|
||||
// static const boost::regex var_name(xpr_text , reg_exp_flags);\
|
||||
// if(!local_is_initialized_2)\
|
||||
// {\
|
||||
// boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_2, 1);\
|
||||
// gregexplock.get_lock().lock().unlock();\
|
||||
// }
|
||||
|
||||
|
||||
#define STATIC_REGEXP_EXPR_3(var_name, xpr_text, reg_exp_flags) \
|
||||
static volatile uint32_t regexp_initialized_3 = 0;\
|
||||
volatile uint32_t local_is_initialized_3 = regexp_initialized_3;\
|
||||
if(!local_is_initialized_3)\
|
||||
gregexplock.get_lock().lock().lock();\
|
||||
static const boost::regex var_name(xpr_text , reg_exp_flags);\
|
||||
static const boost::regex& var_name = *build_regexp(xpr_text, reg_exp_flags);\
|
||||
if(!local_is_initialized_3)\
|
||||
{\
|
||||
boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_3, 1);\
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "static_helpers.h"
|
||||
|
||||
template<class owned_object_t>
|
||||
class abstract_singleton
|
||||
|
|
@ -39,7 +39,7 @@ class abstract_singleton
|
|||
|
||||
static std::shared_ptr<owned_object_t> get_set_instance_internal(bool is_need_set = false, owned_object_t* pnew_obj = nullptr)
|
||||
{
|
||||
static std::shared_ptr<owned_object_t> val_pobj;
|
||||
static epee::static_helpers::wrapper<std::shared_ptr<owned_object_t>> val_pobj;
|
||||
|
||||
if (is_need_set)
|
||||
val_pobj.reset(pnew_obj);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// Copyright (c) 2006-2020, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -26,59 +26,76 @@
|
|||
|
||||
|
||||
|
||||
#ifndef _STATIC_INITIALIZER_H_
|
||||
#define _STATIC_INITIALIZER_H_
|
||||
#pragma once
|
||||
#include <limits>
|
||||
#include <set>
|
||||
#include <iterator>
|
||||
#include <boost/thread.hpp>
|
||||
#include "include_base_utils.h"
|
||||
#include "auto_val_init.h"
|
||||
|
||||
#define DEFINE_SECURE_STATIC_VAR(type, var) static epee::static_helpers::wrapper<type> var##inst; \
|
||||
static type& var = var##inst;
|
||||
|
||||
namespace epee
|
||||
{
|
||||
/***********************************************************************
|
||||
class initializer - useful to initialize some static classes
|
||||
which have init() and un_init() static members
|
||||
************************************************************************/
|
||||
namespace static_helpers
|
||||
{
|
||||
template<class to_initialize>
|
||||
class initializer
|
||||
{
|
||||
public:
|
||||
initializer()
|
||||
{
|
||||
to_initialize::init();
|
||||
//get_set_is_initialized(true, true);
|
||||
}
|
||||
~initializer()
|
||||
{
|
||||
to_initialize::un_init();
|
||||
//get_set_is_uninitialized(true, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef void(*static_destroy_handler_type)();
|
||||
|
||||
template<class to_initialize>
|
||||
class initializer
|
||||
{
|
||||
public:
|
||||
initializer()
|
||||
{
|
||||
to_initialize::init();
|
||||
//get_set_is_initialized(true, true);
|
||||
}
|
||||
~initializer()
|
||||
{
|
||||
to_initialize::un_init();
|
||||
//get_set_is_uninitialized(true, true);
|
||||
}
|
||||
inline
|
||||
bool set_or_call_on_destruct(bool set = false, static_destroy_handler_type destr_ptr = nullptr)
|
||||
{
|
||||
volatile static bool deinit_called = false;
|
||||
volatile static static_destroy_handler_type static_destroy_handler = nullptr;
|
||||
|
||||
if (set)
|
||||
{
|
||||
static_destroy_handler = destr_ptr;
|
||||
return true;
|
||||
}
|
||||
if (!deinit_called)
|
||||
{
|
||||
|
||||
if (static_destroy_handler)
|
||||
static_destroy_handler();
|
||||
|
||||
deinit_called = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class t_base>
|
||||
struct wrapper : public t_base
|
||||
{
|
||||
~wrapper()
|
||||
{
|
||||
set_or_call_on_destruct();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*static inline bool is_initialized()
|
||||
{
|
||||
return get_set_is_initialized();
|
||||
}
|
||||
static inline bool is_uninitialized()
|
||||
{
|
||||
return get_set_is_uninitialized();
|
||||
}
|
||||
|
||||
private:
|
||||
static inline bool get_set_is_initialized(bool need_to_set = false, bool val_to_set= false)
|
||||
{
|
||||
static bool val_is_initialized = false;
|
||||
if(need_to_set)
|
||||
val_is_initialized = val_to_set;
|
||||
return val_is_initialized;
|
||||
}
|
||||
static inline bool get_set_is_uninitialized(bool need_to_set = false, bool val_to_set = false)
|
||||
{
|
||||
static bool val_is_uninitialized = false;
|
||||
if(need_to_set)
|
||||
val_is_uninitialized = val_to_set;
|
||||
return val_is_uninitialized;
|
||||
}*/
|
||||
};
|
||||
|
||||
}
|
||||
#endif //_STATIC_INITIALIZER_H_
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
#include <boost/thread/recursive_mutex.hpp>
|
||||
|
||||
#include "singleton.h"
|
||||
#include "static_initializer.h"
|
||||
#include "static_helpers.h"
|
||||
#include "misc_helpers.h"
|
||||
|
||||
//#define DISABLE_DEADLOCK_GUARD
|
||||
|
|
@ -532,7 +532,7 @@ namespace epee
|
|||
}
|
||||
};
|
||||
|
||||
const static initializer<abstract_singleton<deadlock_guard> > singleton_initializer;
|
||||
//const static initializer<abstract_singleton<deadlock_guard> > singleton_initializer;
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
|
|
@ -705,7 +705,8 @@ namespace epee
|
|||
#define EXCLUSIVE_CRITICAL_REGION_LOCAL(x) boost::unique_lock< boost::shared_mutex > critical_region_var(x)
|
||||
|
||||
#define SHARED_CRITICAL_REGION_BEGIN(x) { SHARED_CRITICAL_REGION_LOCAL(x)
|
||||
#define SHARED_CRITICAL_REGION_END() }
|
||||
#define EXCLUSIVE_CRITICAL_REGION_BEGIN(x) { EXCLUSIVE_CRITICAL_REGION_LOCAL(x)
|
||||
|
||||
#define EXCLUSIVE_CRITICAL_REGION_END() }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ epoch_context_full* create_epoch_context(
|
|||
LOG_CUSTOM_WITH_CALLSTACK("CRITICAL: std::calloc(" << alloc_size << ") failed in create_epoch_context()", 0);
|
||||
return nullptr; // Signal out-of-memory by returning null pointer.
|
||||
}
|
||||
LOG_CUSTOM("context for epoch " << epoch_number << " allocated, size: " << alloc_size << " bytes", 0);
|
||||
LOG_CUSTOM("context for epoch " << epoch_number << " allocated, size: " << alloc_size << " bytes, full dataset size: " << full_dataset_size << " bytes", 0);
|
||||
|
||||
hash512* const light_cache = reinterpret_cast<hash512*>(alloc_data + context_alloc_size);
|
||||
const hash256 epoch_seed = calculate_epoch_seed(epoch_number);
|
||||
|
|
|
|||
|
|
@ -105,6 +105,11 @@ namespace tools
|
|||
|
||||
std::string get_callstack_win_x64()
|
||||
{
|
||||
// @TODO@
|
||||
// static epee::static_helpers::wrapper<std::recursive_mutex> cs;
|
||||
static std::recursive_mutex cs;
|
||||
std::lock_guard<std::recursive_mutex> lock(cs);
|
||||
|
||||
HANDLE h_process = GetCurrentProcess();
|
||||
HANDLE h_thread = GetCurrentThread();
|
||||
|
||||
|
|
|
|||
|
|
@ -913,28 +913,48 @@ namespace tools
|
|||
{
|
||||
typedef basic_key_value_accessor<composite_key<t_key, uint64_t>, t_value, is_t_access_strategy> basic_accessor_type;
|
||||
|
||||
// template<class t_key>
|
||||
solo_db_value<composite_key<t_key, guid_key>, uint64_t, basic_accessor_type>
|
||||
get_counter_accessor(const t_key& container_id)
|
||||
get_counter_accessor(const t_key& container_id)
|
||||
{
|
||||
|
||||
static_assert(std::is_pod<t_key>::value, "t_pod_key must be a POD type.");
|
||||
composite_key<t_key, guid_key> cc = { container_id, const_counter_suffix};
|
||||
|
||||
return solo_db_value<composite_key<t_key, guid_key>, uint64_t, basic_accessor_type >(cc, *this);
|
||||
}
|
||||
|
||||
// template<class t_key>
|
||||
const solo_db_value<composite_key<t_key, guid_key>, uint64_t, basic_accessor_type >
|
||||
get_counter_accessor(const t_key& container_id) const
|
||||
get_counter_accessor(const t_key& container_id) const
|
||||
{
|
||||
static_assert(std::is_pod<t_key>::value, "t_pod_key must be a POD type.");
|
||||
composite_key<t_key, guid_key> cc = { container_id, const_counter_suffix };
|
||||
|
||||
static_assert(std::is_pod<t_key>::value, "t_pod_key must be a POD type.");
|
||||
composite_key<t_key, guid_key> cc = { container_id, const_counter_suffix };
|
||||
return solo_db_value<composite_key<t_key, guid_key>, uint64_t, basic_accessor_type >(cc, const_cast<basic_accessor_type&>(static_cast<const basic_accessor_type&>(*this)));
|
||||
}
|
||||
|
||||
return solo_db_value<composite_key<t_key, guid_key>, uint64_t, basic_accessor_type >(cc, const_cast<basic_accessor_type&>(static_cast<const basic_accessor_type&>(*this)));
|
||||
template<typename callback_t>
|
||||
struct subitems_visitor : public i_db_callback
|
||||
{
|
||||
subitems_visitor(callback_t cb)
|
||||
: m_callback(cb)
|
||||
{}
|
||||
|
||||
virtual bool on_enum_item(uint64_t i, const void* key_data, uint64_t key_size, const void* value_data, uint64_t value_size) override
|
||||
{
|
||||
if (key_size != sizeof(composite_key<t_key, uint64_t>))
|
||||
return true; // skip solo values containing items size
|
||||
|
||||
composite_key<t_key, uint64_t> key = AUTO_VAL_INIT(key);
|
||||
key_from_ptr(key, key_data, key_size);
|
||||
|
||||
t_value value = AUTO_VAL_INIT(value);
|
||||
access_strategy_selector<is_t_access_strategy>::from_buff_to_obj(value_data, value_size, value);
|
||||
|
||||
return m_callback(i, key.container_id, key.sufix, value);
|
||||
}
|
||||
|
||||
callback_t m_callback;
|
||||
};
|
||||
|
||||
public:
|
||||
basic_key_to_array_accessor(basic_db_accessor& db) : basic_key_value_accessor<composite_key<t_key, uint64_t>, t_value, is_t_access_strategy>(db)
|
||||
{}
|
||||
|
|
@ -991,6 +1011,14 @@ namespace tools
|
|||
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
template<typename callback_t>
|
||||
void enumerate_subitems(callback_t callback) const
|
||||
{
|
||||
subitems_visitor<callback_t> visitor(callback);
|
||||
basic_accessor_type::bdb.get_backend()->enumerate(basic_accessor_type::m_h, &visitor);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
|
|
|
|||
|
|
@ -34,5 +34,6 @@
|
|||
#define API_RETURN_CODE_WRONG_SEED "WRONG_SEED"
|
||||
#define API_RETURN_CODE_GENESIS_MISMATCH "GENESIS_MISMATCH"
|
||||
#define API_RETURN_CODE_DISCONNECTED "DISCONNECTED"
|
||||
#define API_RETURN_CODE_UNINITIALIZED "UNINITIALIZED"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace tools
|
|||
};
|
||||
|
||||
#ifndef TESTNET
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_lmdb_94_425000.pak", "e6ac69dcf8e7a7017d032cb4326d661c541a3b6a328e6299e6d61c3acde5d49f", 684683820, 1021865984 };
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_mdbx_94_425000.pak", "e1f50efba1149a349eb626037dda30052c0233091693a00a10dd5363d5de1206", 535268266, 1073725440 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_lmdb_94_524999.pak", "ac46a4932813e28fe11ec160a2be4e48c961dce701ecace5133184cff2754d3d", 747173581, 1087696896 };
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_mdbx_94_524999.pak", "b195fdc1bda7173469db0b313f2ead2dbda1788639ba0aedb7001a6cc640fc47", 561335640, 1342156800 };
|
||||
#else
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_testnet_lmdb_96_99000.pak", "9e8522b287ac7637ca770970542e94702f9fbaa267633cfcaeee4383dfe15bd0", 83851119, 131493888 };
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_testnet_mdbx_96_99000.pak", "de33646711f2276e5b22db5741d7b2bf6a8e4c4231d393b730f9a4fce1d7ec03", 63257747, 268431360 };
|
||||
|
|
@ -88,7 +88,7 @@ namespace tools
|
|||
};
|
||||
|
||||
tools::create_directories_if_necessary(working_folder);
|
||||
r = cl.download_and_unzip(cb, downloading_file_path, url, 1000 /* timout */, "GET", std::string(), 3 /* fails count */);
|
||||
r = cl.download_and_unzip(cb, downloading_file_path, url, 5000 /* timout */, "GET", std::string(), 30 /* fails count */);
|
||||
if (!r)
|
||||
{
|
||||
LOG_PRINT_RED("Download failed", LOG_LEVEL_0);
|
||||
|
|
|
|||
|
|
@ -259,14 +259,14 @@ namespace tools
|
|||
|
||||
static void handle_signal()
|
||||
{
|
||||
static std::mutex m_mutex;
|
||||
static epee::static_helpers::wrapper<std::mutex> m_mutex;
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_handler();
|
||||
}
|
||||
|
||||
static void handle_fatal_signal(int sig_number, void* address)
|
||||
{
|
||||
static std::mutex m_mutex_fatal;
|
||||
static epee::static_helpers::wrapper<std::mutex> m_mutex_fatal;
|
||||
std::unique_lock<std::mutex> lock(m_mutex_fatal);
|
||||
m_fatal_handler(sig_number, address);
|
||||
uninstall_fatal();
|
||||
|
|
|
|||
|
|
@ -298,11 +298,19 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
|
|||
bool need_reinit = false;
|
||||
if (m_db_blocks.size() != 0)
|
||||
{
|
||||
#ifndef TESTNET
|
||||
if (m_db_storage_major_compatibility_version == 93 && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 94)
|
||||
{
|
||||
// do not reinit db if moving from version 93 to version 94
|
||||
LOG_PRINT_MAGENTA("DB storage does not need reinit because moving from v93 to v94", LOG_LEVEL_0);
|
||||
}
|
||||
#else
|
||||
if (m_db_storage_major_compatibility_version == 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);
|
||||
}
|
||||
#endif
|
||||
else if (m_db_storage_major_compatibility_version != BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION)
|
||||
{
|
||||
need_reinit = true;
|
||||
|
|
@ -1535,7 +1543,6 @@ bool blockchain_storage::purge_altblock_keyimages_from_big_heap(const block& b,
|
|||
std::shared_ptr<transaction> tx_ptr;
|
||||
if (!get_transaction_from_pool_or_db(tx_id, tx_ptr))
|
||||
{
|
||||
LOG_ERROR("failed to get alt block tx " << tx_id << " on block detach from alts");
|
||||
continue;
|
||||
}
|
||||
transaction& tx = *tx_ptr;
|
||||
|
|
@ -2829,45 +2836,75 @@ void blockchain_storage::print_last_n_difficulty_numbers(uint64_t n) const
|
|||
LOG_PRINT_L0("LAST BLOCKS:" << ss.str());
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::print_blockchain_outs_stat() const
|
||||
void blockchain_storage::print_blockchain_outs_stats() const
|
||||
{
|
||||
LOG_ERROR("NOT IMPLEMENTED YET");
|
||||
// std::stringstream ss;
|
||||
// CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
// BOOST_FOREACH(const outputs_container::value_type& v, m_db_outputs)
|
||||
// {
|
||||
// const std::vector<std::pair<crypto::hash, size_t> >& vals = v.second;
|
||||
// if (vals.size())
|
||||
// {
|
||||
// ss << "amount: " << print_money(v.first);
|
||||
// uint64_t total_count = vals.size();
|
||||
// uint64_t unused_count = 0;
|
||||
// for (size_t i = 0; i != vals.size(); i++)
|
||||
// {
|
||||
// bool used = false;
|
||||
// auto it_tx = m_db_transactions.find(vals[i].first);
|
||||
// if (it_tx == m_db_transactions.end())
|
||||
// {
|
||||
// LOG_ERROR("Tx with id not found " << vals[i].first);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (vals[i].second >= it_tx->second.m_spent_flags.size())
|
||||
// {
|
||||
// LOG_ERROR("Tx with id " << vals[i].first << " in global index have wrong entry in global index, offset in tx = " << vals[i].second
|
||||
// << ", it_tx->second.m_spent_flags.size()=" << it_tx->second.m_spent_flags.size()
|
||||
// << ", it_tx->second.tx.vin.size()=" << it_tx->second.tx.vin.size());
|
||||
// }
|
||||
// used = it_tx->second.m_spent_flags[vals[i].second];
|
||||
//
|
||||
// }
|
||||
// if (!used)
|
||||
// ++unused_count;
|
||||
// }
|
||||
// ss << "\t total: " << total_count << "\t unused: " << unused_count << ENDL;
|
||||
// }
|
||||
// }
|
||||
// LOG_PRINT_L0("OUTS: " << ENDL << ss.str());
|
||||
std::stringstream ss;
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
struct output_stat_t
|
||||
{
|
||||
uint64_t total = 0;
|
||||
uint64_t unspent = 0;
|
||||
uint64_t mixable = 0;
|
||||
};
|
||||
|
||||
std::map<uint64_t, output_stat_t> outputs_stats;
|
||||
|
||||
const uint64_t subitems_cnt = m_db_outputs.size();
|
||||
uint64_t progress = 0;
|
||||
|
||||
auto lambda_handler = [&](uint64_t i, uint64_t amount, uint64_t index, const currency::global_output_entry& output_entry) -> bool
|
||||
{
|
||||
uint64_t progress_current = 20 * i / subitems_cnt;
|
||||
if (progress_current != progress)
|
||||
{
|
||||
progress = progress_current;
|
||||
LOG_PRINT_L0(progress * 5 << "%");
|
||||
}
|
||||
|
||||
auto p_tx = m_db_transactions.find(output_entry.tx_id);
|
||||
if (!p_tx)
|
||||
{
|
||||
LOG_ERROR("tx " << output_entry.tx_id << " not found");
|
||||
return true; // continue
|
||||
}
|
||||
if (output_entry.out_no >= p_tx->m_spent_flags.size())
|
||||
{
|
||||
LOG_ERROR("tx with id " << output_entry.tx_id << " has wrong entry in global index, out_no = " << output_entry.out_no
|
||||
<< ", p_tx->m_spent_flags.size() = " << p_tx->m_spent_flags.size()
|
||||
<< ", p_tx->tx.vin.size() = " << p_tx->tx.vin.size());
|
||||
return true; // continue
|
||||
}
|
||||
if (p_tx->tx.vout.size() != p_tx->m_spent_flags.size())
|
||||
{
|
||||
LOG_ERROR("Tx with id " << output_entry.tx_id << " has wrong entry in global index, out_no = " << output_entry.out_no
|
||||
<< ", p_tx->tx.vout.size() = " << p_tx->tx.vout.size()
|
||||
<< ", p_tx->m_spent_flags.size() = " << p_tx->m_spent_flags.size());
|
||||
return true; // continue
|
||||
}
|
||||
|
||||
auto& stat = outputs_stats[amount];
|
||||
++stat.total;
|
||||
|
||||
bool spent = p_tx->m_spent_flags[output_entry.out_no];
|
||||
if (!spent)
|
||||
++stat.unspent;
|
||||
|
||||
if (!spent && p_tx->tx.vout[output_entry.out_no].target.type() == typeid(txout_to_key))
|
||||
{
|
||||
if (boost::get<txout_to_key>(p_tx->tx.vout[output_entry.out_no].target).mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX)
|
||||
++stat.mixable;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
m_db_outputs.enumerate_subitems(lambda_handler);
|
||||
|
||||
ss << std::right << std::setw(15) << "amount" << std::setw(10) << "total" << std::setw(10) << "unspent" << std::setw(10) << "mixable" << ENDL;
|
||||
for(auto it = outputs_stats.begin(); it != outputs_stats.end(); ++it)
|
||||
ss << std::setw(15) << print_money_brief(it->first) << std::setw(10) << it->second.total << std::setw(10) << it->second.unspent << std::setw(10) << it->second.mixable << ENDL;
|
||||
|
||||
LOG_PRINT_L0("OUTS: " << ENDL << ss.str());
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::print_blockchain_outs(const std::string& file) const
|
||||
|
|
@ -6114,7 +6151,11 @@ bool blockchain_storage::get_transaction_from_pool_or_db(const crypto::hash& tx_
|
|||
if (!m_tx_pool.get_transaction(tx_id, *tx_ptr)) // first try to get from the pool
|
||||
{
|
||||
auto p = m_db_transactions.get(tx_id); // if not found in the pool -- get from the DB
|
||||
CHECK_AND_ASSERT_MES(p != nullptr, false, "can't get tx " << tx_id << " neither from the pool, nor from db_transactions");
|
||||
if (p == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//CHECK_AND_ASSERT_MES(p != nullptr, false, "can't get tx " << tx_id << " neither from the pool, nor from db_transactions");
|
||||
CHECK_AND_ASSERT_MES(p->m_keeper_block_height >= min_allowed_block_height, false, "tx " << tx_id << " found in the main chain at height " << p->m_keeper_block_height << " while required min allowed height is " << min_allowed_block_height);
|
||||
*tx_ptr = p->tx;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ namespace currency
|
|||
void print_blockchain_with_tx(uint64_t start_index, uint64_t end_index) const;
|
||||
void print_blockchain_index() const;
|
||||
void print_blockchain_outs(const std::string& file) const;
|
||||
void print_blockchain_outs_stat() const;
|
||||
void print_blockchain_outs_stats() const;
|
||||
void print_db_cache_perfeormance_data() const;
|
||||
void print_last_n_difficulty_numbers(uint64_t n) const;
|
||||
bool calc_tx_cummulative_blob(const block& bl)const;
|
||||
|
|
|
|||
|
|
@ -19,9 +19,11 @@ namespace currency
|
|||
#ifdef TESTNET
|
||||
ADD_CHECKPOINT(50000, "cb05a7bdc7f78c5cdb6ef1048f85b27c569f44879233903ce5f5a4e5bd590a3d");
|
||||
ADD_CHECKPOINT(100000, "6b8b54356a9d44f6c1ebdacb8593d8f5ab2e2e2ca4493e7ae7baf4b3755c5e16");
|
||||
ADD_CHECKPOINT(350000, "885841f079e5a38f1921f4a5319f0d52fdbab64bb2026ca3cabad1c032d22db7");
|
||||
#else
|
||||
// MAINNET
|
||||
ADD_CHECKPOINT(425000, "46a6c36d5dec2d484d5e4845a8525ca322aafc06915ed9c8da2a241b51b7d1e8");
|
||||
ADD_CHECKPOINT(525000, "8c1ac57e67448130207a224b2d6e33ccdc64d6dd1c59dbcf9ad2361dc0d07d51");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -101,12 +101,14 @@
|
|||
#define RPC_DEFAULT_PORT 11211
|
||||
#define STRATUM_DEFAULT_PORT 11777
|
||||
#define P2P_NETWORK_ID_TESTNET_FLAG 0
|
||||
#define P2P_MAINTAINERS_PUB_KEY "8f138bb73f6d663a3746a542770781a09579a7b84cb4125249e95530824ee607"
|
||||
#else
|
||||
#define P2P_DEFAULT_PORT (11112 + CURRENCY_FORMATION_VERSION)
|
||||
#define RPC_DEFAULT_PORT 12111
|
||||
#define STRATUM_DEFAULT_PORT 11888
|
||||
#define STRARUM_DEFAULT_PORT 51113
|
||||
#define P2P_NETWORK_ID_TESTNET_FLAG 1
|
||||
#define P2P_MAINTAINERS_PUB_KEY "aaa2d7aabc8d383fd53a3ae898697b28f236ceade6bafc1eecff413a6a02272a"
|
||||
#endif
|
||||
|
||||
#define P2P_NETWORK_ID_VER (CURRENCY_FORMATION_VERSION+0)
|
||||
|
|
@ -124,7 +126,6 @@
|
|||
#define P2P_DEFAULT_PING_CONNECTION_TIMEOUT 2000 //2 seconds
|
||||
#define P2P_DEFAULT_INVOKE_TIMEOUT 60*2*1000 //2 minutes
|
||||
#define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT 10000 //10 seconds
|
||||
#define P2P_MAINTAINERS_PUB_KEY "8f138bb73f6d663a3746a542770781a09579a7b84cb4125249e95530824ee607"
|
||||
#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70
|
||||
#define P2P_FAILED_ADDR_FORGET_SECONDS (60*5) //5 minutes
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ namespace currency
|
|||
int64_t get_net_time_delta_median();
|
||||
bool add_time_delta_and_check_time_sync(int64_t delta);
|
||||
bool get_last_time_sync_difference(int64_t& last_median2local_time_difference, int64_t& last_ntp2local_time_difference); // returns true if differences in allowed bounds
|
||||
//-----------------------------------------------------------------------------------
|
||||
void set_to_debug_mode(uint32_t ip);
|
||||
|
||||
private:
|
||||
//----------------- commands handlers ----------------------------------------------
|
||||
|
|
@ -114,6 +116,7 @@ namespace currency
|
|||
std::mutex m_time_deltas_lock;
|
||||
int64_t m_last_median2local_time_difference;
|
||||
int64_t m_last_ntp2local_time_difference;
|
||||
uint32_t m_debug_ip_address;
|
||||
|
||||
template<class t_parametr>
|
||||
bool post_notify(typename t_parametr::request& arg, currency_connection_context& context)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ namespace currency
|
|||
, m_want_stop(false)
|
||||
, m_last_median2local_time_difference(0)
|
||||
, m_last_ntp2local_time_difference(0)
|
||||
, m_debug_ip_address(0)
|
||||
{
|
||||
if(!m_p2p)
|
||||
m_p2p = &m_p2p_stub;
|
||||
|
|
@ -241,6 +242,10 @@ namespace currency
|
|||
template<class t_core>
|
||||
int t_currency_protocol_handler<t_core>::handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& context)
|
||||
{
|
||||
//do not process requests if it comes from node wich is debugged
|
||||
if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address)
|
||||
return 1;
|
||||
|
||||
if(context.m_state != currency_connection_context::state_normal)
|
||||
return 1;
|
||||
|
||||
|
|
@ -363,6 +368,10 @@ namespace currency
|
|||
template<class t_core>
|
||||
int t_currency_protocol_handler<t_core>::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& context)
|
||||
{
|
||||
//do not process requests if it comes from node wich is debugged
|
||||
if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address)
|
||||
return 1;
|
||||
|
||||
if(context.m_state != currency_connection_context::state_normal)
|
||||
return 1;
|
||||
uint64_t inital_tx_count = arg.txs.size();
|
||||
|
|
@ -400,6 +409,10 @@ namespace currency
|
|||
template<class t_core>
|
||||
int t_currency_protocol_handler<t_core>::handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context)
|
||||
{
|
||||
//do not process requests if it comes from node wich is debugged
|
||||
if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address)
|
||||
return 1;
|
||||
|
||||
LOG_PRINT_L2("[HANDLE]NOTIFY_REQUEST_GET_OBJECTS: arg.blocks.size() = " << arg.blocks.size() << ", arg.txs.size()="<< arg.txs.size());
|
||||
LOG_PRINT_L3("[HANDLE]NOTIFY_REQUEST_GET_OBJECTS: " << ENDL << currency::print_kv_structure(arg));
|
||||
|
||||
|
|
@ -445,6 +458,10 @@ namespace currency
|
|||
template<class t_core>
|
||||
int t_currency_protocol_handler<t_core>::handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request& arg, currency_connection_context& context)
|
||||
{
|
||||
//do not process requests if it comes from node wich is debugged
|
||||
if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address)
|
||||
return 1;
|
||||
|
||||
LOG_PRINT_L2("[HANDLE]NOTIFY_RESPONSE_GET_OBJECTS: arg.blocks.size()=" << arg.blocks.size() << ", arg.missed_ids.size()=" << arg.missed_ids.size() << ", arg.txs.size()=" << arg.txs.size());
|
||||
LOG_PRINT_L3("[HANDLE]NOTIFY_RESPONSE_GET_OBJECTS: " << ENDL << currency::print_kv_structure(arg));
|
||||
if(context.m_last_response_height > arg.current_blockchain_height)
|
||||
|
|
@ -627,6 +644,10 @@ namespace currency
|
|||
template<class t_core>
|
||||
int t_currency_protocol_handler<t_core>::handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, currency_connection_context& context)
|
||||
{
|
||||
//do not process requests if it comes from node wich is debugged
|
||||
if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address)
|
||||
return 1;
|
||||
|
||||
LOG_PRINT_L2("[HANDLE]NOTIFY_REQUEST_CHAIN: block_ids.size()=" << arg.block_ids.size());
|
||||
LOG_PRINT_L3("[HANDLE]NOTIFY_REQUEST_CHAIN: " << print_kv_structure(arg));
|
||||
NOTIFY_RESPONSE_CHAIN_ENTRY::request r;
|
||||
|
|
@ -851,10 +872,20 @@ namespace currency
|
|||
|
||||
return !(std::abs(m_last_median2local_time_difference) > TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE && std::abs(m_last_ntp2local_time_difference) > TIME_SYNC_NTP_TO_LOCAL_MAX_DIFFERENCE);
|
||||
}
|
||||
template<class t_core>
|
||||
void t_currency_protocol_handler<t_core>::set_to_debug_mode(uint32_t ip)
|
||||
{
|
||||
m_debug_ip_address = ip;
|
||||
LOG_PRINT_L0("debug mode is set for IP " << epee::string_tools::get_ip_string_from_int32(m_debug_ip_address));
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_core>
|
||||
int t_currency_protocol_handler<t_core>::handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, currency_connection_context& context)
|
||||
{
|
||||
//do not process requests if it comes from node wich is debugged
|
||||
if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address)
|
||||
return 1;
|
||||
|
||||
LOG_PRINT_L2("[HANDLE]NOTIFY_RESPONSE_CHAIN_ENTRY: m_block_ids.size()=" << arg.m_block_ids.size()
|
||||
<< ", m_start_height=" << arg.start_height << ", m_total_height=" << arg.total_height);
|
||||
LOG_PRINT_L3("[HANDLE]NOTIFY_RESPONSE_CHAIN_ENTRY: " << ENDL << currency::print_kv_structure(arg));
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "warnings.h"
|
||||
#include "currency_core/bc_offers_service.h"
|
||||
#include "serialization/binary_utils.h"
|
||||
#include "simplewallet/password_container.h"
|
||||
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4100)
|
||||
|
|
@ -38,7 +39,7 @@ public:
|
|||
//m_cmd_binder.set_handler("print_bci", boost::bind(&daemon_commands_handler::print_bci, this, _1));
|
||||
m_cmd_binder.set_handler("print_bc_outs", boost::bind(&daemon_commands_handler::print_bc_outs, this, _1));
|
||||
m_cmd_binder.set_handler("print_market", boost::bind(&daemon_commands_handler::print_market, this, _1));
|
||||
m_cmd_binder.set_handler("print_bc_outs_stat", boost::bind(&daemon_commands_handler::print_bc_outs_stat, this, _1));
|
||||
m_cmd_binder.set_handler("print_bc_outs_stats", boost::bind(&daemon_commands_handler::print_bc_outs_stats, this, _1));
|
||||
m_cmd_binder.set_handler("print_block", boost::bind(&daemon_commands_handler::print_block, this, _1), "Print block, print_block <block_hash> | <block_height>");
|
||||
m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_commands_handler::print_block_info, this, _1), "Print block info, print_block <block_hash> | <block_height>");
|
||||
m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_commands_handler::print_tx, this, _1), "Print transaction, print_tx <transaction_hash>");
|
||||
|
|
@ -69,7 +70,7 @@ public:
|
|||
m_cmd_binder.set_handler("print_tx_from_hex_blob", boost::bind(&daemon_commands_handler::print_tx_from_hex_blob, this, _1), "Unserialize transaction from hex binary data to json-like representation");
|
||||
m_cmd_binder.set_handler("print_tx_outputs_usage", boost::bind(&daemon_commands_handler::print_tx_outputs_usage, this, _1), "Analyse if tx outputs for involved in subsequent transactions");
|
||||
m_cmd_binder.set_handler("print_difficulties_of_last_n_blocks", boost::bind(&daemon_commands_handler::print_difficulties_of_last_n_blocks, this, _1), "Print difficulties of last n blocks");
|
||||
|
||||
m_cmd_binder.set_handler("debug_remote_node_mode", boost::bind(&daemon_commands_handler::debug_remote_node_mode, this, _1), "<ip-address> - If node got connected put node into 'debug mode' i.e. no sync process of other communication except ping responses, maintenance secrete key will be requested");
|
||||
#ifdef _DEBUG
|
||||
m_cmd_binder.set_handler("debug_set_time_adj", boost::bind(&daemon_commands_handler::debug_set_time_adj, this, _1), "DEBUG: set core time adjustment");
|
||||
#endif
|
||||
|
|
@ -217,9 +218,9 @@ private:
|
|||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool print_bc_outs_stat(const std::vector<std::string>& args)
|
||||
bool print_bc_outs_stats(const std::vector<std::string>& args)
|
||||
{
|
||||
m_srv.get_payload_object().get_core().get_blockchain_storage().print_blockchain_outs_stat();
|
||||
m_srv.get_payload_object().get_core().get_blockchain_storage().print_blockchain_outs_stats();
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
|
|
@ -734,6 +735,24 @@ private:
|
|||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool debug_remote_node_mode(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.empty())
|
||||
{
|
||||
std::cout << "expected: ip address" << std::endl;
|
||||
return true;
|
||||
}
|
||||
uint32_t ip = AUTO_VAL_INIT(ip);
|
||||
if (!string_tools::get_ip_int32_from_string(ip, args.front()))
|
||||
{
|
||||
std::cout << "expected: ip address" << std::endl;
|
||||
return true;
|
||||
}
|
||||
m_srv.get_payload_object().set_to_debug_mode(ip);
|
||||
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool print_pool(const std::vector<std::string>& args)
|
||||
{
|
||||
LOG_PRINT_L0("Pool state: " << ENDL << m_srv.get_payload_object().get_core().print_pool(false));
|
||||
|
|
|
|||
|
|
@ -7214,7 +7214,7 @@ var SendComponent = /** @class */ (function () {
|
|||
return null;
|
||||
}]),
|
||||
comment: new _angular_forms__WEBPACK_IMPORTED_MODULE_1__["FormControl"](''),
|
||||
mixin: new _angular_forms__WEBPACK_IMPORTED_MODULE_1__["FormControl"](0, _angular_forms__WEBPACK_IMPORTED_MODULE_1__["Validators"].required),
|
||||
mixin: new _angular_forms__WEBPACK_IMPORTED_MODULE_1__["FormControl"](10, _angular_forms__WEBPACK_IMPORTED_MODULE_1__["Validators"].required),
|
||||
fee: new _angular_forms__WEBPACK_IMPORTED_MODULE_1__["FormControl"](this.variablesService.default_fee, [_angular_forms__WEBPACK_IMPORTED_MODULE_1__["Validators"].required, function (g) {
|
||||
if ((new bignumber_js__WEBPACK_IMPORTED_MODULE_6__["BigNumber"](g.value)).isLessThan(_this.variablesService.default_fee)) {
|
||||
return { 'less_min': true };
|
||||
|
|
@ -7246,7 +7246,7 @@ var SendComponent = /** @class */ (function () {
|
|||
address: _this.variablesService.currentWallet.send_data['address'],
|
||||
amount: _this.variablesService.currentWallet.send_data['amount'],
|
||||
comment: _this.variablesService.currentWallet.send_data['comment'],
|
||||
mixin: _this.variablesService.currentWallet.send_data['mixin'] || 0,
|
||||
mixin: _this.variablesService.currentWallet.send_data['mixin'] || 10,
|
||||
fee: _this.variablesService.currentWallet.send_data['fee'] || _this.variablesService.default_fee,
|
||||
hide: _this.variablesService.currentWallet.send_data['hide'] || false
|
||||
});
|
||||
|
|
@ -7276,7 +7276,7 @@ var SendComponent = /** @class */ (function () {
|
|||
if (send_status) {
|
||||
_this.modalService.prepareModal('success', 'SEND.SUCCESS_SENT');
|
||||
_this.variablesService.currentWallet.send_data = { address: null, amount: null, comment: null, mixin: null, fee: null, hide: null };
|
||||
_this.sendForm.reset({ address: null, amount: null, comment: null, mixin: 0, fee: _this.variablesService.default_fee, hide: false });
|
||||
_this.sendForm.reset({ address: null, amount: null, comment: null, mixin: 10, fee: _this.variablesService.default_fee, hide: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -7296,7 +7296,7 @@ var SendComponent = /** @class */ (function () {
|
|||
if (send_status) {
|
||||
_this.modalService.prepareModal('success', 'SEND.SUCCESS_SENT');
|
||||
_this.variablesService.currentWallet.send_data = { address: null, amount: null, comment: null, mixin: null, fee: null, hide: null };
|
||||
_this.sendForm.reset({ address: null, amount: null, comment: null, mixin: 0, fee: _this.variablesService.default_fee, hide: false });
|
||||
_this.sendForm.reset({ address: null, amount: null, comment: null, mixin: 10, fee: _this.variablesService.default_fee, hide: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ namespace nodetool
|
|||
m_use_only_priority_peers(false),
|
||||
m_peer_livetime{},
|
||||
m_debug_requests_enabled(false)
|
||||
|
||||
{}
|
||||
|
||||
static void init_options(boost::program_options::options_description& desc);
|
||||
|
|
@ -248,6 +247,7 @@ namespace nodetool
|
|||
bool m_debug_requests_enabled;
|
||||
uint64_t m_startup_time;
|
||||
|
||||
|
||||
//critical_section m_connections_lock;
|
||||
//connections_indexed_container m_connections;
|
||||
|
||||
|
|
|
|||
|
|
@ -1442,6 +1442,7 @@ namespace nodetool
|
|||
std::string s = ss.str();
|
||||
return s;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::on_connection_new(p2p_connection_context& context)
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
#define PROJECT_MAJOR_VERSION "1"
|
||||
#define PROJECT_MINOR_VERSION "1"
|
||||
#define PROJECT_REVISION "5"
|
||||
#define PROJECT_REVISION "6"
|
||||
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
|
||||
|
||||
#define PROJECT_VERSION_BUILD_NO 82
|
||||
#define PROJECT_VERSION_BUILD_NO 87
|
||||
#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 "]"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
#include "wallets_manager.h"
|
||||
#include "common/base58.h"
|
||||
#include "common/config_encrypt_helper.h"
|
||||
#include "static_helpers.h"
|
||||
|
||||
|
||||
#define ANDROID_PACKAGE_NAME "com.zano_mobile"
|
||||
|
||||
|
|
@ -27,21 +29,69 @@
|
|||
#define GENERAL_INTERNAL_ERRROR_INIT "Failed to intialize library"
|
||||
|
||||
//TODO: global objects, subject to refactoring
|
||||
wallets_manager gwm;
|
||||
std::atomic<bool> initialized(false);
|
||||
|
||||
std::atomic<uint64_t> gjobs_counter(1);
|
||||
std::map<uint64_t, std::string> gjobs;
|
||||
epee::critical_section gjobs_lock;
|
||||
std::string gconfig_folder;
|
||||
|
||||
struct plain_wallet_instance
|
||||
{
|
||||
plain_wallet_instance() :initialized(false), gjobs_counter(1)
|
||||
{}
|
||||
wallets_manager gwm;
|
||||
std::atomic<bool> initialized;
|
||||
|
||||
std::atomic<uint64_t> gjobs_counter;
|
||||
std::map<uint64_t, std::string> gjobs;
|
||||
epee::critical_section gjobs_lock;
|
||||
};
|
||||
|
||||
std::shared_ptr<plain_wallet_instance> ginstance_ptr;
|
||||
|
||||
#define GET_INSTANCE_PTR(ptr_name) \
|
||||
auto ptr_name = std::atomic_load(&ginstance_ptr); \
|
||||
if (!ptr_name) \
|
||||
{ \
|
||||
LOG_ERROR("Core already deinitialised or not initialized yet."); \
|
||||
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response); \
|
||||
ok_response.result.return_code = API_RETURN_CODE_UNINITIALIZED; \
|
||||
return epee::serialization::store_t_to_json(ok_response); \
|
||||
}
|
||||
namespace plain_wallet
|
||||
{
|
||||
void deinit();
|
||||
}
|
||||
|
||||
void static_destroy_handler()
|
||||
{
|
||||
std::cout << "[DESTROY CALLBACK HANDLER STARTED]: " << std::endl;
|
||||
plain_wallet::deinit();
|
||||
std::cout << "[DESTROY CALLBACK HANDLER FINISHED]: " << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// #ifdef MOBILE_WALLET_BUILD
|
||||
// void on_lib_unload() __attribute__((destructor));
|
||||
// void on_lib_unload() {
|
||||
// std::cout << "[ON_LIB_UNLOAD]-->>" << ENDL;
|
||||
// plain_wallet::deinit();
|
||||
// std::cout << "[ON_LIB_UNLOAD]<<--" << ENDL;
|
||||
// }
|
||||
// #endif
|
||||
|
||||
namespace plain_wallet
|
||||
{
|
||||
typedef epee::json_rpc::response<epee::json_rpc::dummy_result, error> error_response;
|
||||
|
||||
|
||||
std::string get_set_working_dir(bool need_to_set = false, const std::string val = "")
|
||||
{
|
||||
DEFINE_SECURE_STATIC_VAR(std::string, working_dir);
|
||||
if (need_to_set)
|
||||
working_dir = val;
|
||||
return working_dir;
|
||||
}
|
||||
|
||||
std::string get_bundle_working_dir()
|
||||
{
|
||||
return gconfig_folder;
|
||||
return get_set_working_dir();
|
||||
// #ifdef WIN32
|
||||
// return boost::dll::program_location().parent_path().string();
|
||||
// #elif IOS_BUILD
|
||||
|
|
@ -56,7 +106,7 @@ namespace plain_wallet
|
|||
}
|
||||
void set_bundle_working_dir(const std::string& dir)
|
||||
{
|
||||
gconfig_folder = dir;
|
||||
get_set_working_dir(true, dir);
|
||||
}
|
||||
|
||||
std::string get_wallets_folder()
|
||||
|
|
@ -102,15 +152,39 @@ namespace plain_wallet
|
|||
return "{}";
|
||||
}
|
||||
|
||||
void deinit()
|
||||
{
|
||||
auto local_ptr = std::atomic_load(&ginstance_ptr);
|
||||
if (local_ptr)
|
||||
{
|
||||
std::atomic_store(&ginstance_ptr, std::shared_ptr<plain_wallet_instance>());
|
||||
//wait other callers finish
|
||||
local_ptr->gjobs_lock.lock();
|
||||
local_ptr->gjobs_lock.unlock();
|
||||
bool r = local_ptr->gwm.quick_stop_no_save();
|
||||
std::cout << "[QUICK_STOP_NO_SAVE] return " << r;
|
||||
//let's prepare wallet manager for quick shutdown
|
||||
local_ptr.reset();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::string init(const std::string& ip, const std::string& port, const std::string& working_dir, int log_level)
|
||||
{
|
||||
if (initialized)
|
||||
auto local_ptr = std::atomic_load(&ginstance_ptr);
|
||||
if (local_ptr)
|
||||
{
|
||||
LOG_ERROR("Double-initialization in plain_wallet detected.");
|
||||
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
|
||||
ok_response.result.return_code = API_RETURN_CODE_ALREADY_EXISTS;
|
||||
return epee::serialization::store_t_to_json(ok_response);
|
||||
}
|
||||
|
||||
epee::static_helpers::set_or_call_on_destruct(true, static_destroy_handler);
|
||||
|
||||
std::cout << "[INIT PLAIN_WALLET_INSTANCE]" << ENDL;
|
||||
std::shared_ptr<plain_wallet_instance> ptr(new plain_wallet_instance());
|
||||
|
||||
set_bundle_working_dir(working_dir);
|
||||
|
||||
initialize_logs(log_level);
|
||||
|
|
@ -122,13 +196,13 @@ namespace plain_wallet
|
|||
args[1] = const_cast<char*>(argss_1.c_str());
|
||||
args[2] = const_cast<char*>(argss_2.c_str());
|
||||
args[3] = nullptr;
|
||||
if (!gwm.init(3, args, nullptr))
|
||||
if (!ptr->gwm.init(3, args, nullptr))
|
||||
{
|
||||
LOG_ERROR("Failed to init wallets_manager");
|
||||
return GENERAL_INTERNAL_ERRROR_INIT;
|
||||
}
|
||||
|
||||
if(!gwm.start())
|
||||
if(!ptr->gwm.start())
|
||||
{
|
||||
LOG_ERROR("Failed to start wallets_manager");
|
||||
return GENERAL_INTERNAL_ERRROR_INIT;
|
||||
|
|
@ -155,7 +229,7 @@ namespace plain_wallet
|
|||
return epee::serialization::store_t_to_json(err_result);
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
std::atomic_store(&ginstance_ptr, ptr);
|
||||
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
|
||||
ok_response.result.return_code = API_RETURN_CODE_OK;
|
||||
return epee::serialization::store_t_to_json(ok_response);
|
||||
|
|
@ -215,7 +289,9 @@ namespace plain_wallet
|
|||
|
||||
std::string get_connectivity_status()
|
||||
{
|
||||
return gwm.get_connectivity_status();
|
||||
GET_INSTANCE_PTR(inst_ptr);
|
||||
|
||||
return inst_ptr->gwm.get_connectivity_status();
|
||||
}
|
||||
|
||||
std::string get_version()
|
||||
|
|
@ -254,16 +330,18 @@ namespace plain_wallet
|
|||
|
||||
std::string open(const std::string& path, const std::string& password)
|
||||
{
|
||||
GET_INSTANCE_PTR(inst_ptr);
|
||||
|
||||
std::string full_path = get_wallets_folder() + path;
|
||||
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
|
||||
std::string rsp = gwm.open_wallet(epee::string_encoding::convert_to_unicode(full_path), password, 20, ok_response.result);
|
||||
std::string rsp = inst_ptr->gwm.open_wallet(epee::string_encoding::convert_to_unicode(full_path), password, 20, ok_response.result);
|
||||
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
|
||||
{
|
||||
if (rsp == API_RETURN_CODE_FILE_RESTORED)
|
||||
{
|
||||
ok_response.result.recovered = true;
|
||||
}
|
||||
gwm.run_wallet(ok_response.result.wallet_id);
|
||||
inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
|
||||
|
||||
return epee::serialization::store_t_to_json(ok_response);
|
||||
}
|
||||
|
|
@ -271,18 +349,21 @@ namespace plain_wallet
|
|||
err_result.error.code = rsp;
|
||||
return epee::serialization::store_t_to_json(err_result);
|
||||
}
|
||||
|
||||
std::string restore(const std::string& seed, const std::string& path, const std::string& password)
|
||||
{
|
||||
GET_INSTANCE_PTR(inst_ptr);
|
||||
|
||||
std::string full_path = get_wallets_folder() + path;
|
||||
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
|
||||
std::string rsp = gwm.restore_wallet(epee::string_encoding::convert_to_unicode(full_path), password, seed, ok_response.result);
|
||||
std::string rsp = inst_ptr->gwm.restore_wallet(epee::string_encoding::convert_to_unicode(full_path), password, seed, ok_response.result);
|
||||
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
|
||||
{
|
||||
if (rsp == API_RETURN_CODE_FILE_RESTORED)
|
||||
{
|
||||
ok_response.result.recovered = true;
|
||||
}
|
||||
gwm.run_wallet(ok_response.result.wallet_id);
|
||||
inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
|
||||
return epee::serialization::store_t_to_json(ok_response);
|
||||
}
|
||||
error_response err_result = AUTO_VAL_INIT(err_result);
|
||||
|
|
@ -292,16 +373,18 @@ namespace plain_wallet
|
|||
|
||||
std::string generate(const std::string& path, const std::string& password)
|
||||
{
|
||||
GET_INSTANCE_PTR(inst_ptr);
|
||||
|
||||
std::string full_path = get_wallets_folder() + path;
|
||||
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
|
||||
std::string rsp = gwm.generate_wallet(epee::string_encoding::convert_to_unicode(full_path), password, ok_response.result);
|
||||
std::string rsp = inst_ptr->gwm.generate_wallet(epee::string_encoding::convert_to_unicode(full_path), password, ok_response.result);
|
||||
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
|
||||
{
|
||||
if (rsp == API_RETURN_CODE_FILE_RESTORED)
|
||||
{
|
||||
ok_response.result.recovered = true;
|
||||
}
|
||||
gwm.run_wallet(ok_response.result.wallet_id);
|
||||
inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
|
||||
return epee::serialization::store_t_to_json(ok_response);
|
||||
}
|
||||
error_response err_result = AUTO_VAL_INIT(err_result);
|
||||
|
|
@ -311,34 +394,44 @@ namespace plain_wallet
|
|||
|
||||
std::string close_wallet(hwallet h)
|
||||
{
|
||||
GET_INSTANCE_PTR(inst_ptr);
|
||||
|
||||
std::string r = "{\"response\": \"";
|
||||
r += gwm.close_wallet(h);
|
||||
r += inst_ptr->gwm.close_wallet(h);
|
||||
r += "\"}";
|
||||
return r;
|
||||
}
|
||||
|
||||
std::string get_wallet_status(hwallet h)
|
||||
{
|
||||
return gwm.get_wallet_status(h);
|
||||
GET_INSTANCE_PTR(inst_ptr);
|
||||
return inst_ptr->gwm.get_wallet_status(h);
|
||||
}
|
||||
|
||||
std::string invoke(hwallet h, const std::string& params)
|
||||
{
|
||||
return gwm.invoke(h, params);
|
||||
GET_INSTANCE_PTR(inst_ptr);
|
||||
return inst_ptr->gwm.invoke(h, params);
|
||||
}
|
||||
|
||||
void put_result(uint64_t job_id, const std::string& res)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(gjobs_lock);
|
||||
gjobs[job_id] = res;
|
||||
auto inst_ptr = std::atomic_load(&ginstance_ptr);
|
||||
if (!inst_ptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CRITICAL_REGION_LOCAL(inst_ptr->gjobs_lock);
|
||||
inst_ptr->gjobs[job_id] = res;
|
||||
LOG_PRINT_L2("[ASYNC_CALL]: Finished(result put), job id: " << job_id);
|
||||
}
|
||||
|
||||
|
||||
std::string async_call(const std::string& method_name, uint64_t instance_id, const std::string& params)
|
||||
{
|
||||
GET_INSTANCE_PTR(inst_ptr);
|
||||
std::function<void()> async_callback;
|
||||
|
||||
uint64_t job_id = gjobs_counter++;
|
||||
uint64_t job_id = inst_ptr->gjobs_counter++;
|
||||
if (method_name == "close")
|
||||
{
|
||||
async_callback = [job_id, instance_id]()
|
||||
|
|
@ -413,17 +506,22 @@ namespace plain_wallet
|
|||
|
||||
std::string try_pull_result(uint64_t job_id)
|
||||
{
|
||||
//TODO: need refactoring
|
||||
CRITICAL_REGION_LOCAL(gjobs_lock);
|
||||
auto it = gjobs.find(job_id);
|
||||
if (it == gjobs.end())
|
||||
{
|
||||
return "{\"delivered\": false}";
|
||||
auto inst_ptr = std::atomic_load(&ginstance_ptr);
|
||||
if (!inst_ptr)
|
||||
{
|
||||
return "{\"status\": \"canceled\"}";
|
||||
}
|
||||
std::string res = "{\"delivered\": true, \"result\": ";
|
||||
//TODO: need refactoring
|
||||
CRITICAL_REGION_LOCAL(inst_ptr->gjobs_lock);
|
||||
auto it = inst_ptr->gjobs.find(job_id);
|
||||
if (it == inst_ptr->gjobs.end())
|
||||
{
|
||||
return "{\"status\": \"idle\"}";
|
||||
}
|
||||
std::string res = "{\"status\": \"delivered\", \"result\": ";
|
||||
res += it->second;
|
||||
res += " }";
|
||||
gjobs.erase(it);
|
||||
inst_ptr->gjobs.erase(it);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -432,6 +432,7 @@ public:
|
|||
std::string seed;
|
||||
bool recovered;
|
||||
uint64_t wallet_local_bc_size;
|
||||
uint64_t wallet_file_size;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallet_id)
|
||||
|
|
@ -440,6 +441,7 @@ public:
|
|||
KV_SERIALIZE(seed)
|
||||
KV_SERIALIZE(recovered)
|
||||
KV_SERIALIZE(wallet_local_bc_size)
|
||||
KV_SERIALIZE(wallet_file_size)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1083,7 +1083,8 @@ void wallet2::process_unconfirmed(const currency::transaction& tx, std::vector<s
|
|||
void wallet2::process_new_blockchain_entry(const currency::block& b, const currency::block_direct_data_entry& bche, const crypto::hash& bl_id, uint64_t height)
|
||||
{
|
||||
//handle transactions from new block
|
||||
THROW_IF_TRUE_WALLET_EX(height != get_blockchain_current_size() && !(height == m_minimum_height && get_blockchain_current_size() <= 1), error::wallet_internal_error,
|
||||
THROW_IF_TRUE_WALLET_EX(height != get_blockchain_current_size() &&
|
||||
!(height == m_minimum_height || get_blockchain_current_size() <= 1), error::wallet_internal_error,
|
||||
"current_index=" + std::to_string(height) + ", get_blockchain_current_height()=" + std::to_string(get_blockchain_current_size()));
|
||||
|
||||
//optimization: seeking only for blocks that are not older then the wallet creation time plus 1 day. 1 day is for possible user incorrect time setup
|
||||
|
|
@ -1242,9 +1243,18 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop
|
|||
crypto::hash bl_id = get_block_hash(bl);
|
||||
|
||||
if (processed_blocks_count != 1 && height > processed_blocks_count)
|
||||
{//internal error:
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(false,
|
||||
"height{" << height <<"} > processed_blocks_count{" << processed_blocks_count << "}");
|
||||
{
|
||||
if (height != m_minimum_height)
|
||||
{
|
||||
//internal error:
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(false,
|
||||
"height{" << height << "} > processed_blocks_count{" << processed_blocks_count << "}");
|
||||
}
|
||||
else
|
||||
{
|
||||
//possible case, wallet rewound to m_minimum_height
|
||||
m_chain.clear();
|
||||
}
|
||||
}
|
||||
else if (height == processed_blocks_count)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -359,7 +359,10 @@ namespace wallet_public
|
|||
|
||||
struct response
|
||||
{
|
||||
uint64_t wallet_file_size;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallet_file_size)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -345,6 +345,8 @@ namespace tools
|
|||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
m_wallet.store();
|
||||
boost::system::error_code ec = AUTO_VAL_INIT(ec);
|
||||
res.wallet_file_size = boost::filesystem::file_size(m_wallet.get_wallet_path(), ec);
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
#include <chrono>
|
||||
#include "wallets_manager.h"
|
||||
#include "currency_core/alias_helper.h"
|
||||
#ifndef MOBILE_WALLET_BUILD
|
||||
|
|
@ -33,7 +33,12 @@
|
|||
return API_RETURN_CODE_WALLET_WRONG_ID; \
|
||||
auto& name = it->second.w;
|
||||
|
||||
#define DAEMON_IDLE_UPDATE_TIME_MS 2000
|
||||
#ifdef MOBILE_WALLET_BUILD
|
||||
#define DAEMON_IDLE_UPDATE_TIME_MS 10000
|
||||
#else
|
||||
#define DAEMON_IDLE_UPDATE_TIME_MS 2000
|
||||
#endif
|
||||
|
||||
#define HTTP_PROXY_TIMEOUT 2000
|
||||
#define HTTP_PROXY_ATTEMPTS_COUNT 1
|
||||
|
||||
|
|
@ -56,7 +61,8 @@ wallets_manager::wallets_manager():m_pview(&m_view_stub),
|
|||
m_ui_opt(AUTO_VAL_INIT(m_ui_opt)),
|
||||
m_remote_node_mode(false),
|
||||
m_is_pos_allowed(false),
|
||||
m_qt_logs_enbaled(false)
|
||||
m_qt_logs_enbaled(false),
|
||||
dont_save_wallet_at_stop(false)
|
||||
{
|
||||
#ifndef MOBILE_WALLET_BUILD
|
||||
m_offers_service.set_disabled(true);
|
||||
|
|
@ -87,6 +93,7 @@ wallets_manager::~wallets_manager()
|
|||
{
|
||||
TRY_ENTRY();
|
||||
stop();
|
||||
LOG_PRINT_L0("[~WALLETS_MANAGER] destroyed");
|
||||
CATCH_ENTRY_NO_RETURN();
|
||||
}
|
||||
|
||||
|
|
@ -280,13 +287,6 @@ bool wallets_manager::start()
|
|||
CATCH_ENTRY_L0("main", false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wallets_manager::send_stop_signal()
|
||||
{
|
||||
m_stop_singal_sent = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wallets_manager::stop()
|
||||
|
|
@ -297,12 +297,17 @@ bool wallets_manager::stop()
|
|||
LOG_PRINT_L0("Waiting for backend main worker thread: " << m_main_worker_thread.get_id());
|
||||
m_main_worker_thread.join();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wallets_manager::quick_stop_no_save() //stop without storing wallets
|
||||
{
|
||||
dont_save_wallet_at_stop = true;
|
||||
return stop();
|
||||
}
|
||||
|
||||
std::string wallets_manager::get_config_folder()
|
||||
{
|
||||
return m_data_dir;
|
||||
|
|
@ -345,7 +350,10 @@ bool wallets_manager::init_local_daemon()
|
|||
|
||||
return static_cast<bool>(m_stop_singal_sent);
|
||||
});
|
||||
CHECK_AND_ASSERT_AND_SET_GUI(res, "pre-downloading failed");
|
||||
if (!res)
|
||||
{
|
||||
LOG_PRINT_RED("pre-downloading failed, continue with normal network synchronization", LOG_LEVEL_0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -497,6 +505,25 @@ void wallets_manager::main_worker(const po::variables_map& m_vm)
|
|||
|
||||
|
||||
SHARED_CRITICAL_REGION_BEGIN(m_wallets_lock);
|
||||
//first send stop signal to all wallets
|
||||
for (auto& wo : m_wallets)
|
||||
{
|
||||
try
|
||||
{
|
||||
wo.second.stop(false);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_ERROR("Exception rised at storing wallet: " << e.what());
|
||||
continue;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_ERROR("Exception rised at storing wallet");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& wo : m_wallets)
|
||||
{
|
||||
LOG_PRINT_L0("Storing wallet data...");
|
||||
|
|
@ -504,11 +531,9 @@ void wallets_manager::main_worker(const po::variables_map& m_vm)
|
|||
//m_pview->update_daemon_status(dsi);
|
||||
try
|
||||
{
|
||||
wo.second.major_stop = true;
|
||||
wo.second.stop_for_refresh = true;
|
||||
wo.second.w.unlocked_get()->stop();
|
||||
|
||||
wo.second.w->get()->store();
|
||||
wo.second.stop();
|
||||
if(!dont_save_wallet_at_stop)
|
||||
wo.second.w->get()->store();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
|
@ -605,13 +630,34 @@ void wallets_manager::toggle_pos_mining()
|
|||
//update_wallets_info();
|
||||
}
|
||||
|
||||
bool wallets_manager::send_stop_signal()
|
||||
{
|
||||
m_stop_singal_sent = true;
|
||||
m_stop_singal_sent_mutex_cv.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void wallets_manager::loop()
|
||||
{
|
||||
while(!m_stop_singal_sent)
|
||||
|
||||
while (!m_stop_singal_sent)
|
||||
{
|
||||
update_state_info();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(DAEMON_IDLE_UPDATE_TIME_MS));
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(m_stop_singal_sent_mutex);
|
||||
m_stop_singal_sent_mutex_cv.wait_for(lk, std::chrono::microseconds(DAEMON_IDLE_UPDATE_TIME_MS), [&] {return m_stop_singal_sent.load(); });
|
||||
}
|
||||
if (!m_stop_singal_sent)
|
||||
{
|
||||
update_state_info();
|
||||
}
|
||||
|
||||
}
|
||||
// while(!m_stop_singal_sent)
|
||||
// {
|
||||
// update_state_info();
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(DAEMON_IDLE_UPDATE_TIME_MS));
|
||||
// }
|
||||
}
|
||||
|
||||
void wallets_manager::init_wallet_entry(wallet_vs_options& wo, uint64_t id)
|
||||
|
|
@ -732,6 +778,16 @@ std::string wallets_manager::get_my_offers(const bc_services::core_offers_filter
|
|||
|
||||
std::string wallets_manager::open_wallet(const std::wstring& path, const std::string& password, uint64_t txs_to_return, view::open_wallet_response& owr)
|
||||
{
|
||||
// check if that file already opened
|
||||
SHARED_CRITICAL_REGION_BEGIN(m_wallets_lock);
|
||||
for (auto& wallet_entry : m_wallets)
|
||||
{
|
||||
if (wallet_entry.second.w.unlocked_get()->get_wallet_path() == path)
|
||||
return API_RETURN_CODE_ALREADY_EXISTS;
|
||||
}
|
||||
SHARED_CRITICAL_REGION_END();
|
||||
|
||||
|
||||
std::shared_ptr<tools::wallet2> w(new tools::wallet2());
|
||||
owr.wallet_id = m_wallet_id_counter++;
|
||||
|
||||
|
|
@ -788,6 +844,8 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
|
|||
}
|
||||
}
|
||||
EXCLUSIVE_CRITICAL_REGION_LOCAL(m_wallets_lock);
|
||||
boost::system::error_code ec = AUTO_VAL_INIT(ec);
|
||||
owr.wallet_file_size = boost::filesystem::file_size(path, ec);
|
||||
wallet_vs_options& wo = m_wallets[owr.wallet_id];
|
||||
**wo.w = w;
|
||||
get_wallet_info(wo, owr.wi);
|
||||
|
|
@ -840,7 +898,6 @@ std::string wallets_manager::generate_wallet(const std::wstring& path, const std
|
|||
#else
|
||||
LOG_ERROR("Unexpected location reached");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
try
|
||||
|
|
@ -1802,14 +1859,22 @@ void wallets_manager::wallet_vs_options::worker_func()
|
|||
}
|
||||
LOG_PRINT_GREEN("[WALLET_HANDLER] Wallet thread thread stopped", LOG_LEVEL_0);
|
||||
}
|
||||
wallets_manager::wallet_vs_options::~wallet_vs_options()
|
||||
void wallets_manager::wallet_vs_options::stop(bool wait)
|
||||
{
|
||||
w.unlocked_get()->stop();
|
||||
do_mining = false;
|
||||
major_stop = true;
|
||||
stop_for_refresh = true;
|
||||
break_mining_loop = true;
|
||||
if (miner_thread.joinable())
|
||||
miner_thread.join();
|
||||
if (wait)
|
||||
{
|
||||
if (miner_thread.joinable())
|
||||
miner_thread.join();
|
||||
}
|
||||
}
|
||||
wallets_manager::wallet_vs_options::~wallet_vs_options()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
std::string wallets_manager::get_wallet_log_prefix(size_t wallet_id) const
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ public:
|
|||
std::atomic<bool>* plast_daemon_is_disconnected;
|
||||
std::atomic<bool> has_related_alias_in_unconfirmed;
|
||||
std::atomic<bool> need_to_update_wallet_info;
|
||||
|
||||
std::atomic<bool> long_refresh_in_progress;
|
||||
epee::critical_section long_refresh_in_progress_lock; //secure wallet state and prevent from long wait while long refresh is in work
|
||||
|
||||
|
|
@ -81,6 +80,7 @@ public:
|
|||
|
||||
std::thread miner_thread;
|
||||
void worker_func();
|
||||
void stop(bool wait = true);
|
||||
std::string get_log_prefix() const { return std::string("[") + epee::string_tools::num_to_string_fast(wallet_id) + ":" + w->get()->get_log_prefix() + "]"; }
|
||||
~wallet_vs_options();
|
||||
};
|
||||
|
|
@ -90,6 +90,7 @@ public:
|
|||
bool init(int argc, char* argv[], view::i_view* pview_handler);
|
||||
bool start();
|
||||
bool stop();
|
||||
bool quick_stop_no_save(); //stop without storing wallets
|
||||
bool send_stop_signal();
|
||||
std::string open_wallet(const std::wstring& path, const std::string& password, uint64_t txs_to_return, view::open_wallet_response& owr);
|
||||
std::string generate_wallet(const std::wstring& path, const std::string& password, view::open_wallet_response& owr);
|
||||
|
|
@ -173,7 +174,11 @@ private:
|
|||
virtual void on_transfer_canceled(size_t wallet_id, const tools::wallet_public::wallet_transfer_info& wti);
|
||||
|
||||
std::thread m_main_worker_thread;
|
||||
|
||||
std::atomic<bool> m_stop_singal_sent;
|
||||
std::mutex m_stop_singal_sent_mutex;
|
||||
std::condition_variable m_stop_singal_sent_mutex_cv;
|
||||
|
||||
view::i_view m_view_stub;
|
||||
view::i_view* m_pview;
|
||||
std::shared_ptr<tools::i_core_proxy> m_rpc_proxy;
|
||||
|
|
@ -184,6 +189,7 @@ private:
|
|||
std::atomic<bool> m_last_daemon_is_disconnected;
|
||||
// std::atomic<uint64_t> m_last_wallet_synch_height;
|
||||
std::atomic<uint64_t> m_wallet_id_counter;
|
||||
std::atomic<bool> dont_save_wallet_at_stop;
|
||||
|
||||
std::string m_data_dir;
|
||||
view::gui_options m_ui_opt;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue