diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index d713ee7c0a8..1ee433a02a6 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -358,6 +358,9 @@ public: //! support for writing null values to settings.json. //! Depending on the action returned by the update function, this will either //! update the setting in memory or write the updated settings to disk. + //! Returns false if the update function returned no action, or if the + //! settings could not be written to disk, including when settings are + //! disabled with -nosettings. In-memory changes are kept either way. virtual bool updateRwSetting(const std::string& name, const SettingsUpdate& update_function) = 0; //! Replace a setting in /settings.json with a new value. diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 130f9602bc6..c1dd8e7a4dd 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -843,7 +843,7 @@ public: }); if (!action) return false; // Now dump value to disk if requested - return *action != interfaces::SettingsAction::WRITE || args().WriteSettingsFile(); + return *action != interfaces::SettingsAction::WRITE || (args().GetSettingsPath() && args().WriteSettingsFile()); } bool overwriteRwSetting(const std::string& name, common::SettingsValue value, interfaces::SettingsAction action) override { diff --git a/test/functional/wallet_startup.py b/test/functional/wallet_startup.py index 2c5fb259059..ed07bb044a4 100755 --- a/test/functional/wallet_startup.py +++ b/test/functional/wallet_startup.py @@ -64,6 +64,35 @@ class WalletStartupTest(BitcoinTestFramework): # Reset directory permissions for cleanup dir_path.chmod(original_dir_perms) + def test_disabled_settings(self, node): + self.log.info("Test wallet startup preferences with dynamic settings disabled") + load_message = "Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup." + + settings_path = node.chain_path / "settings.json" + settings_before = settings_path.read_bytes() + self.restart_node(0, extra_args=["-nosettings"]) + assert_equal(node.listwallets(), ['']) + + assert_equal(node.createwallet(wallet_name="no_settings", load_on_startup=True), {"name": "no_settings", "warnings": [load_message]}) + assert_equal(set(node.listwallets()), {'', 'no_settings'}) + + # Leaving the startup preference unchanged does not warn, and the wallet remains usable. + assert_equal(node.unloadwallet(wallet_name="no_settings"), {}) + assert_equal(node.loadwallet(filename="no_settings"), {"name": "no_settings"}) + assert_equal(node.get_wallet_rpc("no_settings").getwalletinfo()["walletname"], "no_settings") + + assert_equal(node.loadwallet(filename="w2", load_on_startup=True), {"name": "w2", "warnings": [load_message]}) + assert_equal(set(node.listwallets()), {'', 'no_settings', 'w2'}) + + assert_equal(node.unloadwallet(wallet_name="no_settings", load_on_startup=False), {"warnings": ["Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."]}) + assert_equal(set(node.listwallets()), {'', 'w2'}) + self.stop_node(0) + assert_equal(settings_path.read_bytes(), settings_before) + + # Re-enabling settings restores the original startup preferences. + self.start_node(0) + assert_equal(set(node.listwallets()), {'w2', 'w3'}) + def run_test(self): self.log.info('Should start without any wallets') assert_equal(self.nodes[0].listwallets(), []) @@ -94,6 +123,7 @@ class WalletStartupTest(BitcoinTestFramework): assert_equal(set(self.nodes[0].listwallets()), set(('w2', 'w3'))) self.test_load_unwritable_wallet(self.nodes[0]) + self.test_disabled_settings(self.nodes[0]) if __name__ == '__main__': WalletStartupTest(__file__).main()