Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/scriptpubkeyman.cpp
Show First 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | for (const valtype &pubkey : pubkeys) { | ||||
CKeyID keyID = CPubKey(pubkey).GetID(); | CKeyID keyID = CPubKey(pubkey).GetID(); | ||||
if (!keystore.HaveKey(keyID)) { | if (!keystore.HaveKey(keyID)) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
//! Recursively solve script and return spendable/watchonly/invalid status. | |||||
//! | |||||
//! @param keystore legacy key and script store | |||||
//! @param script script to solve | |||||
//! @param sigversion script type (top-level / redeemscript / | |||||
//! witnessscript) | |||||
//! @param recurse_scripthash whether to recurse into nested p2sh and p2wsh | |||||
//! scripts or simply treat any script that has been | |||||
//! stored in the keystore as spendable | |||||
IsMineResult IsMineInner(const LegacyScriptPubKeyMan &keystore, | IsMineResult IsMineInner(const LegacyScriptPubKeyMan &keystore, | ||||
const CScript &scriptPubKey, | const CScript &scriptPubKey, | ||||
IsMineSigVersion sigversion) { | IsMineSigVersion sigversion, | ||||
bool recurse_scripthash = true) { | |||||
IsMineResult ret = IsMineResult::NO; | IsMineResult ret = IsMineResult::NO; | ||||
std::vector<valtype> vSolutions; | std::vector<valtype> vSolutions; | ||||
TxoutType whichType = Solver(scriptPubKey, vSolutions); | TxoutType whichType = Solver(scriptPubKey, vSolutions); | ||||
CKeyID keyID; | CKeyID keyID; | ||||
switch (whichType) { | switch (whichType) { | ||||
case TxoutType::NONSTANDARD: | case TxoutType::NONSTANDARD: | ||||
Show All 14 Lines | switch (whichType) { | ||||
case TxoutType::SCRIPTHASH: { | case TxoutType::SCRIPTHASH: { | ||||
if (sigversion != IsMineSigVersion::TOP) { | if (sigversion != IsMineSigVersion::TOP) { | ||||
// P2SH inside P2SH is invalid. | // P2SH inside P2SH is invalid. | ||||
return IsMineResult::INVALID; | return IsMineResult::INVALID; | ||||
} | } | ||||
CScriptID scriptID = CScriptID(uint160(vSolutions[0])); | CScriptID scriptID = CScriptID(uint160(vSolutions[0])); | ||||
CScript subscript; | CScript subscript; | ||||
if (keystore.GetCScript(scriptID, subscript)) { | if (keystore.GetCScript(scriptID, subscript)) { | ||||
ret = std::max(ret, IsMineInner(keystore, subscript, | ret = std::max(ret, recurse_scripthash | ||||
IsMineSigVersion::P2SH)); | ? IsMineInner(keystore, subscript, | ||||
IsMineSigVersion::P2SH) | |||||
: IsMineResult::SPENDABLE); | |||||
} | } | ||||
break; | break; | ||||
} | } | ||||
case TxoutType::MULTISIG: { | case TxoutType::MULTISIG: { | ||||
// Never treat bare multisig outputs as ours (they can still be made | // Never treat bare multisig outputs as ours (they can still be made | ||||
// watchonly-though) | // watchonly-though) | ||||
if (sigversion == IsMineSigVersion::TOP) { | if (sigversion == IsMineSigVersion::TOP) { | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 317 Lines • ▼ Show 20 Lines | |||||
std::unique_ptr<SigningProvider> | std::unique_ptr<SigningProvider> | ||||
LegacyScriptPubKeyMan::GetSolvingProvider(const CScript &script) const { | LegacyScriptPubKeyMan::GetSolvingProvider(const CScript &script) const { | ||||
return std::make_unique<LegacySigningProvider>(*this); | return std::make_unique<LegacySigningProvider>(*this); | ||||
} | } | ||||
bool LegacyScriptPubKeyMan::CanProvide(const CScript &script, | bool LegacyScriptPubKeyMan::CanProvide(const CScript &script, | ||||
SignatureData &sigdata) { | SignatureData &sigdata) { | ||||
if (IsMine(script) != ISMINE_NO) { | IsMineResult ismine = IsMineInner(*this, script, IsMineSigVersion::TOP, | ||||
// If it IsMine, we can always provide in some way | /* recurse_scripthash= */ false); | ||||
return true; | if (ismine == IsMineResult::SPENDABLE || | ||||
} | ismine == IsMineResult::WATCH_ONLY) { | ||||
if (HaveCScript(CScriptID(script))) { | // If ismine, it means we recognize keys or script ids in the script, or | ||||
// We can still provide some stuff if we have the script, but IsMine | // are watching the script itself, and we can at least provide metadata | ||||
// failed because we don't have keys | // or solving information, even if not able to sign fully. | ||||
return true; | return true; | ||||
} | } | ||||
// If, given the stuff in sigdata, we could make a valid sigature, then | // If, given the stuff in sigdata, we could make a valid sigature, then | ||||
// we can provide for this script | // we can provide for this script | ||||
ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, script, sigdata); | ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, script, sigdata); | ||||
if (!sigdata.signatures.empty()) { | if (!sigdata.signatures.empty()) { | ||||
// If we could make signatures, make sure we have a private key to | // If we could make signatures, make sure we have a private key to | ||||
// actually make a signature | // actually make a signature | ||||
▲ Show 20 Lines • Show All 1,802 Lines • Show Last 20 Lines |