wallet: disallow migration of invalid or not-watched scripts

The legacy wallet allowed to import any raw script, without checking if
it was valid or not. Appending it to the watch-only set.

This causes a crash in the migration process because we are only
expecting to find valid scripts inside the legacy spkm.

These stored scripts internally map to `ISMINE_NO` (same as if they
weren't stored at all..).

So we need to check for these special case, and take into account that
the legacy spkm could be storing invalid not watched scripts.

Which, in code words, means IsMineInner() returning IsMineResult::INVALID
for them.
This commit is contained in:
furszy
2023-07-21 21:37:31 -03:00
parent d23fda0584
commit 1de8a2372a
3 changed files with 36 additions and 1 deletions

View File

@@ -1714,11 +1714,26 @@ 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;
}
std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()
{
LOCK(cs_KeyStore);