-
Notifications
You must be signed in to change notification settings - Fork 36.6k
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
rpc: Add feeRate argument to bumpFee RPC #16492
Conversation
concept ACK |
@@ -57,6 +57,58 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai | |||
return feebumper::Result::OK; | |||
} | |||
|
|||
//! Check if the user provided a valid feeRate | |||
static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) { | |||
// check that fee rate is higher than mempool's minimum 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.
is this block of code cribbed from somewhere to compare with?
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.
Yeah, this code is from the CreateTotalBumpTransaction
method
bitcoin/src/wallet/feebumper.cpp
Lines 199 to 247 in b89249e
// calculate the old fee and fee-rate | |
old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut(); | |
CFeeRate nOldFeeRate(old_fee, txSize); | |
// The wallet uses a conservative WALLET_INCREMENTAL_RELAY_FEE value to | |
// future proof against changes to network wide policy for incremental relay | |
// fee that our node may not be aware of. | |
CFeeRate nodeIncrementalRelayFee = wallet->chain().relayIncrementalFee(); | |
CFeeRate walletIncrementalRelayFee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE); | |
if (nodeIncrementalRelayFee > walletIncrementalRelayFee) { | |
walletIncrementalRelayFee = nodeIncrementalRelayFee; | |
} | |
CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + nodeIncrementalRelayFee.GetFee(maxNewTxSize); | |
if (total_fee < minTotalFee) { | |
errors.push_back(strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)", | |
FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(nodeIncrementalRelayFee.GetFee(maxNewTxSize)))); | |
return Result::INVALID_PARAMETER; | |
} | |
CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize); | |
if (total_fee < requiredFee) { | |
errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)", | |
FormatMoney(requiredFee))); | |
return Result::INVALID_PARAMETER; | |
} | |
// Check that in all cases the new fee doesn't violate maxTxFee | |
const CAmount max_tx_fee = wallet->m_default_max_tx_fee; | |
if (new_fee > max_tx_fee) { | |
errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)", | |
FormatMoney(new_fee), FormatMoney(max_tx_fee))); | |
return Result::WALLET_ERROR; | |
} | |
// check that fee rate is higher than mempool's minimum fee | |
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool) | |
// This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps, | |
// in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a | |
// moment earlier. In this case, we report an error to the user, who may use total_fee to make an adjustment. | |
CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee(); | |
CFeeRate nNewFeeRate = CFeeRate(total_fee, maxNewTxSize); | |
if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) { | |
errors.push_back(strprintf( | |
"New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- " | |
"the totalFee value should be at least %s to add transaction", | |
FormatMoney(nNewFeeRate.GetFeePerK()), | |
FormatMoney(minMempoolFeeRate.GetFeePerK()), | |
FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize)))); | |
return Result::WALLET_ERROR; | |
} |
src/wallet/feebumper.cpp
Outdated
CAmount minTotalFee = nOldFeeRate.GetFee(maxTxSize) + incrementalRelayFee.GetFee(maxTxSize); | ||
|
||
if (new_total_fee < minTotalFee) { | ||
errors.push_back(strprintf("Insufficient totalFee %s, must be at least %s (oldFee %s + incrementalFee %s)", |
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.
totalFee
isn't a thing
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'll rewrite these error messages.
Concept ACK. Some notes:
|
@promag Thanks for your feedback. |
Could rebase on master and modify the release notes in the section "removed or deprecated rpcs"? |
5e564f6
to
9bc7a55
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.
Concept ACK.
In the description, if you replace "Draft commit for issue" with "Fixes" then Github will automatically close that issue when this PR is merged, which saves maintainers some effort.
Regarding the organization, what do you feel is not organized?
You should use git interactive rebase to reduce the number of commits, for example:
- commit
linter: fix whitespace
: add this into the commit that added the incorrect whitespace (fixup
) - commits
rpc: test bumpfee feeRate argument
: squash these together - commit
doc: Add release note...
: drop this commit, because doc: Add release note for the deprecated totalFee option of bumpfee #16504
This makes it easier to review a pull request one commit at a time.
- commit
Changes the verbosity of msbuild
: move to separate pull request
test/functional/wallet_bumpfee.py
Outdated
@@ -176,7 +188,6 @@ def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address) | |||
rbf_node.sendrawtransaction(tx["hex"]) | |||
assert_raises_rpc_error(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id) | |||
|
|||
|
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.
Nit: avoid dropping or adding whitespace in code that you're not touching.
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.
fixed
27fb2f1
to
e1fd79a
Compare
Thanks @Sjors, |
48d3691
to
002dbde
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.
Thanks for condensing the commits.
You can probably remove the WIP and Draft status; those are meant to prevent too detailed review, but it's too late for that :-)
There's still quite a bit of duplicate code between CheckFeeRate
and CreateTotalBumpTransaction
. Can you add an additional commit, similar to rpc: bumpfee move feeRate estimation logic into sepparate method
, where you move this to a helper function? I'll review the actual functionality in more detail after that.
There's a couple of places where you or your editor fixed stuff in code that you're not otherwise touching. This increases review burden, because it's harder to see what changes are relevant, so is best avoided. I left a bunch of inline comments for that.
Couple more nits:
- commit
rpc: test bumpfee feeRate argument
should be named[test] rpc bumpfee feeRate argument
doc/release-notes.md
Outdated
@@ -92,7 +92,9 @@ Deprecated or removed RPCs | |||
-------------------------- | |||
|
|||
- The `totalFee` option of the `bumpfee` RPC has been deprecated and will be | |||
removed in 0.20. To continue using this option start with | |||
removed in 0.20. The `feeRate` option is now the preferred way to specify | |||
the fee for the bump transaction. |
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.
Nit: bumped
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 initially wrote it as 'bumped' but went with 'bump'. My thought was that the bumped transaction is the one we are replacing, and the bump transaction is the new one?
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.
the fee for the new transaction.
See
bitcoin/src/wallet/rpcwallet.cpp
Line 3274 in 3a3d8b8
"\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n" |
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.
thats better, fixed.
@@ -3361,7 +3361,7 @@ static UniValue bumpfee(const JSONRPCRequest& request) | |||
if (fee_rate <= 0) { | |||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid feeRate %s (must be greater than 0)", fee_rate.ToString())); | |||
} | |||
coin_control.m_feerate = fee_rate; | |||
coin_control.m_feerate = fee_rate; |
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.
Nit: move whitespace fix to commit where the whitespace mistake was made
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.
fixed
src/wallet/rpcwallet.cpp
Outdated
@@ -3278,7 +3278,7 @@ static UniValue bumpfee(const JSONRPCRequest& request) | |||
"All inputs in the original transaction will be included in the replacement transaction.\n" | |||
"The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n" | |||
"By default, the new fee will be calculated automatically using estimatesmartfee.\n" | |||
"The user can specify a confirmation target for estimatesmartfee.\n" |
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.
Nit: don't remove whitespace here
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.
fixed
src/wallet/feebumper.cpp
Outdated
@@ -304,7 +361,8 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo | |||
return Result::OK; | |||
} | |||
|
|||
bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx) { |
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.
Nit: you're not touching this function, so don't fix the brackets please
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.
fixed :)
src/wallet/feebumper.cpp
Outdated
@@ -4,16 +4,16 @@ | |||
|
|||
#include <consensus/validation.h> | |||
#include <interfaces/chain.h> | |||
#include <wallet/coincontrol.h> |
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.
nit: don't fix the include order; that's best done when you add a new include
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.
fixed
src/wallet/feebumper.cpp
Outdated
@@ -71,8 +152,7 @@ bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid) | |||
return res == feebumper::Result::OK; | |||
} | |||
|
|||
Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors, | |||
CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx) | |||
Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors, CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx) |
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.
nit: don't fix things you're not otherwise touching
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.
fixed this too
src/wallet/feebumper.cpp
Outdated
FormatMoney(new_fee), FormatMoney(max_tx_fee))); | ||
return Result::WALLET_ERROR; | ||
} | ||
const CAmount max_tx_fee = wallet->m_default_max_tx_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.
nit: don't fix this
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.
done
@Sjors I should be done with your comments, let me know if there is anything missing. Only thing missing is to get rid of the code re-use on CreateTotalTransaction. |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. 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. |
if (options.exists("confTarget") && (options.exists("totalFee") || options.exists("feeRate"))) { | ||
throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget can't be set with totalFee or feeRate. Please provide either a conftarget for fee estimation, or an explicit total fee or fee rate for the transaction."); | ||
} else if (options.exists("feeRate") && options.exists("totalFee")) { | ||
throw JSONRPCError(RPC_INVALID_PARAMETER, "feeRate can't be set along with totalFee. Please provide either a total fee or a fee rate (in satoshis per K) for the transaction."); |
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.
Where else are we using satoshis per Kb? Seems like we're using BTC/kB everywhere else unless I'm missing a use?
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.
You are correct, I used Satoshis per kB on my first iteration of this feature and forgot to change the error message. nice catch
(couldn't reach you on IRC) still working on this? |
Needs rebase |
Taken over in #16727. |
c812aba test bumpfee fee_rate argument (ezegom) 9f25de3 rpc bumpfee check fee_rate argument (ezegom) 88e5f99 rpc bumpfee: add fee_rate argument (ezegom) 1a4c791 rpc bumpfee: move feerate estimation logic into separate method (ezegom) Pull request description: Taking over for #16492 which seems to have gone inactive. Only minor commit cleanups, rebase, and some help text fixes on top of previous PR. Renamed `feeRate` to `fee_rate` to reflect updated guidelines. ACKs for top commit: Sjors: Code review ACK c812aba laanwj: ACK c812aba Tree-SHA512: 5f7f51bd780a573ccef1ccd72b0faf3e5d143f6551060a667560c5163f7d9480e17e73775d1d7bcac0463f3b6b4328f0cff7b27e39483bddc42a530f4583ce30
Fixes #16203.
On PR #15996, the totalfee argument in
bumpfee
gets deprecated. The feeRate argument inbumpfee
serves as a replacement to totalFee.Small changes to
CreateRateBumpTransaction