wallet: don't return utxos from multiple truc txs in AvailableCoins

This commit is contained in:
ishaanam
2025-08-12 14:41:53 -04:00
parent da8748ad62
commit c5a2d08011

View File

@@ -325,6 +325,9 @@ CoinsResult AvailableCoins(const CWallet& wallet,
AssertLockHeld(wallet.cs_wallet);
CoinsResult result;
// track unconfirmed truc outputs separately if we are tracking trucness
std::vector<std::pair<OutputType, COutput>> unconfirmed_truc_coins;
std::unordered_map<Txid, CAmount, SaltedTxidHasher> truc_txid_by_value;
// Either the WALLET_FLAG_AVOID_REUSE flag is not set (in which case we always allow), or we default to avoiding, and only in the case where
// a coin control object is provided, and has the avoid address reuse flag set to false, do we allow already used addresses
bool allow_used_addresses = !wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE) || (coinControl && !coinControl->m_avoid_address_reuse);
@@ -470,8 +473,15 @@ CoinsResult AvailableCoins(const CWallet& wallet,
is_from_p2sh = true;
}
result.Add(GetOutputType(type, is_from_p2sh),
COutput(outpoint, output, nDepth, input_bytes, spendable, solvable, tx_safe, wtx.GetTxTime(), tx_from_me, feerate));
auto available_output_type = GetOutputType(type, is_from_p2sh);
auto available_output = COutput(outpoint, output, nDepth, input_bytes, spendable, solvable, tx_safe, wtx.GetTxTime(), tx_from_me, feerate);
if (wtx.tx->version == TRUC_VERSION && nDepth == 0 && params.check_version_trucness) {
unconfirmed_truc_coins.emplace_back(available_output_type, available_output);
auto [it, _] = truc_txid_by_value.try_emplace(wtx.tx->GetHash(), 0);
it->second += output.nValue;
} else {
result.Add(available_output_type, available_output);
}
outpoints.push_back(outpoint);
@@ -488,6 +498,23 @@ CoinsResult AvailableCoins(const CWallet& wallet,
}
}
// Return all the coins from one TRUC transaction, that have the highest value.
// This could be improved in the future by encoding these restrictions in
// the coin selection itself so that we don't have to filter out
// other unconfirmed TRUC coins beforehand.
if (params.check_version_trucness && unconfirmed_truc_coins.size() > 0) {
auto highest_value_truc_tx = std::max_element(truc_txid_by_value.begin(), truc_txid_by_value.end(), [](const auto& tx1, const auto& tx2){
return tx1.second < tx2.second;
});
const Txid& truc_txid = highest_value_truc_tx->first;
for (const auto& [type, output] : unconfirmed_truc_coins) {
if (output.outpoint.hash == truc_txid) {
result.Add(type, output);
}
}
}
if (feerate.has_value()) {
std::map<COutPoint, CAmount> map_of_bump_fees = wallet.chain().calculateIndividualBumpFees(outpoints, feerate.value());