aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/wallet/scriptpubkeyman.cpp17
-rw-r--r--src/wallet/scriptpubkeyman.h6
-rw-r--r--src/wallet/wallet.cpp14
3 files changed, 36 insertions, 1 deletions
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 5b110b4d14..c3c027b8aa 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -1714,8 +1714,23 @@ std::unordered_set<CScript, SaltedSipHasher> LegacyScriptPubKeyMan::GetScriptPub
}
// All watchonly scripts are raw
- spks.insert(setWatchOnly.begin(), setWatchOnly.end());
+ for (const CScript& script : setWatchOnly) {
+ // As the legacy wallet allowed to import any script, we need to verify the validity here.
+ // LegacyScriptPubKeyMan::IsMine() return 'ISMINE_NO' for invalid or not watched scripts (IsMineResult::INVALID or IsMineResult::NO).
+ // e.g. a "sh(sh(pkh()))" which legacy wallets allowed to import!.
+ if (IsMine(script) != ISMINE_NO) spks.insert(script);
+ }
+
+ return spks;
+}
+std::unordered_set<CScript, SaltedSipHasher> LegacyScriptPubKeyMan::GetNotMineScriptPubKeys() const
+{
+ LOCK(cs_KeyStore);
+ std::unordered_set<CScript, SaltedSipHasher> spks;
+ for (const CScript& script : setWatchOnly) {
+ if (IsMine(script) == ISMINE_NO) spks.insert(script);
+ }
return spks;
}
diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h
index bf35c776ae..3c89a850cf 100644
--- a/src/wallet/scriptpubkeyman.h
+++ b/src/wallet/scriptpubkeyman.h
@@ -523,6 +523,12 @@ public:
std::set<CKeyID> GetKeys() const override;
std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
+ /**
+ * Retrieves scripts that were imported by bugs into the legacy spkm and are
+ * simply invalid, such as a sh(sh(pkh())) script, or not watched.
+ */
+ std::unordered_set<CScript, SaltedSipHasher> GetNotMineScriptPubKeys() const;
+
/** Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this LegacyScriptPubKeyMan.
* Does not modify this ScriptPubKeyMan. */
std::optional<MigrationData> MigrateToDescriptor();
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 8fa93b97d6..50f54e82fb 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -3920,6 +3920,13 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
return false;
}
+ // Get all invalid or non-watched scripts that will not be migrated
+ std::set<CTxDestination> not_migrated_dests;
+ for (const auto& script : legacy_spkm->GetNotMineScriptPubKeys()) {
+ CTxDestination dest;
+ if (ExtractDestination(script, dest)) not_migrated_dests.emplace(dest);
+ }
+
for (auto& desc_spkm : data.desc_spkms) {
if (m_spk_managers.count(desc_spkm->GetID()) > 0) {
error = _("Error: Duplicate descriptors created during migration. Your wallet may be corrupted.");
@@ -4026,6 +4033,13 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
continue;
}
}
+
+ // Skip invalid/non-watched scripts that will not be migrated
+ if (not_migrated_dests.count(addr_pair.first) > 0) {
+ dests_to_delete.push_back(addr_pair.first);
+ continue;
+ }
+
// Not ours, not in watchonly wallet, and not in solvable
error = _("Error: Address book data in wallet cannot be identified to belong to migrated wallets");
return false;