1
0
Fork 0
forked from lthn/blockchain

Merge branch 'cryptoassets' into cake

This commit is contained in:
cryptozoidberg 2023-11-21 18:05:40 +01:00
commit 41452dbb4c
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
56 changed files with 1661 additions and 980 deletions

View file

@ -123,22 +123,22 @@ DISABLE_VS_WARNINGS(4100)
#if defined(ENABLE_LOGGING_INTERNAL)
#define LOG_PRINT_CHANNEL_NO_PREFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
#define LOG_PRINT_CHANNEL_NO_PREFIX2(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
{TRY_ENTRY();std::stringstream ss________; ss________ << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str() , y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}}
#define LOG_PRINT_CHANNEL_NO_PREFIX_NO_POSTFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
#define LOG_PRINT_CHANNEL_NO_PREFIX_NO_POSTFIX2(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
{TRY_ENTRY();std::stringstream ss________; ss________ << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}}
#define LOG_PRINT_CHANNEL_NO_POSTFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
#define LOG_PRINT_CHANNEL_NO_POSTFIX2(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}}
#define LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
#define LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, cb) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);cb(ss________.str());CATCH_ALL_DO_NOTHING();}}
#define LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
#define LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, cb) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, color, false, log_name); cb(ss________.str());CATCH_ALL_DO_NOTHING();}}
#define LOG_PRINT_CHANNEL_2_JORNAL(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
#define LOG_PRINT_CHANNEL_2_JORNAL(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, true, log_name);CATCH_ALL_DO_NOTHING();}}
#define LOG_ERROR2_CB(log_name, x, cb) { \

View file

@ -31,12 +31,20 @@
#include "http_base.h"
#include "net/net_utils_base.h"
template<typename typename_t>
typename_t get_documentation_json_struct()
{
return AUTO_VAL_INIT_T(typename_t);
}
template<typename request_t, typename response_t>
bool auto_doc_t(const std::string& prefix_name, std::string& generate_reference)
{
if (!generate_reference.size()) return true;
request_t req = AUTO_VAL_INIT(req);
response_t res = AUTO_VAL_INIT(res);
request_t req = get_documentation_json_struct<request_t>();
response_t res = get_documentation_json_struct<response_t>();
std::stringstream ss;
ss << prefix_name << ENDL
<< "REQUEST: " << ENDL << epee::serialization::store_t_to_json(req) << ENDL << "--------------------------------" << ENDL

View file

@ -65,7 +65,7 @@ namespace epee
bool res = m_net_server.init_server(bind_port, bind_ip);
if(!res)
{
LOG_ERROR("Failed to bind server");
LOG_ERROR("Failed to bind to " << bind_ip << ":" << bind_port);
return false;
}
return true;
@ -74,14 +74,14 @@ namespace epee
bool run(size_t threads_count, bool wait = true)
{
//go to loop
LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0);
LOG_PRINT("Run net_service loop (" << threads_count << " threads)...", LOG_LEVEL_1);
if(!m_net_server.run_server(threads_count, wait))
{
LOG_ERROR("Failed to run net tcp server!");
}
if(wait)
LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0);
LOG_PRINT("net_service loop stopped.", LOG_LEVEL_1);
return true;
}

View file

@ -77,8 +77,7 @@ namespace epee
bool insert_next_section(harray hSecArray, hsection& hinserted_childsection);
//------------------------------------------------------------------------
//delete entry (section, value or array)
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
//-------------------------------------------------------------------------------
bool store_to_binary(binarybuffer& target);
bool load_from_binary(const binarybuffer& target);
@ -87,6 +86,8 @@ namespace epee
bool dump_as_json(std::string& targetObj, size_t indent = 0, end_of_line_t eol = eol_crlf);
bool load_from_json(const std::string& source);
template<typename cb_t>
bool enum_entries(hsection hparent_section, cb_t cb);
private:
section m_root;
hsection get_root_section() {return &m_root;}
@ -384,6 +385,20 @@ namespace epee
CATCH_ENTRY("portable_storage::insert_first_value", nullptr);
}
//---------------------------------------------------------------------------------------------------------------
template<typename cb_t>
bool portable_storage::enum_entries(hsection hparent_section, cb_t cb)
{
TRY_ENTRY();
if (!hparent_section) hparent_section = &m_root;
for (const auto& e : hparent_section->m_entries)
{
if (!cb(e.first, e.second))
break;
}
return true;
CATCH_ENTRY("portable_storage::enum_entries", false);
}
template<class t_value>
bool portable_storage::insert_next_value(harray hval_array, const t_value& target)
{

View file

@ -37,6 +37,7 @@
#endif
#include <windows.h>
#endif
#include <cctype>
#include "warnings.h"
@ -310,7 +311,14 @@ namespace string_encoding
return get_md5_as_hexstring(src.data(), src.size());
}
#endif
inline
std::string toupper(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return std::toupper(c); } // correct
);
return s;
}
}
}

View file

@ -18,6 +18,7 @@ template<size_t A, size_t B> struct TAssertEquality {
#define BOOST_SERIALIZE(x) _arch & x;
#define BOOST_SERIALIZE_BASE_CLASS(class_type) _arch & static_cast<class_type&>(*this);
#define BOOST_END_VERSION_UNDER(x) \
if(ver < x ) {return;}

View file

@ -21,8 +21,8 @@ namespace tools
};
#ifndef TESTNET
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_1569000.pak", "c2aff6fb65c2d7a40492738c75d1d04f2f35388d3c1a664aeb77420f2d90d644", 1740147926, 3221176320 };
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_1569000.pak", "f673636638b666b36c976168a3c64b2fd1fcf071c41b5d9cf01ed58a5924f80a", 2244905636, 3216977920 };
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_2200000.pak", "c3bd64c62495c3f266759750952519f13f32fc161b59547beaa8202b6e26d516", 2628767033, 5100195840 };
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_2200000.pak", "fcbf0ab3b23836e1a51fa675e719900fb94110cfb74790b3323cebce7fb9f5bd", 3426025872, 4954472448 };
#else
static constexpr pre_download_entry c_pre_download_mdbx = { "", "", 0, 0 };
static constexpr pre_download_entry c_pre_download_lmdb = { "", "", 0, 0 };

View file

@ -2646,7 +2646,7 @@ bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDO
}
if (result_outs.outs.size() < req.decoys_count)
{
LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.decoys_count << ", added " << result_outs.outs.size() << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total");
LOG_PRINT_YELLOW("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.decoys_count << ", added " << result_outs.outs.size() << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total", LOG_LEVEL_0);
}
}
else
@ -2654,7 +2654,7 @@ bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDO
size_t added = 0;
for (size_t i = 0; i != up_index_limit; i++)
added += add_out_to_get_random_outs(result_outs, amount, i, req.decoys_count, req.use_forced_mix_outs, req.height_upper_limit) ? 1 : 0;
LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.decoys_count << ", added " << added << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total - respond with all good outs");
LOG_PRINT_YELLOW("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.decoys_count << ", added " << added << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total - respond with all good outs", LOG_LEVEL_0);
}
}
return true;
@ -2889,6 +2889,51 @@ size_t blockchain_storage::get_current_sequence_factor_for_alt(alt_chain_type& a
return n;
}
//------------------------------------------------------------------
bool blockchain_storage::get_pos_votes(uint64_t start_index, uint64_t end_index, vote_results& r)
{
CRITICAL_REGION_LOCAL(m_read_lock);
if (start_index >= m_db_blocks.size() || start_index >= end_index)
{
//LOG_PRINT_L0("Wrong starter or end index set: start_index = " << start_index << ", end_index=" << end_index << ", expected max index " << m_db_blocks.size() - 1);
return true;
}
std::map<std::string, vote_on_proposal> summary;
for (size_t i = start_index; i < m_db_blocks.size() && i < end_index; i++)
{
auto block_ptr = m_db_blocks[i];
//only coin holders can vote
if(!is_pos_block(block_ptr->bl))
continue;
r.total_pos_blocks++;
extra_user_data eud = AUTO_VAL_INIT(eud);
if (!get_type_in_variant_container(block_ptr->bl.miner_tx.extra, eud))
{
continue;
}
std::list<std::pair<std::string, bool>> votes;
if (!currency::parse_vote(eud.buff, votes))
{
continue;
}
for (const auto& v : votes)
{
if (v.second)
summary[v.first].yes++;
else
summary[v.first].no++;
}
}
for (const auto s_entry : summary)
{
r.votes.push_back(s_entry.second);
r.votes.back().proposal_id = s_entry.first;
}
return true;
}
//------------------------------------------------------------------
std::string blockchain_storage::get_blockchain_string(uint64_t start_index, uint64_t end_index) const
{
std::stringstream ss;
@ -4201,9 +4246,6 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const
if (need_to_profile && max_mixins_count > 0)
{
m_performance_data.tx_mixin_count.push(max_mixins_count);
#ifdef _DEBUG
LOG_PRINT_L0("[TX_MIXINS]: " << max_mixins_count);
#endif
}
//check if there is already transaction with this hash
@ -5660,15 +5702,19 @@ bool blockchain_storage::validate_pos_block(const block& b,
CHECK_AND_ASSERT_MES(!have_tx_keyimg_as_spent(stake_key_image), false, "stake key image has been already spent in blockchain: " << stake_key_image);
}
// 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)
)
if (!is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM))
{
LOG_PRINT_L0("PoS block actual timestamp " << actual_ts << " differs from b.timestamp " << b.timestamp << " by " << ((int64_t)actual_ts - (int64_t)b.timestamp) << " s, it's more than allowed " << POS_MAX_ACTUAL_TIMESTAMP_TO_MINED << " s.");
return false;
// 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
// TODO: remove this entire section after HF4 -- sowle
uint64_t actual_ts = get_block_timestamp_from_miner_tx_extra(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)
)
{
LOG_PRINT_L0("PoS block actual timestamp " << actual_ts << " differs from b.timestamp " << b.timestamp << " by " << ((int64_t)actual_ts - (int64_t)b.timestamp) << " s, it's more than allowed " << POS_MAX_ACTUAL_TIMESTAMP_TO_MINED << " s.");
return false;
}
}
// build kernel and calculate hash

View file

@ -457,6 +457,7 @@ namespace currency
void serialize(archive_t & ar, const unsigned int version);
bool get_est_height_from_date(uint64_t date, uint64_t& res_h)const;
bool get_pos_votes(uint64_t start_h, uint64_t end_h, vote_results& r);
//debug functions
bool validate_blockchain_prev_links(size_t last_n_blocks_to_check = 10) const;

View file

@ -159,6 +159,28 @@ namespace currency
transactions_map onboard_transactions;
};
struct vote_on_proposal
{
std::string proposal_id;
uint64_t yes;
uint64_t no;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(proposal_id)
KV_SERIALIZE(yes)
KV_SERIALIZE(no)
END_KV_SERIALIZE_MAP()
};
struct vote_results
{
uint64_t total_pos_blocks; //total pos blocks in a given range
std::list<vote_on_proposal> votes;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(total_pos_blocks)
KV_SERIALIZE(votes)
END_KV_SERIALIZE_MAP()
};
} // namespace currency

View file

@ -26,6 +26,7 @@ namespace currency
ADD_CHECKPOINT(900000, "2205b73cd79d4937b087b02a8b001171b73c34464bc4a952834eaf7c2bd63e86");
ADD_CHECKPOINT(1161000, "96990d851b484e30190678756ba2a4d3a2f92b987e2470728ac1e38b2bf35908");
ADD_CHECKPOINT(1480000, "5dd3381eec35e8b4eba4518bfd8eec682a4292761d92218fd59b9f0ffedad3fe");
ADD_CHECKPOINT(2000000, "7b6698a8cc279aa78d6263f01fef186bd16f5b1ea263a7f4714abc1d506b9cb3");
#endif
return true;

View file

@ -36,6 +36,8 @@
#define HF3_BLOCK_MINOR_VERSION 0
#define CURRENT_BLOCK_MAJOR_VERSION 3
#define CURRENCY_DEFAULT_DECOY_SET_SIZE 10
#define CURRENT_BLOCK_MINOR_VERSION 0
#define CURRENCY_BLOCK_FUTURE_TIME_LIMIT 60*60*2
#define CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT 60*20
@ -230,6 +232,7 @@
#define GUI_INTERNAL_CONFIG2 "gui_internal_config.json"
#define GUI_IPC_MESSAGE_CHANNEL_NAME CURRENCY_NAME_BASE "_message_que"
#define CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME "voting_config.json"
#define CURRENT_TRANSACTION_CHAIN_ENTRY_ARCHIVE_VER 3
@ -246,8 +249,8 @@
#define WALLET_FILE_SERIALIZATION_VERSION 160
#define WALLET_FILE_LAST_SUPPORTED_VERSION 160
#else
#define WALLET_FILE_LAST_SUPPORTED_VERSION (CURRENCY_FORMATION_VERSION+74)
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+74)
#define WALLET_FILE_LAST_SUPPORTED_VERSION (CURRENCY_FORMATION_VERSION+76)
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+76)
#endif
#define CURRENT_MEMPOOL_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+31)

View file

@ -504,6 +504,15 @@ namespace currency
//-----------------------------------------------------------------------------------------------
bool core::add_new_block(const block& b, block_verification_context& bvc)
{
uint64_t h = m_blockchain_storage.get_top_block_height();
if (m_stop_after_height != 0 && h >= m_stop_after_height)
{
LOG_PRINT_YELLOW("Blockchain top block height is " << h << ", the daemon will now stop as requested", LOG_LEVEL_0);
if (m_critical_error_handler)
return m_critical_error_handler->on_immediate_stop_requested();
return false;
}
bool r = m_blockchain_storage.add_new_block(b, bvc);
if (r && bvc.m_added_to_main_chain)
{

View file

@ -2751,6 +2751,35 @@ namespace currency
return timestamp;
}
//---------------------------------------------------------------
bool parse_vote(const std::string& json_, std::list<std::pair<std::string, bool>>& votes)
{
//do preliminary check of text if it looks like json
std::string::size_type pos = json_.find('{');
if (pos == std::string::npos)
return false;
std::string json = json_.substr(pos);
epee::serialization::portable_storage ps;
bool rs = ps.load_from_json(json);
if (!rs)
return false;
auto cb = [&](const std::string& name, const epee::serialization::storage_entry& entry) {
if (entry.type() == typeid(uint64_t))
{
bool vote = boost::get<uint64_t>(entry) ? true : false;
votes.push_back(std::make_pair(epee::string_encoding::toupper(name), vote));
}
return true;
};
ps.enum_entries(nullptr, cb);
return true;
}
//---------------------------------------------------------------
bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed /* = nullptr */)
{
#define LOC_CHK(cond, msg) CHECK_AND_ASSERT_MES(cond, false, msg << ", ms input index: " << ms_input_index << ", tx: " << get_transaction_hash(tx) << ", source tx: " << get_transaction_hash(source_tx))
@ -3367,9 +3396,8 @@ namespace currency
return median_fee * 10;
}
//---------------------------------------------------------------
// NOTE: this function is obsolete and depricated
[[deprecated("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)
// TODO: remove this function after HF4 -- sowle
uint64_t get_block_timestamp_from_miner_tx_extra(const block& b)
{
uint64_t tes_ts = b.timestamp;
if (is_pos_block(b))
@ -3658,50 +3686,6 @@ namespace currency
boost::get<uint64_t>(res[i]) += boost::get<uint64_t>(res[i - 1]);
}
return res;
}
//---------------------------------------------------------------
// DEPRECATED: consider using prepare_outputs_entries_for_key_offsets and absolute_sorted_output_offsets_to_relative_in_place instead
std::vector<txout_ref_v> absolute_output_offsets_to_relative(const std::vector<txout_ref_v>& off)
{
std::vector<txout_ref_v> res = off;
if (off.size() < 2)
return res;
std::sort(res.begin(), res.end(), [](const txout_ref_v& lft, const txout_ref_v& rght)
{
if (lft.type() == typeid(uint64_t))
{
if (rght.type() == typeid(uint64_t))
return boost::get<uint64_t>(lft) < boost::get<uint64_t>(rght);
else if (rght.type() == typeid(ref_by_id))
return true;
else
LOG_ERROR("Unknown type in txout_v");
}
else if (lft.type() == typeid(ref_by_id))
{
if (rght.type() == typeid(uint64_t))
return false;
else if (rght.type() == typeid(ref_by_id))
return false; // don't change the order of ref_by_id elements
else
LOG_ERROR("Unknown type in txout_v");
}
return false;
});//just to be sure, actually it is already should be sorted
//find starter index - skip ref_by_id entries
size_t i = res.size() - 1;
while (i != 0 && res[i].type() == typeid(ref_by_id))
--i;
for (; i != 0; i--)
{
boost::get<uint64_t>(res[i]) -= boost::get<uint64_t>(res[i - 1]);
}
return res;
}
//---------------------------------------------------------------
@ -3801,33 +3785,6 @@ namespace currency
}
return sum_of_amount_commitments == amount * native_coin_asset_id_pt;
}
//---------------------------------------------------------------
// DEPRECATED, don't use -- sowle
uint64_t get_amount_for_zero_pubkeys(const transaction& tx)
{
uint64_t found_alias_reward = 0;
for (const auto& out : tx.vout)
{
VARIANT_SWITCH_BEGIN(out);
VARIANT_CASE_CONST(tx_out_bare, out)
if (out.target.type() != typeid(txout_to_key))
continue;
const txout_to_key& o = boost::get<txout_to_key>(out.target);
if (o.key == null_pkey)
found_alias_reward += out.amount;
VARIANT_CASE_CONST(tx_out_zarcanum, o)
//@#@
VARIANT_SWITCH_END();
}
#ifdef TESTNET
found_alias_reward = 10 * COIN;
#else
@#@ fix it for mainnet bui
#endif
return found_alias_reward;
}
//---------------------------------------------------------------
bool get_aliases_reward_account(account_public_address& acc)
{
@ -3881,7 +3838,11 @@ namespace currency
VARIANT_SWITCH_END();
}
VARIANT_CASE_CONST(tx_out_zarcanum, o)
//@#@
tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(o.stealth_address));
tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(o.concealing_point));
tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(o.amount_commitment));
tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(o.blinded_asset_id));
tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(o.encrypted_amount));
VARIANT_SWITCH_END();
++i;
}

View file

@ -405,15 +405,13 @@ namespace currency
uint64_t get_block_height(const transaction& coinbase);
uint64_t get_block_height(const block& b);
std::vector<txout_ref_v> relative_output_offsets_to_absolute(const std::vector<txout_ref_v>& off);
// DEPRECATED: consider using prepare_outputs_entries_for_key_offsets and absolute_sorted_output_offsets_to_relative_in_place instead
[[deprecated]] std::vector<txout_ref_v> absolute_output_offsets_to_relative(const std::vector<txout_ref_v>& off);
bool absolute_sorted_output_offsets_to_relative_in_place(std::vector<txout_ref_v>& offsets) noexcept;
// prints amount in format "3.14", "0.0"
std::string print_money_brief(uint64_t amount, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT);
uint64_t get_actual_timestamp(const block& b); // obsolete and depricated, use get_block_datetime
uint64_t get_block_timestamp_from_miner_tx_extra(const block& b); // remove this function after HF4 -- sowle
uint64_t get_block_datetime(const block& b);
void set_block_datetime(uint64_t datetime, block& b);
@ -425,8 +423,6 @@ namespace currency
bool does_tx_have_only_mixin_inputs(const transaction& tx);
bool is_showing_sender_addres(const transaction& tx);
bool check_native_coins_amount_burnt_in_outs(const transaction& tx, const uint64_t amount, uint64_t* p_amount_burnt = nullptr);
[[deprecated("Use check_native_coins_amount_burnt_in_outs instead")]] uint64_t get_amount_for_zero_pubkeys(const transaction& tx);
//std::string get_comment_from_tx(const transaction& tx);
std::string print_stake_kernel_info(const stake_kernel& sk);
std::string dump_ring_sig_data(const crypto::hash& hash_for_sig, const crypto::key_image& k_image, const std::vector<const crypto::public_key*>& output_keys_ptrs, const std::vector<crypto::signature>& sig);
@ -446,7 +442,10 @@ namespace currency
bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h);
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices);
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password);
uint64_t get_timstamp_from_word(std::string word, bool& password_used, const std::string& buff);
uint64_t get_timstamp_from_word(std::string word, bool& password_used);
bool parse_vote(const std::string& buff, std::list<std::pair<std::string, bool>>& votes);
std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys);
bool validate_ado_update_allowed(const asset_descriptor_base& a, const asset_descriptor_base& b);

View file

@ -408,4 +408,17 @@ namespace currency
#endif
}
//----------------------------------------------------------------------------------------------------
std::string transform_tx_to_str(const currency::transaction& tx)
{
return currency::obj_to_json_str(tx);
}
//----------------------------------------------------------------------------------------------------
transaction transform_str_to_tx(const std::string& tx_str)
{
CHECK_AND_ASSERT_THROW_MES(false, "transform_str_to_tx shoruld never be called");
return transaction();
}
}

View file

@ -329,5 +329,9 @@ namespace currency
}; // struct tx_generation_context
bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context, const crypto::secret_key& onet_time_key);
std::string transform_tx_to_str(const transaction& tx);
transaction transform_str_to_tx(const std::string& tx_str);
} // namespace currency

@ -1 +1 @@
Subproject commit f7d1a92e9d3b2126cca41f589260802346b29a17
Subproject commit ea512b08c9166406ae5fd84ae69a6b57c9a03b67

View file

@ -669,6 +669,18 @@ namespace currency
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_votes(const COMMAND_RPC_GET_VOTES::request& req, COMMAND_RPC_GET_VOTES::response& res, connection_context& cntx)
{
if (!m_core.get_blockchain_storage().get_pos_votes(req.h_start, req.h_end, res.votes))
{
res.status = API_RETURN_CODE_INTERNAL_ERROR;
res.error_code = "Internal error";
return true;
}
res.status = API_RETURN_CODE_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_asset_info(const COMMAND_RPC_GET_ASSET_INFO::request& req, COMMAND_RPC_GET_ASSET_INFO::response& res, connection_context& cntx)
{
if (!m_core.get_blockchain_storage().get_asset_info(req.asset_id, res.asset_descriptor))

View file

@ -83,6 +83,7 @@ namespace currency
bool on_get_pool_txs_brief_details(const COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::request& req, COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::response& res, connection_context& cntx);
bool on_get_all_pool_tx_list(const COMMAND_RPC_GET_ALL_POOL_TX_LIST::request& req, COMMAND_RPC_GET_ALL_POOL_TX_LIST::response& res, connection_context& cntx);
bool on_get_pool_info(const COMMAND_RPC_GET_POOL_INFO::request& req, COMMAND_RPC_GET_POOL_INFO::response& res, connection_context& cntx);
bool on_get_votes(const COMMAND_RPC_GET_VOTES::request& req, COMMAND_RPC_GET_VOTES::response& res, connection_context& cntx);
bool on_get_asset_info(const COMMAND_RPC_GET_ASSET_INFO::request& req, COMMAND_RPC_GET_ASSET_INFO::response& res, connection_context& cntx);
bool on_get_main_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
@ -139,6 +140,8 @@ namespace currency
MAP_JON_RPC ("get_pool_txs_brief_details", on_get_pool_txs_brief_details, COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS)
MAP_JON_RPC ("get_all_pool_tx_list", on_get_all_pool_tx_list, COMMAND_RPC_GET_ALL_POOL_TX_LIST)
MAP_JON_RPC ("get_pool_info", on_get_pool_info, COMMAND_RPC_GET_POOL_INFO)
MAP_JON_RPC ("getrandom_outs", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS)
MAP_JON_RPC ("get_votes", on_get_votes, COMMAND_RPC_GET_VOTES)
//assets api
MAP_JON_RPC ("get_asset_info", on_get_asset_info, COMMAND_RPC_GET_ASSET_INFO)

View file

@ -82,6 +82,33 @@ namespace currency
};
};
struct COMMAND_RPC_GET_VOTES
{
struct request
{
uint64_t h_start;
uint64_t h_end;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(h_start)
KV_SERIALIZE(h_end)
END_KV_SERIALIZE_MAP()
};
struct response
{
std::string status;
std::string error_code;
vote_results votes;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
KV_SERIALIZE(error_code)
KV_SERIALIZE(votes)
END_KV_SERIALIZE_MAP()
};
};
struct asset_id_kv
{
crypto::public_key asset_id;

View file

@ -130,14 +130,16 @@ namespace
const command_line::arg_descriptor<bool> arg_dont_refresh ( "no-refresh", "Do not refresh after load");
const command_line::arg_descriptor<bool> arg_dont_set_date ( "no-set-creation-date", "Do not set wallet creation date", false);
const command_line::arg_descriptor<int> arg_daemon_port ("daemon-port", "Use daemon instance at port <arg> instead of default", 0);
const command_line::arg_descriptor<uint32_t> arg_log_level ("set-log", "");
//const command_line::arg_descriptor<uint32_t> arg_log_level ("set-log", "");
const command_line::arg_descriptor<bool> arg_do_pos_mining ( "do-pos-mining", "Do PoS mining", false);
const command_line::arg_descriptor<std::string> arg_pos_mining_reward_address ( "pos-mining-reward-address", "Block reward will be sent to the giving address if specified", "" );
const command_line::arg_descriptor<std::string> arg_restore_wallet ( "restore-wallet", "Restore wallet from seed phrase or tracking seed and save it to <arg>", "" );
const command_line::arg_descriptor<bool> arg_offline_mode ( "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)");
const command_line::arg_descriptor<std::string> arg_scan_for_wallet ( "scan-for-wallet", "");
const command_line::arg_descriptor<std::string> arg_addr_to_compare ( "addr-to-compare", "");
const command_line::arg_descriptor<bool> arg_disable_tor_relay ( "disable-tor-relay", "Do PoS mining", false);
const command_line::arg_descriptor<bool> arg_disable_tor_relay ( "disable-tor-relay", "Disable TOR relay", false);
const command_line::arg_descriptor<unsigned int> arg_set_timeout("set-timeout", "Set timeout for the wallet");
const command_line::arg_descriptor<std::string> arg_voting_config_file("voting-config-file", "Set voting config instead of getting if from daemon", "");
const command_line::arg_descriptor< std::vector<std::string> > arg_command ("command", "");
@ -239,6 +241,26 @@ namespace
}
}
void display_vote_info(tools::wallet2& w)
{
const tools::wallet_public::wallet_vote_config& votes = w.get_current_votes();
if (votes.entries.size())
{
message_writer(epee::log_space::console_color_magenta, true) << "VOTING SET LOADED:";
for (const auto& e : votes.entries)
{
epee::log_space::console_colors color = epee::log_space::console_color_green;
if (e.h_end < w.get_top_block_height())
{
color = epee::log_space::console_color_white;
}
message_writer(color, true) << "\t\t" << e.proposal_id << "\t\t" << (e.vote ? "1" : "0") << "\t\t(" << e.h_start << " - " << e.h_end << ")";
}
}
}
std::string simple_wallet::get_commands_str()
{
std::stringstream ss;
@ -264,7 +286,8 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::start_mining, this, ph::_1), "start_mining <threads_count> - Start mining in daemon");
m_cmd_binder.set_handler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, ph::_1), "Stop mining in daemon");
m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, ph::_1), "Resynchronize transactions and balance");
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, ph::_1), "Show current wallet balance");
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, ph::_1), "Show current wallet balance");
m_cmd_binder.set_handler("show_staking_history", boost::bind(&simple_wallet::show_staking_history, this, ph::_1), "show_staking_history [2] - Show staking transfers, if option provided - number of days for history to display");
m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, ph::_1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability");
m_cmd_binder.set_handler("incoming_counts", boost::bind(&simple_wallet::show_incoming_transfers_counts, this, ph::_1), "incoming_transfers counts");
m_cmd_binder.set_handler("list_recent_transfers", boost::bind(&simple_wallet::list_recent_transfers, this, ph::_1), "list_recent_transfers [offset] [count] - Show recent maximum 1000 transfers, offset default = 0, count default = 100 ");
@ -355,6 +378,29 @@ bool simple_wallet::set_log(const std::vector<std::string> &args)
return true;
}
//----------------------------------------------------------------------------------------------------
void process_wallet_command_line_params(const po::variables_map& vm, tools::wallet2& wal, bool is_server_mode = true)
{
if (command_line::has_arg(vm, arg_disable_tor_relay))
{
wal.set_disable_tor_relay(command_line::get_arg(vm, arg_disable_tor_relay));
message_writer(epee::log_space::console_color_default, true, std::string(), LOG_LEVEL_0) << "Notice: Relaying transactions over TOR disabled with command line parameter";
}
else
{
if (is_server_mode)
{
//disable TOR by default for server-mode, to avoid potential sporadic errors due to TOR connectivity fails
wal.set_disable_tor_relay(true);
}
}
if (command_line::has_arg(vm, arg_set_timeout))
{
wal.set_connectivity_options(command_line::get_arg(vm, arg_set_timeout));
}
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
handle_command_line(vm);
@ -399,7 +445,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
m_do_refresh_after_load = false;
}
bool was_open = false;
if (!m_generate_new.empty())
{
bool r = new_wallet(m_generate_new, pwd_container.password(), false);
@ -450,12 +496,14 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
bool r = open_wallet(m_wallet_file, pwd_container.password());
CHECK_AND_ASSERT_MES(r, false, "could not open account");
was_open = true;
}
if (m_disable_tor)
{
m_wallet->set_disable_tor_relay(true);
message_writer(epee::log_space::console_color_default, true, std::string(), LOG_LEVEL_0) << "Notice: Relaying transactions over TOR disabled with command line parameter";
}
process_wallet_command_line_params(vm, *m_wallet, false);
m_wallet->init(m_daemon_address);
if (was_open && (m_do_refresh_after_load && !m_offline_mode))
refresh(std::vector<std::string>());
return true;
}
@ -480,6 +528,7 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_
m_do_pos_mining = command_line::get_arg(vm, arg_do_pos_mining);
m_restore_wallet = command_line::get_arg(vm, arg_restore_wallet);
m_disable_tor = command_line::get_arg(vm, arg_disable_tor_relay);
m_voting_config_file = command_line::get_arg(vm, arg_voting_config_file);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::try_connect_to_daemon()
@ -500,18 +549,21 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
m_wallet.reset(new tools::wallet2());
m_wallet->callback(this->shared_from_this());
if (!m_voting_config_file.empty())
m_wallet->set_votes_config_path(m_voting_config_file);
m_wallet->set_do_rise_transfer(false);
try
{
m_wallet->generate(epee::string_encoding::utf8_to_wstring(m_wallet_file), password, create_auditable_wallet);
message_writer(epee::log_space::console_color_white, true) << "Generated new " << (create_auditable_wallet ? "AUDITABLE" : "") << " wallet: " << m_wallet->get_account().get_public_address_str();
display_vote_info(*m_wallet);
std::cout << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().view_secret_key) << std::endl << std::flush;
if (m_wallet->is_auditable())
std::cout << "tracking seed: " << std::endl << m_wallet->get_account().get_tracking_seed() << std::endl << std::flush;
if (m_do_not_set_date)
m_wallet->reset_creation_time(0);
}
catch (const std::exception& e)
{
@ -519,9 +571,6 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
return false;
}
m_wallet->init(m_daemon_address);
success_msg_writer() <<
"**********************************************************************\n" <<
"Your wallet has been generated.\n" <<
@ -535,6 +584,9 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
m_wallet.reset(new tools::wallet2());
m_wallet->callback(this->shared_from_this());
if (!m_voting_config_file.empty())
m_wallet->set_votes_config_path(m_voting_config_file);
m_wallet->set_do_rise_transfer(true);
try
{
@ -553,6 +605,7 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
if (m_wallet->is_auditable())
std::cout << "tracking seed: " << std::endl << m_wallet->get_account().get_tracking_seed() << std::endl << std::flush;
}
display_vote_info(*m_wallet);
if (m_do_not_set_date)
m_wallet->reset_creation_time(0);
}
@ -566,7 +619,6 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
fail_msg_writer() << "failed to restore wallet, check your " << (tracking_wallet ? "tracking seed!" : "seed phrase!") << ENDL;
return false;
}
m_wallet->init(m_daemon_address);
success_msg_writer() <<
"**********************************************************************\n" <<
@ -580,11 +632,15 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::open_wallet(const string &wallet_file, const std::string& password)
{
m_wallet_file = wallet_file;
m_wallet.reset(new tools::wallet2());
m_wallet->callback(shared_from_this());
if (!m_voting_config_file.empty())
m_wallet->set_votes_config_path(m_voting_config_file);
while (true)
{
@ -592,6 +648,7 @@ bool simple_wallet::open_wallet(const string &wallet_file, const std::string& pa
{
m_wallet->load(epee::string_encoding::utf8_to_wstring(m_wallet_file), password);
message_writer(epee::log_space::console_color_white, true) << "Opened" << (m_wallet->is_auditable() ? " auditable" : "") << (m_wallet->is_watch_only() ? " watch-only" : "") << " wallet: " << m_wallet->get_account().get_public_address_str();
display_vote_info(*m_wallet);
break;
}
@ -608,12 +665,6 @@ bool simple_wallet::open_wallet(const string &wallet_file, const std::string& pa
}
}
m_wallet->init(m_daemon_address);
if (m_do_refresh_after_load && !m_offline_mode)
refresh(std::vector<std::string>());
success_msg_writer() <<
"**********************************************************************\n" <<
"Use \"help\" command to see the list of available commands.\n" <<
@ -986,15 +1037,13 @@ bool simple_wallet::list_recent_transfers(const std::vector<std::string>& args)
success_msg_writer() << "Unconfirmed transfers: ";
for (auto & wti : unconfirmed)
{
if (!wti.fee)
wti.fee = currency::get_tx_fee(wti.tx);
wti.fee = currency::get_tx_fee(wti.tx);
print_wti(wti);
}
success_msg_writer() << "Recent transfers: ";
for (auto & wti : recent)
{
if (!wti.fee)
wti.fee = currency::get_tx_fee(wti.tx);
wti.fee = currency::get_tx_fee(wti.tx);
print_wti(wti);
}
return true;
@ -1066,6 +1115,70 @@ bool simple_wallet::dump_key_images(const std::vector<std::string>& args)
success_msg_writer() << "Storing text to dump_keyimages.txt....";
file_io_utils::save_string_to_file(log_space::log_singletone::get_default_log_folder() + "/dump_keyimages.txt", ss.str());
success_msg_writer() << "Done....";
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::show_staking_history(const std::vector<std::string>& args)
{
uint64_t n_days = 0;
if (!args.empty())
{
if (!epee::string_tools::get_xtype_from_string(n_days, args[0]))
{
fail_msg_writer() << "Unknown amount of days to list";
return true;
}
}
tools::transfer_container transfers;
m_wallet->get_transfers(transfers);
uint64_t timestamp = 0;
if (n_days)
timestamp = static_cast<uint64_t>(time(nullptr)) - (n_days * 60 * 60 * 24);
uint64_t amount_total_staked = 0;
bool transfers_found = false;
for (auto it = transfers.rbegin(); it != transfers.rend(); it++)
{
const auto& td = *it;
if (timestamp && td.m_ptx_wallet_info->m_block_timestamp < timestamp)
break;
if (!(td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER))
continue;
bool pos_coinbase = false;
is_coinbase(td.m_ptx_wallet_info->m_tx, pos_coinbase);
if (!pos_coinbase)
continue;
if (!transfers_found)
{
message_writer() << " amount \tspent\tglobal index\t tx id";
transfers_found = true;
}
amount_total_staked += td.amount();
message_writer(static_cast<bool>(td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT) ? epee::log_space::console_color_magenta : epee::log_space::console_color_green, false) <<
std::setw(21) << print_money(td.amount()) << '\t' <<
std::setw(3) << (static_cast<bool>(td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT) ? 'T' : 'F') << " \t" <<
std::setw(12) << td.m_global_output_index << '\t' <<
get_transaction_hash(td.m_ptx_wallet_info->m_tx) << "[" << td.m_ptx_wallet_info->m_block_height << "] unlocked: " << (m_wallet->is_transfer_unlocked(td) ? 'T' : 'F');
}
if (!transfers_found)
{
success_msg_writer() << "No staking transactions";
}
else
{
success_msg_writer() << "Total staked: " << print_money(amount_total_staked);
}
return true;
}
//----------------------------------------------------------------------------------------------------
@ -1087,7 +1200,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
}
}
tools::wallet2::transfer_container transfers;
tools::transfer_container transfers;
m_wallet->get_transfers(transfers);
bool transfers_found = false;
@ -1130,7 +1243,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
bool simple_wallet::show_incoming_transfers_counts(const std::vector<std::string>& args)
{
tools::wallet2::transfer_container transfers;
tools::transfer_container transfers;
m_wallet->get_transfers(transfers);
uint64_t spent_count = 0;
@ -1189,7 +1302,7 @@ bool simple_wallet::fix_collisions(const std::vector<std::string> &args)
return true;
}
void print_td_list(const std::list<tools::wallet2::transfer_details>& td)
void print_td_list(const std::list<tools::transfer_details>& td)
{
message_writer() << "entries found: " << td.size();
for (auto& e : td)
@ -1208,7 +1321,7 @@ bool simple_wallet::scan_transfers_for_id(const std::vector<std::string> &args)
fail_msg_writer() << "expected valid tx id";
return true;
}
std::list<tools::wallet2::transfer_details> td;
std::list<tools::transfer_details> td;
m_wallet->scan_for_transaction_entries(id, currency::null_ki, td);
print_td_list(td);
return true;
@ -1222,7 +1335,7 @@ bool simple_wallet::scan_transfers_for_ki(const std::vector<std::string> &args)
fail_msg_writer() << "expected valid key_image";
return true;
}
std::list<tools::wallet2::transfer_details> td;
std::list<tools::transfer_details> td;
m_wallet->scan_for_transaction_entries(currency::null_hash, ki, td);
print_td_list(td);
return true;
@ -1249,7 +1362,7 @@ bool simple_wallet::get_transfer_info(const std::vector<std::string> &args)
}
size_t i = 0;
tools::wallet2::transfer_details td = AUTO_VAL_INIT(td);
tools::transfer_details td = AUTO_VAL_INIT(td);
if (epee::string_tools::get_xtype_from_string(i, args[0]))
{
@ -1294,7 +1407,7 @@ bool simple_wallet::show_payments(const std::vector<std::string> &args)
bool payments_found = false;
for(std::string arg : args)
{
std::list<tools::wallet2::payment_details> payments;
std::list<tools::payment_details> payments;
m_wallet->get_payments(arg, payments);
if (payments.empty())
{
@ -1302,7 +1415,7 @@ bool simple_wallet::show_payments(const std::vector<std::string> &args)
continue;
}
for (const tools::wallet2::payment_details& pd : payments)
for (const tools::payment_details& pd : payments)
{
if (!payments_found)
{
@ -2447,6 +2560,7 @@ bool search_for_wallet_file(const std::wstring &search_here/*, const std::string
}
return false;
}
//----------------------------------------------------------------------------------------------------
#ifdef WIN32
int wmain( int argc, wchar_t* argv_w[ ], wchar_t* envp[ ] )
@ -2495,7 +2609,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_daemon_host);
command_line::add_arg(desc_params, arg_daemon_port);
command_line::add_arg(desc_params, arg_command);
command_line::add_arg(desc_params, arg_log_level);
//command_line::add_arg(desc_params, arg_log_level);
command_line::add_arg(desc_params, arg_dont_refresh);
command_line::add_arg(desc_params, arg_dont_set_date);
command_line::add_arg(desc_params, arg_do_pos_mining);
@ -2507,6 +2621,9 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_scan_for_wallet);
command_line::add_arg(desc_params, arg_addr_to_compare);
command_line::add_arg(desc_params, arg_disable_tor_relay);
command_line::add_arg(desc_params, arg_set_timeout);
command_line::add_arg(desc_params, arg_voting_config_file);
tools::wallet_rpc_server::init_options(desc_params);
@ -2544,7 +2661,7 @@ int main(int argc, char* argv[])
return EXIT_FAILURE;
//set up logging options
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2);
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_0);
boost::filesystem::path log_file_path(command_line::get_arg(vm, command_line::arg_log_file));
if (log_file_path.empty())
log_file_path = log_space::log_singletone::get_default_log_file();
@ -2553,15 +2670,13 @@ int main(int argc, char* argv[])
log_space::log_singletone::add_logger(LOGGER_FILE, log_file_path.filename().string().c_str(), log_dir.c_str(), LOG_LEVEL_4);
message_writer(epee::log_space::console_color_white, true) << CURRENCY_NAME << " wallet v" << PROJECT_VERSION_LONG;
if (command_line::has_arg(vm, arg_log_level))
{
LOG_PRINT_L0("Setting log level = " << command_line::get_arg(vm, arg_log_level));
log_space::get_set_log_detalisation_level(true, command_line::get_arg(vm, arg_log_level));
}
if (command_line::has_arg(vm, command_line::arg_log_level))
{
LOG_PRINT_L0("Setting log level = " << command_line::get_arg(vm, command_line::arg_log_level));
log_space::get_set_log_detalisation_level(true, command_line::get_arg(vm, command_line::arg_log_level));
int old_log_level = log_space::get_set_log_detalisation_level(false);
int new_log_level = command_line::get_arg(vm, command_line::arg_log_level);
log_space::get_set_log_detalisation_level(true, new_log_level);
LOG_PRINT_L0("Log level changed: " << old_log_level << " -> " << new_log_level);
message_writer(epee::log_space::console_color_white, true) << "Log level changed: " << old_log_level << " -> " << new_log_level;
}
@ -2582,7 +2697,7 @@ int main(int argc, char* argv[])
// runs wallet as RPC server
log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2);
sw->set_offline_mode(offline_mode);
LOG_PRINT_L0("Starting wallet RPC server...");
LOG_PRINT_L0("Starting in RPC server mode...");
if (!command_line::has_arg(vm, arg_wallet_file) || command_line::get_arg(vm, arg_wallet_file).empty())
{
@ -2649,7 +2764,9 @@ int main(int argc, char* argv[])
try
{
LOG_PRINT_L0("Initializing wallet...");
process_wallet_command_line_params(vm, wal);
wal.init(daemon_address);
display_vote_info(wal);
if (command_line::get_arg(vm, arg_generate_new_wallet).size() || command_line::get_arg(vm, arg_generate_new_auditable_wallet).size())
return EXIT_FAILURE;
@ -2680,6 +2797,8 @@ int main(int argc, char* argv[])
LOG_PRINT_YELLOW("PoS reward will be sent to another address: " << arg_pos_mining_reward_address_str, LOG_LEVEL_0);
}
}
tools::wallet_rpc_server wrpc(wallet_ptr);
bool r = wrpc.init(vm);
@ -2708,7 +2827,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, arg_do_pos_mining))
{
// PoS mining can be turned on only in RPC server mode, please provide --rpc-bind-port to make this
fail_msg_writer() << "PoS mining can be turned on only in RPC server mode, please provide --rpc-bind-port=PORT_NO to enable staking in simplewallet";
fail_msg_writer() << "PoS mining can only be started in RPC server mode, please use command-line option --rpc-bind-port=<PORT_NUM> along with --do-pos-mining to enable staking";
return EXIT_FAILURE;
}

View file

@ -59,6 +59,7 @@ namespace currency
bool dump_trunsfers(const std::vector<std::string>& args);
bool dump_key_images(const std::vector<std::string>& args);
bool show_incoming_transfers(const std::vector<std::string> &args);
bool show_staking_history(const std::vector<std::string>& args);
bool show_incoming_transfers_counts(const std::vector<std::string> &args);
bool list_outputs(const std::vector<std::string> &args);
bool show_payments(const std::vector<std::string> &args);
@ -187,6 +188,7 @@ namespace currency
bool m_offline_mode;
bool m_disable_tor;
std::string m_restore_wallet;
std::string m_voting_config_file;
epee::console_handlers_binder m_cmd_binder;

View file

@ -8,6 +8,6 @@
#define PROJECT_REVISION "0"
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
#define PROJECT_VERSION_BUILD_NO 237
#define PROJECT_VERSION_BUILD_NO 244
#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

@ -184,11 +184,10 @@ namespace tools
// m_plast_daemon_is_disconnected = plast_daemon_is_disconnected ? plast_daemon_is_disconnected : &m_last_daemon_is_disconnected_stub;
// }
//------------------------------------------------------------------------------------------------------------------------------
bool default_http_core_proxy::set_connectivity(unsigned int connection_timeout, size_t repeats_count)
void default_http_core_proxy::set_connectivity(unsigned int connection_timeout, size_t repeats_count)
{
m_connection_timeout = connection_timeout;
m_attempts_count = repeats_count;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
default_http_core_proxy::default_http_core_proxy(): //:m_plast_daemon_is_disconnected(&m_last_daemon_is_disconnected_stub),

View file

@ -28,7 +28,7 @@ namespace tools
bool set_connection_addr(const std::string& url) override;
bool set_connectivity(unsigned int connection_timeout, size_t repeats_count);
void set_connectivity(unsigned int connection_timeout, size_t repeats_count);
bool call_COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES(const currency::COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& rqt, currency::COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& rsp) override;
bool call_COMMAND_RPC_GET_BLOCKS_FAST(const currency::COMMAND_RPC_GET_BLOCKS_FAST::request& rqt, currency::COMMAND_RPC_GET_BLOCKS_FAST::response& rsp) override;
bool call_COMMAND_RPC_GET_BLOCKS_DIRECT(const currency::COMMAND_RPC_GET_BLOCKS_DIRECT::request& rqt, currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& rsp) override;
@ -56,7 +56,7 @@ namespace tools
bool check_connection() override;
bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id) override;
void set_plast_daemon_is_disconnected(std::atomic<bool> *plast_daemon_is_disconnected);
void set_plast_daemon_is_disconnected(std::atomic<bool> *plast_daemon_is_disconnected);
default_http_core_proxy();
private:

View file

@ -63,6 +63,7 @@ namespace tools
std::shared_ptr<const proxy_diagnostic_info> get_proxy_diagnostic_info() const { return m_pdiganostic_info; }
std::shared_ptr<proxy_diagnostic_info> get_editable_proxy_diagnostic_info() { return m_pdiganostic_info; }
virtual bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id){ return false; }
virtual void set_connectivity(unsigned int connection_timeout, size_t repeats_count) {}
protected:
std::shared_ptr<proxy_diagnostic_info> m_pdiganostic_info;
};

View file

@ -23,6 +23,7 @@ using namespace epee;
#include "currency_core/bc_offers_service_basic.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "misc_language.h"
#include "common/util.h"
#include "common/boost_serialization_helper.h"
#include "crypto/crypto.h"
@ -66,24 +67,21 @@ namespace tools
, m_wcallback(new i_wallet2_callback()) //stub
, m_core_proxy(new default_http_core_proxy())
, m_upper_transaction_size_limit(0)
, m_height_of_start_sync(0)
, m_last_sync_percent(0)
, m_fake_outputs_count(0)
, m_do_rise_transfer(false)
, m_log_prefix("???")
, m_watch_only(false)
, m_last_pow_block_h(0)
, m_minimum_height(WALLET_MINIMUM_HEIGHT_UNSET_CONST)
, m_required_decoys_count(CURRENCY_DEFAULT_DECOY_SET_SIZE)
, m_min_utxo_count_for_defragmentation_tx(WALLET_MIN_UTXO_COUNT_FOR_DEFRAGMENTATION_TX)
, m_max_utxo_count_for_defragmentation_tx(WALLET_MAX_UTXO_COUNT_FOR_DEFRAGMENTATION_TX)
, m_decoys_count_for_defragmentation_tx(WALLET_DEFAULT_DECOYS_COUNT_FOR_DEFRAGMENTATION_TX)
, m_current_wallet_file_size(0)
, m_use_deffered_global_outputs(false)
#ifdef DISABLE_TOR
, m_disable_tor_relay(true)
#else
, m_disable_tor_relay(false)
#endif
, m_votes_config_path(tools::get_default_data_dir() + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME)
{
m_core_runtime_config = currency::get_default_core_runtime_config();
}
@ -137,45 +135,25 @@ std::string wallet2::transfer_flags_to_str(uint32_t flags)
result[4] = 'c';
return result;
}
//----------------------------------------------------------------------------------------------------
std::string wallet2::transform_tx_to_str(const currency::transaction& tx)
{
return currency::obj_to_json_str(tx);
}
//----------------------------------------------------------------------------------------------------
currency::transaction wallet2::transform_str_to_tx(const std::string& tx_str)
{
THROW_IF_TRUE_WALLET_INT_ERR_EX_NO_HANDLER(false, "transform_str_to_tx shoruld never be called");
return currency::transaction();
}
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::transfer_details_base_to_amount(const transfer_details_base& tdb)
{
return tdb.amount();
}
//----------------------------------------------------------------------------------------------------
std::string wallet2::transfer_details_base_to_tx_hash(const transfer_details_base& tdb)
{
return epee::string_tools::pod_to_hex(currency::get_transaction_hash(tdb.m_ptx_wallet_info->m_tx));
}
//----------------------------------------------------------------------------------------------------
const wallet2::transaction_wallet_info& wallet2::transform_ptr_to_value(const std::shared_ptr<wallet2::transaction_wallet_info>& a)
{
return *a;
}
//----------------------------------------------------------------------------------------------------
std::shared_ptr<wallet2::transaction_wallet_info> wallet2::transform_value_to_ptr(const wallet2::transaction_wallet_info& d)
{
THROW_IF_TRUE_WALLET_INT_ERR_EX_NO_HANDLER(false, "transform_value_to_ptr shoruld never be called");
return std::shared_ptr<wallet2::transaction_wallet_info>();
}
//----------------------------------------------------------------------------------------------------
void wallet2::init(const std::string& daemon_address)
{
m_miner_text_info = PROJECT_VERSION_LONG;
//m_miner_text_info = PROJECT_VERSION_LONG;
m_core_proxy->set_connection_addr(daemon_address);
m_core_proxy->check_connection();
std::stringstream ss;
const tools::wallet_public::wallet_vote_config& votes = this->get_current_votes();
if (votes.entries.size())
{
ss << "VOTING SET LOADED:";
for (const auto& e : votes.entries)
{
ss << "\t\t" << e.proposal_id << "\t\t" << (e.vote ? "1" : "0") << "\t\t(" << e.h_start << " - " << e.h_end << ")";
}
}
WLT_LOG_L0(ss.str());
}
//----------------------------------------------------------------------------------------------------
bool wallet2::set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy)
@ -1248,12 +1226,12 @@ void wallet2::change_contract_state(wallet_public::escrow_contract_details_basic
contract.state = new_state;
}
//-----------------------------------------------------------------------------------------------------
void from_outs_to_received_items(const std::vector<currency::wallet_out_info>& outs, std::vector<tools::wallet2::payment_details_subtransfer>& received, const currency::transaction& tx)
void from_outs_to_received_items(const std::vector<currency::wallet_out_info>& outs, std::vector<tools::payment_details_subtransfer>& received, const currency::transaction& tx)
{
for (const auto& item : outs)
{
if(!out_is_multisig(tx.vout[item.index]))
received.push_back(tools::wallet2::payment_details_subtransfer{ item.asset_id, item.amount});
received.push_back(tools::payment_details_subtransfer{ item.asset_id, item.amount});
}
}
//-----------------------------------------------------------------------------------------------------
@ -1772,7 +1750,7 @@ void wallet2::process_new_blockchain_entry(const currency::block& b, const curre
//optimization: seeking only for blocks that are not older then the wallet creation time plus 1 day. 1 day is for possible user incorrect time setup
const std::vector<uint64_t>* pglobal_index = nullptr;
if (b.timestamp + 60 * 60 * 24 > m_account.get_createtime())
if (get_block_height(b) > get_wallet_minimum_height()) // b.timestamp + 60 * 60 * 24 > m_account.get_createtime())
{
pglobal_index = nullptr;
if (bche.coinbase_ptr.get())
@ -2820,29 +2798,9 @@ bool wallet2::clear()
//----------------------------------------------------------------------------------------------------
bool wallet2::reset_all()
{
//m_blockchain.clear();
m_chain.clear();
m_transfers.clear();
m_amount_gindex_to_transfer_id.clear();
m_key_images.clear();
// m_pending_key_images is not cleared intentionally
m_unconfirmed_in_transfers.clear();
m_unconfirmed_txs.clear();
m_unconfirmed_multisig_transfers.clear();
// m_tx_keys is not cleared intentionally, considered to be safe
m_multisig_transfers.clear();
m_payments.clear();
m_transfer_history.clear();
//m_account = AUTO_VAL_INIT(m_account);
//m_local_bc_size = 1; //including genesis
m_last_bc_timestamp = 0;
m_height_of_start_sync = 0;
m_last_sync_percent = 0;
m_last_pow_block_h = 0;
m_current_wallet_file_size = 0;
m_custom_assets.clear();
m_own_asset_descriptors.clear();
//static_cast<wallet2_base_state&>(*this) = wallet2_base_state{};
static_cast<wallet2_base_state&>(*this).~wallet2_base_state();
new (static_cast<wallet2_base_state*>(this)) wallet2_base_state();
return true;
}
//----------------------------------------------------------------------------------------------------
@ -3054,6 +3012,19 @@ bool wallet2::check_connection()
return m_core_proxy->check_connection();
}
//----------------------------------------------------------------------------------------------------
void wallet2::set_votes_config_path(const std::string& path_to_config_file/* = tools::get_default_data_dir() + "\voting_config.json"*/)
{
m_votes_config_path = path_to_config_file;
}
//----------------------------------------------------------------------------------------------------
void wallet2::load_votes_config()
{
if (boost::filesystem::exists(m_votes_config_path))
{
epee::serialization::load_t_from_json_file(m_votes_config, m_votes_config_path);
}
}
//----------------------------------------------------------------------------------------------------
void wallet2::load(const std::wstring& wallet_, const std::string& password)
{
clear();
@ -3092,7 +3063,7 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
{
// old WALLET_FILE_BINARY_HEADER_VERSION version means no encryption
need_to_resync = !tools::portable_unserialize_obj_from_stream(*this, data_file);
WLT_LOG_L0("Detected format: WALLET_FILE_BINARY_HEADER_VERSION_INITAL(need_to_resync=" << need_to_resync << ")");
WLT_LOG_L1("Detected format: WALLET_FILE_BINARY_HEADER_VERSION_INITAL (need_to_resync=" << need_to_resync << ")");
}
else if (wbh.m_ver == WALLET_FILE_BINARY_HEADER_VERSION_2)
{
@ -3101,7 +3072,7 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
in.push(decrypt_filter);
in.push(data_file);
need_to_resync = !tools::portable_unserialize_obj_from_stream(*this, in);
WLT_LOG_L0("Detected format: WALLET_FILE_BINARY_HEADER_VERSION_2(need_to_resync=" << need_to_resync << ")");
WLT_LOG_L1("Detected format: WALLET_FILE_BINARY_HEADER_VERSION_2 (need_to_resync=" << need_to_resync << ")");
}
else
{
@ -3122,10 +3093,11 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
<< ", file_size=" << m_current_wallet_file_size
<< ", blockchain_size: " << m_chain.get_blockchain_current_size()
);
WLT_LOG_L0("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
WLT_LOG_L1("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
load_votes_config();
WLT_LOG_L0("(after loading: pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")");
WLT_LOG_L1("(after loading: pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")");
if (need_to_resync)
{
@ -3197,7 +3169,7 @@ void wallet2::store(const std::wstring& path_to_save, const std::string& passwor
boost::uintmax_t tmp_file_size = boost::filesystem::file_size(tmp_file_path);
WLT_LOG_L0("Stored successfully to temporary file " << tmp_file_path.string() << ", file size=" << tmp_file_size);
WLT_LOG_L0("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
WLT_LOG_L1("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
// for the sake of safety perform a double-renaming: wallet file -> old tmp, new tmp -> wallet file, remove old tmp
@ -3547,8 +3519,6 @@ bool wallet2::load_whitelisted_tokens() const
if(!m_use_assets_whitelisting)
return true;
m_whitelisted_assets.clear();
std::string body;
wallet_public::assets_whitelist aw = AUTO_VAL_INIT(aw);
@ -3564,14 +3534,17 @@ bool wallet2::load_whitelisted_tokens() const
//----------------------------------------------------------------------------------------------------
bool wallet2::load_whitelisted_tokens_if_not_loaded() const
{
if (m_whitelisted_assets.size())
if (m_whitelist_updated)
{
return true;
}
return load_whitelisted_tokens();
if (!load_whitelisted_tokens())
return false;
m_whitelist_updated = true;
return true;
}
//----------------------------------------------------------------------------------------------------
void wallet2::get_transfers(wallet2::transfer_container& incoming_transfers) const
void wallet2::get_transfers(transfer_container& incoming_transfers) const
{
incoming_transfers = m_transfers;
}
@ -3673,7 +3646,7 @@ std::string wallet2::get_balance_str() const
return ss.str();
}
//----------------------------------------------------------------------------------------------------
void wallet2::get_payments(const std::string& payment_id, std::list<wallet2::payment_details>& payments, uint64_t min_height) const
void wallet2::get_payments(const std::string& payment_id, std::list<payment_details>& payments, uint64_t min_height) const
{
auto range = m_payments.equal_range(payment_id);
std::for_each(range.first, range.second, [&payments, &min_height](const payment_container::value_type& x)
@ -3999,7 +3972,11 @@ void wallet2::wti_to_json_line(std::ostream& ss, const wallet_public::wallet_tra
ss << epee::serialization::store_t_to_json(wti, 4) << ",";
};
//----------------------------------------------------------------------------------------------------
void wallet2::set_connectivity_options(unsigned int timeout)
{
m_core_proxy->set_connectivity(timeout, WALLET_RCP_COUNT_ATTEMNTS);
}
//----------------------------------------------------------------------------------------------------
void wallet2::export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions)
{
@ -4171,26 +4148,100 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
txin_to_key& stake_input = boost::get<txin_to_key>(b.miner_tx.vin[1]);
const txout_to_key& stake_out_target = boost::get<txout_to_key>(stake_out.target);
// fill stake input
// partially fill stake input
stake_input.k_image = pe.keyimage;
stake_input.amount = pe.amount;
stake_input.key_offsets.push_back(pe.g_index);
// get decoys outputs and construct miner tx
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response decoys_resp = AUTO_VAL_INIT(decoys_resp);
std::vector<const crypto::public_key*> ring;
uint64_t secret_index = 0; // index of the real stake output
if (m_required_decoys_count > 0 && !is_auditable())
{
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request decoys_req = AUTO_VAL_INIT(decoys_req);
decoys_req.height_upper_limit = 0; // TODO @#@# maybe use m_last_pow_block_h like Zarcanum?
decoys_req.use_forced_mix_outs = false;
decoys_req.decoys_count = m_required_decoys_count + 1; // one more to be able to skip a decoy in case it hits the real output
decoys_req.amounts.push_back(pe.amount); // request one batch of decoys
r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(decoys_req, decoys_resp);
// TODO @#@# do we need these exceptions?
THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs.bin");
THROW_IF_FALSE_WALLET_EX(decoys_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs.bin");
THROW_IF_FALSE_WALLET_EX(decoys_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, decoys_resp.status);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(decoys_resp.outs.size() == 1, "got wrong number of decoys batches: " << decoys_resp.outs.size());
// we expect that less decoys can be returned than requested, we will use them all anyway
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(decoys_resp.outs[0].outs.size() <= m_required_decoys_count + 1, "for PoS stake tx got greater decoys to mix than requested: " << decoys_resp.outs[0].outs.size() << " < " << m_required_decoys_count + 1);
auto& ring_candidates = decoys_resp.outs[0].outs;
ring_candidates.emplace_front(td.m_global_output_index, stake_out_target.key);
std::unordered_set<uint64_t> used_gindices;
size_t good_outs_count = 0;
for(auto it = ring_candidates.begin(); it != ring_candidates.end(); )
{
if (used_gindices.count(it->global_amount_index) != 0)
{
it = ring_candidates.erase(it);
continue;
}
used_gindices.insert(it->global_amount_index);
if (++good_outs_count == m_required_decoys_count + 1)
{
ring_candidates.erase(++it, ring_candidates.end());
break;
}
++it;
}
// won't assert that ring_candidates.size() == m_required_decoys_count + 1 here as we will use all the decoys anyway
if (ring_candidates.size() < m_required_decoys_count + 1)
LOG_PRINT_YELLOW("PoS: using " << ring_candidates.size() - 1 << " decoys for mining tx, while " << m_required_decoys_count << " are required", LOG_LEVEL_1);
ring_candidates.sort([](auto& l, auto& r){ return l.global_amount_index < r.global_amount_index; }); // sort them now (note absolute_sorted_output_offsets_to_relative_in_place() below)
uint64_t i = 0;
for(auto& el : ring_candidates)
{
uint64_t gindex = el.global_amount_index;
if (gindex == td.m_global_output_index)
secret_index = i;
++i;
ring.emplace_back(&el.stealth_address);
stake_input.key_offsets.push_back(el.global_amount_index);
}
r = absolute_sorted_output_offsets_to_relative_in_place(stake_input.key_offsets);
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(r, "absolute_sorted_output_offsets_to_relative_in_place failed");
}
else
{
// no decoys, the ring consist of one element -- the real stake output
ring.emplace_back(&stake_out_target.key);
stake_input.key_offsets.push_back(td.m_global_output_index);
}
// sign block actually in coinbase transaction
crypto::hash block_hash = currency::get_block_hash(b);
// get stake output pub key (stealth address) for ring signature generation
std::vector<const crypto::public_key*> keys_ptrs;
keys_ptrs.push_back(&stake_out_target.key);
// generate sring signature
sig.s.resize(1);
crypto::generate_ring_signature(block_hash, stake_input.k_image, keys_ptrs, secret_x, 0, sig.s.data());
sig.s.resize(ring.size());
crypto::generate_ring_signature(block_hash, stake_input.k_image, ring, secret_x, secret_index, sig.s.data());
WLT_LOG_L4("GENERATED RING SIGNATURE for PoS block coinbase: block_id " << block_hash
<< "txin.k_image" << stake_input.k_image
<< "key_ptr:" << *keys_ptrs[0]
<< "signature:" << sig.s);
if (epee::log_space::get_set_log_detalisation_level() >= LOG_LEVEL_4)
{
std::stringstream ss;
ss << "GENERATED RING SIGNATURE for PoS block coinbase:" << ENDL <<
" block hash: " << block_hash << ENDL <<
" key image: " << stake_input.k_image << ENDL <<
" ring:" << ENDL;
for(auto el: ring)
ss << " " << *el << ENDL;
ss << " signature:" << ENDL;
for(auto el: sig.s)
ss << " " << el << ENDL;
WLT_LOG_L4(ss.str());
}
return true;
}
@ -4215,7 +4266,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
// get decoys outputs and construct miner tx
static size_t required_decoys_count = 4; // TODO @#@# set them somewhere else
static bool use_only_forced_to_mix = false; // TODO @#@# set them somewhere else
if (required_decoys_count > 0)
if (required_decoys_count > 0 && !is_auditable())
{
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request decoys_req = AUTO_VAL_INIT(decoys_req);
decoys_req.height_upper_limit = m_last_pow_block_h; // request decoys to be either older than, or the same age as stake output's height
@ -4366,7 +4417,7 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
{
TIME_MEASURE_START_MS(mining_duration_ms);
mining_context ctx = AUTO_VAL_INIT(ctx);
WLT_LOG_L1("Starting PoS mining iteration");
WLT_LOG_L2("Starting PoS mining iteration");
fill_mining_context(ctx);
if (!ctx.is_pos_allowed)
@ -4438,7 +4489,31 @@ bool wallet2::build_minted_block(const mining_context& cxt)
{
return build_minted_block(cxt, m_account.get_public_address());
}
//------------------------------------------------------------------
std::string wallet2::get_extra_text_for_block(uint64_t new_block_expected_height)
{
size_t entries_voted = 0;
std::string extra_text = "{";
for (const auto& e : m_votes_config.entries)
{
if (e.h_start <= new_block_expected_height && e.h_end >= new_block_expected_height)
{
//do vote for/against this
if (entries_voted != 0)
extra_text += ",";
extra_text += "\"";
extra_text += e.proposal_id;
extra_text += "\":";
extra_text += e.vote ? "1" : "0";
entries_voted++;
}
}
extra_text += "}";
if (!entries_voted)
extra_text = "";
return extra_text;
}
//------------------------------------------------------------------
bool wallet2::build_minted_block(const mining_context& cxt, const currency::account_public_address& miner_address)
{
//found a block, construct it, sign and push to daemon
@ -4452,7 +4527,7 @@ bool wallet2::build_minted_block(const mining_context& cxt, const currency::acco
tmpl_req.wallet_address = get_account_address_as_str(miner_address);
tmpl_req.stakeholder_address = get_account_address_as_str(m_account.get_public_address());
tmpl_req.pos_block = true;
tmpl_req.extra_text = m_miner_text_info;
tmpl_req.extra_text = get_extra_text_for_block(m_chain.get_top_block_height());
tmpl_req.pe = AUTO_VAL_INIT(tmpl_req.pe);
tmpl_req.pe.amount = td.amount();
@ -4912,10 +4987,10 @@ std::string get_random_rext(size_t len)
// local_transfers_struct - structure to avoid copying the whole m_transfers
struct local_transfers_struct
{
local_transfers_struct(wallet2::transfer_container& tf) :l_transfers_ref(tf)
local_transfers_struct(transfer_container& tf) :l_transfers_ref(tf)
{}
wallet2::transfer_container& l_transfers_ref;
transfer_container& l_transfers_ref;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(l_transfers_ref)
END_KV_SERIALIZE_MAP()

View file

@ -45,18 +45,11 @@
#include "tor-connect/torlib/tor_lib_iface.h"
#include "currency_core/pos_mining.h"
#include "view_iface.h"
#include "wallet2_base.h"
#define WALLET_DEFAULT_TX_SPENDABLE_AGE 10
#define WALLET_POS_MINT_CHECK_HEIGHT_INTERVAL 1
#define WALLET_TRANSFER_DETAIL_FLAG_SPENT uint32_t(1 << 0)
#define WALLET_TRANSFER_DETAIL_FLAG_BLOCKED uint32_t(1 << 1)
#define WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION uint32_t(1 << 2)
#define WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER uint32_t(1 << 3)
#define WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION uint32_t(1 << 4) // transfer is reserved for cold-signing (unsigned tx was created and passed for signing)
#define WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM uint32_t(1 << 5) // for htlc keeps info if this htlc belong as redeem or as refund
const uint64_t WALLET_MINIMUM_HEIGHT_UNSET_CONST = std::numeric_limits<uint64_t>::max();
@ -84,9 +77,6 @@ const uint64_t WALLET_MINIMUM_HEIGHT_UNSET_CONST = std::numeric_limits<uint64_t>
#define WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, "[W:" << m_log_prefix << "] " << msg)
#define WLT_THROW_IF_FALSE_WALLET_EX_MES(cond, exception_t, msg, ...) THROW_IF_FALSE_WALLET_EX_MES(cond, exception_t, "[W:" << m_log_prefix << "] " << msg, ## __VA_ARGS__)
class test_generator;
namespace tools
@ -124,391 +114,121 @@ namespace tools
virtual bool on_mw_select_wallet(uint64_t wallet_id) { return true; }
};
struct tx_dust_policy
{
uint64_t dust_threshold = 0;
bool add_to_fee = false;
currency::account_public_address addr_for_dust;
tx_dust_policy(uint64_t a_dust_threshold = DEFAULT_DUST_THRESHOLD, bool an_add_to_fee = true, currency::account_public_address an_addr_for_dust = currency::account_public_address())
: dust_threshold(a_dust_threshold)
, add_to_fee(an_add_to_fee)
, addr_for_dust(an_addr_for_dust)
{
}
BEGIN_SERIALIZE_OBJECT()
FIELD(dust_threshold)
FIELD(add_to_fee)
FIELD(addr_for_dust)
END_SERIALIZE()
};
class test_generator;
#pragma pack(push, 1)
struct out_key_to_ki
/*
This structure aggregates all variables that hold current wallet synchronization state and could be reset
*/
struct wallet2_base_state
{
crypto::public_key out_key;
crypto::key_image key_image;
};
#pragma pack(pop)
wallet_chain_shortener m_chain;
uint64_t m_minimum_height = WALLET_MINIMUM_HEIGHT_UNSET_CONST;
amount_gindex_to_transfer_id_container m_amount_gindex_to_transfer_id;
transfer_container m_transfers;
multisig_transfer_container m_multisig_transfers;
payment_container m_payments;
std::unordered_map<crypto::key_image, size_t> m_key_images;
std::vector<wallet_public::wallet_transfer_info> m_transfer_history;
std::unordered_map<crypto::hash, currency::transaction> m_unconfirmed_in_transfers;
std::unordered_map<crypto::hash, tools::wallet_public::wallet_transfer_info> m_unconfirmed_txs;
std::unordered_set<crypto::hash> m_unconfirmed_multisig_transfers;
std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys;
std::unordered_map<crypto::public_key, wallet_own_asset_context> m_own_asset_descriptors;
std::unordered_map<crypto::public_key, currency::asset_descriptor_base> m_custom_assets; //assets that manually added by user
mutable std::unordered_map<crypto::public_key, currency::asset_descriptor_base> m_whitelisted_assets; //assets that whitelisted
escrow_contracts_container m_contracts;
std::multimap<uint64_t, htlc_expiration_trigger> m_htlcs; //map [expired_if_more_then] -> height of expiration
amount_gindex_to_transfer_id_container m_active_htlcs; // map [amount; gindex] -> transfer index
std::unordered_map<crypto::hash, uint64_t> m_active_htlcs_txid; // map [txid] -> transfer index, limitation: 1 transactiom -> 1 htlc
std::list<expiration_entry_info> m_money_expirations;
std::unordered_map<crypto::public_key, crypto::key_image> m_pending_key_images; // (out_pk -> ki) pairs of change outputs to be added in watch-only wallet without spend sec key
uint64_t m_last_pow_block_h = 0;
std::list<std::pair<uint64_t, wallet_event_t>> m_rollback_events;
//variables that not being serialized
std::atomic<uint64_t> m_last_bc_timestamp = 0;
uint64_t m_height_of_start_sync = 0;
std::atomic<uint64_t> m_last_sync_percent = 0;
mutable uint64_t m_current_wallet_file_size = 0;
typedef tools::pod_array_file_container<out_key_to_ki> pending_ki_file_container_t;
namespace detail
{
//----------------------------------------------------------------------------------------------------
inline void digit_split_strategy(const std::vector<currency::tx_destination_entry>& dsts,
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
//===============================================================
template <class t_archive>
inline void serialize(t_archive &a, const unsigned int ver)
{
splitted_dsts.clear();
dust = 0;
for(auto& de : dsts)
if (t_archive::is_saving::value)
{
if (de.addr.size() > 1)
{
//for multisig we don't split
splitted_dsts.push_back(de);
}
else if (de.htlc_options.expiration != 0)
{
//for htlc we don't do split
splitted_dsts.push_back(de);
}
else
{
currency::decompose_amount_into_digits(de.amount, dust_threshold,
[&](uint64_t chunk) { splitted_dsts.push_back(currency::tx_destination_entry(chunk, de.addr, de.asset_id)); },
[&](uint64_t a_dust) { splitted_dsts.push_back(currency::tx_destination_entry(a_dust, de.addr, de.asset_id)); }, max_output_allowed);
}
LOG_PRINT_MAGENTA("Serializing file with ver: " << ver, LOG_LEVEL_0);
}
if (change_dst.amount > 0)
// do not load wallet if data version is greather than the code version
if (ver > WALLET_FILE_SERIALIZATION_VERSION)
{
if (change_dst.addr.size() > 1)
LOG_PRINT_MAGENTA("Wallet file truncated due to WALLET_FILE_SERIALIZATION_VERSION is more then curren build", LOG_LEVEL_0);
return;
}
if (ver < WALLET_FILE_LAST_SUPPORTED_VERSION)
{
LOG_PRINT_MAGENTA("Wallet file truncated due to ver(" << ver << ") is less then WALLET_FILE_LAST_SUPPORTED_VERSION", LOG_LEVEL_0);
return;
}
if (t_archive::is_saving::value)
{
uint64_t formation_ver = CURRENCY_FORMATION_VERSION;
a & formation_ver;
}
else
{
uint64_t formation_ver = 0;
a & formation_ver;
if (formation_ver != CURRENCY_FORMATION_VERSION)
{
//for multisig we don't split
splitted_dsts.push_back(change_dst);
}
else
{
currency::decompose_amount_into_digits(change_dst.amount, dust_threshold,
[&](uint64_t chunk) { splitted_dsts.push_back(currency::tx_destination_entry(chunk, change_dst.addr)); },
[&](uint64_t a_dust) { dust = a_dust; }, max_output_allowed);
LOG_PRINT_MAGENTA("Wallet file truncated due to mismatch CURRENCY_FORMATION_VERSION", LOG_LEVEL_0);
return;
}
}
//convert from old version
a & m_chain;
a & m_minimum_height;
a & m_amount_gindex_to_transfer_id;
a & m_transfers;
a & m_multisig_transfers;
a & m_key_images;
a & m_unconfirmed_txs;
a & m_unconfirmed_multisig_transfers;
a & m_payments;
a & m_transfer_history;
a & m_unconfirmed_in_transfers;
a & m_contracts;
a & m_money_expirations;
a & m_pending_key_images;
a & m_tx_keys;
a & m_last_pow_block_h;
a & m_htlcs;
a & m_active_htlcs;
a & m_active_htlcs_txid;
a & m_own_asset_descriptors;
a & m_custom_assets;
a & m_rollback_events;
a & m_whitelisted_assets;
}
//----------------------------------------------------------------------------------------------------
inline void null_split_strategy(const std::vector<currency::tx_destination_entry>& dsts,
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
{
splitted_dsts = dsts;
dust = 0;
uint64_t change = change_dst.amount;
if (0 < dust_threshold)
{
for (uint64_t order = 10; order <= 10 * dust_threshold; order *= 10)
{
uint64_t dust_candidate = change_dst.amount % order;
uint64_t change_candidate = (change_dst.amount / order) * order;
if (dust_candidate <= dust_threshold)
{
dust = dust_candidate;
change = change_candidate;
}
else
{
break;
}
}
}
if (0 != change)
{
splitted_dsts.push_back(currency::tx_destination_entry(change, change_dst.addr));
}
}
//----------------------------------------------------------------------------------------------------
inline void void_split_strategy(const std::vector<currency::tx_destination_entry>& dsts,
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
{
splitted_dsts.insert(splitted_dsts.end(), dsts.begin(), dsts.end());
if (change_dst.amount > 0)
splitted_dsts.push_back(change_dst);
}
//----------------------------------------------------------------------------------------------------
enum split_strategy_id_t { ssi_none = 0, ssi_digit = 1, ssi_null = 2, ssi_void = 3 };
//----------------------------------------------------------------------------------------------------
inline bool apply_split_strategy_by_id(split_strategy_id_t id, const std::vector<currency::tx_destination_entry>& dsts,
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
{
switch (id)
{
case ssi_digit:
digit_split_strategy(dsts, change_dst, dust_threshold, splitted_dsts, dust, max_output_allowed);
return true;
case ssi_null:
null_split_strategy(dsts, change_dst, dust_threshold, splitted_dsts, dust, max_output_allowed);
return true;
case ssi_void:
void_split_strategy(dsts, change_dst, dust_threshold, splitted_dsts, dust, max_output_allowed);
return true;
default:
return false;
}
}
} // namespace detail
struct construct_tx_param
{
// preparing data for tx
std::vector<currency::tx_destination_entry> dsts;
size_t fake_outputs_count = 0;
uint64_t fee = 0;
tx_dust_policy dust_policy;
crypto::hash multisig_id = currency::null_hash;
uint8_t flags = 0;
uint8_t split_strategy_id = 0;
bool mark_tx_as_complete = false;
crypto::hash htlc_tx_id;
std::string htlc_origin;
// constructing tx
uint64_t unlock_time = 0;
std::vector<currency::extra_v> extra;
std::vector<currency::attachment_v> attachments;
currency::account_public_address crypt_address;
uint8_t tx_outs_attr = 0;
bool shuffle = false;
bool create_utxo_defragmentation_tx = false;
bool need_at_least_1_zc = false;
crypto::secret_key asset_deploy_control_key = currency::null_skey;
};
struct mode_separate_context
{
currency::transaction tx_for_mode_separate;
view::ionic_swap_proposal_info proposal_info;
bool escrow = false;
};
struct selection_for_amount
{
uint64_t needed_amount = 0;
uint64_t found_amount = 0;
//std::vector<uint64_t> selected_indicies;
};
typedef std::unordered_map<crypto::public_key, selection_for_amount> assets_selection_context;
class wallet2: public tools::tor::t_transport_state_notifier, public boost::static_visitor<void>
class wallet2: public tools::tor::t_transport_state_notifier, public boost::static_visitor<void>, public wallet2_base_state
{
wallet2(const wallet2&) = delete;
public:
wallet2();
static std::string transfer_flags_to_str(uint32_t flags);
static std::string transform_tx_to_str(const currency::transaction& tx);
static currency::transaction transform_str_to_tx(const std::string& tx_str);
//general rollback mechanism
struct asset_register_event
{
crypto::public_key asset_id = currency::null_pkey;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_id)
END_BOOST_SERIALIZATION()
};
struct wallet_own_asset_context
{
currency::asset_descriptor_base asset_descriptor;
crypto::secret_key control_key;
//uint64_t height = 0;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_descriptor)
BOOST_SERIALIZE(control_key)
//BOOST_SERIALIZE(height)
END_BOOST_SERIALIZATION()
};
struct asset_update_event
{
crypto::public_key asset_id = currency::null_pkey;
wallet_own_asset_context own_context;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_id)
BOOST_SERIALIZE(own_context)
END_BOOST_SERIALIZATION()
};
struct asset_unown_event
{
crypto::public_key asset_id = currency::null_pkey;
wallet_own_asset_context own_context;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_id)
BOOST_SERIALIZE(own_context)
END_BOOST_SERIALIZATION()
};
typedef boost::variant<asset_register_event, asset_update_event, asset_unown_event> wallet_event_t;
struct transaction_wallet_info
{
uint64_t m_block_height = 0;
uint64_t m_block_timestamp = 0;
currency::transaction m_tx;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(m_block_height)
KV_SERIALIZE(m_block_timestamp)
KV_SERIALIZE_CUSTOM(m_tx, std::string, tools::wallet2::transform_tx_to_str, tools::wallet2::transform_str_to_tx)
END_KV_SERIALIZE_MAP()
};
static const transaction_wallet_info& transform_ptr_to_value(const std::shared_ptr<transaction_wallet_info>& a);
static std::shared_ptr<transaction_wallet_info> transform_value_to_ptr(const transaction_wallet_info& d);
struct transfer_details_base;
static uint64_t transfer_details_base_to_amount(const transfer_details_base& tdb);
static std::string transfer_details_base_to_tx_hash(const transfer_details_base& tdb);
struct transfer_details_base
{
struct ZC_out_info // TODO: @#@# consider using wallet_out_info instead
{
ZC_out_info() = default;
ZC_out_info(const crypto::scalar_t& amount_blinding_mask, const crypto::scalar_t& asset_id_blinding_mask, const crypto::public_key& asset_id)
: amount_blinding_mask(amount_blinding_mask), asset_id_blinding_mask(asset_id_blinding_mask), asset_id(asset_id)
{}
crypto::scalar_t amount_blinding_mask = 0;
crypto::scalar_t asset_id_blinding_mask = 0;
crypto::public_key asset_id = currency::null_pkey; // not blinded, not multiplied by 1/8 TODO: @#@# consider changing to point_t, also consider using wallet wallet_out_info
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amount_blinding_mask)
KV_SERIALIZE(asset_id_blinding_mask)
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id)
END_KV_SERIALIZE_MAP()
};
std::shared_ptr<transaction_wallet_info> m_ptx_wallet_info;
uint64_t m_internal_output_index = 0;
uint64_t m_spent_height = 0;
uint32_t m_flags = 0;
uint64_t m_amount = 0;
boost::shared_ptr<ZC_out_info> m_zc_info_ptr;
uint64_t amount() const { return m_amount; }
uint64_t amount_for_global_output_index() const { return is_zc() ? 0 : m_amount; } // amount value for global outputs index, it's zero for outputs with hidden amounts
// @#@ will throw if type is not tx_out_bare, TODO: change according to new model,
// need to replace all get_tx_out_bare_from_out_v() to proper code
//const currency::tx_out_bare& output() const { return currency::get_tx_out_bare_from_out_v(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]); }
const currency::tx_out_v& output() const { return m_ptx_wallet_info->m_tx.vout[m_internal_output_index]; }
uint8_t mix_attr() const { uint8_t result = UINT8_MAX; get_mix_attr_from_tx_out_v(output(), result); return result; }
crypto::hash tx_hash() const { return get_transaction_hash(m_ptx_wallet_info->m_tx); }
bool is_spent() const { return m_flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT; }
bool is_spendable() const { return (m_flags & (WALLET_TRANSFER_DETAIL_FLAG_SPENT | WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION | WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION)) == 0; }
bool is_reserved_for_escrow() const { return ( (m_flags & WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION) != 0 ); }
bool is_zc() const { return m_zc_info_ptr.get(); }
const crypto::public_key& get_asset_id() const { if (m_zc_info_ptr.get()) { return m_zc_info_ptr->asset_id; } else { return currency::native_coin_asset_id; } }
bool is_native_coin() const { return m_zc_info_ptr.get() ? (m_zc_info_ptr->asset_id == currency::native_coin_asset_id) : true; }
bool is_htlc() const {
if (m_ptx_wallet_info->m_tx.vout[m_internal_output_index].type() == typeid(currency::tx_out_bare) &&
boost::get<currency::tx_out_bare>(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]).target.type() == typeid(currency::txout_htlc))
return true;
return false;
}
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_CUSTOM(m_ptx_wallet_info, const transaction_wallet_info&, tools::wallet2::transform_ptr_to_value, tools::wallet2::transform_value_to_ptr)
KV_SERIALIZE(m_internal_output_index)
KV_SERIALIZE(m_spent_height)
KV_SERIALIZE(m_flags)
KV_SERIALIZE(m_amount)
KV_SERIALIZE_N(m_zc_info_ptr, "zc_out_info")
KV_SERIALIZE_EPHEMERAL_N(uint64_t, tools::wallet2::transfer_details_base_to_amount, "amount")
KV_SERIALIZE_EPHEMERAL_N(std::string, tools::wallet2::transfer_details_base_to_tx_hash, "tx_id")
END_KV_SERIALIZE_MAP()
};
struct transfer_details_extra_option_htlc_info
{
std::string origin; //this field filled only if htlc had been redeemed
crypto::hash redeem_tx_id = currency::null_hash;
};
typedef boost::variant<transfer_details_extra_option_htlc_info, currency::tx_payer> transfer_details_extra_options_v;
struct transfer_details : public transfer_details_base
{
uint64_t m_global_output_index = 0;
crypto::key_image m_key_image; //TODO: key_image stored twice :(
std::vector<transfer_details_extra_options_v> varian_options;
//v2
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(m_global_output_index)
KV_SERIALIZE_POD_AS_HEX_STRING(m_key_image)
KV_CHAIN_BASE(transfer_details_base)
END_KV_SERIALIZE_MAP()
};
//used in wallet
struct htlc_expiration_trigger
{
bool is_wallet_owns_redeem = false; //specify if this HTLC belong to this wallet by pkey_redeem or by pkey_refund
uint64_t transfer_index = 0;
};
struct payment_details_subtransfer
{
crypto::public_key asset_id = currency::null_pkey;
uint64_t amount = 0;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_id)
BOOST_SERIALIZE(amount)
END_BOOST_SERIALIZATION()
};
struct payment_details
{
crypto::hash m_tx_hash = currency::null_hash;
uint64_t m_amount = 0; // native coins amount
uint64_t m_block_height = 0;
uint64_t m_unlock_time = 0;
std::vector<payment_details_subtransfer> subtransfers; //subtransfers added for confidential asset only, native amount should be stored in m_amount (for space saving)
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(m_tx_hash)
BOOST_SERIALIZE(m_amount)
BOOST_SERIALIZE(m_block_height)
BOOST_SERIALIZE(m_unlock_time)
BOOST_SERIALIZE(subtransfers)
END_BOOST_SERIALIZATION()
};
struct mining_context : public currency::pos_mining_context
{
@ -528,20 +248,6 @@ namespace tools
uint64_t total_amount_checked = 0;
};
struct expiration_entry_info
{
std::vector<uint64_t> selected_transfers;
uint64_t expiration_time = 0;
crypto::hash related_tx_id = currency::null_hash; // tx id which caused money lock, if any (ex: escrow proposal transport tx)
std::vector<payment_details_subtransfer> receved;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(selected_transfers)
BOOST_SERIALIZE(expiration_time)
BOOST_SERIALIZE(related_tx_id)
BOOST_SERIALIZE(receved)
END_BOOST_SERIALIZATION()
};
/*
This might be not the best solution so far, but after discussion with @sowle we came up to conclusion
@ -559,17 +265,6 @@ namespace tools
};
typedef std::unordered_multimap<std::string, payment_details> payment_container;
typedef std::deque<transfer_details> transfer_container;
typedef std::unordered_map<crypto::hash, transfer_details_base> multisig_transfer_container;
typedef std::unordered_map<crypto::hash, tools::wallet_public::escrow_contract_details_basic> escrow_contracts_container;
typedef std::map<uint64_t, std::set<size_t> > free_amounts_cache_type;
typedef std::unordered_map<crypto::public_key, free_amounts_cache_type> free_assets_amounts_cache_type;
typedef std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t> amount_gindex_to_transfer_id_container; // maps [amount; gindex] -> tid
struct keys_file_data_old
{
crypto::chacha8_iv iv;
@ -700,6 +395,7 @@ namespace tools
bool set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy);
void set_pos_utxo_count_limits_for_defragmentation_tx(uint64_t min_outs, uint64_t max_outs); // don't create UTXO defrag. tx if there are less than 'min_outs' outs; don't put more than 'max_outs' outs
void set_pos_decoys_count_for_defragmentation_tx(size_t decoys_count);
void set_pos_required_decoys_count(size_t v) { m_required_decoys_count = v; }
void set_minimum_height(uint64_t h);
std::shared_ptr<i_core_proxy> get_core_proxy();
uint64_t balance() const;
@ -832,7 +528,7 @@ namespace tools
bool scan_pos(mining_context& cxt, std::atomic<bool>& stop, idle_condition_cb_t idle_condition_cb, const currency::core_runtime_config &runtime_config);
bool fill_mining_context(mining_context& ctx);
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
void get_transfers(transfer_container& incoming_transfers) const;
std::string get_transfers_str(bool include_spent = true, bool include_unspent = true, bool show_only_unknown = false, const std::string& filter_asset_ticker = std::string{}) const;
std::string get_balance_str() const;
@ -868,61 +564,7 @@ namespace tools
template <class t_archive>
inline void serialize(t_archive &a, const unsigned int ver)
{
if (t_archive::is_saving::value)
{
WLT_LOG_MAGENTA("Serializing file with ver: " << ver, LOG_LEVEL_0);
}
// do not load wallet if data version is greather than the code version
if (ver > WALLET_FILE_SERIALIZATION_VERSION)
{
WLT_LOG_MAGENTA("Wallet file truncated due to WALLET_FILE_SERIALIZATION_VERSION is more then curren build", LOG_LEVEL_0);
return;
}
if(ver < WALLET_FILE_LAST_SUPPORTED_VERSION)
{
WLT_LOG_MAGENTA("Wallet file truncated due to ver(" << ver << ") is less then WALLET_FILE_LAST_SUPPORTED_VERSION", LOG_LEVEL_0);
return;
}
if (t_archive::is_saving::value)
{
uint64_t formation_ver = CURRENCY_FORMATION_VERSION;
a & formation_ver;
}
else
{
uint64_t formation_ver = 0;
a & formation_ver;
if (formation_ver != CURRENCY_FORMATION_VERSION)
{
WLT_LOG_MAGENTA("Wallet file truncated due to mismatch CURRENCY_FORMATION_VERSION", LOG_LEVEL_0);
return;
}
}
//convert from old version
a & m_chain;
a & m_minimum_height;
a & m_amount_gindex_to_transfer_id;
a & m_transfers;
a & m_multisig_transfers;
a & m_key_images;
a & m_unconfirmed_txs;
a & m_unconfirmed_multisig_transfers;
a & m_payments;
a & m_transfer_history;
a & m_unconfirmed_in_transfers;
a & m_contracts;
a & m_money_expirations;
a & m_pending_key_images;
a & m_tx_keys;
a & m_last_pow_block_h;
a & m_htlcs;
a & m_active_htlcs;
a & m_active_htlcs_txid;
a & m_own_asset_descriptors;
a & m_custom_assets;
wallet2_base_state::serialize(a, ver);
}
bool is_transfer_ready_to_go(const transfer_details& td, uint64_t fake_outputs_count);
@ -953,6 +595,7 @@ namespace tools
bool build_minted_block(const mining_context& cxt);
bool build_minted_block(const mining_context& cxt, const currency::account_public_address& miner_address);
std::string get_extra_text_for_block(uint64_t new_block_expected_height);
bool reset_history();
bool is_transfer_unlocked(const transfer_details& td) const;
bool is_transfer_unlocked(const transfer_details& td, bool for_pos_mining, uint64_t& stake_lock_time) const;
@ -1010,6 +653,8 @@ namespace tools
bool load_whitelisted_tokens_if_not_loaded() const;
bool load_whitelisted_tokens() const;
void set_connectivity_options(unsigned int timeout);
/*
create_htlc_proposal: if htlc_hash == null_hash, then this wallet is originator of the atomic process, and
we use deterministic origin, if given some particular htlc_hash, then we use this hash, and this means that
@ -1021,6 +666,9 @@ namespace tools
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);
void set_votes_config_path(const std::string& path_to_config_file);
const tools::wallet_public::wallet_vote_config& get_current_votes() { return m_votes_config; }
// ionic swaps:
bool create_ionic_swap_proposal(const wallet_public::ionic_swap_proposal_info& proposal_details, const currency::account_public_address& destination_addr, wallet_public::ionic_swap_proposal& proposal);
bool build_ionic_swap_template(const wallet_public::ionic_swap_proposal_info& proposal_detais, const currency::account_public_address& destination_addr,
@ -1047,6 +695,7 @@ namespace tools
protected:
epee::misc_utils::events_dispatcher m_debug_events_dispatcher;
private:
// -------- t_transport_state_notifier ------------------------------------------------
@ -1127,6 +776,7 @@ private:
uint64_t get_current_tx_version();
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const wallet_public::wallet_transfer_info& wti) const;
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const std::string& reason = "internal intention") const;
void load_votes_config();
bool is_need_to_split_outputs();
template<typename input_t>
bool process_input_t(const input_t& in_t, wallet2::process_transaction_context& ptc, const currency::transaction& tx);
@ -1197,71 +847,57 @@ private:
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);
/*
!!!!! IMPORTAN !!!!!
All variables that supposed to hold wallet state of synchronization(i.e. transfers, assets, htlc, swaps, contracts) - should
be placed in wallet2_base_state base class to avoid typical bugs when it's forgotten to be included in reset/resync/serialize functions
*/
currency::account_base m_account;
bool m_watch_only;
std::string m_log_prefix; // part of pub address, prefix for logging functions
std::wstring m_wallet_file;
std::wstring m_pending_ki_file;
std::string m_password;
uint64_t m_minimum_height;
std::atomic<uint64_t> m_last_bc_timestamp;
bool m_do_rise_transfer;
uint64_t m_min_utxo_count_for_defragmentation_tx;
uint64_t m_max_utxo_count_for_defragmentation_tx;
size_t m_decoys_count_for_defragmentation_tx;
transfer_container m_transfers;
multisig_transfer_container m_multisig_transfers;
amount_gindex_to_transfer_id_container m_amount_gindex_to_transfer_id;
payment_container m_payments;
std::unordered_map<crypto::key_image, size_t> m_key_images;
std::unordered_map<crypto::public_key, crypto::key_image> m_pending_key_images; // (out_pk -> ki) pairs of change outputs to be added in watch-only wallet without spend sec key
size_t m_required_decoys_count;
pending_ki_file_container_t m_pending_key_images_file_container;
uint64_t m_upper_transaction_size_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value
std::atomic<bool> m_stop;
std::vector<wallet_public::wallet_transfer_info> m_transfer_history;
std::unordered_map<crypto::hash, currency::transaction> m_unconfirmed_in_transfers;
std::unordered_map<crypto::hash, tools::wallet_public::wallet_transfer_info> m_unconfirmed_txs;
std::unordered_set<crypto::hash> m_unconfirmed_multisig_transfers;
std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys;
std::unordered_map<crypto::public_key, wallet_own_asset_context> m_own_asset_descriptors;
std::unordered_map<crypto::public_key, currency::asset_descriptor_base> m_custom_assets; //assets that manually added by user
mutable std::unordered_map<crypto::public_key, currency::asset_descriptor_base> m_whitelisted_assets; //assets that whitelisted
std::multimap<uint64_t, htlc_expiration_trigger> m_htlcs; //map [expired_if_more_then] -> height of expiration
amount_gindex_to_transfer_id_container m_active_htlcs; // map [amount; gindex] -> transfer index
std::unordered_map<crypto::hash, uint64_t> m_active_htlcs_txid; // map [txid] -> transfer index, limitation: 1 transactiom -> 1 htlc
mutable std::atomic<bool> m_whitelist_updated = false;
std::shared_ptr<i_core_proxy> m_core_proxy;
std::shared_ptr<i_wallet2_callback> m_wcallback;
uint64_t m_height_of_start_sync;
std::atomic<uint64_t> m_last_sync_percent;
uint64_t m_last_pow_block_h;
currency::core_runtime_config m_core_runtime_config;
escrow_contracts_container m_contracts;
wallet_chain_shortener m_chain;
std::list<expiration_entry_info> m_money_expirations;
//optimization for big wallets and batch tx
currency::core_runtime_config m_core_runtime_config;
//optimization for big wallets and batch tx
free_assets_amounts_cache_type m_found_free_amounts;
uint64_t m_fake_outputs_count;
std::string m_miner_text_info;
mutable uint64_t m_current_wallet_file_size;
bool m_use_deffered_global_outputs;
bool m_disable_tor_relay;
bool m_use_assets_whitelisting = true;
mutable current_operation_context m_current_context;
std::string m_votes_config_path;
tools::wallet_public::wallet_vote_config m_votes_config;
//this needed to access wallets state in coretests, for creating abnormal blocks and tranmsactions
friend class test_generator;
std::list<std::pair<uint64_t, wallet_event_t>> m_rollback_events;
}; // class wallet2
} // namespace tools
@ -1269,71 +905,56 @@ private:
BOOST_CLASS_VERSION(tools::wallet2, WALLET_FILE_SERIALIZATION_VERSION)
BOOST_CLASS_VERSION(tools::wallet_public::wallet_transfer_info, 12)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 3)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details_base, 2)
namespace boost
{
namespace serialization
{
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::transaction_wallet_info &x, const boost::serialization::version_type ver)
{
a & x.m_block_height;
a & x.m_block_timestamp;
a & x.m_tx;
}
template <class Archive>
inline void serialize(Archive& a, tools::wallet2::transfer_details_base::ZC_out_info& x, const boost::serialization::version_type ver)
{
a & x.amount_blinding_mask;
a & x.asset_id_blinding_mask;
a & x.asset_id;
}
// template <class Archive>
// inline void serialize(Archive &a, tools::transfer_details &x, const boost::serialization::version_type ver)
// {
// a & x.m_global_output_index;
// a & x.m_key_image;
// a & static_cast<tools::transfer_details_base&>(x);
// if (ver < 3)
// return;
// a & x.varian_options;
// }
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::transfer_details_base &x, const boost::serialization::version_type ver)
{
a & x.m_ptx_wallet_info;
a & x.m_internal_output_index;
a & x.m_flags;
a & x.m_spent_height;
if (ver < 2)
{
x.m_amount = get_amount_from_variant(x.output());
return;
}
a & x.m_amount;
a & x.m_zc_info_ptr;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::transfer_details_extra_option_htlc_info &x, const boost::serialization::version_type ver)
{
a & x.origin;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::transfer_details &x, const boost::serialization::version_type ver)
{
a & x.m_global_output_index;
a & x.m_key_image;
a & static_cast<tools::wallet2::transfer_details_base&>(x);
if (ver < 3)
return;
a & x.varian_options;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::htlc_expiration_trigger &x, const boost::serialization::version_type ver)
{
a & x.is_wallet_owns_redeem;
a & x.transfer_index;
}
/*template <class Archive>
inline void serialize(Archive& a, tools::wallet_public::wallet_transfer_info_details& x, const boost::serialization::version_type ver)
{
a & x.rcv;
a & x.spn;
}
template <class Archive>
inline void serialize(Archive& a, tools::wallet_public::wallet_transfer_info& x, const boost::serialization::version_type ver)
{
a & x.amount;
a & x.timestamp;
a & x.tx_hash;
a & x.height;
a & x.tx_blob_size;
a & x.payment_id;
a & x.remote_addresses;
a & x.is_income;
a & x.td;
a & x.tx;
a & x.remote_aliases;
a & x.comment;
a & x.contract;
a & x.selected_indicies;
a & x.marketplace_entries;
a & x.unlock_time;
if (ver < 10)
return;
a & x.service_entries;
}*/
template <class Archive>
inline void serialize(Archive& a, tools::wallet_public::escrow_contract_details_basic& x, const boost::serialization::version_type ver)
{

523
src/wallet/wallet2_base.h Normal file
View file

@ -0,0 +1,523 @@
// Copyright (c) 2014-2023 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
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <memory>
#include <boost/serialization/list.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/deque.hpp>
#include <boost/serialization/singleton.hpp>
#include <boost/serialization/extended_type_info.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/optional.hpp>
#include <atomic>
#include "include_base_utils.h"
#include "profile_tools.h"
#include "sync_locked_object.h"
#include "currency_core/currency_boost_serialization.h"
#include "currency_core/account_boost_serialization.h"
#include "currency_core/currency_format_utils.h"
#include "common/make_hashable.h"
#include "wallet_public_structs_defs.h"
#include "currency_core/currency_format_utils.h"
#include "common/unordered_containers_boost_serialization.h"
#include "common/atomics_boost_serialization.h"
#include "storages/portable_storage_template_helper.h"
#include "crypto/chacha8.h"
#include "crypto/hash.h"
#include "core_rpc_proxy.h"
#include "core_default_rpc_proxy.h"
#include "wallet_errors.h"
#include "currency_core/core_runtime_config.h"
#include "currency_core/bc_offers_serialization.h"
#include "currency_core/bc_escrow_service.h"
#include "common/pod_array_file_container.h"
#include "wallet_chain_shortener.h"
#include "tor-connect/torlib/tor_lib_iface.h"
#include "currency_core/pos_mining.h"
#include "view_iface.h"
#define WALLET_TRANSFER_DETAIL_FLAG_SPENT uint32_t(1 << 0)
#define WALLET_TRANSFER_DETAIL_FLAG_BLOCKED uint32_t(1 << 1)
#define WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION uint32_t(1 << 2)
#define WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER uint32_t(1 << 3)
#define WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION uint32_t(1 << 4) // transfer is reserved for cold-signing (unsigned tx was created and passed for signing)
#define WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM uint32_t(1 << 5) // for htlc keeps info if this htlc belong as redeem or as refund
namespace tools
{
#pragma pack(push, 1)
struct out_key_to_ki
{
crypto::public_key out_key;
crypto::key_image key_image;
};
#pragma pack(pop)
typedef tools::pod_array_file_container<out_key_to_ki> pending_ki_file_container_t;
namespace detail
{
//----------------------------------------------------------------------------------------------------
inline void digit_split_strategy(const std::vector<currency::tx_destination_entry>& dsts,
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
{
splitted_dsts.clear();
dust = 0;
for (auto& de : dsts)
{
if (de.addr.size() > 1)
{
//for multisig we don't split
splitted_dsts.push_back(de);
}
else if (de.htlc_options.expiration != 0)
{
//for htlc we don't do split
splitted_dsts.push_back(de);
}
else
{
currency::decompose_amount_into_digits(de.amount, dust_threshold,
[&](uint64_t chunk) { splitted_dsts.push_back(currency::tx_destination_entry(chunk, de.addr, de.asset_id)); },
[&](uint64_t a_dust) { splitted_dsts.push_back(currency::tx_destination_entry(a_dust, de.addr, de.asset_id)); }, max_output_allowed);
}
}
if (change_dst.amount > 0)
{
if (change_dst.addr.size() > 1)
{
//for multisig we don't split
splitted_dsts.push_back(change_dst);
}
else
{
currency::decompose_amount_into_digits(change_dst.amount, dust_threshold,
[&](uint64_t chunk) { splitted_dsts.push_back(currency::tx_destination_entry(chunk, change_dst.addr)); },
[&](uint64_t a_dust) { dust = a_dust; }, max_output_allowed);
}
}
}
//----------------------------------------------------------------------------------------------------
inline void null_split_strategy(const std::vector<currency::tx_destination_entry>& dsts,
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
{
splitted_dsts = dsts;
dust = 0;
uint64_t change = change_dst.amount;
if (0 < dust_threshold)
{
for (uint64_t order = 10; order <= 10 * dust_threshold; order *= 10)
{
uint64_t dust_candidate = change_dst.amount % order;
uint64_t change_candidate = (change_dst.amount / order) * order;
if (dust_candidate <= dust_threshold)
{
dust = dust_candidate;
change = change_candidate;
}
else
{
break;
}
}
}
if (0 != change)
{
splitted_dsts.push_back(currency::tx_destination_entry(change, change_dst.addr));
}
}
//----------------------------------------------------------------------------------------------------
inline void void_split_strategy(const std::vector<currency::tx_destination_entry>& dsts,
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
{
splitted_dsts.insert(splitted_dsts.end(), dsts.begin(), dsts.end());
if (change_dst.amount > 0)
splitted_dsts.push_back(change_dst);
}
//----------------------------------------------------------------------------------------------------
enum split_strategy_id_t { ssi_none = 0, ssi_digit = 1, ssi_null = 2, ssi_void = 3 };
//----------------------------------------------------------------------------------------------------
inline bool apply_split_strategy_by_id(split_strategy_id_t id, const std::vector<currency::tx_destination_entry>& dsts,
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
{
switch (id)
{
case ssi_digit:
digit_split_strategy(dsts, change_dst, dust_threshold, splitted_dsts, dust, max_output_allowed);
return true;
case ssi_null:
null_split_strategy(dsts, change_dst, dust_threshold, splitted_dsts, dust, max_output_allowed);
return true;
case ssi_void:
void_split_strategy(dsts, change_dst, dust_threshold, splitted_dsts, dust, max_output_allowed);
return true;
default:
return false;
}
}
} // namespace detail
struct tx_dust_policy
{
uint64_t dust_threshold = 0;
bool add_to_fee = false;
currency::account_public_address addr_for_dust;
tx_dust_policy(uint64_t a_dust_threshold = DEFAULT_DUST_THRESHOLD, bool an_add_to_fee = true, currency::account_public_address an_addr_for_dust = currency::account_public_address())
: dust_threshold(a_dust_threshold)
, add_to_fee(an_add_to_fee)
, addr_for_dust(an_addr_for_dust)
{
}
BEGIN_SERIALIZE_OBJECT()
FIELD(dust_threshold)
FIELD(add_to_fee)
FIELD(addr_for_dust)
END_SERIALIZE()
};
struct construct_tx_param
{
// preparing data for tx
std::vector<currency::tx_destination_entry> dsts;
size_t fake_outputs_count = 0;
uint64_t fee = 0;
tx_dust_policy dust_policy;
crypto::hash multisig_id = currency::null_hash;
uint8_t flags = 0;
uint8_t split_strategy_id = 0;
bool mark_tx_as_complete = false;
crypto::hash htlc_tx_id;
std::string htlc_origin;
// constructing tx
uint64_t unlock_time = 0;
std::vector<currency::extra_v> extra;
std::vector<currency::attachment_v> attachments;
currency::account_public_address crypt_address;
uint8_t tx_outs_attr = 0;
bool shuffle = false;
bool create_utxo_defragmentation_tx = false;
bool need_at_least_1_zc = false;
crypto::secret_key asset_deploy_control_key = currency::null_skey;
};
struct mode_separate_context
{
currency::transaction tx_for_mode_separate;
view::ionic_swap_proposal_info proposal_info;
bool escrow = false;
};
struct selection_for_amount
{
uint64_t needed_amount = 0;
uint64_t found_amount = 0;
//std::vector<uint64_t> selected_indicies;
};
typedef std::unordered_map<crypto::public_key, selection_for_amount> assets_selection_context;
//general rollback mechanism
struct asset_register_event
{
crypto::public_key asset_id = currency::null_pkey;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_id)
END_BOOST_SERIALIZATION()
};
struct wallet_own_asset_context
{
currency::asset_descriptor_base asset_descriptor;
crypto::secret_key control_key;
//uint64_t height = 0;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_descriptor)
BOOST_SERIALIZE(control_key)
//BOOST_SERIALIZE(height)
END_BOOST_SERIALIZATION()
};
struct asset_update_event
{
crypto::public_key asset_id = currency::null_pkey;
wallet_own_asset_context own_context;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_id)
BOOST_SERIALIZE(own_context)
END_BOOST_SERIALIZATION()
};
struct asset_unown_event
{
crypto::public_key asset_id = currency::null_pkey;
wallet_own_asset_context own_context;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_id)
BOOST_SERIALIZE(own_context)
END_BOOST_SERIALIZATION()
};
typedef boost::variant<asset_register_event, asset_update_event, asset_unown_event> wallet_event_t;
struct transaction_wallet_info
{
uint64_t m_block_height = 0;
uint64_t m_block_timestamp = 0;
currency::transaction m_tx;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(m_block_height)
KV_SERIALIZE(m_block_timestamp)
KV_SERIALIZE_CUSTOM(m_tx, std::string, currency::transform_tx_to_str, currency::transform_str_to_tx)
END_KV_SERIALIZE_MAP()
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(m_block_height)
BOOST_SERIALIZE(m_block_timestamp)
BOOST_SERIALIZE(m_tx)
END_BOOST_SERIALIZATION()
};
namespace detail
{
//----------------------------------------------------------------------------------------------------
inline const transaction_wallet_info& transform_ptr_to_value(const std::shared_ptr<transaction_wallet_info>& a)
{
return *a;
}
//----------------------------------------------------------------------------------------------------
inline std::shared_ptr<transaction_wallet_info> transform_value_to_ptr(const transaction_wallet_info& d)
{
THROW_IF_TRUE_WALLET_INT_ERR_EX_NO_HANDLER(false, "transform_value_to_ptr shoruld never be called");
return std::shared_ptr<transaction_wallet_info>();
}
//----------------------------------------------------------------------------------------------------
}
struct transfer_details_base
{
struct ZC_out_info // TODO: @#@# consider using wallet_out_info instead
{
ZC_out_info() = default;
ZC_out_info(const crypto::scalar_t& amount_blinding_mask, const crypto::scalar_t& asset_id_blinding_mask, const crypto::public_key& asset_id)
: amount_blinding_mask(amount_blinding_mask), asset_id_blinding_mask(asset_id_blinding_mask), asset_id(asset_id)
{}
crypto::scalar_t amount_blinding_mask = 0;
crypto::scalar_t asset_id_blinding_mask = 0;
crypto::public_key asset_id = currency::null_pkey; // not blinded, not multiplied by 1/8 TODO: @#@# consider changing to point_t, also consider using wallet wallet_out_info
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amount_blinding_mask)
KV_SERIALIZE(asset_id_blinding_mask)
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id)
END_KV_SERIALIZE_MAP()
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(amount_blinding_mask)
BOOST_SERIALIZE(asset_id_blinding_mask)
BOOST_SERIALIZE(asset_id)
END_BOOST_SERIALIZATION()
};
std::shared_ptr<transaction_wallet_info> m_ptx_wallet_info;
uint64_t m_internal_output_index = 0;
uint64_t m_spent_height = 0;
uint32_t m_flags = 0;
uint64_t m_amount = 0;
boost::shared_ptr<ZC_out_info> m_zc_info_ptr;
uint64_t amount() const { return m_amount; }
uint64_t amount_for_global_output_index() const { return is_zc() ? 0 : m_amount; } // amount value for global outputs index, it's zero for outputs with hidden amounts
// @#@ will throw if type is not tx_out_bare, TODO: change according to new model,
// need to replace all get_tx_out_bare_from_out_v() to proper code
//const currency::tx_out_bare& output() const { return currency::get_tx_out_bare_from_out_v(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]); }
const currency::tx_out_v& output() const { return m_ptx_wallet_info->m_tx.vout[m_internal_output_index]; }
uint8_t mix_attr() const { uint8_t result = UINT8_MAX; get_mix_attr_from_tx_out_v(output(), result); return result; }
crypto::hash tx_hash() const { return get_transaction_hash(m_ptx_wallet_info->m_tx); }
bool is_spent() const { return m_flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT; }
bool is_spendable() const { return (m_flags & (WALLET_TRANSFER_DETAIL_FLAG_SPENT | WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION | WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION)) == 0; }
bool is_reserved_for_escrow() const { return ((m_flags & WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION) != 0); }
bool is_zc() const { return m_zc_info_ptr.get(); }
const crypto::public_key& get_asset_id() const { if (m_zc_info_ptr.get()) { return m_zc_info_ptr->asset_id; } else { return currency::native_coin_asset_id; } }
bool is_native_coin() const { return m_zc_info_ptr.get() ? (m_zc_info_ptr->asset_id == currency::native_coin_asset_id) : true; }
bool is_htlc() const {
if (m_ptx_wallet_info->m_tx.vout[m_internal_output_index].type() == typeid(currency::tx_out_bare) &&
boost::get<currency::tx_out_bare>(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]).target.type() == typeid(currency::txout_htlc))
return true;
return false;
}
static inline uint64_t transfer_details_base_to_amount(const transfer_details_base& tdb)
{
return tdb.amount();
}
//----------------------------------------------------------------------------------------------------
static inline std::string transfer_details_base_to_tx_hash(const transfer_details_base& tdb)
{
return epee::string_tools::pod_to_hex(currency::get_transaction_hash(tdb.m_ptx_wallet_info->m_tx));
}
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_CUSTOM(m_ptx_wallet_info, const transaction_wallet_info&, detail::transform_ptr_to_value, detail::transform_value_to_ptr)
KV_SERIALIZE(m_internal_output_index)
KV_SERIALIZE(m_spent_height)
KV_SERIALIZE(m_flags)
KV_SERIALIZE(m_amount)
KV_SERIALIZE_N(m_zc_info_ptr, "zc_out_info")
KV_SERIALIZE_EPHEMERAL_N(uint64_t, transfer_details_base_to_amount, "amount")
KV_SERIALIZE_EPHEMERAL_N(std::string, transfer_details_base_to_tx_hash, "tx_id")
END_KV_SERIALIZE_MAP()
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(m_ptx_wallet_info)
BOOST_SERIALIZE(m_internal_output_index)
BOOST_SERIALIZE(m_flags)
BOOST_SERIALIZE(m_spent_height)
BOOST_SERIALIZE(m_amount)
BOOST_SERIALIZE(m_zc_info_ptr)
END_BOOST_SERIALIZATION()
};
struct transfer_details_extra_option_htlc_info
{
std::string origin; //this field filled only if htlc had been redeemed
crypto::hash redeem_tx_id = currency::null_hash;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(origin)
BOOST_SERIALIZE(redeem_tx_id)
END_BOOST_SERIALIZATION()
};
typedef boost::variant<transfer_details_extra_option_htlc_info, currency::tx_payer> transfer_details_extra_options_v;
struct transfer_details : public transfer_details_base
{
uint64_t m_global_output_index = 0;
crypto::key_image m_key_image; //TODO: key_image stored twice :(
std::vector<transfer_details_extra_options_v> varian_options;
//v2
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(m_global_output_index)
KV_SERIALIZE_POD_AS_HEX_STRING(m_key_image)
KV_CHAIN_BASE(transfer_details_base)
END_KV_SERIALIZE_MAP()
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(m_global_output_index)
BOOST_SERIALIZE(m_key_image)
BOOST_SERIALIZE_BASE_CLASS(transfer_details_base)
BOOST_SERIALIZE(varian_options)
END_BOOST_SERIALIZATION()
};
//used in wallet
struct htlc_expiration_trigger
{
bool is_wallet_owns_redeem = false; //specify if this HTLC belong to this wallet by pkey_redeem or by pkey_refund
uint64_t transfer_index = 0;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(is_wallet_owns_redeem)
BOOST_SERIALIZE(transfer_index)
END_BOOST_SERIALIZATION()
};
struct payment_details_subtransfer
{
crypto::public_key asset_id = currency::null_pkey;
uint64_t amount = 0;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_id)
BOOST_SERIALIZE(amount)
END_BOOST_SERIALIZATION()
};
struct payment_details
{
crypto::hash m_tx_hash = currency::null_hash;
uint64_t m_amount = 0; // native coins amount
uint64_t m_block_height = 0;
uint64_t m_unlock_time = 0;
std::vector<payment_details_subtransfer> subtransfers; //subtransfers added for confidential asset only, native amount should be stored in m_amount (for space saving)
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(m_tx_hash)
BOOST_SERIALIZE(m_amount)
BOOST_SERIALIZE(m_block_height)
BOOST_SERIALIZE(m_unlock_time)
BOOST_SERIALIZE(subtransfers)
END_BOOST_SERIALIZATION()
};
struct expiration_entry_info
{
std::vector<uint64_t> selected_transfers;
uint64_t expiration_time = 0;
crypto::hash related_tx_id = currency::null_hash; // tx id which caused money lock, if any (ex: escrow proposal transport tx)
std::vector<payment_details_subtransfer> receved;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(selected_transfers)
BOOST_SERIALIZE(expiration_time)
BOOST_SERIALIZE(related_tx_id)
BOOST_SERIALIZE(receved)
END_BOOST_SERIALIZATION()
};
typedef std::unordered_multimap<std::string, payment_details> payment_container;
typedef std::deque<transfer_details> transfer_container;
typedef std::unordered_map<crypto::hash, transfer_details_base> multisig_transfer_container;
typedef std::unordered_map<crypto::hash, tools::wallet_public::escrow_contract_details_basic> escrow_contracts_container;
typedef std::map<uint64_t, std::set<size_t> > free_amounts_cache_type;
typedef std::unordered_map<crypto::public_key, free_amounts_cache_type> free_assets_amounts_cache_type;
typedef std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t> amount_gindex_to_transfer_id_container; // maps [amount; gindex] -> tid
}// namespace tools
BOOST_CLASS_VERSION(tools::transfer_details, 3)
BOOST_CLASS_VERSION(tools::transfer_details_base, 2)

View file

@ -15,10 +15,7 @@
static void exception_handler(){}
wallet_chain_shortener::wallet_chain_shortener(): m_genesis(currency::gdefault_genesis)
{
m_local_bc_size = 1;
}
void wallet_chain_shortener::clear()
{
m_local_bc_size = 1;

View file

@ -18,12 +18,11 @@
#include "include_base_utils.h"
#include "crypto/crypto.h"
#include "currency_core/currency_basic.h"
class wallet_chain_shortener
{
public:
wallet_chain_shortener();
void push_new_block_id(const crypto::hash& id, uint64_t height);
uint64_t get_top_block_height() const;
uint64_t get_blockchain_current_size() const;
@ -48,8 +47,8 @@ public:
//debug functions
std::string get_internal_state_text() const;
private:
std::atomic<uint64_t> m_local_bc_size; //temporary workaround
crypto::hash m_genesis;
std::atomic<uint64_t> m_local_bc_size = 1; //temporary workaround
crypto::hash m_genesis = currency::gdefault_genesis;
std::map<uint64_t, crypto::hash> m_last_20_blocks;
std::map<uint64_t, crypto::hash> m_last_144_blocks_every_10; //1 day
std::map<uint64_t, crypto::hash> m_last_144_blocks_every_100; //10 days

View file

@ -1308,6 +1308,30 @@ namespace wallet_public
};
struct wallet_vote_config_entry
{
std::string proposal_id;
uint64_t h_start;
uint64_t h_end;
bool vote;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(proposal_id)
KV_SERIALIZE(h_start)
KV_SERIALIZE(h_end)
KV_SERIALIZE(vote)
END_KV_SERIALIZE_MAP()
};
struct wallet_vote_config
{
std::vector<wallet_vote_config_entry> entries;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(entries)
END_KV_SERIALIZE_MAP()
};
struct asset_funds
{

View file

@ -94,6 +94,8 @@ namespace tools
static const uint64_t wallet_rpc_idle_work_period_ms = 2000;
m_do_mint = do_mint;
if (m_do_mint)
LOG_PRINT_CYAN("PoS mining is ON", LOG_LEVEL_0);
if (!offline_mode)
{
@ -171,6 +173,7 @@ namespace tools
{
w.get_wallet()->set_miner_text_info(command_line::get_arg(vm, arg_miner_text_info));
}
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@ -448,7 +451,7 @@ namespace tools
}
res.payments.clear();
std::list<wallet2::payment_details> payment_list;
std::list<payment_details> payment_list;
w.get_wallet()->get_payments(payment_id, payment_list);
for (auto payment : payment_list)
{
@ -486,7 +489,7 @@ namespace tools
return false;
}
std::list<wallet2::payment_details> payment_list;
std::list<payment_details> payment_list;
w.get_wallet()->get_payments(payment_id, payment_list, req.min_block_height);
for (auto & payment : payment_list)
@ -772,7 +775,7 @@ namespace tools
bool wallet_rpc_server::on_contracts_get_all(const wallet_public::COMMAND_CONTRACTS_GET_ALL::request& req, wallet_public::COMMAND_CONTRACTS_GET_ALL::response& res, epee::json_rpc::error& er, connection_context& cntx)
{
WALLET_RPC_BEGIN_TRY_ENTRY();
tools::wallet2::escrow_contracts_container ecc;
tools::escrow_contracts_container ecc;
w.get_wallet()->get_contracts(ecc);
res.contracts.resize(ecc.size());
size_t i = 0;

View file

@ -90,61 +90,61 @@ namespace tools
bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response, connection_context& m_conn_context);
BEGIN_URI_MAP2_VIRTUAL()
BEGIN_JSON_RPC_MAP("/json_rpc")
MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_public::COMMAND_RPC_GET_BALANCE)
MAP_JON_RPC_WE("getaddress", on_getaddress, wallet_public::COMMAND_RPC_GET_ADDRESS)
MAP_JON_RPC_WE("get_wallet_info", on_getwallet_info, wallet_public::COMMAND_RPC_GET_WALLET_INFO)
MAP_JON_RPC_WE("get_recent_txs_and_info", on_get_recent_txs_and_info, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO)
MAP_JON_RPC_WE("transfer", on_transfer, wallet_public::COMMAND_RPC_TRANSFER)
MAP_JON_RPC_WE("store", on_store, wallet_public::COMMAND_RPC_STORE)
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_public::COMMAND_RPC_GET_PAYMENTS)
MAP_JON_RPC_WE("get_bulk_payments", on_get_bulk_payments, wallet_public::COMMAND_RPC_GET_BULK_PAYMENTS)
MAP_JON_RPC_WE("make_integrated_address", on_make_integrated_address, wallet_public::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS)
MAP_JON_RPC_WE("split_integrated_address", on_split_integrated_address, wallet_public::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS)
MAP_JON_RPC_WE("sweep_below", on_sweep_below, wallet_public::COMMAND_SWEEP_BELOW)
MAP_JON_RPC_WE("sign_transfer", on_sign_transfer, wallet_public::COMMAND_SIGN_TRANSFER)
MAP_JON_RPC_WE("submit_transfer", on_submit_transfer, wallet_public::COMMAND_SUBMIT_TRANSFER)
MAP_JON_RPC_WE("search_for_transactions", on_search_for_transactions, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS)
MAP_JON_RPC_WE("get_restore_info", on_getwallet_restore_info, wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO)
MAP_JON_RPC_WE("get_seed_phrase_info", on_get_seed_phrase_info, wallet_public::COMMAND_RPC_GET_SEED_PHRASE_INFO)
MAP_JON_RPC_WE("get_mining_history", on_get_mining_history, wallet_public::COMMAND_RPC_GET_MINING_HISTORY)
MAP_JON_RPC_WE("register_alias", on_register_alias, wallet_public::COMMAND_RPC_REGISTER_ALIAS)
//contracts API
MAP_JON_RPC_WE("contracts_send_proposal", on_contracts_send_proposal, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL)
MAP_JON_RPC_WE("contracts_accept_proposal", on_contracts_accept_proposal, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL)
MAP_JON_RPC_WE("contracts_get_all", on_contracts_get_all, wallet_public::COMMAND_CONTRACTS_GET_ALL)
MAP_JON_RPC_WE("contracts_release", on_contracts_release, wallet_public::COMMAND_CONTRACTS_RELEASE)
MAP_JON_RPC_WE("contracts_request_cancel", on_contracts_request_cancel, wallet_public::COMMAND_CONTRACTS_REQUEST_CANCEL)
MAP_JON_RPC_WE("contracts_accept_cancel", on_contracts_accept_cancel, wallet_public::COMMAND_CONTRACTS_ACCEPT_CANCEL)
//marketplace API
MAP_JON_RPC_WE("marketplace_get_offers_ex", on_marketplace_get_my_offers, wallet_public::COMMAND_MARKETPLACE_GET_MY_OFFERS)
MAP_JON_RPC_WE("marketplace_push_offer", on_marketplace_push_offer, wallet_public::COMMAND_MARKETPLACE_PUSH_OFFER)
MAP_JON_RPC_WE("marketplace_push_update_offer", on_marketplace_push_update_offer, wallet_public::COMMAND_MARKETPLACE_PUSH_UPDATE_OFFER)
MAP_JON_RPC_WE("marketplace_cancel_offer", on_marketplace_cancel_offer, wallet_public::COMMAND_MARKETPLACE_CANCEL_OFFER)
//HTLC API
MAP_JON_RPC_WE("atomics_create_htlc_proposal", on_create_htlc_proposal, wallet_public::COMMAND_CREATE_HTLC_PROPOSAL)
MAP_JON_RPC_WE("atomics_get_list_of_active_htlc", on_get_list_of_active_htlc, wallet_public::COMMAND_GET_LIST_OF_ACTIVE_HTLC)
MAP_JON_RPC_WE("atomics_redeem_htlc", on_redeem_htlc, wallet_public::COMMAND_REDEEM_HTLC)
MAP_JON_RPC_WE("atomics_check_htlc_redeemed", on_check_htlc_redeemed, wallet_public::COMMAND_CHECK_HTLC_REDEEMED)
BEGIN_JSON_RPC_MAP("/json_rpc")
MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_public::COMMAND_RPC_GET_BALANCE)
MAP_JON_RPC_WE("getaddress", on_getaddress, wallet_public::COMMAND_RPC_GET_ADDRESS)
MAP_JON_RPC_WE("get_wallet_info", on_getwallet_info, wallet_public::COMMAND_RPC_GET_WALLET_INFO)
MAP_JON_RPC_WE("get_recent_txs_and_info", on_get_recent_txs_and_info, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO)
MAP_JON_RPC_WE("transfer", on_transfer, wallet_public::COMMAND_RPC_TRANSFER)
MAP_JON_RPC_WE("store", on_store, wallet_public::COMMAND_RPC_STORE)
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_public::COMMAND_RPC_GET_PAYMENTS)
MAP_JON_RPC_WE("get_bulk_payments", on_get_bulk_payments, wallet_public::COMMAND_RPC_GET_BULK_PAYMENTS)
MAP_JON_RPC_WE("make_integrated_address", on_make_integrated_address, wallet_public::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS)
MAP_JON_RPC_WE("split_integrated_address", on_split_integrated_address, wallet_public::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS)
MAP_JON_RPC_WE("sweep_below", on_sweep_below, wallet_public::COMMAND_SWEEP_BELOW)
MAP_JON_RPC_WE("sign_transfer", on_sign_transfer, wallet_public::COMMAND_SIGN_TRANSFER)
MAP_JON_RPC_WE("submit_transfer", on_submit_transfer, wallet_public::COMMAND_SUBMIT_TRANSFER)
MAP_JON_RPC_WE("search_for_transactions", on_search_for_transactions, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS)
MAP_JON_RPC_WE("get_restore_info", on_getwallet_restore_info, wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO)
MAP_JON_RPC_WE("get_seed_phrase_info", on_get_seed_phrase_info, wallet_public::COMMAND_RPC_GET_SEED_PHRASE_INFO)
MAP_JON_RPC_WE("get_mining_history", on_get_mining_history, wallet_public::COMMAND_RPC_GET_MINING_HISTORY)
MAP_JON_RPC_WE("register_alias", on_register_alias, wallet_public::COMMAND_RPC_REGISTER_ALIAS)
//contracts API
MAP_JON_RPC_WE("contracts_send_proposal", on_contracts_send_proposal, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL)
MAP_JON_RPC_WE("contracts_accept_proposal", on_contracts_accept_proposal, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL)
MAP_JON_RPC_WE("contracts_get_all", on_contracts_get_all, wallet_public::COMMAND_CONTRACTS_GET_ALL)
MAP_JON_RPC_WE("contracts_release", on_contracts_release, wallet_public::COMMAND_CONTRACTS_RELEASE)
MAP_JON_RPC_WE("contracts_request_cancel", on_contracts_request_cancel, wallet_public::COMMAND_CONTRACTS_REQUEST_CANCEL)
MAP_JON_RPC_WE("contracts_accept_cancel", on_contracts_accept_cancel, wallet_public::COMMAND_CONTRACTS_ACCEPT_CANCEL)
//marketplace API
MAP_JON_RPC_WE("marketplace_get_offers_ex", on_marketplace_get_my_offers, wallet_public::COMMAND_MARKETPLACE_GET_MY_OFFERS)
MAP_JON_RPC_WE("marketplace_push_offer", on_marketplace_push_offer, wallet_public::COMMAND_MARKETPLACE_PUSH_OFFER)
MAP_JON_RPC_WE("marketplace_push_update_offer", on_marketplace_push_update_offer, wallet_public::COMMAND_MARKETPLACE_PUSH_UPDATE_OFFER)
MAP_JON_RPC_WE("marketplace_cancel_offer", on_marketplace_cancel_offer, wallet_public::COMMAND_MARKETPLACE_CANCEL_OFFER)
//HTLC API
MAP_JON_RPC_WE("atomics_create_htlc_proposal", on_create_htlc_proposal, wallet_public::COMMAND_CREATE_HTLC_PROPOSAL)
MAP_JON_RPC_WE("atomics_get_list_of_active_htlc", on_get_list_of_active_htlc, wallet_public::COMMAND_GET_LIST_OF_ACTIVE_HTLC)
MAP_JON_RPC_WE("atomics_redeem_htlc", on_redeem_htlc, wallet_public::COMMAND_REDEEM_HTLC)
MAP_JON_RPC_WE("atomics_check_htlc_redeemed", on_check_htlc_redeemed, wallet_public::COMMAND_CHECK_HTLC_REDEEMED)
//IONIC_SWAPS API
MAP_JON_RPC_WE("ionic_swap_generate_proposal", on_ionic_swap_generate_proposal, wallet_public::COMMAND_IONIC_SWAP_GENERATE_PROPOSAL)
MAP_JON_RPC_WE("ionic_swap_get_proposal_info", on_ionic_swap_get_proposal_info, wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO)
MAP_JON_RPC_WE("ionic_swap_accept_proposal", on_ionic_swap_accept_proposal, wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL)
//IONIC_SWAPS API
MAP_JON_RPC_WE("ionic_swap_generate_proposal", on_ionic_swap_generate_proposal, wallet_public::COMMAND_IONIC_SWAP_GENERATE_PROPOSAL)
MAP_JON_RPC_WE("ionic_swap_get_proposal_info", on_ionic_swap_get_proposal_info, wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO)
MAP_JON_RPC_WE("ionic_swap_accept_proposal", on_ionic_swap_accept_proposal, wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL)
//MULTIWALLET APIs
MAP_JON_RPC_WE("mw_get_wallets", on_mw_get_wallets, wallet_public::COMMAND_MW_GET_WALLETS)
MAP_JON_RPC_WE("mw_select_wallet", on_mw_select_wallet, wallet_public::COMMAND_MW_SELECT_WALLET)
//MULTIWALLET APIs
MAP_JON_RPC_WE("mw_get_wallets", on_mw_get_wallets, wallet_public::COMMAND_MW_GET_WALLETS)
MAP_JON_RPC_WE("mw_select_wallet", on_mw_select_wallet, wallet_public::COMMAND_MW_SELECT_WALLET)
//basic crypto operations
MAP_JON_RPC_WE("sign_message", on_sign_message, wallet_public::COMMAND_SIGN_MESSAGE)
MAP_JON_RPC_WE("encrypt_data", on_encrypt_data, wallet_public::COMMAND_ENCRYPT_DATA)
MAP_JON_RPC_WE("decrypt_data", on_decrypt_data, wallet_public::COMMAND_DECRYPT_DATA)
//basic crypto operations
MAP_JON_RPC_WE("sign_message", on_sign_message, wallet_public::COMMAND_SIGN_MESSAGE)
MAP_JON_RPC_WE("encrypt_data", on_encrypt_data, wallet_public::COMMAND_ENCRYPT_DATA)
MAP_JON_RPC_WE("decrypt_data", on_decrypt_data, wallet_public::COMMAND_DECRYPT_DATA)
END_JSON_RPC_MAP()
END_URI_MAP2()
//json_rpc
bool on_getbalance(const wallet_public::COMMAND_RPC_GET_BALANCE::request& req, wallet_public::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er, connection_context& cntx);
//json_rpc
bool on_getbalance(const wallet_public::COMMAND_RPC_GET_BALANCE::request& req, wallet_public::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_getaddress(const wallet_public::COMMAND_RPC_GET_ADDRESS::request& req, wallet_public::COMMAND_RPC_GET_ADDRESS::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_getwallet_info(const wallet_public::COMMAND_RPC_GET_WALLET_INFO::request& req, wallet_public::COMMAND_RPC_GET_WALLET_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_getwallet_restore_info(const wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO::request& req, wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx);
@ -162,8 +162,8 @@ namespace tools
bool on_search_for_transactions(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_get_mining_history(const wallet_public::COMMAND_RPC_GET_MINING_HISTORY::request& req, wallet_public::COMMAND_RPC_GET_MINING_HISTORY::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_register_alias(const wallet_public::COMMAND_RPC_REGISTER_ALIAS::request& req, wallet_public::COMMAND_RPC_REGISTER_ALIAS::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_contracts_send_proposal(const wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_contracts_accept_proposal(const wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_contracts_get_all(const wallet_public::COMMAND_CONTRACTS_GET_ALL::request& req, wallet_public::COMMAND_CONTRACTS_GET_ALL::response& res, epee::json_rpc::error& er, connection_context& cntx);

View file

@ -1037,6 +1037,9 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
LOG_ERROR("Unexpected location reached");
#endif
}
w->set_votes_config_path(m_data_dir + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME);
std::string return_code = API_RETURN_CODE_OK;
while (true)
@ -1051,6 +1054,7 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
//w->get_unconfirmed_transfers(owr.recent_history.unconfirmed);
w->get_unconfirmed_transfers(owr.recent_history.history, exclude_mining_txs);
owr.wallet_local_bc_size = w->get_blockchain_current_size();
//workaround for missed fee
//owr.seed = w->get_account().get_seed_phrase();
break;
@ -1142,6 +1146,7 @@ std::string wallets_manager::generate_wallet(const std::wstring& path, const std
{
std::shared_ptr<tools::wallet2> w(new tools::wallet2());
w->set_use_deffered_global_outputs(m_use_deffered_global_outputs);
w->set_votes_config_path(m_data_dir + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME);
owr.wallet_id = m_wallet_id_counter++;
w->callback(std::shared_ptr<tools::i_wallet2_callback>(new i_wallet_to_i_backend_adapter(this, owr.wallet_id)));
if (m_remote_node_mode)
@ -1248,6 +1253,7 @@ std::string wallets_manager::restore_wallet(const std::wstring& path, const std:
{
std::shared_ptr<tools::wallet2> w(new tools::wallet2());
w->set_use_deffered_global_outputs(m_use_deffered_global_outputs);
w->set_votes_config_path(m_data_dir + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME);
owr.wallet_id = m_wallet_id_counter++;
w->callback(std::shared_ptr<tools::i_wallet2_callback>(new i_wallet_to_i_backend_adapter(this, owr.wallet_id)));
if (m_remote_node_mode)
@ -1669,7 +1675,7 @@ std::string wallets_manager::get_wallet_info_extra(uint64_t wallet_id, view::wal
std::string wallets_manager::get_contracts(size_t wallet_id, std::vector<tools::wallet_public::escrow_contract_details>& contracts)
{
tools::wallet2::escrow_contracts_container cc;
tools::escrow_contracts_container cc;
GET_WALLET_OPT_BY_ID(wallet_id, w);
try
{
@ -1693,7 +1699,7 @@ std::string wallets_manager::get_contracts(size_t wallet_id, std::vector<tools::
}
std::string wallets_manager::create_proposal(const view::create_proposal_param_gui& cpp)
{
//tools::wallet2::escrow_contracts_container cc;
//tools::escrow_contracts_container cc;
GET_WALLET_OPT_BY_ID(cpp.wallet_id, w);
currency::transaction tx = AUTO_VAL_INIT(tx);
currency::transaction template_tx = AUTO_VAL_INIT(template_tx);
@ -2126,7 +2132,7 @@ void wallets_manager::wallet_vs_options::worker_func()
{
LOG_PRINT_GREEN("[WALLET_HANDLER] Wallet handler thread started, addr: " << w->get()->get_account().get_public_address_str(), LOG_LEVEL_0);
epee::math_helper::once_a_time_seconds<TX_POOL_SCAN_INTERVAL> scan_pool_interval;
epee::math_helper::once_a_time_seconds<POS_WALLET_MINING_SCAN_INTERVAL> pos_minin_interval;
epee::math_helper::once_a_time_seconds<2> pos_minin_interval;
view::wallet_status_info wsi = AUTO_VAL_INIT(wsi);
while (!major_stop)
{

View file

@ -32,7 +32,7 @@ target_link_libraries(coretests rpc wallet currency_core common crypto zlibstati
target_link_libraries(functional_tests rpc wallet currency_core crypto common zlibstatic ethash libminiupnpc-static ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(hash-tests crypto ethash)
target_link_libraries(hash-target-tests crypto currency_core ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(performance_tests currency_core common crypto zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(performance_tests wallet currency_core common crypto zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(unit_tests wallet currency_core common crypto gtest_main zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(net_load_tests_clt currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(net_load_tests_srv currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})

View file

@ -516,6 +516,8 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain,
wallets.back().wallet->assign_account(a);
wallets.back().wallet->get_account().set_createtime(0);
wallets.back().wallet->set_core_proxy(tmp_proxy);
wallets.back().wallet->set_minimum_height(0);
wallets.back().wallet->set_pos_required_decoys_count(0);
currency::core_runtime_config pc = cc;
pc.min_coinstake_age = TESTS_POS_CONFIG_MIN_COINSTAKE_AGE;
@ -634,7 +636,7 @@ bool test_generator::find_kernel(const std::list<currency::account_base>& accs,
found_timestamp = context.sk.block_timestamp;
found_kh = crypto::cn_fast_hash(&context.sk, sizeof(context.sk)); // TODO: consider passing kernel_hash from scan_pos and do_pos_mining_iteration
tools::wallet2::transfer_details td = AUTO_VAL_INIT(td);
tools::transfer_details td = AUTO_VAL_INIT(td);
r = w->get_transfer_info_by_index(context.index, td);
CHECK_AND_NO_ASSERT_MES(r, false, "get_transfer_info_by_index() failed for index " << context.index);
@ -1456,7 +1458,7 @@ bool fill_tx_sources(std::vector<currency::tx_source_entry>& sources, const std:
}
}
uint64_t head_block_ts = get_actual_timestamp(blk_head);
uint64_t head_block_ts = get_block_datetime(blk_head);
uint64_t next_block_height = blockchain.size();
// Iterate in reverse is more efficiency
@ -2151,18 +2153,18 @@ bool make_tx_multisig_to_key(const currency::transaction& source_tx,
bool estimate_wallet_balance_blocked_for_escrow(const tools::wallet2& w, uint64_t& result, bool substruct_change_from_result /* = true */)
{
std::deque<tools::wallet2::transfer_details> transfers;
std::deque<tools::transfer_details> transfers;
w.get_transfers(transfers);
result = 0;
for (const tools::wallet2::transfer_details& td : transfers)
for (const tools::transfer_details& td : transfers)
{
if (td.m_flags == (WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION))
result += td.amount();
}
if (substruct_change_from_result)
{
const std::list<tools::wallet2::expiration_entry_info>& ee = w.get_expiration_entries();
const std::list<tools::expiration_entry_info>& ee = w.get_expiration_entries();
for (auto &e : ee)
{
uint64_t change_amount_native = 0;

View file

@ -819,47 +819,44 @@ bool construct_broken_tx(const currency::account_keys& sender_account_keys, cons
struct input_generation_context_data
{
currency::keypair in_ephemeral;
std::vector<currency::tx_source_entry::output_entry> sorted_outputs;
size_t real_out_index = 0;
};
std::vector<input_generation_context_data> in_contexts;
uint64_t summary_inputs_money = 0;
//fill inputs
BOOST_FOREACH(const currency::tx_source_entry& src_entr, sources)
// fill inputs
for(const currency::tx_source_entry& src_entr : sources)
{
if (src_entr.real_output >= src_entr.outputs.size())
{
LOG_ERROR("real_output index (" << src_entr.real_output << ")bigger than output_keys.size()=" << src_entr.outputs.size());
return false;
}
CHECK_AND_ASSERT_MES(src_entr.real_output < src_entr.outputs.size(), false, "real_output index = " << src_entr.real_output << " is bigger than output_keys.size() = " << src_entr.outputs.size());
input_generation_context_data& igc = in_contexts.emplace_back();
igc.sorted_outputs = prepare_outputs_entries_for_key_offsets(src_entr.outputs, src_entr.real_output, igc.real_out_index);
summary_inputs_money += src_entr.amount;
//key_derivation recv_derivation;
in_contexts.push_back(input_generation_context_data());
currency::keypair& in_ephemeral = in_contexts.back().in_ephemeral;
crypto::key_image img;
if (!currency::generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, in_ephemeral, img))
if (!currency::generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, igc.in_ephemeral, img))
return false;
//check that derivated key is equal with real output key
if (!(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].stealth_address))
if (!(igc.in_ephemeral.pub == igc.sorted_outputs[igc.real_out_index].stealth_address))
{
LOG_ERROR("derived public key missmatch with output public key! " << ENDL << "derived_key:"
<< epst::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:"
<< epst::pod_to_hex(src_entr.outputs[src_entr.real_output].stealth_address));
<< epst::pod_to_hex(igc.in_ephemeral.pub) << ENDL << "real output_public_key:"
<< epst::pod_to_hex(igc.sorted_outputs[igc.real_out_index].stealth_address));
return false;
}
//put key image into tx input
// fill tx input
currency::txin_to_key input_to_key;
input_to_key.amount = src_entr.amount;
input_to_key.k_image = img;
//fill outputs array and use relative offsets
BOOST_FOREACH(const currency::tx_source_entry::output_entry& out_entry, src_entr.outputs)
// fill ring references
for(const currency::tx_source_entry::output_entry& out_entry : igc.sorted_outputs)
input_to_key.key_offsets.push_back(out_entry.out_reference);
input_to_key.key_offsets = currency::absolute_output_offsets_to_relative(input_to_key.key_offsets); // TODO @#@#
tx.vin.push_back(input_to_key);
}
@ -899,11 +896,11 @@ bool construct_broken_tx(const currency::account_keys& sender_account_keys, cons
std::stringstream ss_ring_s;
size_t i = 0;
BOOST_FOREACH(const currency::tx_source_entry& src_entr, sources)
for(const currency::tx_source_entry& src_entr : sources)
{
ss_ring_s << "pub_keys:" << ENDL;
std::vector<const crypto::public_key*> keys_ptrs;
BOOST_FOREACH(const currency::tx_source_entry::output_entry& o, src_entr.outputs)
for(const currency::tx_source_entry::output_entry& o : in_contexts[i].sorted_outputs)
{
keys_ptrs.push_back(&o.stealth_address);
ss_ring_s << o.stealth_address << ENDL;
@ -912,10 +909,10 @@ bool construct_broken_tx(const currency::account_keys& sender_account_keys, cons
tx.signatures.push_back(currency::NLSAG_sig());
std::vector<crypto::signature>& sigs = boost::get<currency::NLSAG_sig>(tx.signatures.back()).s;
sigs.resize(src_entr.outputs.size());
crypto::generate_ring_signature(tx_prefix_hash, boost::get<currency::txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
crypto::generate_ring_signature(tx_prefix_hash, boost::get<currency::txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, in_contexts[i].real_out_index, sigs.data());
ss_ring_s << "signatures:" << ENDL;
std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL; });
ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output;
ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << in_contexts[i].real_out_index;
i++;
}

View file

@ -118,7 +118,7 @@ bool test_parse_hardfork_str_mask()
{
static_assert(ZANO_HARDFORKS_TOTAL >= 5, "this test was made in assumption that this condition holds");
auto v_range = [](size_t a, size_t b) -> std::vector<size_t> { std::vector<size_t> r; for(size_t i = a; i <= b; ++i) r.push_back(i); return r; };
auto v_concat = [](const std::vector<size_t>& a, const std::vector<size_t>& b) -> std::vector<size_t> { std::vector<size_t> r = a; r.insert(r.end(), b.begin(), b.end()); return r; };
//auto v_concat = [](const std::vector<size_t>& a, const std::vector<size_t>& b) -> std::vector<size_t> { std::vector<size_t> r = a; r.insert(r.end(), b.begin(), b.end()); return r; };
const std::vector<size_t> res_empty;
const std::vector<size_t> res_all_hf = v_range(0, ZANO_HARDFORKS_TOTAL - 1);
std::string hf_total_num_str_m_1 = epee::string_tools::num_to_string_fast(ZANO_HARDFORKS_TOTAL - 1);
@ -1104,6 +1104,7 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(pos_wallet_big_block_test);
//GENERATE_AND_PLAY(block_template_against_txs_size); // Long test! by demand only
GENERATE_AND_PLAY(pos_altblocks_validation);
GENERATE_AND_PLAY_HF(pos_mining_with_decoys, "3");
// alternative blocks and generic chain-switching tests
GENERATE_AND_PLAY(gen_chain_switch_pow_pos);

View file

@ -118,7 +118,7 @@ bool emission_test::c1(currency::core& c, size_t ev_index, const std::vector<tes
c.handle_incoming_block(t_serializable_object_to_blob(pb.m_block), bvc);
CHECK_AND_NO_ASSERT_MES(!bvc.m_verification_failed && !bvc.m_marked_as_orphaned && !bvc.m_already_exists, false, "PoS block verification context check failed");
//CHECK_AND_ASSERT_MES(get_actual_timestamp(pb.m_block) == timestamp, false, "Invalid PoS block ts: " << get_actual_timestamp(pb.m_block) << ", expected: " << timestamp);
//CHECK_AND_ASSERT_MES(get_block_datetime(pb.m_block) == timestamp, false, "Invalid PoS block ts: " << get_block_datetime(pb.m_block) << ", expected: " << timestamp);
gen_coins = get_outs_money_amount(pb.m_block.miner_tx) - boost::get<txin_to_key>(pb.m_block.miner_tx.vin[1]).amount;
already_generated_coins += gen_coins;
CHECK_AND_ASSERT_MES(already_generated_coins == bcs.total_coins(), false, "total coins missmatch: BCS has: " << bcs.total_coins() << ", expected: " << already_generated_coins);

View file

@ -312,7 +312,7 @@ bool escrow_altchain_meta_impl::c1(currency::core& c, size_t ev_index, const std
LOG_PRINT_YELLOW("sub event #" << eam_event_index << " (height " << e.height << "): eam_event_refresh_and_check", LOG_LEVEL_0);
LOG_PRINT_GREEN("Alice's wallet is refreshing...", LOG_LEVEL_1);
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
bool stub;
alice_wlt->scan_tx_pool(stub);
size_t blocks_fetched = 0;

View file

@ -67,7 +67,7 @@ inline bool refresh_wallet_and_check_1_contract_state(const char* wallet_name, s
LOG_PRINT_CYAN("Scan tx pool for " << wallet_name << "'s wallet...", LOG_LEVEL_0);
wallet->scan_tx_pool(stub_bool);
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = wallet->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r && contracts.size() == 1, false, "get_contracts() for " << wallet_name << " failed or returned wrong contracts count: " << contracts.size());
CHECK_AND_ASSERT_MES(contracts.begin()->second.state == expected_contract_state, false, wallet_name << " has invalid contract state: " << tools::wallet_public::get_escrow_contract_state_name(contracts.begin()->second.state)
@ -85,7 +85,7 @@ inline bool refresh_wallet_and_check_contract_state(const char* wallet_name, std
CHECK_AND_ASSERT_MES(block_to_be_fetched == SIZE_MAX || blocks_fetched == block_to_be_fetched, false, wallet_name << ": incorrect amount of fetched blocks: " << blocks_fetched << ", expected: " << block_to_be_fetched);
wallet->scan_tx_pool(stub_bool);
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = wallet->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r, false, "get_contracts() for " << wallet_name << " failed");
for (const auto& c : contracts)
@ -611,7 +611,7 @@ inline bool operator==(const bc_services::contract_private_details& lhs, const b
lhs.title == rhs.title;
}
inline bool check_contract_state(const tools::wallet2::escrow_contracts_container& contracts, const bc_services::contract_private_details& cpd, tools::wallet_public::escrow_contract_details::contract_state state, const char* party)
inline bool check_contract_state(const tools::escrow_contracts_container& contracts, const bc_services::contract_private_details& cpd, tools::wallet_public::escrow_contract_details::contract_state state, const char* party)
{
CHECK_AND_ASSERT_MES(contracts.size() == 1, false, party << " has incorrect number of contracts: " << contracts.size());
CHECK_AND_ASSERT_MES(contracts.begin()->second.private_detailes == cpd, false, party << " has invalid contract's private details");

View file

@ -126,7 +126,7 @@ bool escrow_wallet_test::prepare_proposal_accepted_test(currency::core& c, const
wallet_buyer->refresh();
wallet_seller->refresh();
tools::wallet2::escrow_contracts_container contracts_buyer, contracts_seller;
tools::escrow_contracts_container contracts_buyer, contracts_seller;
wallet_buyer->get_contracts(contracts_buyer);
wallet_seller->get_contracts(contracts_seller);
@ -163,7 +163,7 @@ bool escrow_wallet_test::prepare_proposal_accepted_test(currency::core& c, const
CHECK_AND_FORCE_ASSERT_MES(contracts_buyer.begin()->second.state == tools::wallet_public::escrow_contract_details_basic::contract_accepted, false, "Incorrect contracts_buyer state");
CHECK_AND_FORCE_ASSERT_MES(contracts_seller.begin()->second.state == tools::wallet_public::escrow_contract_details_basic::contract_accepted, false, "Incorrect contracts_seller state");
tools::wallet2::multisig_transfer_container ms_buyer, ms_seller;
tools::multisig_transfer_container ms_buyer, ms_seller;
wallet_buyer->get_multisig_transfers(ms_buyer);
wallet_seller->get_multisig_transfers(ms_seller);
CHECK_AND_FORCE_ASSERT_MES(ms_buyer.size() == 1, false, "Incorrect contracts_buyer state");
@ -195,7 +195,7 @@ bool escrow_wallet_test::exec_test_with_specific_release_type(currency::core& c,
expected_state = tools::wallet_public::escrow_contract_details_basic::contract_released_burned;
}
tools::wallet2::escrow_contracts_container contracts_buyer, contracts_seller;
tools::escrow_contracts_container contracts_buyer, contracts_seller;
wallet_buyer->finish_contract(multisig_id, release_instruction);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, 2);
wallet_buyer->refresh();
@ -232,7 +232,7 @@ bool escrow_wallet_test::exec_test_with_cancel_release_type(currency::core& c, c
wallet_miner->transfer(TESTS_DEFAULT_FEE, wallet_buyer->get_account().get_public_address());
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, 10);
wallet_buyer->refresh();
tools::wallet2::escrow_contracts_container contracts_buyer, contracts_seller;
tools::escrow_contracts_container contracts_buyer, contracts_seller;
wallet_buyer->request_cancel_contract(multisig_id, TESTS_DEFAULT_FEE, 60 * 60);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, 2);
wallet_buyer->refresh();
@ -643,7 +643,7 @@ bool escrow_incorrect_proposal::check_normal_proposal(currency::core& c, size_t
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
alice_wlt->refresh();
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(contracts.size() == 1, false, "Alice didn't receive escrow proposal");
CHECK_AND_ASSERT_MES(contracts.begin()->second.is_a == false, false, "proposal has wrong is_a");
@ -682,7 +682,7 @@ bool escrow_incorrect_proposal::check_incorrect_proposal(currency::core& c, size
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
alice_wlt->refresh();
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
alice_wlt->get_contracts(contracts);
if (contracts.size() != 0)
@ -780,7 +780,7 @@ bool escrow_proposal_expiration::c1(currency::core& c, size_t ev_index, const st
uint64_t alice_post_proposal_balance = alice_wlt->balance();
uint64_t alice_post_proposal_balance_expected = alice_start_balance - TESTS_DEFAULT_FEE;
CHECK_AND_ASSERT_MES(alice_post_proposal_balance == alice_post_proposal_balance_expected, false, "Incorrect alice_post_proposal_balance: " << print_money(alice_post_proposal_balance) << ", expected: " << print_money(alice_post_proposal_balance_expected));
std::deque<tools::wallet2::transfer_details> transfers;
std::deque<tools::transfer_details> transfers;
alice_wlt->get_transfers(transfers);
CHECK_AND_ASSERT_MES(transfers.size() == 2 && (
(transfers[0].is_spent() && (transfers[1].m_flags & (WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION))) ||
@ -1330,7 +1330,7 @@ bool escrow_incorrect_proposal_acceptance::check_normal_acceptance(currency::cor
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r, false, "get_contracts() for Alice failed");
@ -1393,7 +1393,7 @@ bool escrow_incorrect_proposal_acceptance::check_incorrect_acceptance(currency::
alice_wlt->dump_trunsfers(ss, false);
LOG_PRINT_L0("check_incorrect_acceptance(" << param << "):" << ENDL << "Alice balance: " << print_money(alice_balance) << ", transfers: " << ENDL << ss.str());
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r, false, "get_contracts() for Alice failed");
@ -1723,7 +1723,7 @@ bool escrow_custom_test::do_custom_test(currency::core& c, size_t ev_index, cons
bob_wlt->refresh();
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", bob_start_balance, 0, INVALID_BALANCE_VAL, 0, 0), false, "");
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = bob_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r, false, "get_contracts() for Bob failed");
CHECK_AND_ASSERT_MES(check_contract_state(contracts, cd.cpd, tools::wallet_public::escrow_contract_details::proposal_sent, "Bob"), false, "wrong contract");
@ -2121,7 +2121,7 @@ bool escrow_incorrect_cancel_proposal::check_normal_cancel_proposal(currency::co
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r, false, "get_contracts() for Alice failed");
CHECK_AND_ASSERT_MES(contracts.size() == 1, false, "Alice has incorrect number of contracts: " << contracts.size());
@ -2209,7 +2209,7 @@ bool escrow_incorrect_cancel_proposal::check_incorrect_cancel_proposal_internal(
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r, false, "get_contracts() for Alice failed");
CHECK_AND_ASSERT_MES(contracts.size() == 1, false, "Alice has incorrect number of contracts: " << contracts.size());
@ -2283,7 +2283,7 @@ bool escrow_proposal_not_enough_money::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "Alice", MK_TEST_COINS(30), 0, MK_TEST_COINS(30), 0, 0), false, "");
std::deque<tools::wallet2::transfer_details> transfers;
std::deque<tools::transfer_details> transfers;
alice_wlt->get_transfers(transfers);
CHECK_AND_ASSERT_MES(transfers.size() == 1, false, "Incorrect transfers size: " << transfers.size());
@ -2392,7 +2392,7 @@ bool escrow_cancellation_and_tx_order::c1(currency::core& c, size_t ev_index, co
LOG_PRINT_GREEN("\n" "alice_wlt->send_escrow_proposal()", LOG_LEVEL_0);
alice_wlt->send_escrow_proposal(cpd, 0, 0, expiration_time, TESTS_DEFAULT_FEE, TESTS_DEFAULT_FEE, "", proposal_tx, escrow_template_tx);
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r, false, "get_contracts() for Alice failed");
CHECK_AND_ASSERT_MES(contracts.size() == 1, false, "Alice has incorrect number of contracts: " << contracts.size());
@ -2593,7 +2593,7 @@ bool escrow_cancellation_proposal_expiration::c1(currency::core& c, size_t ev_in
LOG_PRINT_GREEN("\n" "alice_wlt->send_escrow_proposal()", LOG_LEVEL_0);
alice_wlt->send_escrow_proposal(cpd, 0, 0, expiration_time, TESTS_DEFAULT_FEE, b_release_fee, "", proposal_tx, escrow_template_tx);
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r, false, "get_contracts() for Alice failed");
CHECK_AND_ASSERT_MES(contracts.size() == 1, false, "Alice has incorrect number of contracts: " << contracts.size());
@ -2843,7 +2843,7 @@ bool escrow_cancellation_acceptance_expiration::c1(currency::core& c, size_t ev_
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_1_contract_state("Alice", alice_wlt, tools::wallet_public::escrow_contract_details::proposal_sent), false, "");
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_1_contract_state("Bob", bob_wlt, tools::wallet_public::escrow_contract_details::proposal_sent), false, "");
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r && contracts.size() == 1, false, "get_contracts() for Alice failed");
crypto::hash contract_id = contracts.begin()->first;
@ -3217,7 +3217,7 @@ bool escrow_balance::c1(currency::core& c, size_t ev_index, const std::vector<te
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
tools::wallet2::escrow_contracts_container contracts;
tools::escrow_contracts_container contracts;
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r && contracts.size() == 1, false, "get_contracts() for Alice failed");
crypto::hash contract_id = contracts.begin()->first;

View file

@ -493,9 +493,9 @@ bool assets_and_explicit_native_coins_in_outs::c2_alice_deploys_asset(currency::
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", m_alice_initial_balance - TESTS_DEFAULT_FEE, 0, m_alice_initial_balance - TESTS_DEFAULT_FEE, 0, 0), false, "");
// make sure Alice has two UTXO now
tools::wallet2::transfer_container transfers{};
tools::transfer_container transfers{};
alice_wlt->get_transfers(transfers);
size_t unspent_transfers = std::count_if(transfers.begin(), transfers.end(), [](const tools::wallet2::transfer_details& tr){ return !tr.is_spent(); });
size_t unspent_transfers = std::count_if(transfers.begin(), transfers.end(), [](const tools::transfer_details& tr){ return !tr.is_spent(); });
CHECK_AND_ASSERT_MES(unspent_transfers == 2, false, "unexpected number of Alice's unspent transfers: " << unspent_transfers);
asset_descriptor_base adb{};
@ -654,7 +654,7 @@ bool asset_depoyment_and_few_zc_utxos::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", m_alice_initial_balance, 0, m_alice_initial_balance, 0, 0), false, "");
// make sure Alice has correct UTXO wallet structure
tools::wallet2::transfer_container transfers{};
tools::transfer_container transfers{};
alice_wlt->get_transfers(transfers);
size_t zc_unspent_outs = 0, unspent_outs = 0;
for(auto& td : transfers)

View file

@ -185,7 +185,7 @@ bool multisig_wallet_test::c1(currency::core& c, size_t ev_index, const std::vec
wallet_a->refresh();
wallet_b->refresh();
tools::wallet2::multisig_transfer_container ms_a, ms_b;
tools::multisig_transfer_container ms_a, ms_b;
wallet_a->get_multisig_transfers(ms_a);
wallet_b->get_multisig_transfers(ms_b);
CHECK_AND_ASSERT_MES(ms_a.size() == 1 && ms_b.size() == 1, false, "Multisig failed: ms_a.size() == 1 && ms_b.size() == 1");
@ -334,7 +334,7 @@ bool multisig_wallet_test_many_dst::c1(currency::core& c, size_t ev_index, const
r = check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", amount - TESTS_DEFAULT_FEE);
CHECK_AND_ASSERT_MES(r, false, "invalid balance");
tools::wallet2::multisig_transfer_container mstc;
tools::multisig_transfer_container mstc;
alice_wlt->get_multisig_transfers(mstc);
CHECK_AND_ASSERT_MES(mstc.empty(), false, "Got invalid multisig transfer");
@ -446,7 +446,7 @@ bool multisig_wallet_heterogenous_dst::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(blocks_fetched == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1, false, "Incorrect numbers of blocks fetched");
r = check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", amount5 + TESTS_DEFAULT_FEE);
CHECK_AND_ASSERT_MES(r, false, "Invalid wallet balance");
tools::wallet2::multisig_transfer_container alice_mstc;
tools::multisig_transfer_container alice_mstc;
alice_wlt->get_multisig_transfers(alice_mstc);
CHECK_AND_ASSERT_MES(alice_mstc.size() == 2 && alice_mstc.count(ms1_hash) == 1 && alice_mstc.count(ms3_hash) == 1, false, "Alice has incorrect multisig transfers");
@ -456,7 +456,7 @@ bool multisig_wallet_heterogenous_dst::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(blocks_fetched == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1, false, "Incorrect numbers of blocks fetched");
r = check_balance_via_wallet(*bob_wlt.get(), "bob_wlt", 0);
CHECK_AND_ASSERT_MES(r, false, "Invalid wallet balance");
tools::wallet2::multisig_transfer_container bob_mstc;
tools::multisig_transfer_container bob_mstc;
bob_wlt->get_multisig_transfers(bob_mstc);
CHECK_AND_ASSERT_MES(bob_mstc.size() == 2 && bob_mstc.count(ms1_hash) == 1 && bob_mstc.count(ms4_hash) == 1, false, "Bob has incorrect multisig transfers");
@ -466,7 +466,7 @@ bool multisig_wallet_heterogenous_dst::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(blocks_fetched == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1, false, "Incorrect numbers of blocks fetched");
r = check_balance_via_wallet(*carol_wlt.get(), "carol_wlt", 0);
CHECK_AND_ASSERT_MES(r, false, "Invalid wallet balance");
tools::wallet2::multisig_transfer_container carol_mstc;
tools::multisig_transfer_container carol_mstc;
carol_wlt->get_multisig_transfers(carol_mstc);
CHECK_AND_ASSERT_MES(carol_mstc.size() == 2 && carol_mstc.count(ms2_hash) == 1 && carol_mstc.count(ms4_hash) == 1, false, "Carol has incorrect multisig transfers");
@ -476,7 +476,7 @@ bool multisig_wallet_heterogenous_dst::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(blocks_fetched == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1, false, "Incorrect numbers of blocks fetched");
r = check_balance_via_wallet(*dan_wlt.get(), "dan_wlt", amount6 + TESTS_DEFAULT_FEE);
CHECK_AND_ASSERT_MES(r, false, "Invalid wallet balance");
tools::wallet2::multisig_transfer_container dan_mstc;
tools::multisig_transfer_container dan_mstc;
dan_wlt->get_multisig_transfers(dan_mstc);
CHECK_AND_ASSERT_MES(dan_mstc.size() == 2 && dan_mstc.count(ms2_hash) == 1 && dan_mstc.count(ms3_hash) == 1, false, "Dan has incorrect multisig transfers");
@ -2540,7 +2540,7 @@ bool multisig_unconfirmed_transfer_and_multiple_scan_pool_calls::c1(currency::co
miner_wlt->refresh();
alice_wlt->refresh();
tools::wallet2::multisig_transfer_container ms_m, ms_a;
tools::multisig_transfer_container ms_m, ms_a;
miner_wlt->get_multisig_transfers(ms_m);
alice_wlt->get_multisig_transfers(ms_a);
CHECK_AND_ASSERT_MES(ms_m.size() == 1 && ms_a.size() == 1, false, "Multisig failed: ms_m.size() == 1 && ms_a.size() == 1");
@ -2571,7 +2571,7 @@ bool multisig_unconfirmed_transfer_and_multiple_scan_pool_calls::c1(currency::co
LOG_PRINT_YELLOW("%%%%% tx " << get_transaction_hash(tx) << " is spending multisig output " << multisig_id, LOG_LEVEL_0);
bool stub;
std::deque<tools::wallet2::transfer_details> transfers;
std::deque<tools::transfer_details> transfers;
std::vector<tools::wallet_public::wallet_transfer_info> unconfirmed_transfers;
alice_wlt->scan_tx_pool(stub);

View file

@ -139,3 +139,149 @@ bool gen_pos_basic_tests::check_exchange_1(currency::core& c, size_t ev_index, c
CHECK_EQ(offers.size(), 1);
return true;
}
//------------------------------------------------------------------------------
pos_mining_with_decoys::pos_mining_with_decoys()
{
REGISTER_CALLBACK_METHOD(pos_mining_with_decoys, c1);
}
bool pos_mining_with_decoys::generate(std::vector<test_event_entry>& events) const
{
uint64_t ts = test_core_time::get_time();
m_accounts.resize(TOTAL_ACCS_COUNT);
currency::account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
currency::account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
currency::account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); bob_acc.set_createtime(ts);
currency::account_base& carol_acc = m_accounts[CAROL_ACC_IDX]; carol_acc.generate(); carol_acc.set_createtime(ts);
currency::account_base& dan_acc = m_accounts[DAN_ACC_IDX]; dan_acc.generate(true); dan_acc.set_createtime(ts); // Dan has an auditable wallet
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1);
bool r = false;
std::vector<tx_source_entry> sources;
r = fill_tx_sources(sources, events, blk_0r, miner_acc.get_keys(), 2 * COIN, 0);
CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed");
std::vector<tx_destination_entry> destinations;
destinations.emplace_back(47 * TESTS_DEFAULT_FEE, alice_acc.get_public_address());
destinations.emplace_back(47 * TESTS_DEFAULT_FEE, miner_acc.get_public_address()); // as a decoy for Alice and Dan
destinations.emplace_back(47 * TESTS_DEFAULT_FEE, dan_acc.get_public_address());
destinations.emplace_back(5 * TESTS_DEFAULT_FEE, bob_acc.get_public_address());
destinations.emplace_back(COIN, carol_acc.get_public_address());
transaction tx_0{};
r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_attachment, tx_0, get_tx_version_from_events(events), 0);
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
events.push_back(tx_0);
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0);
REWIND_BLOCKS_N(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
DO_CALLBACK(events, "c1");
return true;
}
bool pos_mining_with_decoys::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false;
CHECK_AND_ASSERT_MES(!c.get_blockchain_storage().get_core_runtime_config().is_hardfork_active_for_height(4, c.get_top_block_height()), false, "HF4 should not be active");
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, m_accounts[MINER_ACC_IDX]);
miner_wlt->refresh();
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]);
alice_wlt->refresh();
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", 47 * TESTS_DEFAULT_FEE, INVALID_BALANCE_VAL, 47 * TESTS_DEFAULT_FEE), false, "");
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, m_accounts[BOB_ACC_IDX]);
bob_wlt->refresh();
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt, "Bob", 5 * TESTS_DEFAULT_FEE, INVALID_BALANCE_VAL, 5 * TESTS_DEFAULT_FEE), false, "");
std::shared_ptr<tools::wallet2> carol_wlt = init_playtime_test_wallet(events, c, m_accounts[CAROL_ACC_IDX]);
carol_wlt->refresh();
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*carol_wlt, "Carol", COIN, INVALID_BALANCE_VAL, COIN), false, "");
std::shared_ptr<tools::wallet2> dan_wlt = init_playtime_test_wallet(events, c, m_accounts[DAN_ACC_IDX]);
dan_wlt->refresh();
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*dan_wlt, "Dan", 47 * TESTS_DEFAULT_FEE, INVALID_BALANCE_VAL, 47 * TESTS_DEFAULT_FEE), false, "");
// 1. Alice should be able to mine a PoS block with 1 decoys (ring size == 2)
size_t top_block_height = c.get_top_block_height();
r = alice_wlt->try_mint_pos(m_accounts[ALICE_ACC_IDX].get_public_address());
CHECK_AND_ASSERT_MES(r, false, "try_mint_pos failed");
{
block b{};
CHECK_AND_ASSERT_MES(c.get_blockchain_storage().get_top_block(b), false, "");
CHECK_AND_ASSERT_MES(get_block_height(b) == top_block_height + 1, false, "unexpected top block height");
txin_to_key& intk = boost::get<txin_to_key>(b.miner_tx.vin[1]);
CHECK_AND_ASSERT_MES(intk.amount == 47 * TESTS_DEFAULT_FEE, false, "incorrect amount: " << intk.amount);
CHECK_AND_ASSERT_MES(intk.key_offsets.size() == 2, false, "unexpected ring size: " << intk.key_offsets.size());
}
// 2. Bob should only be able to mine a PoS block with zero decoys (ring size == 1)
top_block_height = c.get_top_block_height();
bob_wlt->refresh();
r = bob_wlt->try_mint_pos(m_accounts[BOB_ACC_IDX].get_public_address());
CHECK_AND_ASSERT_MES(r, false, "try_mint_pos failed");
{
block b{};
CHECK_AND_ASSERT_MES(c.get_blockchain_storage().get_top_block(b), false, "");
CHECK_AND_ASSERT_MES(get_block_height(b) == top_block_height + 1, false, "unexpected top block height");
txin_to_key& intk = boost::get<txin_to_key>(b.miner_tx.vin[1]);
CHECK_AND_ASSERT_MES(intk.amount == 5 * TESTS_DEFAULT_FEE, false, "incorrect amount: " << intk.amount);
CHECK_AND_ASSERT_MES(intk.key_offsets.size() == 1, false, "unexpected ring size: " << intk.key_offsets.size());
}
// 3. Carol should only be able to mine a PoS block with CURRENCY_DEFAULT_DECOY_SET_SIZE decoys (ring size == CURRENCY_DEFAULT_DECOY_SET_SIZE + 1)
top_block_height = c.get_top_block_height();
carol_wlt->refresh();
r = carol_wlt->try_mint_pos(m_accounts[CAROL_ACC_IDX].get_public_address());
CHECK_AND_ASSERT_MES(r, false, "try_mint_pos failed");
{
block b{};
CHECK_AND_ASSERT_MES(c.get_blockchain_storage().get_top_block(b), false, "");
CHECK_AND_ASSERT_MES(get_block_height(b) == top_block_height + 1, false, "unexpected top block height");
txin_to_key& intk = boost::get<txin_to_key>(b.miner_tx.vin[1]);
CHECK_AND_ASSERT_MES(intk.amount == COIN, false, "incorrect amount: " << intk.amount);
CHECK_AND_ASSERT_MES(intk.key_offsets.size() == CURRENCY_DEFAULT_DECOY_SET_SIZE + 1, false, "unexpected ring size: " << intk.key_offsets.size());
}
// 4. Dan has an auditable wallet that couldn't use mixins, but still he should be able to successfully mine a PoS block (ring size = 1, zero decoys)
top_block_height = c.get_top_block_height();
CHECK_AND_ASSERT_MES(dan_wlt->is_auditable(), false, "Dan's wallet is not auditable, which is unexpected");
dan_wlt->refresh();
r = dan_wlt->try_mint_pos(m_accounts[DAN_ACC_IDX].get_public_address());
CHECK_AND_ASSERT_MES(r, false, "try_mint_pos failed");
{
block b{};
CHECK_AND_ASSERT_MES(c.get_blockchain_storage().get_top_block(b), false, "");
CHECK_AND_ASSERT_MES(get_block_height(b) == top_block_height + 1, false, "unexpected top block height");
txin_to_key& intk = boost::get<txin_to_key>(b.miner_tx.vin[1]);
CHECK_AND_ASSERT_MES(intk.amount == 47 * TESTS_DEFAULT_FEE, false, "incorrect amount: " << intk.amount);
CHECK_AND_ASSERT_MES(intk.key_offsets.size() == 1, false, "unexpected ring size: " << intk.key_offsets.size());
}
return true;
}

View file

@ -5,6 +5,7 @@
#pragma once
#include "chaingen.h"
#include "wallet_tests_basic.h"
struct gen_pos_basic_tests : public test_chain_unit_base
{
@ -22,3 +23,12 @@ struct gen_pos_basic_tests : public test_chain_unit_base
bool check_exchange_1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};
struct pos_mining_with_decoys : public wallet_test
{
pos_mining_with_decoys();
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

@ -37,7 +37,8 @@ struct tx_builder
for(const currency::tx_source_entry::output_entry& out_entry : src_entr.outputs)
input_to_key.key_offsets.push_back(out_entry.out_reference);
input_to_key.key_offsets = currency::absolute_output_offsets_to_relative(input_to_key.key_offsets); // TODO @#@#
// if the following line fails, consider using prepare_outputs_entries_for_key_offsets() for correct calculation of real out index
CHECK_AND_ASSERT_THROW_MES(absolute_sorted_output_offsets_to_relative_in_place(input_to_key.key_offsets), "absolute_sorted_output_offsets_to_relative_in_place failed");
m_tx.vin.push_back(input_to_key);
}
}

View file

@ -144,7 +144,7 @@ bool wallet_rpc_integrated_address_transfer::c1(currency::core& c, size_t ev_ind
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt, tds.amount), false, "");
// check the transfer has been received
std::list<tools::wallet2::payment_details> payments;
std::list<tools::payment_details> payments;
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");
@ -254,7 +254,7 @@ bool wallet_rpc_transfer::c1(currency::core& c, size_t ev_index, const std::vect
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);
tools::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, "");

View file

@ -1072,10 +1072,10 @@ bool gen_wallet_payment_id::generate(std::vector<test_event_entry>& events) cons
CHECK_TEST_WALLET_BALANCE_AT_GEN_TIME(alice_wlt, MK_TEST_COINS(40 + 5 + 7 - 10 + 13 + 1) - TESTS_DEFAULT_FEE);
DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(ALICE_ACC_IDX, MK_TEST_COINS(40 + 5 + 7 - 10 + 13 + 1) - TESTS_DEFAULT_FEE));
std::list<tools::wallet2::payment_details> payments;
std::list<tools::payment_details> payments;
alice_wlt->get_payments(m_payment_id, payments);
CHECK_AND_ASSERT_MES(payments.size() == 3, false, "Invalid payments count");
payments.sort([](const tools::wallet2::payment_details& lhs, const tools::wallet2::payment_details& rhs) -> bool { return lhs.m_amount < rhs.m_amount; } ); // sort payments by amount to order them for further checks
payments.sort([](const tools::payment_details& lhs, const tools::payment_details& rhs) -> bool { return lhs.m_amount < rhs.m_amount; } ); // sort payments by amount to order them for further checks
CHECK_AND_ASSERT_MES(payments.front().m_amount == MK_TEST_COINS(5) && payments.front().m_tx_hash == get_transaction_hash(tx_1), false, "Invalid payments #1");
CHECK_AND_ASSERT_MES(payments.back().m_amount == MK_TEST_COINS(13) && payments.back().m_tx_hash == get_transaction_hash(tx_4), false, "Invalid payments #3");
payments.clear();
@ -1104,7 +1104,7 @@ bool gen_wallet_payment_id::generate(std::vector<test_event_entry>& events) cons
payments.clear();
alice_wlt->get_payments(m_payment_id, payments);
CHECK_AND_ASSERT_MES(payments.size() == 3, false, "Invalid payments count (2)");
payments.sort([](const tools::wallet2::payment_details& lhs, const tools::wallet2::payment_details& rhs) -> bool { return lhs.m_amount < rhs.m_amount; } ); // sort payments by amount to order them for further checks
payments.sort([](const tools::payment_details& lhs, const tools::payment_details& rhs) -> bool { return lhs.m_amount < rhs.m_amount; } ); // sort payments by amount to order them for further checks
CHECK_AND_ASSERT_MES(payments.front().m_amount == MK_TEST_COINS(5) && payments.front().m_tx_hash == get_transaction_hash(tx_1), false, "Invalid payments #1");
CHECK_AND_ASSERT_MES(payments.back().m_amount == MK_TEST_COINS(9) && payments.back().m_tx_hash == get_transaction_hash(tx_6), false, "Invalid payments #3");
@ -1126,10 +1126,10 @@ bool gen_wallet_payment_id::c1(currency::core& c, size_t ev_index, const std::ve
if (!check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(56) - TESTS_DEFAULT_FEE, 0, 0, 0, 0))
return false;
std::list<tools::wallet2::payment_details> payments;
std::list<tools::payment_details> payments;
alice_wlt->get_payments(m_payment_id, payments);
CHECK_AND_ASSERT_MES(payments.size() == 3, false, "Invalid payments count (4)");
payments.sort([](const tools::wallet2::payment_details& lhs, const tools::wallet2::payment_details& rhs) -> bool { return lhs.m_amount < rhs.m_amount; } ); // sort payments by amount to order them for further checks
payments.sort([](const tools::payment_details& lhs, const tools::payment_details& rhs) -> bool { return lhs.m_amount < rhs.m_amount; } ); // sort payments by amount to order them for further checks
CHECK_AND_ASSERT_MES(payments.front().m_amount == MK_TEST_COINS(5), false, "Invalid payments #1");
CHECK_AND_ASSERT_MES(payments.back().m_amount == MK_TEST_COINS(13), false, "Invalid payments #3");
@ -1157,10 +1157,10 @@ bool gen_wallet_payment_id::c2(currency::core& c, size_t ev_index, const std::ve
return false;
std::list<tools::wallet2::payment_details> payments;
std::list<tools::payment_details> payments;
alice_wlt->get_payments(m_payment_id, payments);
CHECK_AND_ASSERT_MES(payments.size() == 3, false, "Invalid payments count (4)");
payments.sort([](const tools::wallet2::payment_details& lhs, const tools::wallet2::payment_details& rhs) -> bool { return lhs.m_amount < rhs.m_amount; } ); // sort payments by amount to order them for further checks
payments.sort([](const tools::payment_details& lhs, const tools::payment_details& rhs) -> bool { return lhs.m_amount < rhs.m_amount; } ); // sort payments by amount to order them for further checks
CHECK_AND_ASSERT_MES(payments.front().m_amount == MK_TEST_COINS(5), false, "Invalid payments #1");
CHECK_AND_ASSERT_MES(payments.back().m_amount == MK_TEST_COINS(9), false, "Invalid payments #3");
@ -1230,7 +1230,7 @@ bool gen_wallet_oversized_payment_id::c1(currency::core& c, size_t ev_index, con
alice_wlt->refresh(blocks_fetched, received_money, atomic_false);
CHECK_AND_ASSERT_MES(blocks_fetched == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3 + 1, false, "incorrect number of blocks fetched by Alice's wallet: " << blocks_fetched);
std::list<tools::wallet2::payment_details> payments;
std::list<tools::payment_details> payments;
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");
@ -1306,7 +1306,7 @@ bool gen_wallet_transfers_and_outdated_unconfirmed_txs::generate(std::vector<tes
// refresh the wallet and check transfers, both should be not spent
CREATE_TEST_WALLET(alice_wlt, alice_acc, blk_0);
REFRESH_TEST_WALLET_AT_GEN_TIME(events, alice_wlt, blk_1r, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2 + WALLET_DEFAULT_TX_SPENDABLE_AGE);
tools::wallet2::transfer_container trs;
tools::transfer_container trs;
alice_wlt->get_transfers(trs);
CHECK_AND_ASSERT_MES(trs.size() == 2 && !trs[0].is_spent() && !trs[1].is_spent(), false, "Wrong transfers state");
@ -1383,7 +1383,7 @@ bool gen_wallet_transfers_and_chain_switch::generate(std::vector<test_event_entr
// refresh the wallet and check transfers, both should be not spent
CREATE_TEST_WALLET(alice_wlt, alice_acc, blk_0);
REFRESH_TEST_WALLET_AT_GEN_TIME(events, alice_wlt, blk_1r, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1 + WALLET_DEFAULT_TX_SPENDABLE_AGE);
tools::wallet2::transfer_container trs;
tools::transfer_container trs;
alice_wlt->get_transfers(trs);
CHECK_AND_ASSERT_MES(trs.size() == 2 && !trs[0].is_spent() && !trs[1].is_spent(), false, "Wrong transfers state");

View file

@ -193,11 +193,11 @@ bool do_send_money_by_fractions(tools::wallet2& w1, tools::wallet2& w2, size_t m
}
}
uint64_t got_money_in_first_transfers(const tools::wallet2::transfer_container& incoming_transfers, size_t n_transfers)
uint64_t got_money_in_first_transfers(const tools::transfer_container& incoming_transfers, size_t n_transfers)
{
uint64_t summ = 0;
size_t count = 0;
BOOST_FOREACH(const tools::wallet2::transfer_details& td, incoming_transfers)
BOOST_FOREACH(const tools::transfer_details& td, incoming_transfers)
{
summ += boost::get<tx_out_bare>(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).amount;
if(++count >= n_transfers)
@ -240,7 +240,7 @@ void wait_unlock_money(tools::wallet2& w, flow_test_context& control)
std::string get_incoming_transfers_str(tools::wallet2& w)
{
tools::wallet2::transfer_container transfers;
tools::transfer_container transfers;
w.get_transfers(transfers);
uint64_t spent_count = 0;
@ -453,7 +453,7 @@ bool transactions_flow_test(
LOG_PRINT_GREEN("Transfers: " << get_incoming_transfers_str(w1), LOG_LEVEL_0);
uint64_t transfer_size = TX_DEFAULT_FEE;//amount_to_transfer / transactions_count;
tools::wallet2::transfer_container incoming_transfers;
tools::transfer_container incoming_transfers;
size_t prepared_transfers = 0;
@ -469,7 +469,7 @@ bool transactions_flow_test(
//lets go!
size_t count = 0;
prepared_transfers = 0;
BOOST_FOREACH(tools::wallet2::transfer_details& td, incoming_transfers)
BOOST_FOREACH(tools::transfer_details& td, incoming_transfers)
{
if (td.is_spent())
continue;

View file

@ -0,0 +1,25 @@
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "wallet/core_rpc_proxy.h"
#include "wallet/core_default_rpc_proxy.h"
int test_get_rand_outs()
{
currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req = AUTO_VAL_INIT(req);
currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response rsp = AUTO_VAL_INIT(rsp);
req.use_forced_mix_outs = false;
req.decoys_count = 10 + 1;
for (size_t i = 0; i != 50; i++)
req.amounts.push_back(COIN);
std::shared_ptr<tools::i_core_proxy> m_core_proxy(new tools::default_http_core_proxy());
m_core_proxy->set_connection_addr("127.0.0.1:11211");
m_core_proxy->check_connection();
bool r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(req, rsp);
return 0;
}

View file

@ -0,0 +1,26 @@
// Copyright (c) 2012-2014 The Zano developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "gtest/gtest.h"
#include <cstdint>
#include <vector>
#include "misc_language.h"
#include "currency_core/currency_format_utils.h"
TEST(governance_testig, governance_tests_1)
{
std::string vote = "{\"ZGP11\":1,\"ZGP23\":0}";
std::list<std::pair<std::string, bool>> votes;
currency::parse_vote(vote, votes);
ASSERT_TRUE(votes.size() == 2);
ASSERT_TRUE(votes.begin()->first == "ZGP11");
ASSERT_TRUE(votes.begin()->second == true);
ASSERT_TRUE((++votes.begin())->first == "ZGP23");
ASSERT_TRUE((++votes.begin())->second == false);
}

View file

@ -185,41 +185,11 @@ rm -f Zano.zip
/usr/bin/ditto -c -k --keepParent ./Zano.app ./Zano.zip
tmpfile="tmptmptmp"
xcrun altool --notarize-app --primary-bundle-id "org.zano.desktop" -u "andrey@zano.org" -p "@keychain:Developer-altool" --file ./Zano.zip > $tmpfile 2>&1
NOTARIZE_RES=$?
NOTARIZE_OUTPUT=$( cat $tmpfile )
rm $tmpfile
echo "NOTARIZE_OUTPUT=$NOTARIZE_OUTPUT"
if [ $NOTARIZE_RES -ne 0 ]; then
echo "Notarization failed"
exit 1
fi
GUID=$(echo "$NOTARIZE_OUTPUT" | egrep -Ewo '[[:xdigit:]]{8}(-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}')
if [ ${#GUID} -ne 36 ]; then
echo "Couldn't get correct GUID from the response, got only \"$GUID\""
exit 1
fi
success=0
# check notarization status
for i in {1..10}; do
xcrun altool --notarization-info $GUID -u "andrey@zano.org" -p "@keychain:Developer-altool" > $tmpfile 2>&1
NOTARIZE_OUTPUT=$( cat $tmpfile )
rm $tmpfile
NOTARIZATION_LOG_URL=$(echo "$NOTARIZE_OUTPUT" | sed -n "s/.*LogFileURL\: \([[:graph:]]*\).*/\1/p")
if [ ${#NOTARIZATION_LOG_URL} -ge 30 ]; then
success=1
curl -L $NOTARIZATION_LOG_URL
break
fi
sleep 60
done
if [ $success -ne 1 ]; then
echo "Build notarization failed"
#xcrun altool --notarize-app --primary-bundle-id "org.zano.desktop" -u "andrey@zano.org" -p "@keychain:Developer-altool" --file ./Zano.zip > $tmpfile 2>&1
xcrun notarytool submit --wait --keychain-profile "notarytool-password" ./Zano.zip
RETURN=$?
if [ $RETURN -ne 0 ]; then
echo "Failed to submit for notarization or notarization failed, error code $RETURN"
exit 1
fi

View file

@ -0,0 +1 @@
{"method": "getrandom_outs","params": {"amounts": [80000000000000000],"outs_count": 11, "use_forced_mix_outs": false }}