aboutsummaryrefslogtreecommitdiff
path: root/src/script/descriptor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/descriptor.cpp')
-rw-r--r--src/script/descriptor.cpp52
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]);