From e27da3150b48ccf106ba93044bd28c6d1f505421 Mon Sep 17 00:00:00 2001 From: woltx <94266259+w0xlt@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:15:45 -0700 Subject: [PATCH 1/6] wallet: Remove `GetVersion()` --- src/wallet/rpc/wallet.cpp | 6 ++++-- src/wallet/wallet.h | 3 --- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp index 01413f02229..d68118994bf 100644 --- a/src/wallet/rpc/wallet.cpp +++ b/src/wallet/rpc/wallet.cpp @@ -40,7 +40,7 @@ static RPCHelpMan getwalletinfo() { { {RPCResult::Type::STR, "walletname", "the wallet name"}, - {RPCResult::Type::NUM, "walletversion", "the wallet version"}, + {RPCResult::Type::NUM, "walletversion", "(DEPRECATED) only related to unsupported legacy wallet, returns the latest version 169900 for backwards compatibility"}, {RPCResult::Type::STR, "format", "the database format (only sqlite)"}, {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"}, {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"}, @@ -82,9 +82,11 @@ static RPCHelpMan getwalletinfo() UniValue obj(UniValue::VOBJ); + const int latest_legacy_wallet_minversion{169900}; + size_t kpExternalSize = pwallet->KeypoolCountExternalKeys(); obj.pushKV("walletname", pwallet->GetName()); - obj.pushKV("walletversion", pwallet->GetVersion()); + obj.pushKV("walletversion", latest_legacy_wallet_minversion); obj.pushKV("format", pwallet->GetDatabase().Format()); obj.pushKV("txcount", (int)pwallet->mapWallet.size()); obj.pushKV("keypoolsize", (int64_t)kpExternalSize); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 95ed7af806a..1b1080fd81c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -828,9 +828,6 @@ public: //! signify that a particular wallet feature is now used. void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr) override; - //! get the current wallet format (the oldest client version guaranteed to understand this wallet) - int GetVersion() const { LOCK(cs_wallet); return nWalletVersion; } - //! Get wallet transactions that conflict with given transaction (spend same outputs) std::set GetConflicts(const Txid& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); From 63acee279756e72f96fda14a9963281860bf318b Mon Sep 17 00:00:00 2001 From: woltx <94266259+w0xlt@users.noreply.github.com> Date: Mon, 14 Jul 2025 23:12:31 -0700 Subject: [PATCH 2/6] wallet: Remove `GetClosestWalletFeature()` --- src/wallet/walletutil.cpp | 9 --------- src/wallet/walletutil.h | 1 - 2 files changed, 10 deletions(-) diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index 53e65d0194a..9b296aebed9 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -37,15 +37,6 @@ bool IsFeatureSupported(int wallet_version, int feature_version) return wallet_version >= feature_version; } -WalletFeature GetClosestWalletFeature(int version) -{ - static constexpr std::array wallet_features{FEATURE_LATEST, FEATURE_PRE_SPLIT_KEYPOOL, FEATURE_NO_DEFAULT_KEY, FEATURE_HD_SPLIT, FEATURE_HD, FEATURE_COMPRPUBKEY, FEATURE_WALLETCRYPT, FEATURE_BASE}; - for (const WalletFeature& wf : wallet_features) { - if (version >= wf) return wf; - } - return static_cast(0); -} - WalletDescriptor GenerateWalletDescriptor(const CExtPubKey& master_key, const OutputType& addr_type, bool internal) { int64_t creation_time = GetTime(); diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h index ef9d93eb07c..ca0786c1f37 100644 --- a/src/wallet/walletutil.h +++ b/src/wallet/walletutil.h @@ -31,7 +31,6 @@ enum WalletFeature }; bool IsFeatureSupported(int wallet_version, int feature_version); -WalletFeature GetClosestWalletFeature(int version); enum WalletFlags : uint64_t { // wallet flags in the upper section (> 1 << 31) will lead to not opening the wallet if flag is unknown From ba0158522981287f2fde83f38392baac0216b0b4 Mon Sep 17 00:00:00 2001 From: woltx <94266259+w0xlt@users.noreply.github.com> Date: Tue, 15 Jul 2025 00:45:18 -0700 Subject: [PATCH 3/6] wallet: `MigrateToDescriptor` no longer calls `CanSupportFeature` --- src/wallet/scriptpubkeyman.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index 730667dbdf4..0edb6ac967f 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -624,10 +624,13 @@ std::optional LegacyDataSPKM::MigrateToDescriptor() for (const auto& chain_pair : m_inactive_hd_chains) { chains.push_back(chain_pair.second); } + + bool can_support_hd_split_feature = m_hd_chain.nVersion >= CHDChain::VERSION_HD_CHAIN_SPLIT; + for (const CHDChain& chain : chains) { for (int i = 0; i < 2; ++i) { // Skip if doing internal chain and split chain is not supported - if (chain.seed_id.IsNull() || (i == 1 && !m_storage.CanSupportFeature(FEATURE_HD_SPLIT))) { + if (chain.seed_id.IsNull() || (i == 1 && !can_support_hd_split_feature)) { continue; } // Get the master xprv From 7cda3d0f5bdca64b11f966a60167cde5451071a3 Mon Sep 17 00:00:00 2001 From: woltx <94266259+w0xlt@users.noreply.github.com> Date: Tue, 15 Jul 2025 00:56:53 -0700 Subject: [PATCH 4/6] wallet: Remove `IsFeatureSupported()` and `CanSupportFeature()` --- src/wallet/rpc/wallet.cpp | 4 +--- src/wallet/scriptpubkeyman.h | 1 - src/wallet/wallet.h | 3 --- src/wallet/walletutil.cpp | 5 ----- src/wallet/walletutil.h | 2 -- 5 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp index d68118994bf..0a844fcee53 100644 --- a/src/wallet/rpc/wallet.cpp +++ b/src/wallet/rpc/wallet.cpp @@ -90,10 +90,8 @@ static RPCHelpMan getwalletinfo() obj.pushKV("format", pwallet->GetDatabase().Format()); obj.pushKV("txcount", (int)pwallet->mapWallet.size()); obj.pushKV("keypoolsize", (int64_t)kpExternalSize); + obj.pushKV("keypoolsize_hd_internal", pwallet->GetKeyPoolSize() - kpExternalSize); - if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) { - obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize)); - } if (pwallet->IsCrypted()) { obj.pushKV("unlocked_until", pwallet->nRelockTime); } diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index c6f6e37f2b9..f8086fdbff7 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -47,7 +47,6 @@ public: virtual WalletDatabase& GetDatabase() const = 0; virtual bool IsWalletFlagSet(uint64_t) const = 0; virtual void UnsetBlankWalletFlag(WalletBatch&) = 0; - virtual bool CanSupportFeature(enum WalletFeature) const = 0; virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr) = 0; //! Pass the encryption key to cb(). virtual bool WithEncryptionKey(std::function cb) const = 0; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 1b1080fd81c..c7c6c3c1070 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -556,9 +556,6 @@ public: int GetTxBlocksToMaturity(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool IsTxImmatureCoinBase(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - //! check whether we support the named feature - bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return IsFeatureSupported(nWalletVersion, wf); } - bool IsSpent(const COutPoint& outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); // Whether this or any known scriptPubKey with the same single key has been spent. diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index 9b296aebed9..3ee296a6725 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -32,11 +32,6 @@ fs::path GetWalletDir() return path; } -bool IsFeatureSupported(int wallet_version, int feature_version) -{ - return wallet_version >= feature_version; -} - WalletDescriptor GenerateWalletDescriptor(const CExtPubKey& master_key, const OutputType& addr_type, bool internal) { int64_t creation_time = GetTime(); diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h index ca0786c1f37..ba93a90ed97 100644 --- a/src/wallet/walletutil.h +++ b/src/wallet/walletutil.h @@ -30,8 +30,6 @@ enum WalletFeature FEATURE_LATEST = FEATURE_PRE_SPLIT_KEYPOOL }; -bool IsFeatureSupported(int wallet_version, int feature_version); - enum WalletFlags : uint64_t { // wallet flags in the upper section (> 1 << 31) will lead to not opening the wallet if flag is unknown // unknown wallet flags in the lower section <= (1 << 31) will be tolerated From 66de58208a713e16f0d48bceed4d7496eae4b05b Mon Sep 17 00:00:00 2001 From: woltx <94266259+w0xlt@users.noreply.github.com> Date: Tue, 15 Jul 2025 01:07:01 -0700 Subject: [PATCH 5/6] wallet: Remove `CWallet::nWalletVersion` and related functions --- src/wallet/scriptpubkeyman.h | 1 - src/wallet/test/wallet_tests.cpp | 1 - src/wallet/wallet.cpp | 23 ----------------------- src/wallet/wallet.h | 8 -------- src/wallet/walletdb.cpp | 20 -------------------- src/wallet/walletdb.h | 2 -- src/wallet/wallettool.cpp | 1 - test/functional/wallet_createwallet.py | 6 ++---- 8 files changed, 2 insertions(+), 60 deletions(-) diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index f8086fdbff7..905c5c003ba 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -47,7 +47,6 @@ public: virtual WalletDatabase& GetDatabase() const = 0; virtual bool IsWalletFlagSet(uint64_t) const = 0; virtual void UnsetBlankWalletFlag(WalletBatch&) = 0; - virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr) = 0; //! Pass the encryption key to cb(). virtual bool WithEncryptionKey(std::function cb) const = 0; virtual bool HasEncryptionKeys() const = 0; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 19feaca2060..b23b6e94603 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -492,7 +492,6 @@ BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup) const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), "", CreateMockableWalletDatabase()); LOCK(wallet->cs_wallet); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); - wallet->SetMinVersion(FEATURE_LATEST); wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS); BOOST_CHECK(!wallet->GetNewDestination(OutputType::BECH32, "")); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c7df818745f..9e3b9f678aa 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -639,23 +639,6 @@ void CWallet::SetLastBlockProcessed(int block_height, uint256 block_hash) WriteBestBlock(); } -void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in) -{ - LOCK(cs_wallet); - if (nWalletVersion >= nVersion) - return; - WalletLogPrintf("Setting minversion to %d\n", nVersion); - nWalletVersion = nVersion; - - { - WalletBatch* batch = batch_in ? batch_in : new WalletBatch(GetDatabase()); - if (nWalletVersion > 40000) - batch->WriteMinVersion(nWalletVersion); - if (!batch_in) - delete batch; - } -} - std::set CWallet::GetConflicts(const Txid& txid) const { std::set result; @@ -821,9 +804,6 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) } } - // Encryption was introduced in version 0.4.0 - SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch); - if (!encrypted_batch->TxnCommit()) { delete encrypted_batch; encrypted_batch = nullptr; @@ -2871,9 +2851,6 @@ std::shared_ptr CWallet::Create(WalletContext& context, const std::stri { LOCK(walletInstance->cs_wallet); - // ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key - walletInstance->SetMinVersion(FEATURE_LATEST); - // Init with passed flags. // Always set the cache upgrade flag as this feature is supported from the beginning. walletInstance->InitWalletFlags(wallet_creation_flags | WALLET_FLAG_LAST_HARDENED_XPUB_CACHED); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c7c6c3c1070..b9ca377538b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -321,9 +321,6 @@ private: std::atomic m_scanning_progress{0}; friend class WalletRescanReserver; - //! the current wallet version: clients below this version are not able to load the wallet - int nWalletVersion GUARDED_BY(cs_wallet){FEATURE_BASE}; - /** The next scheduled rebroadcast of wallet transactions. */ NodeClock::time_point m_next_resend{GetDefaultNextResend()}; /** Whether this wallet will submit newly created transactions to the node's mempool and @@ -585,8 +582,6 @@ public: //! Upgrade DescriptorCaches void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; return true; } - //! Marks destination as previously spent. void LoadAddressPreviouslySpent(const CTxDestination& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); //! Appends payment request to destination. @@ -822,9 +817,6 @@ public: unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - //! signify that a particular wallet feature is now used. - void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr) override; - //! Get wallet transactions that conflict with given transaction (spend same outputs) std::set GetConflicts(const Txid& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 2c0073f3568..79c2af24b29 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -199,11 +199,6 @@ bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext) return WriteIC(DBKeys::ORDERPOSNEXT, nOrderPosNext); } -bool WalletBatch::WriteMinVersion(int nVersion) -{ - return WriteIC(DBKeys::MINVERSION, nVersion); -} - bool WalletBatch::WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal) { std::string key = internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK; @@ -442,19 +437,6 @@ bool LoadHDChain(CWallet* pwallet, DataStream& ssValue, std::string& strErr) return true; } -static DBErrors LoadMinVersion(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) -{ - AssertLockHeld(pwallet->cs_wallet); - int nMinVersion = 0; - if (batch.Read(DBKeys::MINVERSION, nMinVersion)) { - pwallet->WalletLogPrintf("Wallet file version = %d\n", nMinVersion); - if (nMinVersion > FEATURE_LATEST) - return DBErrors::TOO_NEW; - pwallet->LoadMinVersion(nMinVersion); - } - return DBErrors::LOAD_OK; -} - static DBErrors LoadWalletFlags(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { AssertLockHeld(pwallet->cs_wallet); @@ -1137,8 +1119,6 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet) if (has_last_client) pwallet->WalletLogPrintf("Last client version = %d\n", last_client); try { - if ((result = LoadMinVersion(pwallet, *m_batch)) != DBErrors::LOAD_OK) return result; - // Load wallet flags, so they are known when processing other records. // The FLAGS key is absent during wallet creation. if ((result = LoadWalletFlags(pwallet, *m_batch)) != DBErrors::LOAD_OK) return result; diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 5327a2cf691..7a1dac3bce4 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -241,8 +241,6 @@ public: bool WriteOrderPosNext(int64_t nOrderPosNext); - bool WriteMinVersion(int nVersion); - bool WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey); bool WriteCryptedDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const std::vector& secret); bool WriteDescriptor(const uint256& desc_id, const WalletDescriptor& descriptor); diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index 228f3efbfb7..af32986ce65 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -31,7 +31,6 @@ static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flag { LOCK(wallet_instance->cs_wallet); - wallet_instance->SetMinVersion(FEATURE_LATEST); wallet_instance->InitWalletFlags(wallet_creation_flags); Assert(wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)); diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py index a2e7aae33ea..cf0d8b4e0b8 100755 --- a/test/functional/wallet_createwallet.py +++ b/test/functional/wallet_createwallet.py @@ -167,15 +167,13 @@ class CreateWalletTest(BitcoinTestFramework): 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) self.log.info("Check that the version number is being logged correctly") - with node.assert_debug_log(expected_msgs=[], unexpected_msgs=["Last client version = ", "Wallet file version = "]): + with node.assert_debug_log(expected_msgs=[], unexpected_msgs=["Last client version = "]): node.createwallet("version_check") wallet = node.get_wallet_rpc("version_check") - wallet_version = wallet.getwalletinfo()["walletversion"] client_version = node.getnetworkinfo()["version"] wallet.unloadwallet() with node.assert_debug_log( - expected_msgs=[f"Last client version = {client_version}", f"Wallet file version = {wallet_version}"], - unexpected_msgs=["Wallet file version = 10500"] + expected_msgs=[f"Last client version = {client_version}"] ): node.loadwallet("version_check") From 60d1042b9a4db8daf9fffdc29053652e99b7126e Mon Sep 17 00:00:00 2001 From: woltx <94266259+w0xlt@users.noreply.github.com> Date: Tue, 15 Jul 2025 01:14:25 -0700 Subject: [PATCH 6/6] wallet: Remove unused `WalletFeature` enums --- src/wallet/walletutil.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h index ba93a90ed97..e9e661819e3 100644 --- a/src/wallet/walletutil.h +++ b/src/wallet/walletutil.h @@ -11,24 +11,6 @@ #include namespace wallet { -/** (client) version numbers for particular wallet features */ -enum WalletFeature -{ - FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getwalletinfo's clientversion output) - - FEATURE_WALLETCRYPT = 40000, // wallet encryption - FEATURE_COMPRPUBKEY = 60000, // compressed public keys - - FEATURE_HD = 130000, // Hierarchical key derivation after BIP32 (HD Wallet) - - FEATURE_HD_SPLIT = 139900, // Wallet with HD chain split (change outputs will use m/0'/1'/k) - - FEATURE_NO_DEFAULT_KEY = 159900, // Wallet without a default key written - - FEATURE_PRE_SPLIT_KEYPOOL = 169900, // Upgraded to HD SPLIT and can have a pre-split keypool - - FEATURE_LATEST = FEATURE_PRE_SPLIT_KEYPOOL -}; enum WalletFlags : uint64_t { // wallet flags in the upper section (> 1 << 31) will lead to not opening the wallet if flag is unknown