1
0
Fork 0
forked from lthn/blockchain

Merge branch 'develop' into develop_mobile

This commit is contained in:
cryptozoidberg 2021-11-03 22:18:13 +01:00
commit fbc50419db
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
39 changed files with 628 additions and 253 deletions

View file

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

View file

@ -284,12 +284,19 @@ POP_GCC_WARNINGS
typedef std::map<std::wstring, std::wstring> command_line_params_w;
template<typename t_pod_data>
void apped_pod_to_strbuff(std::string& buff, const t_pod_data& pod)
void append_pod_to_strbuff(std::string& buff, const t_pod_data& pod)
{
buff.append(reinterpret_cast<const char*>(&pod), sizeof(pod));
}
template<typename pod_t>
bool get_pod_from_strbuff(const std::string& buff, pod_t& output)
{
if (buff.size() != sizeof(pod_t))
return false;
output = *reinterpret_cast<const pod_t*>(buff.data());
return true;
}
template<class t_string>
bool parse_commandline(std::map<t_string, t_string>& res, int argc, char** argv)

View file

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

View file

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

View file

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

View file

@ -0,0 +1,7 @@
// Copyright (c) 2014-2021 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#define BC_BLOCK_DATETIME_SERVICE_ID "d"
#define BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT ""

View file

@ -2114,7 +2114,7 @@ bool blockchain_storage::get_tx_rpc_details(const crypto::hash& h, tx_rpc_extend
if (tx_ptr && !timestamp)
{
timestamp = get_actual_timestamp(m_db_blocks[tx_ptr->m_keeper_block_height]->bl);
timestamp = get_block_datetime(m_db_blocks[tx_ptr->m_keeper_block_height]->bl);
}
tei.keeper_block = static_cast<int64_t>(tx_ptr->m_keeper_block_height);
fill_tx_rpc_details(tei, tx_ptr->tx, &(*tx_ptr), h, timestamp, is_short);
@ -2203,11 +2203,11 @@ bool blockchain_storage::get_main_block_rpc_details(uint64_t i, block_rpc_extend
crypto::hash coinbase_id = get_transaction_hash(core_bei_ptr->bl.miner_tx);
//load transactions details
bei.transactions_details.push_back(tx_rpc_extended_info());
get_tx_rpc_details(coinbase_id, bei.transactions_details.back(), get_actual_timestamp(core_bei_ptr->bl), true);
get_tx_rpc_details(coinbase_id, bei.transactions_details.back(), get_block_datetime(core_bei_ptr->bl), true);
for (auto& h : core_bei_ptr->bl.tx_hashes)
{
bei.transactions_details.push_back(tx_rpc_extended_info());
get_tx_rpc_details(h, bei.transactions_details.back(), get_actual_timestamp(core_bei_ptr->bl), true);
get_tx_rpc_details(h, bei.transactions_details.back(), get_block_datetime(core_bei_ptr->bl), true);
bei.total_fee += bei.transactions_details.back().fee;
bei.total_txs_size += bei.transactions_details.back().blob_size;
}
@ -2288,13 +2288,13 @@ bool blockchain_storage::get_alt_block_rpc_details(const block_extended_info& be
crypto::hash coinbase_id = get_transaction_hash(bei_core.bl.miner_tx);
//load transactions details
bei.transactions_details.push_back(tx_rpc_extended_info());
fill_tx_rpc_details(bei.transactions_details.back(), bei_core.bl.miner_tx, nullptr, coinbase_id, get_actual_timestamp(bei_core.bl));
fill_tx_rpc_details(bei.transactions_details.back(), bei_core.bl.miner_tx, nullptr, coinbase_id, get_block_datetime(bei_core.bl));
bei.total_fee = 0;
for (auto& h : bei_core.bl.tx_hashes)
{
bei.transactions_details.push_back(tx_rpc_extended_info());
if (!get_tx_rpc_details(h, bei.transactions_details.back(), get_actual_timestamp(bei_core.bl), true))
if (!get_tx_rpc_details(h, bei.transactions_details.back(), get_block_datetime(bei_core.bl), true))
{
//tx not in blockchain, supposed to be in tx pool
m_tx_pool.get_transaction_details(h, bei.transactions_details.back());
@ -2407,8 +2407,8 @@ uint64_t blockchain_storage::get_seconds_between_last_n_block(size_t n) const
if (m_db_blocks.size() <= n)
return 0;
uint64_t top_block_ts = get_actual_timestamp(m_db_blocks[m_db_blocks.size() - 1]->bl);
uint64_t n_block_ts = get_actual_timestamp(m_db_blocks[m_db_blocks.size() - 1 - n]->bl);
uint64_t top_block_ts = get_block_datetime(m_db_blocks[m_db_blocks.size() - 1]->bl);
uint64_t n_block_ts = get_block_datetime(m_db_blocks[m_db_blocks.size() - 1 - n]->bl);
return top_block_ts > n_block_ts ? top_block_ts - n_block_ts : 0;
}
@ -4905,7 +4905,7 @@ void blockchain_storage::get_pos_mining_estimate(uint64_t amount_coins,
auto bei = m_db_blocks[h];
if (!is_pos_block(bei->bl))
continue;
uint64_t ts = get_actual_timestamp(bei->bl);
uint64_t ts = get_block_datetime(bei->bl);
pos_ts_min = min(pos_ts_min, ts);
pos_ts_max = max(pos_ts_max, ts);
pos_total_minted_money += get_reward_from_miner_tx(bei->bl.miner_tx);
@ -5060,7 +5060,8 @@ bool blockchain_storage::validate_pos_block(const block& b,
}
//check actual time if it there
// the following check is de-facto not applicable since 2021-10, but left intact to avoid consensus issues
// PoS blocks don't use etc_tx_time anymore to store actual timestamp; instead, they use tx_service_attachment in mining tx extra
uint64_t actual_ts = get_actual_timestamp(b);
if ((actual_ts > b.timestamp && actual_ts - b.timestamp > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED) ||
(actual_ts < b.timestamp && b.timestamp - actual_ts > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED)
@ -5379,7 +5380,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
block_fees.reserve(bl.tx_hashes.size());
//process transactions
TIME_MEASURE_START_PD(all_txs_insert_time_5);
if (!add_transaction_from_block(bl.miner_tx, get_transaction_hash(bl.miner_tx), id, get_current_blockchain_size(), get_actual_timestamp(bl)))
if (!add_transaction_from_block(bl.miner_tx, get_transaction_hash(bl.miner_tx), id, get_current_blockchain_size(), get_block_datetime(bl)))
{
LOG_PRINT_L0("Block with id: " << id << " failed to add transaction to blockchain storage");
bvc.m_verification_failed = true;
@ -5454,7 +5455,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
TIME_MEASURE_START_PD(tx_prapare_append);
uint64_t current_bc_size = get_current_blockchain_size();
uint64_t actual_timestamp = get_actual_timestamp(bl);
uint64_t actual_timestamp = get_block_datetime(bl);
TIME_MEASURE_FINISH_PD(tx_prapare_append);
TIME_MEASURE_START_PD(tx_append_time);
if(!add_transaction_from_block(tx, tx_id, id, current_bc_size, actual_timestamp))
@ -5622,7 +5623,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
stringstream powpos_str_entry, timestamp_str_entry;
if (is_pos_bl)
{ // PoS
int64_t actual_ts = get_actual_timestamp(bei.bl); // signed int is intentionally used here
int64_t actual_ts = get_block_datetime(bei.bl); // signed int is intentionally used here
int64_t ts_diff = actual_ts - m_core_runtime_config.get_core_time();
powpos_str_entry << "PoS:\t" << proof_hash << ", stake amount: " << print_money_brief(pos_coinstake_amount) << ", final_difficulty: " << this_coin_diff;
timestamp_str_entry << ", actual ts: " << actual_ts << " (diff: " << std::showpos << ts_diff << "s) block ts: " << std::noshowpos << bei.bl.timestamp << " (shift: " << std::showpos << static_cast<int64_t>(bei.bl.timestamp) - actual_ts << ")";

View file

@ -26,6 +26,7 @@ using namespace epee;
#include "bc_payments_id_service.h"
#include "bc_escrow_service.h"
#include "bc_attachments_helpers.h"
#include "bc_block_datetime_service.h"
#include "genesis.h"
#include "genesis_acc.h"
#include "common/mnemonic-encoding.h"
@ -64,11 +65,6 @@ namespace currency
pos_entry());
}*/
//---------------------------------------------------------------
uint64_t get_coinday_weight(uint64_t amount)
{
return amount;
}
//---------------------------------------------------------------
wide_difficulty_type correct_difficulty_with_sequence_factor(size_t sequence_factor, wide_difficulty_type diff)
{
//delta=delta*(0.75^n)
@ -594,12 +590,12 @@ namespace currency
std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys)
{
std::string blob;
string_tools::apped_pod_to_strbuff(blob, htlc.pkey_redeem);
string_tools::apped_pod_to_strbuff(blob, htlc.pkey_refund);
string_tools::apped_pod_to_strbuff(blob, acc_keys.spend_secret_key);
string_tools::append_pod_to_strbuff(blob, htlc.pkey_redeem);
string_tools::append_pod_to_strbuff(blob, htlc.pkey_refund);
string_tools::append_pod_to_strbuff(blob, acc_keys.spend_secret_key);
crypto::hash origin_hs = crypto::cn_fast_hash(blob.data(), blob.size());
std::string origin_blob;
string_tools::apped_pod_to_strbuff(origin_blob, origin_hs);
string_tools::append_pod_to_strbuff(origin_blob, origin_hs);
return origin_blob;
}
//---------------------------------------------------------------
@ -819,7 +815,7 @@ namespace currency
//take hash from derivation and use it as a salt
crypto::hash derivation_hash = crypto::cn_fast_hash(&derivation_local, sizeof(derivation_local));
std::string salted_body = original_body;
string_tools::apped_pod_to_strbuff(salted_body, derivation_hash);
string_tools::append_pod_to_strbuff(salted_body, derivation_hash);
crypto::hash proof_hash = crypto::cn_fast_hash(salted_body.data(), salted_body.size());
sa.security.push_back(*(crypto::public_key*)&proof_hash);
}
@ -890,8 +886,8 @@ namespace currency
//take hash from derivation and use it as a salt
crypto::hash derivation_hash = crypto::cn_fast_hash(&derivation_local, sizeof(derivation_local));
std::string salted_body = local_sa.body;
string_tools::apped_pod_to_strbuff(salted_body, derivation_hash);
crypto::hash proof_hash = crypto::cn_fast_hash(salted_body.data(), salted_body.size());
string_tools::append_pod_to_strbuff(salted_body, derivation_hash);
crypto::hash proof_hash = crypto::cn_fast_hash(salted_body.data(), salted_body.size()); // proof_hash = Hs(local_sa.body || Hs(s * R)), s - spend secret, R - tx pub
CHECK_AND_ASSERT_MES(*(crypto::public_key*)&proof_hash == sa.security.front(), void(), "Proof hash missmatch on decrypting with TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF");
}
@ -2062,8 +2058,8 @@ namespace currency
crypto::hash hash_together(const pod_operand_a& a, const pod_operand_b& b)
{
std::string blob;
string_tools::apped_pod_to_strbuff(blob, a);
string_tools::apped_pod_to_strbuff(blob, b);
string_tools::append_pod_to_strbuff(blob, a);
string_tools::append_pod_to_strbuff(blob, b);
return crypto::cn_fast_hash(blob.data(), blob.size());
}
//------------------------------------------------------------------
@ -2113,6 +2109,8 @@ namespace currency
return median_fee * 10;
}
//---------------------------------------------------------------
// NOTE: this function is obsolete and depricated
// PoS block real timestamp is set using a service attachment in mining tx extra since 2021-10
uint64_t get_actual_timestamp(const block& b)
{
uint64_t tes_ts = b.timestamp;
@ -2124,6 +2122,41 @@ namespace currency
}
return tes_ts;
}
//---------------------------------------------------------------
// returns timestamp from BC_BLOCK_DATETIME_SERVICE_ID via tx_service_attachment in extra
// fallbacks to old-style actual timestamp via etc_tx_time, then to block timestamp
uint64_t get_block_datetime(const block& b)
{
// first try BC_BLOCK_DATETIME_SERVICE_ID
tx_service_attachment sa = AUTO_VAL_INIT(sa);
if (get_type_in_variant_container(b.miner_tx.extra, sa))
{
if (sa.service_id == BC_BLOCK_DATETIME_SERVICE_ID && sa.instruction == BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT)
{
uint64_t ts;
if (epee::string_tools::get_pod_from_strbuff(sa.body, ts))
return ts;
}
}
// next try etc_tx_time
etc_tx_time t = AUTO_VAL_INIT(t);
if (get_type_in_variant_container(b.miner_tx.extra, t))
return t.v;
// otherwise return default: block.ts
return b.timestamp;
}
//---------------------------------------------------------------
void set_block_datetime(uint64_t datetime, block& b)
{
tx_service_attachment sa = AUTO_VAL_INIT(sa);
sa.service_id = BC_BLOCK_DATETIME_SERVICE_ID;
sa.instruction = BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT;
sa.flags = 0;
epee::string_tools::append_pod_to_strbuff(sa.body, datetime);
b.miner_tx.extra.push_back(sa);
}
//------------------------------------------------------------------
bool validate_alias_name(const std::string& al)
{
@ -2782,7 +2815,7 @@ namespace currency
pei_rpc.timestamp = bei_chain.bl.timestamp;
pei_rpc.id = epee::string_tools::pod_to_hex(h);
pei_rpc.prev_id = epee::string_tools::pod_to_hex(bei_chain.bl.prev_id);
pei_rpc.actual_timestamp = get_actual_timestamp(bei_chain.bl);
pei_rpc.actual_timestamp = get_block_datetime(bei_chain.bl);
pei_rpc.type = is_pos_block(bei_chain.bl) ? 0 : 1;
pei_rpc.already_generated_coins = boost::lexical_cast<std::string>(bei_chain.already_generated_coins);
pei_rpc.this_block_fee_median = bei_chain.this_block_tx_fee_median;

View file

@ -329,8 +329,10 @@ namespace currency
// prints amount in format "3.14", "0.0"
std::string print_money_brief(uint64_t amount);
uint64_t get_actual_timestamp(const block& b);
uint64_t get_actual_timestamp(const block& b); // obsolete and depricated, use get_block_datetime
uint64_t get_block_datetime(const block& b);
void set_block_datetime(uint64_t datetime, block& b);
bool addendum_to_hexstr(const std::vector<crypto::hash>& add, std::string& hex_buff);
bool hexstr_to_addendum(const std::string& hex_buff, std::vector<crypto::hash>& add);
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id);
@ -346,7 +348,6 @@ namespace currency
//PoS
bool is_pos_block(const block& b);
bool is_pos_block(const transaction& tx);
uint64_t get_coinday_weight(uint64_t amount);
wide_difficulty_type correct_difficulty_with_sequence_factor(size_t sequence_factor, wide_difficulty_type diff);
void print_currency_details();
std::string print_reward_change_first_blocks(size_t n_of_first_blocks);

View file

@ -97,8 +97,8 @@ namespace bc_services
inline currency::blobdata make_offer_sig_blob(const update_offer& uo)
{
currency::blobdata bd;
epee::string_tools::apped_pod_to_strbuff(bd, uo.tx_id);
epee::string_tools::apped_pod_to_strbuff(bd, uo.offer_index);
epee::string_tools::append_pod_to_strbuff(bd, uo.tx_id);
epee::string_tools::append_pod_to_strbuff(bd, uo.offer_index);
bd += epee::serialization::store_t_to_binary(uo.of);
return bd;
}
@ -106,8 +106,8 @@ namespace bc_services
inline currency::blobdata make_offer_sig_blob(const cancel_offer& co)
{
currency::blobdata bd;
epee::string_tools::apped_pod_to_strbuff(bd, co.tx_id);
epee::string_tools::apped_pod_to_strbuff(bd, co.offer_index);
epee::string_tools::append_pod_to_strbuff(bd, co.tx_id);
epee::string_tools::append_pod_to_strbuff(bd, co.offer_index);
return bd;
}

View file

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

View file

@ -330,7 +330,7 @@ private:
currency::block_extended_info bei = AUTO_VAL_INIT(bei);
CHECK_AND_ASSERT_MES(bcs.get_block_extended_info_by_height(tx_chain_entry->m_keeper_block_height, bei), false, "cannot find block by height " << tx_chain_entry->m_keeper_block_height);
LOG_PRINT_L0("Key image found in tx: " << tx_id << " height " << tx_chain_entry->m_keeper_block_height << " (ts: " << epee::misc_utils::get_time_str_v2(currency::get_actual_timestamp(bei.bl)) << ")" << ENDL
LOG_PRINT_L0("Key image found in tx: " << tx_id << " height " << tx_chain_entry->m_keeper_block_height << " (ts: " << epee::misc_utils::get_time_str_v2(currency::get_block_datetime(bei.bl)) << ")" << ENDL
<< obj_to_json_str(tx_chain_entry->tx));
}
else

View file

@ -643,6 +643,7 @@ bool MainWindow::show_inital()
restore_pos(true);
else
{
m_config = AUTO_VAL_INIT(m_config);
this->show();
QSize sz;
sz.setHeight(770);
@ -651,6 +652,7 @@ bool MainWindow::show_inital()
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 +729,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 +825,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(false);
}
bool MainWindow::update_wallets_info(const view::wallets_summary_info& wsi)
{
TRY_ENTRY();
@ -834,6 +865,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 +887,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 +904,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;

View file

@ -64,6 +64,7 @@ public:
std::pair<int64_t, int64_t> m_window_size;
bool is_maximazed;
bool is_showed;
bool disable_notifications;
};
protected slots:
@ -150,6 +151,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 +181,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 +260,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,

@ -1 +1 @@
Subproject commit fd506b5669624c8deeab901347228c400d9dc89d
Subproject commit b028252d30a32e80c12fa890c306d3c5842e937a

View file

@ -64,9 +64,9 @@ int main(int argc, char *argv[])
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();

View file

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

View file

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

View file

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

View file

@ -180,7 +180,7 @@ namespace currency
res.pos_block_ts_shift_vs_actual = 0;
auto last_pos_block_ptr = m_core.get_blockchain_storage().get_last_block_of_type(true);
if (last_pos_block_ptr)
res.pos_block_ts_shift_vs_actual = last_pos_block_ptr->bl.timestamp - get_actual_timestamp(last_pos_block_ptr->bl);
res.pos_block_ts_shift_vs_actual = last_pos_block_ptr->bl.timestamp - get_block_datetime(last_pos_block_ptr->bl);
}
if (req.flags&COMMAND_RPC_GET_INFO_FLAG_OUTS_STAT)
m_core.get_blockchain_storage().get_outs_index_stat(res.outs_stat);
@ -916,17 +916,6 @@ namespace currency
error_resp.message = "Block not accepted";
return false;
}
//@#@
//temporary double check timestamp
if (time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) > 5)
{
LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")");
//mark node to make it easier to find it via scanner
m_core.get_blockchain_storage().get_performnce_data().epic_failure_happend = true;
}
//
res.status = "OK";
return true;
@ -973,17 +962,6 @@ namespace currency
error_resp.message = "Block not accepted";
return false;
}
//@#@
//temporary double check timestamp
if (time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) > 5)
{
LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")");
//mark node to make it easier to find it via scanner
m_core.get_blockchain_storage().get_performnce_data().epic_failure_happend = true;
}
//
res.status = "OK";
return true;

View file

@ -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;
}
//----------------------------------------------------------------------------------------------------
@ -1183,7 +1158,7 @@ bool simple_wallet::validate_wrap_status(uint64_t amount)
currency::void_struct req = AUTO_VAL_INIT(req);
currency::rpc_get_wrap_info_response res = AUTO_VAL_INIT(res);
bool r = epee::net_utils::invoke_http_json_remote_command2("http://wrapped.zano.org/api/get_wrap_info", req, res, http_client, 10000);
bool r = epee::net_utils::invoke_http_json_remote_command2("http://wrapped.zano.org/api2/get_wrap_info", req, res, http_client, 10000);
if (!r)
{
fail_msg_writer() << "Failed to request wrap status from server, check internet connection";

View file

@ -5,9 +5,9 @@
#define PROJECT_MAJOR_VERSION "1"
#define PROJECT_MINOR_VERSION "3"
#define PROJECT_REVISION "0"
#define PROJECT_REVISION "1"
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
#define PROJECT_VERSION_BUILD_NO 132
#define PROJECT_VERSION_BUILD_NO 134
#define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO)
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"

View file

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

View file

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

View file

@ -1281,7 +1281,7 @@ void wallet2::handle_money_received2(const currency::block& b, const currency::t
m_transfer_history.push_back(AUTO_VAL_INIT(wallet_public::wallet_transfer_info()));
wallet_public::wallet_transfer_info& wti = m_transfer_history.back();
wti.is_income = true;
prepare_wti(wti, get_block_height(b), get_actual_timestamp(b), tx, amount, td);
prepare_wti(wti, get_block_height(b), get_block_datetime(b), tx, amount, td);
WLT_LOG_L1("[MONEY RECEIVED]: " << epee::serialization::store_t_to_json(wti));
rise_on_transfer2(wti);
}
@ -1311,7 +1311,7 @@ void wallet2::handle_money_spent2(const currency::block& b,
wti.remote_addresses = recipients;
wti.recipients_aliases = recipients_aliases;
prepare_wti(wti, get_block_height(b), get_actual_timestamp(b), in_tx, amount, td);
prepare_wti(wti, get_block_height(b), get_block_datetime(b), in_tx, amount, td);
WLT_LOG_L1("[MONEY SPENT]: " << epee::serialization::store_t_to_json(wti));
rise_on_transfer2(wti);
}
@ -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)
@ -3377,16 +3458,13 @@ bool wallet2::prepare_and_sign_pos_block(currency::block& b,
return true;
}
//------------------------------------------------------------------
bool wallet2::build_kernel(const pos_entry& pe, const stake_modifier_type& stake_modifier, stake_kernel& kernel, uint64_t& coindays_weight, uint64_t timestamp)
bool wallet2::build_kernel(const pos_entry& pe, const stake_modifier_type& stake_modifier, const uint64_t timestamp, stake_kernel& kernel)
{
PROFILE_FUNC("build_kernel");
coindays_weight = 0;
kernel = stake_kernel();
kernel.kimage = pe.keyimage;
kernel.stake_modifier = stake_modifier;
kernel.block_timestamp = timestamp;
coindays_weight = get_coinday_weight(pe.amount);
return true;
}
//----------------------------------------------------------------------------------------------------
@ -3457,7 +3535,7 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
build_minted_block(ctx.sp, ctx.rsp, miner_address);
}
WLT_LOG_L0("PoS mining iteration finished, status: " << ctx.rsp.status << ", used " << ctx.sp.pos_entries.size() << " entries with total amount: " << print_money_brief(pos_entries_amount));
WLT_LOG_L0("PoS mining: " << ctx.rsp.iterations_processed << " iterations finished, status: " << ctx.rsp.status << ", used " << ctx.sp.pos_entries.size() << " entries with total amount: " << print_money_brief(pos_entries_amount));
return true;
}
@ -3533,12 +3611,11 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
const currency::txout_to_key& txtokey = boost::get<currency::txout_to_key>(target);
keys_ptrs.push_back(&txtokey.key);
//put actual time for tx block
// set a real timestamp
b.timestamp = rsp.block_timestamp;
currency::etc_tx_time tt = AUTO_VAL_INIT(tt);
tt.v = m_core_runtime_config.get_core_time();
b.miner_tx.extra.push_back(tt);
WLT_LOG_MAGENTA("Applying actual timestamp: " << epee::misc_utils::get_time_str(tt.v), LOG_LEVEL_0);
uint64_t current_timestamp = m_core_runtime_config.get_core_time();
set_block_datetime(current_timestamp, b);
WLT_LOG_MAGENTA("Applying actual timestamp: " << current_timestamp, LOG_LEVEL_0);
//sign block
res = prepare_and_sign_pos_block(b,
@ -3564,14 +3641,7 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
}
WLT_LOG_GREEN("POS block generated and accepted, congrats!", LOG_LEVEL_0);
m_wcallback->on_pos_block_found(b);
//@#@
//double check timestamp
if (time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) > 5)
{
WLT_LOG_RED("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")", LOG_LEVEL_0);
}
//
return true;
}
//----------------------------------------------------------------------------------------------------

View file

@ -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);
@ -920,7 +921,7 @@ private:
void handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop,
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks);
std::string get_alias_for_address(const std::string& addr);
static bool build_kernel(const currency::pos_entry& pe, const currency::stake_modifier_type& stake_modifier, currency::stake_kernel& kernel, uint64_t& coindays_weight, uint64_t timestamp);
static bool build_kernel(const currency::pos_entry& pe, const currency::stake_modifier_type& stake_modifier, const uint64_t timestamp, currency::stake_kernel& kernel);
bool is_connected_to_net();
bool is_transfer_okay_for_pos(const transfer_details& tr, uint64_t& stake_unlock_time);
bool scan_unconfirmed_outdate_tx();
@ -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
@ -1203,16 +1208,20 @@ namespace tools
const currency::core_runtime_config &runtime_config)
{
cxt.rsp.status = API_RETURN_CODE_NOT_FOUND;
uint64_t timstamp_start = runtime_config.get_core_time();
uint64_t timstamp_last_idle_call = runtime_config.get_core_time();
cxt.rsp.iterations_processed = 0;
uint64_t ts_from = cxt.rsp.starter_timestamp; // median ts of last BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW blocks
ts_from = ts_from - (ts_from % POS_SCAN_STEP) + POS_SCAN_STEP;
uint64_t ts_to = runtime_config.get_core_time() + CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT - 5;
ts_to = ts_to - (ts_to % POS_SCAN_STEP);
CHECK_AND_ASSERT_MES(ts_to > ts_from, false, "scan_pos: ts_to <= ts_from: " << ts_to << ", " << ts_from);
uint64_t ts_middle = (ts_to + ts_from) / 2;
ts_middle -= ts_middle % POS_SCAN_STEP;
uint64_t ts_window = std::min(ts_middle - ts_from, ts_to - ts_middle);
for (size_t i = 0; i != cxt.sp.pos_entries.size(); i++)
{
//set timestamp starting from timestamp%POS_SCAN_STEP = 0
uint64_t adjusted_starter_timestamp = timstamp_start - POS_SCAN_STEP;
adjusted_starter_timestamp = POS_SCAN_STEP * 2 - (adjusted_starter_timestamp%POS_SCAN_STEP) + adjusted_starter_timestamp;
bool go_past = true;
uint64_t step = 0;
@ -1232,7 +1241,7 @@ namespace tools
}
};
while(step <= POS_SCAN_WINDOW)
while(step <= ts_window)
{
//check every WALLET_POS_MINT_CHECK_HEIGHT_INTERVAL seconds if top block changes, in case - break loop
@ -1248,8 +1257,8 @@ namespace tools
}
uint64_t ts = go_past ? adjusted_starter_timestamp - step : adjusted_starter_timestamp + step;
if (ts < cxt.rsp.starter_timestamp)
uint64_t ts = go_past ? ts_middle - step : ts_middle + step;
if (ts < ts_from || ts > ts_to)
{
next_turn();
continue;
@ -1258,27 +1267,27 @@ namespace tools
if (stop)
return false;
currency::stake_kernel sk = AUTO_VAL_INIT(sk);
uint64_t coindays_weight = 0;
build_kernel(cxt.sp.pos_entries[i], cxt.sm, sk, coindays_weight, ts);
const uint64_t& stake_amount = cxt.sp.pos_entries[i].amount;
build_kernel(cxt.sp.pos_entries[i], cxt.sm, ts, sk);
crypto::hash kernel_hash;
{
PROFILE_FUNC("calc_hash");
kernel_hash = crypto::cn_fast_hash(&sk, sizeof(sk));
}
currency::wide_difficulty_type this_coin_diff = cxt.basic_diff / coindays_weight;
currency::wide_difficulty_type final_diff = cxt.basic_diff / stake_amount;
bool check_hash_res;
{
PROFILE_FUNC("check_hash");
check_hash_res = currency::check_hash(kernel_hash, this_coin_diff);
check_hash_res = currency::check_hash(kernel_hash, final_diff);
++cxt.rsp.iterations_processed;
}
if (check_hash_res)
{
//found kernel
LOG_PRINT_GREEN("Found kernel: amount=" << currency::print_money(cxt.sp.pos_entries[i].amount) << ENDL
<< "difficulty_basic=" << cxt.basic_diff << ", diff for this coin: " << this_coin_diff << ENDL
<< "index=" << cxt.sp.pos_entries[i].index << ENDL
LOG_PRINT_GREEN("Found kernel: amount: " << currency::print_money(stake_amount) << ENDL
<< "difficulty: " << cxt.basic_diff << ", final_diff: " << final_diff << ENDL
<< "index: " << cxt.sp.pos_entries[i].index << ENDL
<< "kernel info: " << ENDL
<< print_stake_kernel_info(sk) << ENDL
<< "kernel_hash(proof): " << kernel_hash,

View file

@ -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)
@ -91,6 +95,18 @@ namespace tools
LOG_PRINT_L2("wallet RPC idle: trying to do PoS iteration...");
m_wallet.try_mint_pos(miner_address);
}
//auto-store wallet in server mode, let's do it every 24-hour
if (m_wallet.get_top_block_height() < m_last_wallet_store_height)
{
LOG_ERROR("Unexpected m_last_wallet_store_height = " << m_last_wallet_store_height << " or " << m_wallet.get_top_block_height());
}
else if (m_wallet.get_top_block_height() - m_last_wallet_store_height > CURRENCY_BLOCKS_PER_DAY)
{
//store wallet
m_wallet.store();
m_last_wallet_store_height = m_wallet.get_top_block_height();
}
}
catch (error::no_connection_to_daemon&)
{
@ -132,6 +148,7 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::init(const boost::program_options::variables_map& vm)
{
m_last_wallet_store_height = m_wallet.get_top_block_height();
m_net_server.set_threads_prefix("RPC");
bool r = handle_command_line(vm);
CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server");
@ -296,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;
@ -384,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())
{

View file

@ -118,6 +118,7 @@ namespace tools
std::string m_bind_ip;
bool m_do_mint;
bool m_deaf;
uint64_t m_last_wallet_store_height;
};
} // namespace tools

View file

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

View file

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

View file

@ -563,17 +563,15 @@ bool test_generator::find_kernel(const std::list<currency::account_base>& accs,
{
stake_kernel sk = AUTO_VAL_INIT(sk);
uint64_t coindays_weight = 0;
build_kernel(scan_pos_entries.pos_entries[i].amount,
scan_pos_entries.pos_entries[i].index,
scan_pos_entries.pos_entries[i].keyimage,
sk,
coindays_weight,
blck_chain,
indexes,
ts);
crypto::hash kernel_hash = crypto::cn_fast_hash(&sk, sizeof(sk));
wide_difficulty_type this_coin_diff = basic_diff / coindays_weight;
wide_difficulty_type this_coin_diff = basic_diff / scan_pos_entries.pos_entries[i].amount;
if (!check_hash(kernel_hash, this_coin_diff))
continue;
else
@ -672,12 +670,10 @@ bool test_generator::build_kernel(uint64_t amount,
uint64_t global_index,
const crypto::key_image& ki,
stake_kernel& kernel,
uint64_t& coindays_weight,
const test_generator::blockchain_vector& blck_chain,
const test_generator::outputs_index& indexes,
uint64_t timestamp)
{
coindays_weight = 0;
kernel = stake_kernel();
kernel.kimage = ki;
@ -701,7 +697,6 @@ bool test_generator::build_kernel(uint64_t amount,
kernel.block_timestamp = timestamp;
coindays_weight = get_coinday_weight(amount);
build_stake_modifier(kernel.stake_modifier, blck_chain);
return true;
}
@ -2058,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)

View file

@ -410,7 +410,6 @@ public:
uint64_t global_index,
const crypto::key_image& ki,
currency::stake_kernel& kernel,
uint64_t& coindays_weight,
const blockchain_vector& blck_chain,
const outputs_index& indexes,
uint64_t timestamp);
@ -680,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>

View file

@ -867,6 +867,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);

View file

@ -112,7 +112,7 @@ bool emission_test::c1(currency::core& c, size_t ev_index, const std::vector<tes
pb.step2_set_txs(std::vector<transaction>());
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, difficulty, prev_id, null_hash, timestamp);
pb.step4_generate_coinbase_tx(0, already_generated_coins, m_miner_acc.get_public_address());
pb.m_block.miner_tx.extra.push_back(currency::etc_tx_time({ timestamp })); // actual timestamp
set_block_datetime(timestamp, pb.m_block);
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, m_miner_acc);
c.handle_incoming_block(t_serializable_object_to_blob(pb.m_block), bvc);

View file

@ -634,7 +634,7 @@ bool hard_fork_1_pos_and_locked_coins::generate(std::vector<test_event_entry>& e
{
MAKE_NEXT_POS_BLOCK(events, b, prev, miner_acc, std::list<currency::account_base>{miner_acc});
prev = b;
events.push_back(event_core_time(get_actual_timestamp(b) + 100));
events.push_back(event_core_time(get_block_datetime(b) + 100));
}

View file

@ -23,6 +23,10 @@ isolate_auditable_and_proof::isolate_auditable_and_proof()
bool isolate_auditable_and_proof::generate(std::vector<test_event_entry>& events) const
{
// Test outline: this test makes sure:
// 1) that only owner of the secret spend key can decode the attachment (TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE)
// 2) TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF -- add public hash of original info
random_state_test_restorer::reset_random(0); // to make the test deterministic
m_genesis_timestamp = 1450000000;
test_core_time::adjust(m_genesis_timestamp);
@ -87,7 +91,7 @@ bool isolate_auditable_and_proof::c1(currency::core& c, size_t ev_index, const s
tx_service_attachment sa = AUTO_VAL_INIT(sa);
sa.service_id = BC_WRAP_SERVICE_ID;
sa.instruction = BC_WRAP_SERVICE_INSTRUCTION_ERC20;
sa.flags = TX_SERVICE_ATTACHMENT_ENCRYPT_BODY | TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE| TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF;
sa.flags = TX_SERVICE_ATTACHMENT_ENCRYPT_BODY | TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE | TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF;
sa.body = "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B";
extra.push_back(sa);
@ -122,4 +126,3 @@ bool isolate_auditable_and_proof::c1(currency::core& c, size_t ev_index, const s
return true;
}

View file

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

View file

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

View file

@ -1365,7 +1365,7 @@ bool gen_wallet_transfers_and_chain_switch::generate(std::vector<test_event_entr
CHECK_AND_ASSERT_MES(trs.size() == 2 && trs[0].is_spent() && trs[1].is_spent(), false, "Wrong transfers state");
// fast forward time to make tx_1 and tx_2 outdated (blk_3 is the block where tx_2 came with)
test_core_time::adjust(get_actual_timestamp(blk_3) + CURRENCY_MEMPOOL_TX_LIVETIME + 1);
test_core_time::adjust(get_block_datetime(blk_3) + CURRENCY_MEMPOOL_TX_LIVETIME + 1);
MAKE_NEXT_BLOCK(events, blk_5a, blk_4a, miner_acc);