Repository: bitcoin/bitcoin
File: src/script/miniscript.h (C/C++)

Code before:
                }
                case Fragment::WRAP_J: return BuildScript(OP_SIZE, OP_0NOTEQUAL, OP_IF, subs[0], OP_ENDIF);
                case Fragment::WRAP_N: return BuildScript(std::move(subs[0]), OP_0NOTEQUAL);
                case Fragment::JUST_1: return BuildScript(OP_1);
                case Fragment::JUST_0: return BuildScript(OP_0);
                case Fragment::AND_V: return BuildScript(std::move(subs[0]), subs[1]);
                case Fragment::AND_B: return BuildScript(std::move(subs[0]), subs[1], OP_BOOLAND);
                case Fragment::OR_B: return BuildScript(std::move(subs[0]), subs[1], OP_BOOLOR);
                case Fragment::OR_D: return BuildScript(std::move(subs[0]), OP_IFDUP, OP_NOTIF, subs[1], OP_ENDIF);
                case Fragment::OR_C: return BuildScript(std::move(subs[0]), OP_NOTIF, subs[1], OP_ENDIF);
                case Fragment::OR_I: return BuildScript(OP_IF, subs[0], OP_ELSE, subs[1], OP_ENDIF);
                case Fragment::ANDOR: return BuildScript(std::move(subs[0]), OP_NOTIF, subs[2], OP_ELSE, subs[1], OP_ENDIF);
                case Fragment::MULTI: {
                    CHECK_NONFATAL(!is_tapscript);
                    CScript script = BuildScript(node.k);
                    for (const auto& key : node.keys) {
                        script = BuildScript(std::move(script), ctx.ToPKBytes(key));
                    }
                    return BuildScript(std::move(script), node.keys.size(), verify ? OP_CHECKMULTISIGVERIFY : OP_CHECKMULTISIG);
                }
                case Fragment::MULTI_A: {
                    CHECK_NONFATAL(is_tapscript);
                    CScript script = BuildScript(ctx.ToPKBytes(*node.keys.begin()), OP_CHECKSIG);
                    for (auto it = node.keys.begin() + 1; it != node.keys.end(); ++it) {
                        script = BuildScript(std::move(script), ctx.ToPKBytes(*it), OP_CHECKSIGADD);
                    }
                    return BuildScript(std::move(script), node.k, verify ? OP_NUMEQUALVERIFY : OP_NUMEQUAL);
                }
                case Fragment::THRESH: {
                    CScript script = std::move(subs[0]);
                    for (size_t i = 1; i < subs.size(); ++i) {
                        script = BuildScript(std::move(script), subs[i], OP_ADD);
                    }
                    return BuildScript(std::move(script), node.k, verify ? OP_EQUALVERIFY : OP_EQUAL);
                }
            }
            assert(false);
        };
        return TreeEval<CScript>(false, downfn, upfn);
    }

    template<typename CTx>
    std::optional<std::string> ToString(const CTx& ctx) const {
        // To construct the std::string representation for a Miniscript object, we use
        // the TreeEvalMaybe algorithm. The State is a boolean: whether the parent node is a
        // wrapper. If so, non-wrapper expressions must be prefixed with a ":".
        auto downfn = [](bool, const Node& node, size_t) {
            return (node.fragment == Fragment::WRAP_A || node.fragment == Fragment::WRAP_S ||
                    node.fragment == Fragment::WRAP_D || node.fragment == Fragment::WRAP_V ||
                    node.fragment == Fragment::WRAP_J || node.fragment == Fragment::WRAP_N ||
                    node.fragment == Fragment::WRAP_C ||

Review comment (suggestion):
In 4d07eff13002384ed59a3b7f592be56a25b88c15 "descriptor: ToPrivateString() pass if  at least 1 priv key exists"

`has_priv_key` does not need to be a pointer here.

Code after:
                    }
                    return BuildScript(std::move(script), node.keys.size(), verify ? OP_CHECKMULTISIGVERIFY : OP_CHECKMULTISIG);
                }
                case Fragment::MULTI_A: {
                    CHECK_NONFATAL(is_tapscript);
                    CScript script = BuildScript(ctx.ToPKBytes(*node.keys.begin()), OP_CHECKSIG);
                    for (auto it = node.keys.begin() + 1; it != node.keys.end(); ++it) {
                        script = BuildScript(std::move(script), ctx.ToPKBytes(*it), OP_CHECKSIGADD);
                    }
                    return BuildScript(std::move(script), node.k, verify ? OP_NUMEQUALVERIFY : OP_NUMEQUAL);
                }
                case Fragment::THRESH: {
                    CScript script = std::move(subs[0]);
                    for (size_t i = 1; i < subs.size(); ++i) {
                        script = BuildScript(std::move(script), subs[i], OP_ADD);
                    }
                    return BuildScript(std::move(script), node.k, verify ? OP_EQUALVERIFY : OP_EQUAL);
                }
            }
            assert(false);
        };
        return TreeEval<CScript>(false, downfn, upfn);
    }

    template<typename CTx>
    std::optional<std::string> ToString(const CTx& ctx) const {
        bool dummy{false};
        return ToString(ctx, dummy);
    }

    template<typename CTx>
    std::optional<std::string> ToString(const CTx& ctx, bool& has_priv_key) const {
        // To construct the std::string representation for a Miniscript object, we use
        // the TreeEvalMaybe algorithm. The State is a boolean: whether the parent node is a
        // wrapper. If so, non-wrapper expressions must be prefixed with a ":".
        auto downfn = [](bool, const Node& node, size_t) {
            return (node.fragment == Fragment::WRAP_A || node.fragment == Fragment::WRAP_S ||
                    node.fragment == Fragment::WRAP_D || node.fragment == Fragment::WRAP_V ||
                    node.fragment == Fragment::WRAP_J || node.fragment == Fragment::WRAP_N ||
                    node.fragment == Fragment::WRAP_C ||
                    (node.fragment == Fragment::AND_V && node.subs[1]->fragment == Fragment::JUST_1) ||
                    (node.fragment == Fragment::OR_I && node.subs[0]->fragment == Fragment::JUST_0) ||
                    (node.fragment == Fragment::OR_I && node.subs[1]->fragment == Fragment::JUST_0));
        };
        auto toString = [&ctx, &has_priv_key](Key key) -> std::optional<std::string> {
            bool fragment_has_priv_key{false};
            auto key_str{ctx.ToString(key, fragment_has_priv_key)};
            if (key_str) has_priv_key = has_priv_key || fragment_has_priv_key;
            return key_str;
        };
        // The upward function computes for a node, given whether its parent is a wrapper,