mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 07:31:35 +02:00
Merge pull request #11213
ba3884e wallet2: exclude outputs from an unconfirmed send in reserve proofs (Cole Munz)
ACKs: jpk68, selsta
This commit is contained in:
+14
-4
@@ -12558,22 +12558,32 @@ 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(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
|
||||
// is_spent(td, false) excludes an output already used as input to a pending, unconfirmed
|
||||
// send too, not just a confirmed one, so we don't claim reserve we no longer have
|
||||
std::vector<size_t> selected_transfers;
|
||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||
{
|
||||
const transfer_details &td = m_transfers[i];
|
||||
if (!is_spent(td, true) && !td.m_frozen && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major))
|
||||
if (!is_spent(td, false) && !td.m_frozen && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major))
|
||||
selected_transfers.push_back(i);
|
||||
}
|
||||
|
||||
// sum what's actually selected instead of calling balance_all()/balance(): those also fold
|
||||
// in pending change and self-transfer amounts from our own unconfirmed txs, which have no
|
||||
// matching entry in m_transfers yet and can leave a balance-based guard non-zero even once
|
||||
// every output backing it has been excluded above
|
||||
uint64_t available = 0;
|
||||
for (size_t idx : selected_transfers)
|
||||
available += m_transfers[idx].amount();
|
||||
THROW_WALLET_EXCEPTION_IF(available == 0, error::wallet_internal_error, "Zero balance");
|
||||
|
||||
if (account_minreserve)
|
||||
{
|
||||
THROW_WALLET_EXCEPTION_IF(account_minreserve->second == 0, error::wallet_internal_error, "Proved amount must be greater than 0");
|
||||
THROW_WALLET_EXCEPTION_IF(available < account_minreserve->second, error::wallet_internal_error,
|
||||
"Not enough balance in this account for the requested minimum reserve amount");
|
||||
// minimize the number of outputs included in the proof, by only picking the N largest outputs that can cover the requested min reserve amount
|
||||
std::sort(selected_transfers.begin(), selected_transfers.end(), [&](const size_t a, const size_t b)
|
||||
{ return m_transfers[a].amount() > m_transfers[b].amount(); });
|
||||
|
||||
Reference in New Issue
Block a user