From d28c989243df7a622b598806cc12f48272358ac1 Mon Sep 17 00:00:00 2001 From: David Gumberg Date: Tue, 24 Mar 2026 17:40:17 -0700 Subject: [PATCH 1/3] test: wallet: refactor: fallbackfee extract common send failure checks. --- test/functional/wallet_fallbackfee.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/test/functional/wallet_fallbackfee.py b/test/functional/wallet_fallbackfee.py index e6930627c44..b5244020306 100755 --- a/test/functional/wallet_fallbackfee.py +++ b/test/functional/wallet_fallbackfee.py @@ -2,13 +2,13 @@ # Copyright (c) 2017-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test wallet replace-by-fee capabilities in conjunction with the fallbackfee.""" +"""Test wallet fallbackfee.""" from test_framework.blocktools import COINBASE_MATURITY from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_raises_rpc_error -class WalletRBFTest(BitcoinTestFramework): +class WalletFallbackFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True @@ -16,17 +16,22 @@ class WalletRBFTest(BitcoinTestFramework): def skip_test_if_missing_module(self): self.skip_if_no_wallet() + def sending_fails(self, node): + assert_raises_rpc_error(-6, "Fee estimation failed", lambda: node.sendtoaddress(node.getnewaddress(), 1)) + assert_raises_rpc_error(-4, "Fee estimation failed", lambda: node.fundrawtransaction(node.createrawtransaction([], {node.getnewaddress(): 1}))) + assert_raises_rpc_error(-6, "Fee estimation failed", lambda: node.sendmany("", {node.getnewaddress(): 1})) + def run_test(self): - self.generate(self.nodes[0], COINBASE_MATURITY + 1) + node = self.nodes[0] + self.generate(node, COINBASE_MATURITY + 1) # sending a transaction without fee estimations must be possible by default on regtest - self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) + node.sendtoaddress(node.getnewaddress(), 1) - # test sending a tx with disabled fallback fee (must fail) + # Sending a tx with explicitly disabled fallback fee fails. self.restart_node(0, extra_args=["-fallbackfee=0"]) - assert_raises_rpc_error(-6, "Fee estimation failed", lambda: self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)) - assert_raises_rpc_error(-4, "Fee estimation failed", lambda: self.nodes[0].fundrawtransaction(self.nodes[0].createrawtransaction([], {self.nodes[0].getnewaddress(): 1}))) - assert_raises_rpc_error(-6, "Fee estimation failed", lambda: self.nodes[0].sendmany("", {self.nodes[0].getnewaddress(): 1})) + self.sending_fails(node) + if __name__ == '__main__': - WalletRBFTest(__file__).main() + WalletFallbackFeeTest(__file__).main() From 6664e41e56a184254372a5a2642ceb4f5059a9bc Mon Sep 17 00:00:00 2001 From: David Gumberg Date: Tue, 24 Mar 2026 17:44:46 -0700 Subject: [PATCH 2/3] test: wallet: -fallbackfee default is 0 Also check more RPC's for success and check that we are using `-fallbackfee`. --- test/functional/wallet_fallbackfee.py | 35 ++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/test/functional/wallet_fallbackfee.py b/test/functional/wallet_fallbackfee.py index b5244020306..b2a76b8550b 100755 --- a/test/functional/wallet_fallbackfee.py +++ b/test/functional/wallet_fallbackfee.py @@ -4,9 +4,14 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test wallet fallbackfee.""" +from decimal import Decimal + from test_framework.blocktools import COINBASE_MATURITY from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_raises_rpc_error +from test_framework.util import assert_equal, assert_raises_rpc_error + +HIGH_TX_FEE_PER_KB = Decimal('0.01') + class WalletFallbackFeeTest(BitcoinTestFramework): def set_test_params(self): @@ -16,6 +21,18 @@ class WalletFallbackFeeTest(BitcoinTestFramework): def skip_test_if_missing_module(self): self.skip_if_no_wallet() + def sending_succeeds(self, node): + # Check that fallback fee is being used as a test-of-the-test. + assert_equal( + node.sendtoaddress(node.getnewaddress(), 1, verbose=True)['fee_reason'], + "Fallback fee" + ) + node.fundrawtransaction(node.createrawtransaction([], {node.getnewaddress(): 1})) + assert_equal( + node.sendmany("", {node.getnewaddress(): 1}, verbose=True)["fee_reason"], + "Fallback fee" + ) + def sending_fails(self, node): assert_raises_rpc_error(-6, "Fee estimation failed", lambda: node.sendtoaddress(node.getnewaddress(), 1)) assert_raises_rpc_error(-4, "Fee estimation failed", lambda: node.fundrawtransaction(node.createrawtransaction([], {node.getnewaddress(): 1}))) @@ -25,13 +42,25 @@ class WalletFallbackFeeTest(BitcoinTestFramework): node = self.nodes[0] self.generate(node, COINBASE_MATURITY + 1) - # sending a transaction without fee estimations must be possible by default on regtest - node.sendtoaddress(node.getnewaddress(), 1) + # By default, the test framework sets a fallback fee for nodes, + # in order to test default behavior, comment this line out. + node.replace_in_config([("fallbackfee=", "#fallbackfee=")]) + self.restart_node(0) + + # Sending a transaction with no -fallbackfee setting fails, since the + # default value is 0. + self.sending_fails(node) # Sending a tx with explicitly disabled fallback fee fails. self.restart_node(0, extra_args=["-fallbackfee=0"]) self.sending_fails(node) + # Sending a transaction with a fallback fee set succeeds. Use the + # largest fallbackfee value that doesn't trigger a warning. + self.restart_node(0, extra_args=[f"-fallbackfee={HIGH_TX_FEE_PER_KB}"]) + self.sending_succeeds(node) + self.stop_node(0, expected_stderr='') + if __name__ == '__main__': WalletFallbackFeeTest(__file__).main() From 3dcdb2b9ba18a848d7108d754a60a9ed5530f7a4 Mon Sep 17 00:00:00 2001 From: David Gumberg Date: Thu, 22 Jan 2026 13:05:51 -0800 Subject: [PATCH 3/3] test: wallet: Warning for excessive fallback fee. --- test/functional/wallet_fallbackfee.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/functional/wallet_fallbackfee.py b/test/functional/wallet_fallbackfee.py index b2a76b8550b..23fa5b681c3 100755 --- a/test/functional/wallet_fallbackfee.py +++ b/test/functional/wallet_fallbackfee.py @@ -61,6 +61,15 @@ class WalletFallbackFeeTest(BitcoinTestFramework): self.sending_succeeds(node) self.stop_node(0, expected_stderr='') + # Starting a node with a large fallback fee set... + excessive_fallback = HIGH_TX_FEE_PER_KB + Decimal('0.00000001') + self.start_node(0, extra_args=[f"-fallbackfee={excessive_fallback}"]) + # ...works... + self.sending_succeeds(node) + # ...but results in a warning message. + expected_error = "Warning: -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available." + self.stop_node(0, expected_stderr=expected_error) + if __name__ == '__main__': WalletFallbackFeeTest(__file__).main()