From 9f04e02ffaee0fe64027dc56c7bea3885254321a Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Thu, 10 Apr 2025 13:45:31 -0700 Subject: [PATCH] wallet: Disallow creating legacy wallets Remove the option to set descriptors=False when creating a wallet, and enforce this in RPC and in CreateWallet --- src/wallet/rpc/wallet.cpp | 20 ++++---------------- src/wallet/wallet.cpp | 14 ++++++-------- src/wallet/wallettool.cpp | 2 +- test/functional/wallet_createwallet.py | 14 ++------------ test/functional/wallet_listdescriptors.py | 5 ----- 5 files changed, 13 insertions(+), 42 deletions(-) diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp index 63bd8703989..4df23873fd8 100644 --- a/src/wallet/rpc/wallet.cpp +++ b/src/wallet/rpc/wallet.cpp @@ -355,9 +355,7 @@ static RPCHelpMan createwallet() {"blank", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed."}, {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."}, {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{false}, "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."}, - {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation." - " Setting to \"false\" will create a legacy wallet; This is only possible with the -deprecatedrpc=create_bdb setting because, the legacy wallet type is being deprecated and" - " support for creating and opening legacy wallets will be removed in the future."}, + {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "If set, must be \"true\""}, {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."}, {"external_signer", RPCArg::Type::BOOL, RPCArg::Default{false}, "Use an external signer such as a hardware wallet. Requires -signer to be configured. Wallet creation will fail if keys cannot be fetched. Requires disable_private_keys and descriptors set to true."}, }, @@ -402,13 +400,9 @@ static RPCHelpMan createwallet() if (!request.params[4].isNull() && request.params[4].get_bool()) { flags |= WALLET_FLAG_AVOID_REUSE; } - if (self.Arg("descriptors")) { - flags |= WALLET_FLAG_DESCRIPTORS; - } else { - if (!context.chain->rpcEnableDeprecated("create_bdb")) { - throw JSONRPCError(RPC_WALLET_ERROR, "BDB wallet creation is deprecated and will be removed in a future release." - " In this release it can be re-enabled temporarily with the -deprecatedrpc=create_bdb setting."); - } + flags |= WALLET_FLAG_DESCRIPTORS; + if (!self.Arg("descriptors")) { + throw JSONRPCError(RPC_WALLET_ERROR, "descriptors argument must be set to \"true\"; it is no longer possible to create a legacy wallet."); } if (!request.params[7].isNull() && request.params[7].get_bool()) { #ifdef ENABLE_EXTERNAL_SIGNER @@ -418,12 +412,6 @@ static RPCHelpMan createwallet() #endif } -#ifndef USE_BDB - if (!(flags & WALLET_FLAG_DESCRIPTORS)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without bdb support (required for legacy wallets)"); - } -#endif - DatabaseOptions options; DatabaseStatus status; ReadDatabaseArgs(*context.args, options); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9ae0fb5329e..efd18983940 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -385,11 +385,11 @@ std::shared_ptr CreateWallet(WalletContext& context, const std::string& uint64_t wallet_creation_flags = options.create_flags; const SecureString& passphrase = options.create_passphrase; - ArgsManager& args = *Assert(context.args); - if (wallet_creation_flags & WALLET_FLAG_DESCRIPTORS) options.require_format = DatabaseFormat::SQLITE; - else if (args.GetBoolArg("-swapbdbendian", false)) { - options.require_format = DatabaseFormat::BERKELEY_SWAP; + else { + error = Untranslated("Legacy wallets can no longer be created"); + status = DatabaseStatus::FAILED_CREATE; + return nullptr; } // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted @@ -3069,10 +3069,8 @@ std::shared_ptr CWallet::Create(WalletContext& context, const std::stri walletInstance->InitWalletFlags(wallet_creation_flags); - // Only create LegacyScriptPubKeyMan when not descriptor wallet - if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) { - walletInstance->SetupLegacyScriptPubKeyMan(); - } + // Only descriptor wallets can be created + assert(walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)); if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) || !(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) { LOCK(walletInstance->cs_wallet); diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index e2185a72fd7..feeb17988ed 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -131,7 +131,7 @@ bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command) return false; } if (args.GetBoolArg("-legacy", true)) { - tfm::format(std::cerr, "The -legacy option must be set to \"false\""); + tfm::format(std::cerr, "The -legacy option must be set to \"false\"\n"); return false; } } diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py index 14cac2a92ea..3fbbf5aac51 100755 --- a/test/functional/wallet_createwallet.py +++ b/test/functional/wallet_createwallet.py @@ -162,18 +162,8 @@ class CreateWalletTest(BitcoinTestFramework): self.log.info('Using a passphrase with private keys disabled returns error') assert_raises_rpc_error(-4, 'Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.', self.nodes[0].createwallet, wallet_name='w9', disable_private_keys=True, passphrase='thisisapassphrase') - if self.is_bdb_compiled(): - self.log.info("Test legacy wallet deprecation") - result = self.nodes[0].createwallet(wallet_name="legacy_w0", descriptors=False, passphrase=None) - assert_equal(result, { - "name": "legacy_w0", - "warnings": [LEGACY_WALLET_MSG], - }) - result = self.nodes[0].createwallet(wallet_name="legacy_w1", descriptors=False, passphrase="") - assert_equal(result, { - "name": "legacy_w1", - "warnings": [EMPTY_PASSPHRASE_MSG, LEGACY_WALLET_MSG], - }) + self.log.info("Test that legacy wallets cannot be created") + assert_raises_rpc_error(-4, 'descriptors argument must be set to "true"; it is no longer possible to create a legacy wallet.', self.nodes[0].createwallet, wallet_name="legacy", descriptors=False) if __name__ == '__main__': diff --git a/test/functional/wallet_listdescriptors.py b/test/functional/wallet_listdescriptors.py index 28f8d6a1891..263e4ea80ae 100755 --- a/test/functional/wallet_listdescriptors.py +++ b/test/functional/wallet_listdescriptors.py @@ -33,11 +33,6 @@ class ListDescriptorsTest(BitcoinTestFramework): node = self.nodes[0] assert_raises_rpc_error(-18, 'No wallet is loaded.', node.listdescriptors) - if self.is_bdb_compiled(): - self.log.info('Test that the command is not available for legacy wallets.') - node.createwallet(wallet_name='w1', descriptors=False) - assert_raises_rpc_error(-4, 'listdescriptors is not available for non-descriptor wallets', node.listdescriptors) - self.log.info('Test the command for empty descriptors wallet.') node.createwallet(wallet_name='w2', blank=True, descriptors=True) assert_equal(0, len(node.get_wallet_rpc('w2').listdescriptors()['descriptors']))