@@ -1992,10 +1992,29 @@ std::optional<MigrationData> LegacyDataSPKM::MigrateToDescriptor()
19921992 }
19931993 }
19941994
1995- // Multisigs are special. They don't show up as ISMINE_SPENDABLE unless they are in a P2SH
1996- // So we have to check if any of our scripts are a multisig and if so, add the P2SH
1997- for (const auto & script_pair : mapScripts) {
1998- const CScript script = script_pair.second ;
1995+ // Make sure that we have accounted for all scriptPubKeys
1996+ if (!Assume (spks.empty ())) {
1997+ LogPrintf (" %s\n " , STR_INTERNAL_BUG (" Error: Some output scripts were not migrated.\n " ));
1998+ return std::nullopt ;
1999+ }
2000+
2001+ // Legacy wallets can also contain scripts whose P2SH, P2WSH, or P2SH-P2WSH it is not watching for
2002+ // but can provide script data to a PSBT spending them. These "solvable" output scripts will need to
2003+ // be put into the separate "solvables" wallet.
2004+ // These can be detected by going through the entire candidate output scripts, finding the ISMINE_NO scripts,
2005+ // and checking CanProvide() which will dummy sign.
2006+ for (const CScript& script : GetCandidateScriptPubKeys ()) {
2007+ // Since we only care about P2SH, P2WSH, and P2SH-P2WSH, filter out any scripts that are not those
2008+ if (!script.IsPayToScriptHash () && !script.IsPayToWitnessScriptHash ()) {
2009+ continue ;
2010+ }
2011+ if (IsMine (script) != ISMINE_NO) {
2012+ continue ;
2013+ }
2014+ SignatureData dummy_sigdata;
2015+ if (!CanProvide (script, dummy_sigdata)) {
2016+ continue ;
2017+ }
19992018
20002019 // Get birthdate from script meta
20012020 uint64_t creation_time = 0 ;
@@ -2004,45 +2023,28 @@ std::optional<MigrationData> LegacyDataSPKM::MigrateToDescriptor()
20042023 creation_time = it->second .nCreateTime ;
20052024 }
20062025
2007- std::vector<std::vector<unsigned char >> sols;
2008- TxoutType type = Solver (script, sols);
2009- if (type == TxoutType::MULTISIG) {
2010- CScript sh_spk = GetScriptForDestination (ScriptHash (script));
2011- CTxDestination witdest = WitnessV0ScriptHash (script);
2012- CScript witprog = GetScriptForDestination (witdest);
2013- CScript sh_wsh_spk = GetScriptForDestination (ScriptHash (witprog));
2014-
2015- // We only want the multisigs that we have not already seen, i.e. they are not watchonly and not spendable
2016- // For P2SH, a multisig is not ISMINE_NO when:
2017- // * All keys are in the wallet
2018- // * The multisig itself is watch only
2019- // * The P2SH is watch only
2020- // For P2SH-P2WSH, if the script is in the wallet, then it will have the same conditions as P2SH.
2021- // For P2WSH, a multisig is not ISMINE_NO when, other than the P2SH conditions:
2022- // * The P2WSH script is in the wallet and it is being watched
2023- std::vector<std::vector<unsigned char >> keys (sols.begin () + 1 , sols.begin () + sols.size () - 1 );
2024- if (HaveWatchOnly (sh_spk) || HaveWatchOnly (script) || HaveKeys (keys, *this ) || (HaveCScript (CScriptID (witprog)) && HaveWatchOnly (witprog))) {
2025- // The above emulates IsMine for these 3 scriptPubKeys, so double check that by running IsMine
2026- assert (IsMine (sh_spk) != ISMINE_NO || IsMine (witprog) != ISMINE_NO || IsMine (sh_wsh_spk) != ISMINE_NO);
2027- continue ;
2028- }
2029- assert (IsMine (sh_spk) == ISMINE_NO && IsMine (witprog) == ISMINE_NO && IsMine (sh_wsh_spk) == ISMINE_NO);
2030-
2031- std::unique_ptr<Descriptor> sh_desc = InferDescriptor (sh_spk, *GetSolvingProvider (sh_spk));
2032- out.solvable_descs .emplace_back (sh_desc->ToString (), creation_time);
2026+ // InferDescriptor as that will get us all the solving info if it is there
2027+ std::unique_ptr<Descriptor> desc = InferDescriptor (script, *GetSolvingProvider (script));
2028+ if (!desc->IsSolvable ()) {
2029+ // The wallet was able to provide some information, but not enough to make a descriptor that actually
2030+ // contains anything useful. This is probably because the script itself is actually unsignable (e.g. P2WSH-P2WSH).
2031+ continue ;
2032+ }
20332033
2034- const auto desc = InferDescriptor (witprog, *this );
2035- if (desc->IsSolvable ()) {
2036- std::unique_ptr<Descriptor> wsh_desc = InferDescriptor (witprog, *GetSolvingProvider (witprog));
2037- out.solvable_descs .emplace_back (wsh_desc->ToString (), creation_time);
2038- std::unique_ptr<Descriptor> sh_wsh_desc = InferDescriptor (sh_wsh_spk, *GetSolvingProvider (sh_wsh_spk));
2039- out.solvable_descs .emplace_back (sh_wsh_desc->ToString (), creation_time);
2034+ // Past bugs in InferDescriptor have caused it to create descriptors which cannot be re-parsed
2035+ // Re-parse the descriptors to detect that, and skip any that do not parse.
2036+ {
2037+ std::string desc_str = desc->ToString ();
2038+ FlatSigningProvider parsed_keys;
2039+ std::string parse_error;
2040+ std::vector<std::unique_ptr<Descriptor>> parsed_descs = Parse (desc_str, parsed_keys, parse_error, false );
2041+ if (parsed_descs.empty ()) {
2042+ continue ;
20402043 }
20412044 }
2042- }
20432045
2044- // Make sure that we have accounted for all scriptPubKeys
2045- assert (spks. size () == 0 );
2046+ out. solvable_descs . emplace_back (desc-> ToString (), creation_time);
2047+ }
20462048
20472049 // Finalize transaction
20482050 if (!batch.TxnCommit ()) {
0 commit comments