-
Notifications
You must be signed in to change notification settings - Fork 36.5k
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
wallet, rpc: explicit fee rate follow-ups/fixes for 0.21 #20220
wallet, rpc: explicit fee rate follow-ups/fixes for 0.21 #20220
Conversation
@@ -3461,7 +3461,6 @@ static RPCHelpMan bumpfee_helper(std::string method_name) | |||
if (options.exists("fee_rate")) { | |||
throw JSONRPCError(RPC_INVALID_PARAMETER, "conf_target can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate."); | |||
} | |||
coin_control.m_confirm_target = ParseConfirmTarget(conf_target, pwallet->chain().estimateMaxBlocks()); |
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 action is performed in SetFeeEstimateMode()
and calling it in bumpfee beforehand causes an error when explicit feerates are used (issue #20219).
9bd1253
to
f97a3cd
Compare
Pushed a few improvements. Should be ready for review. |
@@ -132,6 +134,13 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address): | |||
if mode == "fee_rate": | |||
bumped_psbt = rbf_node.psbtbumpfee(rbfid, {"fee_rate": NORMAL}) | |||
bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": NORMAL}) | |||
elif mode == BTC_MODE: |
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.
Isn't the BTC_MODE then essentially a duplicate of the
{"fee_rate": …}` option?
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, it's a redundant feature here that adds to the confusion...and it also uses a different code path so the test is needed.
@@ -3459,7 +3459,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name) | |||
|
|||
if (!conf_target.isNull()) { | |||
if (options.exists("fee_rate")) { | |||
throw JSONRPCError(RPC_INVALID_PARAMETER, "conf_target can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate."); | |||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit 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.
So much clearer! 👍
test/functional/wallet_bumpfee.py
Outdated
|
||
self.log.info("Test explicit feerate raises RPC error if estimate_mode is passed without a conf_target") | ||
assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL, "estimate_mode": BTC_MODE}) | ||
assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate", rbf_node.bumpfee, rbfid, {"fee_rate": 10, "estimate_mode": SAT_MODE}) |
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.
That's an odd name clash, that the error complains about the missing "fee rate", but it's actually conf_target
that's missing. I assume that was part of the items that #19543 was meant to address?
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 find. Fixed the error message to now print Selected estimate_mode <MODE> requires a fee rate to be specified in conf_target
and updated the tests.
+++ b/src/wallet/rpcwallet.cpp
@@ -214,7 +214,7 @@ static void SetFeeEstimateMode(const CWallet* pwallet, CCoinControl& cc, const U
if (cc.m_fee_mode == FeeEstimateMode::BTC_KB || cc.m_fee_mode == FeeEstimateMode::SAT_B) {
if (estimate_param.isNull()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Selected estimate_mode requires a fee rate");
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Selected estimate_mode %s requires a fee rate to be specified in conf_target", estimate_mode.get_str()));
}
+++ b/test/functional/wallet_bumpfee.py
- assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate", rbf_node.bumpfee, rbfid, {"fee_rate": HIGH, "estimate_mode": BTC_MODE})
- assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate", rbf_node.bumpfee, rbfid, {"fee_rate": 1000, "estimate_mode": SAT_MODE})
+ for unit, fee_rate in {"SAT/B": 100, "BTC/KB": NORMAL}.items():
+ assert_raises_rpc_error(-8, "Selected estimate_mode {} requires a fee rate to be specified in conf_target".format(unit),
+ rbf_node.bumpfee, rbfid, {"fee_rate": fee_rate, "estimate_mode": unit})
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 in fc57217
test/functional/rpc_psbt.py
Outdated
# previously this was silently capped at -maxtxfee | ||
assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[1].walletcreatefundedpsbt, [{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0, {"feeRate": 10, "add_inputs": True}) | ||
assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[1].walletcreatefundedpsbt, [{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():1}, 0, {"feeRate": 10, "add_inputs": False}) | ||
for bool_add, addr in {True: addr, False: {self.nodes[1].getnewaddress(): 1}}.items(): |
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.
Still getting used to this, but totally see what you're doing now. :)
test/functional/rpc_psbt.py
Outdated
res = self.nodes[1].walletcreatefundedpsbt(inputs, addr, 0, {"feeRate": 0.1, "add_inputs": True}) | ||
assert_approx(res["fee"], 0.055, 0.005) | ||
|
||
self.log.info("Test passing walletcreatefundedpsbt explicit feerate with conf_target and estimate_mode") | ||
for unit, feerate in {"btc/kb": 0.1, "sat/b": 10000}.items(): |
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.
Probably not the right place to bring this up, but the explicit specifying of the unit does seem really error prone as mentioned in the comments of #19543 before.
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. It would be good to replace this with the fixed-unit feerate_sat_vb
argument before the 0.21 branch-off. Edit: I have a changeset for that but I guess it's too late though.
@@ -4034,7 +4034,7 @@ static RPCHelpMan send() | |||
{"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"}, | |||
{"lock_unspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"}, | |||
{"psbt", RPCArg::Type::BOOL, /* default */ "automatic", "Always return a PSBT, implies add_to_wallet=false."}, | |||
{"subtract_fee_from_outputs", RPCArg::Type::ARR, /* default */ "empty array", "A JSON array of integers.\n" | |||
{"subtract_fee_from_outputs", RPCArg::Type::ARR, /* default */ "empty array", "Outputs to subtract the fee from, specified as integer indices.\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.
Oh my, great improvement!
to clarify for the user the confusing error message that the missing fee rate needs to be set in the conf_target param/option.
@xekyo thanks for the excellent feedback--I have been building on it, writing more tests, finding a few more things, will push an update tomorrow. |
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. |
might be best reviewed with: git show COMMIT_HASH -w --color-moved=dimmed-zebra
f97a3cd
to
c80e227
Compare
Hopefully addressed the (excellent) review feedback and also added missing explicit fee rate coverage in |
Just seeing this now. Aiming to take a look tomorrow. |
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.
Looks good to me. There are two spots where I wonder whether I found an actual issue, the rest are just nits that I consider optional.
inputs = [{"txid": txid, "vout": p2wpkh_pos}, {"txid": txid, "vout": p2sh_p2wpkh_pos}, {"txid": txid, "vout": p2pkh_pos}] | ||
outputs = [{self.nodes[1].getnewaddress(): 29.99}] |
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.
Love how much more readable the tests below become. Good improvement.
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=1, arg_estimate_mode="economical", | ||
conf_target=1, estimate_mode="economical", add_to_wallet=False, expect_error=(-8,"Use either conf_target and estimate_mode or the options dictionary to control fee rate")) | ||
for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]: | ||
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=1, arg_estimate_mode="economical", |
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 noticed that both arg_estimate_mode
and estimate_mode
appear in these test parameters. That seems odd. I wonder whether both pertain to the same value. If one of them would supersede the other, and that happened to be arg_estimate_mode
, we would actually only be testing for economical
here. If they actually do refer both to the same value, they should probably both be set to =mode
.
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 point. In the send
RPC, conf_target
and estimate_mode
can be both args (arg_estimate_mode
in this test file) and options (estimate_mode
in this test file).
There seem to be some oddities or bugs in the send
RPC related to this, as described in #20220 (comment). The send RPC is marked as experimental, but these should be fixed or made consistent with the other RPCs after this is merged. I started to look into it but didn't find a fix quickly, and the PR is already quite large and the deadline for 0.21 branch-off this weekend is looming.
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.
Okay, since this is only in a test, it may be fine to keep track of it, but not get too hung up on fixing every little bit before the merge.
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode=mode, | ||
expect_error=(-8, "Invalid estimate_mode parameter")) | ||
# TODO: these 2 equivalent sends with an invalid estimate_mode arg should both fail, but they do not...why? | ||
# self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0.1, arg_estimate_mode=mode, |
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 only difference I see in this line is that it now uses arg_conf_target
where conf_target
was used in 284 and arg_estimate_mode
where estimate_mode
was used. Potentially, the sanitation for those parameters are different?
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, there seems to be a bug in the send
RPC: per the code in wallet/rpcwallet.cpp
, these should behave the same whether passed as an arg or an option, but they do not.
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, there seems to be a bug in the
send
RPC: per the code inwallet/rpcwallet.cpp
, these should behave the same whether passed as an arg or an option, but they do not.
Fixed in #20305.
@@ -440,7 +440,8 @@ static RPCHelpMan sendtoaddress() | |||
{"subtractfeefromamount", RPCArg::Type::BOOL, /* 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."}, | |||
{"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"}, | |||
{"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/kB or " + CURRENCY_ATOM + "/B estimate modes)"}, | |||
{"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target (in blocks)\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.
I see that the third argument here has changed from "wallet default"
to "wallet -txconfirmtarget"
, but it's not clear to me what the effect of that would be.
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 the RPC help output the user sees. The idea was to make the conf_target
help correct (some were missing the sat/B mention), consistent and helpful across the 6 RPCs. The txconfirmtarget mention in some of the conf_target
helps seems more useful info than just "wallet default", so I made them all the same/consistent. Open to disagreement about that :)
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.
e.g. before
7. conf_target (numeric, optional, default=wallet default) Confirmation target (in blocks), or fee rate (for BTC/kB or sat/B estimate modes)
after
7. conf_target (numeric, optional, default=wallet -txconfirmtarget) Confirmation target (in blocks)
or fee rate (for BTC/kB and sat/B estimate modes)
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 see. That looks like a good change to me.
c80e227
to
c9fccaf
Compare
for sendtoaddress, sendmany, send, fundrawtransaction, walletcreatefundedpsbt, bumpfee
c9fccaf
to
0be2900
Compare
Thanks @xekyo, updated units and comments per
|
Just ran the functional tests (for the previous commit I reviewed), which takes a surprisingly long time. Luckily, the first hit on an internet search for how to run the functional tests was this guide by some Jon Atack, made it really easy to get set up. 😆 |
Changes look great to me. |
@xekyo You can run them in parallel; if you have sufficient RAM pretty extremely even. |
Good point; I'll mention that in the guide. |
tack (functional tests only) 0be2900 |
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/Tested ACK 0be2900
It feels like this touches a fair bit of code that is unrelated to the explicit fee rate stuff, but maybe it's related and I'm just not seeing it. Otherwise looks good.
(I was unable to run test_runner with any kind of -j flags, though both machines had bitcoin daemons running which it claims could cause problems.)
I have a sloow 4-core 32GB RAM laptop and |
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 + functional test run ACK 0be2900
Very nice improvements & cleanups, thanks jonatack!
Thank you @xekyo, @kallewoof and @meshcollider! |
05e82d8 wallet: override minfee checks (fOverrideFeeRate) for fee_rate (Jon Atack) 9a670b4 wallet: update sendtoaddress, send RPC examples with fee_rate (Jon Atack) be481b7 wallet: use MIN_RELAY_TX_FEE in bumpfee help (Jon Atack) 449b730 wallet: provide valid values if invalid estimate mode passed (Jon Atack) 6da3afb wallet: update remaining rpcwallet fee rate units to BTC/kvB (Jon Atack) 173b5b5 wallet: update fee rate units, use sat/vB for fee_rate error messages (Jon Atack) 7f9835a wallet: remove fee rates from conf_target helps (Jon Atack) b7994c0 wallet: add fee_rate unit warnings to bumpfee (Jon Atack) 410e471 wallet: remove redundant bumpfee fee_rate checks (Jon Atack) a0d4957 wallet: introduce fee_rate (sat/vB) param/option (Jon Atack) e21212f wallet: remove unneeded WALLET_BTC_KB_TO_SAT_B constant (Jon Atack) 6112cf2 wallet: add CFeeRate ctor doxygen documentation (Jon Atack) 3f72791 wallet: fix bug in RPC send options (Jon Atack) Pull request description: This PR builds on #11413 and #20220 to address #19543. - replace overloading the conf_target and estimate_mode params with `fee_rate` in sat/vB in the sendtoaddress, sendmany, send, fundrawtransaction, walletcreatefundedpsbt, and bumpfee RPCs - allow non-actionable conf_target value of `0` and estimate_mode value of `""` to be passed to use `fee_rate` as a positional argument, in addition to as a named argument - fix a bug in the experimental send RPC described in #20220 (comment) where args were not being passed correctly into the options values - update the feerate error message units for these RPCs from BTC/kB to sat/vB - update the test coverage, help docs, doxygen docs, and some of the RPC examples - other changes to address the excellent review feedback See this wallet meeting log for more context: http://www.erisian.com.au/bitcoin-core-dev/log-2020-11-06.html#l-309 ACKs for top commit: achow101: re-ACK 05e82d8 MarcoFalke: review ACK 05e82d8 did not test and found a few style nits, which can be fixed later 🍯 Xekyo: tACK 05e82d8 Sjors: utACK 05e82d8 Tree-SHA512: a4ee5f184ada53f1840b2923d25873bda88c5a2ae48e67eeea2417a0b35154798cfdb3c147b05dd56bd6608a784e1b91623bb985ee2ab9ef2baaec22206d0a9c
Summary: This is a partial backport of [[bitcoin/bitcoin#20220 | core#20220]] Most of the PR is not applicable because we do not use `estimate_mode` nor `conf_target` for fees. List of changes and source commits: - Use a const ref in `FundTransaction` for `options`: bitcoin/bitcoin@1697a40 - Minor rpc_psbt.py refactoring: bitcoin/bitcoin@6e1ea42 - Add a `log.info` in wallet_basic.py: bitcoin/bitcoin@dd341e6 - Improve RPC doc for `subtract_fee_from_outputs`: bitcoin/bitcoin@778b9be Test Plan: `ninja all check-all` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Differential Revision: https://reviews.bitcoinabc.org/D10716
Follow-up to #11413 providing a base to build on for #19543:
bumpfee
raising a JSON error with explicit feerates, fixes issue RPC bumpfee error with explicit feerate #20219bumpfee
,fundrawtransaction
,walletcreatefundedpsbt
,send
,sendtoaddress
, andsendmany
ParseConfirmTarget()
/ error messageconf_target
sat/B unitsThis provides a spec and regression coverage for the potential next step of a universal
sat/vB
feerate argument (see #19543), as well as immediate coverage and minimum fixes for 0.21.