Removes the default fallback fee on mainnet (but keeps it on testnet/regtest).
Transactions using the fallbackfee in case the fallback fee has not been set are getting rejected.
Removes the default fallback fee on mainnet (but keeps it on testnet/regtest).
Transactions using the fallbackfee in case the fallback fee has not been set are getting rejected.
Not yet sure about adding a command line arg just to disable and disallow fallbackfee.
Using a static (!) fallback fee seems an incorrect concept. It will very likely result in significant overpay or significant underpay (==stuck transaction). I would strongly recommend to either reject during the time when no estimations are available or to collect fee estimations from somewhere else (probably controversial).
I would even vote for defaulting walletallowfallbackfee
to true (which this PR does not, it just offers the option to disable it).
walletallowfallbackfee
should be disabled by default.
Removing the fallback fee entirely would be an abrupt task and it would probably make regression tests more difficult. Reasonable steps are:
I think I am bad at choosing words. Let me explain by example:
conf
or on command line -> Consider as fallbackfee disabledconf
or on command line -> Consider fallbackfee enabledfallbackfee not set in conf or on command line -> Consider as fallbackfee disabled
That would disable the fallback fee by default. Right?
Agree with @MarcoFalke
we already have too many configuration options if you want to use fallbackfee, then set one, otherwise you don’t get one.
Sometimes we err too much on maintaining every aspect of backwards compatibility.
Just tell people in the release notes that RPC and GUI will now refuse to send when fee estimates are not initialized UNLESS you specifically instruct what feerate to fallback to.
We also already have the option to include the fee on a per transaction basis .
How would we handle regression tests (enable fallbackfee by default there)?
Jup, that makes sense to me. Don’t worry too much about the tests for now, you can ignore the travis result and then later push a test-fix commit that follows your implementation and is acceptable to everyone.
enablefallbackfee=<state>
).-walletfallbackfeerbf125
to fallbackfeerbf125
.@jonasschnelli Can we please get rid of both of the new options?
I haven’t understood why they are necessary.
We already have -fallbackfee
, it seems to me if you set that then you pretty clearly want to enable it and it doesn’t make sense to have an option to enable fallbackfee without explicitly specifying what you want it to be.
-fallbackfeerbf125
also seems unnecessary. In the GUI, we’ll already have the warning and can set rbf on a per transaction basis. I think we can just warn people using RPC that if they set a fallbackfee and don’t have rbf set, then they are taking some risk. Unlike the prior option, this at least serves some purpose, but its just so esoteric that I think it’s essentially clutter.
52@@ -53,6 +53,9 @@ CAmount GetMinimumFee(unsigned int nTxBytes, const CCoinControl& coin_control, c
53 // if we don't have enough data for estimateSmartFee, then use fallbackFee
54 fee_needed = CWallet::fallbackFee.GetFee(nTxBytes);
55 if (feeCalc) feeCalc->reason = FeeReason::FALLBACK;
56+
57+ // directly return if fallback fee is disabled (feerate 0 == disabled)
58+ if (CWallet::fallbackFee.GetFee(1000) == 0) return fee_needed;
shorter, faster and clearer:
0if (fee_needed == 0)
fee_needed == 0
seems the wrong check, it could be 0 in case you would run through with nTxBytes=0
, very unlikely, but testing the fallbackfee instead the current fee_needed
seems correct.
68@@ -66,7 +69,7 @@ CAmount GetMinimumFee(unsigned int nTxBytes, const CCoinControl& coin_control, c
69 CAmount required_fee = GetRequiredFee(nTxBytes);
70 if (required_fee > fee_needed) {
71 fee_needed = required_fee;
72- if (feeCalc) feeCalc->reason = FeeReason::REQUIRED;
73+ if (feeCalc && feeCalc->reason != FeeReason::FALLBACK) feeCalc->reason = FeeReason::REQUIRED;
Excuse my brevity, but I fail to see why fallbackfee is special cased here.
Let’s assume the user sets paytxfee to one satoshi per byte, but the required fee is higher. It will correctly report that the required fee rate was used.
Let’s assume the user sets fallbackfee to something very low and the required fee is higher. It will incorrectly report in the debug.log that the fallbackfee was used, no? Since in this case g_wallet_allow_fallback_fee
will be true, it won’t incorrectly hit the check in wallet.cpp.
So if there is a reason to add this piece of code, please explain and/or add a comment.
You right. It’s no longer in use. The question here is, that we return a single flag where a bitset would be required. Reason can be FeeReason::REQUIRED but also (AND) FeeReason::FALLBACK.
This code part was required to enable RBF125 in case a fallback fee has been used regardless of the mintxrelayfee. But no longer relevant, will remove.
0@@ -0,0 +1,27 @@
1+#!/usr/bin/env python3
2+# Copyright (c) 2014-2016 The Bitcoin Core developers
129@@ -130,6 +130,7 @@
130 'feature_logging.py',
131 'node_network_limited.py',
132 'conf_args.py',
133+ 'wallet-fallbackfee.py',
20+ # test sending a tx with disabled fallback fee (must fail)
21+ self.stop_nodes()
22+ self.start_node(0, extra_args=["-fallbackfee=0"])
23+ addr = self.nodes[0].getnewaddress()
24+ assert_raises_rpc_error(-4, "Fee estimation failed", self.nodes[0].sendtoaddress, addr, 1)
25+
Could also add tests for the other rpc that potentially hit this error:
E.g.
0 assert_raises_rpc_error(-4, "Fee estimation failed. Fallbackfee is disabled", lambda: self.nodes[0].fundrawtransaction(self.nodes[0].createrawtransaction([], {self.nodes[0].getnewaddress(): 1})))
1 assert_raises_rpc_error(-4, "Fee estimation failed. Fallbackfee is disabled", lambda: self.nodes[0].sendfrom("", self.nodes[0].getnewaddress(), 1))
2 assert_raises_rpc_error(-6, "Fee estimation failed. Fallbackfee is disabled", lambda: self.nodes[0].sendmany("", {self.nodes[0].getnewaddress(): 1}))
Thanks for adding the tests. I also slightly tested a previous version in the gui.
0-----BEGIN PGP SIGNED MESSAGE-----
1Hash: SHA512
2
3utACK 93ba98a6dcab49965e9080adeaf84984b3677e29
4-----BEGIN PGP SIGNATURE-----
5
6iQIcBAEBCgAGBQJaQRwAAAoJENLqSFDnUoslcdsP/241UP7KxSViikJmkv0XHYvx
7CKgsTPCnDBudbJoNYQ/dJ6pVuTcVUFUpJroOlsksUTX4SX1iz0t9zpXOqo1x+fQy
8VOD6vNqgOIHuhbbaDgc2kjeEcMLYTnLTLc+mQdEo2/2xlIWRfKKXhTyb5gCelAP+
9MykMhfXqM4Rrfnf/m+9eqP+ciMlxZlYUfKxFK4ZzijGw8tgTpXoVTVMR8cTtKFHw
101tqEXObZ8R3vMH+7JL3V2iriR9TuiWuKV7ZrHTvdpLYGw2XhkZe7RiL12WpiRjE6
11WT71333lg+HupGThjOKWtdEJo/oOt7ttatx8m/298Gp4Zw5auJh1Ij3u683/VR5I
12JdqHdm2J3GPzZ02zz34NR/IKpeX270z0R28nlJ/vHTeYOt3Z1v/CRqxeezzh1Go/
13hDcm/xQIbtXuELeayBg1wHthfPZpga9RsCKHkSR0hrl717ocDUIt6XvJBAFyquf1
14UhdR47Y9z2YUNjr/Gb4jRQjF8FvEpkEKIKdcsbCNbbhFpMnr0lE3VqRWEIsbPdcv
15daIJsqm7lnPP2Zy7mmE3QAK9I0nfOjaKi3SciSYpHJB7cGaXY+dlOtGkh66iE+YP
16xuVAxRrjbTDEwXmCF0rPCVThFZOWsqfUYhU8VtgE2FydGnKZXkGFPhJY4aXCIyDV
17cumCc/4r3Mf4LxPqIKRU
18=TzpY
19-----END PGP SIGNATURE-----
17+ # sending a transaction without fee estimations must be possible by default on regtest
18+ self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
19+
20+ # test sending a tx with disabled fallback fee (must fail)
21+ self.stop_nodes()
22+ self.start_node(0, extra_args=["-fallbackfee=0"])
stop
above and change here to restart
.
Needs rebase.
Concept ACK on setting the rbf flag on transactions where it is unclear if they confirm with the default fallback fee
I see 2 distinct options here: 1) automatically set RBF; 2) give error if coin control RBF is not set. From the UI point of view, being “preventive” is not that bad, I would go for option 2).
I think we can just warn people using RPC that if they set a fallbackfee and don’t have rbf set, then they are taking some risk
Should update descriptions of send/fund RPC?
Rebased and fixed the test nit reported by @promag.
Concept ACK on setting the rbf flag on transactions where it is unclear if they confirm with the default fallback fee
I see 2 distinct options here: 1) automatically set RBF; 2) give error if coin control RBF is not set. From the UI point of view, being “preventive” is not that bad, I would go for option 2).
The idea 1) has been removed (was there in a previous version of Core): #11882 (comment) For 2) / GUI UX optimization, see #11892.
15@@ -15,6 +16,9 @@
16
17 std::string GetWalletHelpString(bool showDebug)
18 {
19+ const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
138@@ -132,6 +139,7 @@ bool WalletParameterInteraction()
139 InitWarning(AmountHighWarn("-fallbackfee") + " " +
140 _("This is the transaction fee you may pay when fee estimates are not available."));
141 CWallet::fallbackFee = CFeeRate(nFeePerK);
142+ g_wallet_allow_fallback_fee = (nFeePerK == 0 ? false : true); //disable fallback fee in case value was set to 0, enable if non-null value
Nit
0g_wallet_allow_fallback_fee = nFeePerK != 0;
21+ self.restart_node(0, extra_args=["-fallbackfee=0"])
22+ assert_raises_rpc_error(-4, "Fee estimation failed", lambda: self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1))
23+ assert_raises_rpc_error(-4, "Fee estimation failed", lambda: self.nodes[0].fundrawtransaction(self.nodes[0].createrawtransaction([], {self.nodes[0].getnewaddress(): 1})))
24+ assert_raises_rpc_error(-4, "Fee estimation failed", lambda: self.nodes[0].sendfrom("", self.nodes[0].getnewaddress(), 1))
25+ assert_raises_rpc_error(-6, "Fee estimation failed", lambda: self.nodes[0].sendmany("", {self.nodes[0].getnewaddress(): 1}))
26+if __name__ == '__main__':
92@@ -91,6 +93,7 @@ class CChainParams
93 bool fMineBlocksOnDemand;
94 CCheckpointData checkpointData;
95 ChainTxData chainTxData;
96+ bool m_fallback_fee_enabled;
fMineBlocksOnDemand
above.
Take the following example:
0#include <iostream>
1using namespace std;
2
3struct s1 {
4 char a;
5 int b;
6};
7
8struct s2 {
9 char a;
10 int b;
11 char c;
12};
13
14struct s3 {
15 char a;
16 char c;
17 int b;
18};
19
20int main() {
21 cout << sizeof(s1) << endl;
22 cout << sizeof(s2) << endl;
23 cout << sizeof(s3) << endl;
24 return 0;
25}
on my system the output is
08
112
28
See http://www.catb.org/esr/structure-packing/#_structure_alignment_and_padding
But it’s no big deal in this case, but should be taken into account when it’s instanced a lot.
126@@ -123,6 +127,9 @@ bool WalletParameterInteraction()
127 _("This is the minimum transaction fee you pay on every transaction."));
128 CWallet::minTxFee = CFeeRate(n);
129 }
130+
131+ const CChainParams& chainParams = Params();
132+ g_wallet_allow_fallback_fee = chainParams.IsFallbackFeeEnabled();
Nit, shorter:
0g_wallet_allow_fallback_fee = Params().IsFallbackFeeEnabled();
43@@ -44,6 +44,7 @@ bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE;
44 bool fWalletRbf = DEFAULT_WALLET_RBF;
45 OutputType g_address_type = OUTPUT_TYPE_NONE;
46 OutputType g_change_type = OUTPUT_TYPE_NONE;
47+bool g_wallet_allow_fallback_fee = false; //<! will be defined via chainparams
Only changes were feedback addressed by promag.
0-----BEGIN PGP SIGNED MESSAGE-----
1Hash: SHA512
2
3re-ACK 3f592b81dcca3d2ef11403a623a6ba5b017567d7
4-----BEGIN PGP SIGNATURE-----
5
6iQIcBAEBCgAGBQJakuCeAAoJENLqSFDnUosl6WYP/AzLIKmB1aPMbpjXekqbBnqO
7jVzOfPXN2GIxGqbynZHKvof6EYYAwVG47hNVWy9wO6+vGiZtmAC/qlQnorb9pfZb
8oKNv1CDqK8dk8+LqHMSKggqAUHiJd0cP4mm8/GhySgewFCmjDVnYuHrpRNilsdHd
9Zk46bEgiSpAbAM6OtY/55CvCEMS0w6/Vn2CU8g5EAagoNIkJPhsaWS+Vq3wZJLlV
10MPrf+waPLGDykXionlbxEz4HZ37z3hSOkvB9wG/+L6j/kTyqnvUJS9haJaJ/4L7q
11VEKJd+zAcqshDnoIyQD7L8+5v4rKcr75MNHVzKUtFWeVJc/ouF5HgCdyGdjAQgrk
12FUZoaxrz6JYdbR7phfHtHzIcHtX5CipmgcS0JXdmVDxcY7iIsC8NVPRCfWm5kdTD
13HNN+cBLd7i0oEuWqFJN03zMZ6rE4iy9MsQ3nL2BbPU5fd3OXnZWWL4ARBGv5l1Fj
14qxNOenn4S21nvUOya6EOe7dcC36wRnv3asLUrCoJxLLJZKpqHsEBabRTDgSCcPoV
15DzCIr5igtaHwOYCnU/OxL5cK3xUrnqJ2vs71F1xkCKWZMb1MCpNs5DhX1GWdITRA
16T5XuEdJXsf7jVBoyZxCwwGJ40YVSiY9R0TkjQZ7sXJFOI440C5Q1GdzPCSrJRLAM
17htpBKa4NdBb6Q6x/meTx
18=Iq6n
19-----END PGP SIGNATURE-----