/Users/eugenesiegel/btc/bitcoin/src/script/miniscript.h
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright (c) 2019-present The Bitcoin Core developers | 
| 2 |  | // Distributed under the MIT software license, see the accompanying | 
| 3 |  | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | 
| 4 |  |  | 
| 5 |  | #ifndef BITCOIN_SCRIPT_MINISCRIPT_H | 
| 6 |  | #define BITCOIN_SCRIPT_MINISCRIPT_H | 
| 7 |  |  | 
| 8 |  | #include <algorithm> | 
| 9 |  | #include <compare> | 
| 10 |  | #include <cstdint> | 
| 11 |  | #include <cstdlib> | 
| 12 |  | #include <iterator> | 
| 13 |  | #include <memory> | 
| 14 |  | #include <optional> | 
| 15 |  | #include <set> | 
| 16 |  | #include <stdexcept> | 
| 17 |  | #include <tuple> | 
| 18 |  | #include <utility> | 
| 19 |  | #include <vector> | 
| 20 |  |  | 
| 21 |  | #include <consensus/consensus.h> | 
| 22 |  | #include <policy/policy.h> | 
| 23 |  | #include <script/interpreter.h> | 
| 24 |  | #include <script/parsing.h> | 
| 25 |  | #include <script/script.h> | 
| 26 |  | #include <serialize.h> | 
| 27 |  | #include <span.h> | 
| 28 |  | #include <util/check.h> | 
| 29 |  | #include <util/strencodings.h> | 
| 30 |  | #include <util/string.h> | 
| 31 |  | #include <util/vector.h> | 
| 32 |  |  | 
| 33 |  | namespace miniscript { | 
| 34 |  |  | 
| 35 |  | /** This type encapsulates the miniscript type system properties. | 
| 36 |  |  * | 
| 37 |  |  * Every miniscript expression is one of 4 basic types, and additionally has | 
| 38 |  |  * a number of boolean type properties. | 
| 39 |  |  * | 
| 40 |  |  * The basic types are: | 
| 41 |  |  * - "B" Base: | 
| 42 |  |  *   - Takes its inputs from the top of the stack. | 
| 43 |  |  *   - When satisfied, pushes a nonzero value of up to 4 bytes onto the stack. | 
| 44 |  |  *   - When dissatisfied, pushes a 0 onto the stack. | 
| 45 |  |  *   - This is used for most expressions, and required for the top level one. | 
| 46 |  |  *   - For example: older(n) = <n> OP_CHECKSEQUENCEVERIFY. | 
| 47 |  |  * - "V" Verify: | 
| 48 |  |  *   - Takes its inputs from the top of the stack. | 
| 49 |  |  *   - When satisfied, pushes nothing. | 
| 50 |  |  *   - Cannot be dissatisfied. | 
| 51 |  |  *   - This can be obtained by adding an OP_VERIFY to a B, modifying the last opcode | 
| 52 |  |  *     of a B to its -VERIFY version (only for OP_CHECKSIG, OP_CHECKSIGVERIFY, | 
| 53 |  |  *     OP_NUMEQUAL and OP_EQUAL), or by combining a V fragment under some conditions. | 
| 54 |  |  *   - For example vc:pk_k(key) = <key> OP_CHECKSIGVERIFY | 
| 55 |  |  * - "K" Key: | 
| 56 |  |  *   - Takes its inputs from the top of the stack. | 
| 57 |  |  *   - Becomes a B when followed by OP_CHECKSIG. | 
| 58 |  |  *   - Always pushes a public key onto the stack, for which a signature is to be | 
| 59 |  |  *     provided to satisfy the expression. | 
| 60 |  |  *   - For example pk_h(key) = OP_DUP OP_HASH160 <Hash160(key)> OP_EQUALVERIFY | 
| 61 |  |  * - "W" Wrapped: | 
| 62 |  |  *   - Takes its input from one below the top of the stack. | 
| 63 |  |  *   - When satisfied, pushes a nonzero value (like B) on top of the stack, or one below. | 
| 64 |  |  *   - When dissatisfied, pushes 0 op top of the stack or one below. | 
| 65 |  |  *   - Is always "OP_SWAP [B]" or "OP_TOALTSTACK [B] OP_FROMALTSTACK". | 
| 66 |  |  *   - For example sc:pk_k(key) = OP_SWAP <key> OP_CHECKSIG | 
| 67 |  |  * | 
| 68 |  |  * There are type properties that help reasoning about correctness: | 
| 69 |  |  * - "z" Zero-arg: | 
| 70 |  |  *   - Is known to always consume exactly 0 stack elements. | 
| 71 |  |  *   - For example after(n) = <n> OP_CHECKLOCKTIMEVERIFY | 
| 72 |  |  * - "o" One-arg: | 
| 73 |  |  *   - Is known to always consume exactly 1 stack element. | 
| 74 |  |  *   - Conflicts with property 'z' | 
| 75 |  |  *   - For example sha256(hash) = OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 <hash> OP_EQUAL | 
| 76 |  |  * - "n" Nonzero: | 
| 77 |  |  *   - For every way this expression can be satisfied, a satisfaction exists that never needs | 
| 78 |  |  *     a zero top stack element. | 
| 79 |  |  *   - Conflicts with property 'z' and with type 'W'. | 
| 80 |  |  * - "d" Dissatisfiable: | 
| 81 |  |  *   - There is an easy way to construct a dissatisfaction for this expression. | 
| 82 |  |  *   - Conflicts with type 'V'. | 
| 83 |  |  * - "u" Unit: | 
| 84 |  |  *   - In case of satisfaction, an exact 1 is put on the stack (rather than just nonzero). | 
| 85 |  |  *   - Conflicts with type 'V'. | 
| 86 |  |  * | 
| 87 |  |  * Additional type properties help reasoning about nonmalleability: | 
| 88 |  |  * - "e" Expression: | 
| 89 |  |  *   - This implies property 'd', but the dissatisfaction is nonmalleable. | 
| 90 |  |  *   - This generally requires 'e' for all subexpressions which are invoked for that | 
| 91 |  |  *     dissatisfaction, and property 'f' for the unexecuted subexpressions in that case. | 
| 92 |  |  *   - Conflicts with type 'V'. | 
| 93 |  |  * - "f" Forced: | 
| 94 |  |  *   - Dissatisfactions (if any) for this expression always involve at least one signature. | 
| 95 |  |  *   - Is always true for type 'V'. | 
| 96 |  |  * - "s" Safe: | 
| 97 |  |  *   - Satisfactions for this expression always involve at least one signature. | 
| 98 |  |  * - "m" Nonmalleable: | 
| 99 |  |  *   - For every way this expression can be satisfied (which may be none), | 
| 100 |  |  *     a nonmalleable satisfaction exists. | 
| 101 |  |  *   - This generally requires 'm' for all subexpressions, and 'e' for all subexpressions | 
| 102 |  |  *     which are dissatisfied when satisfying the parent. | 
| 103 |  |  * | 
| 104 |  |  * One type property is an implementation detail: | 
| 105 |  |  * - "x" Expensive verify: | 
| 106 |  |  *   - Expressions with this property have a script whose last opcode is not EQUAL, CHECKSIG, or CHECKMULTISIG. | 
| 107 |  |  *   - Not having this property means that it can be converted to a V at no cost (by switching to the | 
| 108 |  |  *     -VERIFY version of the last opcode). | 
| 109 |  |  * | 
| 110 |  |  * Five more type properties for representing timelock information. Spend paths | 
| 111 |  |  * in miniscripts containing conflicting timelocks and heightlocks cannot be spent together. | 
| 112 |  |  * This helps users detect if miniscript does not match the semantic behaviour the | 
| 113 |  |  * user expects. | 
| 114 |  |  * - "g" Whether the branch contains a relative time timelock | 
| 115 |  |  * - "h" Whether the branch contains a relative height timelock | 
| 116 |  |  * - "i" Whether the branch contains an absolute time timelock | 
| 117 |  |  * - "j" Whether the branch contains an absolute height timelock | 
| 118 |  |  * - "k" | 
| 119 |  |  *   - Whether all satisfactions of this expression don't contain a mix of heightlock and timelock | 
| 120 |  |  *     of the same type. | 
| 121 |  |  *   - If the miniscript does not have the "k" property, the miniscript template will not match | 
| 122 |  |  *     the user expectation of the corresponding spending policy. | 
| 123 |  |  * For each of these properties the subset rule holds: an expression with properties X, Y, and Z, is also | 
| 124 |  |  * valid in places where an X, a Y, a Z, an XY, ... is expected. | 
| 125 |  | */ | 
| 126 |  | class Type { | 
| 127 |  |     //! Internal bitmap of properties (see ""_mst operator for details). | 
| 128 |  |     uint32_t m_flags; | 
| 129 |  |  | 
| 130 |  |     //! Internal constructor used by the ""_mst operator. | 
| 131 | 0 |     explicit constexpr Type(uint32_t flags) : m_flags(flags) {} | 
| 132 |  |  | 
| 133 |  | public: | 
| 134 |  |     //! The only way to publicly construct a Type is using this literal operator. | 
| 135 |  |     friend consteval Type operator""_mst(const char* c, size_t l); | 
| 136 |  |  | 
| 137 |  |     //! Compute the type with the union of properties. | 
| 138 | 0 |     constexpr Type operator|(Type x) const { return Type(m_flags | x.m_flags); } | 
| 139 |  |  | 
| 140 |  |     //! Compute the type with the intersection of properties. | 
| 141 | 0 |     constexpr Type operator&(Type x) const { return Type(m_flags & x.m_flags); } | 
| 142 |  |  | 
| 143 |  |     //! Check whether the left hand's properties are superset of the right's (= left is a subtype of right). | 
| 144 | 0 |     constexpr bool operator<<(Type x) const { return (x.m_flags & ~m_flags) == 0; } | 
| 145 |  |  | 
| 146 |  |     //! Comparison operator to enable use in sets/maps (total ordering incompatible with <<). | 
| 147 | 0 |     constexpr bool operator<(Type x) const { return m_flags < x.m_flags; } | 
| 148 |  |  | 
| 149 |  |     //! Equality operator. | 
| 150 | 0 |     constexpr bool operator==(Type x) const { return m_flags == x.m_flags; } | 
| 151 |  |  | 
| 152 |  |     //! The empty type if x is false, itself otherwise. | 
| 153 | 0 |     constexpr Type If(bool x) const { return Type(x ? m_flags : 0); } | 
| 154 |  | }; | 
| 155 |  |  | 
| 156 |  | //! Literal operator to construct Type objects. | 
| 157 |  | inline consteval Type operator""_mst(const char* c, size_t l) | 
| 158 |  | { | 
| 159 |  |     Type typ{0}; | 
| 160 |  |  | 
| 161 |  |     for (const char *p = c; p < c + l; p++) { | 
| 162 |  |         typ = typ | Type( | 
| 163 |  |             *p == 'B' ? 1 << 0 : // Base type | 
| 164 |  |             *p == 'V' ? 1 << 1 : // Verify type | 
| 165 |  |             *p == 'K' ? 1 << 2 : // Key type | 
| 166 |  |             *p == 'W' ? 1 << 3 : // Wrapped type | 
| 167 |  |             *p == 'z' ? 1 << 4 : // Zero-arg property | 
| 168 |  |             *p == 'o' ? 1 << 5 : // One-arg property | 
| 169 |  |             *p == 'n' ? 1 << 6 : // Nonzero arg property | 
| 170 |  |             *p == 'd' ? 1 << 7 : // Dissatisfiable property | 
| 171 |  |             *p == 'u' ? 1 << 8 : // Unit property | 
| 172 |  |             *p == 'e' ? 1 << 9 : // Expression property | 
| 173 |  |             *p == 'f' ? 1 << 10 : // Forced property | 
| 174 |  |             *p == 's' ? 1 << 11 : // Safe property | 
| 175 |  |             *p == 'm' ? 1 << 12 : // Nonmalleable property | 
| 176 |  |             *p == 'x' ? 1 << 13 : // Expensive verify | 
| 177 |  |             *p == 'g' ? 1 << 14 : // older: contains relative time timelock   (csv_time) | 
| 178 |  |             *p == 'h' ? 1 << 15 : // older: contains relative height timelock (csv_height) | 
| 179 |  |             *p == 'i' ? 1 << 16 : // after: contains time timelock   (cltv_time) | 
| 180 |  |             *p == 'j' ? 1 << 17 : // after: contains height timelock   (cltv_height) | 
| 181 |  |             *p == 'k' ? 1 << 18 : // does not contain a combination of height and time locks | 
| 182 |  |             (throw std::logic_error("Unknown character in _mst literal"), 0) | 
| 183 |  |         ); | 
| 184 |  |     } | 
| 185 |  |  | 
| 186 |  |     return typ; | 
| 187 |  | } | 
| 188 |  |  | 
| 189 |  | using Opcode = std::pair<opcodetype, std::vector<unsigned char>>; | 
| 190 |  |  | 
| 191 |  | template<typename Key> struct Node; | 
| 192 |  | template<typename Key> using NodeRef = std::unique_ptr<const Node<Key>>; | 
| 193 |  |  | 
| 194 |  | //! Construct a miniscript node as a unique_ptr. | 
| 195 |  | template<typename Key, typename... Args> | 
| 196 | 0 | NodeRef<Key> MakeNodeRef(Args&&... args) { return std::make_unique<const Node<Key>>(std::forward<Args>(args)...); }Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentEEEENSt3__110unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISB_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIS1_NS6_9allocatorIS1_EEEEEEENS6_10unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISF_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERxEEENSt3__110unique_ptrIKNS_4NodeIT_EENS7_14default_deleteISC_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERNSt3__16vectorIhNS6_9allocatorIhEEEEEEENS6_10unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISG_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIS1_NS6_9allocatorIS1_EEEERKxEEENS6_10unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISH_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS6_10unique_ptrIKNS_4NodeIS1_EENS6_14default_deleteISB_EEEENS6_9allocatorISE_EEEEEEENS8_IKNS9_IT_EENSC_ISK_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckERKNS_17MiniscriptContextERNS_8FragmentENSt3__16vectorINS9_10unique_ptrIKNS_4NodeIS1_EENS9_14default_deleteISE_EEEENS9_9allocatorISH_EEEEEEENSB_IKNSC_IT_EENSF_ISN_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS6_10unique_ptrIKNS_4NodeIS1_EENS6_14default_deleteISB_EEEENS6_9allocatorISE_EEEERxEEENS8_IKNS9_IT_EENSC_ISL_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIhNS6_9allocatorIhEEEEEEENS6_10unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISF_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERKxEEENSt3__110unique_ptrIKNS_4NodeIT_EENS8_14default_deleteISD_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckERNS_17MiniscriptContextERNS_8FragmentENSt3__16vectorINS8_10unique_ptrIKNS_4NodeIS1_EENS8_14default_deleteISD_EEEENS8_9allocatorISG_EEEENS9_IhNSH_IhEEEERjEEENSA_IKNSB_IT_EENSE_ISP_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI7CPubKeyJNS_8internal10NoDupCheckERNS_17MiniscriptContextERNS_8FragmentENSt3__16vectorIS1_NS8_9allocatorIS1_EEEERjEEENS8_10unique_ptrIKNS_4NodeIT_EENS8_14default_deleteISI_EEEEDpOT0_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript11MakeNodeRefIN12_GLOBAL__N_119ScriptParserContext3KeyEJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentEEEENSt3__110unique_ptrIKNS_4NodeIT_EENS8_14default_deleteISD_EEEEDpOT0_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript11MakeNodeRefIN12_GLOBAL__N_119ScriptParserContext3KeyEJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIS3_NS8_9allocatorIS3_EEEEEEENS8_10unique_ptrIKNS_4NodeIT_EENS8_14default_deleteISH_EEEEDpOT0_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript11MakeNodeRefIN12_GLOBAL__N_119ScriptParserContext3KeyEJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERxEEENSt3__110unique_ptrIKNS_4NodeIT_EENS9_14default_deleteISE_EEEEDpOT0_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript11MakeNodeRefIN12_GLOBAL__N_119ScriptParserContext3KeyEJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERNSt3__16vectorIhNS8_9allocatorIhEEEEEEENS8_10unique_ptrIKNS_4NodeIT_EENS8_14default_deleteISI_EEEEDpOT0_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript11MakeNodeRefIN12_GLOBAL__N_119ScriptParserContext3KeyEJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIS3_NS8_9allocatorIS3_EEEERKxEEENS8_10unique_ptrIKNS_4NodeIT_EENS8_14default_deleteISJ_EEEEDpOT0_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript11MakeNodeRefIN12_GLOBAL__N_119ScriptParserContext3KeyEJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS8_10unique_ptrIKNS_4NodeIS3_EENS8_14default_deleteISD_EEEENS8_9allocatorISG_EEEEEEENSA_IKNSB_IT_EENSE_ISM_EEEEDpOT0_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript11MakeNodeRefIN12_GLOBAL__N_119ScriptParserContext3KeyEJNS_8internal10NoDupCheckERKNS_17MiniscriptContextERNS_8FragmentENSt3__16vectorINSB_10unique_ptrIKNS_4NodeIS3_EENSB_14default_deleteISG_EEEENSB_9allocatorISJ_EEEEEEENSD_IKNSE_IT_EENSH_ISP_EEEEDpOT0_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript11MakeNodeRefIN12_GLOBAL__N_119ScriptParserContext3KeyEJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS8_10unique_ptrIKNS_4NodeIS3_EENS8_14default_deleteISD_EEEENS8_9allocatorISG_EEEERxEEENSA_IKNSB_IT_EENSE_ISN_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentEEEENSt3__110unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISA_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS5_10unique_ptrIKNS_4NodeIjEENS5_14default_deleteISA_EEEENS5_9allocatorISD_EEEEEEENS7_IKNS8_IT_EENSB_ISJ_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIjNS5_9allocatorIjEEEEEEENS5_10unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISE_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIhNS5_9allocatorIhEEEEEEENS5_10unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISE_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERKxEEENSt3__110unique_ptrIKNS_4NodeIT_EENS7_14default_deleteISC_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIjNS5_9allocatorIjEEEERKxEEENS5_10unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISG_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckERKNS_17MiniscriptContextERNS_8FragmentENSt3__16vectorINS8_10unique_ptrIKNS_4NodeIjEENS8_14default_deleteISD_EEEENS8_9allocatorISG_EEEEEEENSA_IKNSB_IT_EENSE_ISM_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS5_10unique_ptrIKNS_4NodeIjEENS5_14default_deleteISA_EEEENS5_9allocatorISD_EEEERxEEENS7_IKNS8_IT_EENSB_ISK_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERxEEENSt3__110unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISB_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefIjJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERNSt3__16vectorIhNS5_9allocatorIhEEEEEEENS5_10unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISF_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI11XOnlyPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentEEEENSt3__110unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISB_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI11XOnlyPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIS1_NS6_9allocatorIS1_EEEEEEENS6_10unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISF_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI11XOnlyPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERxEEENSt3__110unique_ptrIKNS_4NodeIT_EENS7_14default_deleteISC_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI11XOnlyPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentERNSt3__16vectorIhNS6_9allocatorIhEEEEEEENS6_10unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISG_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI11XOnlyPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIS1_NS6_9allocatorIS1_EEEERKxEEENS6_10unique_ptrIKNS_4NodeIT_EENS6_14default_deleteISH_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI11XOnlyPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS6_10unique_ptrIKNS_4NodeIS1_EENS6_14default_deleteISB_EEEENS6_9allocatorISE_EEEEEEENS8_IKNS9_IT_EENSC_ISK_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI11XOnlyPubKeyJNS_8internal10NoDupCheckERKNS_17MiniscriptContextERNS_8FragmentENSt3__16vectorINS9_10unique_ptrIKNS_4NodeIS1_EENS9_14default_deleteISE_EEEENS9_9allocatorISH_EEEEEEENSB_IKNSC_IT_EENSF_ISN_EEEEDpOT0_Unexecuted instantiation: _ZN10miniscript11MakeNodeRefI11XOnlyPubKeyJNS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS6_10unique_ptrIKNS_4NodeIS1_EENS6_14default_deleteISB_EEEENS6_9allocatorISE_EEEERxEEENS8_IKNS9_IT_EENSC_ISL_EEEEDpOT0_ | 
| 197 |  |  | 
| 198 |  | //! The different node types in miniscript. | 
| 199 |  | enum class Fragment { | 
| 200 |  |     JUST_0,    //!< OP_0 | 
| 201 |  |     JUST_1,    //!< OP_1 | 
| 202 |  |     PK_K,      //!< [key] | 
| 203 |  |     PK_H,      //!< OP_DUP OP_HASH160 [keyhash] OP_EQUALVERIFY | 
| 204 |  |     OLDER,     //!< [n] OP_CHECKSEQUENCEVERIFY | 
| 205 |  |     AFTER,     //!< [n] OP_CHECKLOCKTIMEVERIFY | 
| 206 |  |     SHA256,    //!< OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 [hash] OP_EQUAL | 
| 207 |  |     HASH256,   //!< OP_SIZE 32 OP_EQUALVERIFY OP_HASH256 [hash] OP_EQUAL | 
| 208 |  |     RIPEMD160, //!< OP_SIZE 32 OP_EQUALVERIFY OP_RIPEMD160 [hash] OP_EQUAL | 
| 209 |  |     HASH160,   //!< OP_SIZE 32 OP_EQUALVERIFY OP_HASH160 [hash] OP_EQUAL | 
| 210 |  |     WRAP_A,    //!< OP_TOALTSTACK [X] OP_FROMALTSTACK | 
| 211 |  |     WRAP_S,    //!< OP_SWAP [X] | 
| 212 |  |     WRAP_C,    //!< [X] OP_CHECKSIG | 
| 213 |  |     WRAP_D,    //!< OP_DUP OP_IF [X] OP_ENDIF | 
| 214 |  |     WRAP_V,    //!< [X] OP_VERIFY (or -VERIFY version of last opcode in X) | 
| 215 |  |     WRAP_J,    //!< OP_SIZE OP_0NOTEQUAL OP_IF [X] OP_ENDIF | 
| 216 |  |     WRAP_N,    //!< [X] OP_0NOTEQUAL | 
| 217 |  |     AND_V,     //!< [X] [Y] | 
| 218 |  |     AND_B,     //!< [X] [Y] OP_BOOLAND | 
| 219 |  |     OR_B,      //!< [X] [Y] OP_BOOLOR | 
| 220 |  |     OR_C,      //!< [X] OP_NOTIF [Y] OP_ENDIF | 
| 221 |  |     OR_D,      //!< [X] OP_IFDUP OP_NOTIF [Y] OP_ENDIF | 
| 222 |  |     OR_I,      //!< OP_IF [X] OP_ELSE [Y] OP_ENDIF | 
| 223 |  |     ANDOR,     //!< [X] OP_NOTIF [Z] OP_ELSE [Y] OP_ENDIF | 
| 224 |  |     THRESH,    //!< [X1] ([Xn] OP_ADD)* [k] OP_EQUAL | 
| 225 |  |     MULTI,     //!< [k] [key_n]* [n] OP_CHECKMULTISIG (only available within P2WSH context) | 
| 226 |  |     MULTI_A,   //!< [key_0] OP_CHECKSIG ([key_n] OP_CHECKSIGADD)* [k] OP_NUMEQUAL (only within Tapscript ctx) | 
| 227 |  |     // AND_N(X,Y) is represented as ANDOR(X,Y,0) | 
| 228 |  |     // WRAP_T(X) is represented as AND_V(X,1) | 
| 229 |  |     // WRAP_L(X) is represented as OR_I(0,X) | 
| 230 |  |     // WRAP_U(X) is represented as OR_I(X,0) | 
| 231 |  | }; | 
| 232 |  |  | 
| 233 |  | enum class Availability { | 
| 234 |  |     NO, | 
| 235 |  |     YES, | 
| 236 |  |     MAYBE, | 
| 237 |  | }; | 
| 238 |  |  | 
| 239 |  | enum class MiniscriptContext { | 
| 240 |  |     P2WSH, | 
| 241 |  |     TAPSCRIPT, | 
| 242 |  | }; | 
| 243 |  |  | 
| 244 |  | /** Whether the context Tapscript, ensuring the only other possibility is P2WSH. */ | 
| 245 |  | constexpr bool IsTapscript(MiniscriptContext ms_ctx) | 
| 246 | 0 | { | 
| 247 | 0 |     switch (ms_ctx) { | 
| 248 | 0 |         case MiniscriptContext::P2WSH: return false; | 
| 249 | 0 |         case MiniscriptContext::TAPSCRIPT: return true; | 
| 250 | 0 |     } | 
| 251 | 0 |     assert(false); | 
| 252 | 0 | } | 
| 253 |  |  | 
| 254 |  | namespace internal { | 
| 255 |  |  | 
| 256 |  | //! The maximum size of a witness item for a Miniscript under Tapscript context. (A BIP340 signature with a sighash type byte.) | 
| 257 |  | static constexpr uint32_t MAX_TAPMINISCRIPT_STACK_ELEM_SIZE{65}; | 
| 258 |  |  | 
| 259 |  | //! version + nLockTime | 
| 260 |  | constexpr uint32_t TX_OVERHEAD{4 + 4}; | 
| 261 |  | //! prevout + nSequence + scriptSig | 
| 262 |  | constexpr uint32_t TXIN_BYTES_NO_WITNESS{36 + 4 + 1}; | 
| 263 |  | //! nValue + script len + OP_0 + pushdata 32. | 
| 264 |  | constexpr uint32_t P2WSH_TXOUT_BYTES{8 + 1 + 1 + 33}; | 
| 265 |  | //! Data other than the witness in a transaction. Overhead + vin count + one vin + vout count + one vout + segwit marker | 
| 266 |  | constexpr uint32_t TX_BODY_LEEWAY_WEIGHT{(TX_OVERHEAD + GetSizeOfCompactSize(1) + TXIN_BYTES_NO_WITNESS + GetSizeOfCompactSize(1) + P2WSH_TXOUT_BYTES) * WITNESS_SCALE_FACTOR + 2}; | 
| 267 |  | //! Maximum possible stack size to spend a Taproot output (excluding the script itself). | 
| 268 |  | constexpr uint32_t MAX_TAPSCRIPT_SAT_SIZE{GetSizeOfCompactSize(MAX_STACK_SIZE) + (GetSizeOfCompactSize(MAX_TAPMINISCRIPT_STACK_ELEM_SIZE) + MAX_TAPMINISCRIPT_STACK_ELEM_SIZE) * MAX_STACK_SIZE + GetSizeOfCompactSize(TAPROOT_CONTROL_MAX_SIZE) + TAPROOT_CONTROL_MAX_SIZE}; | 
| 269 |  | /** The maximum size of a script depending on the context. */ | 
| 270 |  | constexpr uint32_t MaxScriptSize(MiniscriptContext ms_ctx) | 
| 271 | 0 | { | 
| 272 | 0 |     if (IsTapscript(ms_ctx)) { | 
| 273 |  |         // Leaf scripts under Tapscript are not explicitly limited in size. They are only implicitly | 
| 274 |  |         // bounded by the maximum standard size of a spending transaction. Let the maximum script | 
| 275 |  |         // size conservatively be small enough such that even a maximum sized witness and a reasonably | 
| 276 |  |         // sized spending transaction can spend an output paying to this script without running into | 
| 277 |  |         // the maximum standard tx size limit. | 
| 278 | 0 |         constexpr auto max_size{MAX_STANDARD_TX_WEIGHT - TX_BODY_LEEWAY_WEIGHT - MAX_TAPSCRIPT_SAT_SIZE}; | 
| 279 | 0 |         return max_size - GetSizeOfCompactSize(max_size); | 
| 280 | 0 |     } | 
| 281 | 0 |     return MAX_STANDARD_P2WSH_SCRIPT_SIZE; | 
| 282 | 0 | } | 
| 283 |  |  | 
| 284 |  | //! Helper function for Node::CalcType. | 
| 285 |  | Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Type>& sub_types, uint32_t k, size_t data_size, size_t n_subs, size_t n_keys, MiniscriptContext ms_ctx); | 
| 286 |  |  | 
| 287 |  | //! Helper function for Node::CalcScriptLen. | 
| 288 |  | size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_t k, size_t n_subs, size_t n_keys, MiniscriptContext ms_ctx); | 
| 289 |  |  | 
| 290 |  | //! A helper sanitizer/checker for the output of CalcType. | 
| 291 |  | Type SanitizeType(Type x); | 
| 292 |  |  | 
| 293 |  | //! An object representing a sequence of witness stack elements. | 
| 294 |  | struct InputStack { | 
| 295 |  |     /** Whether this stack is valid for its intended purpose (satisfaction or dissatisfaction of a Node). | 
| 296 |  |      *  The MAYBE value is used for size estimation, when keys/preimages may actually be unavailable, | 
| 297 |  |      *  but may be available at signing time. This makes the InputStack structure and signing logic, | 
| 298 |  |      *  filled with dummy signatures/preimages usable for witness size estimation. | 
| 299 |  |      */ | 
| 300 |  |     Availability available = Availability::YES; | 
| 301 |  |     //! Whether this stack contains a digital signature. | 
| 302 |  |     bool has_sig = false; | 
| 303 |  |     //! Whether this stack is malleable (can be turned into an equally valid other stack by a third party). | 
| 304 |  |     bool malleable = false; | 
| 305 |  |     //! Whether this stack is non-canonical (using a construction known to be unnecessary for satisfaction). | 
| 306 |  |     //! Note that this flag does not affect the satisfaction algorithm; it is only used for sanity checking. | 
| 307 |  |     bool non_canon = false; | 
| 308 |  |     //! Serialized witness size. | 
| 309 |  |     size_t size = 0; | 
| 310 |  |     //! Data elements. | 
| 311 |  |     std::vector<std::vector<unsigned char>> stack; | 
| 312 |  |     //! Construct an empty stack (valid). | 
| 313 | 0 |     InputStack() = default; | 
| 314 |  |     //! Construct a valid single-element stack (with an element up to 75 bytes). | 
| 315 | 0 |     InputStack(std::vector<unsigned char> in) : size(in.size() + 1), stack(Vector(std::move(in))) {} | 
| 316 |  |     //! Change availability | 
| 317 |  |     InputStack& SetAvailable(Availability avail); | 
| 318 |  |     //! Mark this input stack as having a signature. | 
| 319 |  |     InputStack& SetWithSig(); | 
| 320 |  |     //! Mark this input stack as non-canonical (known to not be necessary in non-malleable satisfactions). | 
| 321 |  |     InputStack& SetNonCanon(); | 
| 322 |  |     //! Mark this input stack as malleable. | 
| 323 |  |     InputStack& SetMalleable(bool x = true); | 
| 324 |  |     //! Concatenate two input stacks. | 
| 325 |  |     friend InputStack operator+(InputStack a, InputStack b); | 
| 326 |  |     //! Choose between two potential input stacks. | 
| 327 |  |     friend InputStack operator|(InputStack a, InputStack b); | 
| 328 |  | }; | 
| 329 |  |  | 
| 330 |  | /** A stack consisting of a single zero-length element (interpreted as 0 by the script interpreter in numeric context). */ | 
| 331 |  | static const auto ZERO = InputStack(std::vector<unsigned char>()); | 
| 332 |  | /** A stack consisting of a single malleable 32-byte 0x0000...0000 element (for dissatisfying hash challenges). */ | 
| 333 |  | static const auto ZERO32 = InputStack(std::vector<unsigned char>(32, 0)).SetMalleable(); | 
| 334 |  | /** A stack consisting of a single 0x01 element (interpreted as 1 by the script interpreted in numeric context). */ | 
| 335 |  | static const auto ONE = InputStack(Vector((unsigned char)1)); | 
| 336 |  | /** The empty stack. */ | 
| 337 |  | static const auto EMPTY = InputStack(); | 
| 338 |  | /** A stack representing the lack of any (dis)satisfactions. */ | 
| 339 |  | static const auto INVALID = InputStack().SetAvailable(Availability::NO); | 
| 340 |  |  | 
| 341 |  | //! A pair of a satisfaction and a dissatisfaction InputStack. | 
| 342 |  | struct InputResult { | 
| 343 |  |     InputStack nsat, sat; | 
| 344 |  |  | 
| 345 |  |     template<typename A, typename B> | 
| 346 | 0 |     InputResult(A&& in_nsat, B&& in_sat) : nsat(std::forward<A>(in_nsat)), sat(std::forward<B>(in_sat)) {}Unexecuted instantiation: _ZN10miniscript8internal11InputResultC2IRKNS0_10InputStackERS3_EEOT_OT0_Unexecuted instantiation: _ZN10miniscript8internal11InputResultC2INS0_10InputStackERS3_EEOT_OT0_Unexecuted instantiation: _ZN10miniscript8internal11InputResultC2INS0_10InputStackES3_EEOT_OT0_Unexecuted instantiation: _ZN10miniscript8internal11InputResultC2IRKNS0_10InputStackES5_EEOT_OT0_Unexecuted instantiation: _ZN10miniscript8internal11InputResultC2IRNS0_10InputStackES3_EEOT_OT0_Unexecuted instantiation: _ZN10miniscript8internal11InputResultC2IRKNS0_10InputStackES3_EEOT_OT0_ | 
| 347 |  | }; | 
| 348 |  |  | 
| 349 |  | //! Class whose objects represent the maximum of a list of integers. | 
| 350 |  | template<typename I> | 
| 351 |  | struct MaxInt { | 
| 352 |  |     const bool valid; | 
| 353 |  |     const I value; | 
| 354 |  |  | 
| 355 | 0 |     MaxInt() : valid(false), value(0) {} | 
| 356 | 0 |     MaxInt(I val) : valid(true), value(val) {} | 
| 357 |  |  | 
| 358 | 0 |     friend MaxInt<I> operator+(const MaxInt<I>& a, const MaxInt<I>& b) { | 
| 359 | 0 |         if (!a.valid || !b.valid) return {}; | 
| 360 | 0 |         return a.value + b.value; | 
| 361 | 0 |     } | 
| 362 |  |  | 
| 363 | 0 |     friend MaxInt<I> operator|(const MaxInt<I>& a, const MaxInt<I>& b) { | 
| 364 | 0 |         if (!a.valid) return b; | 
| 365 | 0 |         if (!b.valid) return a; | 
| 366 | 0 |         return std::max(a.value, b.value); | 
| 367 | 0 |     } | 
| 368 |  | }; | 
| 369 |  |  | 
| 370 |  | struct Ops { | 
| 371 |  |     //! Non-push opcodes. | 
| 372 |  |     uint32_t count; | 
| 373 |  |     //! Number of keys in possibly executed OP_CHECKMULTISIG(VERIFY)s to satisfy. | 
| 374 |  |     MaxInt<uint32_t> sat; | 
| 375 |  |     //! Number of keys in possibly executed OP_CHECKMULTISIG(VERIFY)s to dissatisfy. | 
| 376 |  |     MaxInt<uint32_t> dsat; | 
| 377 |  |  | 
| 378 | 0 |     Ops(uint32_t in_count, MaxInt<uint32_t> in_sat, MaxInt<uint32_t> in_dsat) : count(in_count), sat(in_sat), dsat(in_dsat) {}; | 
| 379 |  | }; | 
| 380 |  |  | 
| 381 |  | /** A data structure to help the calculation of stack size limits. | 
| 382 |  |  * | 
| 383 |  |  * Conceptually, every SatInfo object corresponds to a (possibly empty) set of script execution | 
| 384 |  |  * traces (sequences of opcodes). | 
| 385 |  |  * - SatInfo{} corresponds to the empty set. | 
| 386 |  |  * - SatInfo{n, e} corresponds to a single trace whose net effect is removing n elements from the | 
| 387 |  |  *   stack (may be negative for a net increase), and reaches a maximum of e stack elements more | 
| 388 |  |  *   than it ends with. | 
| 389 |  |  * - operator| is the union operation: (a | b) corresponds to the union of the traces in a and the | 
| 390 |  |  *   traces in b. | 
| 391 |  |  * - operator+ is the concatenation operator: (a + b) corresponds to the set of traces formed by | 
| 392 |  |  *   concatenating any trace in a with any trace in b. | 
| 393 |  |  * | 
| 394 |  |  * Its fields are: | 
| 395 |  |  * - valid is true if the set is non-empty. | 
| 396 |  |  * - netdiff (if valid) is the largest difference between stack size at the beginning and at the | 
| 397 |  |  *   end of the script across all traces in the set. | 
| 398 |  |  * - exec (if valid) is the largest difference between stack size anywhere during execution and at | 
| 399 |  |  *   the end of the script, across all traces in the set (note that this is not necessarily due | 
| 400 |  |  *   to the same trace as the one that resulted in the value for netdiff). | 
| 401 |  |  * | 
| 402 |  |  * This allows us to build up stack size limits for any script efficiently, by starting from the | 
| 403 |  |  * individual opcodes miniscripts correspond to, using concatenation to construct scripts, and | 
| 404 |  |  * using the union operation to choose between execution branches. Since any top-level script | 
| 405 |  |  * satisfaction ends with a single stack element, we know that for a full script: | 
| 406 |  |  * - netdiff+1 is the maximal initial stack size (relevant for P2WSH stack limits). | 
| 407 |  |  * - exec+1 is the maximal stack size reached during execution (relevant for P2TR stack limits). | 
| 408 |  |  * | 
| 409 |  |  * Mathematically, SatInfo forms a semiring: | 
| 410 |  |  * - operator| is the semiring addition operator, with identity SatInfo{}, and which is commutative | 
| 411 |  |  *   and associative. | 
| 412 |  |  * - operator+ is the semiring multiplication operator, with identity SatInfo{0}, and which is | 
| 413 |  |  *   associative. | 
| 414 |  |  * - operator+ is distributive over operator|, so (a + (b | c)) = (a+b | a+c). This means we do not | 
| 415 |  |  *   need to actually materialize all possible full execution traces over the whole script (which | 
| 416 |  |  *   may be exponential in the length of the script); instead we can use the union operation at the | 
| 417 |  |  *   individual subexpression level, and concatenate the result with subexpressions before and | 
| 418 |  |  *   after it. | 
| 419 |  |  * - It is not a commutative semiring, because a+b can differ from b+a. For example, "OP_1 OP_DROP" | 
| 420 |  |  *   has exec=1, while "OP_DROP OP_1" has exec=0. | 
| 421 |  |  */ | 
| 422 |  | struct SatInfo { | 
| 423 |  |     //! Whether a canonical satisfaction/dissatisfaction is possible at all. | 
| 424 |  |     const bool valid; | 
| 425 |  |     //! How much higher the stack size at start of execution can be compared to at the end. | 
| 426 |  |     const int32_t netdiff; | 
| 427 |  |     //! Mow much higher the stack size can be during execution compared to at the end. | 
| 428 |  |     const int32_t exec; | 
| 429 |  |  | 
| 430 |  |     /** Empty script set. */ | 
| 431 | 0 |     constexpr SatInfo() noexcept : valid(false), netdiff(0), exec(0) {} | 
| 432 |  |  | 
| 433 |  |     /** Script set with a single script in it, with specified netdiff and exec. */ | 
| 434 |  |     constexpr SatInfo(int32_t in_netdiff, int32_t in_exec) noexcept : | 
| 435 | 0 |         valid{true}, netdiff{in_netdiff}, exec{in_exec} {} | 
| 436 |  |  | 
| 437 |  |     /** Script set union. */ | 
| 438 |  |     constexpr friend SatInfo operator|(const SatInfo& a, const SatInfo& b) noexcept | 
| 439 | 0 |     { | 
| 440 |  |         // Union with an empty set is itself. | 
| 441 | 0 |         if (!a.valid) return b; | 
| 442 | 0 |         if (!b.valid) return a; | 
| 443 |  |         // Otherwise the netdiff and exec of the union is the maximum of the individual values. | 
| 444 | 0 |         return {std::max(a.netdiff, b.netdiff), std::max(a.exec, b.exec)}; | 
| 445 | 0 |     } | 
| 446 |  |  | 
| 447 |  |     /** Script set concatenation. */ | 
| 448 |  |     constexpr friend SatInfo operator+(const SatInfo& a, const SatInfo& b) noexcept | 
| 449 | 0 |     { | 
| 450 |  |         // Concatenation with an empty set yields an empty set. | 
| 451 | 0 |         if (!a.valid || !b.valid) return {}; | 
| 452 |  |         // Otherwise, the maximum stack size difference for the combined scripts is the sum of the | 
| 453 |  |         // netdiffs, and the maximum stack size difference anywhere is either b.exec (if the | 
| 454 |  |         // maximum occurred in b) or b.netdiff+a.exec (if the maximum occurred in a). | 
| 455 | 0 |         return {a.netdiff + b.netdiff, std::max(b.exec, b.netdiff + a.exec)}; | 
| 456 | 0 |     } | 
| 457 |  |  | 
| 458 |  |     /** The empty script. */ | 
| 459 | 0 |     static constexpr SatInfo Empty() noexcept { return {0, 0}; } | 
| 460 |  |     /** A script consisting of a single push opcode. */ | 
| 461 | 0 |     static constexpr SatInfo Push() noexcept { return {-1, 0}; } | 
| 462 |  |     /** A script consisting of a single hash opcode. */ | 
| 463 | 0 |     static constexpr SatInfo Hash() noexcept { return {0, 0}; } | 
| 464 |  |     /** A script consisting of just a repurposed nop (OP_CHECKLOCKTIMEVERIFY, OP_CHECKSEQUENCEVERIFY). */ | 
| 465 | 0 |     static constexpr SatInfo Nop() noexcept { return {0, 0}; } | 
| 466 |  |     /** A script consisting of just OP_IF or OP_NOTIF. Note that OP_ELSE and OP_ENDIF have no stack effect. */ | 
| 467 | 0 |     static constexpr SatInfo If() noexcept { return {1, 1}; } | 
| 468 |  |     /** A script consisting of just a binary operator (OP_BOOLAND, OP_BOOLOR, OP_ADD). */ | 
| 469 | 0 |     static constexpr SatInfo BinaryOp() noexcept { return {1, 1}; } | 
| 470 |  |  | 
| 471 |  |     // Scripts for specific individual opcodes. | 
| 472 | 0 |     static constexpr SatInfo OP_DUP() noexcept { return {-1, 0}; } | 
| 473 | 0 |     static constexpr SatInfo OP_IFDUP(bool nonzero) noexcept { return {nonzero ? -1 : 0, 0}; } | 
| 474 | 0 |     static constexpr SatInfo OP_EQUALVERIFY() noexcept { return {2, 2}; } | 
| 475 | 0 |     static constexpr SatInfo OP_EQUAL() noexcept { return {1, 1}; } | 
| 476 | 0 |     static constexpr SatInfo OP_SIZE() noexcept { return {-1, 0}; } | 
| 477 | 0 |     static constexpr SatInfo OP_CHECKSIG() noexcept { return {1, 1}; } | 
| 478 | 0 |     static constexpr SatInfo OP_0NOTEQUAL() noexcept { return {0, 0}; } | 
| 479 | 0 |     static constexpr SatInfo OP_VERIFY() noexcept { return {1, 1}; } | 
| 480 |  | }; | 
| 481 |  |  | 
| 482 |  | struct StackSize { | 
| 483 |  |     const SatInfo sat, dsat; | 
| 484 |  |  | 
| 485 | 0 |     constexpr StackSize(SatInfo in_sat, SatInfo in_dsat) noexcept : sat(in_sat), dsat(in_dsat) {}; | 
| 486 | 0 |     constexpr StackSize(SatInfo in_both) noexcept : sat(in_both), dsat(in_both) {}; | 
| 487 |  | }; | 
| 488 |  |  | 
| 489 |  | struct WitnessSize { | 
| 490 |  |     //! Maximum witness size to satisfy; | 
| 491 |  |     MaxInt<uint32_t> sat; | 
| 492 |  |     //! Maximum witness size to dissatisfy; | 
| 493 |  |     MaxInt<uint32_t> dsat; | 
| 494 |  |  | 
| 495 | 0 |     WitnessSize(MaxInt<uint32_t> in_sat, MaxInt<uint32_t> in_dsat) : sat(in_sat), dsat(in_dsat) {}; | 
| 496 |  | }; | 
| 497 |  |  | 
| 498 |  | struct NoDupCheck {}; | 
| 499 |  |  | 
| 500 |  | } // namespace internal | 
| 501 |  |  | 
| 502 |  | //! A node in a miniscript expression. | 
| 503 |  | template<typename Key> | 
| 504 |  | struct Node { | 
| 505 |  |     //! What node type this node is. | 
| 506 |  |     const Fragment fragment; | 
| 507 |  |     //! The k parameter (time for OLDER/AFTER, threshold for THRESH(_M)) | 
| 508 |  |     const uint32_t k = 0; | 
| 509 |  |     //! The keys used by this expression (only for PK_K/PK_H/MULTI) | 
| 510 |  |     const std::vector<Key> keys; | 
| 511 |  |     //! The data bytes in this expression (only for HASH160/HASH256/SHA256/RIPEMD10). | 
| 512 |  |     const std::vector<unsigned char> data; | 
| 513 |  |     //! Subexpressions (for WRAP_*/AND_*/OR_*/ANDOR/THRESH) | 
| 514 |  |     mutable std::vector<NodeRef<Key>> subs; | 
| 515 |  |     //! The Script context for this node. Either P2WSH or Tapscript. | 
| 516 |  |     const MiniscriptContext m_script_ctx; | 
| 517 |  |  | 
| 518 |  |     /* Destroy the shared pointers iteratively to avoid a stack-overflow due to recursive calls | 
| 519 |  |      * to the subs' destructors. */ | 
| 520 | 0 |     ~Node() { | 
| 521 | 0 |         while (!subs.empty()) { | 
| 522 | 0 |             auto node = std::move(subs.back()); | 
| 523 | 0 |             subs.pop_back(); | 
| 524 | 0 |             while (!node->subs.empty()) { | 
| 525 | 0 |                 subs.push_back(std::move(node->subs.back())); | 
| 526 | 0 |                 node->subs.pop_back(); | 
| 527 | 0 |             } | 
| 528 | 0 |         } | 
| 529 | 0 |     } Unexecuted instantiation: _ZN10miniscript4NodeI7CPubKeyED2EvUnexecuted instantiation: miniscript.cpp:_ZN10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEED2EvUnexecuted instantiation: _ZN10miniscript4NodeIjED2EvUnexecuted instantiation: _ZN10miniscript4NodeI11XOnlyPubKeyED2Ev | 
| 530 |  |  | 
| 531 |  |     NodeRef<Key> Clone() const | 
| 532 | 0 |     { | 
| 533 |  |         // Use TreeEval() to avoid a stack-overflow due to recursion | 
| 534 | 0 |         auto upfn = [](const Node& node, std::span<NodeRef<Key>> children) { | 
| 535 | 0 |             std::vector<NodeRef<Key>> new_subs; | 
| 536 | 0 |             for (auto child = children.begin(); child != children.end(); ++child) { | 
| 537 | 0 |                 new_subs.emplace_back(std::move(*child)); | 
| 538 | 0 |             } | 
| 539 |  |             // std::make_unique (and therefore MakeNodeRef) doesn't work on private constructors | 
| 540 | 0 |             return std::unique_ptr<Node>{new Node{internal::NoDupCheck{}, node.m_script_ctx, node.fragment, std::move(new_subs), node.keys, node.data, node.k}}; | 
| 541 | 0 |         }; | 
| 542 | 0 |         return TreeEval<NodeRef<Key>>(upfn); | 
| 543 | 0 |     } | 
| 544 |  |  | 
| 545 |  | private: | 
| 546 |  |     //! Cached ops counts. | 
| 547 |  |     const internal::Ops ops; | 
| 548 |  |     //! Cached stack size bounds. | 
| 549 |  |     const internal::StackSize ss; | 
| 550 |  |     //! Cached witness size bounds. | 
| 551 |  |     const internal::WitnessSize ws; | 
| 552 |  |     //! Cached expression type (computed by CalcType and fed through SanitizeType). | 
| 553 |  |     const Type typ; | 
| 554 |  |     //! Cached script length (computed by CalcScriptLen). | 
| 555 |  |     const size_t scriptlen; | 
| 556 |  |     //! Whether a public key appears more than once in this node. This value is initialized | 
| 557 |  |     //! by all constructors except the NoDupCheck ones. The NoDupCheck ones skip the | 
| 558 |  |     //! computation, requiring it to be done manually by invoking DuplicateKeyCheck(). | 
| 559 |  |     //! DuplicateKeyCheck(), or a non-NoDupCheck constructor, will compute has_duplicate_keys | 
| 560 |  |     //! for all subnodes as well. | 
| 561 |  |     mutable std::optional<bool> has_duplicate_keys; | 
| 562 |  |  | 
| 563 |  |     // Constructor which takes all of the data that a Node could possibly contain. | 
| 564 |  |     // This is kept private as no valid fragment has all of these arguments. | 
| 565 |  |     // Only used by Clone() | 
| 566 |  |     Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, std::vector<unsigned char> arg, uint32_t val) | 
| 567 | 0 |         : fragment(nt), k(val), keys(key), data(std::move(arg)), subs(std::move(sub)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {} | 
| 568 |  |  | 
| 569 |  |     //! Compute the length of the script for this miniscript (including children). | 
| 570 | 0 |     size_t CalcScriptLen() const { | 
| 571 | 0 |         size_t subsize = 0; | 
| 572 | 0 |         for (const auto& sub : subs) { | 
| 573 | 0 |             subsize += sub->ScriptSize(); | 
| 574 | 0 |         } | 
| 575 | 0 |         Type sub0type = subs.size() > 0 ? subs[0]->GetType() : ""_mst; | 
| 576 | 0 |         return internal::ComputeScriptLen(fragment, sub0type, subsize, k, subs.size(), keys.size(), m_script_ctx); | 
| 577 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE13CalcScriptLenEvUnexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE13CalcScriptLenEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE13CalcScriptLenEvUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE13CalcScriptLenEv | 
| 578 |  |  | 
| 579 |  |     /* Apply a recursive algorithm to a Miniscript tree, without actual recursive calls. | 
| 580 |  |      * | 
| 581 |  |      * The algorithm is defined by two functions: downfn and upfn. Conceptually, the | 
| 582 |  |      * result can be thought of as first using downfn to compute a "state" for each node, | 
| 583 |  |      * from the root down to the leaves. Then upfn is used to compute a "result" for each | 
| 584 |  |      * node, from the leaves back up to the root, which is then returned. In the actual | 
| 585 |  |      * implementation, both functions are invoked in an interleaved fashion, performing a | 
| 586 |  |      * depth-first traversal of the tree. | 
| 587 |  |      * | 
| 588 |  |      * In more detail, it is invoked as node.TreeEvalMaybe<Result>(root, downfn, upfn): | 
| 589 |  |      * - root is the state of the root node, of type State. | 
| 590 |  |      * - downfn is a callable (State&, const Node&, size_t) -> State, which given a | 
| 591 |  |      *   node, its state, and an index of one of its children, computes the state of that | 
| 592 |  |      *   child. It can modify the state. Children of a given node will have downfn() | 
| 593 |  |      *   called in order. | 
| 594 |  |      * - upfn is a callable (State&&, const Node&, std::span<Result>) -> std::optional<Result>, | 
| 595 |  |      *   which given a node, its state, and a span of the results of its children, | 
| 596 |  |      *   computes the result of the node. If std::nullopt is returned by upfn, | 
| 597 |  |      *   TreeEvalMaybe() immediately returns std::nullopt. | 
| 598 |  |      * The return value of TreeEvalMaybe is the result of the root node. | 
| 599 |  |      * | 
| 600 |  |      * Result type cannot be bool due to the std::vector<bool> specialization. | 
| 601 |  |      */ | 
| 602 |  |     template<typename Result, typename State, typename DownFn, typename UpFn> | 
| 603 |  |     std::optional<Result> TreeEvalMaybe(State root_state, DownFn downfn, UpFn upfn) const | 
| 604 | 0 |     { | 
| 605 |  |         /** Entries of the explicit stack tracked in this algorithm. */ | 
| 606 | 0 |         struct StackElem | 
| 607 | 0 |         { | 
| 608 | 0 |             const Node& node; //!< The node being evaluated. | 
| 609 | 0 |             size_t expanded; //!< How many children of this node have been expanded. | 
| 610 | 0 |             State state; //!< The state for that node. | 
| 611 |  | 
 | 
| 612 | 0 |             StackElem(const Node& node_, size_t exp_, State&& state_) : | 
| 613 | 0 |                 node(node_), expanded(exp_), state(std::move(state_)) {}Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeI7CScriptbZNKS2_8ToScriptIN12_GLOBAL__N_113ParserContextEEES4_RKT_EUlbRKS2_mE_ZNKS2_8TreeEvalIS4_bRSD_ZNKS5_IS7_EES4_SA_EUlbSC_NSt3__14spanIS4_Lm18446744073709551615EEEE_EES8_T0_OT1_T2_EUlObSC_SI_E_EENSG_8optionalIS8_EESK_SL_SN_EN9StackElemC2ESC_mSO_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113ParserContextEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS2_8TreeEvalISH_ZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_E10DummyStateZNKSI_ISH_SN_EESA_SO_EUlSP_SK_mE_ZNKSI_ISH_SN_EESA_SO_EUlSP_SK_SM_E_EENS5_ISA_EESO_T1_T2_EN9StackElemC2ESK_mOSP_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINS_8internal11InputResultEZNKS2_8TreeEvalIS5_ZNKS2_12ProduceInputIN12_GLOBAL__N_116SatisfierContextEEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EESA_T0_E10DummyStateZNKS6_IS5_SI_EESA_SJ_EUlSK_SE_mE_ZNKS6_IS5_SI_EESA_SJ_EUlSK_SE_SH_E_EENSF_8optionalISA_EESJ_T1_T2_EN9StackElemC2ESE_mOSK_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeIiZNKS2_8TreeEvalIiZNKS2_13IsSatisfiableIZN12_GLOBAL__N_18TestNodeENS_17MiniscriptContextERKNSt3__110unique_ptrIKS2_NS8_14default_deleteISA_EEEER18FuzzedDataProviderE3$_0EEbT_EUlRSA_NS8_4spanIiLm18446744073709551615EEEE_EESJ_T0_E10DummyStateZNKS4_IiSN_EESJ_SO_EUlSP_SK_mE_ZNKS4_IiSN_EESJ_SO_EUlSP_SK_SM_E_EENS8_8optionalISJ_EESO_T1_T2_EN9StackElemC2ESK_mOSP_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEbZNKS2_8ToStringIN12_GLOBAL__N_113ParserContextEEENS4_8optionalISA_EERKT_EUlbRKS2_mE_ZNKSB_ISD_EESF_SI_EUlbSK_NS4_4spanISA_Lm18446744073709551615EEEE_EENSE_ISG_EET0_T1_T2_EN9StackElemC2ESK_mObUnexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113KeyComparatorEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS2_8TreeEvalISH_ZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_E10DummyStateZNKSI_ISH_SN_EESA_SO_EUlSP_SK_mE_ZNKSI_ISH_SN_EESA_SO_EUlSP_SK_SM_E_EENS5_ISA_EESO_T1_T2_EN9StackElemC2ESK_mOSP_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE13TreeEvalMaybeINSt3__18optionalINS6_3setIS3_ZNKS4_17DuplicateKeyCheckIS2_EEvRKT_E4CompNS6_9allocatorIS3_EEEEEEZNKS4_8TreeEvalISH_ZNKS9_IS2_EEvSC_EUlRKS4_NS6_4spanISH_Lm18446744073709551615EEEE_EESA_T0_E10DummyStateZNKSI_ISH_SN_EESA_SO_EUlSP_SK_mE_ZNKSI_ISH_SN_EESA_SO_EUlSP_SK_SM_E_EENS7_ISA_EESO_T1_T2_EN9StackElemC2ESK_mOSP_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE13TreeEvalMaybeI7CScriptbZNKS4_8ToScriptIS2_EES6_RKT_EUlbRKS4_mE_ZNKS4_8TreeEvalIS6_bRSD_ZNKS7_IS2_EES6_SA_EUlbSC_NSt3__14spanIS6_Lm18446744073709551615EEEE_EES8_T0_OT1_T2_EUlObSC_SI_E_EENSG_8optionalIS8_EESK_SL_SN_EN9StackElemC2ESC_mSO_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE13TreeEvalMaybeINSt3__18optionalINS3_3setIjZNKS1_17DuplicateKeyCheckIN12_GLOBAL__N_19KeyParserEEEvRKT_E4CompNS3_9allocatorIjEEEEEEZNKS1_8TreeEvalISG_ZNKS6_IS8_EEvSB_EUlRKS1_NS3_4spanISG_Lm18446744073709551615EEEE_EES9_T0_E10DummyStateZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_mE_ZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_SL_E_EENS4_IS9_EESN_T1_T2_EN9StackElemC2ESJ_mOSO_Unexecuted instantiation: _ZZNK10miniscript4NodeIjE13TreeEvalMaybeIPKS1_ZNKS1_8TreeEvalIS4_ZNKS1_13FindInsaneSubEvEUlRS3_NSt3__14spanIS4_Lm18446744073709551615EEEE_EET_T0_E10DummyStateZNKS5_IS4_SA_EESB_SC_EUlSD_S6_mE_ZNKS5_IS4_SA_EESB_SC_EUlSD_S6_S9_E_EENS7_8optionalISB_EESC_T1_T2_EN9StackElemC2ES6_mOSD_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE13TreeEvalMaybeINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbZNKS1_8ToStringIN12_GLOBAL__N_19KeyParserEEENS3_8optionalIS9_EERKT_EUlbRKS1_mE_ZNKSA_ISC_EESE_SH_EUlbSJ_NS3_4spanIS9_Lm18446744073709551615EEEE_EENSD_ISF_EET0_T1_T2_EN9StackElemC2ESJ_mObUnexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE13TreeEvalMaybeI7CScriptbZNKS1_8ToScriptIN12_GLOBAL__N_111ScriptMakerEEES3_RKT_EUlbRKS1_mE_ZNKS1_8TreeEvalIS3_bRSC_ZNKS4_IS6_EES3_S9_EUlbSB_NSt3__14spanIS3_Lm18446744073709551615EEEE_EES7_T0_OT1_T2_EUlObSB_SH_E_EENSF_8optionalIS7_EESJ_SK_SM_EN9StackElemC2ESB_mSN_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE13TreeEvalMaybeINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbZNKS1_8ToStringIN12_GLOBAL__N_111StringMakerEEENS3_8optionalIS9_EERKT_EUlbRKS1_mE_ZNKSA_ISC_EESE_SH_EUlbSJ_NS3_4spanIS9_Lm18446744073709551615EEEE_EENSD_ISF_EET0_T1_T2_EN9StackElemC2ESJ_mObUnexecuted instantiation: _ZZNK10miniscript4NodeIjE13TreeEvalMaybeINSt3__110unique_ptrIKS1_NS3_14default_deleteIS5_EEEEZNKS1_8TreeEvalIS8_ZNKS1_5CloneEvEUlRS5_NS3_4spanIS8_Lm18446744073709551615EEEE_EET_T0_E10DummyStateZNKS9_IS8_SD_EESE_SF_EUlSG_SA_mE_ZNKS9_IS8_SD_EESE_SF_EUlSG_SA_SC_E_EENS3_8optionalISE_EESF_T1_T2_EN9StackElemC2ESA_mOSG_Unexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE13TreeEvalMaybeINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12TapSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS2_8TreeEvalISG_ZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_E10DummyStateZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_mE_ZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_SL_E_EENS5_IS9_EESN_T1_T2_EN9StackElemC2ESJ_mOSO_Unexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE13TreeEvalMaybeINS_8internal11InputResultEZNKS2_8TreeEvalIS5_ZNKS2_12ProduceInputI12TapSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES9_T0_E10DummyStateZNKS6_IS5_SH_EES9_SI_EUlSJ_SD_mE_ZNKS6_IS5_SH_EES9_SI_EUlSJ_SD_SG_E_EENSE_8optionalIS9_EESI_T1_T2_EN9StackElemC2ESD_mOSJ_Unexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12WshSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS2_8TreeEvalISG_ZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_E10DummyStateZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_mE_ZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_SL_E_EENS5_IS9_EESN_T1_T2_EN9StackElemC2ESJ_mOSO_Unexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINS_8internal11InputResultEZNKS2_8TreeEvalIS5_ZNKS2_12ProduceInputI12WshSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES9_T0_E10DummyStateZNKS6_IS5_SH_EES9_SI_EUlSJ_SD_mE_ZNKS6_IS5_SH_EES9_SI_EUlSJ_SD_SG_E_EENSE_8optionalIS9_EESI_T1_T2_EN9StackElemC2ESD_mOSJ_ | 
| 614 | 0 |         }; | 
| 615 |  |         /* Stack of tree nodes being explored. */ | 
| 616 | 0 |         std::vector<StackElem> stack; | 
| 617 |  |         /* Results of subtrees so far. Their order and mapping to tree nodes | 
| 618 |  |          * is implicitly defined by stack. */ | 
| 619 | 0 |         std::vector<Result> results; | 
| 620 | 0 |         stack.emplace_back(*this, 0, std::move(root_state)); | 
| 621 |  |  | 
| 622 |  |         /* Here is a demonstration of the algorithm, for an example tree A(B,C(D,E),F). | 
| 623 |  |          * State variables are omitted for simplicity. | 
| 624 |  |          * | 
| 625 |  |          * First: stack=[(A,0)] results=[] | 
| 626 |  |          *        stack=[(A,1),(B,0)] results=[] | 
| 627 |  |          *        stack=[(A,1)] results=[B] | 
| 628 |  |          *        stack=[(A,2),(C,0)] results=[B] | 
| 629 |  |          *        stack=[(A,2),(C,1),(D,0)] results=[B] | 
| 630 |  |          *        stack=[(A,2),(C,1)] results=[B,D] | 
| 631 |  |          *        stack=[(A,2),(C,2),(E,0)] results=[B,D] | 
| 632 |  |          *        stack=[(A,2),(C,2)] results=[B,D,E] | 
| 633 |  |          *        stack=[(A,2)] results=[B,C] | 
| 634 |  |          *        stack=[(A,3),(F,0)] results=[B,C] | 
| 635 |  |          *        stack=[(A,3)] results=[B,C,F] | 
| 636 |  |          * Final: stack=[] results=[A] | 
| 637 |  |          */ | 
| 638 | 0 |         while (stack.size()) { | 
| 639 | 0 |             const Node& node = stack.back().node; | 
| 640 | 0 |             if (stack.back().expanded < node.subs.size()) { | 
| 641 |  |                 /* We encounter a tree node with at least one unexpanded child. | 
| 642 |  |                  * Expand it. By the time we hit this node again, the result of | 
| 643 |  |                  * that child (and all earlier children) will be at the end of `results`. */ | 
| 644 | 0 |                 size_t child_index = stack.back().expanded++; | 
| 645 | 0 |                 State child_state = downfn(stack.back().state, node, child_index); | 
| 646 | 0 |                 stack.emplace_back(*node.subs[child_index], 0, std::move(child_state)); | 
| 647 | 0 |                 continue; | 
| 648 | 0 |             } | 
| 649 |  |             // Invoke upfn with the last node.subs.size() elements of results as input. | 
| 650 | 0 |             assert(results.size() >= node.subs.size()); | 
| 651 | 0 |             std::optional<Result> result{upfn(std::move(stack.back().state), node, | 
| 652 | 0 |                 std::span<Result>{results}.last(node.subs.size()))}; | 
| 653 |  |             // If evaluation returns std::nullopt, abort immediately. | 
| 654 | 0 |             if (!result) return {}; | 
| 655 |  |             // Replace the last node.subs.size() elements of results with the new result. | 
| 656 | 0 |             results.erase(results.end() - node.subs.size(), results.end()); | 
| 657 | 0 |             results.push_back(std::move(*result)); | 
| 658 | 0 |             stack.pop_back(); | 
| 659 | 0 |         } | 
| 660 |  |         // The final remaining results element is the root result, return it. | 
| 661 | 0 |         assert(results.size() >= 1); | 
| 662 | 0 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |         CHECK_NONFATAL(results.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 663 | 0 |         return std::move(results[0]); | 
| 664 | 0 |     } Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeI7CScriptbZNKS2_8ToScriptIN12_GLOBAL__N_113ParserContextEEES4_RKT_EUlbRKS2_mE_ZNKS2_8TreeEvalIS4_bRSD_ZNKS5_IS7_EES4_SA_EUlbSC_NSt3__14spanIS4_Lm18446744073709551615EEEE_EES8_T0_OT1_T2_EUlObSC_SI_E_EENSG_8optionalIS8_EESK_SL_SN_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113ParserContextEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS2_8TreeEvalISH_ZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_E10DummyStateZNKSI_ISH_SN_EESA_SO_EUlSP_SK_mE_ZNKSI_ISH_SN_EESA_SO_EUlSP_SK_SM_E_EENS5_ISA_EESO_T1_T2_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINS_8internal11InputResultEZNKS2_8TreeEvalIS5_ZNKS2_12ProduceInputIN12_GLOBAL__N_116SatisfierContextEEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EESA_T0_E10DummyStateZNKS6_IS5_SI_EESA_SJ_EUlSK_SE_mE_ZNKS6_IS5_SI_EESA_SJ_EUlSK_SE_SH_E_EENSF_8optionalISA_EESJ_T1_T2_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeIiZNKS2_8TreeEvalIiZNKS2_13IsSatisfiableIZN12_GLOBAL__N_18TestNodeENS_17MiniscriptContextERKNSt3__110unique_ptrIKS2_NS8_14default_deleteISA_EEEER18FuzzedDataProviderE3$_0EEbT_EUlRSA_NS8_4spanIiLm18446744073709551615EEEE_EESJ_T0_E10DummyStateZNKS4_IiSN_EESJ_SO_EUlSP_SK_mE_ZNKS4_IiSN_EESJ_SO_EUlSP_SK_SM_E_EENS8_8optionalISJ_EESO_T1_T2_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEbZNKS2_8ToStringIN12_GLOBAL__N_113ParserContextEEENS4_8optionalISA_EERKT_EUlbRKS2_mE_ZNKSB_ISD_EESF_SI_EUlbSK_NS4_4spanISA_Lm18446744073709551615EEEE_EENSE_ISG_EET0_T1_T2_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113KeyComparatorEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS2_8TreeEvalISH_ZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_E10DummyStateZNKSI_ISH_SN_EESA_SO_EUlSP_SK_mE_ZNKSI_ISH_SN_EESA_SO_EUlSP_SK_SM_E_EENS5_ISA_EESO_T1_T2_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE13TreeEvalMaybeINSt3__18optionalINS6_3setIS3_ZNKS4_17DuplicateKeyCheckIS2_EEvRKT_E4CompNS6_9allocatorIS3_EEEEEEZNKS4_8TreeEvalISH_ZNKS9_IS2_EEvSC_EUlRKS4_NS6_4spanISH_Lm18446744073709551615EEEE_EESA_T0_E10DummyStateZNKSI_ISH_SN_EESA_SO_EUlSP_SK_mE_ZNKSI_ISH_SN_EESA_SO_EUlSP_SK_SM_E_EENS7_ISA_EESO_T1_T2_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE13TreeEvalMaybeI7CScriptbZNKS4_8ToScriptIS2_EES6_RKT_EUlbRKS4_mE_ZNKS4_8TreeEvalIS6_bRSD_ZNKS7_IS2_EES6_SA_EUlbSC_NSt3__14spanIS6_Lm18446744073709551615EEEE_EES8_T0_OT1_T2_EUlObSC_SI_E_EENSG_8optionalIS8_EESK_SL_SN_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE13TreeEvalMaybeINSt3__18optionalINS3_3setIjZNKS1_17DuplicateKeyCheckIN12_GLOBAL__N_19KeyParserEEEvRKT_E4CompNS3_9allocatorIjEEEEEEZNKS1_8TreeEvalISG_ZNKS6_IS8_EEvSB_EUlRKS1_NS3_4spanISG_Lm18446744073709551615EEEE_EES9_T0_E10DummyStateZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_mE_ZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_SL_E_EENS4_IS9_EESN_T1_T2_Unexecuted instantiation: _ZNK10miniscript4NodeIjE13TreeEvalMaybeIPKS1_ZNKS1_8TreeEvalIS4_ZNKS1_13FindInsaneSubEvEUlRS3_NSt3__14spanIS4_Lm18446744073709551615EEEE_EET_T0_E10DummyStateZNKS5_IS4_SA_EESB_SC_EUlSD_S6_mE_ZNKS5_IS4_SA_EESB_SC_EUlSD_S6_S9_E_EENS7_8optionalISB_EESC_T1_T2_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE13TreeEvalMaybeINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbZNKS1_8ToStringIN12_GLOBAL__N_19KeyParserEEENS3_8optionalIS9_EERKT_EUlbRKS1_mE_ZNKSA_ISC_EESE_SH_EUlbSJ_NS3_4spanIS9_Lm18446744073709551615EEEE_EENSD_ISF_EET0_T1_T2_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE13TreeEvalMaybeI7CScriptbZNKS1_8ToScriptIN12_GLOBAL__N_111ScriptMakerEEES3_RKT_EUlbRKS1_mE_ZNKS1_8TreeEvalIS3_bRSC_ZNKS4_IS6_EES3_S9_EUlbSB_NSt3__14spanIS3_Lm18446744073709551615EEEE_EES7_T0_OT1_T2_EUlObSB_SH_E_EENSF_8optionalIS7_EESJ_SK_SM_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE13TreeEvalMaybeINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbZNKS1_8ToStringIN12_GLOBAL__N_111StringMakerEEENS3_8optionalIS9_EERKT_EUlbRKS1_mE_ZNKSA_ISC_EESE_SH_EUlbSJ_NS3_4spanIS9_Lm18446744073709551615EEEE_EENSD_ISF_EET0_T1_T2_Unexecuted instantiation: _ZNK10miniscript4NodeIjE13TreeEvalMaybeINSt3__110unique_ptrIKS1_NS3_14default_deleteIS5_EEEEZNKS1_8TreeEvalIS8_ZNKS1_5CloneEvEUlRS5_NS3_4spanIS8_Lm18446744073709551615EEEE_EET_T0_E10DummyStateZNKS9_IS8_SD_EESE_SF_EUlSG_SA_mE_ZNKS9_IS8_SD_EESE_SF_EUlSG_SA_SC_E_EENS3_8optionalISE_EESF_T1_T2_Unexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE13TreeEvalMaybeINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12TapSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS2_8TreeEvalISG_ZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_E10DummyStateZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_mE_ZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_SL_E_EENS5_IS9_EESN_T1_T2_Unexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE13TreeEvalMaybeINS_8internal11InputResultEZNKS2_8TreeEvalIS5_ZNKS2_12ProduceInputI12TapSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES9_T0_E10DummyStateZNKS6_IS5_SH_EES9_SI_EUlSJ_SD_mE_ZNKS6_IS5_SH_EES9_SI_EUlSJ_SD_SG_E_EENSE_8optionalIS9_EESI_T1_T2_Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12WshSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS2_8TreeEvalISG_ZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_E10DummyStateZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_mE_ZNKSH_ISG_SM_EES9_SN_EUlSO_SJ_SL_E_EENS5_IS9_EESN_T1_T2_Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE13TreeEvalMaybeINS_8internal11InputResultEZNKS2_8TreeEvalIS5_ZNKS2_12ProduceInputI12WshSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES9_T0_E10DummyStateZNKS6_IS5_SH_EES9_SI_EUlSJ_SD_mE_ZNKS6_IS5_SH_EES9_SI_EUlSJ_SD_SG_E_EENSE_8optionalIS9_EESI_T1_T2_ | 
| 665 |  |  | 
| 666 |  |     /** Like TreeEvalMaybe, but without downfn or State type. | 
| 667 |  |      * upfn takes (const Node&, std::span<Result>) and returns std::optional<Result>. */ | 
| 668 |  |     template<typename Result, typename UpFn> | 
| 669 |  |     std::optional<Result> TreeEvalMaybe(UpFn upfn) const | 
| 670 |  |     { | 
| 671 |  |         struct DummyState {}; | 
| 672 |  |         return TreeEvalMaybe<Result>(DummyState{}, | 
| 673 |  |             [](DummyState, const Node&, size_t) { return DummyState{}; }, | 
| 674 |  |             [&upfn](DummyState, const Node& node, std::span<Result> subs) { | 
| 675 |  |                 return upfn(node, subs); | 
| 676 |  |             } | 
| 677 |  |         ); | 
| 678 |  |     } | 
| 679 |  |  | 
| 680 |  |     /** Like TreeEvalMaybe, but always produces a result. upfn must return Result. */ | 
| 681 |  |     template<typename Result, typename State, typename DownFn, typename UpFn> | 
| 682 |  |     Result TreeEval(State root_state, DownFn&& downfn, UpFn upfn) const | 
| 683 | 0 |     { | 
| 684 |  |         // Invoke TreeEvalMaybe with upfn wrapped to return std::optional<Result>, and then | 
| 685 |  |         // unconditionally dereference the result (it cannot be std::nullopt). | 
| 686 | 0 |         return std::move(*TreeEvalMaybe<Result>(std::move(root_state), | 
| 687 | 0 |             std::forward<DownFn>(downfn), | 
| 688 | 0 |             [&upfn](State&& state, const Node& node, std::span<Result> subs) { | 
| 689 | 0 |                 Result res{upfn(std::move(state), node, subs)}; | 
| 690 | 0 |                 return std::optional<Result>(std::move(res)); | 
| 691 | 0 |             } Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalI7CScriptbRZNKS2_8ToScriptIN12_GLOBAL__N_113ParserContextEEES4_RKT_EUlbRKS2_mE_ZNKS5_IS7_EES4_SA_EUlbSC_NSt3__14spanIS4_Lm18446744073709551615EEEE_EES8_T0_OT1_T2_ENKUlObSC_SH_E_clESN_SC_SH_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE8TreeEvalI7CScriptbRZNKS4_8ToScriptIS2_EES6_RKT_EUlbRKS4_mE_ZNKS7_IS2_EES6_SA_EUlbSC_NSt3__14spanIS6_Lm18446744073709551615EEEE_EES8_T0_OT1_T2_ENKUlObSC_SH_E_clESN_SC_SH_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE8TreeEvalI7CScriptbRZNKS1_8ToScriptIN12_GLOBAL__N_111ScriptMakerEEES3_RKT_EUlbRKS1_mE_ZNKS4_IS6_EES3_S9_EUlbSB_NSt3__14spanIS3_Lm18446744073709551615EEEE_EES7_T0_OT1_T2_ENKUlObSB_SG_E_clESM_SB_SG_ | 
| 692 | 0 |         )); | 
| 693 | 0 |     } Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE8TreeEvalI7CScriptbRZNKS2_8ToScriptIN12_GLOBAL__N_113ParserContextEEES4_RKT_EUlbRKS2_mE_ZNKS5_IS7_EES4_SA_EUlbSC_NSt3__14spanIS4_Lm18446744073709551615EEEE_EES8_T0_OT1_T2_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE8TreeEvalI7CScriptbRZNKS4_8ToScriptIS2_EES6_RKT_EUlbRKS4_mE_ZNKS7_IS2_EES6_SA_EUlbSC_NSt3__14spanIS6_Lm18446744073709551615EEEE_EES8_T0_OT1_T2_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE8TreeEvalI7CScriptbRZNKS1_8ToScriptIN12_GLOBAL__N_111ScriptMakerEEES3_RKT_EUlbRKS1_mE_ZNKS4_IS6_EES3_S9_EUlbSB_NSt3__14spanIS3_Lm18446744073709551615EEEE_EES7_T0_OT1_T2_ | 
| 694 |  |  | 
| 695 |  |     /** Like TreeEval, but without downfn or State type. | 
| 696 |  |      *  upfn takes (const Node&, std::span<Result>) and returns Result. */ | 
| 697 |  |     template<typename Result, typename UpFn> | 
| 698 |  |     Result TreeEval(UpFn upfn) const | 
| 699 | 0 |     { | 
| 700 | 0 |         struct DummyState {}; | 
| 701 | 0 |         return std::move(*TreeEvalMaybe<Result>(DummyState{}, | 
| 702 | 0 |             [](DummyState, const Node&, size_t) { return DummyState{}; },Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113ParserContextEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_ENKUlZNKS3_ISH_SM_EESA_SN_E10DummyStateSJ_mE_clESO_SJ_mUnexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINS_8internal11InputResultEZNKS2_12ProduceInputIN12_GLOBAL__N_116SatisfierContextEEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES9_T0_ENKUlZNKS3_IS5_SH_EES9_SI_E10DummyStateSD_mE_clESJ_SD_mUnexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalIiZNKS2_13IsSatisfiableIZN12_GLOBAL__N_18TestNodeENS_17MiniscriptContextERKNSt3__110unique_ptrIKS2_NS7_14default_deleteIS9_EEEER18FuzzedDataProviderE3$_0EEbT_EUlRS9_NS7_4spanIiLm18446744073709551615EEEE_EESI_T0_ENKUlZNKS3_IiSM_EESI_SN_E10DummyStateSJ_mE_clESO_SJ_mUnexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113KeyComparatorEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_ENKUlZNKS3_ISH_SM_EESA_SN_E10DummyStateSJ_mE_clESO_SJ_mUnexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE8TreeEvalINSt3__18optionalINS6_3setIS3_ZNKS4_17DuplicateKeyCheckIS2_EEvRKT_E4CompNS6_9allocatorIS3_EEEEEEZNKS9_IS2_EEvSC_EUlRKS4_NS6_4spanISH_Lm18446744073709551615EEEE_EESA_T0_ENKUlZNKS5_ISH_SM_EESA_SN_E10DummyStateSJ_mE_clESO_SJ_mUnexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE8TreeEvalINSt3__18optionalINS3_3setIjZNKS1_17DuplicateKeyCheckIN12_GLOBAL__N_19KeyParserEEEvRKT_E4CompNS3_9allocatorIjEEEEEEZNKS6_IS8_EEvSB_EUlRKS1_NS3_4spanISG_Lm18446744073709551615EEEE_EES9_T0_ENKUlZNKS2_ISG_SL_EES9_SM_E10DummyStateSI_mE_clESN_SI_mUnexecuted instantiation: _ZZNK10miniscript4NodeIjE8TreeEvalIPKS1_ZNKS1_13FindInsaneSubEvEUlRS3_NSt3__14spanIS4_Lm18446744073709551615EEEE_EET_T0_ENKUlZNKS2_IS4_S9_EESA_SB_E10DummyStateS5_mE_clESC_S5_mUnexecuted instantiation: _ZZNK10miniscript4NodeIjE8TreeEvalINSt3__110unique_ptrIKS1_NS3_14default_deleteIS5_EEEEZNKS1_5CloneEvEUlRS5_NS3_4spanIS8_Lm18446744073709551615EEEE_EET_T0_ENKUlZNKS2_IS8_SC_EESD_SE_E10DummyStateS9_mE_clESF_S9_mUnexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12TapSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_ENKUlZNKS3_ISG_SL_EES9_SM_E10DummyStateSI_mE_clESN_SI_mUnexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE8TreeEvalINS_8internal11InputResultEZNKS2_12ProduceInputI12TapSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES8_T0_ENKUlZNKS3_IS5_SG_EES8_SH_E10DummyStateSC_mE_clESI_SC_mUnexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12WshSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_ENKUlZNKS3_ISG_SL_EES9_SM_E10DummyStateSI_mE_clESN_SI_mUnexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINS_8internal11InputResultEZNKS2_12ProduceInputI12WshSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES8_T0_ENKUlZNKS3_IS5_SG_EES8_SH_E10DummyStateSC_mE_clESI_SC_m | 
| 703 | 0 |             [&upfn](DummyState, const Node& node, std::span<Result> subs) { | 
| 704 | 0 |                 Result res{upfn(node, subs)}; | 
| 705 | 0 |                 return std::optional<Result>(std::move(res)); | 
| 706 | 0 |             } Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113ParserContextEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_ENKUlZNKS3_ISH_SM_EESA_SN_E10DummyStateSJ_SL_E_clESO_SJ_SL_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINS_8internal11InputResultEZNKS2_12ProduceInputIN12_GLOBAL__N_116SatisfierContextEEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES9_T0_ENKUlZNKS3_IS5_SH_EES9_SI_E10DummyStateSD_SG_E_clESJ_SD_SG_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalIiZNKS2_13IsSatisfiableIZN12_GLOBAL__N_18TestNodeENS_17MiniscriptContextERKNSt3__110unique_ptrIKS2_NS7_14default_deleteIS9_EEEER18FuzzedDataProviderE3$_0EEbT_EUlRS9_NS7_4spanIiLm18446744073709551615EEEE_EESI_T0_ENKUlZNKS3_IiSM_EESI_SN_E10DummyStateSJ_SL_E_clESO_SJ_SL_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113KeyComparatorEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_ENKUlZNKS3_ISH_SM_EESA_SN_E10DummyStateSJ_SL_E_clESO_SJ_SL_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE8TreeEvalINSt3__18optionalINS6_3setIS3_ZNKS4_17DuplicateKeyCheckIS2_EEvRKT_E4CompNS6_9allocatorIS3_EEEEEEZNKS9_IS2_EEvSC_EUlRKS4_NS6_4spanISH_Lm18446744073709551615EEEE_EESA_T0_ENKUlZNKS5_ISH_SM_EESA_SN_E10DummyStateSJ_SL_E_clESO_SJ_SL_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE8TreeEvalINSt3__18optionalINS3_3setIjZNKS1_17DuplicateKeyCheckIN12_GLOBAL__N_19KeyParserEEEvRKT_E4CompNS3_9allocatorIjEEEEEEZNKS6_IS8_EEvSB_EUlRKS1_NS3_4spanISG_Lm18446744073709551615EEEE_EES9_T0_ENKUlZNKS2_ISG_SL_EES9_SM_E10DummyStateSI_SK_E_clESN_SI_SK_Unexecuted instantiation: _ZZNK10miniscript4NodeIjE8TreeEvalIPKS1_ZNKS1_13FindInsaneSubEvEUlRS3_NSt3__14spanIS4_Lm18446744073709551615EEEE_EET_T0_ENKUlZNKS2_IS4_S9_EESA_SB_E10DummyStateS5_S8_E_clESC_S5_S8_Unexecuted instantiation: _ZZNK10miniscript4NodeIjE8TreeEvalINSt3__110unique_ptrIKS1_NS3_14default_deleteIS5_EEEEZNKS1_5CloneEvEUlRS5_NS3_4spanIS8_Lm18446744073709551615EEEE_EET_T0_ENKUlZNKS2_IS8_SC_EESD_SE_E10DummyStateS9_SB_E_clESF_S9_SB_Unexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12TapSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_ENKUlZNKS3_ISG_SL_EES9_SM_E10DummyStateSI_SK_E_clESN_SI_SK_Unexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE8TreeEvalINS_8internal11InputResultEZNKS2_12ProduceInputI12TapSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES8_T0_ENKUlZNKS3_IS5_SG_EES8_SH_E10DummyStateSC_SF_E_clESI_SC_SF_Unexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12WshSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_ENKUlZNKS3_ISG_SL_EES9_SM_E10DummyStateSI_SK_E_clESN_SI_SK_Unexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE8TreeEvalINS_8internal11InputResultEZNKS2_12ProduceInputI12WshSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES8_T0_ENKUlZNKS3_IS5_SG_EES8_SH_E10DummyStateSC_SF_E_clESI_SC_SF_ | 
| 707 | 0 |         )); | 
| 708 | 0 |     } Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113ParserContextEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE8TreeEvalINS_8internal11InputResultEZNKS2_12ProduceInputIN12_GLOBAL__N_116SatisfierContextEEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES9_T0_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE8TreeEvalIiZNKS2_13IsSatisfiableIZN12_GLOBAL__N_18TestNodeENS_17MiniscriptContextERKNSt3__110unique_ptrIKS2_NS7_14default_deleteIS9_EEEER18FuzzedDataProviderE3$_0EEbT_EUlRS9_NS7_4spanIiLm18446744073709551615EEEE_EESI_T0_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckIN12_GLOBAL__N_113KeyComparatorEEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS9_EEvSC_EUlRKS2_NS4_4spanISH_Lm18446744073709551615EEEE_EESA_T0_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE8TreeEvalINSt3__18optionalINS6_3setIS3_ZNKS4_17DuplicateKeyCheckIS2_EEvRKT_E4CompNS6_9allocatorIS3_EEEEEEZNKS9_IS2_EEvSC_EUlRKS4_NS6_4spanISH_Lm18446744073709551615EEEE_EESA_T0_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE8TreeEvalINSt3__18optionalINS3_3setIjZNKS1_17DuplicateKeyCheckIN12_GLOBAL__N_19KeyParserEEEvRKT_E4CompNS3_9allocatorIjEEEEEEZNKS6_IS8_EEvSB_EUlRKS1_NS3_4spanISG_Lm18446744073709551615EEEE_EES9_T0_Unexecuted instantiation: _ZNK10miniscript4NodeIjE8TreeEvalIPKS1_ZNKS1_13FindInsaneSubEvEUlRS3_NSt3__14spanIS4_Lm18446744073709551615EEEE_EET_T0_Unexecuted instantiation: _ZNK10miniscript4NodeIjE8TreeEvalINSt3__110unique_ptrIKS1_NS3_14default_deleteIS5_EEEEZNKS1_5CloneEvEUlRS5_NS3_4spanIS8_Lm18446744073709551615EEEE_EET_T0_Unexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12TapSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_Unexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE8TreeEvalINS_8internal11InputResultEZNKS2_12ProduceInputI12TapSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES8_T0_Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE8TreeEvalINSt3__18optionalINS4_3setIS1_ZNKS2_17DuplicateKeyCheckI12WshSatisfierEEvRKT_E4CompNS4_9allocatorIS1_EEEEEEZNKS7_IS8_EEvSB_EUlRKS2_NS4_4spanISG_Lm18446744073709551615EEEE_EES9_T0_Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE8TreeEvalINS_8internal11InputResultEZNKS2_12ProduceInputI12WshSatisfierEES5_RKT_EUlRKS2_NSt3__14spanIS5_Lm18446744073709551615EEEE0_EES8_T0_ | 
| 709 |  |  | 
| 710 |  |     /** Compare two miniscript subtrees, using a non-recursive algorithm. */ | 
| 711 |  |     friend int Compare(const Node<Key>& node1, const Node<Key>& node2) | 
| 712 | 0 |     { | 
| 713 | 0 |         std::vector<std::pair<const Node<Key>&, const Node<Key>&>> queue; | 
| 714 | 0 |         queue.emplace_back(node1, node2); | 
| 715 | 0 |         while (!queue.empty()) { | 
| 716 | 0 |             const auto& [a, b] = queue.back(); | 
| 717 | 0 |             queue.pop_back(); | 
| 718 | 0 |             if (std::tie(a.fragment, a.k, a.keys, a.data) < std::tie(b.fragment, b.k, b.keys, b.data)) return -1; | 
| 719 | 0 |             if (std::tie(b.fragment, b.k, b.keys, b.data) < std::tie(a.fragment, a.k, a.keys, a.data)) return 1; | 
| 720 | 0 |             if (a.subs.size() < b.subs.size()) return -1; | 
| 721 | 0 |             if (b.subs.size() < a.subs.size()) return 1; | 
| 722 | 0 |             size_t n = a.subs.size(); | 
| 723 | 0 |             for (size_t i = 0; i < n; ++i) { | 
| 724 | 0 |                 queue.emplace_back(*a.subs[n - 1 - i], *b.subs[n - 1 - i]); | 
| 725 | 0 |             } | 
| 726 | 0 |         } | 
| 727 | 0 |         return 0; | 
| 728 | 0 |     } | 
| 729 |  |  | 
| 730 |  |     //! Compute the type for this miniscript. | 
| 731 | 0 |     Type CalcType() const { | 
| 732 | 0 |         using namespace internal; | 
| 733 |  |  | 
| 734 |  |         // THRESH has a variable number of subexpressions | 
| 735 | 0 |         std::vector<Type> sub_types; | 
| 736 | 0 |         if (fragment == Fragment::THRESH) { | 
| 737 | 0 |             for (const auto& sub : subs) sub_types.push_back(sub->GetType()); | 
| 738 | 0 |         } | 
| 739 |  |         // All other nodes than THRESH can be computed just from the types of the 0-3 subexpressions. | 
| 740 | 0 |         Type x = subs.size() > 0 ? subs[0]->GetType() : ""_mst; | 
| 741 | 0 |         Type y = subs.size() > 1 ? subs[1]->GetType() : ""_mst; | 
| 742 | 0 |         Type z = subs.size() > 2 ? subs[2]->GetType() : ""_mst; | 
| 743 |  | 
 | 
| 744 | 0 |         return SanitizeType(ComputeType(fragment, x, y, z, sub_types, k, data.size(), subs.size(), keys.size(), m_script_ctx)); | 
| 745 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE8CalcTypeEvUnexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE8CalcTypeEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE8CalcTypeEvUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE8CalcTypeEv | 
| 746 |  |  | 
| 747 |  | public: | 
| 748 |  |     template<typename Ctx> | 
| 749 |  |     CScript ToScript(const Ctx& ctx) const | 
| 750 | 0 |     { | 
| 751 |  |         // To construct the CScript for a Miniscript object, we use the TreeEval algorithm. | 
| 752 |  |         // The State is a boolean: whether or not the node's script expansion is followed | 
| 753 |  |         // by an OP_VERIFY (which may need to be combined with the last script opcode). | 
| 754 | 0 |         auto downfn = [](bool verify, const Node& node, size_t index) { | 
| 755 |  |             // For WRAP_V, the subexpression is certainly followed by OP_VERIFY. | 
| 756 | 0 |             if (node.fragment == Fragment::WRAP_V) return true; | 
| 757 |  |             // The subexpression of WRAP_S, and the last subexpression of AND_V | 
| 758 |  |             // inherit the followed-by-OP_VERIFY property from the parent. | 
| 759 | 0 |             if (node.fragment == Fragment::WRAP_S || | 
| 760 | 0 |                 (node.fragment == Fragment::AND_V && index == 1)) return verify; | 
| 761 | 0 |             return false; | 
| 762 | 0 |         }; Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8ToScriptIN12_GLOBAL__N_113ParserContextEEE7CScriptRKT_ENKUlbRKS2_mE_clEbSB_mUnexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE8ToScriptIS2_EE7CScriptRKT_ENKUlbRKS4_mE_clEbSB_mUnexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE8ToScriptIN12_GLOBAL__N_111ScriptMakerEEE7CScriptRKT_ENKUlbRKS1_mE_clEbSA_m | 
| 763 |  |         // The upward function computes for a node, given its followed-by-OP_VERIFY status | 
| 764 |  |         // and the CScripts of its child nodes, the CScript of the node. | 
| 765 | 0 |         const bool is_tapscript{IsTapscript(m_script_ctx)}; | 
| 766 | 0 |         auto upfn = [&ctx, is_tapscript](bool verify, const Node& node, std::span<CScript> subs) -> CScript { | 
| 767 | 0 |             switch (node.fragment) { | 
| 768 | 0 |                 case Fragment::PK_K: return BuildScript(ctx.ToPKBytes(node.keys[0])); | 
| 769 | 0 |                 case Fragment::PK_H: return BuildScript(OP_DUP, OP_HASH160, ctx.ToPKHBytes(node.keys[0]), OP_EQUALVERIFY); | 
| 770 | 0 |                 case Fragment::OLDER: return BuildScript(node.k, OP_CHECKSEQUENCEVERIFY); | 
| 771 | 0 |                 case Fragment::AFTER: return BuildScript(node.k, OP_CHECKLOCKTIMEVERIFY); | 
| 772 | 0 |                 case Fragment::SHA256: return BuildScript(OP_SIZE, 32, OP_EQUALVERIFY, OP_SHA256, node.data, verify ? OP_EQUALVERIFY : OP_EQUAL); | 
| 773 | 0 |                 case Fragment::RIPEMD160: return BuildScript(OP_SIZE, 32, OP_EQUALVERIFY, OP_RIPEMD160, node.data, verify ? OP_EQUALVERIFY : OP_EQUAL); | 
| 774 | 0 |                 case Fragment::HASH256: return BuildScript(OP_SIZE, 32, OP_EQUALVERIFY, OP_HASH256, node.data, verify ? OP_EQUALVERIFY : OP_EQUAL); | 
| 775 | 0 |                 case Fragment::HASH160: return BuildScript(OP_SIZE, 32, OP_EQUALVERIFY, OP_HASH160, node.data, verify ? OP_EQUALVERIFY : OP_EQUAL); | 
| 776 | 0 |                 case Fragment::WRAP_A: return BuildScript(OP_TOALTSTACK, subs[0], OP_FROMALTSTACK); | 
| 777 | 0 |                 case Fragment::WRAP_S: return BuildScript(OP_SWAP, subs[0]); | 
| 778 | 0 |                 case Fragment::WRAP_C: return BuildScript(std::move(subs[0]), verify ? OP_CHECKSIGVERIFY : OP_CHECKSIG); | 
| 779 | 0 |                 case Fragment::WRAP_D: return BuildScript(OP_DUP, OP_IF, subs[0], OP_ENDIF); | 
| 780 | 0 |                 case Fragment::WRAP_V: { | 
| 781 | 0 |                     if (node.subs[0]->GetType() << "x"_mst) { | 
| 782 | 0 |                         return BuildScript(std::move(subs[0]), OP_VERIFY); | 
| 783 | 0 |                     } else { | 
| 784 | 0 |                         return std::move(subs[0]); | 
| 785 | 0 |                     } | 
| 786 | 0 |                 } | 
| 787 | 0 |                 case Fragment::WRAP_J: return BuildScript(OP_SIZE, OP_0NOTEQUAL, OP_IF, subs[0], OP_ENDIF); | 
| 788 | 0 |                 case Fragment::WRAP_N: return BuildScript(std::move(subs[0]), OP_0NOTEQUAL); | 
| 789 | 0 |                 case Fragment::JUST_1: return BuildScript(OP_1); | 
| 790 | 0 |                 case Fragment::JUST_0: return BuildScript(OP_0); | 
| 791 | 0 |                 case Fragment::AND_V: return BuildScript(std::move(subs[0]), subs[1]); | 
| 792 | 0 |                 case Fragment::AND_B: return BuildScript(std::move(subs[0]), subs[1], OP_BOOLAND); | 
| 793 | 0 |                 case Fragment::OR_B: return BuildScript(std::move(subs[0]), subs[1], OP_BOOLOR); | 
| 794 | 0 |                 case Fragment::OR_D: return BuildScript(std::move(subs[0]), OP_IFDUP, OP_NOTIF, subs[1], OP_ENDIF); | 
| 795 | 0 |                 case Fragment::OR_C: return BuildScript(std::move(subs[0]), OP_NOTIF, subs[1], OP_ENDIF); | 
| 796 | 0 |                 case Fragment::OR_I: return BuildScript(OP_IF, subs[0], OP_ELSE, subs[1], OP_ENDIF); | 
| 797 | 0 |                 case Fragment::ANDOR: return BuildScript(std::move(subs[0]), OP_NOTIF, subs[2], OP_ELSE, subs[1], OP_ENDIF); | 
| 798 | 0 |                 case Fragment::MULTI: { | 
| 799 | 0 |                     CHECK_NONFATAL(!is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(!is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(!is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 800 | 0 |                     CScript script = BuildScript(node.k); | 
| 801 | 0 |                     for (const auto& key : node.keys) { | 
| 802 | 0 |                         script = BuildScript(std::move(script), ctx.ToPKBytes(key)); | 
| 803 | 0 |                     } | 
| 804 | 0 |                     return BuildScript(std::move(script), node.keys.size(), verify ? OP_CHECKMULTISIGVERIFY : OP_CHECKMULTISIG); | 
| 805 | 0 |                 } | 
| 806 | 0 |                 case Fragment::MULTI_A: { | 
| 807 | 0 |                     CHECK_NONFATAL(is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 808 | 0 |                     CScript script = BuildScript(ctx.ToPKBytes(*node.keys.begin()), OP_CHECKSIG); | 
| 809 | 0 |                     for (auto it = node.keys.begin() + 1; it != node.keys.end(); ++it) { | 
| 810 | 0 |                         script = BuildScript(std::move(script), ctx.ToPKBytes(*it), OP_CHECKSIGADD); | 
| 811 | 0 |                     } | 
| 812 | 0 |                     return BuildScript(std::move(script), node.k, verify ? OP_NUMEQUALVERIFY : OP_NUMEQUAL); | 
| 813 | 0 |                 } | 
| 814 | 0 |                 case Fragment::THRESH: { | 
| 815 | 0 |                     CScript script = std::move(subs[0]); | 
| 816 | 0 |                     for (size_t i = 1; i < subs.size(); ++i) { | 
| 817 | 0 |                         script = BuildScript(std::move(script), subs[i], OP_ADD); | 
| 818 | 0 |                     } | 
| 819 | 0 |                     return BuildScript(std::move(script), node.k, verify ? OP_EQUALVERIFY : OP_EQUAL); | 
| 820 | 0 |                 } | 
| 821 | 0 |             } | 
| 822 | 0 |             assert(false); | 
| 823 | 0 |         }; Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8ToScriptIN12_GLOBAL__N_113ParserContextEEE7CScriptRKT_ENKUlbRKS2_NSt3__14spanIS6_Lm18446744073709551615EEEE_clEbSB_SE_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE8ToScriptIS2_EE7CScriptRKT_ENKUlbRKS4_NSt3__14spanIS6_Lm18446744073709551615EEEE_clEbSB_SE_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE8ToScriptIN12_GLOBAL__N_111ScriptMakerEEE7CScriptRKT_ENKUlbRKS1_NSt3__14spanIS5_Lm18446744073709551615EEEE_clEbSA_SD_ | 
| 824 | 0 |         return TreeEval<CScript>(false, downfn, upfn); | 
| 825 | 0 |     } Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE8ToScriptIN12_GLOBAL__N_113ParserContextEEE7CScriptRKT_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE8ToScriptIS2_EE7CScriptRKT_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE8ToScriptIN12_GLOBAL__N_111ScriptMakerEEE7CScriptRKT_ | 
| 826 |  |  | 
| 827 |  |     template<typename CTx> | 
| 828 | 0 |     std::optional<std::string> ToString(const CTx& ctx) const { | 
| 829 |  |         // To construct the std::string representation for a Miniscript object, we use | 
| 830 |  |         // the TreeEvalMaybe algorithm. The State is a boolean: whether the parent node is a | 
| 831 |  |         // wrapper. If so, non-wrapper expressions must be prefixed with a ":". | 
| 832 | 0 |         auto downfn = [](bool, const Node& node, size_t) { | 
| 833 | 0 |             return (node.fragment == Fragment::WRAP_A || node.fragment == Fragment::WRAP_S || | 
| 834 | 0 |                     node.fragment == Fragment::WRAP_D || node.fragment == Fragment::WRAP_V || | 
| 835 | 0 |                     node.fragment == Fragment::WRAP_J || node.fragment == Fragment::WRAP_N || | 
| 836 | 0 |                     node.fragment == Fragment::WRAP_C || | 
| 837 | 0 |                     (node.fragment == Fragment::AND_V && node.subs[1]->fragment == Fragment::JUST_1) || | 
| 838 | 0 |                     (node.fragment == Fragment::OR_I && node.subs[0]->fragment == Fragment::JUST_0) || | 
| 839 | 0 |                     (node.fragment == Fragment::OR_I && node.subs[1]->fragment == Fragment::JUST_0)); | 
| 840 | 0 |         }; Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8ToStringIN12_GLOBAL__N_113ParserContextEEENSt3__18optionalINS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERKT_ENKUlbRKS2_mE_clEbSJ_mUnexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE8ToStringIN12_GLOBAL__N_19KeyParserEEENSt3__18optionalINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEERKT_ENKUlbRKS1_mE_clEbSI_mUnexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE8ToStringIN12_GLOBAL__N_111StringMakerEEENSt3__18optionalINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEERKT_ENKUlbRKS1_mE_clEbSI_m | 
| 841 |  |         // The upward function computes for a node, given whether its parent is a wrapper, | 
| 842 |  |         // and the string representations of its child nodes, the string representation of the node. | 
| 843 | 0 |         const bool is_tapscript{IsTapscript(m_script_ctx)}; | 
| 844 | 0 |         auto upfn = [&ctx, is_tapscript](bool wrapped, const Node& node, std::span<std::string> subs) -> std::optional<std::string> { | 
| 845 | 0 |             std::string ret = wrapped ? ":" : ""; | 
| 846 |  | 
 | 
| 847 | 0 |             switch (node.fragment) { | 
| 848 | 0 |                 case Fragment::WRAP_A: return "a" + std::move(subs[0]); | 
| 849 | 0 |                 case Fragment::WRAP_S: return "s" + std::move(subs[0]); | 
| 850 | 0 |                 case Fragment::WRAP_C: | 
| 851 | 0 |                     if (node.subs[0]->fragment == Fragment::PK_K) { | 
| 852 |  |                         // pk(K) is syntactic sugar for c:pk_k(K) | 
| 853 | 0 |                         auto key_str = ctx.ToString(node.subs[0]->keys[0]); | 
| 854 | 0 |                         if (!key_str) return {}; | 
| 855 | 0 |                         return std::move(ret) + "pk(" + std::move(*key_str) + ")"; | 
| 856 | 0 |                     } | 
| 857 | 0 |                     if (node.subs[0]->fragment == Fragment::PK_H) { | 
| 858 |  |                         // pkh(K) is syntactic sugar for c:pk_h(K) | 
| 859 | 0 |                         auto key_str = ctx.ToString(node.subs[0]->keys[0]); | 
| 860 | 0 |                         if (!key_str) return {}; | 
| 861 | 0 |                         return std::move(ret) + "pkh(" + std::move(*key_str) + ")"; | 
| 862 | 0 |                     } | 
| 863 | 0 |                     return "c" + std::move(subs[0]); | 
| 864 | 0 |                 case Fragment::WRAP_D: return "d" + std::move(subs[0]); | 
| 865 | 0 |                 case Fragment::WRAP_V: return "v" + std::move(subs[0]); | 
| 866 | 0 |                 case Fragment::WRAP_J: return "j" + std::move(subs[0]); | 
| 867 | 0 |                 case Fragment::WRAP_N: return "n" + std::move(subs[0]); | 
| 868 | 0 |                 case Fragment::AND_V: | 
| 869 |  |                     // t:X is syntactic sugar for and_v(X,1). | 
| 870 | 0 |                     if (node.subs[1]->fragment == Fragment::JUST_1) return "t" + std::move(subs[0]); | 
| 871 | 0 |                     break; | 
| 872 | 0 |                 case Fragment::OR_I: | 
| 873 | 0 |                     if (node.subs[0]->fragment == Fragment::JUST_0) return "l" + std::move(subs[1]); | 
| 874 | 0 |                     if (node.subs[1]->fragment == Fragment::JUST_0) return "u" + std::move(subs[0]); | 
| 875 | 0 |                     break; | 
| 876 | 0 |                 default: break; | 
| 877 | 0 |             } | 
| 878 | 0 |             switch (node.fragment) { | 
| 879 | 0 |                 case Fragment::PK_K: { | 
| 880 | 0 |                     auto key_str = ctx.ToString(node.keys[0]); | 
| 881 | 0 |                     if (!key_str) return {}; | 
| 882 | 0 |                     return std::move(ret) + "pk_k(" + std::move(*key_str) + ")"; | 
| 883 | 0 |                 } | 
| 884 | 0 |                 case Fragment::PK_H: { | 
| 885 | 0 |                     auto key_str = ctx.ToString(node.keys[0]); | 
| 886 | 0 |                     if (!key_str) return {}; | 
| 887 | 0 |                     return std::move(ret) + "pk_h(" + std::move(*key_str) + ")"; | 
| 888 | 0 |                 } | 
| 889 | 0 |                 case Fragment::AFTER: return std::move(ret) + "after(" + util::ToString(node.k) + ")"; | 
| 890 | 0 |                 case Fragment::OLDER: return std::move(ret) + "older(" + util::ToString(node.k) + ")"; | 
| 891 | 0 |                 case Fragment::HASH256: return std::move(ret) + "hash256(" + HexStr(node.data) + ")"; | 
| 892 | 0 |                 case Fragment::HASH160: return std::move(ret) + "hash160(" + HexStr(node.data) + ")"; | 
| 893 | 0 |                 case Fragment::SHA256: return std::move(ret) + "sha256(" + HexStr(node.data) + ")"; | 
| 894 | 0 |                 case Fragment::RIPEMD160: return std::move(ret) + "ripemd160(" + HexStr(node.data) + ")"; | 
| 895 | 0 |                 case Fragment::JUST_1: return std::move(ret) + "1"; | 
| 896 | 0 |                 case Fragment::JUST_0: return std::move(ret) + "0"; | 
| 897 | 0 |                 case Fragment::AND_V: return std::move(ret) + "and_v(" + std::move(subs[0]) + "," + std::move(subs[1]) + ")"; | 
| 898 | 0 |                 case Fragment::AND_B: return std::move(ret) + "and_b(" + std::move(subs[0]) + "," + std::move(subs[1]) + ")"; | 
| 899 | 0 |                 case Fragment::OR_B: return std::move(ret) + "or_b(" + std::move(subs[0]) + "," + std::move(subs[1]) + ")"; | 
| 900 | 0 |                 case Fragment::OR_D: return std::move(ret) + "or_d(" + std::move(subs[0]) + "," + std::move(subs[1]) + ")"; | 
| 901 | 0 |                 case Fragment::OR_C: return std::move(ret) + "or_c(" + std::move(subs[0]) + "," + std::move(subs[1]) + ")"; | 
| 902 | 0 |                 case Fragment::OR_I: return std::move(ret) + "or_i(" + std::move(subs[0]) + "," + std::move(subs[1]) + ")"; | 
| 903 | 0 |                 case Fragment::ANDOR: | 
| 904 |  |                     // and_n(X,Y) is syntactic sugar for andor(X,Y,0). | 
| 905 | 0 |                     if (node.subs[2]->fragment == Fragment::JUST_0) return std::move(ret) + "and_n(" + std::move(subs[0]) + "," + std::move(subs[1]) + ")"; | 
| 906 | 0 |                     return std::move(ret) + "andor(" + std::move(subs[0]) + "," + std::move(subs[1]) + "," + std::move(subs[2]) + ")"; | 
| 907 | 0 |                 case Fragment::MULTI: { | 
| 908 | 0 |                     CHECK_NONFATAL(!is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(!is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(!is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 909 | 0 |                     auto str = std::move(ret) + "multi(" + util::ToString(node.k); | 
| 910 | 0 |                     for (const auto& key : node.keys) { | 
| 911 | 0 |                         auto key_str = ctx.ToString(key); | 
| 912 | 0 |                         if (!key_str) return {}; | 
| 913 | 0 |                         str += "," + std::move(*key_str); | 
| 914 | 0 |                     } | 
| 915 | 0 |                     return std::move(str) + ")"; | 
| 916 | 0 |                 } | 
| 917 | 0 |                 case Fragment::MULTI_A: { | 
| 918 | 0 |                     CHECK_NONFATAL(is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(is_tapscript); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 919 | 0 |                     auto str = std::move(ret) + "multi_a(" + util::ToString(node.k); | 
| 920 | 0 |                     for (const auto& key : node.keys) { | 
| 921 | 0 |                         auto key_str = ctx.ToString(key); | 
| 922 | 0 |                         if (!key_str) return {}; | 
| 923 | 0 |                         str += "," + std::move(*key_str); | 
| 924 | 0 |                     } | 
| 925 | 0 |                     return std::move(str) + ")"; | 
| 926 | 0 |                 } | 
| 927 | 0 |                 case Fragment::THRESH: { | 
| 928 | 0 |                     auto str = std::move(ret) + "thresh(" + util::ToString(node.k); | 
| 929 | 0 |                     for (auto& sub : subs) { | 
| 930 | 0 |                         str += "," + std::move(sub); | 
| 931 | 0 |                     } | 
| 932 | 0 |                     return std::move(str) + ")"; | 
| 933 | 0 |                 } | 
| 934 | 0 |                 default: break; | 
| 935 | 0 |             } | 
| 936 | 0 |             assert(false); | 
| 937 | 0 |         }; Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE8ToStringIN12_GLOBAL__N_113ParserContextEEENSt3__18optionalINS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERKT_ENKUlbRKS2_NS6_4spanISD_Lm18446744073709551615EEEE_clEbSJ_SL_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE8ToStringIN12_GLOBAL__N_19KeyParserEEENSt3__18optionalINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEERKT_ENKUlbRKS1_NS5_4spanISC_Lm18446744073709551615EEEE_clEbSI_SK_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE8ToStringIN12_GLOBAL__N_111StringMakerEEENSt3__18optionalINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEERKT_ENKUlbRKS1_NS5_4spanISC_Lm18446744073709551615EEEE_clEbSI_SK_ | 
| 938 |  | 
 | 
| 939 | 0 |         return TreeEvalMaybe<std::string>(false, downfn, upfn); | 
| 940 | 0 |     } Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE8ToStringIN12_GLOBAL__N_113ParserContextEEENSt3__18optionalINS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEERKT_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE8ToStringIN12_GLOBAL__N_19KeyParserEEENSt3__18optionalINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEERKT_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE8ToStringIN12_GLOBAL__N_111StringMakerEEENSt3__18optionalINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEERKT_ | 
| 941 |  |  | 
| 942 |  | private: | 
| 943 | 0 |     internal::Ops CalcOps() const { | 
| 944 | 0 |         switch (fragment) { | 
| 945 | 0 |             case Fragment::JUST_1: return {0, 0, {}}; | 
| 946 | 0 |             case Fragment::JUST_0: return {0, {}, 0}; | 
| 947 | 0 |             case Fragment::PK_K: return {0, 0, 0}; | 
| 948 | 0 |             case Fragment::PK_H: return {3, 0, 0}; | 
| 949 | 0 |             case Fragment::OLDER: | 
| 950 | 0 |             case Fragment::AFTER: return {1, 0, {}}; | 
| 951 | 0 |             case Fragment::SHA256: | 
| 952 | 0 |             case Fragment::RIPEMD160: | 
| 953 | 0 |             case Fragment::HASH256: | 
| 954 | 0 |             case Fragment::HASH160: return {4, 0, {}}; | 
| 955 | 0 |             case Fragment::AND_V: return {subs[0]->ops.count + subs[1]->ops.count, subs[0]->ops.sat + subs[1]->ops.sat, {}}; | 
| 956 | 0 |             case Fragment::AND_B: { | 
| 957 | 0 |                 const auto count{1 + subs[0]->ops.count + subs[1]->ops.count}; | 
| 958 | 0 |                 const auto sat{subs[0]->ops.sat + subs[1]->ops.sat}; | 
| 959 | 0 |                 const auto dsat{subs[0]->ops.dsat + subs[1]->ops.dsat}; | 
| 960 | 0 |                 return {count, sat, dsat}; | 
| 961 | 0 |             } | 
| 962 | 0 |             case Fragment::OR_B: { | 
| 963 | 0 |                 const auto count{1 + subs[0]->ops.count + subs[1]->ops.count}; | 
| 964 | 0 |                 const auto sat{(subs[0]->ops.sat + subs[1]->ops.dsat) | (subs[1]->ops.sat + subs[0]->ops.dsat)}; | 
| 965 | 0 |                 const auto dsat{subs[0]->ops.dsat + subs[1]->ops.dsat}; | 
| 966 | 0 |                 return {count, sat, dsat}; | 
| 967 | 0 |             } | 
| 968 | 0 |             case Fragment::OR_D: { | 
| 969 | 0 |                 const auto count{3 + subs[0]->ops.count + subs[1]->ops.count}; | 
| 970 | 0 |                 const auto sat{subs[0]->ops.sat | (subs[1]->ops.sat + subs[0]->ops.dsat)}; | 
| 971 | 0 |                 const auto dsat{subs[0]->ops.dsat + subs[1]->ops.dsat}; | 
| 972 | 0 |                 return {count, sat, dsat}; | 
| 973 | 0 |             } | 
| 974 | 0 |             case Fragment::OR_C: { | 
| 975 | 0 |                 const auto count{2 + subs[0]->ops.count + subs[1]->ops.count}; | 
| 976 | 0 |                 const auto sat{subs[0]->ops.sat | (subs[1]->ops.sat + subs[0]->ops.dsat)}; | 
| 977 | 0 |                 return {count, sat, {}}; | 
| 978 | 0 |             } | 
| 979 | 0 |             case Fragment::OR_I: { | 
| 980 | 0 |                 const auto count{3 + subs[0]->ops.count + subs[1]->ops.count}; | 
| 981 | 0 |                 const auto sat{subs[0]->ops.sat | subs[1]->ops.sat}; | 
| 982 | 0 |                 const auto dsat{subs[0]->ops.dsat | subs[1]->ops.dsat}; | 
| 983 | 0 |                 return {count, sat, dsat}; | 
| 984 | 0 |             } | 
| 985 | 0 |             case Fragment::ANDOR: { | 
| 986 | 0 |                 const auto count{3 + subs[0]->ops.count + subs[1]->ops.count + subs[2]->ops.count}; | 
| 987 | 0 |                 const auto sat{(subs[1]->ops.sat + subs[0]->ops.sat) | (subs[0]->ops.dsat + subs[2]->ops.sat)}; | 
| 988 | 0 |                 const auto dsat{subs[0]->ops.dsat + subs[2]->ops.dsat}; | 
| 989 | 0 |                 return {count, sat, dsat}; | 
| 990 | 0 |             } | 
| 991 | 0 |             case Fragment::MULTI: return {1, (uint32_t)keys.size(), (uint32_t)keys.size()}; | 
| 992 | 0 |             case Fragment::MULTI_A: return {(uint32_t)keys.size() + 1, 0, 0}; | 
| 993 | 0 |             case Fragment::WRAP_S: | 
| 994 | 0 |             case Fragment::WRAP_C: | 
| 995 | 0 |             case Fragment::WRAP_N: return {1 + subs[0]->ops.count, subs[0]->ops.sat, subs[0]->ops.dsat}; | 
| 996 | 0 |             case Fragment::WRAP_A: return {2 + subs[0]->ops.count, subs[0]->ops.sat, subs[0]->ops.dsat}; | 
| 997 | 0 |             case Fragment::WRAP_D: return {3 + subs[0]->ops.count, subs[0]->ops.sat, 0}; | 
| 998 | 0 |             case Fragment::WRAP_J: return {4 + subs[0]->ops.count, subs[0]->ops.sat, 0}; | 
| 999 | 0 |             case Fragment::WRAP_V: return {subs[0]->ops.count + (subs[0]->GetType() << "x"_mst), subs[0]->ops.sat, {}}; | 
| 1000 | 0 |             case Fragment::THRESH: { | 
| 1001 | 0 |                 uint32_t count = 0; | 
| 1002 | 0 |                 auto sats = Vector(internal::MaxInt<uint32_t>(0)); | 
| 1003 | 0 |                 for (const auto& sub : subs) { | 
| 1004 | 0 |                     count += sub->ops.count + 1; | 
| 1005 | 0 |                     auto next_sats = Vector(sats[0] + sub->ops.dsat); | 
| 1006 | 0 |                     for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + sub->ops.dsat) | (sats[j - 1] + sub->ops.sat)); | 
| 1007 | 0 |                     next_sats.push_back(sats[sats.size() - 1] + sub->ops.sat); | 
| 1008 | 0 |                     sats = std::move(next_sats); | 
| 1009 | 0 |                 } | 
| 1010 | 0 |                 assert(k < sats.size()); | 
| 1011 | 0 |                 return {count, sats[k], sats[0]}; | 
| 1012 | 0 |             } | 
| 1013 | 0 |         } | 
| 1014 | 0 |         assert(false); | 
| 1015 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE7CalcOpsEvUnexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE7CalcOpsEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE7CalcOpsEvUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE7CalcOpsEv | 
| 1016 |  |  | 
| 1017 | 0 |     internal::StackSize CalcStackSize() const { | 
| 1018 | 0 |         using namespace internal; | 
| 1019 | 0 |         switch (fragment) { | 
| 1020 | 0 |             case Fragment::JUST_0: return {{}, SatInfo::Push()}; | 
| 1021 | 0 |             case Fragment::JUST_1: return {SatInfo::Push(), {}}; | 
| 1022 | 0 |             case Fragment::OLDER: | 
| 1023 | 0 |             case Fragment::AFTER: return {SatInfo::Push() + SatInfo::Nop(), {}}; | 
| 1024 | 0 |             case Fragment::PK_K: return {SatInfo::Push()}; | 
| 1025 | 0 |             case Fragment::PK_H: return {SatInfo::OP_DUP() + SatInfo::Hash() + SatInfo::Push() + SatInfo::OP_EQUALVERIFY()}; | 
| 1026 | 0 |             case Fragment::SHA256: | 
| 1027 | 0 |             case Fragment::RIPEMD160: | 
| 1028 | 0 |             case Fragment::HASH256: | 
| 1029 | 0 |             case Fragment::HASH160: return { | 
| 1030 | 0 |                 SatInfo::OP_SIZE() + SatInfo::Push() + SatInfo::OP_EQUALVERIFY() + SatInfo::Hash() + SatInfo::Push() + SatInfo::OP_EQUAL(), | 
| 1031 | 0 |                 {} | 
| 1032 | 0 |             }; | 
| 1033 | 0 |             case Fragment::ANDOR: { | 
| 1034 | 0 |                 const auto& x{subs[0]->ss}; | 
| 1035 | 0 |                 const auto& y{subs[1]->ss}; | 
| 1036 | 0 |                 const auto& z{subs[2]->ss}; | 
| 1037 | 0 |                 return { | 
| 1038 | 0 |                     (x.sat + SatInfo::If() + y.sat) | (x.dsat + SatInfo::If() + z.sat), | 
| 1039 | 0 |                     x.dsat + SatInfo::If() + z.dsat | 
| 1040 | 0 |                 }; | 
| 1041 | 0 |             } | 
| 1042 | 0 |             case Fragment::AND_V: { | 
| 1043 | 0 |                 const auto& x{subs[0]->ss}; | 
| 1044 | 0 |                 const auto& y{subs[1]->ss}; | 
| 1045 | 0 |                 return {x.sat + y.sat, {}}; | 
| 1046 | 0 |             } | 
| 1047 | 0 |             case Fragment::AND_B: { | 
| 1048 | 0 |                 const auto& x{subs[0]->ss}; | 
| 1049 | 0 |                 const auto& y{subs[1]->ss}; | 
| 1050 | 0 |                 return {x.sat + y.sat + SatInfo::BinaryOp(), x.dsat + y.dsat + SatInfo::BinaryOp()}; | 
| 1051 | 0 |             } | 
| 1052 | 0 |             case Fragment::OR_B: { | 
| 1053 | 0 |                 const auto& x{subs[0]->ss}; | 
| 1054 | 0 |                 const auto& y{subs[1]->ss}; | 
| 1055 | 0 |                 return { | 
| 1056 | 0 |                     ((x.sat + y.dsat) | (x.dsat + y.sat)) + SatInfo::BinaryOp(), | 
| 1057 | 0 |                     x.dsat + y.dsat + SatInfo::BinaryOp() | 
| 1058 | 0 |                 }; | 
| 1059 | 0 |             } | 
| 1060 | 0 |             case Fragment::OR_C: { | 
| 1061 | 0 |                 const auto& x{subs[0]->ss}; | 
| 1062 | 0 |                 const auto& y{subs[1]->ss}; | 
| 1063 | 0 |                 return {(x.sat + SatInfo::If()) | (x.dsat + SatInfo::If() + y.sat), {}}; | 
| 1064 | 0 |             } | 
| 1065 | 0 |             case Fragment::OR_D: { | 
| 1066 | 0 |                 const auto& x{subs[0]->ss}; | 
| 1067 | 0 |                 const auto& y{subs[1]->ss}; | 
| 1068 | 0 |                 return { | 
| 1069 | 0 |                     (x.sat + SatInfo::OP_IFDUP(true) + SatInfo::If()) | (x.dsat + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.sat), | 
| 1070 | 0 |                     x.dsat + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.dsat | 
| 1071 | 0 |                 }; | 
| 1072 | 0 |             } | 
| 1073 | 0 |             case Fragment::OR_I: { | 
| 1074 | 0 |                 const auto& x{subs[0]->ss}; | 
| 1075 | 0 |                 const auto& y{subs[1]->ss}; | 
| 1076 | 0 |                 return {SatInfo::If() + (x.sat | y.sat), SatInfo::If() + (x.dsat | y.dsat)}; | 
| 1077 | 0 |             } | 
| 1078 |  |             // multi(k, key1, key2, ..., key_n) starts off with k+1 stack elements (a 0, plus k | 
| 1079 |  |             // signatures), then reaches n+k+3 stack elements after pushing the n keys, plus k and | 
| 1080 |  |             // n itself, and ends with 1 stack element (success or failure). Thus, it net removes | 
| 1081 |  |             // k elements (from k+1 to 1), while reaching k+n+2 more than it ends with. | 
| 1082 | 0 |             case Fragment::MULTI: return {SatInfo(k, k + keys.size() + 2)}; | 
| 1083 |  |             // multi_a(k, key1, key2, ..., key_n) starts off with n stack elements (the | 
| 1084 |  |             // signatures), reaches 1 more (after the first key push), and ends with 1. Thus it net | 
| 1085 |  |             // removes n-1 elements (from n to 1) while reaching n more than it ends with. | 
| 1086 | 0 |             case Fragment::MULTI_A: return {SatInfo(keys.size() - 1, keys.size())}; | 
| 1087 | 0 |             case Fragment::WRAP_A: | 
| 1088 | 0 |             case Fragment::WRAP_N: | 
| 1089 | 0 |             case Fragment::WRAP_S: return subs[0]->ss; | 
| 1090 | 0 |             case Fragment::WRAP_C: return { | 
| 1091 | 0 |                 subs[0]->ss.sat + SatInfo::OP_CHECKSIG(), | 
| 1092 | 0 |                 subs[0]->ss.dsat + SatInfo::OP_CHECKSIG() | 
| 1093 | 0 |             }; | 
| 1094 | 0 |             case Fragment::WRAP_D: return { | 
| 1095 | 0 |                 SatInfo::OP_DUP() + SatInfo::If() + subs[0]->ss.sat, | 
| 1096 | 0 |                 SatInfo::OP_DUP() + SatInfo::If() | 
| 1097 | 0 |             }; | 
| 1098 | 0 |             case Fragment::WRAP_V: return {subs[0]->ss.sat + SatInfo::OP_VERIFY(), {}}; | 
| 1099 | 0 |             case Fragment::WRAP_J: return { | 
| 1100 | 0 |                 SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If() + subs[0]->ss.sat, | 
| 1101 | 0 |                 SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If() | 
| 1102 | 0 |             }; | 
| 1103 | 0 |             case Fragment::THRESH: { | 
| 1104 |  |                 // sats[j] is the SatInfo corresponding to all traces reaching j satisfactions. | 
| 1105 | 0 |                 auto sats = Vector(SatInfo::Empty()); | 
| 1106 | 0 |                 for (size_t i = 0; i < subs.size(); ++i) { | 
| 1107 |  |                     // Loop over the subexpressions, processing them one by one. After adding | 
| 1108 |  |                     // element i we need to add OP_ADD (if i>0). | 
| 1109 | 0 |                     auto add = i ? SatInfo::BinaryOp() : SatInfo::Empty(); | 
| 1110 |  |                     // Construct a variable that will become the next sats, starting with index 0. | 
| 1111 | 0 |                     auto next_sats = Vector(sats[0] + subs[i]->ss.dsat + add); | 
| 1112 |  |                     // Then loop to construct next_sats[1..i]. | 
| 1113 | 0 |                     for (size_t j = 1; j < sats.size(); ++j) { | 
| 1114 | 0 |                         next_sats.push_back(((sats[j] + subs[i]->ss.dsat) | (sats[j - 1] + subs[i]->ss.sat)) + add); | 
| 1115 | 0 |                     } | 
| 1116 |  |                     // Finally construct next_sats[i+1]. | 
| 1117 | 0 |                     next_sats.push_back(sats[sats.size() - 1] + subs[i]->ss.sat + add); | 
| 1118 |  |                     // Switch over. | 
| 1119 | 0 |                     sats = std::move(next_sats); | 
| 1120 | 0 |                 } | 
| 1121 |  |                 // To satisfy thresh we need k satisfactions; to dissatisfy we need 0. In both | 
| 1122 |  |                 // cases a push of k and an OP_EQUAL follow. | 
| 1123 | 0 |                 return { | 
| 1124 | 0 |                     sats[k] + SatInfo::Push() + SatInfo::OP_EQUAL(), | 
| 1125 | 0 |                     sats[0] + SatInfo::Push() + SatInfo::OP_EQUAL() | 
| 1126 | 0 |                 }; | 
| 1127 | 0 |             } | 
| 1128 | 0 |         } | 
| 1129 | 0 |         assert(false); | 
| 1130 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE13CalcStackSizeEvUnexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE13CalcStackSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE13CalcStackSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE13CalcStackSizeEv | 
| 1131 |  |  | 
| 1132 | 0 |     internal::WitnessSize CalcWitnessSize() const { | 
| 1133 | 0 |         const uint32_t sig_size = IsTapscript(m_script_ctx) ? 1 + 65 : 1 + 72; | 
| 1134 | 0 |         const uint32_t pubkey_size = IsTapscript(m_script_ctx) ? 1 + 32 : 1 + 33; | 
| 1135 | 0 |         switch (fragment) { | 
| 1136 | 0 |             case Fragment::JUST_0: return {{}, 0}; | 
| 1137 | 0 |             case Fragment::JUST_1: | 
| 1138 | 0 |             case Fragment::OLDER: | 
| 1139 | 0 |             case Fragment::AFTER: return {0, {}}; | 
| 1140 | 0 |             case Fragment::PK_K: return {sig_size, 1}; | 
| 1141 | 0 |             case Fragment::PK_H: return {sig_size + pubkey_size, 1 + pubkey_size}; | 
| 1142 | 0 |             case Fragment::SHA256: | 
| 1143 | 0 |             case Fragment::RIPEMD160: | 
| 1144 | 0 |             case Fragment::HASH256: | 
| 1145 | 0 |             case Fragment::HASH160: return {1 + 32, {}}; | 
| 1146 | 0 |             case Fragment::ANDOR: { | 
| 1147 | 0 |                 const auto sat{(subs[0]->ws.sat + subs[1]->ws.sat) | (subs[0]->ws.dsat + subs[2]->ws.sat)}; | 
| 1148 | 0 |                 const auto dsat{subs[0]->ws.dsat + subs[2]->ws.dsat}; | 
| 1149 | 0 |                 return {sat, dsat}; | 
| 1150 | 0 |             } | 
| 1151 | 0 |             case Fragment::AND_V: return {subs[0]->ws.sat + subs[1]->ws.sat, {}}; | 
| 1152 | 0 |             case Fragment::AND_B: return {subs[0]->ws.sat + subs[1]->ws.sat, subs[0]->ws.dsat + subs[1]->ws.dsat}; | 
| 1153 | 0 |             case Fragment::OR_B: { | 
| 1154 | 0 |                 const auto sat{(subs[0]->ws.dsat + subs[1]->ws.sat) | (subs[0]->ws.sat + subs[1]->ws.dsat)}; | 
| 1155 | 0 |                 const auto dsat{subs[0]->ws.dsat + subs[1]->ws.dsat}; | 
| 1156 | 0 |                 return {sat, dsat}; | 
| 1157 | 0 |             } | 
| 1158 | 0 |             case Fragment::OR_C: return {subs[0]->ws.sat | (subs[0]->ws.dsat + subs[1]->ws.sat), {}}; | 
| 1159 | 0 |             case Fragment::OR_D: return {subs[0]->ws.sat | (subs[0]->ws.dsat + subs[1]->ws.sat), subs[0]->ws.dsat + subs[1]->ws.dsat}; | 
| 1160 | 0 |             case Fragment::OR_I: return {(subs[0]->ws.sat + 1 + 1) | (subs[1]->ws.sat + 1), (subs[0]->ws.dsat + 1 + 1) | (subs[1]->ws.dsat + 1)}; | 
| 1161 | 0 |             case Fragment::MULTI: return {k * sig_size + 1, k + 1}; | 
| 1162 | 0 |             case Fragment::MULTI_A: return {k * sig_size + static_cast<uint32_t>(keys.size()) - k, static_cast<uint32_t>(keys.size())}; | 
| 1163 | 0 |             case Fragment::WRAP_A: | 
| 1164 | 0 |             case Fragment::WRAP_N: | 
| 1165 | 0 |             case Fragment::WRAP_S: | 
| 1166 | 0 |             case Fragment::WRAP_C: return subs[0]->ws; | 
| 1167 | 0 |             case Fragment::WRAP_D: return {1 + 1 + subs[0]->ws.sat, 1}; | 
| 1168 | 0 |             case Fragment::WRAP_V: return {subs[0]->ws.sat, {}}; | 
| 1169 | 0 |             case Fragment::WRAP_J: return {subs[0]->ws.sat, 1}; | 
| 1170 | 0 |             case Fragment::THRESH: { | 
| 1171 | 0 |                 auto sats = Vector(internal::MaxInt<uint32_t>(0)); | 
| 1172 | 0 |                 for (const auto& sub : subs) { | 
| 1173 | 0 |                     auto next_sats = Vector(sats[0] + sub->ws.dsat); | 
| 1174 | 0 |                     for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + sub->ws.dsat) | (sats[j - 1] + sub->ws.sat)); | 
| 1175 | 0 |                     next_sats.push_back(sats[sats.size() - 1] + sub->ws.sat); | 
| 1176 | 0 |                     sats = std::move(next_sats); | 
| 1177 | 0 |                 } | 
| 1178 | 0 |                 assert(k < sats.size()); | 
| 1179 | 0 |                 return {sats[k], sats[0]}; | 
| 1180 | 0 |             } | 
| 1181 | 0 |         } | 
| 1182 | 0 |         assert(false); | 
| 1183 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE15CalcWitnessSizeEvUnexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE15CalcWitnessSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE15CalcWitnessSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE15CalcWitnessSizeEv | 
| 1184 |  |  | 
| 1185 |  |     template<typename Ctx> | 
| 1186 | 0 |     internal::InputResult ProduceInput(const Ctx& ctx) const { | 
| 1187 | 0 |         using namespace internal; | 
| 1188 |  |  | 
| 1189 |  |         // Internal function which is invoked for every tree node, constructing satisfaction/dissatisfactions | 
| 1190 |  |         // given those of its subnodes. | 
| 1191 | 0 |         auto helper = [&ctx](const Node& node, std::span<InputResult> subres) -> InputResult { | 
| 1192 | 0 |             switch (node.fragment) { | 
| 1193 | 0 |                 case Fragment::PK_K: { | 
| 1194 | 0 |                     std::vector<unsigned char> sig; | 
| 1195 | 0 |                     Availability avail = ctx.Sign(node.keys[0], sig); | 
| 1196 | 0 |                     return {ZERO, InputStack(std::move(sig)).SetWithSig().SetAvailable(avail)}; | 
| 1197 | 0 |                 } | 
| 1198 | 0 |                 case Fragment::PK_H: { | 
| 1199 | 0 |                     std::vector<unsigned char> key = ctx.ToPKBytes(node.keys[0]), sig; | 
| 1200 | 0 |                     Availability avail = ctx.Sign(node.keys[0], sig); | 
| 1201 | 0 |                     return {ZERO + InputStack(key), (InputStack(std::move(sig)).SetWithSig() + InputStack(key)).SetAvailable(avail)}; | 
| 1202 | 0 |                 } | 
| 1203 | 0 |                 case Fragment::MULTI_A: { | 
| 1204 |  |                     // sats[j] represents the best stack containing j valid signatures (out of the first i keys). | 
| 1205 |  |                     // In the loop below, these stacks are built up using a dynamic programming approach. | 
| 1206 | 0 |                     std::vector<InputStack> sats = Vector(EMPTY); | 
| 1207 | 0 |                     for (size_t i = 0; i < node.keys.size(); ++i) { | 
| 1208 |  |                         // Get the signature for the i'th key in reverse order (the signature for the first key needs to | 
| 1209 |  |                         // be at the top of the stack, contrary to CHECKMULTISIG's satisfaction). | 
| 1210 | 0 |                         std::vector<unsigned char> sig; | 
| 1211 | 0 |                         Availability avail = ctx.Sign(node.keys[node.keys.size() - 1 - i], sig); | 
| 1212 |  |                         // Compute signature stack for just this key. | 
| 1213 | 0 |                         auto sat = InputStack(std::move(sig)).SetWithSig().SetAvailable(avail); | 
| 1214 |  |                         // Compute the next sats vector: next_sats[0] is a copy of sats[0] (no signatures). All further | 
| 1215 |  |                         // next_sats[j] are equal to either the existing sats[j] + ZERO, or sats[j-1] plus a signature | 
| 1216 |  |                         // for the current (i'th) key. The very last element needs all signatures filled. | 
| 1217 | 0 |                         std::vector<InputStack> next_sats; | 
| 1218 | 0 |                         next_sats.push_back(sats[0] + ZERO); | 
| 1219 | 0 |                         for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + ZERO) | (std::move(sats[j - 1]) + sat)); | 
| 1220 | 0 |                         next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(sat)); | 
| 1221 |  |                         // Switch over. | 
| 1222 | 0 |                         sats = std::move(next_sats); | 
| 1223 | 0 |                     } | 
| 1224 |  |                     // The dissatisfaction consists of as many empty vectors as there are keys, which is the same as | 
| 1225 |  |                     // satisfying 0 keys. | 
| 1226 | 0 |                     auto& nsat{sats[0]}; | 
| 1227 | 0 |                     CHECK_NONFATAL(node.k != 0); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(node.k != 0); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |                     CHECK_NONFATAL(node.k != 0); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1228 | 0 |                     assert(node.k < sats.size()); | 
| 1229 | 0 |                     return {std::move(nsat), std::move(sats[node.k])}; | 
| 1230 | 0 |                 } | 
| 1231 | 0 |                 case Fragment::MULTI: { | 
| 1232 |  |                     // sats[j] represents the best stack containing j valid signatures (out of the first i keys). | 
| 1233 |  |                     // In the loop below, these stacks are built up using a dynamic programming approach. | 
| 1234 |  |                     // sats[0] starts off being {0}, due to the CHECKMULTISIG bug that pops off one element too many. | 
| 1235 | 0 |                     std::vector<InputStack> sats = Vector(ZERO); | 
| 1236 | 0 |                     for (size_t i = 0; i < node.keys.size(); ++i) { | 
| 1237 | 0 |                         std::vector<unsigned char> sig; | 
| 1238 | 0 |                         Availability avail = ctx.Sign(node.keys[i], sig); | 
| 1239 |  |                         // Compute signature stack for just the i'th key. | 
| 1240 | 0 |                         auto sat = InputStack(std::move(sig)).SetWithSig().SetAvailable(avail); | 
| 1241 |  |                         // Compute the next sats vector: next_sats[0] is a copy of sats[0] (no signatures). All further | 
| 1242 |  |                         // next_sats[j] are equal to either the existing sats[j], or sats[j-1] plus a signature for the | 
| 1243 |  |                         // current (i'th) key. The very last element needs all signatures filled. | 
| 1244 | 0 |                         std::vector<InputStack> next_sats; | 
| 1245 | 0 |                         next_sats.push_back(sats[0]); | 
| 1246 | 0 |                         for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back(sats[j] | (std::move(sats[j - 1]) + sat)); | 
| 1247 | 0 |                         next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(sat)); | 
| 1248 |  |                         // Switch over. | 
| 1249 | 0 |                         sats = std::move(next_sats); | 
| 1250 | 0 |                     } | 
| 1251 |  |                     // The dissatisfaction consists of k+1 stack elements all equal to 0. | 
| 1252 | 0 |                     InputStack nsat = ZERO; | 
| 1253 | 0 |                     for (size_t i = 0; i < node.k; ++i) nsat = std::move(nsat) + ZERO; | 
| 1254 | 0 |                     assert(node.k < sats.size()); | 
| 1255 | 0 |                     return {std::move(nsat), std::move(sats[node.k])}; | 
| 1256 | 0 |                 } | 
| 1257 | 0 |                 case Fragment::THRESH: { | 
| 1258 |  |                     // sats[k] represents the best stack that satisfies k out of the *last* i subexpressions. | 
| 1259 |  |                     // In the loop below, these stacks are built up using a dynamic programming approach. | 
| 1260 |  |                     // sats[0] starts off empty. | 
| 1261 | 0 |                     std::vector<InputStack> sats = Vector(EMPTY); | 
| 1262 | 0 |                     for (size_t i = 0; i < subres.size(); ++i) { | 
| 1263 |  |                         // Introduce an alias for the i'th last satisfaction/dissatisfaction. | 
| 1264 | 0 |                         auto& res = subres[subres.size() - i - 1]; | 
| 1265 |  |                         // Compute the next sats vector: next_sats[0] is sats[0] plus res.nsat (thus containing all dissatisfactions | 
| 1266 |  |                         // so far. next_sats[j] is either sats[j] + res.nsat (reusing j earlier satisfactions) or sats[j-1] + res.sat | 
| 1267 |  |                         // (reusing j-1 earlier satisfactions plus a new one). The very last next_sats[j] is all satisfactions. | 
| 1268 | 0 |                         std::vector<InputStack> next_sats; | 
| 1269 | 0 |                         next_sats.push_back(sats[0] + res.nsat); | 
| 1270 | 0 |                         for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + res.nsat) | (std::move(sats[j - 1]) + res.sat)); | 
| 1271 | 0 |                         next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(res.sat)); | 
| 1272 |  |                         // Switch over. | 
| 1273 | 0 |                         sats = std::move(next_sats); | 
| 1274 | 0 |                     } | 
| 1275 |  |                     // At this point, sats[k].sat is the best satisfaction for the overall thresh() node. The best dissatisfaction | 
| 1276 |  |                     // is computed by gathering all sats[i].nsat for i != k. | 
| 1277 | 0 |                     InputStack nsat = INVALID; | 
| 1278 | 0 |                     for (size_t i = 0; i < sats.size(); ++i) { | 
| 1279 |  |                         // i==k is the satisfaction; i==0 is the canonical dissatisfaction; | 
| 1280 |  |                         // the rest are non-canonical (a no-signature dissatisfaction - the i=0 | 
| 1281 |  |                         // form - is always available) and malleable (due to overcompleteness). | 
| 1282 |  |                         // Marking the solutions malleable here is not strictly necessary, as they | 
| 1283 |  |                         // should already never be picked in non-malleable solutions due to the | 
| 1284 |  |                         // availability of the i=0 form. | 
| 1285 | 0 |                         if (i != 0 && i != node.k) sats[i].SetMalleable().SetNonCanon(); | 
| 1286 |  |                         // Include all dissatisfactions (even these non-canonical ones) in nsat. | 
| 1287 | 0 |                         if (i != node.k) nsat = std::move(nsat) | std::move(sats[i]); | 
| 1288 | 0 |                     } | 
| 1289 | 0 |                     assert(node.k < sats.size()); | 
| 1290 | 0 |                     return {std::move(nsat), std::move(sats[node.k])}; | 
| 1291 | 0 |                 } | 
| 1292 | 0 |                 case Fragment::OLDER: { | 
| 1293 | 0 |                     return {INVALID, ctx.CheckOlder(node.k) ? EMPTY : INVALID}; | 
| 1294 | 0 |                 } | 
| 1295 | 0 |                 case Fragment::AFTER: { | 
| 1296 | 0 |                     return {INVALID, ctx.CheckAfter(node.k) ? EMPTY : INVALID}; | 
| 1297 | 0 |                 } | 
| 1298 | 0 |                 case Fragment::SHA256: { | 
| 1299 | 0 |                     std::vector<unsigned char> preimage; | 
| 1300 | 0 |                     Availability avail = ctx.SatSHA256(node.data, preimage); | 
| 1301 | 0 |                     return {ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)}; | 
| 1302 | 0 |                 } | 
| 1303 | 0 |                 case Fragment::RIPEMD160: { | 
| 1304 | 0 |                     std::vector<unsigned char> preimage; | 
| 1305 | 0 |                     Availability avail = ctx.SatRIPEMD160(node.data, preimage); | 
| 1306 | 0 |                     return {ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)}; | 
| 1307 | 0 |                 } | 
| 1308 | 0 |                 case Fragment::HASH256: { | 
| 1309 | 0 |                     std::vector<unsigned char> preimage; | 
| 1310 | 0 |                     Availability avail = ctx.SatHASH256(node.data, preimage); | 
| 1311 | 0 |                     return {ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)}; | 
| 1312 | 0 |                 } | 
| 1313 | 0 |                 case Fragment::HASH160: { | 
| 1314 | 0 |                     std::vector<unsigned char> preimage; | 
| 1315 | 0 |                     Availability avail = ctx.SatHASH160(node.data, preimage); | 
| 1316 | 0 |                     return {ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)}; | 
| 1317 | 0 |                 } | 
| 1318 | 0 |                 case Fragment::AND_V: { | 
| 1319 | 0 |                     auto& x = subres[0], &y = subres[1]; | 
| 1320 |  |                     // As the dissatisfaction here only consist of a single option, it doesn't | 
| 1321 |  |                     // actually need to be listed (it's not required for reasoning about malleability of | 
| 1322 |  |                     // other options), and is never required (no valid miniscript relies on the ability | 
| 1323 |  |                     // to satisfy the type V left subexpression). It's still listed here for | 
| 1324 |  |                     // completeness, as a hypothetical (not currently implemented) satisfier that doesn't | 
| 1325 |  |                     // care about malleability might in some cases prefer it still. | 
| 1326 | 0 |                     return {(y.nsat + x.sat).SetNonCanon(), y.sat + x.sat}; | 
| 1327 | 0 |                 } | 
| 1328 | 0 |                 case Fragment::AND_B: { | 
| 1329 | 0 |                     auto& x = subres[0], &y = subres[1]; | 
| 1330 |  |                     // Note that it is not strictly necessary to mark the 2nd and 3rd dissatisfaction here | 
| 1331 |  |                     // as malleable. While they are definitely malleable, they are also non-canonical due | 
| 1332 |  |                     // to the guaranteed existence of a no-signature other dissatisfaction (the 1st) | 
| 1333 |  |                     // option. Because of that, the 2nd and 3rd option will never be chosen, even if they | 
| 1334 |  |                     // weren't marked as malleable. | 
| 1335 | 0 |                     return {(y.nsat + x.nsat) | (y.sat + x.nsat).SetMalleable().SetNonCanon() | (y.nsat + x.sat).SetMalleable().SetNonCanon(), y.sat + x.sat}; | 
| 1336 | 0 |                 } | 
| 1337 | 0 |                 case Fragment::OR_B: { | 
| 1338 | 0 |                     auto& x = subres[0], &z = subres[1]; | 
| 1339 |  |                     // The (sat(Z) sat(X)) solution is overcomplete (attacker can change either into dsat). | 
| 1340 | 0 |                     return {z.nsat + x.nsat, (z.nsat + x.sat) | (z.sat + x.nsat) | (z.sat + x.sat).SetMalleable().SetNonCanon()}; | 
| 1341 | 0 |                 } | 
| 1342 | 0 |                 case Fragment::OR_C: { | 
| 1343 | 0 |                     auto& x = subres[0], &z = subres[1]; | 
| 1344 | 0 |                     return {INVALID, std::move(x.sat) | (z.sat + x.nsat)}; | 
| 1345 | 0 |                 } | 
| 1346 | 0 |                 case Fragment::OR_D: { | 
| 1347 | 0 |                     auto& x = subres[0], &z = subres[1]; | 
| 1348 | 0 |                     return {z.nsat + x.nsat, std::move(x.sat) | (z.sat + x.nsat)}; | 
| 1349 | 0 |                 } | 
| 1350 | 0 |                 case Fragment::OR_I: { | 
| 1351 | 0 |                     auto& x = subres[0], &z = subres[1]; | 
| 1352 | 0 |                     return {(x.nsat + ONE) | (z.nsat + ZERO), (x.sat + ONE) | (z.sat + ZERO)}; | 
| 1353 | 0 |                 } | 
| 1354 | 0 |                 case Fragment::ANDOR: { | 
| 1355 | 0 |                     auto& x = subres[0], &y = subres[1], &z = subres[2]; | 
| 1356 | 0 |                     return {(y.nsat + x.sat).SetNonCanon() | (z.nsat + x.nsat), (y.sat + x.sat) | (z.sat + x.nsat)}; | 
| 1357 | 0 |                 } | 
| 1358 | 0 |                 case Fragment::WRAP_A: | 
| 1359 | 0 |                 case Fragment::WRAP_S: | 
| 1360 | 0 |                 case Fragment::WRAP_C: | 
| 1361 | 0 |                 case Fragment::WRAP_N: | 
| 1362 | 0 |                     return std::move(subres[0]); | 
| 1363 | 0 |                 case Fragment::WRAP_D: { | 
| 1364 | 0 |                     auto &x = subres[0]; | 
| 1365 | 0 |                     return {ZERO, x.sat + ONE}; | 
| 1366 | 0 |                 } | 
| 1367 | 0 |                 case Fragment::WRAP_J: { | 
| 1368 | 0 |                     auto &x = subres[0]; | 
| 1369 |  |                     // If a dissatisfaction with a nonzero top stack element exists, an alternative dissatisfaction exists. | 
| 1370 |  |                     // As the dissatisfaction logic currently doesn't keep track of this nonzeroness property, and thus even | 
| 1371 |  |                     // if a dissatisfaction with a top zero element is found, we don't know whether another one with a | 
| 1372 |  |                     // nonzero top stack element exists. Make the conservative assumption that whenever the subexpression is weakly | 
| 1373 |  |                     // dissatisfiable, this alternative dissatisfaction exists and leads to malleability. | 
| 1374 | 0 |                     return {InputStack(ZERO).SetMalleable(x.nsat.available != Availability::NO && !x.nsat.has_sig), std::move(x.sat)}; | 
| 1375 | 0 |                 } | 
| 1376 | 0 |                 case Fragment::WRAP_V: { | 
| 1377 | 0 |                     auto &x = subres[0]; | 
| 1378 | 0 |                     return {INVALID, std::move(x.sat)}; | 
| 1379 | 0 |                 } | 
| 1380 | 0 |                 case Fragment::JUST_0: return {EMPTY, INVALID}; | 
| 1381 | 0 |                 case Fragment::JUST_1: return {INVALID, EMPTY}; | 
| 1382 | 0 |             } | 
| 1383 | 0 |             assert(false); | 
| 1384 | 0 |             return {INVALID, INVALID}; | 
| 1385 | 0 |         }; Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE12ProduceInputIN12_GLOBAL__N_116SatisfierContextEEENS_8internal11InputResultERKT_ENKUlRKS2_NSt3__14spanIS7_Lm18446744073709551615EEEE_clESC_SF_Unexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE12ProduceInputI12TapSatisfierEENS_8internal11InputResultERKT_ENKUlRKS2_NSt3__14spanIS6_Lm18446744073709551615EEEE_clESB_SE_Unexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE12ProduceInputI12WshSatisfierEENS_8internal11InputResultERKT_ENKUlRKS2_NSt3__14spanIS6_Lm18446744073709551615EEEE_clESB_SE_ | 
| 1386 |  | 
 | 
| 1387 | 0 |         auto tester = [&helper](const Node& node, std::span<InputResult> subres) -> InputResult { | 
| 1388 | 0 |             auto ret = helper(node, subres); | 
| 1389 |  |  | 
| 1390 |  |             // Do a consistency check between the satisfaction code and the type checker | 
| 1391 |  |             // (the actual satisfaction code in ProduceInputHelper does not use GetType) | 
| 1392 |  |  | 
| 1393 |  |             // For 'z' nodes, available satisfactions/dissatisfactions must have stack size 0. | 
| 1394 | 0 |             if (node.GetType() << "z"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() == 0); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "z"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() == 0); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "z"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() == 0); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1395 | 0 |             if (node.GetType() << "z"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() == 0); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "z"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() == 0); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "z"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() == 0); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1396 |  |  | 
| 1397 |  |             // For 'o' nodes, available satisfactions/dissatisfactions must have stack size 1. | 
| 1398 | 0 |             if (node.GetType() << "o"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "o"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "o"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1399 | 0 |             if (node.GetType() << "o"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "o"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "o"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1400 |  |  | 
| 1401 |  |             // For 'n' nodes, available satisfactions/dissatisfactions must have stack size 1 or larger. For satisfactions, | 
| 1402 |  |             // the top element cannot be 0. | 
| 1403 | 0 |             if (node.GetType() << "n"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() >= 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "n"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() >= 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "n"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() >= 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1404 | 0 |             if (node.GetType() << "n"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() >= 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "n"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() >= 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "n"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() >= 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1405 | 0 |             if (node.GetType() << "n"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(!ret.sat.stack.back().empty()); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "n"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(!ret.sat.stack.back().empty()); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "n"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(!ret.sat.stack.back().empty()); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1406 |  |  | 
| 1407 |  |             // For 'd' nodes, a dissatisfaction must exist, and they must not need a signature. If it is non-malleable, | 
| 1408 |  |             // it must be canonical. | 
| 1409 | 0 |             if (node.GetType() << "d"_mst) CHECK_NONFATAL(ret.nsat.available != Availability::NO); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "d"_mst) CHECK_NONFATAL(ret.nsat.available != Availability::NO); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "d"_mst) CHECK_NONFATAL(ret.nsat.available != Availability::NO); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1410 | 0 |             if (node.GetType() << "d"_mst) CHECK_NONFATAL(!ret.nsat.has_sig); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "d"_mst) CHECK_NONFATAL(!ret.nsat.has_sig); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "d"_mst) CHECK_NONFATAL(!ret.nsat.has_sig); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1411 | 0 |             if (node.GetType() << "d"_mst && !ret.nsat.malleable) CHECK_NONFATAL(!ret.nsat.non_canon); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "d"_mst && !ret.nsat.malleable) CHECK_NONFATAL(!ret.nsat.non_canon); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "d"_mst && !ret.nsat.malleable) CHECK_NONFATAL(!ret.nsat.non_canon); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1412 |  |  | 
| 1413 |  |             // For 'f'/'s' nodes, dissatisfactions/satisfactions must have a signature. | 
| 1414 | 0 |             if (node.GetType() << "f"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.has_sig); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "f"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.has_sig); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "f"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.has_sig); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1415 | 0 |             if (node.GetType() << "s"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.has_sig); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "s"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.has_sig); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "s"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.has_sig); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1416 |  |  | 
| 1417 |  |             // For non-malleable 'e' nodes, a non-malleable dissatisfaction must exist. | 
| 1418 | 0 |             if (node.GetType() << "me"_mst) CHECK_NONFATAL(ret.nsat.available != Availability::NO); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "me"_mst) CHECK_NONFATAL(ret.nsat.available != Availability::NO); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "me"_mst) CHECK_NONFATAL(ret.nsat.available != Availability::NO); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1419 | 0 |             if (node.GetType() << "me"_mst) CHECK_NONFATAL(!ret.nsat.malleable); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "me"_mst) CHECK_NONFATAL(!ret.nsat.malleable); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "me"_mst) CHECK_NONFATAL(!ret.nsat.malleable); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1420 |  |  | 
| 1421 |  |             // For 'm' nodes, if a satisfaction exists, it must be non-malleable. | 
| 1422 | 0 |             if (node.GetType() << "m"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(!ret.sat.malleable); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "m"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(!ret.sat.malleable); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (node.GetType() << "m"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(!ret.sat.malleable); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1423 |  |  | 
| 1424 |  |             // If a non-malleable satisfaction exists, it must be canonical. | 
| 1425 | 0 |             if (ret.sat.available != Availability::NO && !ret.sat.malleable) CHECK_NONFATAL(!ret.sat.non_canon); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (ret.sat.available != Availability::NO && !ret.sat.malleable) CHECK_NONFATAL(!ret.sat.non_canon); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |             if (ret.sat.available != Availability::NO && !ret.sat.malleable) CHECK_NONFATAL(!ret.sat.non_canon); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1426 |  | 
 | 
| 1427 | 0 |             return ret; | 
| 1428 | 0 |         }; Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE12ProduceInputIN12_GLOBAL__N_116SatisfierContextEEENS_8internal11InputResultERKT_ENKUlRKS2_NSt3__14spanIS7_Lm18446744073709551615EEEE0_clESC_SF_Unexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE12ProduceInputI12TapSatisfierEENS_8internal11InputResultERKT_ENKUlRKS2_NSt3__14spanIS6_Lm18446744073709551615EEEE0_clESB_SE_Unexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE12ProduceInputI12WshSatisfierEENS_8internal11InputResultERKT_ENKUlRKS2_NSt3__14spanIS6_Lm18446744073709551615EEEE0_clESB_SE_ | 
| 1429 |  | 
 | 
| 1430 | 0 |         return TreeEval<InputResult>(tester); | 
| 1431 | 0 |     } Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE12ProduceInputIN12_GLOBAL__N_116SatisfierContextEEENS_8internal11InputResultERKT_Unexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE12ProduceInputI12TapSatisfierEENS_8internal11InputResultERKT_Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE12ProduceInputI12WshSatisfierEENS_8internal11InputResultERKT_ | 
| 1432 |  |  | 
| 1433 |  | public: | 
| 1434 |  |     /** Update duplicate key information in this Node. | 
| 1435 |  |      * | 
| 1436 |  |      * This uses a custom key comparator provided by the context in order to still detect duplicates | 
| 1437 |  |      * for more complicated types. | 
| 1438 |  |      */ | 
| 1439 |  |     template<typename Ctx> void DuplicateKeyCheck(const Ctx& ctx) const | 
| 1440 | 0 |     { | 
| 1441 |  |         // We cannot use a lambda here, as lambdas are non assignable, and the set operations | 
| 1442 |  |         // below require moving the comparators around. | 
| 1443 | 0 |         struct Comp { | 
| 1444 | 0 |             const Ctx* ctx_ptr; | 
| 1445 | 0 |             Comp(const Ctx& ctx) : ctx_ptr(&ctx) {}Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckIN12_GLOBAL__N_113ParserContextEEEvRKT_EN4CompC2ERKS5_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckIN12_GLOBAL__N_113KeyComparatorEEEvRKT_EN4CompC2ERKS5_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE17DuplicateKeyCheckIS2_EEvRKT_EN4CompC2ERKS2_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE17DuplicateKeyCheckIN12_GLOBAL__N_19KeyParserEEEvRKT_EN4CompC2ERKS4_Unexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE17DuplicateKeyCheckI12TapSatisfierEEvRKT_EN4CompC2ERKS4_Unexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckI12WshSatisfierEEvRKT_EN4CompC2ERKS4_ | 
| 1446 | 0 |             bool operator()(const Key& a, const Key& b) const { return ctx_ptr->KeyCompare(a, b); }Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckIN12_GLOBAL__N_113ParserContextEEEvRKT_ENK4CompclERKS1_SB_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckIN12_GLOBAL__N_113KeyComparatorEEEvRKT_ENK4CompclERKS1_SB_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE17DuplicateKeyCheckIS2_EEvRKT_ENK4CompclERKS3_SB_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE17DuplicateKeyCheckIN12_GLOBAL__N_19KeyParserEEEvRKT_ENK4CompclERKjSA_Unexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE17DuplicateKeyCheckI12TapSatisfierEEvRKT_ENK4CompclERKS1_SA_Unexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckI12WshSatisfierEEvRKT_ENK4CompclERKS1_SA_ | 
| 1447 | 0 |         }; | 
| 1448 |  |  | 
| 1449 |  |         // state in the recursive computation: | 
| 1450 |  |         // - std::nullopt means "this node has duplicates" | 
| 1451 |  |         // - an std::set means "this node has no duplicate keys, and they are: ...". | 
| 1452 | 0 |         using keyset = std::set<Key, Comp>; | 
| 1453 | 0 |         using state = std::optional<keyset>; | 
| 1454 |  | 
 | 
| 1455 | 0 |         auto upfn = [&ctx](const Node& node, std::span<state> subs) -> state { | 
| 1456 |  |             // If this node is already known to have duplicates, nothing left to do. | 
| 1457 | 0 |             if (node.has_duplicate_keys.has_value() && *node.has_duplicate_keys) return {}; | 
| 1458 |  |  | 
| 1459 |  |             // Check if one of the children is already known to have duplicates. | 
| 1460 | 0 |             for (auto& sub : subs) { | 
| 1461 | 0 |                 if (!sub.has_value()) { | 
| 1462 | 0 |                     node.has_duplicate_keys = true; | 
| 1463 | 0 |                     return {}; | 
| 1464 | 0 |                 } | 
| 1465 | 0 |             } | 
| 1466 |  |  | 
| 1467 |  |             // Start building the set of keys involved in this node and children. | 
| 1468 |  |             // Start by keys in this node directly. | 
| 1469 | 0 |             size_t keys_count = node.keys.size(); | 
| 1470 | 0 |             keyset key_set{node.keys.begin(), node.keys.end(), Comp(ctx)}; | 
| 1471 | 0 |             if (key_set.size() != keys_count) { | 
| 1472 |  |                 // It already has duplicates; bail out. | 
| 1473 | 0 |                 node.has_duplicate_keys = true; | 
| 1474 | 0 |                 return {}; | 
| 1475 | 0 |             } | 
| 1476 |  |  | 
| 1477 |  |             // Merge the keys from the children into this set. | 
| 1478 | 0 |             for (auto& sub : subs) { | 
| 1479 | 0 |                 keys_count += sub->size(); | 
| 1480 |  |                 // Small optimization: std::set::merge is linear in the size of the second arg but | 
| 1481 |  |                 // logarithmic in the size of the first. | 
| 1482 | 0 |                 if (key_set.size() < sub->size()) std::swap(key_set, *sub); | 
| 1483 | 0 |                 key_set.merge(*sub); | 
| 1484 | 0 |                 if (key_set.size() != keys_count) { | 
| 1485 | 0 |                     node.has_duplicate_keys = true; | 
| 1486 | 0 |                     return {}; | 
| 1487 | 0 |                 } | 
| 1488 | 0 |             } | 
| 1489 |  |  | 
| 1490 | 0 |             node.has_duplicate_keys = false; | 
| 1491 | 0 |             return key_set; | 
| 1492 | 0 |         }; Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckIN12_GLOBAL__N_113ParserContextEEEvRKT_ENKUlRKS2_NSt3__14spanINSB_8optionalINSB_3setIS1_ZNKS3_IS5_EEvS8_E4CompNSB_9allocatorIS1_EEEEEELm18446744073709551615EEEE_clESA_SK_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckIN12_GLOBAL__N_113KeyComparatorEEEvRKT_ENKUlRKS2_NSt3__14spanINSB_8optionalINSB_3setIS1_ZNKS3_IS5_EEvS8_E4CompNSB_9allocatorIS1_EEEEEELm18446744073709551615EEEE_clESA_SK_Unexecuted instantiation: miniscript.cpp:_ZZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE17DuplicateKeyCheckIS2_EEvRKT_ENKUlRKS4_NSt3__14spanINSB_8optionalINSB_3setIS3_ZNKS5_IS2_EEvS8_E4CompNSB_9allocatorIS3_EEEEEELm18446744073709551615EEEE_clESA_SK_Unexecuted instantiation: descriptor.cpp:_ZZNK10miniscript4NodeIjE17DuplicateKeyCheckIN12_GLOBAL__N_19KeyParserEEEvRKT_ENKUlRKS1_NSt3__14spanINSA_8optionalINSA_3setIjZNKS2_IS4_EEvS7_E4CompNSA_9allocatorIjEEEEEELm18446744073709551615EEEE_clES9_SJ_Unexecuted instantiation: _ZZNK10miniscript4NodeI11XOnlyPubKeyE17DuplicateKeyCheckI12TapSatisfierEEvRKT_ENKUlRKS2_NSt3__14spanINSA_8optionalINSA_3setIS1_ZNKS3_IS4_EEvS7_E4CompNSA_9allocatorIS1_EEEEEELm18446744073709551615EEEE_clES9_SJ_Unexecuted instantiation: _ZZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckI12WshSatisfierEEvRKT_ENKUlRKS2_NSt3__14spanINSA_8optionalINSA_3setIS1_ZNKS3_IS4_EEvS7_E4CompNSA_9allocatorIS1_EEEEEELm18446744073709551615EEEE_clES9_SJ_ | 
| 1493 |  | 
 | 
| 1494 | 0 |         TreeEval<state>(upfn); | 
| 1495 | 0 |     } Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckIN12_GLOBAL__N_113ParserContextEEEvRKT_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckIN12_GLOBAL__N_113KeyComparatorEEEvRKT_Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE17DuplicateKeyCheckIS2_EEvRKT_Unexecuted instantiation: descriptor.cpp:_ZNK10miniscript4NodeIjE17DuplicateKeyCheckIN12_GLOBAL__N_19KeyParserEEEvRKT_Unexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE17DuplicateKeyCheckI12TapSatisfierEEvRKT_Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE17DuplicateKeyCheckI12WshSatisfierEEvRKT_ | 
| 1496 |  |  | 
| 1497 |  |     //! Return the size of the script for this expression (faster than ToScript().size()). | 
| 1498 | 0 |     size_t ScriptSize() const { return scriptlen; }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE10ScriptSizeEvUnexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE10ScriptSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE10ScriptSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE10ScriptSizeEv | 
| 1499 |  |  | 
| 1500 |  |     //! Return the maximum number of ops needed to satisfy this script non-malleably. | 
| 1501 | 0 |     std::optional<uint32_t> GetOps() const { | 
| 1502 | 0 |         if (!ops.sat.valid) return {}; | 
| 1503 | 0 |         return ops.count + ops.sat.value; | 
| 1504 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE6GetOpsEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE6GetOpsEv | 
| 1505 |  |  | 
| 1506 |  |     //! Return the number of ops in the script (not counting the dynamic ones that depend on execution). | 
| 1507 | 0 |     uint32_t GetStaticOps() const { return ops.count; } | 
| 1508 |  |  | 
| 1509 |  |     //! Check the ops limit of this script against the consensus limit. | 
| 1510 | 0 |     bool CheckOpsLimit() const { | 
| 1511 | 0 |         if (IsTapscript(m_script_ctx)) return true; | 
| 1512 | 0 |         if (const auto ops = GetOps()) return *ops <= MAX_OPS_PER_SCRIPT; | 
| 1513 | 0 |         return true; | 
| 1514 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE13CheckOpsLimitEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE13CheckOpsLimitEv | 
| 1515 |  |  | 
| 1516 |  |     /** Whether this node is of type B, K or W. (That is, anything but V.) */ | 
| 1517 | 0 |     bool IsBKW() const { | 
| 1518 | 0 |         return !((GetType() & "BKW"_mst) == ""_mst); | 
| 1519 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE5IsBKWEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE5IsBKWEv | 
| 1520 |  |  | 
| 1521 |  |     /** Return the maximum number of stack elements needed to satisfy this script non-malleably. */ | 
| 1522 | 0 |     std::optional<uint32_t> GetStackSize() const { | 
| 1523 | 0 |         if (!ss.sat.valid) return {}; | 
| 1524 | 0 |         return ss.sat.netdiff + static_cast<int32_t>(IsBKW()); | 
| 1525 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE12GetStackSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE12GetStackSizeEv | 
| 1526 |  |  | 
| 1527 |  |     //! Return the maximum size of the stack during execution of this script. | 
| 1528 | 0 |     std::optional<uint32_t> GetExecStackSize() const { | 
| 1529 | 0 |         if (!ss.sat.valid) return {}; | 
| 1530 | 0 |         return ss.sat.exec + static_cast<int32_t>(IsBKW()); | 
| 1531 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE16GetExecStackSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE16GetExecStackSizeEv | 
| 1532 |  |  | 
| 1533 |  |     //! Check the maximum stack size for this script against the policy limit. | 
| 1534 | 0 |     bool CheckStackSize() const { | 
| 1535 |  |         // Since in Tapscript there is no standardness limit on the script and witness sizes, we may run | 
| 1536 |  |         // into the maximum stack size while executing the script. Make sure it doesn't happen. | 
| 1537 | 0 |         if (IsTapscript(m_script_ctx)) { | 
| 1538 | 0 |             if (const auto exec_ss = GetExecStackSize()) return exec_ss <= MAX_STACK_SIZE; | 
| 1539 | 0 |             return true; | 
| 1540 | 0 |         } | 
| 1541 | 0 |         if (const auto ss = GetStackSize()) return *ss <= MAX_STANDARD_P2WSH_STACK_ITEMS; | 
| 1542 | 0 |         return true; | 
| 1543 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE14CheckStackSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE14CheckStackSizeEv | 
| 1544 |  |  | 
| 1545 |  |     //! Whether no satisfaction exists for this node. | 
| 1546 | 0 |     bool IsNotSatisfiable() const { return !GetStackSize(); } | 
| 1547 |  |  | 
| 1548 |  |     /** Return the maximum size in bytes of a witness to satisfy this script non-malleably. Note this does | 
| 1549 |  |      * not include the witness script push. */ | 
| 1550 | 0 |     std::optional<uint32_t> GetWitnessSize() const { | 
| 1551 | 0 |         if (!ws.sat.valid) return {}; | 
| 1552 | 0 |         return ws.sat.value; | 
| 1553 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE14GetWitnessSizeEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE14GetWitnessSizeEv | 
| 1554 |  |  | 
| 1555 |  |     //! Return the expression type. | 
| 1556 | 0 |     Type GetType() const { return typ; }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE7GetTypeEvUnexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE7GetTypeEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE7GetTypeEvUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE7GetTypeEv | 
| 1557 |  |  | 
| 1558 |  |     //! Return the script context for this node. | 
| 1559 | 0 |     MiniscriptContext GetMsCtx() const { return m_script_ctx; } | 
| 1560 |  |  | 
| 1561 |  |     //! Find an insane subnode which has no insane children. Nullptr if there is none. | 
| 1562 | 0 |     const Node* FindInsaneSub() const { | 
| 1563 | 0 |         return TreeEval<const Node*>([](const Node& node, std::span<const Node*> subs) -> const Node* { | 
| 1564 | 0 |             for (auto& sub: subs) if (sub) return sub; | 
| 1565 | 0 |             if (!node.IsSaneSubexpression()) return &node; | 
| 1566 | 0 |             return nullptr; | 
| 1567 | 0 |         }); | 
| 1568 | 0 |     } | 
| 1569 |  |  | 
| 1570 |  |     //! Determine whether a Miniscript node is satisfiable. fn(node) will be invoked for all | 
| 1571 |  |     //! key, time, and hashing nodes, and should return their satisfiability. | 
| 1572 |  |     template<typename F> | 
| 1573 |  |     bool IsSatisfiable(F fn) const | 
| 1574 | 0 |     { | 
| 1575 |  |         // TreeEval() doesn't support bool as NodeType, so use int instead. | 
| 1576 | 0 |         return TreeEval<int>([&fn](const Node& node, std::span<int> subs) -> bool { | 
| 1577 | 0 |             switch (node.fragment) { | 
| 1578 | 0 |                 case Fragment::JUST_0: | 
| 1579 | 0 |                     return false; | 
| 1580 | 0 |                 case Fragment::JUST_1: | 
| 1581 | 0 |                     return true; | 
| 1582 | 0 |                 case Fragment::PK_K: | 
| 1583 | 0 |                 case Fragment::PK_H: | 
| 1584 | 0 |                 case Fragment::MULTI: | 
| 1585 | 0 |                 case Fragment::MULTI_A: | 
| 1586 | 0 |                 case Fragment::AFTER: | 
| 1587 | 0 |                 case Fragment::OLDER: | 
| 1588 | 0 |                 case Fragment::HASH256: | 
| 1589 | 0 |                 case Fragment::HASH160: | 
| 1590 | 0 |                 case Fragment::SHA256: | 
| 1591 | 0 |                 case Fragment::RIPEMD160: | 
| 1592 | 0 |                     return bool{fn(node)}; | 
| 1593 | 0 |                 case Fragment::ANDOR: | 
| 1594 | 0 |                     return (subs[0] && subs[1]) || subs[2]; | 
| 1595 | 0 |                 case Fragment::AND_V: | 
| 1596 | 0 |                 case Fragment::AND_B: | 
| 1597 | 0 |                     return subs[0] && subs[1]; | 
| 1598 | 0 |                 case Fragment::OR_B: | 
| 1599 | 0 |                 case Fragment::OR_C: | 
| 1600 | 0 |                 case Fragment::OR_D: | 
| 1601 | 0 |                 case Fragment::OR_I: | 
| 1602 | 0 |                     return subs[0] || subs[1]; | 
| 1603 | 0 |                 case Fragment::THRESH: | 
| 1604 | 0 |                     return static_cast<uint32_t>(std::count(subs.begin(), subs.end(), true)) >= node.k; | 
| 1605 | 0 |                 default: // wrappers | 
| 1606 | 0 |                     assert(subs.size() >= 1); | 
| 1607 | 0 |                     CHECK_NONFATAL(subs.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 1608 | 0 |                     return subs[0]; | 
| 1609 | 0 |             } | 
| 1610 | 0 |         }); | 
| 1611 | 0 |     } | 
| 1612 |  |  | 
| 1613 |  |     //! Check whether this node is valid at all. | 
| 1614 | 0 |     bool IsValid() const { | 
| 1615 | 0 |         if (GetType() == ""_mst) return false; | 
| 1616 | 0 |         return ScriptSize() <= internal::MaxScriptSize(m_script_ctx); | 
| 1617 | 0 |     } Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE7IsValidEvUnexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE7IsValidEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE7IsValidEvUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE7IsValidEv | 
| 1618 |  |  | 
| 1619 |  |     //! Check whether this node is valid as a script on its own. | 
| 1620 | 0 |     bool IsValidTopLevel() const { return IsValid() && GetType() << "B"_mst; }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE15IsValidTopLevelEvUnexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEE15IsValidTopLevelEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE15IsValidTopLevelEvUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE15IsValidTopLevelEv | 
| 1621 |  |  | 
| 1622 |  |     //! Check whether this script can always be satisfied in a non-malleable way. | 
| 1623 | 0 |     bool IsNonMalleable() const { return GetType() << "m"_mst; }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE14IsNonMalleableEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE14IsNonMalleableEv | 
| 1624 |  |  | 
| 1625 |  |     //! Check whether this script always needs a signature. | 
| 1626 | 0 |     bool NeedsSignature() const { return GetType() << "s"_mst; }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE14NeedsSignatureEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE14NeedsSignatureEv | 
| 1627 |  |  | 
| 1628 |  |     //! Check whether there is no satisfaction path that contains both timelocks and heightlocks | 
| 1629 | 0 |     bool CheckTimeLocksMix() const { return GetType() << "k"_mst; }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE17CheckTimeLocksMixEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE17CheckTimeLocksMixEv | 
| 1630 |  |  | 
| 1631 |  |     //! Check whether there is no duplicate key across this fragment and all its sub-fragments. | 
| 1632 | 0 |     bool CheckDuplicateKey() const { return has_duplicate_keys && !*has_duplicate_keys; }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE17CheckDuplicateKeyEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE17CheckDuplicateKeyEv | 
| 1633 |  |  | 
| 1634 |  |     //! Whether successful non-malleable satisfactions are guaranteed to be valid. | 
| 1635 | 0 |     bool ValidSatisfactions() const { return IsValid() && CheckOpsLimit() && CheckStackSize(); }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE18ValidSatisfactionsEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE18ValidSatisfactionsEv | 
| 1636 |  |  | 
| 1637 |  |     //! Whether the apparent policy of this node matches its script semantics. Doesn't guarantee it is a safe script on its own. | 
| 1638 | 0 |     bool IsSaneSubexpression() const { return ValidSatisfactions() && IsNonMalleable() && CheckTimeLocksMix() && CheckDuplicateKey(); }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE19IsSaneSubexpressionEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE19IsSaneSubexpressionEv | 
| 1639 |  |  | 
| 1640 |  |     //! Check whether this node is safe as a script on its own. | 
| 1641 | 0 |     bool IsSane() const { return IsValidTopLevel() && IsSaneSubexpression() && NeedsSignature(); }Unexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE6IsSaneEvUnexecuted instantiation: _ZNK10miniscript4NodeIjE6IsSaneEv | 
| 1642 |  |  | 
| 1643 |  |     //! Produce a witness for this script, if possible and given the information available in the context. | 
| 1644 |  |     //! The non-malleable satisfaction is guaranteed to be valid if it exists, and ValidSatisfaction() | 
| 1645 |  |     //! is true. If IsSane() holds, this satisfaction is guaranteed to succeed in case the node's | 
| 1646 |  |     //! conditions are satisfied (private keys and hash preimages available, locktimes satisfied). | 
| 1647 |  |     template<typename Ctx> | 
| 1648 | 0 |     Availability Satisfy(const Ctx& ctx, std::vector<std::vector<unsigned char>>& stack, bool nonmalleable = true) const { | 
| 1649 | 0 |         auto ret = ProduceInput(ctx); | 
| 1650 | 0 |         if (nonmalleable && (ret.sat.malleable || !ret.sat.has_sig)) return Availability::NO; | 
| 1651 | 0 |         stack = std::move(ret.sat.stack); | 
| 1652 | 0 |         return ret.sat.available; | 
| 1653 | 0 |     } Unexecuted instantiation: miniscript.cpp:_ZNK10miniscript4NodeI7CPubKeyE7SatisfyIN12_GLOBAL__N_116SatisfierContextEEENS_12AvailabilityERKT_RNSt3__16vectorINSB_IhNSA_9allocatorIhEEEENSC_ISE_EEEEbUnexecuted instantiation: _ZNK10miniscript4NodeI11XOnlyPubKeyE7SatisfyI12TapSatisfierEENS_12AvailabilityERKT_RNSt3__16vectorINSA_IhNS9_9allocatorIhEEEENSB_ISD_EEEEbUnexecuted instantiation: _ZNK10miniscript4NodeI7CPubKeyE7SatisfyI12WshSatisfierEENS_12AvailabilityERKT_RNSt3__16vectorINSA_IhNS9_9allocatorIhEEEENSB_ISD_EEEEb | 
| 1654 |  |  | 
| 1655 |  |     //! Equality testing. | 
| 1656 | 0 |     bool operator==(const Node<Key>& arg) const { return Compare(*this, arg) == 0; } | 
| 1657 |  |  | 
| 1658 |  |     // Constructors with various argument combinations, which bypass the duplicate key check. | 
| 1659 |  |     Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0) | 
| 1660 | 0 |         : fragment(nt), k(val), data(std::move(arg)), subs(std::move(sub)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {} | 
| 1661 |  |     Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0) | 
| 1662 | 0 |         : fragment(nt), k(val), data(std::move(arg)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}Unexecuted instantiation: _ZN10miniscript4NodeI7CPubKeyEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIhNS7_9allocatorIhEEEEjUnexecuted instantiation: miniscript.cpp:_ZN10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIhNS9_9allocatorIhEEEEjUnexecuted instantiation: _ZN10miniscript4NodeIjEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIhNS6_9allocatorIhEEEEjUnexecuted instantiation: _ZN10miniscript4NodeI11XOnlyPubKeyEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIhNS7_9allocatorIhEEEEj | 
| 1663 |  |     Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0) | 
| 1664 |  |         : fragment(nt), k(val), keys(std::move(key)), m_script_ctx{script_ctx}, subs(std::move(sub)), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {} | 
| 1665 |  |     Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<Key> key, uint32_t val = 0) | 
| 1666 | 0 |         : fragment(nt), k(val), keys(std::move(key)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}Unexecuted instantiation: _ZN10miniscript4NodeI7CPubKeyEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIS1_NS7_9allocatorIS1_EEEEjUnexecuted instantiation: miniscript.cpp:_ZN10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIS3_NS9_9allocatorIS3_EEEEjUnexecuted instantiation: _ZN10miniscript4NodeIjEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIjNS6_9allocatorIjEEEEjUnexecuted instantiation: _ZN10miniscript4NodeI11XOnlyPubKeyEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorIS1_NS7_9allocatorIS1_EEEEj | 
| 1667 |  |     Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0) | 
| 1668 | 0 |         : fragment(nt), k(val), subs(std::move(sub)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}Unexecuted instantiation: _ZN10miniscript4NodeI7CPubKeyEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS7_10unique_ptrIKS2_NS7_14default_deleteISA_EEEENS7_9allocatorISD_EEEEjUnexecuted instantiation: miniscript.cpp:_ZN10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS9_10unique_ptrIKS4_NS9_14default_deleteISC_EEEENS9_9allocatorISF_EEEEjUnexecuted instantiation: _ZN10miniscript4NodeIjEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS6_10unique_ptrIKS1_NS6_14default_deleteIS9_EEEENS6_9allocatorISC_EEEEjUnexecuted instantiation: _ZN10miniscript4NodeI11XOnlyPubKeyEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentENSt3__16vectorINS7_10unique_ptrIKS2_NS7_14default_deleteISA_EEEENS7_9allocatorISD_EEEEj | 
| 1669 |  |     Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, uint32_t val = 0) | 
| 1670 | 0 |         : fragment(nt), k(val), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}Unexecuted instantiation: _ZN10miniscript4NodeI7CPubKeyEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentEjUnexecuted instantiation: miniscript.cpp:_ZN10miniscript4NodeIN12_GLOBAL__N_119ScriptParserContext3KeyEEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentEjUnexecuted instantiation: _ZN10miniscript4NodeIjEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentEjUnexecuted instantiation: _ZN10miniscript4NodeI11XOnlyPubKeyEC2ENS_8internal10NoDupCheckENS_17MiniscriptContextENS_8FragmentEj | 
| 1671 |  |  | 
| 1672 |  |     // Constructors with various argument combinations, which do perform the duplicate key check. | 
| 1673 |  |     template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0) | 
| 1674 |  |         : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(arg), val) { DuplicateKeyCheck(ctx); } | 
| 1675 |  |     template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0) | 
| 1676 |  |         : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(arg), val) { DuplicateKeyCheck(ctx);} | 
| 1677 |  |     template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0) | 
| 1678 |  |         : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(key), val) { DuplicateKeyCheck(ctx); } | 
| 1679 |  |     template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<Key> key, uint32_t val = 0) | 
| 1680 |  |         : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(key), val) { DuplicateKeyCheck(ctx); } | 
| 1681 |  |     template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0) | 
| 1682 |  |         : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), val) { DuplicateKeyCheck(ctx); } | 
| 1683 |  |     template <typename Ctx> Node(const Ctx& ctx, Fragment nt, uint32_t val = 0) | 
| 1684 |  |         : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, val) { DuplicateKeyCheck(ctx); } | 
| 1685 |  |  | 
| 1686 |  |     // Delete copy constructor and assignment operator, use Clone() instead | 
| 1687 |  |     Node(const Node&) = delete; | 
| 1688 |  |     Node& operator=(const Node&) = delete; | 
| 1689 |  | }; | 
| 1690 |  |  | 
| 1691 |  | namespace internal { | 
| 1692 |  |  | 
| 1693 |  | enum class ParseContext { | 
| 1694 |  |     /** An expression which may be begin with wrappers followed by a colon. */ | 
| 1695 |  |     WRAPPED_EXPR, | 
| 1696 |  |     /** A miniscript expression which does not begin with wrappers. */ | 
| 1697 |  |     EXPR, | 
| 1698 |  |  | 
| 1699 |  |     /** SWAP wraps the top constructed node with s: */ | 
| 1700 |  |     SWAP, | 
| 1701 |  |     /** ALT wraps the top constructed node with a: */ | 
| 1702 |  |     ALT, | 
| 1703 |  |     /** CHECK wraps the top constructed node with c: */ | 
| 1704 |  |     CHECK, | 
| 1705 |  |     /** DUP_IF wraps the top constructed node with d: */ | 
| 1706 |  |     DUP_IF, | 
| 1707 |  |     /** VERIFY wraps the top constructed node with v: */ | 
| 1708 |  |     VERIFY, | 
| 1709 |  |     /** NON_ZERO wraps the top constructed node with j: */ | 
| 1710 |  |     NON_ZERO, | 
| 1711 |  |     /** ZERO_NOTEQUAL wraps the top constructed node with n: */ | 
| 1712 |  |     ZERO_NOTEQUAL, | 
| 1713 |  |     /** WRAP_U will construct an or_i(X,0) node from the top constructed node. */ | 
| 1714 |  |     WRAP_U, | 
| 1715 |  |     /** WRAP_T will construct an and_v(X,1) node from the top constructed node. */ | 
| 1716 |  |     WRAP_T, | 
| 1717 |  |  | 
| 1718 |  |     /** AND_N will construct an andor(X,Y,0) node from the last two constructed nodes. */ | 
| 1719 |  |     AND_N, | 
| 1720 |  |     /** AND_V will construct an and_v node from the last two constructed nodes. */ | 
| 1721 |  |     AND_V, | 
| 1722 |  |     /** AND_B will construct an and_b node from the last two constructed nodes. */ | 
| 1723 |  |     AND_B, | 
| 1724 |  |     /** ANDOR will construct an andor node from the last three constructed nodes. */ | 
| 1725 |  |     ANDOR, | 
| 1726 |  |     /** OR_B will construct an or_b node from the last two constructed nodes. */ | 
| 1727 |  |     OR_B, | 
| 1728 |  |     /** OR_C will construct an or_c node from the last two constructed nodes. */ | 
| 1729 |  |     OR_C, | 
| 1730 |  |     /** OR_D will construct an or_d node from the last two constructed nodes. */ | 
| 1731 |  |     OR_D, | 
| 1732 |  |     /** OR_I will construct an or_i node from the last two constructed nodes. */ | 
| 1733 |  |     OR_I, | 
| 1734 |  |  | 
| 1735 |  |     /** THRESH will read a wrapped expression, and then look for a COMMA. If | 
| 1736 |  |      * no comma follows, it will construct a thresh node from the appropriate | 
| 1737 |  |      * number of constructed children. Otherwise, it will recurse with another | 
| 1738 |  |      * THRESH. */ | 
| 1739 |  |     THRESH, | 
| 1740 |  |  | 
| 1741 |  |     /** COMMA expects the next element to be ',' and fails if not. */ | 
| 1742 |  |     COMMA, | 
| 1743 |  |     /** CLOSE_BRACKET expects the next element to be ')' and fails if not. */ | 
| 1744 |  |     CLOSE_BRACKET, | 
| 1745 |  | }; | 
| 1746 |  |  | 
| 1747 |  | int FindNextChar(std::span<const char> in, const char m); | 
| 1748 |  |  | 
| 1749 |  | /** Parse a key string ending at the end of the fragment's text representation. */ | 
| 1750 |  | template<typename Key, typename Ctx> | 
| 1751 |  | std::optional<std::pair<Key, int>> ParseKeyEnd(std::span<const char> in, const Ctx& ctx) | 
| 1752 | 0 | { | 
| 1753 | 0 |     int key_size = FindNextChar(in, ')'); | 
| 1754 | 0 |     if (key_size < 1) return {}; | 
| 1755 | 0 |     auto key = ctx.FromString(in.begin(), in.begin() + key_size); | 
| 1756 | 0 |     if (!key) return {}; | 
| 1757 | 0 |     return {{std::move(*key), key_size}}; | 
| 1758 | 0 | } Unexecuted instantiation: miniscript.cpp:_ZN10miniscript8internal11ParseKeyEndI7CPubKeyN12_GLOBAL__N_113ParserContextEEENSt3__18optionalINS5_4pairIT_iEEEENS5_4spanIKcLm18446744073709551615EEERKT0_Unexecuted instantiation: descriptor.cpp:_ZN10miniscript8internal11ParseKeyEndIjN12_GLOBAL__N_19KeyParserEEENSt3__18optionalINS4_4pairIT_iEEEENS4_4spanIKcLm18446744073709551615EEERKT0_ | 
| 1759 |  |  | 
| 1760 |  | /** Parse a hex string ending at the end of the fragment's text representation. */ | 
| 1761 |  | template<typename Ctx> | 
| 1762 |  | std::optional<std::pair<std::vector<unsigned char>, int>> ParseHexStrEnd(std::span<const char> in, const size_t expected_size, | 
| 1763 |  |                                                                          const Ctx& ctx) | 
| 1764 | 0 | { | 
| 1765 | 0 |     int hash_size = FindNextChar(in, ')'); | 
| 1766 | 0 |     if (hash_size < 1) return {}; | 
| 1767 | 0 |     std::string val = std::string(in.begin(), in.begin() + hash_size); | 
| 1768 | 0 |     if (!IsHex(val)) return {}; | 
| 1769 | 0 |     auto hash = ParseHex(val); | 
| 1770 | 0 |     if (hash.size() != expected_size) return {}; | 
| 1771 | 0 |     return {{std::move(hash), hash_size}}; | 
| 1772 | 0 | } Unexecuted instantiation: miniscript.cpp:_ZN10miniscript8internal14ParseHexStrEndIN12_GLOBAL__N_113ParserContextEEENSt3__18optionalINS4_4pairINS4_6vectorIhNS4_9allocatorIhEEEEiEEEENS4_4spanIKcLm18446744073709551615EEEmRKT_Unexecuted instantiation: descriptor.cpp:_ZN10miniscript8internal14ParseHexStrEndIN12_GLOBAL__N_19KeyParserEEENSt3__18optionalINS4_4pairINS4_6vectorIhNS4_9allocatorIhEEEEiEEEENS4_4spanIKcLm18446744073709551615EEEmRKT_ | 
| 1773 |  |  | 
| 1774 |  | /** BuildBack pops the last two elements off `constructed` and wraps them in the specified Fragment */ | 
| 1775 |  | template<typename Key> | 
| 1776 |  | void BuildBack(const MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>>& constructed, const bool reverse = false) | 
| 1777 | 0 | { | 
| 1778 | 0 |     NodeRef<Key> child = std::move(constructed.back()); | 
| 1779 | 0 |     constructed.pop_back(); | 
| 1780 | 0 |     if (reverse) { | 
| 1781 | 0 |         constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, script_ctx, nt, Vector(std::move(child), std::move(constructed.back()))); | 
| 1782 | 0 |     } else { | 
| 1783 | 0 |         constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, script_ctx, nt, Vector(std::move(constructed.back()), std::move(child))); | 
| 1784 | 0 |     } | 
| 1785 | 0 | } Unexecuted instantiation: _ZN10miniscript8internal9BuildBackI7CPubKeyEEvNS_17MiniscriptContextENS_8FragmentERNSt3__16vectorINS5_10unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISB_EEEENS5_9allocatorISE_EEEEbUnexecuted instantiation: miniscript.cpp:_ZN10miniscript8internal9BuildBackIN12_GLOBAL__N_119ScriptParserContext3KeyEEEvNS_17MiniscriptContextENS_8FragmentERNSt3__16vectorINS7_10unique_ptrIKNS_4NodeIT_EENS7_14default_deleteISD_EEEENS7_9allocatorISG_EEEEbUnexecuted instantiation: _ZN10miniscript8internal9BuildBackIjEEvNS_17MiniscriptContextENS_8FragmentERNSt3__16vectorINS4_10unique_ptrIKNS_4NodeIT_EENS4_14default_deleteISA_EEEENS4_9allocatorISD_EEEEbUnexecuted instantiation: _ZN10miniscript8internal9BuildBackI11XOnlyPubKeyEEvNS_17MiniscriptContextENS_8FragmentERNSt3__16vectorINS5_10unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISB_EEEENS5_9allocatorISE_EEEEb | 
| 1786 |  |  | 
| 1787 |  | /** | 
| 1788 |  |  * Parse a miniscript from its textual descriptor form. | 
| 1789 |  |  * This does not check whether the script is valid, let alone sane. The caller is expected to use | 
| 1790 |  |  * the `IsValidTopLevel()` and `IsSaneTopLevel()` to check for these properties on the node. | 
| 1791 |  |  */ | 
| 1792 |  | template<typename Key, typename Ctx> | 
| 1793 |  | inline NodeRef<Key> Parse(std::span<const char> in, const Ctx& ctx) | 
| 1794 | 0 | { | 
| 1795 | 0 |     using namespace script; | 
| 1796 |  |  | 
| 1797 |  |     // Account for the minimum script size for all parsed fragments so far. It "borrows" 1 | 
| 1798 |  |     // script byte from all leaf nodes, counting it instead whenever a space for a recursive | 
| 1799 |  |     // expression is added (through andor, and_*, or_*, thresh). This guarantees that all fragments | 
| 1800 |  |     // increment the script_size by at least one, except for: | 
| 1801 |  |     // - "0", "1": these leafs are only a single byte, so their subtracted-from increment is 0. | 
| 1802 |  |     //   This is not an issue however, as "space" for them has to be created by combinators, | 
| 1803 |  |     //   which do increment script_size. | 
| 1804 |  |     // - "v:": the v wrapper adds nothing as in some cases it results in no opcode being added | 
| 1805 |  |     //   (instead transforming another opcode into its VERIFY form). However, the v: wrapper has | 
| 1806 |  |     //   to be interleaved with other fragments to be valid, so this is not a concern. | 
| 1807 | 0 |     size_t script_size{1}; | 
| 1808 | 0 |     size_t max_size{internal::MaxScriptSize(ctx.MsContext())}; | 
| 1809 |  |  | 
| 1810 |  |     // The two integers are used to hold state for thresh() | 
| 1811 | 0 |     std::vector<std::tuple<ParseContext, int64_t, int64_t>> to_parse; | 
| 1812 | 0 |     std::vector<NodeRef<Key>> constructed; | 
| 1813 |  | 
 | 
| 1814 | 0 |     to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1); | 
| 1815 |  |  | 
| 1816 |  |     // Parses a multi() or multi_a() from its string representation. Returns false on parsing error. | 
| 1817 | 0 |     const auto parse_multi_exp = [&](std::span<const char>& in, const bool is_multi_a) -> bool { | 
| 1818 | 0 |         const auto max_keys{is_multi_a ? MAX_PUBKEYS_PER_MULTI_A : MAX_PUBKEYS_PER_MULTISIG}; | 
| 1819 | 0 |         const auto required_ctx{is_multi_a ? MiniscriptContext::TAPSCRIPT : MiniscriptContext::P2WSH}; | 
| 1820 | 0 |         if (ctx.MsContext() != required_ctx) return false; | 
| 1821 |  |         // Get threshold | 
| 1822 | 0 |         int next_comma = FindNextChar(in, ','); | 
| 1823 | 0 |         if (next_comma < 1) return false; | 
| 1824 | 0 |         const auto k_to_integral{ToIntegral<int64_t>(std::string_view(in.data(), next_comma))}; | 
| 1825 | 0 |         if (!k_to_integral.has_value()) return false; | 
| 1826 | 0 |         const int64_t k{k_to_integral.value()}; | 
| 1827 | 0 |         in = in.subspan(next_comma + 1); | 
| 1828 |  |         // Get keys. It is compatible for both compressed and x-only keys. | 
| 1829 | 0 |         std::vector<Key> keys; | 
| 1830 | 0 |         while (next_comma != -1) { | 
| 1831 | 0 |             next_comma = FindNextChar(in, ','); | 
| 1832 | 0 |             int key_length = (next_comma == -1) ? FindNextChar(in, ')') : next_comma; | 
| 1833 | 0 |             if (key_length < 1) return false; | 
| 1834 | 0 |             auto key = ctx.FromString(in.begin(), in.begin() + key_length); | 
| 1835 | 0 |             if (!key) return false; | 
| 1836 | 0 |             keys.push_back(std::move(*key)); | 
| 1837 | 0 |             in = in.subspan(key_length + 1); | 
| 1838 | 0 |         } | 
| 1839 | 0 |         if (keys.size() < 1 || keys.size() > max_keys) return false; | 
| 1840 | 0 |         if (k < 1 || k > (int64_t)keys.size()) return false; | 
| 1841 | 0 |         if (is_multi_a) { | 
| 1842 |  |             // (push + xonly-key + CHECKSIG[ADD]) * n + k + OP_NUMEQUAL(VERIFY), minus one. | 
| 1843 | 0 |             script_size += (1 + 32 + 1) * keys.size() + BuildScript(k).size(); | 
| 1844 | 0 |             constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI_A, std::move(keys), k)); | 
| 1845 | 0 |         } else { | 
| 1846 | 0 |             script_size += 2 + (keys.size() > 16) + (k > 16) + 34 * keys.size(); | 
| 1847 | 0 |             constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI, std::move(keys), k)); | 
| 1848 | 0 |         } | 
| 1849 | 0 |         return true; | 
| 1850 | 0 |     }; Unexecuted instantiation: miniscript.cpp:_ZZN10miniscript8internal5ParseI7CPubKeyN12_GLOBAL__N_113ParserContextEEENSt3__110unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISA_EEEENS5_4spanIKcLm18446744073709551615EEERKT0_ENKUlRSG_bE_clESK_bUnexecuted instantiation: descriptor.cpp:_ZZN10miniscript8internal5ParseIjN12_GLOBAL__N_19KeyParserEEENSt3__110unique_ptrIKNS_4NodeIT_EENS4_14default_deleteIS9_EEEENS4_4spanIKcLm18446744073709551615EEERKT0_ENKUlRSF_bE_clESJ_b | 
| 1851 |  | 
 | 
| 1852 | 0 |     while (!to_parse.empty()) { | 
| 1853 | 0 |         if (script_size > max_size) return {}; | 
| 1854 |  |  | 
| 1855 |  |         // Get the current context we are decoding within | 
| 1856 | 0 |         auto [cur_context, n, k] = to_parse.back(); | 
| 1857 | 0 |         to_parse.pop_back(); | 
| 1858 |  | 
 | 
| 1859 | 0 |         switch (cur_context) { | 
| 1860 | 0 |         case ParseContext::WRAPPED_EXPR: { | 
| 1861 | 0 |             std::optional<size_t> colon_index{}; | 
| 1862 | 0 |             for (size_t i = 1; i < in.size(); ++i) { | 
| 1863 | 0 |                 if (in[i] == ':') { | 
| 1864 | 0 |                     colon_index = i; | 
| 1865 | 0 |                     break; | 
| 1866 | 0 |                 } | 
| 1867 | 0 |                 if (in[i] < 'a' || in[i] > 'z') break; | 
| 1868 | 0 |             } | 
| 1869 |  |             // If there is no colon, this loop won't execute | 
| 1870 | 0 |             bool last_was_v{false}; | 
| 1871 | 0 |             for (size_t j = 0; colon_index && j < *colon_index; ++j) { | 
| 1872 | 0 |                 if (script_size > max_size) return {}; | 
| 1873 | 0 |                 if (in[j] == 'a') { | 
| 1874 | 0 |                     script_size += 2; | 
| 1875 | 0 |                     to_parse.emplace_back(ParseContext::ALT, -1, -1); | 
| 1876 | 0 |                 } else if (in[j] == 's') { | 
| 1877 | 0 |                     script_size += 1; | 
| 1878 | 0 |                     to_parse.emplace_back(ParseContext::SWAP, -1, -1); | 
| 1879 | 0 |                 } else if (in[j] == 'c') { | 
| 1880 | 0 |                     script_size += 1; | 
| 1881 | 0 |                     to_parse.emplace_back(ParseContext::CHECK, -1, -1); | 
| 1882 | 0 |                 } else if (in[j] == 'd') { | 
| 1883 | 0 |                     script_size += 3; | 
| 1884 | 0 |                     to_parse.emplace_back(ParseContext::DUP_IF, -1, -1); | 
| 1885 | 0 |                 } else if (in[j] == 'j') { | 
| 1886 | 0 |                     script_size += 4; | 
| 1887 | 0 |                     to_parse.emplace_back(ParseContext::NON_ZERO, -1, -1); | 
| 1888 | 0 |                 } else if (in[j] == 'n') { | 
| 1889 | 0 |                     script_size += 1; | 
| 1890 | 0 |                     to_parse.emplace_back(ParseContext::ZERO_NOTEQUAL, -1, -1); | 
| 1891 | 0 |                 } else if (in[j] == 'v') { | 
| 1892 |  |                     // do not permit "...vv...:"; it's not valid, and also doesn't trigger early | 
| 1893 |  |                     // failure as script_size isn't incremented. | 
| 1894 | 0 |                     if (last_was_v) return {}; | 
| 1895 | 0 |                     to_parse.emplace_back(ParseContext::VERIFY, -1, -1); | 
| 1896 | 0 |                 } else if (in[j] == 'u') { | 
| 1897 | 0 |                     script_size += 4; | 
| 1898 | 0 |                     to_parse.emplace_back(ParseContext::WRAP_U, -1, -1); | 
| 1899 | 0 |                 } else if (in[j] == 't') { | 
| 1900 | 0 |                     script_size += 1; | 
| 1901 | 0 |                     to_parse.emplace_back(ParseContext::WRAP_T, -1, -1); | 
| 1902 | 0 |                 } else if (in[j] == 'l') { | 
| 1903 |  |                     // The l: wrapper is equivalent to or_i(0,X) | 
| 1904 | 0 |                     script_size += 4; | 
| 1905 | 0 |                     constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0)); | 
| 1906 | 0 |                     to_parse.emplace_back(ParseContext::OR_I, -1, -1); | 
| 1907 | 0 |                 } else { | 
| 1908 | 0 |                     return {}; | 
| 1909 | 0 |                 } | 
| 1910 | 0 |                 last_was_v = (in[j] == 'v'); | 
| 1911 | 0 |             } | 
| 1912 | 0 |             to_parse.emplace_back(ParseContext::EXPR, -1, -1); | 
| 1913 | 0 |             if (colon_index) in = in.subspan(*colon_index + 1); | 
| 1914 | 0 |             break; | 
| 1915 | 0 |         } | 
| 1916 | 0 |         case ParseContext::EXPR: { | 
| 1917 | 0 |             if (Const("0", in)) { | 
| 1918 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0)); | 
| 1919 | 0 |             } else if (Const("1", in)) { | 
| 1920 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_1)); | 
| 1921 | 0 |             } else if (Const("pk(", in)) { | 
| 1922 | 0 |                 auto res = ParseKeyEnd<Key, Ctx>(in, ctx); | 
| 1923 | 0 |                 if (!res) return {}; | 
| 1924 | 0 |                 auto& [key, key_size] = *res; | 
| 1925 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_C, Vector(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_K, Vector(std::move(key)))))); | 
| 1926 | 0 |                 in = in.subspan(key_size + 1); | 
| 1927 | 0 |                 script_size += IsTapscript(ctx.MsContext()) ? 33 : 34; | 
| 1928 | 0 |             } else if (Const("pkh(", in)) { | 
| 1929 | 0 |                 auto res = ParseKeyEnd<Key>(in, ctx); | 
| 1930 | 0 |                 if (!res) return {}; | 
| 1931 | 0 |                 auto& [key, key_size] = *res; | 
| 1932 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_C, Vector(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_H, Vector(std::move(key)))))); | 
| 1933 | 0 |                 in = in.subspan(key_size + 1); | 
| 1934 | 0 |                 script_size += 24; | 
| 1935 | 0 |             } else if (Const("pk_k(", in)) { | 
| 1936 | 0 |                 auto res = ParseKeyEnd<Key>(in, ctx); | 
| 1937 | 0 |                 if (!res) return {}; | 
| 1938 | 0 |                 auto& [key, key_size] = *res; | 
| 1939 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_K, Vector(std::move(key)))); | 
| 1940 | 0 |                 in = in.subspan(key_size + 1); | 
| 1941 | 0 |                 script_size += IsTapscript(ctx.MsContext()) ? 32 : 33; | 
| 1942 | 0 |             } else if (Const("pk_h(", in)) { | 
| 1943 | 0 |                 auto res = ParseKeyEnd<Key>(in, ctx); | 
| 1944 | 0 |                 if (!res) return {}; | 
| 1945 | 0 |                 auto& [key, key_size] = *res; | 
| 1946 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_H, Vector(std::move(key)))); | 
| 1947 | 0 |                 in = in.subspan(key_size + 1); | 
| 1948 | 0 |                 script_size += 23; | 
| 1949 | 0 |             } else if (Const("sha256(", in)) { | 
| 1950 | 0 |                 auto res = ParseHexStrEnd(in, 32, ctx); | 
| 1951 | 0 |                 if (!res) return {}; | 
| 1952 | 0 |                 auto& [hash, hash_size] = *res; | 
| 1953 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::SHA256, std::move(hash))); | 
| 1954 | 0 |                 in = in.subspan(hash_size + 1); | 
| 1955 | 0 |                 script_size += 38; | 
| 1956 | 0 |             } else if (Const("ripemd160(", in)) { | 
| 1957 | 0 |                 auto res = ParseHexStrEnd(in, 20, ctx); | 
| 1958 | 0 |                 if (!res) return {}; | 
| 1959 | 0 |                 auto& [hash, hash_size] = *res; | 
| 1960 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::RIPEMD160, std::move(hash))); | 
| 1961 | 0 |                 in = in.subspan(hash_size + 1); | 
| 1962 | 0 |                 script_size += 26; | 
| 1963 | 0 |             } else if (Const("hash256(", in)) { | 
| 1964 | 0 |                 auto res = ParseHexStrEnd(in, 32, ctx); | 
| 1965 | 0 |                 if (!res) return {}; | 
| 1966 | 0 |                 auto& [hash, hash_size] = *res; | 
| 1967 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH256, std::move(hash))); | 
| 1968 | 0 |                 in = in.subspan(hash_size + 1); | 
| 1969 | 0 |                 script_size += 38; | 
| 1970 | 0 |             } else if (Const("hash160(", in)) { | 
| 1971 | 0 |                 auto res = ParseHexStrEnd(in, 20, ctx); | 
| 1972 | 0 |                 if (!res) return {}; | 
| 1973 | 0 |                 auto& [hash, hash_size] = *res; | 
| 1974 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH160, std::move(hash))); | 
| 1975 | 0 |                 in = in.subspan(hash_size + 1); | 
| 1976 | 0 |                 script_size += 26; | 
| 1977 | 0 |             } else if (Const("after(", in)) { | 
| 1978 | 0 |                 int arg_size = FindNextChar(in, ')'); | 
| 1979 | 0 |                 if (arg_size < 1) return {}; | 
| 1980 | 0 |                 const auto num{ToIntegral<int64_t>(std::string_view(in.data(), arg_size))}; | 
| 1981 | 0 |                 if (!num.has_value() || *num < 1 || *num >= 0x80000000L) return {}; | 
| 1982 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AFTER, *num)); | 
| 1983 | 0 |                 in = in.subspan(arg_size + 1); | 
| 1984 | 0 |                 script_size += 1 + (*num > 16) + (*num > 0x7f) + (*num > 0x7fff) + (*num > 0x7fffff); | 
| 1985 | 0 |             } else if (Const("older(", in)) { | 
| 1986 | 0 |                 int arg_size = FindNextChar(in, ')'); | 
| 1987 | 0 |                 if (arg_size < 1) return {}; | 
| 1988 | 0 |                 const auto num{ToIntegral<int64_t>(std::string_view(in.data(), arg_size))}; | 
| 1989 | 0 |                 if (!num.has_value() || *num < 1 || *num >= 0x80000000L) return {}; | 
| 1990 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OLDER, *num)); | 
| 1991 | 0 |                 in = in.subspan(arg_size + 1); | 
| 1992 | 0 |                 script_size += 1 + (*num > 16) + (*num > 0x7f) + (*num > 0x7fff) + (*num > 0x7fffff); | 
| 1993 | 0 |             } else if (Const("multi(", in)) { | 
| 1994 | 0 |                 if (!parse_multi_exp(in, /* is_multi_a = */false)) return {}; | 
| 1995 | 0 |             } else if (Const("multi_a(", in)) { | 
| 1996 | 0 |                 if (!parse_multi_exp(in, /* is_multi_a = */true)) return {}; | 
| 1997 | 0 |             } else if (Const("thresh(", in)) { | 
| 1998 | 0 |                 int next_comma = FindNextChar(in, ','); | 
| 1999 | 0 |                 if (next_comma < 1) return {}; | 
| 2000 | 0 |                 const auto k{ToIntegral<int64_t>(std::string_view(in.data(), next_comma))}; | 
| 2001 | 0 |                 if (!k.has_value() || *k < 1) return {}; | 
| 2002 | 0 |                 in = in.subspan(next_comma + 1); | 
| 2003 |  |                 // n = 1 here because we read the first WRAPPED_EXPR before reaching THRESH | 
| 2004 | 0 |                 to_parse.emplace_back(ParseContext::THRESH, 1, *k); | 
| 2005 | 0 |                 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1); | 
| 2006 | 0 |                 script_size += 2 + (*k > 16) + (*k > 0x7f) + (*k > 0x7fff) + (*k > 0x7fffff); | 
| 2007 | 0 |             } else if (Const("andor(", in)) { | 
| 2008 | 0 |                 to_parse.emplace_back(ParseContext::ANDOR, -1, -1); | 
| 2009 | 0 |                 to_parse.emplace_back(ParseContext::CLOSE_BRACKET, -1, -1); | 
| 2010 | 0 |                 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1); | 
| 2011 | 0 |                 to_parse.emplace_back(ParseContext::COMMA, -1, -1); | 
| 2012 | 0 |                 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1); | 
| 2013 | 0 |                 to_parse.emplace_back(ParseContext::COMMA, -1, -1); | 
| 2014 | 0 |                 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1); | 
| 2015 | 0 |                 script_size += 5; | 
| 2016 | 0 |             } else { | 
| 2017 | 0 |                 if (Const("and_n(", in)) { | 
| 2018 | 0 |                     to_parse.emplace_back(ParseContext::AND_N, -1, -1); | 
| 2019 | 0 |                     script_size += 5; | 
| 2020 | 0 |                 } else if (Const("and_b(", in)) { | 
| 2021 | 0 |                     to_parse.emplace_back(ParseContext::AND_B, -1, -1); | 
| 2022 | 0 |                     script_size += 2; | 
| 2023 | 0 |                 } else if (Const("and_v(", in)) { | 
| 2024 | 0 |                     to_parse.emplace_back(ParseContext::AND_V, -1, -1); | 
| 2025 | 0 |                     script_size += 1; | 
| 2026 | 0 |                 } else if (Const("or_b(", in)) { | 
| 2027 | 0 |                     to_parse.emplace_back(ParseContext::OR_B, -1, -1); | 
| 2028 | 0 |                     script_size += 2; | 
| 2029 | 0 |                 } else if (Const("or_c(", in)) { | 
| 2030 | 0 |                     to_parse.emplace_back(ParseContext::OR_C, -1, -1); | 
| 2031 | 0 |                     script_size += 3; | 
| 2032 | 0 |                 } else if (Const("or_d(", in)) { | 
| 2033 | 0 |                     to_parse.emplace_back(ParseContext::OR_D, -1, -1); | 
| 2034 | 0 |                     script_size += 4; | 
| 2035 | 0 |                 } else if (Const("or_i(", in)) { | 
| 2036 | 0 |                     to_parse.emplace_back(ParseContext::OR_I, -1, -1); | 
| 2037 | 0 |                     script_size += 4; | 
| 2038 | 0 |                 } else { | 
| 2039 | 0 |                     return {}; | 
| 2040 | 0 |                 } | 
| 2041 | 0 |                 to_parse.emplace_back(ParseContext::CLOSE_BRACKET, -1, -1); | 
| 2042 | 0 |                 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1); | 
| 2043 | 0 |                 to_parse.emplace_back(ParseContext::COMMA, -1, -1); | 
| 2044 | 0 |                 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1); | 
| 2045 | 0 |             } | 
| 2046 | 0 |             break; | 
| 2047 | 0 |         } | 
| 2048 | 0 |         case ParseContext::ALT: { | 
| 2049 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_A, Vector(std::move(constructed.back()))); | 
| 2050 | 0 |             break; | 
| 2051 | 0 |         } | 
| 2052 | 0 |         case ParseContext::SWAP: { | 
| 2053 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_S, Vector(std::move(constructed.back()))); | 
| 2054 | 0 |             break; | 
| 2055 | 0 |         } | 
| 2056 | 0 |         case ParseContext::CHECK: { | 
| 2057 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_C, Vector(std::move(constructed.back()))); | 
| 2058 | 0 |             break; | 
| 2059 | 0 |         } | 
| 2060 | 0 |         case ParseContext::DUP_IF: { | 
| 2061 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_D, Vector(std::move(constructed.back()))); | 
| 2062 | 0 |             break; | 
| 2063 | 0 |         } | 
| 2064 | 0 |         case ParseContext::NON_ZERO: { | 
| 2065 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_J, Vector(std::move(constructed.back()))); | 
| 2066 | 0 |             break; | 
| 2067 | 0 |         } | 
| 2068 | 0 |         case ParseContext::ZERO_NOTEQUAL: { | 
| 2069 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_N, Vector(std::move(constructed.back()))); | 
| 2070 | 0 |             break; | 
| 2071 | 0 |         } | 
| 2072 | 0 |         case ParseContext::VERIFY: { | 
| 2073 | 0 |             script_size += (constructed.back()->GetType() << "x"_mst); | 
| 2074 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_V, Vector(std::move(constructed.back()))); | 
| 2075 | 0 |             break; | 
| 2076 | 0 |         } | 
| 2077 | 0 |         case ParseContext::WRAP_U: { | 
| 2078 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OR_I, Vector(std::move(constructed.back()), MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0))); | 
| 2079 | 0 |             break; | 
| 2080 | 0 |         } | 
| 2081 | 0 |         case ParseContext::WRAP_T: { | 
| 2082 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AND_V, Vector(std::move(constructed.back()), MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_1))); | 
| 2083 | 0 |             break; | 
| 2084 | 0 |         } | 
| 2085 | 0 |         case ParseContext::AND_B: { | 
| 2086 | 0 |             BuildBack(ctx.MsContext(), Fragment::AND_B, constructed); | 
| 2087 | 0 |             break; | 
| 2088 | 0 |         } | 
| 2089 | 0 |         case ParseContext::AND_N: { | 
| 2090 | 0 |             auto mid = std::move(constructed.back()); | 
| 2091 | 0 |             constructed.pop_back(); | 
| 2092 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0))); | 
| 2093 | 0 |             break; | 
| 2094 | 0 |         } | 
| 2095 | 0 |         case ParseContext::AND_V: { | 
| 2096 | 0 |             BuildBack(ctx.MsContext(), Fragment::AND_V, constructed); | 
| 2097 | 0 |             break; | 
| 2098 | 0 |         } | 
| 2099 | 0 |         case ParseContext::OR_B: { | 
| 2100 | 0 |             BuildBack(ctx.MsContext(), Fragment::OR_B, constructed); | 
| 2101 | 0 |             break; | 
| 2102 | 0 |         } | 
| 2103 | 0 |         case ParseContext::OR_C: { | 
| 2104 | 0 |             BuildBack(ctx.MsContext(), Fragment::OR_C, constructed); | 
| 2105 | 0 |             break; | 
| 2106 | 0 |         } | 
| 2107 | 0 |         case ParseContext::OR_D: { | 
| 2108 | 0 |             BuildBack(ctx.MsContext(), Fragment::OR_D, constructed); | 
| 2109 | 0 |             break; | 
| 2110 | 0 |         } | 
| 2111 | 0 |         case ParseContext::OR_I: { | 
| 2112 | 0 |             BuildBack(ctx.MsContext(), Fragment::OR_I, constructed); | 
| 2113 | 0 |             break; | 
| 2114 | 0 |         } | 
| 2115 | 0 |         case ParseContext::ANDOR: { | 
| 2116 | 0 |             auto right = std::move(constructed.back()); | 
| 2117 | 0 |             constructed.pop_back(); | 
| 2118 | 0 |             auto mid = std::move(constructed.back()); | 
| 2119 | 0 |             constructed.pop_back(); | 
| 2120 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), std::move(right))); | 
| 2121 | 0 |             break; | 
| 2122 | 0 |         } | 
| 2123 | 0 |         case ParseContext::THRESH: { | 
| 2124 | 0 |             if (in.size() < 1) return {}; | 
| 2125 | 0 |             if (in[0] == ',') { | 
| 2126 | 0 |                 in = in.subspan(1); | 
| 2127 | 0 |                 to_parse.emplace_back(ParseContext::THRESH, n+1, k); | 
| 2128 | 0 |                 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1); | 
| 2129 | 0 |                 script_size += 2; | 
| 2130 | 0 |             } else if (in[0] == ')') { | 
| 2131 | 0 |                 if (k > n) return {}; | 
| 2132 | 0 |                 in = in.subspan(1); | 
| 2133 |  |                 // Children are constructed in reverse order, so iterate from end to beginning | 
| 2134 | 0 |                 std::vector<NodeRef<Key>> subs; | 
| 2135 | 0 |                 for (int i = 0; i < n; ++i) { | 
| 2136 | 0 |                     subs.push_back(std::move(constructed.back())); | 
| 2137 | 0 |                     constructed.pop_back(); | 
| 2138 | 0 |                 } | 
| 2139 | 0 |                 std::reverse(subs.begin(), subs.end()); | 
| 2140 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::THRESH, std::move(subs), k)); | 
| 2141 | 0 |             } else { | 
| 2142 | 0 |                 return {}; | 
| 2143 | 0 |             } | 
| 2144 | 0 |             break; | 
| 2145 | 0 |         } | 
| 2146 | 0 |         case ParseContext::COMMA: { | 
| 2147 | 0 |             if (in.size() < 1 || in[0] != ',') return {}; | 
| 2148 | 0 |             in = in.subspan(1); | 
| 2149 | 0 |             break; | 
| 2150 | 0 |         } | 
| 2151 | 0 |         case ParseContext::CLOSE_BRACKET: { | 
| 2152 | 0 |             if (in.size() < 1 || in[0] != ')') return {}; | 
| 2153 | 0 |             in = in.subspan(1); | 
| 2154 | 0 |             break; | 
| 2155 | 0 |         } | 
| 2156 | 0 |         } | 
| 2157 | 0 |     } | 
| 2158 |  |  | 
| 2159 |  |     // Sanity checks on the produced miniscript | 
| 2160 | 0 |     assert(constructed.size() >= 1); | 
| 2161 | 0 |     CHECK_NONFATAL(constructed.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 |     CHECK_NONFATAL(constructed.size() == 1); | Line | Count | Source |  | 103 | 0 |     inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) | 
 | 
| 2162 | 0 |     assert(constructed[0]->ScriptSize() == script_size); | 
| 2163 | 0 |     if (in.size() > 0) return {}; | 
| 2164 | 0 |     NodeRef<Key> tl_node = std::move(constructed.front()); | 
| 2165 | 0 |     tl_node->DuplicateKeyCheck(ctx); | 
| 2166 | 0 |     return tl_node; | 
| 2167 | 0 | } Unexecuted instantiation: miniscript.cpp:_ZN10miniscript8internal5ParseI7CPubKeyN12_GLOBAL__N_113ParserContextEEENSt3__110unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISA_EEEENS5_4spanIKcLm18446744073709551615EEERKT0_Unexecuted instantiation: descriptor.cpp:_ZN10miniscript8internal5ParseIjN12_GLOBAL__N_19KeyParserEEENSt3__110unique_ptrIKNS_4NodeIT_EENS4_14default_deleteIS9_EEEENS4_4spanIKcLm18446744073709551615EEERKT0_ | 
| 2168 |  |  | 
| 2169 |  | /** Decode a script into opcode/push pairs. | 
| 2170 |  |  * | 
| 2171 |  |  * Construct a vector with one element per opcode in the script, in reverse order. | 
| 2172 |  |  * Each element is a pair consisting of the opcode, as well as the data pushed by | 
| 2173 |  |  * the opcode (including OP_n), if any. OP_CHECKSIGVERIFY, OP_CHECKMULTISIGVERIFY, | 
| 2174 |  |  * OP_NUMEQUALVERIFY and OP_EQUALVERIFY are decomposed into OP_CHECKSIG, OP_CHECKMULTISIG, | 
| 2175 |  |  * OP_EQUAL and OP_NUMEQUAL respectively, plus OP_VERIFY. | 
| 2176 |  |  */ | 
| 2177 |  | std::optional<std::vector<Opcode>> DecomposeScript(const CScript& script); | 
| 2178 |  |  | 
| 2179 |  | /** Determine whether the passed pair (created by DecomposeScript) is pushing a number. */ | 
| 2180 |  | std::optional<int64_t> ParseScriptNumber(const Opcode& in); | 
| 2181 |  |  | 
| 2182 |  | enum class DecodeContext { | 
| 2183 |  |     /** A single expression of type B, K, or V. Specifically, this can't be an | 
| 2184 |  |      * and_v or an expression of type W (a: and s: wrappers). */ | 
| 2185 |  |     SINGLE_BKV_EXPR, | 
| 2186 |  |     /** Potentially multiple SINGLE_BKV_EXPRs as children of (potentially multiple) | 
| 2187 |  |      * and_v expressions. Syntactic sugar for MAYBE_AND_V + SINGLE_BKV_EXPR. */ | 
| 2188 |  |     BKV_EXPR, | 
| 2189 |  |     /** An expression of type W (a: or s: wrappers). */ | 
| 2190 |  |     W_EXPR, | 
| 2191 |  |  | 
| 2192 |  |     /** SWAP expects the next element to be OP_SWAP (inside a W-type expression that | 
| 2193 |  |      * didn't end with FROMALTSTACK), and wraps the top of the constructed stack | 
| 2194 |  |      * with s: */ | 
| 2195 |  |     SWAP, | 
| 2196 |  |     /** ALT expects the next element to be TOALTSTACK (we must have already read a | 
| 2197 |  |      * FROMALTSTACK earlier), and wraps the top of the constructed stack with a: */ | 
| 2198 |  |     ALT, | 
| 2199 |  |     /** CHECK wraps the top constructed node with c: */ | 
| 2200 |  |     CHECK, | 
| 2201 |  |     /** DUP_IF wraps the top constructed node with d: */ | 
| 2202 |  |     DUP_IF, | 
| 2203 |  |     /** VERIFY wraps the top constructed node with v: */ | 
| 2204 |  |     VERIFY, | 
| 2205 |  |     /** NON_ZERO wraps the top constructed node with j: */ | 
| 2206 |  |     NON_ZERO, | 
| 2207 |  |     /** ZERO_NOTEQUAL wraps the top constructed node with n: */ | 
| 2208 |  |     ZERO_NOTEQUAL, | 
| 2209 |  |  | 
| 2210 |  |     /** MAYBE_AND_V will check if the next part of the script could be a valid | 
| 2211 |  |      * miniscript sub-expression, and if so it will push AND_V and SINGLE_BKV_EXPR | 
| 2212 |  |      * to decode it and construct the and_v node. This is recursive, to deal with | 
| 2213 |  |      * multiple and_v nodes inside each other. */ | 
| 2214 |  |     MAYBE_AND_V, | 
| 2215 |  |     /** AND_V will construct an and_v node from the last two constructed nodes. */ | 
| 2216 |  |     AND_V, | 
| 2217 |  |     /** AND_B will construct an and_b node from the last two constructed nodes. */ | 
| 2218 |  |     AND_B, | 
| 2219 |  |     /** ANDOR will construct an andor node from the last three constructed nodes. */ | 
| 2220 |  |     ANDOR, | 
| 2221 |  |     /** OR_B will construct an or_b node from the last two constructed nodes. */ | 
| 2222 |  |     OR_B, | 
| 2223 |  |     /** OR_C will construct an or_c node from the last two constructed nodes. */ | 
| 2224 |  |     OR_C, | 
| 2225 |  |     /** OR_D will construct an or_d node from the last two constructed nodes. */ | 
| 2226 |  |     OR_D, | 
| 2227 |  |  | 
| 2228 |  |     /** In a thresh expression, all sub-expressions other than the first are W-type, | 
| 2229 |  |      * and end in OP_ADD. THRESH_W will check for this OP_ADD and either push a W_EXPR | 
| 2230 |  |      * or a SINGLE_BKV_EXPR and jump to THRESH_E accordingly. */ | 
| 2231 |  |     THRESH_W, | 
| 2232 |  |     /** THRESH_E constructs a thresh node from the appropriate number of constructed | 
| 2233 |  |      * children. */ | 
| 2234 |  |     THRESH_E, | 
| 2235 |  |  | 
| 2236 |  |     /** ENDIF signals that we are inside some sort of OP_IF structure, which could be | 
| 2237 |  |      * or_d, or_c, or_i, andor, d:, or j: wrapper, depending on what follows. We read | 
| 2238 |  |      * a BKV_EXPR and then deal with the next opcode case-by-case. */ | 
| 2239 |  |     ENDIF, | 
| 2240 |  |     /** If, inside an ENDIF context, we find an OP_NOTIF before finding an OP_ELSE, | 
| 2241 |  |      * we could either be in an or_d or an or_c node. We then check for IFDUP to | 
| 2242 |  |      * distinguish these cases. */ | 
| 2243 |  |     ENDIF_NOTIF, | 
| 2244 |  |     /** If, inside an ENDIF context, we find an OP_ELSE, then we could be in either an | 
| 2245 |  |      * or_i or an andor node. Read the next BKV_EXPR and find either an OP_IF or an | 
| 2246 |  |      * OP_NOTIF. */ | 
| 2247 |  |     ENDIF_ELSE, | 
| 2248 |  | }; | 
| 2249 |  |  | 
| 2250 |  | //! Parse a miniscript from a bitcoin script | 
| 2251 |  | template<typename Key, typename Ctx, typename I> | 
| 2252 |  | inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx) | 
| 2253 | 0 | { | 
| 2254 |  |     // The two integers are used to hold state for thresh() | 
| 2255 | 0 |     std::vector<std::tuple<DecodeContext, int64_t, int64_t>> to_parse; | 
| 2256 | 0 |     std::vector<NodeRef<Key>> constructed; | 
| 2257 |  |  | 
| 2258 |  |     // This is the top level, so we assume the type is B | 
| 2259 |  |     // (in particular, disallowing top level W expressions) | 
| 2260 | 0 |     to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1); | 
| 2261 |  | 
 | 
| 2262 | 0 |     while (!to_parse.empty()) { | 
| 2263 |  |         // Exit early if the Miniscript is not going to be valid. | 
| 2264 | 0 |         if (!constructed.empty() && !constructed.back()->IsValid()) return {}; | 
| 2265 |  |  | 
| 2266 |  |         // Get the current context we are decoding within | 
| 2267 | 0 |         auto [cur_context, n, k] = to_parse.back(); | 
| 2268 | 0 |         to_parse.pop_back(); | 
| 2269 |  | 
 | 
| 2270 | 0 |         switch(cur_context) { | 
| 2271 | 0 |         case DecodeContext::SINGLE_BKV_EXPR: { | 
| 2272 | 0 |             if (in >= last) return {}; | 
| 2273 |  |  | 
| 2274 |  |             // Constants | 
| 2275 | 0 |             if (in[0].first == OP_1) { | 
| 2276 | 0 |                 ++in; | 
| 2277 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_1)); | 
| 2278 | 0 |                 break; | 
| 2279 | 0 |             } | 
| 2280 | 0 |             if (in[0].first == OP_0) { | 
| 2281 | 0 |                 ++in; | 
| 2282 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0)); | 
| 2283 | 0 |                 break; | 
| 2284 | 0 |             } | 
| 2285 |  |             // Public keys | 
| 2286 | 0 |             if (in[0].second.size() == 33 || in[0].second.size() == 32) { | 
| 2287 | 0 |                 auto key = ctx.FromPKBytes(in[0].second.begin(), in[0].second.end()); | 
| 2288 | 0 |                 if (!key) return {}; | 
| 2289 | 0 |                 ++in; | 
| 2290 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_K, Vector(std::move(*key)))); | 
| 2291 | 0 |                 break; | 
| 2292 | 0 |             } | 
| 2293 | 0 |             if (last - in >= 5 && in[0].first == OP_VERIFY && in[1].first == OP_EQUAL && in[3].first == OP_HASH160 && in[4].first == OP_DUP && in[2].second.size() == 20) { | 
| 2294 | 0 |                 auto key = ctx.FromPKHBytes(in[2].second.begin(), in[2].second.end()); | 
| 2295 | 0 |                 if (!key) return {}; | 
| 2296 | 0 |                 in += 5; | 
| 2297 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_H, Vector(std::move(*key)))); | 
| 2298 | 0 |                 break; | 
| 2299 | 0 |             } | 
| 2300 |  |             // Time locks | 
| 2301 | 0 |             std::optional<int64_t> num; | 
| 2302 | 0 |             if (last - in >= 2 && in[0].first == OP_CHECKSEQUENCEVERIFY && (num = ParseScriptNumber(in[1]))) { | 
| 2303 | 0 |                 in += 2; | 
| 2304 | 0 |                 if (*num < 1 || *num > 0x7FFFFFFFL) return {}; | 
| 2305 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OLDER, *num)); | 
| 2306 | 0 |                 break; | 
| 2307 | 0 |             } | 
| 2308 | 0 |             if (last - in >= 2 && in[0].first == OP_CHECKLOCKTIMEVERIFY && (num = ParseScriptNumber(in[1]))) { | 
| 2309 | 0 |                 in += 2; | 
| 2310 | 0 |                 if (num < 1 || num > 0x7FFFFFFFL) return {}; | 
| 2311 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AFTER, *num)); | 
| 2312 | 0 |                 break; | 
| 2313 | 0 |             } | 
| 2314 |  |             // Hashes | 
| 2315 | 0 |             if (last - in >= 7 && in[0].first == OP_EQUAL && in[3].first == OP_VERIFY && in[4].first == OP_EQUAL && (num = ParseScriptNumber(in[5])) && num == 32 && in[6].first == OP_SIZE) { | 
| 2316 | 0 |                 if (in[2].first == OP_SHA256 && in[1].second.size() == 32) { | 
| 2317 | 0 |                     constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::SHA256, in[1].second)); | 
| 2318 | 0 |                     in += 7; | 
| 2319 | 0 |                     break; | 
| 2320 | 0 |                 } else if (in[2].first == OP_RIPEMD160 && in[1].second.size() == 20) { | 
| 2321 | 0 |                     constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::RIPEMD160, in[1].second)); | 
| 2322 | 0 |                     in += 7; | 
| 2323 | 0 |                     break; | 
| 2324 | 0 |                 } else if (in[2].first == OP_HASH256 && in[1].second.size() == 32) { | 
| 2325 | 0 |                     constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH256, in[1].second)); | 
| 2326 | 0 |                     in += 7; | 
| 2327 | 0 |                     break; | 
| 2328 | 0 |                 } else if (in[2].first == OP_HASH160 && in[1].second.size() == 20) { | 
| 2329 | 0 |                     constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH160, in[1].second)); | 
| 2330 | 0 |                     in += 7; | 
| 2331 | 0 |                     break; | 
| 2332 | 0 |                 } | 
| 2333 | 0 |             } | 
| 2334 |  |             // Multi | 
| 2335 | 0 |             if (last - in >= 3 && in[0].first == OP_CHECKMULTISIG) { | 
| 2336 | 0 |                 if (IsTapscript(ctx.MsContext())) return {}; | 
| 2337 | 0 |                 std::vector<Key> keys; | 
| 2338 | 0 |                 const auto n = ParseScriptNumber(in[1]); | 
| 2339 | 0 |                 if (!n || last - in < 3 + *n) return {}; | 
| 2340 | 0 |                 if (*n < 1 || *n > 20) return {}; | 
| 2341 | 0 |                 for (int i = 0; i < *n; ++i) { | 
| 2342 | 0 |                     if (in[2 + i].second.size() != 33) return {}; | 
| 2343 | 0 |                     auto key = ctx.FromPKBytes(in[2 + i].second.begin(), in[2 + i].second.end()); | 
| 2344 | 0 |                     if (!key) return {}; | 
| 2345 | 0 |                     keys.push_back(std::move(*key)); | 
| 2346 | 0 |                 } | 
| 2347 | 0 |                 const auto k = ParseScriptNumber(in[2 + *n]); | 
| 2348 | 0 |                 if (!k || *k < 1 || *k > *n) return {}; | 
| 2349 | 0 |                 in += 3 + *n; | 
| 2350 | 0 |                 std::reverse(keys.begin(), keys.end()); | 
| 2351 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI, std::move(keys), *k)); | 
| 2352 | 0 |                 break; | 
| 2353 | 0 |             } | 
| 2354 |  |             // Tapscript's equivalent of multi | 
| 2355 | 0 |             if (last - in >= 4 && in[0].first == OP_NUMEQUAL) { | 
| 2356 | 0 |                 if (!IsTapscript(ctx.MsContext())) return {}; | 
| 2357 |  |                 // The necessary threshold of signatures. | 
| 2358 | 0 |                 const auto k = ParseScriptNumber(in[1]); | 
| 2359 | 0 |                 if (!k) return {}; | 
| 2360 | 0 |                 if (*k < 1 || *k > MAX_PUBKEYS_PER_MULTI_A) return {}; | 
| 2361 | 0 |                 if (last - in < 2 + *k * 2) return {}; | 
| 2362 | 0 |                 std::vector<Key> keys; | 
| 2363 | 0 |                 keys.reserve(*k); | 
| 2364 |  |                 // Walk through the expected (pubkey, CHECKSIG[ADD]) pairs. | 
| 2365 | 0 |                 for (int pos = 2;; pos += 2) { | 
| 2366 | 0 |                     if (last - in < pos + 2) return {}; | 
| 2367 |  |                     // Make sure it's indeed an x-only pubkey and a CHECKSIG[ADD], then parse the key. | 
| 2368 | 0 |                     if (in[pos].first != OP_CHECKSIGADD && in[pos].first != OP_CHECKSIG) return {}; | 
| 2369 | 0 |                     if (in[pos + 1].second.size() != 32) return {}; | 
| 2370 | 0 |                     auto key = ctx.FromPKBytes(in[pos + 1].second.begin(), in[pos + 1].second.end()); | 
| 2371 | 0 |                     if (!key) return {}; | 
| 2372 | 0 |                     keys.push_back(std::move(*key)); | 
| 2373 |  |                     // Make sure early we don't parse an arbitrary large expression. | 
| 2374 | 0 |                     if (keys.size() > MAX_PUBKEYS_PER_MULTI_A) return {}; | 
| 2375 |  |                     // OP_CHECKSIG means it was the last one to parse. | 
| 2376 | 0 |                     if (in[pos].first == OP_CHECKSIG) break; | 
| 2377 | 0 |                 } | 
| 2378 | 0 |                 if (keys.size() < (size_t)*k) return {}; | 
| 2379 | 0 |                 in += 2 + keys.size() * 2; | 
| 2380 | 0 |                 std::reverse(keys.begin(), keys.end()); | 
| 2381 | 0 |                 constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI_A, std::move(keys), *k)); | 
| 2382 | 0 |                 break; | 
| 2383 | 0 |             } | 
| 2384 |  |             /** In the following wrappers, we only need to push SINGLE_BKV_EXPR rather | 
| 2385 |  |              * than BKV_EXPR, because and_v commutes with these wrappers. For example, | 
| 2386 |  |              * c:and_v(X,Y) produces the same script as and_v(X,c:Y). */ | 
| 2387 |  |             // c: wrapper | 
| 2388 | 0 |             if (in[0].first == OP_CHECKSIG) { | 
| 2389 | 0 |                 ++in; | 
| 2390 | 0 |                 to_parse.emplace_back(DecodeContext::CHECK, -1, -1); | 
| 2391 | 0 |                 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1); | 
| 2392 | 0 |                 break; | 
| 2393 | 0 |             } | 
| 2394 |  |             // v: wrapper | 
| 2395 | 0 |             if (in[0].first == OP_VERIFY) { | 
| 2396 | 0 |                 ++in; | 
| 2397 | 0 |                 to_parse.emplace_back(DecodeContext::VERIFY, -1, -1); | 
| 2398 | 0 |                 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1); | 
| 2399 | 0 |                 break; | 
| 2400 | 0 |             } | 
| 2401 |  |             // n: wrapper | 
| 2402 | 0 |             if (in[0].first == OP_0NOTEQUAL) { | 
| 2403 | 0 |                 ++in; | 
| 2404 | 0 |                 to_parse.emplace_back(DecodeContext::ZERO_NOTEQUAL, -1, -1); | 
| 2405 | 0 |                 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1); | 
| 2406 | 0 |                 break; | 
| 2407 | 0 |             } | 
| 2408 |  |             // Thresh | 
| 2409 | 0 |             if (last - in >= 3 && in[0].first == OP_EQUAL && (num = ParseScriptNumber(in[1]))) { | 
| 2410 | 0 |                 if (*num < 1) return {}; | 
| 2411 | 0 |                 in += 2; | 
| 2412 | 0 |                 to_parse.emplace_back(DecodeContext::THRESH_W, 0, *num); | 
| 2413 | 0 |                 break; | 
| 2414 | 0 |             } | 
| 2415 |  |             // OP_ENDIF can be WRAP_J, WRAP_D, ANDOR, OR_C, OR_D, or OR_I | 
| 2416 | 0 |             if (in[0].first == OP_ENDIF) { | 
| 2417 | 0 |                 ++in; | 
| 2418 | 0 |                 to_parse.emplace_back(DecodeContext::ENDIF, -1, -1); | 
| 2419 | 0 |                 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1); | 
| 2420 | 0 |                 break; | 
| 2421 | 0 |             } | 
| 2422 |  |             /** In and_b and or_b nodes, we only look for SINGLE_BKV_EXPR, because | 
| 2423 |  |              * or_b(and_v(X,Y),Z) has script [X] [Y] [Z] OP_BOOLOR, the same as | 
| 2424 |  |              * and_v(X,or_b(Y,Z)). In this example, the former of these is invalid as | 
| 2425 |  |              * miniscript, while the latter is valid. So we leave the and_v "outside" | 
| 2426 |  |              * while decoding. */ | 
| 2427 |  |             // and_b | 
| 2428 | 0 |             if (in[0].first == OP_BOOLAND) { | 
| 2429 | 0 |                 ++in; | 
| 2430 | 0 |                 to_parse.emplace_back(DecodeContext::AND_B, -1, -1); | 
| 2431 | 0 |                 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1); | 
| 2432 | 0 |                 to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1); | 
| 2433 | 0 |                 break; | 
| 2434 | 0 |             } | 
| 2435 |  |             // or_b | 
| 2436 | 0 |             if (in[0].first == OP_BOOLOR) { | 
| 2437 | 0 |                 ++in; | 
| 2438 | 0 |                 to_parse.emplace_back(DecodeContext::OR_B, -1, -1); | 
| 2439 | 0 |                 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1); | 
| 2440 | 0 |                 to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1); | 
| 2441 | 0 |                 break; | 
| 2442 | 0 |             } | 
| 2443 |  |             // Unrecognised expression | 
| 2444 | 0 |             return {}; | 
| 2445 | 0 |         } | 
| 2446 | 0 |         case DecodeContext::BKV_EXPR: { | 
| 2447 | 0 |             to_parse.emplace_back(DecodeContext::MAYBE_AND_V, -1, -1); | 
| 2448 | 0 |             to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1); | 
| 2449 | 0 |             break; | 
| 2450 | 0 |         } | 
| 2451 | 0 |         case DecodeContext::W_EXPR: { | 
| 2452 |  |             // a: wrapper | 
| 2453 | 0 |             if (in >= last) return {}; | 
| 2454 | 0 |             if (in[0].first == OP_FROMALTSTACK) { | 
| 2455 | 0 |                 ++in; | 
| 2456 | 0 |                 to_parse.emplace_back(DecodeContext::ALT, -1, -1); | 
| 2457 | 0 |             } else { | 
| 2458 | 0 |                 to_parse.emplace_back(DecodeContext::SWAP, -1, -1); | 
| 2459 | 0 |             } | 
| 2460 | 0 |             to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1); | 
| 2461 | 0 |             break; | 
| 2462 | 0 |         } | 
| 2463 | 0 |         case DecodeContext::MAYBE_AND_V: { | 
| 2464 |  |             // If we reach a potential AND_V top-level, check if the next part of the script could be another AND_V child | 
| 2465 |  |             // These op-codes cannot end any well-formed miniscript so cannot be used in an and_v node. | 
| 2466 | 0 |             if (in < last && in[0].first != OP_IF && in[0].first != OP_ELSE && in[0].first != OP_NOTIF && in[0].first != OP_TOALTSTACK && in[0].first != OP_SWAP) { | 
| 2467 | 0 |                 to_parse.emplace_back(DecodeContext::AND_V, -1, -1); | 
| 2468 |  |                 // BKV_EXPR can contain more AND_V nodes | 
| 2469 | 0 |                 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1); | 
| 2470 | 0 |             } | 
| 2471 | 0 |             break; | 
| 2472 | 0 |         } | 
| 2473 | 0 |         case DecodeContext::SWAP: { | 
| 2474 | 0 |             if (in >= last || in[0].first != OP_SWAP || constructed.empty()) return {}; | 
| 2475 | 0 |             ++in; | 
| 2476 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_S, Vector(std::move(constructed.back()))); | 
| 2477 | 0 |             break; | 
| 2478 | 0 |         } | 
| 2479 | 0 |         case DecodeContext::ALT: { | 
| 2480 | 0 |             if (in >= last || in[0].first != OP_TOALTSTACK || constructed.empty()) return {}; | 
| 2481 | 0 |             ++in; | 
| 2482 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_A, Vector(std::move(constructed.back()))); | 
| 2483 | 0 |             break; | 
| 2484 | 0 |         } | 
| 2485 | 0 |         case DecodeContext::CHECK: { | 
| 2486 | 0 |             if (constructed.empty()) return {}; | 
| 2487 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_C, Vector(std::move(constructed.back()))); | 
| 2488 | 0 |             break; | 
| 2489 | 0 |         } | 
| 2490 | 0 |         case DecodeContext::DUP_IF: { | 
| 2491 | 0 |             if (constructed.empty()) return {}; | 
| 2492 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_D, Vector(std::move(constructed.back()))); | 
| 2493 | 0 |             break; | 
| 2494 | 0 |         } | 
| 2495 | 0 |         case DecodeContext::VERIFY: { | 
| 2496 | 0 |             if (constructed.empty()) return {}; | 
| 2497 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_V, Vector(std::move(constructed.back()))); | 
| 2498 | 0 |             break; | 
| 2499 | 0 |         } | 
| 2500 | 0 |         case DecodeContext::NON_ZERO: { | 
| 2501 | 0 |             if (constructed.empty()) return {}; | 
| 2502 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_J, Vector(std::move(constructed.back()))); | 
| 2503 | 0 |             break; | 
| 2504 | 0 |         } | 
| 2505 | 0 |         case DecodeContext::ZERO_NOTEQUAL: { | 
| 2506 | 0 |             if (constructed.empty()) return {}; | 
| 2507 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_N, Vector(std::move(constructed.back()))); | 
| 2508 | 0 |             break; | 
| 2509 | 0 |         } | 
| 2510 | 0 |         case DecodeContext::AND_V: { | 
| 2511 | 0 |             if (constructed.size() < 2) return {}; | 
| 2512 | 0 |             BuildBack(ctx.MsContext(), Fragment::AND_V, constructed, /*reverse=*/true); | 
| 2513 | 0 |             break; | 
| 2514 | 0 |         } | 
| 2515 | 0 |         case DecodeContext::AND_B: { | 
| 2516 | 0 |             if (constructed.size() < 2) return {}; | 
| 2517 | 0 |             BuildBack(ctx.MsContext(), Fragment::AND_B, constructed, /*reverse=*/true); | 
| 2518 | 0 |             break; | 
| 2519 | 0 |         } | 
| 2520 | 0 |         case DecodeContext::OR_B: { | 
| 2521 | 0 |             if (constructed.size() < 2) return {}; | 
| 2522 | 0 |             BuildBack(ctx.MsContext(), Fragment::OR_B, constructed, /*reverse=*/true); | 
| 2523 | 0 |             break; | 
| 2524 | 0 |         } | 
| 2525 | 0 |         case DecodeContext::OR_C: { | 
| 2526 | 0 |             if (constructed.size() < 2) return {}; | 
| 2527 | 0 |             BuildBack(ctx.MsContext(), Fragment::OR_C, constructed, /*reverse=*/true); | 
| 2528 | 0 |             break; | 
| 2529 | 0 |         } | 
| 2530 | 0 |         case DecodeContext::OR_D: { | 
| 2531 | 0 |             if (constructed.size() < 2) return {}; | 
| 2532 | 0 |             BuildBack(ctx.MsContext(), Fragment::OR_D, constructed, /*reverse=*/true); | 
| 2533 | 0 |             break; | 
| 2534 | 0 |         } | 
| 2535 | 0 |         case DecodeContext::ANDOR: { | 
| 2536 | 0 |             if (constructed.size() < 3) return {}; | 
| 2537 | 0 |             NodeRef<Key> left = std::move(constructed.back()); | 
| 2538 | 0 |             constructed.pop_back(); | 
| 2539 | 0 |             NodeRef<Key> right = std::move(constructed.back()); | 
| 2540 | 0 |             constructed.pop_back(); | 
| 2541 | 0 |             NodeRef<Key> mid = std::move(constructed.back()); | 
| 2542 | 0 |             constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::ANDOR, Vector(std::move(left), std::move(mid), std::move(right))); | 
| 2543 | 0 |             break; | 
| 2544 | 0 |         } | 
| 2545 | 0 |         case DecodeContext::THRESH_W: { | 
| 2546 | 0 |             if (in >= last) return {}; | 
| 2547 | 0 |             if (in[0].first == OP_ADD) { | 
| 2548 | 0 |                 ++in; | 
| 2549 | 0 |                 to_parse.emplace_back(DecodeContext::THRESH_W, n+1, k); | 
| 2550 | 0 |                 to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1); | 
| 2551 | 0 |             } else { | 
| 2552 | 0 |                 to_parse.emplace_back(DecodeContext::THRESH_E, n+1, k); | 
| 2553 |  |                 // All children of thresh have type modifier d, so cannot be and_v | 
| 2554 | 0 |                 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1); | 
| 2555 | 0 |             } | 
| 2556 | 0 |             break; | 
| 2557 | 0 |         } | 
| 2558 | 0 |         case DecodeContext::THRESH_E: { | 
| 2559 | 0 |             if (k < 1 || k > n || constructed.size() < static_cast<size_t>(n)) return {}; | 
| 2560 | 0 |             std::vector<NodeRef<Key>> subs; | 
| 2561 | 0 |             for (int i = 0; i < n; ++i) { | 
| 2562 | 0 |                 NodeRef<Key> sub = std::move(constructed.back()); | 
| 2563 | 0 |                 constructed.pop_back(); | 
| 2564 | 0 |                 subs.push_back(std::move(sub)); | 
| 2565 | 0 |             } | 
| 2566 | 0 |             constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::THRESH, std::move(subs), k)); | 
| 2567 | 0 |             break; | 
| 2568 | 0 |         } | 
| 2569 | 0 |         case DecodeContext::ENDIF: { | 
| 2570 | 0 |             if (in >= last) return {}; | 
| 2571 |  |  | 
| 2572 |  |             // could be andor or or_i | 
| 2573 | 0 |             if (in[0].first == OP_ELSE) { | 
| 2574 | 0 |                 ++in; | 
| 2575 | 0 |                 to_parse.emplace_back(DecodeContext::ENDIF_ELSE, -1, -1); | 
| 2576 | 0 |                 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1); | 
| 2577 | 0 |             } | 
| 2578 |  |             // could be j: or d: wrapper | 
| 2579 | 0 |             else if (in[0].first == OP_IF) { | 
| 2580 | 0 |                 if (last - in >= 2 && in[1].first == OP_DUP) { | 
| 2581 | 0 |                     in += 2; | 
| 2582 | 0 |                     to_parse.emplace_back(DecodeContext::DUP_IF, -1, -1); | 
| 2583 | 0 |                 } else if (last - in >= 3 && in[1].first == OP_0NOTEQUAL && in[2].first == OP_SIZE) { | 
| 2584 | 0 |                     in += 3; | 
| 2585 | 0 |                     to_parse.emplace_back(DecodeContext::NON_ZERO, -1, -1); | 
| 2586 | 0 |                 } | 
| 2587 | 0 |                 else { | 
| 2588 | 0 |                     return {}; | 
| 2589 | 0 |                 } | 
| 2590 |  |             // could be or_c or or_d | 
| 2591 | 0 |             } else if (in[0].first == OP_NOTIF) { | 
| 2592 | 0 |                 ++in; | 
| 2593 | 0 |                 to_parse.emplace_back(DecodeContext::ENDIF_NOTIF, -1, -1); | 
| 2594 | 0 |             } | 
| 2595 | 0 |             else { | 
| 2596 | 0 |                 return {}; | 
| 2597 | 0 |             } | 
| 2598 | 0 |             break; | 
| 2599 | 0 |         } | 
| 2600 | 0 |         case DecodeContext::ENDIF_NOTIF: { | 
| 2601 | 0 |             if (in >= last) return {}; | 
| 2602 | 0 |             if (in[0].first == OP_IFDUP) { | 
| 2603 | 0 |                 ++in; | 
| 2604 | 0 |                 to_parse.emplace_back(DecodeContext::OR_D, -1, -1); | 
| 2605 | 0 |             } else { | 
| 2606 | 0 |                 to_parse.emplace_back(DecodeContext::OR_C, -1, -1); | 
| 2607 | 0 |             } | 
| 2608 |  |             // or_c and or_d both require X to have type modifier d so, can't contain and_v | 
| 2609 | 0 |             to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1); | 
| 2610 | 0 |             break; | 
| 2611 | 0 |         } | 
| 2612 | 0 |         case DecodeContext::ENDIF_ELSE: { | 
| 2613 | 0 |             if (in >= last) return {}; | 
| 2614 | 0 |             if (in[0].first == OP_IF) { | 
| 2615 | 0 |                 ++in; | 
| 2616 | 0 |                 BuildBack(ctx.MsContext(), Fragment::OR_I, constructed, /*reverse=*/true); | 
| 2617 | 0 |             } else if (in[0].first == OP_NOTIF) { | 
| 2618 | 0 |                 ++in; | 
| 2619 | 0 |                 to_parse.emplace_back(DecodeContext::ANDOR, -1, -1); | 
| 2620 |  |                 // andor requires X to have type modifier d, so it can't be and_v | 
| 2621 | 0 |                 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1); | 
| 2622 | 0 |             } else { | 
| 2623 | 0 |                 return {}; | 
| 2624 | 0 |             } | 
| 2625 | 0 |             break; | 
| 2626 | 0 |         } | 
| 2627 | 0 |         } | 
| 2628 | 0 |     } | 
| 2629 | 0 |     if (constructed.size() != 1) return {}; | 
| 2630 | 0 |     NodeRef<Key> tl_node = std::move(constructed.front()); | 
| 2631 | 0 |     tl_node->DuplicateKeyCheck(ctx); | 
| 2632 |  |     // Note that due to how ComputeType works (only assign the type to the node if the | 
| 2633 |  |     // subs' types are valid) this would fail if any node of tree is badly typed. | 
| 2634 | 0 |     if (!tl_node->IsValidTopLevel()) return {}; | 
| 2635 | 0 |     return tl_node; | 
| 2636 | 0 | } Unexecuted instantiation: miniscript.cpp:_ZN10miniscript8internal12DecodeScriptI7CPubKeyN12_GLOBAL__N_113ParserContextENSt3__111__wrap_iterIPNS5_4pairI10opcodetypeNS5_6vectorIhNS5_9allocatorIhEEEEEEEEEENS5_10unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISK_EEEERT1_SO_RKT0_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript8internal12DecodeScriptIN12_GLOBAL__N_119ScriptParserContext3KeyES3_NSt3__111__wrap_iterIPNS5_4pairI10opcodetypeNS5_6vectorIhNS5_9allocatorIhEEEEEEEEEENS5_10unique_ptrIKNS_4NodeIT_EENS5_14default_deleteISK_EEEERT1_SO_RKT0_Unexecuted instantiation: descriptor.cpp:_ZN10miniscript8internal12DecodeScriptIjN12_GLOBAL__N_19KeyParserENSt3__111__wrap_iterIPNS4_4pairI10opcodetypeNS4_6vectorIhNS4_9allocatorIhEEEEEEEEEENS4_10unique_ptrIKNS_4NodeIT_EENS4_14default_deleteISJ_EEEERT1_SN_RKT0_Unexecuted instantiation: _ZN10miniscript8internal12DecodeScriptI11XOnlyPubKey12TapSatisfierNSt3__111__wrap_iterIPNS4_4pairI10opcodetypeNS4_6vectorIhNS4_9allocatorIhEEEEEEEEEENS4_10unique_ptrIKNS_4NodeIT_EENS4_14default_deleteISJ_EEEERT1_SN_RKT0_Unexecuted instantiation: _ZN10miniscript8internal12DecodeScriptI7CPubKey12WshSatisfierNSt3__111__wrap_iterIPNS4_4pairI10opcodetypeNS4_6vectorIhNS4_9allocatorIhEEEEEEEEEENS4_10unique_ptrIKNS_4NodeIT_EENS4_14default_deleteISJ_EEEERT1_SN_RKT0_ | 
| 2637 |  |  | 
| 2638 |  | } // namespace internal | 
| 2639 |  |  | 
| 2640 |  | template<typename Ctx> | 
| 2641 | 0 | inline NodeRef<typename Ctx::Key> FromString(const std::string& str, const Ctx& ctx) { | 
| 2642 | 0 |     return internal::Parse<typename Ctx::Key>(str, ctx); | 
| 2643 | 0 | } Unexecuted instantiation: miniscript.cpp:_ZN10miniscript10FromStringIN12_GLOBAL__N_113ParserContextEEENSt3__110unique_ptrIKNS_4NodeINT_3KeyEEENS3_14default_deleteIS9_EEEERKNS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERKS6_Unexecuted instantiation: descriptor.cpp:_ZN10miniscript10FromStringIN12_GLOBAL__N_19KeyParserEEENSt3__110unique_ptrIKNS_4NodeINT_3KeyEEENS3_14default_deleteIS9_EEEERKNS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERKS6_ | 
| 2644 |  |  | 
| 2645 |  | template<typename Ctx> | 
| 2646 | 0 | inline NodeRef<typename Ctx::Key> FromScript(const CScript& script, const Ctx& ctx) { | 
| 2647 | 0 |     using namespace internal; | 
| 2648 |  |     // A too large Script is necessarily invalid, don't bother parsing it. | 
| 2649 | 0 |     if (script.size() > MaxScriptSize(ctx.MsContext())) return {}; | 
| 2650 | 0 |     auto decomposed = DecomposeScript(script); | 
| 2651 | 0 |     if (!decomposed) return {}; | 
| 2652 | 0 |     auto it = decomposed->begin(); | 
| 2653 | 0 |     auto ret = DecodeScript<typename Ctx::Key>(it, decomposed->end(), ctx); | 
| 2654 | 0 |     if (!ret) return {}; | 
| 2655 | 0 |     if (it != decomposed->end()) return {}; | 
| 2656 | 0 |     return ret; | 
| 2657 | 0 | } Unexecuted instantiation: miniscript.cpp:_ZN10miniscript10FromScriptIN12_GLOBAL__N_113ParserContextEEENSt3__110unique_ptrIKNS_4NodeINT_3KeyEEENS3_14default_deleteIS9_EEEERK7CScriptRKS6_Unexecuted instantiation: miniscript.cpp:_ZN10miniscript10FromScriptIN12_GLOBAL__N_119ScriptParserContextEEENSt3__110unique_ptrIKNS_4NodeINT_3KeyEEENS3_14default_deleteIS9_EEEERK7CScriptRKS6_Unexecuted instantiation: descriptor.cpp:_ZN10miniscript10FromScriptIN12_GLOBAL__N_19KeyParserEEENSt3__110unique_ptrIKNS_4NodeINT_3KeyEEENS3_14default_deleteIS9_EEEERK7CScriptRKS6_Unexecuted instantiation: _ZN10miniscript10FromScriptI12TapSatisfierEENSt3__110unique_ptrIKNS_4NodeINT_3KeyEEENS2_14default_deleteIS8_EEEERK7CScriptRKS5_Unexecuted instantiation: _ZN10miniscript10FromScriptI12WshSatisfierEENSt3__110unique_ptrIKNS_4NodeINT_3KeyEEENS2_14default_deleteIS8_EEEERK7CScriptRKS5_ | 
| 2658 |  |  | 
| 2659 |  | } // namespace miniscript | 
| 2660 |  |  | 
| 2661 |  | #endif // BITCOIN_SCRIPT_MINISCRIPT_H |