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.
Concept ACK on setting the rbf flag on transactions where it is unclear if they confirm with the default fallback fee fee. Not yet sure about adding a command line arg just to disable and disallow fallbackfee.
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).
I think walletallowfallbackfee should be disabled by default.
If fee estimates are not available perhaps is best to ask the user to wait or to manually set a fee rate (if they are a sufficiently advanced user, maybe even behind a config flag to reduce mistakes). BIP125 replacement enabled helps only the case when you underpay and does nothing for overpaying.
Well, instead of adding a command line arg to disable fallbackfee, why not remove the default value for fallbackfee and require that it is set whenever it is used?
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?
Jup, if we want to disable by default, I'd prefer that way.
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)?
However, I'm fine with skipping step 1) (allow to disable) and directly disable it by default (with allow to enable).
Thats a good question. Maybe for testnet and regtest we have fallbackfee enabled by default? I'm not sure.. It does seem we're prone to errors that aren't caught by testing that way, but fundamentally testing fee estimation is hard. Another option is to just hard code in a fee estimate file for the functional tests that use the cached directory. But you'd still have the problem for all the others...
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.
Followed @morcos advice. This does now simply disable the default fallback fee on mainnet (keeps it on testnet/regtest). Transactions using the fallbackfee in case the fallback fee has not been set are getting rejected (on mainnet).
@jonasschnelli Needs rebase if still relevant. Also see #11918
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:
if (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.
Right, should only matter for unit tests, but makes sense to keep it that way.
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;
How is this not dead code?
Why would that be dead code?
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.
Fixed.
0 | @@ -0,0 +1,27 @@ 1 | +#!/usr/bin/env python3 2 | +# Copyright (c) 2014-2016 The Bitcoin Core developers
nit: off by two years, almost
Oh. Yes. Fixed.
129 | @@ -130,6 +130,7 @@ 130 | 'feature_logging.py', 131 | 'node_network_limited.py', 132 | 'conf_args.py', 133 | + 'wallet-fallbackfee.py',
Could move up by a few lines to avoid merge conflicts
Fixed.
Just some style nits inline
Concept ACK
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.
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})))
assert_raises_rpc_error(-4, "Fee estimation failed. Fallbackfee is disabled", lambda: self.nodes[0].sendfrom("", self.nodes[0].getnewaddress(), 1))
assert_raises_rpc_error(-6, "Fee estimation failed. Fallbackfee is disabled", lambda: self.nodes[0].sendmany("", {self.nodes[0].getnewaddress(): 1}))
Thanks. Added those tests.
Thanks for adding the tests. I also slightly tested a previous version in the gui.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
utACK 93ba98a6dcab49965e9080adeaf84984b3677e29
-----BEGIN PGP SIGNATURE-----
iQIcBAEBCgAGBQJaQRwAAAoJENLqSFDnUoslcdsP/241UP7KxSViikJmkv0XHYvx
CKgsTPCnDBudbJoNYQ/dJ6pVuTcVUFUpJroOlsksUTX4SX1iz0t9zpXOqo1x+fQy
VOD6vNqgOIHuhbbaDgc2kjeEcMLYTnLTLc+mQdEo2/2xlIWRfKKXhTyb5gCelAP+
MykMhfXqM4Rrfnf/m+9eqP+ciMlxZlYUfKxFK4ZzijGw8tgTpXoVTVMR8cTtKFHw
1tqEXObZ8R3vMH+7JL3V2iriR9TuiWuKV7ZrHTvdpLYGw2XhkZe7RiL12WpiRjE6
WT71333lg+HupGThjOKWtdEJo/oOt7ttatx8m/298Gp4Zw5auJh1Ij3u683/VR5I
JdqHdm2J3GPzZ02zz34NR/IKpeX270z0R28nlJ/vHTeYOt3Z1v/CRqxeezzh1Go/
hDcm/xQIbtXuELeayBg1wHthfPZpga9RsCKHkSR0hrl717ocDUIt6XvJBAFyquf1
UhdR47Y9z2YUNjr/Gb4jRQjF8FvEpkEKIKdcsbCNbbhFpMnr0lE3VqRWEIsbPdcv
daIJsqm7lnPP2Zy7mmE3QAK9I0nfOjaKi3SciSYpHJB7cGaXY+dlOtGkh66iE+YP
xuVAxRrjbTDEwXmCF0rPCVThFZOWsqfUYhU8VtgE2FydGnKZXkGFPhJY4aXCIyDV
cumCc/4r3Mf4LxPqIKRU
=TzpY
-----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"])
Remove 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.
Should probably use underscore for the test name (see other test script names)
Fixed the test name (uses now underscore).
15 | @@ -15,6 +16,9 @@ 16 | 17 | std::string GetWalletHelpString(bool showDebug) 18 | { 19 | + const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
Unused, remove? same below.
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
g_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__':
Missing newline before.
92 | @@ -91,6 +93,7 @@ class CChainParams 93 | bool fMineBlocksOnDemand; 94 | CCheckpointData checkpointData; 95 | ChainTxData chainTxData; 96 | + bool m_fallback_fee_enabled;
Nit, could be after fMineBlocksOnDemand above.
Can you explain why?
Take the following example:
#include <iostream>
using namespace std;
struct s1 {
char a;
int b;
};
struct s2 {
char a;
int b;
char c;
};
struct s3 {
char a;
char c;
int b;
};
int main() {
cout << sizeof(s1) << endl;
cout << sizeof(s2) << endl;
cout << sizeof(s3) << endl;
return 0;
}
on my system the output is
8
12
8
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:
g_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
Fallback fee yes or now seems to me after a global setting (not per wallet).
Ok then.
In which case it could be a static member, just saying
Fixed points reported by @promag
Only changes were feedback addressed by promag.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
re-ACK 3f592b81dcca3d2ef11403a623a6ba5b017567d7
-----BEGIN PGP SIGNATURE-----
iQIcBAEBCgAGBQJakuCeAAoJENLqSFDnUosl6WYP/AzLIKmB1aPMbpjXekqbBnqO
jVzOfPXN2GIxGqbynZHKvof6EYYAwVG47hNVWy9wO6+vGiZtmAC/qlQnorb9pfZb
oKNv1CDqK8dk8+LqHMSKggqAUHiJd0cP4mm8/GhySgewFCmjDVnYuHrpRNilsdHd
Zk46bEgiSpAbAM6OtY/55CvCEMS0w6/Vn2CU8g5EAagoNIkJPhsaWS+Vq3wZJLlV
MPrf+waPLGDykXionlbxEz4HZ37z3hSOkvB9wG/+L6j/kTyqnvUJS9haJaJ/4L7q
VEKJd+zAcqshDnoIyQD7L8+5v4rKcr75MNHVzKUtFWeVJc/ouF5HgCdyGdjAQgrk
FUZoaxrz6JYdbR7phfHtHzIcHtX5CipmgcS0JXdmVDxcY7iIsC8NVPRCfWm5kdTD
HNN+cBLd7i0oEuWqFJN03zMZ6rE4iy9MsQ3nL2BbPU5fd3OXnZWWL4ARBGv5l1Fj
qxNOenn4S21nvUOya6EOe7dcC36wRnv3asLUrCoJxLLJZKpqHsEBabRTDgSCcPoV
DzCIr5igtaHwOYCnU/OxL5cK3xUrnqJ2vs71F1xkCKWZMb1MCpNs5DhX1GWdITRA
T5XuEdJXsf7jVBoyZxCwwGJ40YVSiY9R0TkjQZ7sXJFOI440C5Q1GdzPCSrJRLAM
htpBKa4NdBb6Q6x/meTx
=Iq6n
-----END PGP SIGNATURE-----
utACK 3f592b8.