|
|
|
@ -1441,6 +1441,58 @@ void wallet2::set_unspent(size_t idx)
|
|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
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_rct = false;
|
|
|
|
|
}
|
|
|
|
|
td.m_frozen = false;
|
|
|
|
|
set_unspent(m_transfers.size()-1);
|
|
|
|
|
if (td.m_key_image_known)
|
|
|
|
|
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];
|
|
|
|
|
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);
|
|
|
|
|
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;
|
|
|
|
|
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);
|
|
|
|
|
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;
|
|
|
|
|
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);
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
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()));
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
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()));
|
|
|
|
|
for (size_t j = i + 1; j < m_transfers.size(); ++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
|
|
|
|
|
// 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_internal_output_index = o.index;
|
|
|
|
|
td.m_spent = spent;
|
|
|
|
|
td.m_frozen = false;
|
|
|
|
|
|
|
|
|
|
tx_out txout;
|
|
|
|
|
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));
|
|
|
|
|
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;
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
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()))
|
|
|
|
|
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)
|
|
|
|
|
continue;
|
|
|
|
|
if (i->m_frozen)
|
|
|
|
|
continue;
|
|
|
|
|
if (i->m_key_image_partial)
|
|
|
|
|
continue;
|
|
|
|
|
if (!is_transfer_unlocked(*i))
|
|
|
|
@ -9917,7 +9974,7 @@ std::vector<uint64_t> wallet2::get_unspent_amounts_vector() const
|
|
|
|
|
std::set<uint64_t> set;
|
|
|
|
|
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());
|
|
|
|
|
}
|
|
|
|
|
std::vector<uint64_t> vector;
|
|
|
|
@ -10043,7 +10100,7 @@ void wallet2::discard_unmixable_outputs()
|
|
|
|
|
std::vector<size_t> unmixable_outputs = select_available_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)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -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)
|
|
|
|
|
{
|
|
|
|
|
const transfer_details &td = m_transfers[i];
|
|
|
|
|
if (td.m_frozen)
|
|
|
|
|
continue;
|
|
|
|
|
uint64_t amount = td.amount();
|
|
|
|
|
if (td.m_spent)
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
const transfer_details &td = m_transfers[i + offset];
|
|
|
|
|
if (td.m_frozen)
|
|
|
|
|
continue;
|
|
|
|
|
uint64_t amount = td.amount();
|
|
|
|
|
if (td.m_spent)
|
|
|
|
|
spent += amount;
|
|
|
|
|