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
Disable fee estimates for 1 block target #9239
Conversation
Concept ACK |
Concept ACK. Maybe we want to disable for 2 as well? |
@@ -175,7 +175,7 @@ void SendCoinsDialog::setModel(WalletModel *_model) | |||
// set the smartfee-sliders default value (wallets default conf.target or last stored value) | |||
QSettings settings; | |||
if (settings.value("nSmartFeeSliderPosition").toInt() == 0) | |||
ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - model->getDefaultConfirmTarget() + 1); |
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.
Don't we need to explicitly deal with the state where the nSmartFeeSliderPosition
(persisted position) is set to 1
?
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.
Wait, I mean where nSmartFeeSliderPosition
is 24
(=conf target 1).
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.
I don't think so. We already weren't bounds checking what was passed in as nTxConfirmTarget and it turns out that QT sliders make values fit between the min and max, so it just works...
It seems what is exorbitant is a matter of opinion, and it might make sense to allow users to choose it. But I don't care strongly about this. Another possibility is to only have it in the GUI when coin control is enabled, but that may not be worth the effort. |
Tested ACK e878689 |
@luke-jr Yeah it was hard to explain concisely in the PR description. It's not necessarily that the answer is a high fee rate, its that it seems to be the case that when it is a high fee rate, (e.g. 1000 sat/byte), that a much lower fee rate (say 100 sat/byte) is almost just as good an answer, maybe being included in a block 93% of the time instead of 95%. I think any dumb algorithm is always going to have edge cases that human inspection will indicate aren't the best answer, and we can't go chase them all down, and just add more rules to try to deal with them. However in this case, from the very inception of the algorithm we knew that setting a very high confirmation target (95%) for the first block would be problematic if for no other reason that you would see some amount of transactions that miners hadn't even seen yet when they created the block just due to timing differences. This was the reason the original target was 85%, hopefully low enough that we'd get decent answer for 1 confirmation. Then we changed the target to 95% to make the algorithm more responsive to changes in market conditions, and I should have thought more at the time how the persistent flakiness of answers at a block target of 1 would be confusing to users. I do think its possible a future improvement may give better answers for a target of 1, but I'd rather get this small change out there now. |
Not really, I've observed returning values that were 5x higher than the highest feerate transaction in the mempool in the brief window before and long after. That is objectively too high. A somewhat different approach is probably needed for estimatefee 1-- including ignoring transactions which arrived too soon before the block, clamping it based on mempool observations, etc. utACK. |
@@ -423,6 +424,10 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun | |||
if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms()) | |||
return CFeeRate(0); | |||
|
|||
// It's not possible to get reasonable estimates for confTarget of 1 | |||
if (confTarget == 1) |
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.
maybe an assert or an exception would be better here?
EDIT: or return CFeeRate(0) like in CBlockPolicyEstimator::estimateFee
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.
@jtimon I wanted to leave the external behavior essentially unchanged. For estimatefee, it often returned -1, so making it always do that would not be unexpected. It would be very unexpected for estimatesmartfee to not return a reasonable answer. Note that because of this the GUI changes are actually optional, but I think provide for a more clear experience.
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.
I don't understand.
Who is currently calling estimateSmartFee with confTarget = 1 ?
And how is 0 less "reasonable" than the answer for another value?
Why do we want the GUI changes to be optimal?
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.
Before this PR anybody could have been using the RPC call estimatesmartfee and not expecting it to return -1 (which is what CFeeRate(0) gets translated into via RPC). estimatesmartfee already gave you the answer for another value when it couldn't give you one for the target you asked for, it would have been exceedingly unusually for it to give you a -1 except right at startup. So for any outside users of estimatesmartfee, this is the expected result. You should be able to ask for a target of 1, and it'll give you the best answer it can.
EDIT: Also anyone that has a config file or a command line option setting nTxConfirmTarget = 1 will be calling the internal function estimateSmartFee and their behavior would become unnecessarily broken if it returns -1.
We don't want to GUI changes to be optional, but it points out why the other changes are the correct ones, they don't break the existing API.
@@ -175,7 +175,7 @@ void SendCoinsDialog::setModel(WalletModel *_model) | |||
// set the smartfee-sliders default value (wallets default conf.target or last stored value) | |||
QSettings settings; | |||
if (settings.value("nSmartFeeSliderPosition").toInt() == 0) | |||
ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - model->getDefaultConfirmTarget() + 1); | |||
ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - model->getDefaultConfirmTarget() + 2); |
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.
A constant would be nice
#define MIN_CONFIRM_TARGET 2
?
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.
I agree this is slightly non-ideal, but it's convoluted a bit by the fact that the sliderSmartFee value is not the actual confirmation target. I'd rather not make an additional change here, but when we make a change to support estimates greater than 25, we'll have to figure out the right way to do 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.
Right, I agree it is convoluted. Everything would probably look clearer if the "fast" side of the bar was on the left or if we at least had a function that does the conversion ie
return ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2
But I don't see how a constant would make it any less readable.
At the same time, it doesn't mean it cannot be done later.
utACK e878689 besides nits. |
lightly tested ACK e878689 |
e878689 Make GUI incapable of setting tx confirm target of 1 (Alex Morcos) d824ad0 Disable fee estimates for a confirm target of 1 block (Alex Morcos)
The GUI changes may be difficult to backport here because the fee slider behavior changed in master in the meantime. |
What about backporting #8989 (this woulds simplify a backport of this PR) |
@jonasschnelli I think it is perfectly fine to backport without the GUI changes. As mentioned to @jtimon, that was the intent. Will create separate PR. EDIT: Oh it's already a separate commit. You can just grab the first commit. |
Backport of bitcoin#9239 without GUI changes and fixing conflicts in tests.
This was already backported in #9267 |
Backport of bitcoin#9239 without GUI changes and fixing conflicts in tests.
e878689 Make GUI incapable of setting tx confirm target of 1 (Alex Morcos) d824ad0 Disable fee estimates for a confirm target of 1 block (Alex Morcos)
e878689 Make GUI incapable of setting tx confirm target of 1 (Alex Morcos) d824ad0 Disable fee estimates for a confirm target of 1 block (Alex Morcos)
e878689 Make GUI incapable of setting tx confirm target of 1 (Alex Morcos) d824ad0 Disable fee estimates for a confirm target of 1 block (Alex Morcos)
Bitcoin Core fee estimation works by returning a fee rate such that the overwhelming majority (95%) of recent transactions with that fee rate were included in a block within the target number of blocks.
With a confirmation target of 1 it is often not possible to find a feerate that is high enough to meet that criteria and when it is possible it is sometimes an exorbitantly high fee rate. Given the way Bitcoin Core's fee estimation works, the lowest target it is reasonable to estimate a feerate for is 2 blocks. This PR avoids returning occasional absurdly high fee rates for the 1 block target by never giving an answer for that target. This is not different from the common case in practice.
estimatefee is modified to return -1 with a target of 1 always.
estimatesmartfee is modified to start searching with a target of 2 if given a target of 1.
The second commit changes the GUI so targets of 1 can't be selected with the smartfee slider. Selecting a target of 1 via config option will be equivalent to selecting a target of 2 as all internal fee estimation is done using estimatesmartfee.