diff options
Diffstat (limited to 'src/script/descriptor.cpp')
-rw-r--r-- | src/script/descriptor.cpp | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index ba2334df49..7e62d75583 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -1413,8 +1413,16 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index, const Span<c return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider), apostrophe); } -std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider) +std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext ctx, const SigningProvider& provider) { + // Key cannot be hybrid + if (!pubkey.IsValidNonHybrid()) { + return nullptr; + } + // Uncompressed is only allowed in TOP and P2SH contexts + if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.IsCompressed()) { + return nullptr; + } std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, false); KeyOriginInfo info; if (provider.GetKeyOrigin(pubkey.GetID(), info)) { @@ -1491,12 +1499,14 @@ struct KeyParser { if (miniscript::IsTapscript(m_script_ctx) && end - begin == 32) { XOnlyPubKey pubkey; std::copy(begin, end, pubkey.begin()); - m_keys.push_back(InferPubkey(pubkey.GetEvenCorrespondingCPubKey(), ParseContext(), *m_in)); - return key; + if (auto pubkey_provider = InferPubkey(pubkey.GetEvenCorrespondingCPubKey(), ParseContext(), *m_in)) { + m_keys.push_back(std::move(pubkey_provider)); + return key; + } } else if (!miniscript::IsTapscript(m_script_ctx)) { - CPubKey pubkey{begin, end}; - if (pubkey.IsValidNonHybrid()) { - m_keys.push_back(InferPubkey(pubkey, ParseContext(), *m_in)); + CPubKey pubkey(begin, end); + if (auto pubkey_provider = InferPubkey(pubkey, ParseContext(), *m_in)) { + m_keys.push_back(std::move(pubkey_provider)); return key; } } @@ -1512,9 +1522,11 @@ struct KeyParser { CKeyID keyid(hash); CPubKey pubkey; if (m_in->GetPubKey(keyid, pubkey)) { - Key key = m_keys.size(); - m_keys.push_back(InferPubkey(pubkey, ParseContext(), *m_in)); - return key; + if (auto pubkey_provider = InferPubkey(pubkey, ParseContext(), *m_in)) { + Key key = m_keys.size(); + m_keys.push_back(std::move(pubkey_provider)); + return key; + } } return {}; } @@ -1849,8 +1861,8 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo if (txntype == TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) { CPubKey pubkey(data[0]); - if (pubkey.IsValidNonHybrid()) { - return std::make_unique<PKDescriptor>(InferPubkey(pubkey, ctx, provider)); + if (auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) { + return std::make_unique<PKDescriptor>(std::move(pubkey_provider)); } } if (txntype == TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) { @@ -1858,7 +1870,9 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo CKeyID keyid(hash); CPubKey pubkey; if (provider.GetPubKey(keyid, pubkey)) { - return std::make_unique<PKHDescriptor>(InferPubkey(pubkey, ctx, provider)); + if (auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) { + return std::make_unique<PKHDescriptor>(std::move(pubkey_provider)); + } } } if (txntype == TxoutType::WITNESS_V0_KEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH)) { @@ -1866,16 +1880,24 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo CKeyID keyid(hash); CPubKey pubkey; if (provider.GetPubKey(keyid, pubkey)) { - return std::make_unique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider)); + if (auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) { + return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider)); + } } } if (txntype == TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) { + bool ok = true; std::vector<std::unique_ptr<PubkeyProvider>> providers; for (size_t i = 1; i + 1 < data.size(); ++i) { CPubKey pubkey(data[i]); - providers.push_back(InferPubkey(pubkey, ctx, provider)); + if (auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) { + providers.push_back(std::move(pubkey_provider)); + } else { + ok = false; + break; + } } - return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers)); + if (ok) return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers)); } if (txntype == TxoutType::SCRIPTHASH && ctx == ParseScriptContext::TOP) { uint160 hash(data[0]); |