Skip to content

Conversation

jonatack
Copy link
Member

@jonatack jonatack commented Nov 5, 2020

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 wallet, rpc: explicit fee rate follow-ups/fixes for 0.21 #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

@maflcko
Copy link
Member

maflcko commented Nov 5, 2020

How does this differ/compare to #20250 ?

@maflcko
Copy link
Member

maflcko commented Nov 5, 2020

I guess this one is adding a new separate option, #20250 is adding named aliases and keeping the existing options.

@jonatack
Copy link
Member Author

jonatack commented Nov 5, 2020

Yes, this one removes the conf_target/estimate_mode overloading and introduces a standard fee rate param.

#20250 keeps the current overloading and makes it more consistent between the six RPCs. Some of what it does (feeRate -> fee_rate) is compatible or orthogonal.

ISTM the question is, do we want to release with the overloading or with a standard feerate param. (It would be simpler if we decide before the branch-off. After, this PR would need to be changed as we would have to support both.)

@DrahtBot
Copy link
Contributor

DrahtBot commented Nov 5, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, 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.

@luke-jr
Copy link
Member

luke-jr commented Nov 6, 2020

AFAICT, the only "fee_rate" in 0.20 was bumpfee. Specifying BTC/vkB (current value) in place of the new sat/vB would always be a much lower feerate. So it'd most likely be too low and error, or worst case lower than you intended and you can just bump it again to fix.

With that in mind, I think the option here should just be renamed to "fee_rate" and break the compatibility for bumpfee.

@jonatack
Copy link
Member Author

jonatack commented Nov 6, 2020

@luke-jr SGTM and that would further simplify the implementation too.

@achow101
Copy link
Member

achow101 commented Nov 6, 2020

Agree with renaming to fee_rate. However having two fee rate options for some RPCs is kinda weird. I suppose it's too late to fix that for this release, but it'd be nice to not do that in the future.

Concept ACK.

@meshcollider
Copy link
Contributor

Concept ACK for fee_rate

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why fee_rate_sat_vb and not just fee_rate? Also, should not change verbose parameter index?

@jonatack
Copy link
Member Author

jonatack commented Nov 9, 2020

Why fee_rate_sat_vb and not just fee_rate?

I initially began with fee_rate in #20231. Then, based on #20220 (comment) I changed to fee_rate_sat_vb here. Today, based on the feedback at last Friday's wallet meeting and here, I will push an update to use fee_rate.

Also, should not change verbose parameter index?

For sendtoaddress and sendmany, I hesitated on this because I thought that users are used to seeing the verbose argument placed last, e.g. like gettransaction. If positional true or false are passed for the fee_rate, a type error will be raised and the transaction won't proceed. Is it better to put fee_rate after verbose instead?

@maflcko
Copy link
Member

maflcko commented Nov 9, 2020

Has verbose been in a release already?

@jonatack
Copy link
Member Author

jonatack commented Nov 9, 2020

Per d5863c0 it looks like verbose was added to sendtoaddress and sendmany after the 0.20 release. Not a bugfix, so probably not backported. Checking. Edit: nope, they aren't in 0.20.0 or 0.20.1. We're good.

@jonatack jonatack changed the title wallet: introduce fee_rate_sat_vb param/option wallet: introduce fee_rate param/option Nov 9, 2020
@jonatack jonatack changed the title wallet: introduce fee_rate param/option wallet: introduce fee_rate sat/vB param/option Nov 9, 2020
Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review up to ~3/4 of 53b35be. Will continue in approx 60 minutes.


cc.m_feerate = CFeeRate(fee_rate);
CAmount feerate{AmountFromValue(estimate_param)};
cc.m_feerate = cc.m_fee_mode == FeeEstimateMode::SAT_B ? CFeeRate(feerate, COIN) : CFeeRate(feerate);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not immediately obvious to me why CFeeRate(feerate, COIN) is equivalent to fee_rate /= WALLET_BTC_KB_TO_SAT_B; CFeeRate(fee_rate). As far as I see, COIN equals 1e8, but WALLET_BTC_KB_TO_SAT_B equals 1e5.

Upon inspection of ./src/policy/feerate.cpp and ./src/policy/feerate.h, CFeeRate(…) with two arguments appears to construct a fee rate in sat/kvB from fees paid in sats divided by transaction weight in vB:

    /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/
    CFeeRate(const CAmount& nFeePaid, size_t nBytes);
CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nBytes_)
{
    assert(nBytes_ <= uint64_t(std::numeric_limits<int64_t>::max()));
    int64_t nSize = int64_t(nBytes_);

    if (nSize > 0)
        nSatoshisPerK = nFeePaid * 1000 / nSize;
    else
        nSatoshisPerK = 0;
}

and either results in the feerate having been divided by 100,000 (1e5). ✔️

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes 👍 and I was more confident about making this change after all the test coverage we added in #20220.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have a comment explaining this because it is not immediately clear why this works and future work on this code may not see this explanation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, added Doxygen documentation in a3eac6e

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like a hack, unless I misunderstand the original purpose of this constructor. Maybe it's better to add a separate constructor with a boolean to distinguish SAT_VB from BTC/kvB.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I asked myself why else the two-argument ctor might have been written and didn't come up with an answer...I'm not against reviewing a refactoring of it.

Copy link
Member Author

@jonatack jonatack Nov 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at settxfee in wallet/rpcwallet.cpp, it uses this ctor in a similar manner.

    CAmount nAmount = AmountFromValue(request.params[0]);
    CFeeRate tx_fee_rate(nAmount, 1000);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like a hack, unless I misunderstand the original purpose of this constructor. Maybe it's better to add a separate constructor with a boolean to distinguish SAT_VB from BTC/kvB.

@Sjors done, proposed a separate constructor in 9c479bf

assert_raises_rpc_error(-8, "Invalid fee_rate 0.00000000 BTC/kB (must be greater than 0)",
self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"feeRate": 0, "add_inputs": True})
for param, value in {("fee_rate", 100000), ("feeRate", 1.1)}:
assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably out of scope, but it would be kinda nice if an error like this told the user what said limit is.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree--punting on this for the next push but would be good.

Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me! Gonna circle back tomorrow after I get up. :)

Comment on lines -113 to +110
assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, rbfid, options)
# Bumping to just above minrelay should fail to increase the total fee enough.
assert_raises_rpc_error(-8, "Insufficient total fee 0.00000141, must be at least 0.00001704 (oldFee 0.00000999 + incrementalFee 0.00000705)",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting hung up on all the wrong things, but if minRelayTxFee × txsize is 141 sats, I'm surprised that the incrementalFee is 705. I thought that minimum increments are equal to minRelayTxFee.

Copy link
Member Author

@jonatack jonatack Nov 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's from wallet/wallet.h, though the different fee constants and config options are a bit confusing to me.

//! minimum recommended increment for BIP 125 replacement txs
static const CAmount WALLET_INCREMENTAL_RELAY_FEE = 5000;

and wallet/feebumper.cpp

    if (new_total_fee < minTotalFee) {
        errors.push_back(strprintf(Untranslated("Insufficient total fee %s, must be at least %s (oldFee %s + incrementalFee %s)"),
            FormatMoney(new_total_fee), FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxTxSize)), FormatMoney(incrementalRelayFee.GetFee(maxTxSize))));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tracking that down!

self.log.info("Test invalid fee rate settings")
assert_raises_rpc_error(-8, "Invalid fee_rate 0.00000000 BTC/kB (must be greater than 0)",
rbf_node.bumpfee, rbfid, {"fee_rate": 0})
assert_raises_rpc_error(-4, "Specified or calculated fee 0.141 is too high (cannot be higher than -maxtxfee 0.10",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woah, damn. I think we may want to have a look at the maxtxfee that's a lot of money.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be a good follow-up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I proposed that once: #16539

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I proposed that once: #16539

TIL, thanks. Interesting discussion in that PR.

"At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
"returned by getnetworkinfo) to enter the node's mempool.\n",
"returned by getnetworkinfo) to enter the node's mempool.\n"
"* WARNING: before version 0.21, fee_rate was in " + CURRENCY_UNIT + "/kvB. As of 0.21, fee_rate is in " + CURRENCY_ATOM + "/vB. *\n",
Copy link
Contributor

@murchandamus murchandamus Nov 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Luckily, this is very benign. In the worst case, someone is going to get upped to the minRelayTxFee silently and sends at 1 sat/vB. Since RBF is on by default, they should be able to bump when they notice. 👍

@@ -4369,8 +4363,7 @@ static RPCHelpMan walletcreatefundedpsbt()
},
{"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n"
"Allows this transaction to be replaced by a transaction with higher fees"},
{"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target (in blocks)\n"
"or fee rate (for " + CURRENCY_UNIT + "/kB and " + CURRENCY_ATOM + "/B estimate modes)"},
{"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overloading, begone! 🎆

@@ -2303,7 +2303,7 @@ static RPCHelpMan settxfee()
"\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n"
"Can be deactivated by passing 0 as the fee. In that case automatic fee selection will be used by default.\n",
{
{"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kB"},
{"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kvB"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that you considered and deliberately passed on also replacing these. I would surmise that it's it just too much of a can of worms? Otherwise it would be kinda odd that we are using sat/vB for the fee rate in all the send variants, but then use BTC/kvB for settxfee.

Nit: settxfee sets not a fee, but a feerate. ;)

Copy link
Member Author

@jonatack jonatack Nov 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, scope creep on an already-wide PR. Could be a next step.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in #20391.

@achow101
Copy link
Member

ACK 5660dd3

@murchandamus
Copy link
Contributor

tACK 05e82d8

@Sjors
Copy link
Member

Sjors commented Nov 14, 2020

If there's still block explorers (that people use) using real bytes instead of virtual bytes in their fee calculation, then indeed adding the v might be necessary. Either way, don't let it hold back this PR.

@murchandamus
Copy link
Contributor

Just to provide two examples:

This first is from Blockchair providing the fee per raw size as [sat/B] next to the actual feerate: image

This second is Blockchain.com, providing fee per raw size as [sat/B] next to actual [sat/WU]:
image

@luke-jr
Copy link
Member

luke-jr commented Nov 16, 2020

Block explorer websites have been confusing users with bogus "information" forever. Trying to match them doesn't make sense.

@maflcko
Copy link
Member

maflcko commented Nov 17, 2020

review ACK 05e82d8 did not test and found a few style nits, which can be fixed later 🍯

Show signature and timestamp

Signature:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

review ACK 05e82d86b0 did not test and found a few style nits, which can be fixed later 🍯
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUi04QwAtjdQi2xSn12WwCON4MXuHDxB7owu5U1QxHMD5UpoaASOromS45wnAaaS
X2VhwFoYWJWkPAeCycZ0yr+tyhjr91Z8JqcPpPheryzIKyVys1QMSVVU4Nc4m/2D
PrQOhzn5BX74CnYU+lNoqRECzKslJGXypjWnJz8zmyGU41IDbl7LxQf5sOwYw0kD
k0LDLAcQyg1jLhAwlIvhFMccvzUGz49eXxRfpSO/8qghRm4thKyLvQ7l3nN+zGM7
lQuYdo3MU+OOi82fHJAnsLVwziDVxe0hVr1/r4OHaaeRMJsFSzPVRVox/JV7Zq1E
B8OG5GtifbGR1TqTYhUFZaNCVLKiFCmiKn2SY1VR6UoGonHGgtz/JnQzmpSJbqAd
5i4HtojlkPgtMlLuEadZWmwVNNcpJzgpWjubbc0489/5rrhBg9E+tSSQ0KvclzTg
ZBAEKdSJWy/jGvyxZri7Rzp+Z8c13cLo/oWKw98Y6PV12+uNNv2M+DV/jdQkEasW
GaGTrQnL
=h9+z
-----END PGP SIGNATURE-----

python: error while loading shared libraries: libpython3.8.so.1.0: cannot open shared object file: No such file or directory

@maflcko maflcko merged commit 80e32e1 into bitcoin:master Nov 17, 2020
@Sjors
Copy link
Member

Sjors commented Nov 17, 2020

I contacted one such explorer and nagged them to switch from bytes to vbytes :-)

@jonatack jonatack deleted the fee_rate_sat_vb branch November 17, 2020 13:04
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Nov 17, 2020
@maflcko
Copy link
Member

maflcko commented Nov 17, 2020

This probably needs release notes?

@maflcko
Copy link
Member

maflcko commented Nov 17, 2020

Btw, the first commit adds tests that pass without the code changes. I haven't tried the other added tests, but as a general rule, I'd prefer if new tests were added in a separate commit and not in the same commit that also changes behaviour.

@jonatack
Copy link
Member Author

This probably needs release notes?

Yes, will update the wiki.

@maflcko
Copy link
Member

maflcko commented Nov 17, 2020

Turns out the style nits are regressions. See https://github.com/bitcoin/bitcoin/pull/20305/files#r525406176 and #20410

Copy link

@MONIMAKER365 MONIMAKER365 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonatack
Copy link
Member Author

Release notes added to the wiki at https://github.com/bitcoin-core/bitcoin-devwiki/wiki/0.21.0-Release-Notes-Draft.

The Needs release note tag can be removed.

janus pushed a commit to janus/bitgesell that referenced this pull request Dec 13, 2020
in RPCs fundrawtransaction and walletcreatefundedpsbt only.

This provides the existing feeRate (BTC/kvB) behavior in these two RPCs to the
new fee_rate (sat/vB) param also.

See these two GitHub review discussions for more info:
bitcoin/bitcoin#10706
bitcoin/bitcoin#20305 (comment)
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.