@@ -1992,10 +1992,29 @@ std::optional<MigrationData> LegacyDataSPKM::MigrateToDescriptor()
1992
1992
}
1993
1993
}
1994
1994
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
+ }
1999
2018
2000
2019
// Get birthdate from script meta
2001
2020
uint64_t creation_time = 0 ;
@@ -2004,45 +2023,28 @@ std::optional<MigrationData> LegacyDataSPKM::MigrateToDescriptor()
2004
2023
creation_time = it->second .nCreateTime ;
2005
2024
}
2006
2025
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
+ }
2033
2033
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 ;
2040
2043
}
2041
2044
}
2042
- }
2043
2045
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
+ }
2046
2048
2047
2049
// Finalize transaction
2048
2050
if (!batch.TxnCommit ()) {
0 commit comments