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

More economical fee estimates for RBF and RPC options to control #10589

Merged
merged 5 commits into from Jul 11, 2017

Conversation

Projects
None yet
10 participants
@morcos
Member

morcos commented Jun 14, 2017

This PR takes advantage of the new fee estimation feature that will potentially give lower estimates if recent market conditions warrant it. The logic used here is that any time a transaction signals opt-in-RBF and uses automatic fee estimation then it will use the non-conservative estimate. Transactions which do not signal opt-in-RBF will still use the default conservative estimate.

In a nutshell conservative estimates require that your fee rate would meet the necessary confirmation threshold for double your target at longer time horizons as well. This reduces the likelihood that you place a transaction just as the market is starting to get busy again that ends up being stuck for a very long time.

This PR also allows the specification of transaction confirmation target and whether the estimate should be conservative or not on a per-RPC call basis for sendtoaddress, sendmany, bumpfee, and fundrawtransaction using optional named arguments.

Left as an exercise to the reader is adding this to GUI functions to send transactions and bump fee.

@RHavar

This comment has been minimized.

Show comment
Hide comment
@RHavar

RHavar Jun 14, 2017

Contributor

Concept ACK, this is really great and something that's been needed for a long time. It'll simplify some of the locking and settxfee stuff I've needed to do.

But it'd be nice if it used an options object or something. Otherwise if I want to specify the conservative_estimate I'll need to fill in all the other fields, which I might not want to know?

But I guess that's something that can be done in a different commit, with if (arguments.length == 3 && typeof arguments == 'object') style

Contributor

RHavar commented Jun 14, 2017

Concept ACK, this is really great and something that's been needed for a long time. It'll simplify some of the locking and settxfee stuff I've needed to do.

But it'd be nice if it used an options object or something. Otherwise if I want to specify the conservative_estimate I'll need to fill in all the other fields, which I might not want to know?

But I guess that's something that can be done in a different commit, with if (arguments.length == 3 && typeof arguments == 'object') style

@instagibbs

This comment has been minimized.

Show comment
Hide comment
@instagibbs

instagibbs Jun 14, 2017

Member

@RHavar I had the same exact reaction fwiw. fee_options or something.

Member

instagibbs commented Jun 14, 2017

@RHavar I had the same exact reaction fwiw. fee_options or something.

@morcos

This comment has been minimized.

Show comment
Hide comment
@morcos

morcos Jun 14, 2017

Member

I thought the whole point of named arguments is we didn't have to worry about that any more. I think I made sure these work correctly with holes so we can use them with named arguments.

Member

morcos commented Jun 14, 2017

I thought the whole point of named arguments is we didn't have to worry about that any more. I think I made sure these work correctly with holes so we can use them with named arguments.

@RHavar

This comment has been minimized.

Show comment
Hide comment
@RHavar

RHavar Jun 14, 2017

Contributor

Oh yeah, you're right. Guess I should learn how to use named arguments.

Contributor

RHavar commented Jun 14, 2017

Oh yeah, you're right. Guess I should learn how to use named arguments.

@sipa

This comment has been minimized.

Show comment
Hide comment
@sipa

sipa Jun 16, 2017

Member

Needs rebase.

Member

sipa commented Jun 16, 2017

Needs rebase.

@morcos

This comment has been minimized.

Show comment
Hide comment
@morcos

morcos Jun 18, 2017

Member

Rebased due to conflict with #10422

Member

morcos commented Jun 18, 2017

Rebased due to conflict with #10422

Show outdated Hide outdated src/wallet/rpcwallet.cpp Outdated
@laanwj

This comment has been minimized.

Show comment
Hide comment
@laanwj

laanwj Jun 22, 2017

Member

Concept ACK

Member

laanwj commented Jun 22, 2017

Concept ACK

@morcos morcos changed the title from Add RPC options for RBF, confirmation target and conservative fee estimates to More economical fee estimates for RBF and RPC options to control Jun 27, 2017

@morcos

This comment has been minimized.

Show comment
Hide comment
@morcos

morcos Jun 28, 2017

Member

Switched to an estimate_mode string and squashed
5cbc1f6 (rpcestimatechoice.ver2) -> 1bc6a4a (rpcestimatechoices.ver2.squash)

Member

morcos commented Jun 28, 2017

Switched to an estimate_mode string and squashed
5cbc1f6 (rpcestimatechoice.ver2) -> 1bc6a4a (rpcestimatechoices.ver2.squash)

@morcos

This comment has been minimized.

Show comment
Hide comment
@morcos

morcos Jun 28, 2017

Member

Changed argument name from opt_in_rbf to replaceable for conformance with bumpfee

Member

morcos commented Jun 28, 2017

Changed argument name from opt_in_rbf to replaceable for conformance with bumpfee

Show outdated Hide outdated src/wallet/wallet.cpp Outdated
@TheBlueMatt

I still dont really feel comfortable ACKing the Qt changes until I get a chance to test, but this is generally a very welcome improvement.

Show outdated Hide outdated src/wallet/wallet.cpp Outdated
Show outdated Hide outdated src/wallet/rpcwallet.cpp Outdated

@jonasschnelli jonasschnelli added this to the 0.15.0 milestone Jul 6, 2017

morcos added some commits Jun 13, 2017

Introduce a fee estimate mode.
GetMinimumFee now passes the conservative argument into estimateSmartFee.
Call CalculateEstimateType(mode) before calling GetMinimumFee or estimateSmartFee to determine the value of this argument.
CCoinControl can now be used to control this mode.
Change default fee estimation mode.
Fee estimates will default to be non-conservative if the transaction in question is opt-in-RBF.
@morcos

This comment has been minimized.

Show comment
Hide comment
@morcos

morcos Jul 7, 2017

Member

rebased for adjacent line change in #10698 and removed a couple extra \n's

no other changes

I believe we've settled on removing the CalculateEstimateType function entirely at the end of #10706 since it just becomes a helper for GetMinimumFee at that point.

Member

morcos commented Jul 7, 2017

rebased for adjacent line change in #10698 and removed a couple extra \n's

no other changes

I believe we've settled on removing the CalculateEstimateType function entirely at the end of #10706 since it just becomes a helper for GetMinimumFee at that point.

@TheBlueMatt

Looks good. Definitely want #10706 to go in with this.

@@ -166,6 +166,8 @@ void SendCoinsDialog::setModel(WalletModel *_model)
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls()));
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables()));
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(updateSmartFeeLabel()));
connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));

This comment has been minimized.

@TheBlueMatt

TheBlueMatt Jul 9, 2017

Contributor

Cant comment there, but I believe you also need to move the default setting of optInRBF up a bunch here (about 10 lines below this (set default rbf checkbox state, or does that setting automagically result in calling these registrations?).

@TheBlueMatt

TheBlueMatt Jul 9, 2017

Contributor

Cant comment there, but I believe you also need to move the default setting of optInRBF up a bunch here (about 10 lines below this (set default rbf checkbox state, or does that setting automagically result in calling these registrations?).

This comment has been minimized.

@morcos

morcos Jul 10, 2017

Member

Not sure if I understand your question (or how QT works) but I'm pretty sure it's correct as is. Calling setCheckState below will trigger the signal if the checkbox changed from its initial value.

@morcos

morcos Jul 10, 2017

Member

Not sure if I understand your question (or how QT works) but I'm pretty sure it's correct as is. Calling setCheckState below will trigger the signal if the checkbox changed from its initial value.

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

Either way, what about make an explicit call to coinControlUpdateLabels()?

@promag

promag Jul 10, 2017

Member

Either way, what about make an explicit call to coinControlUpdateLabels()?

This comment has been minimized.

@morcos

morcos Jul 10, 2017

Member

I don't think this is necessary. It's analogous to setting the default sliderSmartFee done in the same section of code.

@morcos

morcos Jul 10, 2017

Member

I don't think this is necessary. It's analogous to setting the default sliderSmartFee done in the same section of code.

@promag

IMO this would be a cleaner implementation

bool FeeEstimateModeFromString(const std::string& string, FeeEstimateMode& fee_estimate_mode)
{
    // lookup string
    return false;
}

...


if (!FeeEstimateModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) {
    throw JSONRPCError(RPC_INVALID_PARAMETER, ...);
}
@@ -416,6 +416,12 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
" transaction, just kept in your wallet.\n"
"5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
" The recipient will receive less bitcoins than you enter in the amount field.\n"
"6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
"7. conf_target (numeric, optional) Confirmation target (in blocks)\n"
"8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

fee_estimate_mode, fee_mode or estimate_mode?

@promag

promag Jul 10, 2017

Member

fee_estimate_mode, fee_mode or estimate_mode?

This comment has been minimized.

@morcos

morcos Jul 10, 2017

Member

Hmm.. Yes, I think it might make sense to change this to fee_mode, but leave it estimate_mode for estimateSmartFee (done in another PR). Even though they take the same values now, I could imagine they would differ in the future. Any other thoughts?

@morcos

morcos Jul 10, 2017

Member

Hmm.. Yes, I think it might make sense to change this to fee_mode, but leave it estimate_mode for estimateSmartFee (done in another PR). Even though they take the same values now, I could imagine they would differ in the future. Any other thoughts?

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

I just wanted to point out the inconsistencies between arguments, variable names and types.

@promag

promag Jul 10, 2017

Member

I just wanted to point out the inconsistencies between arguments, variable names and types.

This comment has been minimized.

@morcos

morcos Jul 10, 2017

Member

I decided leaving it as estimate_mode in both RPC's is preferable.
The inconsistency between variable and parameter name is not worth the churn imo.

@morcos

morcos Jul 10, 2017

Member

I decided leaving it as estimate_mode in both RPC's is preferable.
The inconsistency between variable and parameter name is not worth the churn imo.

@@ -166,6 +166,8 @@ void SendCoinsDialog::setModel(WalletModel *_model)
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls()));
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables()));
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(updateSmartFeeLabel()));
connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

Either way, what about make an explicit call to coinControlUpdateLabels()?

@promag

promag Jul 10, 2017

Member

Either way, what about make an explicit call to coinControlUpdateLabels()?

@@ -26,6 +27,8 @@ class CCoinControl
int nConfirmTarget;
//! Signal BIP-125 replace by fee.
bool signalRbf;
//! Fee estimation mode to control arguments to estimateSmartFee
FeeEstimateMode m_fee_mode;

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

m_fee_estimate_mode?

@promag

promag Jul 10, 2017

Member

m_fee_estimate_mode?

Show outdated Hide outdated src/wallet/rpcwallet.cpp Outdated
@@ -910,7 +935,13 @@ UniValue sendmany(const JSONRPCRequest& request)
" \"address\" (string) Subtract fee from this address\n"
" ,...\n"
" ]\n"
"\nResult:\n"
"6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

Add options instead of 3 more optional arguments?

@promag

promag Jul 10, 2017

Member

Add options instead of 3 more optional arguments?

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

I saw the above comment about named arguments. IMO from the client side feels better as an option.

@promag

promag Jul 10, 2017

Member

I saw the above comment about named arguments. IMO from the client side feels better as an option.

@@ -416,6 +416,12 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
" transaction, just kept in your wallet.\n"
"5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
" The recipient will receive less bitcoins than you enter in the amount field.\n"
"6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

Add options instead of 3 more optional arguments?

@promag

promag Jul 10, 2017

Member

Add options instead of 3 more optional arguments?

This comment has been minimized.

@morcos

morcos Jul 10, 2017

Member

I believe named arguments are preferable

@morcos

morcos Jul 10, 2017

Member

I believe named arguments are preferable

This comment has been minimized.

@promag

promag Jul 11, 2017

Member

I understand, but for those that use indexed arguments, they have to pass the middle arguments.

@promag

promag Jul 11, 2017

Member

I understand, but for those that use indexed arguments, they have to pass the middle arguments.

@@ -4154,3 +4157,15 @@ bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState&
{
return ::AcceptToMemoryPool(mempool, state, tx, true, NULL, NULL, false, nAbsurdFee);
}
bool CalculateEstimateType(FeeEstimateMode mode, bool opt_in_rbf) {

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

IsFeeEstimateConservative?

@promag

promag Jul 10, 2017

Member

IsFeeEstimateConservative?

This comment has been minimized.

@morcos

morcos Jul 10, 2017

Member

Function removed in #10706 (or will be shortly)

@morcos

morcos Jul 10, 2017

Member

Function removed in #10706 (or will be shortly)

This comment has been minimized.

@promag

promag Jul 10, 2017

Member

Still, name not clear don't you think?

@promag

promag Jul 10, 2017

Member

Still, name not clear don't you think?

This comment has been minimized.

@morcos

morcos Jul 10, 2017

Member

yeah but who cares, its going away completely in a couple of commits

@morcos

morcos Jul 10, 2017

Member

yeah but who cares, its going away completely in a couple of commits

Add RPC options for RBF, confirmation target, and conservative fee es…
…timation.

Add support for setting each of these attributes on a per RPC call basis to sendtoaddress, sendmany, fundrawtransaction (already had RBF), and bumpfee (already had RBF and conf target).
@morcos

This comment has been minimized.

Show comment
Hide comment
@morcos
Member

morcos commented Jul 10, 2017

@promag

This comment has been minimized.

Show comment
Hide comment
@promag

promag Jul 11, 2017

Member

As suggested in another PR, the first condition can be removed since UniValue::operator[] handles out of bounds. Same below.

Member

promag commented on src/wallet/rpcwallet.cpp in f135923 Jul 11, 2017

As suggested in another PR, the first condition can be removed since UniValue::operator[] handles out of bounds. Same below.

@laanwj

This comment has been minimized.

Show comment
Hide comment
@laanwj

laanwj Jul 11, 2017

Member

utACK f135923

Member

laanwj commented Jul 11, 2017

utACK f135923

@laanwj laanwj merged commit f135923 into bitcoin:master Jul 11, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

laanwj added a commit that referenced this pull request Jul 11, 2017

Merge #10589: More economical fee estimates for RBF and RPC options t…
…o control

f135923 Add RPC options for RBF, confirmation target, and conservative fee estimation. (Alex Morcos)
f0bf33d Change default fee estimation mode. (Alex Morcos)
e0738e3 remove default argument from estimateSmartFee (Alex Morcos)
d507c30 Introduce a fee estimate mode. (Alex Morcos)
cfaef69 remove default argument from GetMinimumFee (Alex Morcos)

Tree-SHA512: 49c3a49a6893790a7e8b4e93a48f123dd5307af26c2017800683b76b4df8fc904ba73402917878676242c7440e3e04288d0c1ff3c2c907418724efc03cedab50

@laanwj laanwj removed this from Blockers in High-priority for review Jul 11, 2017

laanwj added a commit that referenced this pull request Jul 17, 2017

Merge #10706: Improve wallet fee logic and fix GUI bugs
11590d3 Properly bound check conf_target in wallet RPC calls (Alex Morcos)
fd29d3d Remove checking of mempool min fee from estimateSmartFee. (Alex Morcos)
2fffaa9 Make QT fee displays use GetMinimumFee instead of estimateSmartFee (Alex Morcos)
1983ca6 Use CoinControl to pass custom fee setting from QT. (Alex Morcos)
03ee701 Refactor to use CoinControl in GetMinimumFee and FeeBumper (Alex Morcos)
ecd81df Make CoinControl a required argument to CreateTransaction (Alex Morcos)

Pull request description:

  This builds on #10589  (first 5 commits from that PR, last 5 commits are new)

  The first couple commits refactor to use the CCoinControl class to pass fee calculation parameters around.

  This allows for fixing the buggy interaction in QT between the global payTxFee which can be modified by the RPC call settxfee or temporarily modified by the QT custom fee settings.  Before these changes the GUI could sometimes send a transaction with a recently set payTxFee and not respect the settings displayed in the GUI.   After these changes, using the GUI does not involve the global transaction confirm target or payTxFee.

  The prospective fee displays in the smart fee slider and the coin control dialog are changed to use the fee calculation from GetMinimumFee, this simplifies the code and makes them slightly more correct in edge cases.

  Maxing the fee calculation with the mempool min fee is move from estimateSmartFee to GetMinimumFee.

  This fixes a long standing bug, and should be tagged for 0.15 as it is holding up finalizing the estimatesmartfee RPC API before release.

Tree-SHA512: 4d36a1bd5934aa62f3806d380fcafbef73e9fe5bdf190fc5259a3e3a13349e5ce796e50e7068c46dc630ccf56d061bce5804f0bfe2e082bb01ca725b63efd4c1

@jnewbery jnewbery referenced this pull request Aug 1, 2017

Closed

TODO for release notes 0.15.0 #9889

12 of 12 tasks complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment