-
Notifications
You must be signed in to change notification settings - Fork 37.7k
wallet: Allow negative effective value inputs when subtracting fee from outputs #23534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
05ef67a
to
c351e53
Compare
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsNo conflicts as of last run. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK c351e53
Checked that the new test fails on current master but passes with this PR.
Concept ACK. Did a light code review and I think it's better to drop the first commit as it's not required to fix the linked bug. If you'd like to keep it, I'd suggest to make inclusion/exclusion of the change fee explicit when stetting targets for coinselection algorithms, rather than implicit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some nits below
ACK c351e53 |
concept ACK, if someone wants to do "send max value possible" we could support this as another option and choose positive only groups again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tACK c351e53
Verified that the test fails in master.
Though I am thinking, the problem of negative ev utxos are only relevant for sweeping transactions with fundrawtransaction
rpc (there are other ways to create sweeps). Does this warrant removing negative ev for all cases with subtract_fee_outputs
? Maybe we can have a more sweeping focused approach to trigger BnB?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But this solution means you will end up with less bitcoins on the receiving end, doesn't it? Users probably would prefer the higher amount received.
I suppose the best UX would be to either ignore the net-negative UTXOs and simply send less than the requested amount. But that is apt to unprovably "burn" the dust unless we can somehow publish the dust private keys for others to sweep (but that seems dangerous and potentially ties to some centralised publisher).
Second-best might be to effectively reduce the fee rate by simply refusing to pay more for these UTXOs than they're worth. But care is needed to ensure the user is aware of this and transactions don't get stuck.
Also, any of this should only occur when trying to send the entire balance I think?
Yes.
I'm not sure. Subtract fee from outputs has always been "X amount leaves the wallet", so I think having less than that leave would be surprising?
Negative EV UTXOs can become positive if the feerate were to drop (assuming it was high).
I think that might be dangerous, and surprising to users.
I think it is reasonable for this to occur for all subtract fee from outputs sends. Maybe it should try positive only first, and if that fails, allow negative? |
c351e53
to
b9af533
Compare
b9af533
to
f44c3ce
Compare
ACK f44c3ce |
Nit: typo in the PR title "negtive" (may make it harder to find later) I typically use the "subtract fee" feature in combination with manual coin selection (for which this PR has no effect). That's different from the use case of emptying out a wallet. At minimum the RPC docs should warn that this will spend negative net value coins. The GUI should also warn, preferably only when this is actually the case. It can get quite expensive if a wallet has lots of dust. The first commit is worth its own PR if this doesn't make it. |
Sometimes subtractFeeFromOutputs requires spending negative ev UTXOs (e.g. when sweeping an entire wallet). If we are unable to find any solutions normally, then try again but this time allowing negative ev UTXOs.
When subtracting fee from outputs, it should be okay to spend negative ev UTXOs because the recipient is paying for it.
f44c3ce
to
a26a64c
Compare
I've changed this to try negative EVs if there are no solutions with the normal groupings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK a26a64c
Haven't re-verified test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good change to simplify the behavior difference
reACK a26a64c
@@ -403,6 +403,20 @@ std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAm | |||
results.push_back(*srd_result); | |||
} | |||
|
|||
// If we didn't find any solutions, and are subtracting the fee from the outputs, we may need to include negative effective value coins. | |||
// So try BnB and SRD again with all_groups. | |||
// It is safe to do this because a solution including negative EVs will have a greater waste. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about just throwing these two selections into the mix unconditionally? Would that be correct? Efficiency aside.
bnb_result->ComputeAndSetWaste(CAmount(0)); | ||
results.push_back(*bnb_result); | ||
} | ||
if (auto srd_result{SelectCoinsSRD(all_groups, srd_target)}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might this trigger the Assume(group.GetSelectionAmount() > 0)
statement in SelectCoinsSRD()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(also note the comment on the declaration for SelectCoinsSRD()
in coinselection.h states that it expects positive ev groups, might need to change that)
I already mentioned this in person, but I find that "subtract fee" leads to unintuitive behavior, especially in the context of sweeping (and makes all tests a lot more complicated). It would make more sense to me that the wallet never spends UTXOs with negative effective value unless explicitly tasked to do so, since it just costs users (either sender or receiver) more fees and more blockspace for the debatable reason of not leaving any UTXOs behind. The main use-case where I see "subtract fee from recipient" making sense, is in the context of Coin Control, when the sender picks the inputs explicitly and doesn't want to calculate the appropriate fee manually. Especially in the case of sweeping, I agree with Luke, that the user should prefer getting more money over using all UTXOs. If they sweep at |
Could you maybe illustrate what the unintuitive behavior is with an example? The rest of your comment about "user should get more money by default" obviously sounds good if it doesn't have other tradeoffs. |
And that scenario could be considered sweeping as well. Sweeping can be generalized to "spend UTXOs XYZ fully with all value going to one output" where XYZ could be all UTXOs in the wallet, or a preset input list.
I think it is unintuitive and not very good UX to not spend uneconomical UTXOs in a sweep. I think that users would expect a sweep function to spend all UTXOs regardless, and it would be surprising if sweeping a wallet left behind any balance, even uneconomical.
I'm not sure about unintuitive, but subtractFeeFromOutputs definitely causes a lot of headaches in coin selection code, so getting rid of it would greatly simplify a lot of it. It would certainly make the logic much easier to follow. For some historical context, #5831 added subtractFeeFromAmount (which was a rebase of #4331) and that points to 2 issues where the proposed use case is sweeping. |
Closing this in favor of introducing sendall to solve the problem. |
Often the goal with subtracting fee from outputs is to sweep an entire wallet's balance. As such, it is reasonable to allow negative effective value UTXOs as inputs as otherwise the target value (the balance) cannot be reached. However this is not always desirable as there may be solutions with only positive EV UTXOs, so we only try with negative EV UTXOs if we are unable to find any solutions with the normal groupings.
Fixes #23026