diff options
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/descriptor.cpp | 46 | ||||
-rw-r--r-- | src/script/sign.cpp | 5 |
2 files changed, 45 insertions, 6 deletions
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 34a4da74f8..9bcbe1ceef 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -328,7 +328,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider { if (!GetExtKey(arg, xprv)) return false; for (auto entry : m_path) { - xprv.Derive(xprv, entry); + if (!xprv.Derive(xprv, entry)) return false; if (entry >> 31) { last_hardened = xprv; } @@ -388,14 +388,13 @@ public: } } else { for (auto entry : m_path) { - der = parent_extkey.Derive(parent_extkey, entry); - assert(der); + if (!parent_extkey.Derive(parent_extkey, entry)) return false; } final_extkey = parent_extkey; if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos); assert(m_derive != DeriveType::HARDENED); } - assert(der); + if (!der) return false; final_info_out = final_info_out_tmp; key_out = final_extkey.pubkey; @@ -498,8 +497,8 @@ public: CExtKey extkey; CExtKey dummy; if (!GetDerivedExtKey(arg, extkey, dummy)) return false; - if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos); - if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL); + if (m_derive == DeriveType::UNHARDENED && !extkey.Derive(extkey, pos)) return false; + if (m_derive == DeriveType::HARDENED && !extkey.Derive(extkey, pos | 0x80000000UL)) return false; key = extkey.key; return true; } @@ -1015,6 +1014,24 @@ public: bool IsSingleType() const final { return true; } }; +/** A parsed rawtr(...) descriptor. */ +class RawTRDescriptor final : public DescriptorImpl +{ +protected: + std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript> scripts, FlatSigningProvider& out) const override + { + assert(keys.size() == 1); + XOnlyPubKey xpk(keys[0]); + if (!xpk.IsFullyValid()) return {}; + WitnessV1Taproot output{xpk}; + return Vector(GetScriptForDestination(output)); + } +public: + RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(Vector(std::move(output_key)), "rawtr") {} + std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32M; } + bool IsSingleType() const final { return true; } +}; + //////////////////////////////////////////////////////////////////////////// // Parser // //////////////////////////////////////////////////////////////////////////// @@ -1453,6 +1470,16 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const error = "Can only have tr at top level"; return nullptr; } + if (ctx == ParseScriptContext::TOP && Func("rawtr", expr)) { + auto arg = Expr(expr); + auto output_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out, error); + if (!output_key) return nullptr; + ++key_exp_index; + return std::make_unique<RawTRDescriptor>(std::move(output_key)); + } else if (Func("rawtr", expr)) { + error = "Can only have rawtr at top level"; + return nullptr; + } if (ctx == ParseScriptContext::TOP && Func("raw", expr)) { std::string str(expr.begin(), expr.end()); if (!IsHex(str)) { @@ -1626,6 +1653,13 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo } } } + // If the above doesn't work, construct a rawtr() descriptor with just the encoded x-only pubkey. + if (pubkey.IsFullyValid()) { + auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider); + if (key) { + return std::make_unique<RawTRDescriptor>(std::move(key)); + } + } } if (ctx == ParseScriptContext::P2WSH) { diff --git a/src/script/sign.cpp b/src/script/sign.cpp index a63b042ccc..4014ebadbc 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -243,6 +243,11 @@ static bool SignTaproot(const SigningProvider& provider, const BaseSignatureCrea sigdata.taproot_key_path_sig = sig; } } + if (sigdata.taproot_key_path_sig.size() == 0) { + if (creator.CreateSchnorrSig(provider, sig, output, nullptr, nullptr, SigVersion::TAPROOT)) { + sigdata.taproot_key_path_sig = sig; + } + } if (sigdata.taproot_key_path_sig.size()) { result = Vector(sigdata.taproot_key_path_sig); return true; |