fix(wallet): reserve miner fee during z_sendmany note selection
The Sapling note-selection loop stopped once total_value >= nTotalOut, ignoring
the miner fee, so a wallet with notes covering the amount but not amount+fee
selected too few notes and failed later with a spurious "insufficient funds".
Reserve the fee (default or user-supplied) in the selection target.
Leto eb4fc52273.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -5298,6 +5298,12 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
|
||||
CAmount total_value = 0;
|
||||
|
||||
// correctness: reserve the miner fee during note selection so we don't stop at exactly nTotalOut
|
||||
// and then fail later with a spurious "insufficient funds". Mirrors the nFee computed below.
|
||||
CAmount nFeeReserve = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE;
|
||||
if (params.size() > 3)
|
||||
nFeeReserve = (params[3].get_real() == 0.0) ? 0 : AmountFromValue(params[3]);
|
||||
|
||||
std::vector<SendManyInputSaplingNote> saplingNoteInputs;
|
||||
// Decide which sapling notes will be spent
|
||||
for (const SaplingNoteEntry& entry : saplingEntries) {
|
||||
@@ -5309,8 +5315,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
saplingNoteInputs.emplace_back(entry.op, entry.note, nValue, extsk.expsk);
|
||||
total_value += nValue;
|
||||
LogPrintf("%s: adding note to spend with value=%s, total_value=%s\n", __func__, FormatMoney(nValue), FormatMoney(total_value) );
|
||||
if (total_value >= nTotalOut) {
|
||||
// we have enough note value to make the tx
|
||||
if (total_value >= nTotalOut + nFeeReserve) {
|
||||
// we have enough note value (incl. miner fee) to make the tx
|
||||
LogPrintf("%s: found enough notes, nTotalOut=%s total_value=%s\n", __func__, FormatMoney(nTotalOut), FormatMoney(total_value) );
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user