wallet: Disallow creating legacy wallets

Remove the option to set descriptors=False when creating a wallet, and
enforce this in RPC and in CreateWallet
This commit is contained in:
Ava Chow 2025-04-10 13:45:31 -07:00
parent 6b247279b7
commit 9f04e02ffa
5 changed files with 13 additions and 42 deletions

View file

@ -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<bool>("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<bool>("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);

View file

@ -385,11 +385,11 @@ std::shared_ptr<CWallet> 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> 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);

View file

@ -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;
}
}

View file

@ -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__':

View file

@ -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']))