|
|
|
@ -1543,6 +1543,7 @@ bool wallet2::is_deprecated() const
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
void wallet2::set_spent(size_t idx, uint64_t height)
|
|
|
|
|
{
|
|
|
|
|
CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid index");
|
|
|
|
|
transfer_details &td = m_transfers[idx];
|
|
|
|
|
LOG_PRINT_L2("Setting SPENT at " << height << ": ki " << td.m_key_image << ", amount " << print_money(td.m_amount));
|
|
|
|
|
td.m_spent = true;
|
|
|
|
@ -1551,12 +1552,32 @@ void wallet2::set_spent(size_t idx, uint64_t height)
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
void wallet2::set_unspent(size_t idx)
|
|
|
|
|
{
|
|
|
|
|
CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid index");
|
|
|
|
|
transfer_details &td = m_transfers[idx];
|
|
|
|
|
LOG_PRINT_L2("Setting UNSPENT: ki " << td.m_key_image << ", amount " << print_money(td.m_amount));
|
|
|
|
|
td.m_spent = false;
|
|
|
|
|
td.m_spent_height = 0;
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
bool wallet2::is_spent(const transfer_details &td, bool strict) const
|
|
|
|
|
{
|
|
|
|
|
if (strict)
|
|
|
|
|
{
|
|
|
|
|
return td.m_spent && td.m_spent_height > 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return td.m_spent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
bool wallet2::is_spent(size_t idx, bool strict) const
|
|
|
|
|
{
|
|
|
|
|
CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid index");
|
|
|
|
|
const transfer_details &td = m_transfers[idx];
|
|
|
|
|
return is_spent(td, strict);
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
void wallet2::freeze(size_t idx)
|
|
|
|
|
{
|
|
|
|
|
CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid transfer_details index");
|
|
|
|
@ -3294,7 +3315,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
|
|
|
|
|
|
|
|
|
|
m_first_refresh_done = true;
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all()) << ", unlocked: " << print_money(unlocked_balance_all()));
|
|
|
|
|
LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all(false)) << ", unlocked: " << print_money(unlocked_balance_all(false)));
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
bool wallet2::refresh(bool trusted_daemon, uint64_t & blocks_fetched, bool& received_money, bool& ok)
|
|
|
|
@ -5594,24 +5615,24 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
uint64_t wallet2::balance(uint32_t index_major) const
|
|
|
|
|
uint64_t wallet2::balance(uint32_t index_major, bool strict) const
|
|
|
|
|
{
|
|
|
|
|
uint64_t amount = 0;
|
|
|
|
|
if(m_light_wallet)
|
|
|
|
|
return m_light_wallet_unlocked_balance;
|
|
|
|
|
for (const auto& i : balance_per_subaddress(index_major))
|
|
|
|
|
for (const auto& i : balance_per_subaddress(index_major, strict))
|
|
|
|
|
amount += i.second;
|
|
|
|
|
return amount;
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
uint64_t wallet2::unlocked_balance(uint32_t index_major, uint64_t *blocks_to_unlock) const
|
|
|
|
|
uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *blocks_to_unlock) const
|
|
|
|
|
{
|
|
|
|
|
uint64_t amount = 0;
|
|
|
|
|
if (blocks_to_unlock)
|
|
|
|
|
*blocks_to_unlock = 0;
|
|
|
|
|
if(m_light_wallet)
|
|
|
|
|
return m_light_wallet_balance;
|
|
|
|
|
for (const auto& i : unlocked_balance_per_subaddress(index_major))
|
|
|
|
|
for (const auto& i : unlocked_balance_per_subaddress(index_major, strict))
|
|
|
|
|
{
|
|
|
|
|
amount += i.second.first;
|
|
|
|
|
if (blocks_to_unlock && i.second.second > *blocks_to_unlock)
|
|
|
|
@ -5620,12 +5641,12 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, uint64_t *blocks_to_unl
|
|
|
|
|
return amount;
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_major) const
|
|
|
|
|
std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_major, bool strict) const
|
|
|
|
|
{
|
|
|
|
|
std::map<uint32_t, uint64_t> amount_per_subaddr;
|
|
|
|
|
for (const auto& td: m_transfers)
|
|
|
|
|
{
|
|
|
|
|
if (td.m_subaddr_index.major == index_major && !td.m_spent && !td.m_frozen)
|
|
|
|
|
if (td.m_subaddr_index.major == index_major && !is_spent(td, strict) && !td.m_frozen)
|
|
|
|
|
{
|
|
|
|
|
auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
|
|
|
|
|
if (found == amount_per_subaddr.end())
|
|
|
|
@ -5634,8 +5655,10 @@ std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_majo
|
|
|
|
|
found->second += td.amount();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (const auto& utx: m_unconfirmed_txs)
|
|
|
|
|
if (!strict)
|
|
|
|
|
{
|
|
|
|
|
for (const auto& utx: m_unconfirmed_txs)
|
|
|
|
|
{
|
|
|
|
|
if (utx.second.m_subaddr_account == index_major && utx.second.m_state != wallet2::unconfirmed_transfer_details::failed)
|
|
|
|
|
{
|
|
|
|
|
// all changes go to 0-th subaddress (in the current subaddress account)
|
|
|
|
@ -5645,17 +5668,18 @@ std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_majo
|
|
|
|
|
else
|
|
|
|
|
found->second += utx.second.m_change;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return amount_per_subaddr;
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
std::map<uint32_t, std::pair<uint64_t, uint64_t>> wallet2::unlocked_balance_per_subaddress(uint32_t index_major) const
|
|
|
|
|
std::map<uint32_t, std::pair<uint64_t, uint64_t>> wallet2::unlocked_balance_per_subaddress(uint32_t index_major, bool strict) const
|
|
|
|
|
{
|
|
|
|
|
std::map<uint32_t, std::pair<uint64_t, uint64_t>> amount_per_subaddr;
|
|
|
|
|
const uint64_t blockchain_height = get_blockchain_current_height();
|
|
|
|
|
for(const transfer_details& td: m_transfers)
|
|
|
|
|
{
|
|
|
|
|
if(td.m_subaddr_index.major == index_major && !td.m_spent && !td.m_frozen)
|
|
|
|
|
if(td.m_subaddr_index.major == index_major && !is_spent(td, strict) && !td.m_frozen)
|
|
|
|
|
{
|
|
|
|
|
uint64_t amount = 0, blocks_to_unlock = 0;
|
|
|
|
|
if (is_transfer_unlocked(td))
|
|
|
|
@ -5684,15 +5708,15 @@ std::map<uint32_t, std::pair<uint64_t, uint64_t>> wallet2::unlocked_balance_per_
|
|
|
|
|
return amount_per_subaddr;
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
uint64_t wallet2::balance_all() const
|
|
|
|
|
uint64_t wallet2::balance_all(bool strict) const
|
|
|
|
|
{
|
|
|
|
|
uint64_t r = 0;
|
|
|
|
|
for (uint32_t index_major = 0; index_major < get_num_subaddress_accounts(); ++index_major)
|
|
|
|
|
r += balance(index_major);
|
|
|
|
|
r += balance(index_major, strict);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
uint64_t wallet2::unlocked_balance_all(uint64_t *blocks_to_unlock) const
|
|
|
|
|
uint64_t wallet2::unlocked_balance_all(bool strict, uint64_t *blocks_to_unlock) const
|
|
|
|
|
{
|
|
|
|
|
uint64_t r = 0;
|
|
|
|
|
if (blocks_to_unlock)
|
|
|
|
@ -5700,7 +5724,7 @@ uint64_t wallet2::unlocked_balance_all(uint64_t *blocks_to_unlock) const
|
|
|
|
|
for (uint32_t index_major = 0; index_major < get_num_subaddress_accounts(); ++index_major)
|
|
|
|
|
{
|
|
|
|
|
uint64_t local_blocks_to_unlock;
|
|
|
|
|
r += unlocked_balance(index_major, blocks_to_unlock ? &local_blocks_to_unlock : NULL);
|
|
|
|
|
r += unlocked_balance(index_major, strict, blocks_to_unlock ? &local_blocks_to_unlock : NULL);
|
|
|
|
|
if (blocks_to_unlock)
|
|
|
|
|
*blocks_to_unlock = std::max(*blocks_to_unlock, local_blocks_to_unlock);
|
|
|
|
|
}
|
|
|
|
@ -6177,8 +6201,8 @@ void wallet2::commit_tx(pending_tx& ptx)
|
|
|
|
|
//fee includes dust if dust policy specified it.
|
|
|
|
|
LOG_PRINT_L1("Transaction successfully sent. <" << txid << ">" << ENDL
|
|
|
|
|
<< "Commission: " << print_money(ptx.fee) << " (dust sent to dust addr: " << print_money((ptx.dust_added_to_fee ? 0 : ptx.dust)) << ")" << ENDL
|
|
|
|
|
<< "Balance: " << print_money(balance(ptx.construction_data.subaddr_account)) << ENDL
|
|
|
|
|
<< "Unlocked: " << print_money(unlocked_balance(ptx.construction_data.subaddr_account)) << ENDL
|
|
|
|
|
<< "Balance: " << print_money(balance(ptx.construction_data.subaddr_account, false)) << ENDL
|
|
|
|
|
<< "Unlocked: " << print_money(unlocked_balance(ptx.construction_data.subaddr_account, false)) << ENDL
|
|
|
|
|
<< "Please, wait for confirmation for your balance to be unlocked.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -8559,7 +8583,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)
|
|
|
|
|
{
|
|
|
|
|
const transfer_details& td = m_transfers[i];
|
|
|
|
|
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)
|
|
|
|
|
if (!is_spent(td, false) && !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()));
|
|
|
|
|
picks.push_back(i);
|
|
|
|
@ -8574,13 +8598,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)
|
|
|
|
|
{
|
|
|
|
|
const transfer_details& td = m_transfers[i];
|
|
|
|
|
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)
|
|
|
|
|
if (!is_spent(td, false) && !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()));
|
|
|
|
|
for (size_t j = i + 1; j < m_transfers.size(); ++j)
|
|
|
|
|
{
|
|
|
|
|
const transfer_details& td2 = m_transfers[j];
|
|
|
|
|
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)
|
|
|
|
|
if (!is_spent(td2, false) && !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
|
|
|
|
|
// already found. If the same, don't update, and oldest suitable outputs
|
|
|
|
@ -9235,8 +9259,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|
|
|
|
// throw if attempting a transaction with no money
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(needed_money == 0, error::zero_destination);
|
|
|
|
|
|
|
|
|
|
std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account);
|
|
|
|
|
std::map<uint32_t, uint64_t> balance_per_subaddr = balance_per_subaddress(subaddr_account);
|
|
|
|
|
std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account, false);
|
|
|
|
|
std::map<uint32_t, uint64_t> balance_per_subaddr = balance_per_subaddress(subaddr_account, false);
|
|
|
|
|
|
|
|
|
|
if (subaddr_indices.empty()) // "index=<N1>[,<N2>,...]" wasn't specified -> use all the indices with non-zero unlocked balance
|
|
|
|
|
{
|
|
|
|
@ -9282,7 +9306,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));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
if (!is_spent(td, false) && !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;
|
|
|
|
|
auto find_predicate = [&index_minor](const std::pair<uint32_t, std::vector<size_t>>& x) { return x.first == index_minor; };
|
|
|
|
@ -9409,7 +9433,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|
|
|
|
// if we need to spend money and don't have any left, we fail
|
|
|
|
|
if (unused_dust_indices->empty() && unused_transfers_indices->empty()) {
|
|
|
|
|
LOG_PRINT_L2("No more outputs to choose from");
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account), needed_money, accumulated_fee + needed_fee);
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account, false), needed_money, accumulated_fee + needed_fee);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get a random unspent output and use it to pay part (or all) of the current destination (and maybe next one, etc)
|
|
|
|
@ -9627,7 +9651,7 @@ skip_tx:
|
|
|
|
|
if (adding_fee)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("We ran out of outputs while trying to gather final fee");
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account), needed_money, accumulated_fee + needed_fee);
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account, false), needed_money, accumulated_fee + needed_fee);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) <<
|
|
|
|
@ -9762,7 +9786,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
|
|
|
|
std::vector<size_t> unused_dust_indices;
|
|
|
|
|
const bool use_rct = use_fork_rules(4, 0);
|
|
|
|
|
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account) == 0, error::wallet_internal_error, "No unlocked balance in the entire wallet");
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account, false) == 0, error::wallet_internal_error, "No unlocked balance in the entire wallet");
|
|
|
|
|
|
|
|
|
|
std::map<uint32_t, std::pair<std::vector<size_t>, std::vector<size_t>>> unused_transfer_dust_indices_per_subaddr;
|
|
|
|
|
|
|
|
|
@ -9771,7 +9795,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
|
|
|
|
for (size_t i = 0; i < m_transfers.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
const transfer_details& td = m_transfers[i];
|
|
|
|
|
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))
|
|
|
|
|
if (!is_spent(td, false) && !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;
|
|
|
|
|
if (below == 0 || td.amount() < below)
|
|
|
|
@ -9819,7 +9843,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
|
|
|
|
|
for (size_t i = 0; i < m_transfers.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
const transfer_details& td = m_transfers[i];
|
|
|
|
|
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.m_key_image_known && td.m_key_image == ki && !is_spent(td, false) && !td.m_frozen && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td))
|
|
|
|
|
{
|
|
|
|
|
if (td.is_rct() || is_valid_decomposed_amount(td.amount()))
|
|
|
|
|
unused_transfers_indices.push_back(i);
|
|
|
|
@ -10185,7 +10209,7 @@ std::vector<size_t> wallet2::select_available_outputs(const std::function<bool(c
|
|
|
|
|
size_t n = 0;
|
|
|
|
|
for (transfer_container::const_iterator i = m_transfers.begin(); i != m_transfers.end(); ++i, ++n)
|
|
|
|
|
{
|
|
|
|
|
if (i->m_spent)
|
|
|
|
|
if (is_spent(*i, false))
|
|
|
|
|
continue;
|
|
|
|
|
if (i->m_frozen)
|
|
|
|
|
continue;
|
|
|
|
@ -10199,12 +10223,12 @@ std::vector<size_t> wallet2::select_available_outputs(const std::function<bool(c
|
|
|
|
|
return outputs;
|
|
|
|
|
}
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
|
|
|
std::vector<uint64_t> wallet2::get_unspent_amounts_vector() const
|
|
|
|
|
std::vector<uint64_t> wallet2::get_unspent_amounts_vector(bool strict) const
|
|
|
|
|
{
|
|
|
|
|
std::set<uint64_t> set;
|
|
|
|
|
for (const auto &td: m_transfers)
|
|
|
|
|
{
|
|
|
|
|
if (!td.m_spent && !td.m_frozen)
|
|
|
|
|
if (!is_spent(td, strict) && !td.m_frozen)
|
|
|
|
|
set.insert(td.is_rct() ? 0 : td.amount());
|
|
|
|
|
}
|
|
|
|
|
std::vector<uint64_t> vector;
|
|
|
|
@ -10222,7 +10246,7 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co
|
|
|
|
|
cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response resp_t = AUTO_VAL_INIT(resp_t);
|
|
|
|
|
m_daemon_rpc_mutex.lock();
|
|
|
|
|
if (is_trusted_daemon())
|
|
|
|
|
req_t.amounts = get_unspent_amounts_vector();
|
|
|
|
|
req_t.amounts = get_unspent_amounts_vector(false);
|
|
|
|
|
req_t.min_count = count;
|
|
|
|
|
req_t.max_count = 0;
|
|
|
|
|
req_t.unlocked = unlocked;
|
|
|
|
@ -11120,8 +11144,8 @@ bool wallet2::check_tx_proof(const cryptonote::transaction &tx, const cryptonote
|
|
|
|
|
std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t, uint64_t>> &account_minreserve, const std::string &message)
|
|
|
|
|
{
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(m_watch_only || m_multisig, error::wallet_internal_error, "Reserve proof can only be generated by a full wallet");
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(balance_all() == 0, error::wallet_internal_error, "Zero balance");
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(account_minreserve && balance(account_minreserve->first) < account_minreserve->second, error::wallet_internal_error,
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(balance_all(true) == 0, error::wallet_internal_error, "Zero balance");
|
|
|
|
|
THROW_WALLET_EXCEPTION_IF(account_minreserve && balance(account_minreserve->first, true) < account_minreserve->second, error::wallet_internal_error,
|
|
|
|
|
"Not enough balance in this account for the requested minimum reserve amount");
|
|
|
|
|
|
|
|
|
|
// determine which outputs to include in the proof
|
|
|
|
@ -11129,7 +11153,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
|
|
|
|
|
for (size_t i = 0; i < m_transfers.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
const transfer_details &td = m_transfers[i];
|
|
|
|
|
if (!td.m_spent && !td.m_frozen && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major))
|
|
|
|
|
if (!is_spent(td, true) && !td.m_frozen && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major))
|
|
|
|
|
selected_transfers.push_back(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|