bumpfee: enable send coins back to yourself

Simple example:

1) User_1 sends 0.1 btc to user_2 on a low fee transaction.
2) After few hours, the tx is still in the mempool, user_2
   is not interested anymore, so user_1 decides to cancel
   it by sending coins back to himself.
3) User_1 has the bright idea of opening the explorer and
   copy the change output address of the transaction. Then
   call bumpfee providing such output (in the "outputs" arg).

Currently, this is not possible. The wallet fails with
"Unable to create transaction. Transaction must have at least
one recipient" error.
The error reason is that we discard the provided output from
the recipients list and set it inside the coin control
so the process adds it later (when the change is calculated).
But.. there is no later if the tx has no outputs.
This commit is contained in:
furszy 2023-03-03 11:58:27 -03:00
parent b22c275582
commit 7bffec6715
No known key found for this signature in database
GPG Key ID: 5DD23CCC686AA623

View File

@ -231,6 +231,7 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
// is one). If outputs vector is non-empty, replace original
// outputs with its contents, otherwise use original outputs.
std::vector<CRecipient> recipients;
CAmount new_outputs_value = 0;
const auto& txouts = outputs.empty() ? wtx.tx->vout : outputs;
for (const auto& output : txouts) {
if (!OutputIsChange(wallet, output)) {
@ -241,6 +242,21 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
ExtractDestination(output.scriptPubKey, change_dest);
new_coin_control.destChange = change_dest;
}
new_outputs_value += output.nValue;
}
// If no recipients, means that we are sending coins to a change address
if (recipients.empty()) {
// Just as a sanity check, ensure that the change address exist
if (std::get_if<CNoDestination>(&new_coin_control.destChange)) {
errors.emplace_back(Untranslated("Unable to create transaction. Transaction must have at least one recipient"));
return Result::INVALID_PARAMETER;
}
// Add change as recipient with SFFO flag enabled, so fees are deduced from it.
// If the output differs from the original tx output (because the user customized it) a new change output will be created.
recipients.emplace_back(CRecipient{GetScriptForDestination(new_coin_control.destChange), new_outputs_value, /*fSubtractFeeFromAmount=*/true});
new_coin_control.destChange = CNoDestination();
}
if (coin_control.m_feerate) {