Merge branch 'release'
|
|
@ -376,7 +376,7 @@ namespace epee
|
|||
bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "")
|
||||
{
|
||||
async_console_handler console_handler;
|
||||
return console_handler.run(ptsrv, boost::bind<bool>(no_srv_param_adapter<t_server, t_handler>, _1, _2, handlr), prompt, usage);
|
||||
return console_handler.run(ptsrv, boost::bind<bool>(no_srv_param_adapter<t_server, t_handler>, boost::placeholders::_1, boost::placeholders::_2, handlr), prompt, usage);
|
||||
}
|
||||
|
||||
template<class t_server, class t_handler>
|
||||
|
|
@ -460,7 +460,7 @@ namespace epee
|
|||
/*template<class t_srv>
|
||||
bool start_handling(t_srv& srv, const std::string& usage_string = "")
|
||||
{
|
||||
start_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, _1));
|
||||
start_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, boost::placeholders::_1));
|
||||
return true;
|
||||
}*/
|
||||
|
||||
|
|
@ -489,7 +489,7 @@ namespace epee
|
|||
/*template<class t_srv>
|
||||
bool run_handling(t_srv& srv, const std::string& usage_string)
|
||||
{
|
||||
return run_default_console_handler_no_srv_param(&srv, boost::bind<bool>(&console_handlers_binder::process_command_str, this, _1), usage_string);
|
||||
return run_default_console_handler_no_srv_param(&srv, boost::bind<bool>(&console_handlers_binder::process_command_str, this, boost::placeholders::_1), usage_string);
|
||||
}*/
|
||||
};
|
||||
|
||||
|
|
@ -510,7 +510,7 @@ namespace epee
|
|||
|
||||
bool run_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string)
|
||||
{
|
||||
return m_console_handler.run(psrv, boost::bind(&srv_console_handlers_binder<t_server>::process_command_str, this, _1, _2), prompt, usage_string);
|
||||
return m_console_handler.run(psrv, boost::bind(&srv_console_handlers_binder<t_server>::process_command_str, this, boost::placeholders::_1, boost::placeholders::_2), prompt, usage_string);
|
||||
}
|
||||
|
||||
void stop_handling()
|
||||
|
|
|
|||
40
contrib/epee/include/serialization/keyvalue_helper_structs.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) 2006-2021, 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
|
||||
|
||||
namespace epee
|
||||
{
|
||||
|
||||
template<class _Ty1, class _Ty2>
|
||||
struct kvserializable_pair : public std::pair<_Ty1, _Ty2>
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(first)
|
||||
KV_SERIALIZE(second)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ DISABLE_VS_WARNINGS(4996)
|
|||
POP_VS_WARNINGS
|
||||
|
||||
if(pt)
|
||||
strftime( tmpbuf, 199, "%Y_%m_%d %H_%M_%S", pt );
|
||||
strftime( tmpbuf, 199, "%Y-%m-%d %H-%M-%S", pt );
|
||||
else
|
||||
{
|
||||
std::stringstream strs;
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 652 KiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 287 KiB |
|
Before Width: | Height: | Size: 330 KiB After Width: | Height: | Size: 439 KiB |
|
Before Width: | Height: | Size: 604 KiB After Width: | Height: | Size: 805 KiB |
|
|
@ -151,7 +151,7 @@ namespace command_line
|
|||
}
|
||||
|
||||
template<typename F>
|
||||
bool handle_error_helper(const boost::program_options::options_description& desc, F parser)
|
||||
bool handle_error_helper(const boost::program_options::options_description& desc, std::string& err, F parser)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -159,6 +159,7 @@ namespace command_line
|
|||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
err = e.what();
|
||||
std::cerr << "Failed to parse arguments: " << e.what() << std::endl;
|
||||
std::cerr << desc << std::endl;
|
||||
return false;
|
||||
|
|
@ -171,6 +172,13 @@ namespace command_line
|
|||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
bool handle_error_helper(const boost::program_options::options_description& desc, F parser)
|
||||
{
|
||||
std::string stub_err;
|
||||
return handle_error_helper(desc, stub_err, parser);
|
||||
}
|
||||
|
||||
template<typename T, bool required>
|
||||
bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -143,9 +143,10 @@ namespace tools
|
|||
else
|
||||
{
|
||||
int res = 0;
|
||||
//MDBX_txn_flags_t flags = MDBX_txn_flags_t();
|
||||
unsigned int flags = 0;
|
||||
if (read_only)
|
||||
flags += MDBX_RDONLY;
|
||||
flags = MDBX_RDONLY;//flags = MDBX_TXN_RDONLY;
|
||||
|
||||
//don't use parent tx in write transactions if parent tx was read-only (restriction in mdbx)
|
||||
//see "Nested transactions: Max 1 child, write txns only, no writemap"
|
||||
|
|
@ -340,7 +341,9 @@ namespace tools
|
|||
data[0].iov_base = (void*)v;
|
||||
data[0].iov_len = vs;
|
||||
|
||||
res = mdbx_put(get_current_tx(), static_cast<MDBX_dbi>(h), &key, data, 0);
|
||||
//MDBX_put_flags_t flags = MDBX_put_flags_t();
|
||||
unsigned flags = 0;
|
||||
res = mdbx_put(get_current_tx(), static_cast<MDBX_dbi>(h), &key, data, flags);
|
||||
CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_put");
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,8 +70,7 @@ namespace currency
|
|||
iv = *((crypto::chacha8_iv*)&pass_hash);
|
||||
crypto::chacha8(scr_data, src_length, key, iv, (char*)dst_data);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
std::string account_base::get_seed_phrase(const std::string& password) const
|
||||
{
|
||||
if (m_keys_seed_binary.empty())
|
||||
|
|
|
|||
|
|
@ -578,13 +578,13 @@ bool blockchain_storage::set_checkpoints(checkpoints&& chk_pts)
|
|||
catch (const std::exception& ex)
|
||||
{
|
||||
m_db.abort_transaction();
|
||||
LOG_ERROR("UNKNOWN EXCEPTION WHILE ADDINIG NEW BLOCK: " << ex.what());
|
||||
LOG_ERROR("UNKNOWN EXCEPTION WHILE SETTING CHECKPOINTS: " << ex.what());
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
m_db.abort_transaction();
|
||||
LOG_ERROR("UNKNOWN EXCEPTION WHILE ADDINIG NEW BLOCK.");
|
||||
LOG_ERROR("UNKNOWN EXCEPTION WHILE SETTING CHECKPOINTS.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -594,7 +594,7 @@ bool blockchain_storage::prune_ring_signatures_and_attachments(uint64_t height,
|
|||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
CHECK_AND_ASSERT_MES(height < m_db_blocks.size(), false, "prune_ring_signatures called with wrong parameter: " << height << ", m_blocks.size() " << m_db_blocks.size());
|
||||
CHECK_AND_ASSERT_MES(height < m_db_blocks.size(), false, "prune_ring_signatures called with wrong parameter: " << height << ", m_blocks.size() = " << m_db_blocks.size());
|
||||
auto vptr = m_db_blocks[height];
|
||||
CHECK_AND_ASSERT_MES(vptr.get(), false, "Failed to get block on height");
|
||||
|
||||
|
|
@ -626,22 +626,20 @@ bool blockchain_storage::prune_ring_signatures_and_attachments_if_need()
|
|||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
if (m_db_blocks.size() > 1 && m_checkpoints.get_top_checkpoint_height() && m_checkpoints.get_top_checkpoint_height() > m_db_current_pruned_rs_height)
|
||||
{
|
||||
uint64_t pruning_last_height = std::min(m_db_blocks.size() - 1, m_checkpoints.get_top_checkpoint_height());
|
||||
if (pruning_last_height > m_db_current_pruned_rs_height)
|
||||
uint64_t top_block_height = get_top_block_height();
|
||||
uint64_t pruning_end_height = m_checkpoints.get_checkpoint_before_height(top_block_height);
|
||||
if (pruning_end_height > m_db_current_pruned_rs_height)
|
||||
{
|
||||
LOG_PRINT_CYAN("Starting pruning ring signatues and attachments from height " << m_db_current_pruned_rs_height + 1 << " to height " << pruning_end_height
|
||||
<< " (" << pruning_end_height - m_db_current_pruned_rs_height << " blocks), top block height is " << top_block_height, LOG_LEVEL_0);
|
||||
uint64_t tx_count = 0, sig_count = 0, attach_count = 0;
|
||||
for(uint64_t height = m_db_current_pruned_rs_height + 1; height <= pruning_end_height; height++)
|
||||
{
|
||||
LOG_PRINT_CYAN("Starting pruning ring signatues and attachments from height " << m_db_current_pruned_rs_height + 1 << " to height " << pruning_last_height
|
||||
<< " (" << pruning_last_height - m_db_current_pruned_rs_height << " blocks)", LOG_LEVEL_0);
|
||||
uint64_t tx_count = 0, sig_count = 0, attach_count = 0;
|
||||
for(uint64_t height = m_db_current_pruned_rs_height + 1; height <= pruning_last_height; height++)
|
||||
{
|
||||
bool res = prune_ring_signatures_and_attachments(height, tx_count, sig_count, attach_count);
|
||||
CHECK_AND_ASSERT_MES(res, false, "failed to prune_ring_signatures_and_attachments for height = " << height);
|
||||
}
|
||||
m_db_current_pruned_rs_height = pruning_last_height;
|
||||
LOG_PRINT_CYAN("Transaction pruning finished: " << sig_count << " signatures and " << attach_count << " attachments released in " << tx_count << " transactions.", LOG_LEVEL_0);
|
||||
bool res = prune_ring_signatures_and_attachments(height, tx_count, sig_count, attach_count);
|
||||
CHECK_AND_ASSERT_MES(res, false, "failed to prune_ring_signatures_and_attachments for height = " << height);
|
||||
}
|
||||
m_db_current_pruned_rs_height = pruning_end_height;
|
||||
LOG_PRINT_CYAN("Transaction pruning finished: " << sig_count << " signatures and " << attach_count << " attachments released in " << tx_count << " transactions.", LOG_LEVEL_0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1036,7 +1034,9 @@ void blockchain_storage::purge_alt_block_txs_hashs(const block& b)
|
|||
//------------------------------------------------------------------
|
||||
void blockchain_storage::do_erase_altblock(alt_chain_container::iterator it)
|
||||
{
|
||||
purge_altblock_keyimages_from_big_heap(it->second.bl, get_block_hash(it->second.bl));
|
||||
crypto::hash id = get_block_hash(it->second.bl);
|
||||
LOG_PRINT_L1("erasing alt block " << print16(id) << " @ " << get_block_height(it->second.bl));
|
||||
purge_altblock_keyimages_from_big_heap(it->second.bl, id);
|
||||
purge_alt_block_txs_hashs(it->second.bl);
|
||||
m_alternative_chains.erase(it);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ namespace currency
|
|||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(*block_ind_ptr < m_db_blocks.size(), false, "Internal error: bl_id=" << string_tools::pod_to_hex(bl_id)
|
||||
<< " have index record with offset=" << *block_ind_ptr << ", bigger then m_blocks.size()=" << m_db_blocks.size());
|
||||
<< " have index record with offset=" << *block_ind_ptr << ", bigger then m_db_blocks.size()=" << m_db_blocks.size());
|
||||
blocks.push_back(m_db_blocks[*block_ind_ptr]->bl);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@ namespace currency
|
|||
if(height > blockchain_last_block_height)
|
||||
return false;
|
||||
|
||||
auto it = m_points.lower_bound(height);
|
||||
auto it = m_points.lower_bound(height); // if found, it->first >= height
|
||||
if(it == m_points.end())
|
||||
return false;
|
||||
if(it->first <= blockchain_last_block_height)
|
||||
return true;
|
||||
return true; // this is the case only if height <= it->first <= blockchain_last_block_height
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
|
@ -68,4 +68,27 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
uint64_t checkpoints::get_checkpoint_before_height(uint64_t height) const
|
||||
{
|
||||
// returns height of the leftmost CP with height that is LESS than the given height
|
||||
// ex:
|
||||
// If there are two CP at 11 and 15:
|
||||
// get_checkpoint_before_height(10) = 0
|
||||
// get_checkpoint_before_height(11) = 0
|
||||
// get_checkpoint_before_height(12) = 11
|
||||
// get_checkpoint_before_height(13) = 11
|
||||
// get_checkpoint_before_height(14) = 11
|
||||
// get_checkpoint_before_height(15) = 11
|
||||
// get_checkpoint_before_height(16) = 15
|
||||
|
||||
uint64_t top_cp = get_top_checkpoint_height();
|
||||
if (height > top_cp)
|
||||
return top_cp;
|
||||
|
||||
auto it = m_points.lower_bound(height); // if found, it->first >= height
|
||||
if (it == m_points.end() || it == m_points.begin())
|
||||
return 0;
|
||||
return (--it)->first;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ namespace currency
|
|||
bool is_height_passed_zone(uint64_t height, uint64_t blockchain_last_block_height) const;
|
||||
bool check_block(uint64_t height, const crypto::hash& h) const;
|
||||
uint64_t get_top_checkpoint_height() const;
|
||||
|
||||
uint64_t get_checkpoint_before_height(uint64_t height) const;
|
||||
private:
|
||||
std::map<uint64_t, crypto::hash> m_points;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@
|
|||
#define MINER_CONFIG_FILENAME "miner_conf.json"
|
||||
#define GUI_SECURE_CONFIG_FILENAME "gui_secure_conf.bin"
|
||||
#define GUI_CONFIG_FILENAME "gui_settings.json"
|
||||
#define GUI_INTERNAL_CONFIG "gui_internal_config.bin"
|
||||
#define GUI_INTERNAL_CONFIG2 "gui_internal_config.json"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -914,7 +914,8 @@ namespace currency
|
|||
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with \r\nm_total_height=" << arg.total_height
|
||||
<< "\r\nm_start_height=" << arg.start_height
|
||||
<< "\r\nm_block_ids.size()=" << arg.m_block_ids.size());
|
||||
//m_p2p->drop_connection(context);
|
||||
m_p2p->drop_connection(context);
|
||||
m_p2p->add_ip_fail(context.m_remote_ip);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(auto& bl_details, arg.m_block_ids)
|
||||
|
|
|
|||
|
|
@ -45,10 +45,19 @@
|
|||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string></string>
|
||||
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>ZanoApp</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>zano</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 109 KiB |
|
|
@ -387,9 +387,9 @@ void MainWindow::changeEvent(QEvent *e)
|
|||
bool MainWindow::store_app_config()
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::string conf_path = m_backend.get_config_folder() + "/" + GUI_INTERNAL_CONFIG;
|
||||
LOG_PRINT_L0("storing gui internal config from " << conf_path);
|
||||
CHECK_AND_ASSERT_MES(tools::serialize_obj_to_file(m_config, conf_path), false, "failed to store gui internal config");
|
||||
std::string conf_path = m_backend.get_config_folder() + "/" + GUI_INTERNAL_CONFIG2;
|
||||
LOG_PRINT_L0("storing gui internal config to " << conf_path);
|
||||
CHECK_AND_ASSERT_MES(epee::serialization::store_t_to_json_file(m_config, conf_path), false, "failed to store gui internal config");
|
||||
return true;
|
||||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
|
@ -397,9 +397,9 @@ bool MainWindow::store_app_config()
|
|||
bool MainWindow::load_app_config()
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::string conf_path = m_backend.get_config_folder() + "/" + GUI_INTERNAL_CONFIG;
|
||||
std::string conf_path = m_backend.get_config_folder() + "/" + GUI_INTERNAL_CONFIG2;
|
||||
LOG_PRINT_L0("loading gui internal config from " << conf_path);
|
||||
bool r = tools::unserialize_obj_from_file(m_config, conf_path);
|
||||
bool r = epee::serialization::load_t_from_json_file(m_config, conf_path);
|
||||
LOG_PRINT_L0("gui internal config " << (r ? "loaded ok" : "was not loaded"));
|
||||
return r;
|
||||
CATCH_ENTRY2(false);
|
||||
|
|
@ -548,15 +548,29 @@ void MainWindow::restore_pos(bool consider_showed)
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
QPoint pos;
|
||||
QSize sz;
|
||||
pos.setX(m_config.m_window_position.first);
|
||||
pos.setY(m_config.m_window_position.second);
|
||||
sz.setHeight(m_config.m_window_size.first);
|
||||
sz.setWidth(m_config.m_window_size.second);
|
||||
this->move(pos);
|
||||
this->resize(sz);
|
||||
QPoint point = QApplication::desktop()->screenGeometry().bottomRight();
|
||||
if (m_config.m_window_position.first + m_config.m_window_size.second > point.x() ||
|
||||
m_config.m_window_position.second + m_config.m_window_size.first > point.y()
|
||||
)
|
||||
{
|
||||
QSize sz = AUTO_VAL_INIT(sz);
|
||||
sz.setHeight(770);
|
||||
sz.setWidth(1200);
|
||||
this->resize(sz);
|
||||
store_window_pos();
|
||||
//reset position(screen changed or other reason)
|
||||
}
|
||||
else
|
||||
{
|
||||
QPoint pos = AUTO_VAL_INIT(pos);
|
||||
QSize sz = AUTO_VAL_INIT(sz);
|
||||
pos.setX(m_config.m_window_position.first);
|
||||
pos.setY(m_config.m_window_position.second);
|
||||
sz.setHeight(m_config.m_window_size.first);
|
||||
sz.setWidth(m_config.m_window_size.second);
|
||||
this->move(pos);
|
||||
this->resize(sz);
|
||||
}
|
||||
}
|
||||
|
||||
if (consider_showed)
|
||||
|
|
@ -643,14 +657,16 @@ bool MainWindow::show_inital()
|
|||
restore_pos(true);
|
||||
else
|
||||
{
|
||||
m_config = AUTO_VAL_INIT(m_config);
|
||||
this->show();
|
||||
QSize sz;
|
||||
QSize sz = AUTO_VAL_INIT(sz);
|
||||
sz.setHeight(770);
|
||||
sz.setWidth(1200);
|
||||
this->resize(sz);
|
||||
store_window_pos();
|
||||
m_config.is_maximazed = false;
|
||||
m_config.is_showed = true;
|
||||
m_config.disable_notifications = false;
|
||||
}
|
||||
return true;
|
||||
CATCH_ENTRY2(false);
|
||||
|
|
@ -727,14 +743,26 @@ void qt_log_message_handler(QtMsgType type, const QMessageLogContext &context, c
|
|||
bool MainWindow::init_backend(int argc, char* argv[])
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if (!m_backend.init_command_line(argc, argv))
|
||||
std::string command_line_fail_details;
|
||||
if (!m_backend.init_command_line(argc, argv, command_line_fail_details))
|
||||
{
|
||||
this->show_msg_box(command_line_fail_details);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!init_window())
|
||||
{
|
||||
this->show_msg_box("Failed to main screen launch, check logs for the more detais.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_backend.init(this))
|
||||
{
|
||||
this->show_msg_box("Failed to initialize backend, check debug logs for more details.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (m_backend.is_qt_logs_enabled())
|
||||
{
|
||||
|
|
@ -811,8 +839,25 @@ bool MainWindow::nativeEventFilter(const QByteArray &eventType, void *message, l
|
|||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool MainWindow::get_is_disabled_notifications()
|
||||
{
|
||||
return m_config.disable_notifications;
|
||||
}
|
||||
bool MainWindow::set_is_disabled_notifications(const bool& param)
|
||||
{
|
||||
m_config.disable_notifications = param;
|
||||
return m_config.disable_notifications;
|
||||
}
|
||||
QString MainWindow::export_wallet_history(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::export_wallet_info, ewi);
|
||||
PREPARE_RESPONSE(view::api_response, ar);
|
||||
ar.error_code = m_backend.export_wallet_history(ewi);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
bool MainWindow::update_wallets_info(const view::wallets_summary_info& wsi)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -834,6 +879,10 @@ bool MainWindow::money_transfer(const view::transfer_event_info& tei)
|
|||
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());
|
||||
QMetaObject::invokeMethod(this, "money_transfer", Qt::QueuedConnection, Q_ARG(QString, json_str.c_str()));
|
||||
if (m_config.disable_notifications)
|
||||
return true;
|
||||
|
||||
|
||||
if (!m_tray_icon)
|
||||
return true;
|
||||
if (!tei.ti.is_income)
|
||||
|
|
@ -852,7 +901,7 @@ bool MainWindow::money_transfer(const view::transfer_event_info& tei)
|
|||
return true;
|
||||
}
|
||||
|
||||
auto amount_str = currency::print_money(tei.ti.amount);
|
||||
auto amount_str = currency::print_money_brief(tei.ti.amount);
|
||||
std::string title, msg;
|
||||
if (tei.ti.height == 0) // unconfirmed trx
|
||||
{
|
||||
|
|
@ -869,6 +918,7 @@ bool MainWindow::money_transfer(const view::transfer_event_info& tei)
|
|||
else if (tei.ti.unlock_time)
|
||||
msg += m_localization[localization_id_locked];
|
||||
|
||||
|
||||
show_notification(title, msg);
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <QWebChannel>
|
||||
|
||||
#include "wallet/view_iface.h"
|
||||
#include "serialization/keyvalue_helper_structs.h"
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include "wallet/wallets_manager.h"
|
||||
|
|
@ -60,10 +61,20 @@ public:
|
|||
|
||||
struct app_config
|
||||
{
|
||||
std::pair<int64_t, int64_t> m_window_position;
|
||||
std::pair<int64_t, int64_t> m_window_size;
|
||||
|
||||
epee::kvserializable_pair<int64_t, int64_t> m_window_position;
|
||||
epee::kvserializable_pair<int64_t, int64_t> m_window_size;
|
||||
bool is_maximazed;
|
||||
bool is_showed;
|
||||
bool disable_notifications;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(m_window_position)
|
||||
KV_SERIALIZE(m_window_size)
|
||||
KV_SERIALIZE(is_maximazed)
|
||||
KV_SERIALIZE(is_showed)
|
||||
KV_SERIALIZE(disable_notifications)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
protected slots:
|
||||
|
|
@ -150,6 +161,10 @@ public:
|
|||
QString get_default_fee();
|
||||
QString get_options();
|
||||
void bool_toggle_icon(const QString& param);
|
||||
|
||||
bool get_is_disabled_notifications();
|
||||
bool set_is_disabled_notifications(const bool& param);
|
||||
QString export_wallet_history(const QString& param);
|
||||
QString get_log_file();
|
||||
QString check_available_sources(const QString& param);
|
||||
QString open_url_in_browser(const QString& param);
|
||||
|
|
@ -176,6 +191,7 @@ signals:
|
|||
void do_dispatch(const QString status, const QString params); //general function
|
||||
void on_core_event(const QString method_name); //general function
|
||||
void set_options(const QString str); //general function
|
||||
void get_wallet_name();
|
||||
|
||||
private:
|
||||
//-------------------- i_core_event_handler --------------------
|
||||
|
|
@ -254,7 +270,7 @@ private:
|
|||
|
||||
enum localization_string_indices
|
||||
{
|
||||
// order is surprizingly important here! (see also updateLocalisation in AppController.js)
|
||||
// order is surprisingly important here! (see also updateLocalisation in AppController.js)
|
||||
localization_id_quit = 0,
|
||||
localization_id_is_received,
|
||||
localization_id_is_confirmed,
|
||||
|
|
|
|||
18
src/gui/qt-daemon/application/urleventfilter.cpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#include "urleventfilter.h"
|
||||
#include <QMessageBox>
|
||||
|
||||
bool URLEventFilter::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::FileOpen) {
|
||||
QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event);
|
||||
if(!fileEvent->url().isEmpty())
|
||||
{
|
||||
QMessageBox msg;
|
||||
msg.setText(fileEvent->url().toString());
|
||||
msg.exec();
|
||||
}
|
||||
} else {
|
||||
// standard event processing
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
};
|
||||
12
src/gui/qt-daemon/application/urleventfilter.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include <QObject>
|
||||
#include <QFileOpenEvent>
|
||||
#include <QDebug>
|
||||
|
||||
class URLEventFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
URLEventFilter() : QObject(){};
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
};
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit b028252d30a32e80c12fa890c306d3c5842e937a
|
||||
Subproject commit 93802cb8fe1c79daf320aa4b72ba454d27da31d7
|
||||
|
|
@ -12,7 +12,9 @@
|
|||
//#include "qtlogger.h"
|
||||
#include "include_base_utils.h"
|
||||
#include "currency_core/currency_config.h"
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
#include "application/urleventfilter.h"
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
|
@ -26,6 +28,9 @@ int main(int argc, char *argv[])
|
|||
// See http://crbug.com/436603.
|
||||
// _set_FMA3_enable(0);
|
||||
//#endif // ARCH_CPU_X86_64 && _MSC_VER <= 1800
|
||||
|
||||
if(argc > 1)
|
||||
std::cout << argv[1] << std::endl;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _WIN64
|
||||
|
|
@ -61,12 +66,18 @@ int main(int argc, char *argv[])
|
|||
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
URLEventFilter url_event_filter;
|
||||
app.installEventFilter(&url_event_filter);
|
||||
#endif
|
||||
|
||||
MainWindow viewer;
|
||||
if (!viewer.init_backend(argc, argv))
|
||||
{
|
||||
static_cast<view::i_view*>(&viewer)->show_msg_box("Failed to initialize backend, check debug logs for more details.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
app.installNativeEventFilter(&viewer);
|
||||
viewer.setWindowTitle(CURRENCY_NAME_BASE);
|
||||
viewer.show_inital();
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@ namespace nodetool
|
|||
m_last_stat_request_time{},
|
||||
m_use_only_priority_peers(false),
|
||||
m_peer_livetime{},
|
||||
m_debug_requests_enabled(false)
|
||||
m_debug_requests_enabled(false),
|
||||
m_ip_auto_blocking_enabled(false)
|
||||
{}
|
||||
|
||||
static void init_options(boost::program_options::options_description& desc);
|
||||
|
|
@ -215,6 +216,8 @@ namespace nodetool
|
|||
bool urgent_alert_worker();
|
||||
bool critical_alert_worker();
|
||||
bool remove_dead_connections();
|
||||
bool is_ip_good_for_adding_to_peerlist(uint32_t adress);
|
||||
bool is_ip_in_blacklist(uint32_t adress);
|
||||
|
||||
|
||||
//debug functions
|
||||
|
|
@ -245,6 +248,7 @@ namespace nodetool
|
|||
bool m_hide_my_port;
|
||||
bool m_offline_mode;
|
||||
bool m_debug_requests_enabled;
|
||||
bool m_ip_auto_blocking_enabled;
|
||||
uint64_t m_startup_time;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,18 +26,19 @@ namespace nodetool
|
|||
|
||||
namespace
|
||||
{
|
||||
const command_line::arg_descriptor<std::string> arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"};
|
||||
const command_line::arg_descriptor<std::string> arg_p2p_bind_port = {"p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)};
|
||||
const command_line::arg_descriptor<uint32_t> arg_p2p_external_port = {"p2p-external-port", "External port for p2p network protocol (if port forwarding used with NAT)", 0};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"};
|
||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"};
|
||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_priority_node = {"add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"};
|
||||
const command_line::arg_descriptor<std::string> arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"};
|
||||
const command_line::arg_descriptor<std::string> arg_p2p_bind_port = {"p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)};
|
||||
const command_line::arg_descriptor<uint32_t> arg_p2p_external_port = {"p2p-external-port", "External port for p2p network protocol (if port forwarding used with NAT)", 0};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"};
|
||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"};
|
||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_priority_node = {"add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_use_only_priority_nodes = {"use-only-priority-nodes", "Try to connect only to priority nodes"};
|
||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_offline_mode = { "offline-mode", "Don't connect to any node and reject any connections", false, true };
|
||||
const command_line::arg_descriptor<bool> arg_p2p_disable_debug_reqs = { "disable-debug-p2p-requests", "Disable p2p debug requests", false, true };
|
||||
}
|
||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_offline_mode = { "offline-mode", "Don't connect to any node and reject any connections", false, true };
|
||||
const command_line::arg_descriptor<bool> arg_p2p_disable_debug_reqs = { "disable-debug-p2p-requests", "Disable p2p debug requests", false, true };
|
||||
const command_line::arg_descriptor<uint32_t> arg_p2p_ip_auto_blocking = { "p2p-ip-auto-blocking", "Enable (1) or disable (0) peers auto-blocking by IP <0|1>. Default: 0", 0, false };
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
|
|
@ -53,7 +54,8 @@ namespace nodetool
|
|||
command_line::add_arg(desc, arg_p2p_hide_my_port);
|
||||
command_line::add_arg(desc, arg_p2p_offline_mode);
|
||||
command_line::add_arg(desc, arg_p2p_disable_debug_reqs);
|
||||
command_line::add_arg(desc, arg_p2p_use_only_priority_nodes);
|
||||
command_line::add_arg(desc, arg_p2p_use_only_priority_nodes);
|
||||
command_line::add_arg(desc, arg_p2p_ip_auto_blocking);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
|
|
@ -65,7 +67,14 @@ namespace nodetool
|
|||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse P2P_MAINTAINERS_PUB_KEY = " << P2P_MAINTAINERS_PUB_KEY);
|
||||
|
||||
std::string state_file_path = m_config_folder + "/" + P2P_NET_DATA_FILENAME;
|
||||
tools::unserialize_obj_from_file(*this, state_file_path);
|
||||
boost::system::error_code ec = AUTO_VAL_INIT(ec);
|
||||
std::time_t last_update_time = boost::filesystem::last_write_time(state_file_path, ec);
|
||||
//let's assume that if p2p peer list file stored more then 2 weeks ago,
|
||||
//then it outdated and we need to fetch peerlist from seed nodes
|
||||
if (!ec && time(nullptr) - last_update_time < 86400 * 14)
|
||||
{
|
||||
tools::unserialize_obj_from_file(*this, state_file_path);
|
||||
}
|
||||
|
||||
//always use new id, to be able differ cloned computers
|
||||
m_config.m_peer_id = crypto::rand<uint64_t>();
|
||||
|
|
@ -100,21 +109,39 @@ namespace nodetool
|
|||
if (m_offline_mode)
|
||||
return false;
|
||||
|
||||
//@#@ temporary workaround
|
||||
return true;
|
||||
#if 0
|
||||
if (!m_ip_auto_blocking_enabled)
|
||||
return true;
|
||||
|
||||
return !is_ip_in_blacklist(addr);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::is_ip_good_for_adding_to_peerlist(uint32_t addr)
|
||||
{
|
||||
if (m_offline_mode)
|
||||
return false;
|
||||
|
||||
// even if IP auto blocking is disabled, bad peers should not be added to peerlists and be shared with other nodes
|
||||
|
||||
return !is_ip_in_blacklist(addr);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::is_ip_in_blacklist(uint32_t addr)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_blocked_ips_lock);
|
||||
auto it = m_blocked_ips.find(addr);
|
||||
if(it == m_blocked_ips.end())
|
||||
return true;
|
||||
if(time(nullptr) - it->second > P2P_IP_BLOCKTIME )
|
||||
if (it == m_blocked_ips.end())
|
||||
return false;
|
||||
|
||||
if (time(nullptr) - it->second > P2P_IP_BLOCKTIME)
|
||||
{
|
||||
m_blocked_ips.erase(it);
|
||||
LOG_PRINT_CYAN("Ip " << string_tools::get_ip_string_from_int32(addr) << "is unblocked.", LOG_LEVEL_0);
|
||||
return true;
|
||||
LOG_PRINT_CYAN("IP " << string_tools::get_ip_string_from_int32(addr) << " is unblocked due to blocking expiration.", LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
|
|
@ -122,7 +149,8 @@ namespace nodetool
|
|||
{
|
||||
CRITICAL_REGION_LOCAL(m_blocked_ips_lock);
|
||||
m_blocked_ips[addr] = time(nullptr);
|
||||
LOG_PRINT_CYAN("Ip " << string_tools::get_ip_string_from_int32(addr) << " blocked.", LOG_LEVEL_0);
|
||||
m_peerlist.remove_peers_by_ip_from_all(addr);
|
||||
LOG_PRINT_CYAN("IP " << string_tools::get_ip_string_from_int32(addr) << " blocked and removed from peerlist", LOG_LEVEL_0);
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
|
@ -138,6 +166,10 @@ namespace nodetool
|
|||
it->second = P2P_IP_FAILS_BEFOR_BLOCK/2;
|
||||
block_ip(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_PRINT_CYAN("IP " << string_tools::get_ip_string_from_int32(address) << ": fail recorded, total fails count: " << fails, LOG_LEVEL_2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
|
@ -162,6 +194,9 @@ namespace nodetool
|
|||
m_allow_local_ip = command_line::get_arg(vm, arg_p2p_allow_local_ip);
|
||||
m_offline_mode = command_line::get_arg(vm, arg_p2p_offline_mode);
|
||||
m_debug_requests_enabled = !command_line::get_arg(vm, arg_p2p_disable_debug_reqs);
|
||||
m_ip_auto_blocking_enabled = (command_line::get_arg(vm, arg_p2p_ip_auto_blocking) != 0);
|
||||
|
||||
LOG_PRINT_L0("p2p peers auto-blocking is " << (m_ip_auto_blocking_enabled ? "enabled" : "disabled"));
|
||||
|
||||
if (m_offline_mode)
|
||||
{
|
||||
|
|
@ -679,7 +714,6 @@ namespace nodetool
|
|||
<< string_tools::get_ip_string_from_int32(na.ip)
|
||||
<< ":" << string_tools::num_to_string_fast(na.port)
|
||||
/*<< ", try " << try_count*/);
|
||||
//m_peerlist.set_peer_unreachable(pe);
|
||||
return false;
|
||||
}
|
||||
peerid_type pi = AUTO_VAL_INIT(pi);
|
||||
|
|
@ -701,12 +735,15 @@ namespace nodetool
|
|||
return true;
|
||||
}
|
||||
|
||||
peerlist_entry pe_local = AUTO_VAL_INIT(pe_local);
|
||||
pe_local.adr = na;
|
||||
pe_local.id = pi;
|
||||
time(&pe_local.last_seen);
|
||||
m_peerlist.append_with_peer_white(pe_local);
|
||||
//update last seen and push it to peerlist manager
|
||||
if (is_ip_good_for_adding_to_peerlist(na.ip)) // additional check to avoid IP shown up in peers in the case of non-blocking incoming connections
|
||||
{
|
||||
//update last seen and push it to peerlist manager
|
||||
peerlist_entry pe_local = AUTO_VAL_INIT(pe_local);
|
||||
pe_local.adr = na;
|
||||
pe_local.id = pi;
|
||||
time(&pe_local.last_seen);
|
||||
m_peerlist.append_with_peer_white(pe_local);
|
||||
}
|
||||
|
||||
LOG_PRINT_CC_GREEN(con, "CONNECTION HANDSHAKED OK with peer " << string_tools::get_ip_string_from_int32(na.ip) << ":" << string_tools::num_to_string_fast(na.port), LOG_LEVEL_2);
|
||||
return true;
|
||||
|
|
@ -1373,7 +1410,8 @@ namespace nodetool
|
|||
//associate peer_id with this connection
|
||||
context.peer_id = arg.node_data.peer_id;
|
||||
|
||||
if(arg.node_data.peer_id != m_config.m_peer_id && arg.node_data.my_port)
|
||||
if(arg.node_data.peer_id != m_config.m_peer_id && arg.node_data.my_port
|
||||
&& is_ip_good_for_adding_to_peerlist(context.m_remote_ip))
|
||||
{
|
||||
peerid_type peer_id_l = arg.node_data.peer_id;
|
||||
uint32_t port_l = arg.node_data.my_port;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2019 Zano Project
|
||||
// Copyright (c) 2014-2021 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
|
||||
|
|
@ -11,8 +11,6 @@
|
|||
#include <map>
|
||||
#include <iterator>
|
||||
#include <boost/foreach.hpp>
|
||||
//#include <boost/bimap.hpp>
|
||||
//#include <boost/bimap/multiset_of.hpp>
|
||||
#include <boost/archive/binary_oarchive.hpp>
|
||||
#include <boost/archive/binary_iarchive.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
|
|
@ -55,10 +53,10 @@ namespace nodetool
|
|||
bool append_with_peer_gray(const peerlist_entry& pr);
|
||||
bool set_peer_just_seen(peerid_type peer, uint32_t ip, uint32_t port);
|
||||
bool set_peer_just_seen(peerid_type peer, const net_address& addr);
|
||||
bool set_peer_unreachable(const peerlist_entry& pr);
|
||||
bool is_ip_allowed(uint32_t ip);
|
||||
void trim_white_peerlist();
|
||||
void trim_gray_peerlist();
|
||||
bool remove_peers_by_ip_from_all(const uint32_t ip);
|
||||
|
||||
|
||||
private:
|
||||
|
|
@ -110,17 +108,6 @@ namespace nodetool
|
|||
>
|
||||
> peers_indexed;
|
||||
|
||||
typedef boost::multi_index_container<
|
||||
peerlist_entry,
|
||||
boost::multi_index::indexed_by<
|
||||
// access by peerlist_entry::id<
|
||||
boost::multi_index::ordered_unique<boost::multi_index::tag<by_id>, boost::multi_index::member<peerlist_entry,uint64_t,&peerlist_entry::id> >,
|
||||
// access by peerlist_entry::net_adress
|
||||
boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,net_address,&peerlist_entry::adr> >,
|
||||
// sort by peerlist_entry::last_seen<
|
||||
boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,time_t,&peerlist_entry::last_seen> >
|
||||
>
|
||||
> peers_indexed_old;
|
||||
public:
|
||||
|
||||
template <class Archive, class t_version_type>
|
||||
|
|
@ -134,9 +121,7 @@ namespace nodetool
|
|||
ar & m_peers_gray;
|
||||
}
|
||||
|
||||
private:
|
||||
bool peers_indexed_from_old(const peers_indexed_old& pio, peers_indexed& pi);
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
epee::critical_section m_peerlist_lock;
|
||||
std::string m_config_folder;
|
||||
|
|
@ -188,21 +173,6 @@ namespace nodetool
|
|||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
bool peerlist_manager::peers_indexed_from_old(const peers_indexed_old& pio, peers_indexed& pi)
|
||||
{
|
||||
for(auto x: pio)
|
||||
{
|
||||
auto by_addr_it = pi.get<by_addr>().find(x.adr);
|
||||
if(by_addr_it == pi.get<by_addr>().end())
|
||||
{
|
||||
pi.insert(x);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
inline void peerlist_manager::trim_white_peerlist()
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_peerlist_lock);
|
||||
|
|
@ -393,6 +363,33 @@ namespace nodetool
|
|||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
bool peerlist_manager::remove_peers_by_ip_from_all(const uint32_t ip)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_peerlist_lock);
|
||||
|
||||
for (auto it = m_peers_white.begin(); it != m_peers_white.end();)
|
||||
{
|
||||
if (it->adr.ip == ip)
|
||||
it = m_peers_white.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
for (auto it = m_peers_gray.begin(); it != m_peers_gray.end();)
|
||||
{
|
||||
if (it->adr.ip == ip)
|
||||
it = m_peers_gray.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
return true;
|
||||
CATCH_ENTRY_L0("peerlist_manager::remove_peers_by_ip_from_all()", false);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
BOOST_CLASS_VERSION(nodetool::peerlist_manager, CURRENT_PEERLIST_STORAGE_ARCHIVE_VER)
|
||||
|
|
|
|||
|
|
@ -228,6 +228,7 @@ simple_wallet::simple_wallet()
|
|||
|
||||
m_cmd_binder.set_handler("sign_transfer", boost::bind(&simple_wallet::sign_transfer, this, _1), "sign_transfer <unsgined_tx_file> <signed_tx_file> - sign unsigned tx from a watch-only wallet");
|
||||
m_cmd_binder.set_handler("submit_transfer", boost::bind(&simple_wallet::submit_transfer, this, _1), "submit_transfer <signed_tx_file> - broadcast signed tx");
|
||||
m_cmd_binder.set_handler("export_history", boost::bind(&simple_wallet::submit_transfer, this, _1), "Export transaction history in CSV file");
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
simple_wallet::~simple_wallet()
|
||||
|
|
@ -798,12 +799,7 @@ bool simple_wallet::list_recent_transfers(const std::vector<std::string>& args)
|
|||
std::string wti_to_text_line(const tools::wallet_public::wallet_transfer_info& wti)
|
||||
{
|
||||
stringstream ss;
|
||||
ss << (wti.is_income ? "[INC]" : "[OUT]") << "\t"
|
||||
<< epee::misc_utils::get_time_str(wti.timestamp) << "\t"
|
||||
<< print_money(wti.amount) << "\t"
|
||||
<< print_money(wti.fee) << "\t"
|
||||
<< wti.remote_addresses << "\t"
|
||||
<< wti.comment << "\t";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -811,58 +807,37 @@ bool simple_wallet::export_recent_transfers(const std::vector<std::string>& args
|
|||
{
|
||||
bool export_to_json = true;
|
||||
bool ignore_pos = false;
|
||||
if (args.size())
|
||||
{
|
||||
if (args[0] == "json")
|
||||
export_to_json = true;
|
||||
else if (args[0] == "txt")
|
||||
export_to_json = false;
|
||||
}
|
||||
if (args.size() > 1)
|
||||
{
|
||||
if (args[1] == "ignore-pos")
|
||||
ignore_pos = true;
|
||||
}
|
||||
|
||||
std::vector<tools::wallet_public::wallet_transfer_info> unconfirmed;
|
||||
std::vector<tools::wallet_public::wallet_transfer_info> recent;
|
||||
uint64_t total = 0;
|
||||
uint64_t last_index = 0;
|
||||
m_wallet->get_recent_transfers_history(recent, 0, 0, total, last_index, false);
|
||||
m_wallet->get_unconfirmed_transfers(unconfirmed, false);
|
||||
//workaround for missed fee
|
||||
stringstream ss;
|
||||
LOG_PRINT_GREEN("Generating text....", LOG_LEVEL_0);
|
||||
ss << "Unconfirmed transfers: " << ENDL;
|
||||
for (auto & wti : unconfirmed)
|
||||
std::string format = "csv";
|
||||
if (args.size() > 0)
|
||||
{
|
||||
if(ignore_pos && wti.is_mining)
|
||||
continue;
|
||||
if (!wti.fee)
|
||||
wti.fee = currency::get_tx_fee(wti.tx);
|
||||
if(export_to_json)
|
||||
ss << epee::serialization::store_t_to_json(wti) << ENDL;
|
||||
if (args[0] == "json" || args[0] == "csv" || args[0] == "text")
|
||||
{
|
||||
format = args[0];
|
||||
}
|
||||
else
|
||||
ss << wti_to_text_line(wti) << ENDL;
|
||||
|
||||
{
|
||||
fail_msg_writer() << "Unknown format: \"" << args[0] << "\", only \"csv\"(default), \"json\" and \"text\" supported";
|
||||
}
|
||||
}
|
||||
ss << "Recent transfers: " << ENDL;
|
||||
for (auto & wti : recent)
|
||||
|
||||
try {
|
||||
boost::filesystem::ofstream fstream;
|
||||
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(log_space::log_singletone::get_default_log_folder() + "/wallet_recent_transfers.txt", std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
|
||||
m_wallet->export_transaction_history(fstream, format, !ignore_pos);
|
||||
fstream.close();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (ignore_pos && wti.is_mining)
|
||||
continue;
|
||||
if (!wti.fee)
|
||||
wti.fee = currency::get_tx_fee(wti.tx);
|
||||
|
||||
if (export_to_json)
|
||||
ss << epee::serialization::store_t_to_json(wti) << ENDL;
|
||||
else
|
||||
ss << wti_to_text_line(wti) << ENDL;
|
||||
success_msg_writer() << "Failed";
|
||||
return false;
|
||||
}
|
||||
LOG_PRINT_GREEN("Storing text to wallet_recent_transfers.txt....", LOG_LEVEL_0);
|
||||
file_io_utils::save_string_to_file(log_space::log_singletone::get_default_log_folder() + "/wallet_recent_transfers.txt", ss.str());
|
||||
LOG_PRINT_GREEN("Done", LOG_LEVEL_0);
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
#define BUILD_COMMIT_ID "@VERSION@"
|
||||
|
||||
#define PROJECT_MAJOR_VERSION "1"
|
||||
#define PROJECT_MINOR_VERSION "3"
|
||||
#define PROJECT_REVISION "2"
|
||||
#define PROJECT_MINOR_VERSION "4"
|
||||
#define PROJECT_REVISION "0"
|
||||
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
|
||||
|
||||
#define PROJECT_VERSION_BUILD_NO 135
|
||||
#define PROJECT_VERSION_BUILD_NO 138
|
||||
#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 "]"
|
||||
|
|
|
|||
|
|
@ -201,7 +201,8 @@ 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 (!(ptr->gwm.init_command_line(3, args) && ptr->gwm.init(nullptr)))
|
||||
std::string command_line_fail_details;
|
||||
if (!(ptr->gwm.init_command_line(3, args, command_line_fail_details) && ptr->gwm.init(nullptr)))
|
||||
{
|
||||
LOG_ERROR("Failed to init wallets_manager");
|
||||
return GENERAL_INTERNAL_ERRROR_INIT;
|
||||
|
|
|
|||
|
|
@ -284,6 +284,20 @@ public:
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct export_wallet_info
|
||||
{
|
||||
uint64_t wallet_id;
|
||||
bool include_pos_transactions;
|
||||
std::string path;
|
||||
std::string format;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallet_id)
|
||||
KV_SERIALIZE(include_pos_transactions)
|
||||
KV_SERIALIZE(path)
|
||||
KV_SERIALIZE(format)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response_mining_estimate
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3254,6 +3254,87 @@ void wallet2::get_recent_transfers_history(std::vector<wallet_public::wallet_tra
|
|||
|
||||
total = m_transfer_history.size();
|
||||
|
||||
}
|
||||
|
||||
void wallet2::wti_to_csv_entry(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index) {
|
||||
ss << index << ",";
|
||||
ss << epee::misc_utils::get_time_str_v2(wti.timestamp) << ",";
|
||||
ss << print_money(wti.amount) << ",";
|
||||
ss << "\"" << wti.comment << "\",";
|
||||
ss << "[";
|
||||
std::copy(wti.remote_addresses.begin(), wti.remote_addresses.end(), std::ostream_iterator<std::string>(ss, " "));
|
||||
ss << "]" << ",";
|
||||
ss << wti.tx_hash << ",";
|
||||
ss << wti.height << ",";
|
||||
ss << wti.unlock_time << ",";
|
||||
ss << wti.tx_blob_size << ",";
|
||||
ss << epee::string_tools::buff_to_hex_nodelimer(wti.payment_id) << ",";
|
||||
ss << "[";
|
||||
std::copy(wti.recipients_aliases.begin(), wti.recipients_aliases.end(), std::ostream_iterator<std::string>(ss, " "));
|
||||
ss << "]" << ",";
|
||||
ss << (wti.is_income ? "in" : "out") << ",";
|
||||
ss << (wti.is_service ? "[SERVICE]" : "") << (wti.is_mixing ? "[MIXINS]" : "") << (wti.is_mining ? "[MINING]" : "") << ",";
|
||||
ss << wti.tx_type << ",";
|
||||
ss << wti.fee << ENDL;
|
||||
};
|
||||
|
||||
void wallet2::wti_to_txt_line(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index)
|
||||
{
|
||||
ss << (wti.is_income ? "[INC]" : "[OUT]") << "\t"
|
||||
<< epee::misc_utils::get_time_str(wti.timestamp) << "\t"
|
||||
<< print_money(wti.amount) << "\t"
|
||||
<< print_money(wti.fee) << "\t"
|
||||
<< wti.remote_addresses << "\t"
|
||||
<< wti.comment << ENDL;
|
||||
};
|
||||
|
||||
void wallet2::wti_to_json_line(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index)
|
||||
{
|
||||
ss << epee::serialization::store_t_to_json(wti, 4) << ",";
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions)
|
||||
{
|
||||
//typedef int(*t_somefunc)(int, int);
|
||||
typedef void(*playout_cb_type)(std::ostream&, const wallet_public::wallet_transfer_info&, size_t);
|
||||
playout_cb_type cb_csv = &wallet2::wti_to_csv_entry;
|
||||
playout_cb_type cb_json = &wallet2::wti_to_json_line;
|
||||
playout_cb_type cb_plain_text = &wallet2::wti_to_txt_line;
|
||||
|
||||
playout_cb_type cb = cb_csv;
|
||||
if (format == "json")
|
||||
{
|
||||
ss << "{ \"history\": [";
|
||||
cb = cb_json;
|
||||
}
|
||||
else if (format == "text")
|
||||
{
|
||||
cb = cb_plain_text;
|
||||
}
|
||||
else
|
||||
{
|
||||
//csv by default
|
||||
ss << "N, Date, Amount, Comment, Address, ID, Height, Unlock timestamp, Tx size, Alias, In/Out, Flags, Type, Fee" << ENDL;
|
||||
}
|
||||
|
||||
|
||||
enum_container(m_transfer_history.begin(), m_transfer_history.end(), [&](wallet_public::wallet_transfer_info& wti, size_t index) {
|
||||
if (!include_pos_transactions)
|
||||
{
|
||||
if (currency::is_coinbase(wti.tx))
|
||||
return true;
|
||||
}
|
||||
cb(ss, wti, index);
|
||||
return true;
|
||||
});
|
||||
|
||||
if (format == "json")
|
||||
{
|
||||
ss << "{}]}";
|
||||
}
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id)
|
||||
|
|
|
|||
|
|
@ -861,6 +861,8 @@ namespace tools
|
|||
uint64_t get_wallet_file_size()const;
|
||||
void set_use_deffered_global_outputs(bool use);
|
||||
construct_tx_param get_default_construct_tx_param_inital();
|
||||
|
||||
void export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions = true);
|
||||
|
||||
/*
|
||||
create_htlc_proposal: if htlc_hash == null_hash, then this wallet is originator of the atomic process, and
|
||||
|
|
@ -872,7 +874,6 @@ namespace tools
|
|||
void redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin, currency::transaction& result_tx);
|
||||
void redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin);
|
||||
bool check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& origin, crypto::hash& redeem_tx_id);
|
||||
|
||||
private:
|
||||
|
||||
void add_transfers_to_expiration_list(const std::vector<uint64_t>& selected_transfers, uint64_t expiration, uint64_t change_amount, const crypto::hash& related_tx_id);
|
||||
|
|
@ -1006,6 +1007,10 @@ private:
|
|||
void push_alias_info_to_extra_according_to_hf_status(const currency::extra_alias_entry& ai, std::vector<currency::extra_v>& extra);
|
||||
void remove_transfer_from_amount_gindex_map(uint64_t tid);
|
||||
|
||||
static void wti_to_csv_entry(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index);
|
||||
static void wti_to_txt_line(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index);
|
||||
static void wti_to_json_line(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index);
|
||||
|
||||
currency::account_base m_account;
|
||||
bool m_watch_only;
|
||||
std::string m_log_prefix; // part of pub address, prefix for logging functions
|
||||
|
|
|
|||
|
|
@ -56,7 +56,11 @@ namespace tools
|
|||
command_line::add_arg(desc, arg_deaf_mode);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
wallet_rpc_server::wallet_rpc_server(wallet2& w):m_wallet(w), m_do_mint(false), m_deaf(false)
|
||||
wallet_rpc_server::wallet_rpc_server(wallet2& w)
|
||||
: m_wallet(w)
|
||||
, m_do_mint(false)
|
||||
, m_deaf(false)
|
||||
, m_last_wallet_store_height(0)
|
||||
{}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::run(bool do_mint, bool offline_mode, const currency::account_public_address& miner_address)
|
||||
|
|
@ -309,7 +313,7 @@ namespace tools
|
|||
else
|
||||
{
|
||||
//put it to attachments
|
||||
ctp.attachments.insert(ctp.extra.end(), req.service_entries.begin(), req.service_entries.end());
|
||||
ctp.attachments.insert(ctp.attachments.end(), req.service_entries.begin(), req.service_entries.end());
|
||||
}
|
||||
bool wrap = false;
|
||||
std::vector<currency::tx_destination_entry>& dsts = ctp.dsts;
|
||||
|
|
@ -397,7 +401,7 @@ namespace tools
|
|||
currency::finalized_tx result = AUTO_VAL_INIT(result);
|
||||
std::string unsigned_tx_blob_str;
|
||||
ctp.fee = req.fee;
|
||||
ctp.fake_outputs_count = 0;
|
||||
ctp.fake_outputs_count = req.mixin;
|
||||
m_wallet.transfer(ctp, result, true, &unsigned_tx_blob_str);
|
||||
if (m_wallet.is_watch_only())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ bool wallets_manager::do_exception_safe_call(guarded_code_t guarded_code, error_
|
|||
}
|
||||
|
||||
|
||||
bool wallets_manager::init_command_line(int argc, char* argv[])
|
||||
bool wallets_manager::init_command_line(int argc, char* argv[], std::string& fail_message)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
po::options_description desc_cmd_only("Command line options");
|
||||
|
|
@ -197,9 +197,8 @@ bool wallets_manager::init_command_line(int argc, char* argv[])
|
|||
po::options_description desc_options("Allowed options");
|
||||
desc_options.add(desc_cmd_only).add(desc_cmd_sett);
|
||||
|
||||
|
||||
|
||||
bool coomand_line_parsed = command_line::handle_error_helper(desc_options, [&]()
|
||||
std::string err_str;
|
||||
bool command_line_parsed = command_line::handle_error_helper(desc_options, err_str, [&]()
|
||||
{
|
||||
po::store(po::parse_command_line(argc, argv, desc_options), m_vm);
|
||||
|
||||
|
|
@ -230,23 +229,29 @@ bool wallets_manager::init_command_line(int argc, char* argv[])
|
|||
return true;
|
||||
});
|
||||
|
||||
if (!coomand_line_parsed)
|
||||
if (!command_line_parsed)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Command line has wrong arguments: " << std::endl;
|
||||
for (int i = 0; i != argc; i++)
|
||||
ss << "[" << i << "] " << argv[i] << std::endl;
|
||||
std::cerr << ss.str() << std::endl << std::flush;
|
||||
|
||||
fail_message = "Error parsing arguments.\n";
|
||||
fail_message += err_str + "\n";
|
||||
std::stringstream s;
|
||||
desc_options.print(s);
|
||||
fail_message += s.str();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_qt_logs_enbaled = command_line::get_arg(m_vm, arg_enable_qt_logs);
|
||||
m_qt_dev_tools = command_line::get_arg(m_vm, arg_qt_dev_tools);
|
||||
|
||||
return true;
|
||||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
||||
|
||||
void terminate_handler_func()
|
||||
{
|
||||
LOG_ERROR("\n\nTERMINATE HANDLER\n"); // should print callstack
|
||||
|
|
@ -798,6 +803,24 @@ std::string wallets_manager::get_tx_pool_info(currency::COMMAND_RPC_GET_POOL_INF
|
|||
}
|
||||
|
||||
|
||||
std::string wallets_manager::export_wallet_history(const view::export_wallet_info& ewi)
|
||||
{
|
||||
GET_WALLET_OPT_BY_ID(ewi.wallet_id, wo);
|
||||
try {
|
||||
|
||||
boost::filesystem::ofstream fstream;
|
||||
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(ewi.path, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
|
||||
wo.w->get()->export_transaction_history(fstream, ewi.format, ewi.include_pos_transactions);
|
||||
fstream.close();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return API_RETURN_CODE_FAIL;
|
||||
}
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
|
||||
uint64_t wallets_manager::get_default_fee()
|
||||
{
|
||||
return TX_DEFAULT_FEE;
|
||||
|
|
@ -1802,7 +1825,10 @@ void wallets_manager::on_transfer2(size_t wallet_id, const tools::wallet_public:
|
|||
|
||||
GET_WALLET_OPTIONS_BY_ID_VOID_RET(wallet_id, w);
|
||||
tei.is_wallet_in_sync_process = w.long_refresh_in_progress;
|
||||
m_pview->money_transfer(tei);
|
||||
if (!(w.w->get()->is_watch_only()))
|
||||
{
|
||||
m_pview->money_transfer(tei);
|
||||
}
|
||||
}
|
||||
void wallets_manager::on_pos_block_found(size_t wallet_id, const currency::block& b)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ public:
|
|||
|
||||
wallets_manager();
|
||||
~wallets_manager();
|
||||
bool init_command_line(int argc, char* argv[]);
|
||||
bool init_command_line(int argc, char* argv[], std::string& fail_message);
|
||||
bool init(view::i_view* pview_handler);
|
||||
bool start();
|
||||
bool stop();
|
||||
|
|
@ -139,6 +139,7 @@ public:
|
|||
std::string get_my_offers(const bc_services::core_offers_filter& filter, std::list<bc_services::offer_details_ex>& offers);
|
||||
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);
|
||||
uint64_t get_default_fee();
|
||||
std::string get_mining_estimate(uint64_t amuont_coins,
|
||||
uint64_t time,
|
||||
|
|
|
|||
|
|
@ -2053,6 +2053,25 @@ bool check_ring_signature_at_gen_time(const std::vector<test_event_entry>& event
|
|||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for (size_t i = 0; i < ptce->tx.vin.size(); ++i)
|
||||
{
|
||||
auto& input = ptce->tx.vin[i];
|
||||
if (input.type() == typeid(txin_to_key))
|
||||
{
|
||||
auto& intk = boost::get<txin_to_key>(input);
|
||||
CHECK_AND_ASSERT_MES(intk.key_offsets.size() == mixin + 1, false, "for input #" << i << " mixin count is " << intk.key_offsets.size() - 1 << ", expected is " << mixin);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void test_chain_unit_base::register_callback(const std::string& cb_name, verify_callback cb)
|
||||
|
|
|
|||
|
|
@ -679,6 +679,7 @@ bool generate_pos_block_with_given_coinstake(test_generator& generator, const st
|
|||
bool check_ring_signature_at_gen_time(const std::vector<test_event_entry>& events, const crypto::hash& last_block_id, const currency::txin_to_key& in_t_k,
|
||||
const crypto::hash& hash_for_sig, const std::vector<crypto::signature> &sig);
|
||||
|
||||
bool check_mixin_value_for_each_input(size_t mixin, const crypto::hash& tx_id, currency::core& c);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
template<class t_test_class>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ bool clean_data_directory()
|
|||
{
|
||||
std::string config_folder = command_line::get_arg(g_vm, command_line::arg_data_dir);
|
||||
|
||||
static const std::set<std::string> files = { CURRENCY_POOLDATA_FOLDERNAME_OLD, CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD, P2P_NET_DATA_FILENAME, MINER_CONFIG_FILENAME, GUI_SECURE_CONFIG_FILENAME, GUI_CONFIG_FILENAME, GUI_INTERNAL_CONFIG };
|
||||
static const std::set<std::string> files = { CURRENCY_POOLDATA_FOLDERNAME_OLD, CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD, P2P_NET_DATA_FILENAME, MINER_CONFIG_FILENAME, GUI_SECURE_CONFIG_FILENAME, GUI_CONFIG_FILENAME, GUI_INTERNAL_CONFIG2 };
|
||||
static const std::set<std::string> prefixes = { CURRENCY_POOLDATA_FOLDERNAME_PREFIX, CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX };
|
||||
|
||||
std::vector<boost::filesystem::path> entries_to_remove;
|
||||
|
|
@ -743,6 +743,9 @@ int main(int argc, char* argv[])
|
|||
|
||||
#undef MARK_TEST_AS_POSTPONED
|
||||
|
||||
|
||||
// TODO // GENERATE_AND_PLAY(wallet_spend_form_auditable_and_track);
|
||||
|
||||
GENERATE_AND_PLAY(pos_minting_tx_packing);
|
||||
|
||||
GENERATE_AND_PLAY(multisig_wallet_test);
|
||||
|
|
@ -814,6 +817,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(gen_checkpoints_reorganize);
|
||||
GENERATE_AND_PLAY(gen_checkpoints_pos_validation_on_altchain);
|
||||
GENERATE_AND_PLAY(gen_checkpoints_and_invalid_tx_to_pool);
|
||||
GENERATE_AND_PLAY(gen_checkpoints_set_after_switching_to_altchain);
|
||||
GENERATE_AND_PLAY(gen_no_attchments_in_coinbase);
|
||||
GENERATE_AND_PLAY(gen_no_attchments_in_coinbase_gentime);
|
||||
|
||||
|
|
@ -867,6 +871,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
GENERATE_AND_PLAY(wallet_rpc_integrated_address);
|
||||
GENERATE_AND_PLAY(wallet_rpc_integrated_address_transfer);
|
||||
GENERATE_AND_PLAY(wallet_rpc_transfer);
|
||||
GENERATE_AND_PLAY(wallet_chain_switch_with_spending_the_same_ki);
|
||||
GENERATE_AND_PLAY(wallet_sending_to_integrated_address);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,13 +36,18 @@ bool checkpoints_test::set_checkpoint(currency::core& c, size_t ev_index, const
|
|||
{
|
||||
if (pcp.hash != null_hash && pcp.hash != get_block_hash(b))
|
||||
continue;
|
||||
currency::checkpoints cp;
|
||||
cp.add_checkpoint(currency::get_block_height(b), epee::string_tools::pod_to_hex(currency::get_block_hash(b)));
|
||||
c.set_checkpoints(std::move(cp));
|
||||
m_local_checkpoints.add_checkpoint(pcp.height, epee::string_tools::pod_to_hex(currency::get_block_hash(b)));
|
||||
c.set_checkpoints(currency::checkpoints(m_local_checkpoints));
|
||||
LOG_PRINT_YELLOW("CHECKPOINT set at height " << pcp.height, LOG_LEVEL_0);
|
||||
|
||||
//for(uint64_t h = 0; h <= pcp.height + 1; ++h)
|
||||
// LOG_PRINT_MAGENTA("%% " << h << " : " << m_local_checkpoints.get_checkpoint_before_height(h), LOG_LEVEL_0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR("set_checkpoint failed trying to set checkpoint at height " << pcp.height);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -395,8 +400,13 @@ bool gen_checkpoints_prun_txs_after_blockchain_load::generate(std::vector<test_e
|
|||
DO_CALLBACK(events, "check_not_being_in_cp_zone");
|
||||
DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2));
|
||||
|
||||
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, true)); // tx_0 goes with blk_1_bad
|
||||
MAKE_TX(events, tx_0, miner_acc, alice, MK_TEST_COINS(1), blk_0r);
|
||||
std::vector<attachment_v> attach;
|
||||
attach.push_back(tx_comment{"jokes are funny"});
|
||||
|
||||
// tx pool won't accept the tx, because it cannot be verified in CP zone
|
||||
// set kept_by_block flag, so tx_0 be accepted
|
||||
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, true));
|
||||
MAKE_TX_ATTACH(events, tx_0, miner_acc, alice, MK_TEST_COINS(1), blk_0r, attach);
|
||||
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, false));
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0);
|
||||
|
||||
|
|
@ -407,11 +417,12 @@ bool gen_checkpoints_prun_txs_after_blockchain_load::generate(std::vector<test_e
|
|||
|
||||
DO_CALLBACK(events, "check_not_being_in_cp_zone");
|
||||
|
||||
MAKE_TX(events, tx_1, miner_acc, alice, MK_TEST_COINS(1), blk_3);
|
||||
MAKE_TX_ATTACH(events, tx_1, miner_acc, alice, MK_TEST_COINS(1), blk_3, attach);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_4, blk_3, miner_acc, tx_1);
|
||||
|
||||
DO_CALLBACK(events, "check_not_being_in_cp_zone");
|
||||
|
||||
// BCS tx pruning (on interval 0 - CP1) should be triggered once the following checkpoint is set
|
||||
DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 6));
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_5, blk_4, miner_acc);
|
||||
|
|
@ -437,8 +448,8 @@ bool gen_checkpoints_prun_txs_after_blockchain_load::check_txs(currency::core& c
|
|||
|
||||
r = c.get_transaction(m_tx1_id, tx_1);
|
||||
CHECK_AND_ASSERT_MES(r, false, "can't get transaction tx_1");
|
||||
CHECK_AND_ASSERT_MES(tx_1.signatures.empty(), false, "tx_1 has non-empty sig");
|
||||
CHECK_AND_ASSERT_MES(tx_1.attachment.empty(), false, "tx_1 has non-empty attachments");
|
||||
CHECK_AND_ASSERT_MES(!tx_1.signatures.empty(), false, "tx_1 has empty sig");
|
||||
CHECK_AND_ASSERT_MES(!tx_1.attachment.empty(), false, "tx_1 has empty attachments");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -895,3 +906,64 @@ bool gen_checkpoints_and_invalid_tx_to_pool::c1(currency::core& c, size_t ev_ind
|
|||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
gen_checkpoints_set_after_switching_to_altchain::gen_checkpoints_set_after_switching_to_altchain()
|
||||
{
|
||||
}
|
||||
|
||||
bool gen_checkpoints_set_after_switching_to_altchain::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
// Test outline:
|
||||
// 0) no checkpoints are set;
|
||||
// 1) core is in a subchain, that will become alternative;
|
||||
// 2) checkpoint is set (in the furute), transaction pruning is executed;
|
||||
// 3) core continues to sync, chain switching occurs
|
||||
// Make sure that chain switching is still possible after pruning.
|
||||
|
||||
// 0 ... N N+1 N+2 N+3 N+4 N+5 N+6 <- height (N = CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
|
||||
// tx1
|
||||
// (0 )- (0r)- (1 )- (2a)- (3a)- <- alt chain
|
||||
// \
|
||||
// \- (2 )- <- main chain
|
||||
|
||||
bool r = false;
|
||||
GENERATE_ACCOUNT(miner_acc);
|
||||
GENERATE_ACCOUNT(alice_acc);
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
|
||||
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
DO_CALLBACK(events, "check_not_being_in_cp_zone");
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_1, blk_0r, miner_acc);
|
||||
MAKE_TX(events, tx1, miner_acc, alice_acc, MK_TEST_COINS(1), blk_1);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_2a, blk_1, miner_acc, tx1);
|
||||
MAKE_NEXT_BLOCK(events, blk_3a, blk_2a, miner_acc);
|
||||
|
||||
DO_CALLBACK(events, "check_not_being_in_cp_zone");
|
||||
|
||||
// 0 ... N N+1 N+2 N+3 N+4 N+5 N+6 <- height (N = CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
|
||||
// +-----------> CP <- checkpoint
|
||||
// tx1 |
|
||||
// (0 )- (0r)- (1 )- (2a)- (3a)- <- alt chain
|
||||
// \ | <- when CP set up
|
||||
// \- (2 )- (3 )- (4 )- (5 )- (6 )- <- main chain
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5));
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner_acc);
|
||||
MAKE_NEXT_BLOCK(events, blk_3, blk_2, miner_acc);
|
||||
MAKE_NEXT_BLOCK(events, blk_4, blk_3, miner_acc); // <-- this should trigger the switching
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_4), get_block_hash(blk_4)));
|
||||
DO_CALLBACK(events, "check_being_in_cp_zone");
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_5, blk_4, miner_acc); // <-- CHECKPOINT
|
||||
MAKE_NEXT_BLOCK(events, blk_6, blk_5, miner_acc);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_6), get_block_hash(blk_6)));
|
||||
DO_CALLBACK(events, "check_not_being_in_cp_zone");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ protected:
|
|||
uint64_t height;
|
||||
crypto::hash hash;
|
||||
};
|
||||
|
||||
private:
|
||||
currency::checkpoints m_local_checkpoints;
|
||||
};
|
||||
|
||||
struct gen_checkpoints_attachments_basic : public checkpoints_test
|
||||
|
|
@ -109,3 +112,9 @@ struct gen_checkpoints_and_invalid_tx_to_pool : public checkpoints_test
|
|||
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 gen_checkpoints_set_after_switching_to_altchain : public checkpoints_test
|
||||
{
|
||||
gen_checkpoints_set_after_switching_to_altchain();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ bool wallet_rpc_integrated_address_transfer::c1(currency::core& c, size_t ev_ind
|
|||
alice_wlt->get_payments(payment_id, payments);
|
||||
CHECK_AND_ASSERT_MES(payments.size() == 1, false, "Invalid payments count: " << payments.size());
|
||||
CHECK_AND_ASSERT_MES(payments.front().m_amount == MK_TEST_COINS(3), false, "Invalid payment");
|
||||
CHECK_AND_ASSERT_MES(check_mixin_value_for_each_input(0, payments.front().m_tx_hash, c), false, ""); // make sure number of decoys is correct
|
||||
|
||||
|
||||
// 3. standard address + invalid external payment id => fail
|
||||
|
|
@ -181,9 +182,127 @@ bool wallet_rpc_integrated_address_transfer::c1(currency::core& c, size_t ev_ind
|
|||
alice_wlt->get_payments(payment_id, payments);
|
||||
CHECK_AND_ASSERT_MES(payments.size() == 1, false, "Invalid payments count: " << payments.size());
|
||||
CHECK_AND_ASSERT_MES(payments.front().m_amount == MK_TEST_COINS(7), false, "Invalid payment");
|
||||
CHECK_AND_ASSERT_MES(check_mixin_value_for_each_input(0, payments.front().m_tx_hash, c), false, ""); // make sure number of decoys is correct
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
wallet_rpc_transfer::wallet_rpc_transfer()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(wallet_rpc_transfer, configure_core);
|
||||
REGISTER_CALLBACK_METHOD(wallet_rpc_transfer, c1);
|
||||
}
|
||||
|
||||
bool wallet_rpc_transfer::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate();
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate();
|
||||
account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate();
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
set_hard_fork_heights_to_generator(generator);
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 6);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet_rpc_transfer::configure_core(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
currency::core_runtime_config pc = c.get_blockchain_storage().get_core_runtime_config();
|
||||
pc.hard_fork_01_starts_after_height = 1;
|
||||
pc.hard_fork_02_starts_after_height = 1;
|
||||
pc.hard_fork_03_starts_after_height = 1;
|
||||
c.get_blockchain_storage().set_core_runtime_config(pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet_rpc_transfer::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);
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
|
||||
|
||||
miner_wlt->refresh();
|
||||
|
||||
// wallet RPC server
|
||||
tools::wallet_rpc_server miner_wlt_rpc(*miner_wlt);
|
||||
epee::json_rpc::error je;
|
||||
tools::wallet_rpc_server::connection_context ctx;
|
||||
|
||||
// 1. Check non-zero mixin and default settings
|
||||
tools::wallet_public::COMMAND_RPC_TRANSFER::request req = AUTO_VAL_INIT(req);
|
||||
req.fee = TESTS_DEFAULT_FEE;
|
||||
req.mixin = 2;
|
||||
tools::wallet_public::transfer_destination tds = AUTO_VAL_INIT(tds);
|
||||
tds.address = m_accounts[ALICE_ACC_IDX].get_public_address_str();
|
||||
tds.amount = MK_TEST_COINS(3);
|
||||
req.destinations.push_back(tds);
|
||||
|
||||
tools::wallet_public::COMMAND_RPC_TRANSFER::response res = AUTO_VAL_INIT(res);
|
||||
|
||||
r = miner_wlt_rpc.on_transfer(req, res, je, ctx);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC call failed, code: " << je.code << ", msg: " << je.message);
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "enexpected pool txs count: " << c.get_pool_transactions_count());
|
||||
|
||||
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");
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Tx pool is not empty: " << c.get_pool_transactions_count());
|
||||
|
||||
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt, tds.amount), false, "");
|
||||
|
||||
// check the transfer has been received
|
||||
tools::wallet2::transfer_details td = AUTO_VAL_INIT(td);
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->get_transfer_info_by_index(0, td), false, "");
|
||||
CHECK_AND_ASSERT_MES(td.amount() == MK_TEST_COINS(3), false, "Invalid payment");
|
||||
CHECK_AND_ASSERT_MES(check_mixin_value_for_each_input(2, td.tx_hash(), c), false, "");
|
||||
|
||||
// make sure tx_received is set by default, but tx_payer is not
|
||||
std::shared_ptr<const transaction_chain_entry> pche = c.get_blockchain_storage().get_tx_chain_entry(td.tx_hash());
|
||||
CHECK_AND_ASSERT_MES(currency::count_type_in_variant_container<tx_receiver>(pche->tx.extra) == 1, false, "tx_receiver: incorrect count of items");
|
||||
CHECK_AND_ASSERT_MES(currency::count_type_in_variant_container<tx_payer>(pche->tx.extra) == 0, false, "tx_payer: incorrect count of items");
|
||||
|
||||
|
||||
// 2. check tx_receiver and tx_payer non-default
|
||||
req.mixin = 1;
|
||||
req.hide_receiver = true;
|
||||
req.push_payer = true;
|
||||
tds.amount = MK_TEST_COINS(5);
|
||||
req.destinations.clear();
|
||||
req.destinations.push_back(tds);
|
||||
|
||||
res = AUTO_VAL_INIT(res);
|
||||
|
||||
r = miner_wlt_rpc.on_transfer(req, res, je, ctx);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC call failed, code: " << je.code << ", msg: " << je.message);
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "enexpected pool txs count: " << c.get_pool_transactions_count());
|
||||
|
||||
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");
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Tx pool is not empty: " << c.get_pool_transactions_count());
|
||||
|
||||
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt, MK_TEST_COINS(3 + 5)), false, "");
|
||||
|
||||
td = AUTO_VAL_INIT(td);
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->get_transfer_info_by_index(1, td), false, "");
|
||||
CHECK_AND_ASSERT_MES(td.amount() == MK_TEST_COINS(5), false, "Invalid payment");
|
||||
CHECK_AND_ASSERT_MES(check_mixin_value_for_each_input(1, td.tx_hash(), c), false, "");
|
||||
|
||||
// make sure tx_received is set by default, but tx_payer is not
|
||||
pche = c.get_blockchain_storage().get_tx_chain_entry(td.tx_hash());
|
||||
CHECK_AND_ASSERT_MES(currency::count_type_in_variant_container<tx_receiver>(pche->tx.extra) == 0, false, "tx_receiver: incorrect count of items");
|
||||
CHECK_AND_ASSERT_MES(currency::count_type_in_variant_container<tx_payer>(pche->tx.extra) == 1, false, "tx_payer: incorrect count of items");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,3 +21,11 @@ struct wallet_rpc_integrated_address_transfer : public wallet_test
|
|||
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 wallet_rpc_transfer : public wallet_test
|
||||
{
|
||||
wallet_rpc_transfer();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool configure_core(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3553,5 +3553,87 @@ bool wallet_watch_only_and_chain_switch::c1(currency::core& c, size_t ev_index,
|
|||
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt, MK_TEST_COINS(7), false, UINT64_MAX, 0, 0, MK_TEST_COINS(7), 0), false, "");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
wallet_spend_form_auditable_and_track::wallet_spend_form_auditable_and_track()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(wallet_spend_form_auditable_and_track, c1);
|
||||
}
|
||||
|
||||
bool wallet_spend_form_auditable_and_track::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate();
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(true); // Alice has auditable wallet
|
||||
account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc = alice_acc; bob_acc.make_account_watch_only(); // Bob has Alice's tracking wallet
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
MAKE_TX(events, tx_1, miner_acc, alice_acc, MK_TEST_COINS(5), blk_0r);
|
||||
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_1);
|
||||
REWIND_BLOCKS_N(events, blk_1r, blk_1, miner_acc, WALLET_DEFAULT_TX_SPENDABLE_AGE);
|
||||
|
||||
std::vector<attachment_v> attachments;
|
||||
tx_comment comment_attachment = AUTO_VAL_INIT(comment_attachment);
|
||||
m_comment = "Jokes are funny!";
|
||||
comment_attachment.comment = m_comment;
|
||||
attachments.push_back(comment_attachment);
|
||||
MAKE_TX_ATTACH(events, tx_2, alice_acc, miner_acc, MK_TEST_COINS(1), blk_1r, attachments);
|
||||
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1r, miner_acc, tx_2);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet_spend_form_auditable_and_track::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);
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
|
||||
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX);
|
||||
|
||||
// make sure Alice's wallet is autibale and not watch-only
|
||||
CHECK_AND_ASSERT_MES(!alice_wlt->is_watch_only() && alice_wlt->is_auditable(), false, "incorrect type of Alice's wallet");
|
||||
// make sure Bob's wallet is a tracking wallet
|
||||
CHECK_AND_ASSERT_MES(bob_wlt->is_watch_only() && bob_wlt->is_auditable(), false, "incorrect type of Bob's wallet");
|
||||
|
||||
const account_public_address& bob_addr = bob_wlt->get_account().get_public_address();
|
||||
const account_public_address& alice_addr = alice_wlt->get_account().get_public_address();
|
||||
|
||||
// make sure their addresses are linked indeed
|
||||
CHECK_AND_ASSERT_MES(bob_addr.view_public_key == alice_addr.view_public_key && bob_addr.spend_public_key == alice_addr.spend_public_key, false,
|
||||
"Bob's tracking wallet address is not linked with Alice's one");
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
bob_wlt->refresh();
|
||||
|
||||
// check the balances
|
||||
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt, MK_TEST_COINS(3), false, UINT64_MAX, 0, 0, 0, 0), false, "");
|
||||
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt, MK_TEST_COINS(3), false, UINT64_MAX, 0, 0, 0, 0), false, "");
|
||||
|
||||
r = false;
|
||||
bool r_comment = false;
|
||||
bob_wlt->enumerate_transfers_history([&](const tools::wallet_public::wallet_transfer_info& wti) {
|
||||
if (wti.amount == MK_TEST_COINS(5))
|
||||
{
|
||||
r_comment = (wti.comment == m_comment);
|
||||
if (!r_comment)
|
||||
return false; // stop
|
||||
}
|
||||
return true; // continue
|
||||
}, true);
|
||||
CHECK_AND_ASSERT_MES(r, false, "cannot get comment from tx");
|
||||
CHECK_AND_ASSERT_MES(r_comment, false, "wrong comment got from tx");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,3 +276,12 @@ struct wallet_watch_only_and_chain_switch : public wallet_test
|
|||
mutable crypto::hash m_split_point_block_id;
|
||||
mutable uint64_t m_split_point_block_height;
|
||||
};
|
||||
|
||||
struct wallet_spend_form_auditable_and_track : public wallet_test
|
||||
{
|
||||
wallet_spend_form_auditable_and_track();
|
||||
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);
|
||||
|
||||
mutable std::string m_comment;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,3 +39,87 @@ TEST(checkpoints_test, test_checkpoints_for_alternative)
|
|||
r = cp.is_height_passed_zone(11, 12);
|
||||
ASSERT_FALSE(r);
|
||||
}
|
||||
|
||||
|
||||
TEST(checkpoints_test, get_checkpoint_before_height_1)
|
||||
{
|
||||
currency::checkpoints cp;
|
||||
cp.add_checkpoint(15, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
|
||||
for (uint64_t h = 0; h <= 15; ++h)
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 0);
|
||||
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(16) == 15);
|
||||
|
||||
for (uint64_t h = 17; h < 100; ++h)
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 15);
|
||||
}
|
||||
|
||||
|
||||
TEST(checkpoints_test, get_checkpoint_before_height_2)
|
||||
{
|
||||
currency::checkpoints cp;
|
||||
cp.add_checkpoint(11, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
cp.add_checkpoint(15, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
|
||||
for (uint64_t h = 0; h < 11; ++h)
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 0);
|
||||
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(11) == 0);
|
||||
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(12) == 11);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(13) == 11);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(14) == 11);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(15) == 11);
|
||||
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(16) == 15);
|
||||
|
||||
for (uint64_t h = 17; h < 100; ++h)
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 15);
|
||||
}
|
||||
|
||||
|
||||
TEST(checkpoints_test, get_checkpoint_before_height_3)
|
||||
{
|
||||
currency::checkpoints cp;
|
||||
cp.add_checkpoint(11, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
cp.add_checkpoint(15, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
cp.add_checkpoint(21, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
|
||||
for (uint64_t h = 0; h < 11; ++h)
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 0);
|
||||
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(11) == 0);
|
||||
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(12) == 11);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(13) == 11);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(14) == 11);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(15) == 11);
|
||||
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(16) == 15);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(17) == 15);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(18) == 15);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(19) == 15);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(20) == 15);
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(21) == 15);
|
||||
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(22) == 21);
|
||||
|
||||
for (uint64_t h = 22; h < 100; ++h)
|
||||
ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 21);
|
||||
}
|
||||
|
||||
|
||||
TEST(checkpoints_test, is_in_checkpoint_zone)
|
||||
{
|
||||
currency::checkpoints cp;
|
||||
cp.add_checkpoint(11, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
cp.add_checkpoint(15, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
cp.add_checkpoint(21, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
|
||||
for (uint64_t h = 0; h < 22; ++h)
|
||||
ASSERT_TRUE(cp.is_in_checkpoint_zone(h));
|
||||
|
||||
for (uint64_t h = 22; h < 100; ++h)
|
||||
ASSERT_FALSE(cp.is_in_checkpoint_zone(h));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ out_file_name=~/.local/share/applications/Zano.desktop
|
|||
call_app()
|
||||
{
|
||||
pushd $script_dir
|
||||
./Zano
|
||||
./Zano "$@"
|
||||
popd
|
||||
exit
|
||||
}
|
||||
|
|
@ -25,17 +25,20 @@ create_desktop_icon()
|
|||
rm -f $target_file_name
|
||||
echo [Desktop Entry] | tee -a $target_file_name > /dev/null
|
||||
echo Version=1.0 | tee -a $target_file_name > /dev/null
|
||||
echo Name=My Application | tee -a $target_file_name > /dev/null
|
||||
echo GenericName=My Application | tee -a $target_file_name > /dev/null
|
||||
echo Comment=Doing some funny stuff | tee -a $target_file_name > /dev/null
|
||||
echo Name=Zano | tee -a $target_file_name > /dev/null
|
||||
echo GenericName=Zano | tee -a $target_file_name > /dev/null
|
||||
echo Comment=Privacy blockchain | tee -a $target_file_name > /dev/null
|
||||
echo Icon=$script_dir/html/files/desktop_linux_icon.png | tee -a $target_file_name > /dev/null
|
||||
echo Exec=$script_dir/Zano | tee -a $target_file_name > /dev/null
|
||||
echo Exec=$script_dir/Zano.sh %u | tee -a $target_file_name > /dev/null
|
||||
echo Terminal=true | tee -a $target_file_name > /dev/null
|
||||
echo Type=Application | tee -a $target_file_name > /dev/null
|
||||
echo "Categories=Qt;Utility;" | tee -a $target_file_name > /dev/null
|
||||
echo "MimeType=x-scheme-handler/zano;" | tee -a $target_file_name > /dev/null
|
||||
}
|
||||
|
||||
|
||||
create_desktop_icon $out_file_name
|
||||
|
||||
call_app
|
||||
xdg-mime default Zano.desktop x-scheme-handler/zano
|
||||
|
||||
call_app "$@"
|
||||
|
|
@ -46,25 +46,18 @@ if [ $? -ne 0 ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
make -j1 daemon Zano;
|
||||
make -j2 daemon simplewallet connectivity_tool
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to make!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make -j1 simplewallet;
|
||||
make -j1 Zano
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to make!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make -j1 connectivity_tool;
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to make!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
|
||||
read version_str <<< $(./src/zanod --version | awk '/^Zano/ { print $2 }')
|
||||
version_str=${version_str}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ Root: HKCR; Subkey: "ZanoWalletDataKyesFile"; ValueType: string; ValueName: "";
|
|||
Root: HKCR; Subkey: "ZanoWalletDataFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\zano.exe,0"
|
||||
Root: HKCR; Subkey: "ZanoWalletDataKyesFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\zano.exe,0"
|
||||
|
||||
Root: HKCR; Subkey: "Zano"; ValueType: string; ValueName: "URL Protocol"; ValueData: ""
|
||||
Root: HKCR; Subkey: "Zano\shell\open\command"; ValueType: string; ValueName: ""; ValueData: "{app}\zano.exe %1"
|
||||
|
||||
[Files]
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ Root: HKCR; Subkey: "ZanoWalletDataKyesFile"; ValueType: string; ValueName: "";
|
|||
Root: HKCR; Subkey: "ZanoWalletDataFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Zano.exe,0"
|
||||
Root: HKCR; Subkey: "ZanoWalletDataKyesFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Zano.exe,0"
|
||||
|
||||
Root: HKCR; Subkey: "Zano"; ValueType: string; ValueName: "URL Protocol"; ValueData: ""
|
||||
Root: HKCR; Subkey: "Zano\shell\open\command"; ValueType: string; ValueName: ""; ValueData: "{app}\Zano.exe %1"
|
||||
|
||||
|
||||
[Files]
|
||||
|
||||
|
|
|
|||