wallet: add number of blocks required for the balance to fully unlock

This commit is contained in:
moneromooo-monero
2019-04-01 19:31:19 +00:00
parent 3f1e9e84c0
commit c12b43cb5a
5 changed files with 64 additions and 23 deletions
+43 -12
View File
@@ -5430,13 +5430,19 @@ uint64_t wallet2::balance(uint32_t index_major) const
return amount;
}
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::unlocked_balance(uint32_t index_major) const
uint64_t wallet2::unlocked_balance(uint32_t index_major, 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))
amount += i.second;
{
amount += i.second.first;
if (blocks_to_unlock && i.second.second > *blocks_to_unlock)
*blocks_to_unlock = i.second.second;
}
return amount;
}
//----------------------------------------------------------------------------------------------------
@@ -5469,18 +5475,36 @@ std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_majo
return amount_per_subaddr;
}
//----------------------------------------------------------------------------------------------------
std::map<uint32_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) const
{
std::map<uint32_t, uint64_t> amount_per_subaddr;
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 && is_transfer_unlocked(td))
if(td.m_subaddr_index.major == index_major && !td.m_spent && !td.m_frozen)
{
uint64_t amount = 0, blocks_to_unlock = 0;
if (is_transfer_unlocked(td))
{
amount = td.amount();
blocks_to_unlock = 0;
}
else
{
uint64_t unlock_height = td.m_block_height + std::max<uint64_t>(CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS);
if (td.m_tx.unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER && td.m_tx.unlock_time > unlock_height)
unlock_height = td.m_tx.unlock_time;
blocks_to_unlock = unlock_height > blockchain_height ? unlock_height - blockchain_height : 0;
amount = 0;
}
auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
if (found == amount_per_subaddr.end())
amount_per_subaddr[td.m_subaddr_index.minor] = td.amount();
amount_per_subaddr[td.m_subaddr_index.minor] = std::make_pair(amount, blocks_to_unlock);
else
found->second += td.amount();
{
found->second.first += amount;
found->second.second = std::max(found->second.second, blocks_to_unlock);
}
}
}
return amount_per_subaddr;
@@ -5494,11 +5518,18 @@ uint64_t wallet2::balance_all() const
return r;
}
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::unlocked_balance_all() const
uint64_t wallet2::unlocked_balance_all(uint64_t *blocks_to_unlock) const
{
uint64_t r = 0;
if (blocks_to_unlock)
*blocks_to_unlock = 0;
for (uint32_t index_major = 0; index_major < get_num_subaddress_accounts(); ++index_major)
r += unlocked_balance(index_major);
{
uint64_t local_blocks_to_unlock;
r += unlocked_balance(index_major, blocks_to_unlock ? &local_blocks_to_unlock : NULL);
if (blocks_to_unlock)
*blocks_to_unlock = std::max(*blocks_to_unlock, local_blocks_to_unlock);
}
return r;
}
//----------------------------------------------------------------------------------------------------
@@ -9044,7 +9075,7 @@ 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, uint64_t> unlocked_balance_per_subaddr = unlocked_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);
std::map<uint32_t, uint64_t> balance_per_subaddr = balance_per_subaddress(subaddr_account);
if (subaddr_indices.empty()) // "index=<N1>[,<N2>,...]" wasn't specified -> use all the indices with non-zero unlocked balance
@@ -9062,7 +9093,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
for (uint32_t index_minor : subaddr_indices)
{
balance_subtotal += balance_per_subaddr[index_minor];
unlocked_balance_subtotal += unlocked_balance_per_subaddr[index_minor];
unlocked_balance_subtotal += unlocked_balance_per_subaddr[index_minor].first;
}
THROW_WALLET_EXCEPTION_IF(needed_money + min_fee > balance_subtotal, error::not_enough_money,
balance_subtotal, needed_money, 0);
@@ -9128,7 +9159,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
{
auto sort_predicate = [&unlocked_balance_per_subaddr] (const std::pair<uint32_t, std::vector<size_t>>& x, const std::pair<uint32_t, std::vector<size_t>>& y)
{
return unlocked_balance_per_subaddr[x.first] > unlocked_balance_per_subaddr[y.first];
return unlocked_balance_per_subaddr[x.first].first > unlocked_balance_per_subaddr[y.first].first;
};
std::sort(unused_transfers_indices_per_subaddr.begin(), unused_transfers_indices_per_subaddr.end(), sort_predicate);
std::sort(unused_dust_indices_per_subaddr.begin(), unused_dust_indices_per_subaddr.end(), sort_predicate);