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

Code before:
    bool IsRange() const override { return IsRangedDerivation() || m_ranged_participants; }
    // musig() expressions can only be used in tr() contexts which have 32 byte xonly pubkeys
    size_t GetSize() const override { return 32; }

    std::string ToString(StringType type=StringType::PUBLIC) const override
    {
        std::string out = "musig(";
        for (size_t i = 0; i < m_participants.size(); ++i) {
            const auto& pubkey = m_participants.at(i);
            if (i) out += ",";
            out += pubkey->ToString(type);
        }
        out += ")";
        out += FormatHDKeypath(m_path);
        if (IsRangedDerivation()) {
            out += "/*";
        }
        return out;
    }
    bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
    {
        bool any_privkeys = false;
        out = "musig(";
        for (size_t i = 0; i < m_participants.size(); ++i) {
            const auto& pubkey = m_participants.at(i);
            if (i) out += ",";
            std::string tmp;
            if (pubkey->ToPrivateString(arg, tmp)) {
                any_privkeys = true;
                out += tmp;
            } else {
                out += pubkey->ToString();
            }
        }
        out += ")";
        out += FormatHDKeypath(m_path);
        if (IsRangedDerivation()) {
            out += "/*";
        }
        if (!any_privkeys) out.clear();
        return any_privkeys;
    }
    bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache = nullptr) const override
    {
        out = "musig(";
        for (size_t i = 0; i < m_participants.size(); ++i) {
            const auto& pubkey = m_participants.at(i);
            if (i) out += ",";
            std::string tmp;
            if (!pubkey->ToNormalizedString(arg, tmp, cache)) {
                return false;

Review comment (bug):
In a0a458965c944434b1f3e4d83277257793435edb "descriptor: ToPrivateString() pass if  at least 1 priv key exists"

Fine to add `assert` here because for all intents and purposes I don't suppose there would ever be a case where `ToStringHelper` returns `false` here. Perhaps we can add a helpful assert message here for debugging purposes?

```diff
- assert(ToStringHelper(&arg, out, StringType::PRIVATE, has_priv_key));
+ assert(ToStringHelper(&arg, out, StringType::PRIVATE, has_priv_key), "");
```

Code after:
            pubout = *aggregate_pubkey;

            std::unique_ptr<ConstPubkeyProvider> this_agg_provider = std::make_unique<ConstPubkeyProvider>(m_expr_index, aggregate_pubkey.value(), /*xonly=*/false);
            this_agg_provider->GetPubKey(0, dummy, out, read_cache, write_cache);
            out.aggregate_pubkeys.emplace(pubout, pubkeys);
        }

        if (!Assume(pubout.IsValid())) return std::nullopt;
        return pubout;
    }
    bool IsRange() const override { return IsRangedDerivation() || m_ranged_participants; }
    // musig() expressions can only be used in tr() contexts which have 32 byte xonly pubkeys
    size_t GetSize() const override { return 32; }

    std::string ToString(StringType type=StringType::PUBLIC) const override
    {
        std::string out = "musig(";
        for (size_t i = 0; i < m_participants.size(); ++i) {
            const auto& pubkey = m_participants.at(i);
            if (i) out += ",";
            out += pubkey->ToString(type);
        }
        out += ")";
        out += FormatHDKeypath(m_path);
        if (IsRangedDerivation()) {
            out += "/*";
        }
        return out;
    }
    bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
    {
        bool any_privkeys = false;
        out = "musig(";
        for (size_t i = 0; i < m_participants.size(); ++i) {
            const auto& pubkey = m_participants.at(i);
            if (i) out += ",";
            std::string tmp;
            if (pubkey->ToPrivateString(arg, tmp)) {
                any_privkeys = true;
            }
            out += tmp;
        }
        out += ")";
        out += FormatHDKeypath(m_path);
        if (IsRangedDerivation()) {
            out += "/*";
        }
        return any_privkeys;
    }
    bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache = nullptr) const override
    {