-
Notifications
You must be signed in to change notification settings - Fork 37.8k
wallet: Move fee underpayment check to after all fee has been set #26643
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
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
src/wallet/spend.cpp
Outdated
@@ -952,19 +958,6 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal( | |||
CAmount fee_needed = coin_selection_params.m_effective_feerate.GetFee(nBytes); | |||
CAmount current_fee = result->GetSelectedValue() - recipients_sum - change_amount; |
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.
Should we define it the same way as down below?
-CAmount current_fee = result->GetSelectedValue() - recipients_sum - change_amount;
+CAmount current_fee = result->GetSelectedValue() - CalculateOutputValue(txNew);
src/wallet/spend.cpp
Outdated
@@ -756,6 +757,11 @@ static void DiscourageFeeSniping(CMutableTransaction& tx, FastRandomContext& rng | |||
} | |||
} | |||
|
|||
static CAmount CalculateOutputValue(const CMutableTransaction& tx) |
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.
Have you considered making it a member of CMutableTransaction
?
nFeeRet represents the fee that the transaction currently pays. Update it's name to reflect that.
6e73768
to
212e149
Compare
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.
ACK 212e149
// Reduce output values for subtractFeeFromAmount | ||
if (coin_selection_params.m_subtract_fee_outputs) { | ||
CAmount to_reduce = fee_needed - nFeeRet; | ||
CAmount to_reduce = fee_needed - current_fee; |
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.
This is probably too much but.. could fee_needed
be lower than current_fee
?
Because.. if that happens, to_reduce
will be negative so instead of reducing value from the outputs, we would be adding it.
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.
Yes, with a sufficiently large change output script and feerate, this is possible, and (currently) expected behavior. We test for it at spend_tests.cpp:61.
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.
Interesting. That is the opposite to what someone would expect from a functionality called "subtract fee from outputs".
but.. all good anyway, something for later.
212e149
to
1f6b0fa
Compare
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.
There is something that is making some noise inside me.
Based on the convo that we had above #26643 (comment).
Inside 8c8e173, you moved the change output increment due a fees overpay below the SFFO functionality. So, now if there is a fee surplus, instead of adding it to the change output first, we will add it to the recipients amount if SFFO is enabled.
(if there is an extra fee, "fee needed" will be lower than "current fee" so the SFFO to_reduce
amount will be negative, so instead of subtract the amount we will add it to the recipients amount. Sending more coins than what the user specified to send to each SFFO enabled output instead of sending them back to us in the change output).
Should create a test for this (the current SubtractFee
tests aren't contemplating change). It smells bad.
It doesn't make sense to be checking whether the fee paid is underpaying before we've finished setting the fees. So do that after we have done the reduction for SFFO and change adjustment for fee overpayment.
We need to check that the fee is not negative even before it is finalized. The setting of fees for SFFO may adjust the fee to be "correct" and no longer negative, but erroneously reduce the amounts too far. So we need to check this condition before we do those adjustments.
1f6b0fa
to
798430d
Compare
I've flipped it back around so the order stays the same. However, I don't think the scenario you describe is even at all possible. The only times that |
ok great, thanks. The noice is no longer there.
In that case, what about |
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 798430d
Code review ACK 798430d |
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.
utACK 798430d, code looks correct to me
… fee has been set 798430d wallet: Sanity check fee paid cannot be negative (Andrew Chow) c1a84f1 wallet: Move fee underpayment check to after fee setting (Andrew Chow) e5daf97 wallet: Rename nFeeRet in CreateTransactionInternal to current_fee (Andrew Chow) Pull request description: Currently the fee underpayment check occurs right after we calculate what the transaction's fee should be. However the fee paid by the transaction at that time does not always match. Notably, when doing SFFO, the fee paid at that time will almost always be less than the fee required, which then required having a bypass of the underpayment check that results in SFFO payments going through when they should not. This PR moves the underpayment check to after fees have been finalized so that we always check whether the fee is being underpaid. This removes the exception for SFFO and unifies this behavior for both SFFO and non-SFFO txs. ACKs for top commit: S3RK: Code review ACK 798430d furszy: Code review ACK 798430d glozow: utACK 798430d, code looks correct to me Tree-SHA512: 720e8a3dbdc9937b12ee7881eb2ad58332c9584520da87ef3080e6f9d6220ce8d3bd8b9317b4877e56a229113437340852976db8f64df0d5cc50723fa04b02f0
Currently the fee underpayment check occurs right after we calculate what the transaction's fee should be. However the fee paid by the transaction at that time does not always match. Notably, when doing SFFO, the fee paid at that time will almost always be less than the fee required, which then required having a bypass of the underpayment check that results in SFFO payments going through when they should not.
This PR moves the underpayment check to after fees have been finalized so that we always check whether the fee is being underpaid. This removes the exception for SFFO and unifies this behavior for both SFFO and non-SFFO txs.