Repository: bitcoin/bitcoin
File: src/script/descriptor.cpp (C++)

Code before:
        switch (m_script_ctx) {
            case miniscript::MiniscriptContext::P2WSH: return ParseScriptContext::P2WSH;
            case miniscript::MiniscriptContext::TAPSCRIPT: return ParseScriptContext::P2TR;
        }
        assert(false);
    }

    template<typename I> std::optional<Key> FromString(I begin, I end) const
    {
        assert(m_out);
        Key key = m_keys.size();
        uint32_t exp_index = m_offset + key;
        auto pk = ParsePubkey(exp_index, {&*begin, &*end}, ParseContext(), *m_out, m_key_parsing_error);
        if (pk.empty()) return {};
        m_keys.emplace_back(std::move(pk));
        return key;
    }

    std::optional<std::string> ToString(const Key& key) const
    {
        return m_keys.at(key).at(0)->ToString();
    }

    template<typename I> std::optional<Key> FromPKBytes(I begin, I end) const
    {
        assert(m_in);
        Key key = m_keys.size();
        if (miniscript::IsTapscript(m_script_ctx) && end - begin == 32) {
            XOnlyPubKey pubkey;
            std::copy(begin, end, pubkey.begin());
            if (auto pubkey_provider = InferXOnlyPubkey(pubkey, ParseContext(), *m_in)) {
                m_keys.emplace_back();
                m_keys.back().push_back(std::move(pubkey_provider));
                return key;
            }
        } else if (!miniscript::IsTapscript(m_script_ctx)) {
            CPubKey pubkey(begin, end);
            if (auto pubkey_provider = InferPubkey(pubkey, ParseContext(), *m_in)) {
                m_keys.emplace_back();
                m_keys.back().push_back(std::move(pubkey_provider));
                return key;
            }
        }
        return {};
    }

    template<typename I> std::optional<Key> FromPKHBytes(I begin, I end) const
    {
        assert(end - begin == 20);
        assert(m_in);
        uint160 hash;

Review comment (bug):
In https://github.com/bitcoin/bitcoin/commit/deed439bff638abfc298a3b9c4f3d9f75fa18244 "descriptor: ToPrivateString() pass if at least 1 priv key exists"

Nit: 
```diff
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index b6539ab12e..028a7299e5 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -2120,7 +2120,7 @@ struct KeyParser {
         return key;
     }
 
-    std::string ToString(const Key& key, bool* has_priv_key = nullptr) const
+    std::string ToString(const Key& key, bool*) const
     {
         return m_keys.at(key).at(0)->ToString();
     }
```

Code after:

/**
 * The context for parsing a Miniscript descriptor (either from Script or from its textual representation).
 */
struct KeyParser {
    //! The Key type is an index in DescriptorImpl::m_pubkey_args
    using Key = uint32_t;
    //! Must not be nullptr if parsing from string.
    FlatSigningProvider* m_out;
    //! Must not be nullptr if parsing from Script.
    const SigningProvider* m_in;
    //! List of multipath expanded keys contained in the Miniscript.
    mutable std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> m_keys;
    //! Used to detect key parsing errors within a Miniscript.
    mutable std::string m_key_parsing_error;
    //! The script context we're operating within (Tapscript or P2WSH).
    const miniscript::MiniscriptContext m_script_ctx;
    //! The number of keys that were parsed before starting to parse this Miniscript descriptor.
    uint32_t m_offset;

    KeyParser(FlatSigningProvider* out LIFETIMEBOUND, const SigningProvider* in LIFETIMEBOUND,
              miniscript::MiniscriptContext ctx, uint32_t offset = 0)
        : m_out(out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}

    bool KeyCompare(const Key& a, const Key& b) const {
        return *m_keys.at(a).at(0) < *m_keys.at(b).at(0);
    }

    ParseScriptContext ParseContext() const {
        switch (m_script_ctx) {
            case miniscript::MiniscriptContext::P2WSH: return ParseScriptContext::P2WSH;
            case miniscript::MiniscriptContext::TAPSCRIPT: return ParseScriptContext::P2TR;
        }
        assert(false);
    }

    template<typename I> std::optional<Key> FromString(I begin, I end) const
    {
        assert(m_out);
        Key key = m_keys.size();
        uint32_t exp_index = m_offset + key;
        auto pk = ParsePubkey(exp_index, {&*begin, &*end}, ParseContext(), *m_out, m_key_parsing_error);
        if (pk.empty()) return {};
        m_keys.emplace_back(std::move(pk));
        return key;
    }

    std::optional<std::string> ToString(const Key& key, bool&) const
    {
        return m_keys.at(key).at(0)->ToString();
    }