Merge pull request #5333
18faa6da
wallet: add freeze/thaw/frozen commands (moneromooo-monero)
This commit is contained in:
commit
286dec012d
@ -239,6 +239,9 @@ namespace
|
|||||||
const char* USAGE_MARK_OUTPUT_SPENT("mark_output_spent <amount>/<offset> | <filename> [add]");
|
const char* USAGE_MARK_OUTPUT_SPENT("mark_output_spent <amount>/<offset> | <filename> [add]");
|
||||||
const char* USAGE_MARK_OUTPUT_UNSPENT("mark_output_unspent <amount>/<offset>");
|
const char* USAGE_MARK_OUTPUT_UNSPENT("mark_output_unspent <amount>/<offset>");
|
||||||
const char* USAGE_IS_OUTPUT_SPENT("is_output_spent <amount>/<offset>");
|
const char* USAGE_IS_OUTPUT_SPENT("is_output_spent <amount>/<offset>");
|
||||||
|
const char* USAGE_FREEZE("freeze <key_image>");
|
||||||
|
const char* USAGE_THAW("thaw <key_image>");
|
||||||
|
const char* USAGE_FROZEN("frozen <key_image>");
|
||||||
const char* USAGE_VERSION("version");
|
const char* USAGE_VERSION("version");
|
||||||
const char* USAGE_HELP("help [<command>]");
|
const char* USAGE_HELP("help [<command>]");
|
||||||
|
|
||||||
@ -2027,6 +2030,74 @@ bool simple_wallet::save_known_rings(const std::vector<std::string> &args)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool simple_wallet::freeze_thaw(const std::vector<std::string> &args, bool freeze)
|
||||||
|
{
|
||||||
|
if (args.empty())
|
||||||
|
{
|
||||||
|
fail_msg_writer() << boost::format(tr("usage: %s <key_image>|<pubkey>")) % (freeze ? "freeze" : "thaw");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
crypto::key_image ki;
|
||||||
|
if (!epee::string_tools::hex_to_pod(args[0], ki))
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("failed to parse key image");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (freeze)
|
||||||
|
m_wallet->freeze(ki);
|
||||||
|
else
|
||||||
|
m_wallet->thaw(ki);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << e.what();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool simple_wallet::freeze(const std::vector<std::string> &args)
|
||||||
|
{
|
||||||
|
return freeze_thaw(args, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool simple_wallet::thaw(const std::vector<std::string> &args)
|
||||||
|
{
|
||||||
|
return freeze_thaw(args, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool simple_wallet::frozen(const std::vector<std::string> &args)
|
||||||
|
{
|
||||||
|
if (args.empty())
|
||||||
|
{
|
||||||
|
size_t ntd = m_wallet->get_num_transfer_details();
|
||||||
|
for (size_t i = 0; i < ntd; ++i)
|
||||||
|
{
|
||||||
|
if (!m_wallet->frozen(i))
|
||||||
|
continue;
|
||||||
|
const tools::wallet2::transfer_details &td = m_wallet->get_transfer_details(i);
|
||||||
|
message_writer() << tr("Frozen: ") << td.m_key_image << " " << cryptonote::print_money(td.amount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crypto::key_image ki;
|
||||||
|
if (!epee::string_tools::hex_to_pod(args[0], ki))
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("failed to parse key image");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m_wallet->frozen(ki))
|
||||||
|
message_writer() << tr("Frozen: ") << ki;
|
||||||
|
else
|
||||||
|
message_writer() << tr("Not frozen: ") << ki;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool simple_wallet::version(const std::vector<std::string> &args)
|
bool simple_wallet::version(const std::vector<std::string> &args)
|
||||||
{
|
{
|
||||||
message_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
|
message_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
|
||||||
@ -2602,7 +2673,7 @@ simple_wallet::simple_wallet()
|
|||||||
tr(USAGE_INCOMING_TRANSFERS),
|
tr(USAGE_INCOMING_TRANSFERS),
|
||||||
tr("Show the incoming transfers, all or filtered by availability and address index.\n\n"
|
tr("Show the incoming transfers, all or filtered by availability and address index.\n\n"
|
||||||
"Output format:\n"
|
"Output format:\n"
|
||||||
"Amount, Spent(\"T\"|\"F\"), \"locked\"|\"unlocked\", RingCT, Global Index, Transaction Hash, Address Index, [Public Key, Key Image] "));
|
"Amount, Spent(\"T\"|\"F\"), \"frozen\"|\"locked\"|\"unlocked\", RingCT, Global Index, Transaction Hash, Address Index, [Public Key, Key Image] "));
|
||||||
m_cmd_binder.set_handler("payments",
|
m_cmd_binder.set_handler("payments",
|
||||||
boost::bind(&simple_wallet::show_payments, this, _1),
|
boost::bind(&simple_wallet::show_payments, this, _1),
|
||||||
tr(USAGE_PAYMENTS),
|
tr(USAGE_PAYMENTS),
|
||||||
@ -3014,6 +3085,18 @@ simple_wallet::simple_wallet()
|
|||||||
boost::bind(&simple_wallet::blackballed, this, _1),
|
boost::bind(&simple_wallet::blackballed, this, _1),
|
||||||
tr(USAGE_IS_OUTPUT_SPENT),
|
tr(USAGE_IS_OUTPUT_SPENT),
|
||||||
tr("Checks whether an output is marked as spent"));
|
tr("Checks whether an output is marked as spent"));
|
||||||
|
m_cmd_binder.set_handler("freeze",
|
||||||
|
boost::bind(&simple_wallet::freeze, this, _1),
|
||||||
|
tr(USAGE_FREEZE),
|
||||||
|
tr("Freeze a single output by key image so it will not be used"));
|
||||||
|
m_cmd_binder.set_handler("thaw",
|
||||||
|
boost::bind(&simple_wallet::thaw, this, _1),
|
||||||
|
tr(USAGE_THAW),
|
||||||
|
tr("Thaw a single output by key image so it may be used again"));
|
||||||
|
m_cmd_binder.set_handler("frozen",
|
||||||
|
boost::bind(&simple_wallet::frozen, this, _1),
|
||||||
|
tr(USAGE_FROZEN),
|
||||||
|
tr("Checks whether a given output is currently frozen by key image"));
|
||||||
m_cmd_binder.set_handler("version",
|
m_cmd_binder.set_handler("version",
|
||||||
boost::bind(&simple_wallet::version, this, _1),
|
boost::bind(&simple_wallet::version, this, _1),
|
||||||
tr(USAGE_VERSION),
|
tr(USAGE_VERSION),
|
||||||
@ -4989,7 +5072,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
|
|||||||
boost::format("%21s%8s%12s%8s%16u%68s%16u%s") %
|
boost::format("%21s%8s%12s%8s%16u%68s%16u%s") %
|
||||||
print_money(td.amount()) %
|
print_money(td.amount()) %
|
||||||
(td.m_spent ? tr("T") : tr("F")) %
|
(td.m_spent ? tr("T") : tr("F")) %
|
||||||
(m_wallet->is_transfer_unlocked(td) ? tr("unlocked") : tr("locked")) %
|
(m_wallet->frozen(td) ? tr("[frozen]") : m_wallet->is_transfer_unlocked(td) ? tr("unlocked") : tr("locked")) %
|
||||||
(td.is_rct() ? tr("RingCT") : tr("-")) %
|
(td.is_rct() ? tr("RingCT") : tr("-")) %
|
||||||
td.m_global_output_index %
|
td.m_global_output_index %
|
||||||
td.m_txid %
|
td.m_txid %
|
||||||
|
@ -238,9 +238,12 @@ namespace cryptonote
|
|||||||
bool blackball(const std::vector<std::string>& args);
|
bool blackball(const std::vector<std::string>& args);
|
||||||
bool unblackball(const std::vector<std::string>& args);
|
bool unblackball(const std::vector<std::string>& args);
|
||||||
bool blackballed(const std::vector<std::string>& args);
|
bool blackballed(const std::vector<std::string>& args);
|
||||||
|
bool freeze(const std::vector<std::string>& args);
|
||||||
|
bool thaw(const std::vector<std::string>& args);
|
||||||
|
bool frozen(const std::vector<std::string>& args);
|
||||||
bool version(const std::vector<std::string>& args);
|
bool version(const std::vector<std::string>& args);
|
||||||
bool cold_sign_tx(const std::vector<tools::wallet2::pending_tx>& ptx_vector, tools::wallet2::signed_tx_set &exported_txs, std::vector<cryptonote::address_parse_info> &dsts_info, std::function<bool(const tools::wallet2::signed_tx_set &)> accept_func);
|
|
||||||
|
|
||||||
|
bool cold_sign_tx(const std::vector<tools::wallet2::pending_tx>& ptx_vector, tools::wallet2::signed_tx_set &exported_txs, std::vector<cryptonote::address_parse_info> &dsts_info, std::function<bool(const tools::wallet2::signed_tx_set &)> accept_func);
|
||||||
uint64_t get_daemon_blockchain_height(std::string& err);
|
uint64_t get_daemon_blockchain_height(std::string& err);
|
||||||
bool try_connect_to_daemon(bool silent = false, uint32_t* version = nullptr);
|
bool try_connect_to_daemon(bool silent = false, uint32_t* version = nullptr);
|
||||||
bool ask_wallet_create_if_needed();
|
bool ask_wallet_create_if_needed();
|
||||||
@ -253,6 +256,7 @@ namespace cryptonote
|
|||||||
void key_images_sync_intern();
|
void key_images_sync_intern();
|
||||||
void on_refresh_finished(uint64_t start_height, uint64_t fetched_blocks, bool is_init, bool received_money);
|
void on_refresh_finished(uint64_t start_height, uint64_t fetched_blocks, bool is_init, bool received_money);
|
||||||
std::pair<std::string, std::string> show_outputs_line(const std::vector<uint64_t> &heights, uint64_t blockchain_height, uint64_t highlight_height = std::numeric_limits<uint64_t>::max()) const;
|
std::pair<std::string, std::string> show_outputs_line(const std::vector<uint64_t> &heights, uint64_t blockchain_height, uint64_t highlight_height = std::numeric_limits<uint64_t>::max()) const;
|
||||||
|
bool freeze_thaw(const std::vector<std::string>& args, bool freeze);
|
||||||
|
|
||||||
struct transfer_view
|
struct transfer_view
|
||||||
{
|
{
|
||||||
|
@ -1441,6 +1441,58 @@ void wallet2::set_unspent(size_t idx)
|
|||||||
td.m_spent_height = 0;
|
td.m_spent_height = 0;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
void wallet2::freeze(size_t idx)
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid transfer_details index");
|
||||||
|
transfer_details &td = m_transfers[idx];
|
||||||
|
td.m_frozen = true;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
void wallet2::thaw(size_t idx)
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid transfer_details index");
|
||||||
|
transfer_details &td = m_transfers[idx];
|
||||||
|
td.m_frozen = false;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet2::frozen(size_t idx) const
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid transfer_details index");
|
||||||
|
const transfer_details &td = m_transfers[idx];
|
||||||
|
return td.m_frozen;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
void wallet2::freeze(const crypto::key_image &ki)
|
||||||
|
{
|
||||||
|
freeze(get_transfer_details(ki));
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
void wallet2::thaw(const crypto::key_image &ki)
|
||||||
|
{
|
||||||
|
thaw(get_transfer_details(ki));
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet2::frozen(const crypto::key_image &ki) const
|
||||||
|
{
|
||||||
|
return frozen(get_transfer_details(ki));
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
size_t wallet2::get_transfer_details(const crypto::key_image &ki) const
|
||||||
|
{
|
||||||
|
for (size_t idx = 0; idx < m_transfers.size(); ++idx)
|
||||||
|
{
|
||||||
|
const transfer_details &td = m_transfers[idx];
|
||||||
|
if (td.m_key_image_known && td.m_key_image == ki)
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(false, "Key image not found");
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet2::frozen(const transfer_details &td) const
|
||||||
|
{
|
||||||
|
return td.m_frozen;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const
|
void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const
|
||||||
{
|
{
|
||||||
hw::device &hwdev = m_account.get_device();
|
hw::device &hwdev = m_account.get_device();
|
||||||
@ -1858,6 +1910,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||||||
td.m_mask = rct::identity();
|
td.m_mask = rct::identity();
|
||||||
td.m_rct = false;
|
td.m_rct = false;
|
||||||
}
|
}
|
||||||
|
td.m_frozen = false;
|
||||||
set_unspent(m_transfers.size()-1);
|
set_unspent(m_transfers.size()-1);
|
||||||
if (td.m_key_image_known)
|
if (td.m_key_image_known)
|
||||||
m_key_images[td.m_key_image] = m_transfers.size()-1;
|
m_key_images[td.m_key_image] = m_transfers.size()-1;
|
||||||
@ -3205,8 +3258,9 @@ void wallet2::detach_blockchain(uint64_t height, std::map<std::pair<uint64_t, ui
|
|||||||
wallet2::transfer_details &td = m_transfers[i];
|
wallet2::transfer_details &td = m_transfers[i];
|
||||||
if (td.m_spent && td.m_spent_height >= height)
|
if (td.m_spent && td.m_spent_height >= height)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Resetting spent status for output " << i << ": " << td.m_key_image);
|
LOG_PRINT_L1("Resetting spent/frozen status for output " << i << ": " << td.m_key_image);
|
||||||
set_unspent(i);
|
set_unspent(i);
|
||||||
|
thaw(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5391,7 +5445,7 @@ std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_majo
|
|||||||
std::map<uint32_t, uint64_t> amount_per_subaddr;
|
std::map<uint32_t, uint64_t> amount_per_subaddr;
|
||||||
for (const auto& td: m_transfers)
|
for (const auto& td: m_transfers)
|
||||||
{
|
{
|
||||||
if (td.m_subaddr_index.major == index_major && !td.m_spent)
|
if (td.m_subaddr_index.major == index_major && !td.m_spent && !td.m_frozen)
|
||||||
{
|
{
|
||||||
auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
|
auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
|
||||||
if (found == amount_per_subaddr.end())
|
if (found == amount_per_subaddr.end())
|
||||||
@ -5420,7 +5474,7 @@ std::map<uint32_t, uint64_t> wallet2::unlocked_balance_per_subaddress(uint32_t i
|
|||||||
std::map<uint32_t, uint64_t> amount_per_subaddr;
|
std::map<uint32_t, uint64_t> amount_per_subaddr;
|
||||||
for(const transfer_details& td: m_transfers)
|
for(const transfer_details& td: m_transfers)
|
||||||
{
|
{
|
||||||
if(td.m_subaddr_index.major == index_major && !td.m_spent && is_transfer_unlocked(td))
|
if(td.m_subaddr_index.major == index_major && !td.m_spent && !td.m_frozen && is_transfer_unlocked(td))
|
||||||
{
|
{
|
||||||
auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
|
auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
|
||||||
if (found == amount_per_subaddr.end())
|
if (found == amount_per_subaddr.end())
|
||||||
@ -8314,7 +8368,7 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
|
|||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||||
{
|
{
|
||||||
const transfer_details& td = m_transfers[i];
|
const transfer_details& td = m_transfers[i];
|
||||||
if (!td.m_spent && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
if (!td.m_spent && !td.m_frozen && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("We can use " << i << " alone: " << print_money(td.amount()));
|
LOG_PRINT_L2("We can use " << i << " alone: " << print_money(td.amount()));
|
||||||
picks.push_back(i);
|
picks.push_back(i);
|
||||||
@ -8329,13 +8383,13 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
|
|||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||||
{
|
{
|
||||||
const transfer_details& td = m_transfers[i];
|
const transfer_details& td = m_transfers[i];
|
||||||
if (!td.m_spent && !td.m_key_image_partial && td.is_rct() && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
if (!td.m_spent && !td.m_frozen && !td.m_key_image_partial && td.is_rct() && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("Considering input " << i << ", " << print_money(td.amount()));
|
LOG_PRINT_L2("Considering input " << i << ", " << print_money(td.amount()));
|
||||||
for (size_t j = i + 1; j < m_transfers.size(); ++j)
|
for (size_t j = i + 1; j < m_transfers.size(); ++j)
|
||||||
{
|
{
|
||||||
const transfer_details& td2 = m_transfers[j];
|
const transfer_details& td2 = m_transfers[j];
|
||||||
if (!td2.m_spent && !td.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index)
|
if (!td2.m_spent && !td2.m_frozen && !td.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index)
|
||||||
{
|
{
|
||||||
// update our picks if those outputs are less related than any we
|
// update our picks if those outputs are less related than any we
|
||||||
// already found. If the same, don't update, and oldest suitable outputs
|
// already found. If the same, don't update, and oldest suitable outputs
|
||||||
@ -8562,6 +8616,7 @@ void wallet2::light_wallet_get_unspent_outs()
|
|||||||
td.m_pk_index = 0;
|
td.m_pk_index = 0;
|
||||||
td.m_internal_output_index = o.index;
|
td.m_internal_output_index = o.index;
|
||||||
td.m_spent = spent;
|
td.m_spent = spent;
|
||||||
|
td.m_frozen = false;
|
||||||
|
|
||||||
tx_out txout;
|
tx_out txout;
|
||||||
txout.target = txout_to_key(public_key);
|
txout.target = txout_to_key(public_key);
|
||||||
@ -9036,7 +9091,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below threshold " << print_money(fractional_threshold));
|
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below threshold " << print_money(fractional_threshold));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!td.m_spent && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
if (!td.m_spent && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
||||||
{
|
{
|
||||||
const uint32_t index_minor = td.m_subaddr_index.minor;
|
const uint32_t index_minor = td.m_subaddr_index.minor;
|
||||||
auto find_predicate = [&index_minor](const std::pair<uint32_t, std::vector<size_t>>& x) { return x.first == index_minor; };
|
auto find_predicate = [&index_minor](const std::pair<uint32_t, std::vector<size_t>>& x) { return x.first == index_minor; };
|
||||||
@ -9516,7 +9571,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
|||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||||
{
|
{
|
||||||
const transfer_details& td = m_transfers[i];
|
const transfer_details& td = m_transfers[i];
|
||||||
if (!td.m_spent && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && (subaddr_indices.empty() || subaddr_indices.count(td.m_subaddr_index.minor) == 1))
|
if (!td.m_spent && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && (subaddr_indices.empty() || subaddr_indices.count(td.m_subaddr_index.minor) == 1))
|
||||||
{
|
{
|
||||||
fund_found = true;
|
fund_found = true;
|
||||||
if (below == 0 || td.amount() < below)
|
if (below == 0 || td.amount() < below)
|
||||||
@ -9564,7 +9619,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
|
|||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||||
{
|
{
|
||||||
const transfer_details& td = m_transfers[i];
|
const transfer_details& td = m_transfers[i];
|
||||||
if (td.m_key_image_known && td.m_key_image == ki && !td.m_spent && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td))
|
if (td.m_key_image_known && td.m_key_image == ki && !td.m_spent && !td.m_frozen && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td))
|
||||||
{
|
{
|
||||||
if (td.is_rct() || is_valid_decomposed_amount(td.amount()))
|
if (td.is_rct() || is_valid_decomposed_amount(td.amount()))
|
||||||
unused_transfers_indices.push_back(i);
|
unused_transfers_indices.push_back(i);
|
||||||
@ -9902,6 +9957,8 @@ std::vector<size_t> wallet2::select_available_outputs(const std::function<bool(c
|
|||||||
{
|
{
|
||||||
if (i->m_spent)
|
if (i->m_spent)
|
||||||
continue;
|
continue;
|
||||||
|
if (i->m_frozen)
|
||||||
|
continue;
|
||||||
if (i->m_key_image_partial)
|
if (i->m_key_image_partial)
|
||||||
continue;
|
continue;
|
||||||
if (!is_transfer_unlocked(*i))
|
if (!is_transfer_unlocked(*i))
|
||||||
@ -9917,7 +9974,7 @@ std::vector<uint64_t> wallet2::get_unspent_amounts_vector() const
|
|||||||
std::set<uint64_t> set;
|
std::set<uint64_t> set;
|
||||||
for (const auto &td: m_transfers)
|
for (const auto &td: m_transfers)
|
||||||
{
|
{
|
||||||
if (!td.m_spent)
|
if (!td.m_spent && !td.m_frozen)
|
||||||
set.insert(td.is_rct() ? 0 : td.amount());
|
set.insert(td.is_rct() ? 0 : td.amount());
|
||||||
}
|
}
|
||||||
std::vector<uint64_t> vector;
|
std::vector<uint64_t> vector;
|
||||||
@ -10043,7 +10100,7 @@ void wallet2::discard_unmixable_outputs()
|
|||||||
std::vector<size_t> unmixable_outputs = select_available_unmixable_outputs();
|
std::vector<size_t> unmixable_outputs = select_available_unmixable_outputs();
|
||||||
for (size_t idx : unmixable_outputs)
|
for (size_t idx : unmixable_outputs)
|
||||||
{
|
{
|
||||||
m_transfers[idx].m_spent = true;
|
freeze(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10834,7 +10891,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
|
|||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||||
{
|
{
|
||||||
const transfer_details &td = m_transfers[i];
|
const transfer_details &td = m_transfers[i];
|
||||||
if (!td.m_spent && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major))
|
if (!td.m_spent && !td.m_frozen && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major))
|
||||||
selected_transfers.push_back(i);
|
selected_transfers.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11581,6 +11638,8 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
|
|||||||
for(size_t i = 0; i < offset; ++i)
|
for(size_t i = 0; i < offset; ++i)
|
||||||
{
|
{
|
||||||
const transfer_details &td = m_transfers[i];
|
const transfer_details &td = m_transfers[i];
|
||||||
|
if (td.m_frozen)
|
||||||
|
continue;
|
||||||
uint64_t amount = td.amount();
|
uint64_t amount = td.amount();
|
||||||
if (td.m_spent)
|
if (td.m_spent)
|
||||||
spent += amount;
|
spent += amount;
|
||||||
@ -11592,6 +11651,8 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
|
|||||||
for(size_t i = 0; i < signed_key_images.size(); ++i)
|
for(size_t i = 0; i < signed_key_images.size(); ++i)
|
||||||
{
|
{
|
||||||
const transfer_details &td = m_transfers[i + offset];
|
const transfer_details &td = m_transfers[i + offset];
|
||||||
|
if (td.m_frozen)
|
||||||
|
continue;
|
||||||
uint64_t amount = td.amount();
|
uint64_t amount = td.amount();
|
||||||
if (td.m_spent)
|
if (td.m_spent)
|
||||||
spent += amount;
|
spent += amount;
|
||||||
|
@ -266,6 +266,7 @@ namespace tools
|
|||||||
size_t m_internal_output_index;
|
size_t m_internal_output_index;
|
||||||
uint64_t m_global_output_index;
|
uint64_t m_global_output_index;
|
||||||
bool m_spent;
|
bool m_spent;
|
||||||
|
bool m_frozen;
|
||||||
uint64_t m_spent_height;
|
uint64_t m_spent_height;
|
||||||
crypto::key_image m_key_image; //TODO: key_image stored twice :(
|
crypto::key_image m_key_image; //TODO: key_image stored twice :(
|
||||||
rct::key m_mask;
|
rct::key m_mask;
|
||||||
@ -291,6 +292,7 @@ namespace tools
|
|||||||
FIELD(m_internal_output_index)
|
FIELD(m_internal_output_index)
|
||||||
FIELD(m_global_output_index)
|
FIELD(m_global_output_index)
|
||||||
FIELD(m_spent)
|
FIELD(m_spent)
|
||||||
|
FIELD(m_frozen)
|
||||||
FIELD(m_spent_height)
|
FIELD(m_spent_height)
|
||||||
FIELD(m_key_image)
|
FIELD(m_key_image)
|
||||||
FIELD(m_mask)
|
FIELD(m_mask)
|
||||||
@ -1246,6 +1248,14 @@ namespace tools
|
|||||||
bool unblackball_output(const std::pair<uint64_t, uint64_t> &output);
|
bool unblackball_output(const std::pair<uint64_t, uint64_t> &output);
|
||||||
bool is_output_blackballed(const std::pair<uint64_t, uint64_t> &output) const;
|
bool is_output_blackballed(const std::pair<uint64_t, uint64_t> &output) const;
|
||||||
|
|
||||||
|
void freeze(size_t idx);
|
||||||
|
void thaw(size_t idx);
|
||||||
|
bool frozen(size_t idx) const;
|
||||||
|
void freeze(const crypto::key_image &ki);
|
||||||
|
void thaw(const crypto::key_image &ki);
|
||||||
|
bool frozen(const crypto::key_image &ki) const;
|
||||||
|
bool frozen(const transfer_details &td) const;
|
||||||
|
|
||||||
// MMS -------------------------------------------------------------------------------------------------
|
// MMS -------------------------------------------------------------------------------------------------
|
||||||
mms::message_store& get_message_store() { return m_message_store; };
|
mms::message_store& get_message_store() { return m_message_store; };
|
||||||
const mms::message_store& get_message_store() const { return m_message_store; };
|
const mms::message_store& get_message_store() const { return m_message_store; };
|
||||||
@ -1328,6 +1338,7 @@ namespace tools
|
|||||||
bool get_ring(const crypto::chacha_key &key, const crypto::key_image &key_image, std::vector<uint64_t> &outs);
|
bool get_ring(const crypto::chacha_key &key, const crypto::key_image &key_image, std::vector<uint64_t> &outs);
|
||||||
crypto::chacha_key get_ringdb_key();
|
crypto::chacha_key get_ringdb_key();
|
||||||
void setup_keys(const epee::wipeable_string &password);
|
void setup_keys(const epee::wipeable_string &password);
|
||||||
|
size_t get_transfer_details(const crypto::key_image &ki) const;
|
||||||
|
|
||||||
void register_devices();
|
void register_devices();
|
||||||
hw::device& lookup_device(const std::string & device_descriptor);
|
hw::device& lookup_device(const std::string & device_descriptor);
|
||||||
@ -1482,7 +1493,7 @@ namespace tools
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
BOOST_CLASS_VERSION(tools::wallet2, 28)
|
BOOST_CLASS_VERSION(tools::wallet2, 28)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 11)
|
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 12)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
|
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
|
BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::multisig_tx_set, 1)
|
BOOST_CLASS_VERSION(tools::wallet2::multisig_tx_set, 1)
|
||||||
@ -1544,6 +1555,10 @@ namespace boost
|
|||||||
{
|
{
|
||||||
x.m_key_image_request = false;
|
x.m_key_image_request = false;
|
||||||
}
|
}
|
||||||
|
if (ver < 12)
|
||||||
|
{
|
||||||
|
x.m_frozen = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
@ -1632,8 +1647,17 @@ namespace boost
|
|||||||
}
|
}
|
||||||
a & x.m_key_image_request;
|
a & x.m_key_image_request;
|
||||||
if (ver < 11)
|
if (ver < 11)
|
||||||
|
{
|
||||||
|
initialize_transfer_details(a, x, ver);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
a & x.m_uses;
|
a & x.m_uses;
|
||||||
|
if (ver < 12)
|
||||||
|
{
|
||||||
|
initialize_transfer_details(a, x, ver);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
a & x.m_frozen;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
|
Loading…
Reference in New Issue
Block a user