LCOV - code coverage report
Current view: top level - src/script - miniscript.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 291 306 95.1 %
Date: 2022-04-21 14:51:19 Functions: 6 6 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 337 396 85.1 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2019 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                 :            : #include <string>
#       6                 :            : #include <vector>
#       7                 :            : #include <script/script.h>
#       8                 :            : #include <script/standard.h>
#       9                 :            : #include <script/miniscript.h>
#      10                 :            : 
#      11                 :            : #include <assert.h>
#      12                 :            : 
#      13                 :            : namespace miniscript {
#      14                 :            : namespace internal {
#      15                 :            : 
#      16                 :       2054 : Type SanitizeType(Type e) {
#      17                 :       2054 :     int num_types = (e << "K"_mst) + (e << "V"_mst) + (e << "B"_mst) + (e << "W"_mst);
#      18         [ +  + ]:       2054 :     if (num_types == 0) return ""_mst; // No valid type, don't care about the rest
#      19                 :       1994 :     assert(num_types == 1); // K, V, B, W all conflict with each other
#      20                 :          0 :     bool ok = // Work around a GCC 4.8 bug that breaks user-defined literals in macro calls.
#      21 [ +  + ][ +  - ]:       1994 :         (!(e << "z"_mst) || !(e << "o"_mst)) && // z conflicts with o
#      22 [ +  + ][ +  - ]:       1994 :         (!(e << "n"_mst) || !(e << "z"_mst)) && // n conflicts with z
#      23 [ +  + ][ +  - ]:       1994 :         (!(e << "n"_mst) || !(e << "W"_mst)) && // n conflicts with W
#      24 [ +  + ][ +  - ]:       1994 :         (!(e << "V"_mst) || !(e << "d"_mst)) && // V conflicts with d
#      25 [ +  + ][ +  - ]:       1994 :         (!(e << "K"_mst) ||  (e << "u"_mst)) && // K implies u
#      26 [ +  + ][ +  - ]:       1994 :         (!(e << "V"_mst) || !(e << "u"_mst)) && // V conflicts with u
#      27 [ +  + ][ +  - ]:       1994 :         (!(e << "e"_mst) || !(e << "f"_mst)) && // e conflicts with f
#      28 [ +  + ][ +  - ]:       1994 :         (!(e << "e"_mst) ||  (e << "d"_mst)) && // e implies d
#      29 [ +  + ][ +  - ]:       1994 :         (!(e << "V"_mst) || !(e << "e"_mst)) && // V conflicts with e
#      30 [ +  + ][ +  - ]:       1994 :         (!(e << "d"_mst) || !(e << "f"_mst)) && // d conflicts with f
#      31 [ +  + ][ +  - ]:       1994 :         (!(e << "V"_mst) ||  (e << "f"_mst)) && // V implies f
#      32 [ +  + ][ +  - ]:       1994 :         (!(e << "K"_mst) ||  (e << "s"_mst)) && // K implies s
#      33 [ +  + ][ +  - ]:       1994 :         (!(e << "z"_mst) ||  (e << "m"_mst)); // z implies m
#      34                 :       1994 :     assert(ok);
#      35                 :          0 :     return e;
#      36                 :       2054 : }
#      37                 :            : 
#      38                 :       2054 : Type ComputeType(Fragment nodetype, 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) {
#      39                 :            :     // Sanity check on data
#      40 [ +  + ][ +  + ]:       2054 :     if (nodetype == Fragment::SHA256 || nodetype == Fragment::HASH256) {
#      41                 :         76 :         assert(data_size == 32);
#      42 [ +  + ][ +  + ]:       1978 :     } else if (nodetype == Fragment::RIPEMD160 || nodetype == Fragment::HASH160) {
#      43                 :         28 :         assert(data_size == 20);
#      44                 :       1950 :     } else {
#      45                 :       1950 :         assert(data_size == 0);
#      46                 :       1950 :     }
#      47                 :            :     // Sanity check on k
#      48 [ +  + ][ +  + ]:       2054 :     if (nodetype == Fragment::OLDER || nodetype == Fragment::AFTER) {
#      49                 :        226 :         assert(k >= 1 && k < 0x80000000UL);
#      50         [ +  + ]:       1828 :     } else if (nodetype == Fragment::MULTI) {
#      51                 :         50 :         assert(k >= 1 && k <= n_keys);
#      52         [ +  + ]:       1778 :     } else if (nodetype == Fragment::THRESH) {
#      53                 :         32 :         assert(k >= 1 && k <= n_subs);
#      54                 :       1746 :     } else {
#      55                 :       1746 :         assert(k == 0);
#      56                 :       1746 :     }
#      57                 :            :     // Sanity check on subs
#      58 [ +  + ][ +  + ]:       2054 :     if (nodetype == Fragment::AND_V || nodetype == Fragment::AND_B || nodetype == Fragment::OR_B ||
#                 [ +  + ]
#      59 [ +  + ][ +  + ]:       2054 :         nodetype == Fragment::OR_C || nodetype == Fragment::OR_I || nodetype == Fragment::OR_D) {
#                 [ +  + ]
#      60                 :        470 :         assert(n_subs == 2);
#      61         [ +  + ]:       1584 :     } else if (nodetype == Fragment::ANDOR) {
#      62                 :         68 :         assert(n_subs == 3);
#      63 [ +  + ][ +  + ]:       1516 :     } else if (nodetype == Fragment::WRAP_A || nodetype == Fragment::WRAP_S || nodetype == Fragment::WRAP_C ||
#                 [ +  + ]
#      64 [ +  + ][ +  + ]:       1516 :                nodetype == Fragment::WRAP_D || nodetype == Fragment::WRAP_V || nodetype == Fragment::WRAP_J ||
#                 [ +  + ]
#      65         [ +  + ]:       1516 :                nodetype == Fragment::WRAP_N) {
#      66                 :        504 :         assert(n_subs == 1);
#      67         [ +  + ]:       1012 :     } else if (nodetype != Fragment::THRESH) {
#      68                 :        980 :         assert(n_subs == 0);
#      69                 :        980 :     }
#      70                 :            :     // Sanity check on keys
#      71 [ +  + ][ +  + ]:       2054 :     if (nodetype == Fragment::PK_K || nodetype == Fragment::PK_H) {
#      72                 :        150 :         assert(n_keys == 1);
#      73         [ +  + ]:       1904 :     } else if (nodetype == Fragment::MULTI) {
#      74                 :         50 :         assert(n_keys >= 1 && n_keys <= 20);
#      75                 :       1854 :     } else {
#      76                 :       1854 :         assert(n_keys == 0);
#      77                 :       1854 :     }
#      78                 :            : 
#      79                 :            :     // Below is the per-nodetype logic for computing the expression types.
#      80                 :            :     // It heavily relies on Type's << operator (where "X << a_mst" means
#      81                 :            :     // "X has all properties listed in a").
#      82         [ -  + ]:          0 :     switch (nodetype) {
#      83         [ +  + ]:         98 :         case Fragment::PK_K: return "Konudemsxk"_mst;
#      84         [ +  + ]:         52 :         case Fragment::PK_H: return "Knudemsxk"_mst;
#      85         [ +  + ]:         88 :         case Fragment::OLDER: return
#      86                 :         88 :             "g"_mst.If(k & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) |
#      87                 :         88 :             "h"_mst.If(!(k & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG)) |
#      88                 :         88 :             "Bzfmxk"_mst;
#      89         [ +  + ]:        138 :         case Fragment::AFTER: return
#      90                 :        138 :             "i"_mst.If(k >= LOCKTIME_THRESHOLD) |
#      91                 :        138 :             "j"_mst.If(k < LOCKTIME_THRESHOLD) |
#      92                 :        138 :             "Bzfmxk"_mst;
#      93         [ +  + ]:         48 :         case Fragment::SHA256: return "Bonudmk"_mst;
#      94         [ +  + ]:         16 :         case Fragment::RIPEMD160: return "Bonudmk"_mst;
#      95         [ +  + ]:         28 :         case Fragment::HASH256: return "Bonudmk"_mst;
#      96         [ +  + ]:         12 :         case Fragment::HASH160: return "Bonudmk"_mst;
#      97         [ +  + ]:        234 :         case Fragment::JUST_1: return "Bzufmxk"_mst;
#      98         [ +  + ]:        216 :         case Fragment::JUST_0: return "Bzudemsxk"_mst;
#      99         [ +  + ]:        128 :         case Fragment::WRAP_A: return
#     100                 :        128 :             "W"_mst.If(x << "B"_mst) | // W=B_x
#     101                 :        128 :             (x & "ghijk"_mst) | // g=g_x, h=h_x, i=i_x, j=j_x, k=k_x
#     102                 :        128 :             (x & "udfems"_mst) | // u=u_x, d=d_x, f=f_x, e=e_x, m=m_x, s=s_x
#     103                 :        128 :             "x"_mst; // x
#     104         [ +  + ]:         22 :         case Fragment::WRAP_S: return
#     105                 :         22 :             "W"_mst.If(x << "Bo"_mst) | // W=B_x*o_x
#     106                 :         22 :             (x & "ghijk"_mst) | // g=g_x, h=h_x, i=i_x, j=j_x, k=k_x
#     107                 :         22 :             (x & "udfemsx"_mst); // u=u_x, d=d_x, f=f_x, e=e_x, m=m_x, s=s_x, x=x_x
#     108         [ +  + ]:        112 :         case Fragment::WRAP_C: return
#     109                 :        112 :             "B"_mst.If(x << "K"_mst) | // B=K_x
#     110                 :        112 :             (x & "ghijk"_mst) | // g=g_x, h=h_x, i=i_x, j=j_x, k=k_x
#     111                 :        112 :             (x & "ondfem"_mst) | // o=o_x, n=n_x, d=d_x, f=f_x, e=e_x, m=m_x
#     112                 :        112 :             "us"_mst; // u, s
#     113         [ +  + ]:          8 :         case Fragment::WRAP_D: return
#     114                 :          8 :             "B"_mst.If(x << "Vz"_mst) | // B=V_x*z_x
#     115                 :          8 :             "o"_mst.If(x << "z"_mst) | // o=z_x
#     116                 :          8 :             "e"_mst.If(x << "f"_mst) | // e=f_x
#     117                 :          8 :             (x & "ghijk"_mst) | // g=g_x, h=h_x, i=i_x, j=j_x, k=k_x
#     118                 :          8 :             (x & "ms"_mst) | // m=m_x, s=s_x
#     119                 :          8 :             "nudx"_mst; // n, u, d, x
#     120         [ +  + ]:        186 :         case Fragment::WRAP_V: return
#     121                 :        186 :             "V"_mst.If(x << "B"_mst) | // V=B_x
#     122                 :        186 :             (x & "ghijk"_mst) | // g=g_x, h=h_x, i=i_x, j=j_x, k=k_x
#     123                 :        186 :             (x & "zonms"_mst) | // z=z_x, o=o_x, n=n_x, m=m_x, s=s_x
#     124                 :        186 :             "fx"_mst; // f, x
#     125         [ +  + ]:         20 :         case Fragment::WRAP_J: return
#     126                 :         20 :             "B"_mst.If(x << "Bn"_mst) | // B=B_x*n_x
#     127                 :         20 :             "e"_mst.If(x << "f"_mst) | // e=f_x
#     128                 :         20 :             (x & "ghijk"_mst) | // g=g_x, h=h_x, i=i_x, j=j_x, k=k_x
#     129                 :         20 :             (x & "oums"_mst) | // o=o_x, u=u_x, m=m_x, s=s_x
#     130                 :         20 :             "ndx"_mst; // n, d, x
#     131         [ +  + ]:         28 :         case Fragment::WRAP_N: return
#     132                 :         28 :             (x & "ghijk"_mst) | // g=g_x, h=h_x, i=i_x, j=j_x, k=k_x
#     133                 :         28 :             (x & "Bzondfems"_mst) | // B=B_x, z=z_x, o=o_x, n=n_x, d=d_x, f=f_x, e=e_x, m=m_x, s=s_x
#     134                 :         28 :             "ux"_mst; // u, x
#     135         [ +  + ]:        154 :         case Fragment::AND_V: return
#     136                 :        154 :             (y & "KVB"_mst).If(x << "V"_mst) | // B=V_x*B_y, V=V_x*V_y, K=V_x*K_y
#     137                 :        154 :             (x & "n"_mst) | (y & "n"_mst).If(x << "z"_mst) | // n=n_x+z_x*n_y
#     138                 :        154 :             ((x | y) & "o"_mst).If((x | y) << "z"_mst) | // o=o_x*z_y+z_x*o_y
#     139                 :        154 :             (x & y & "dmz"_mst) | // d=d_x*d_y, m=m_x*m_y, z=z_x*z_y
#     140                 :        154 :             ((x | y) & "s"_mst) | // s=s_x+s_y
#     141 [ +  + ][ +  + ]:        154 :             "f"_mst.If((y << "f"_mst) || (x << "s"_mst)) | // f=f_y+s_x
#     142                 :        154 :             (y & "ux"_mst) | // u=u_y, x=x_y
#     143                 :        154 :             ((x | y) & "ghij"_mst) | // g=g_x+g_y, h=h_x+h_y, i=i_x+i_y, j=j_x+j_y
#     144         [ +  + ]:        154 :             "k"_mst.If(((x & y) << "k"_mst) &&
#     145 [ +  + ][ -  + ]:        154 :                 !(((x << "g"_mst) && (y << "h"_mst)) ||
#     146 [ +  + ][ -  + ]:        146 :                 ((x << "h"_mst) && (y << "g"_mst)) ||
#     147 [ +  + ][ -  + ]:        146 :                 ((x << "i"_mst) && (y << "j"_mst)) ||
#     148 [ +  + ][ -  + ]:        146 :                 ((x << "j"_mst) && (y << "i"_mst)))); // k=k_x*k_y*!(g_x*h_y + h_x*g_y + i_x*j_y + j_x*i_y)
#     149         [ +  + ]:         40 :         case Fragment::AND_B: return
#     150                 :         40 :             (x & "B"_mst).If(y << "W"_mst) | // B=B_x*W_y
#     151                 :         40 :             ((x | y) & "o"_mst).If((x | y) << "z"_mst) | // o=o_x*z_y+z_x*o_y
#     152                 :         40 :             (x & "n"_mst) | (y & "n"_mst).If(x << "z"_mst) | // n=n_x+z_x*n_y
#     153                 :         40 :             (x & y & "e"_mst).If((x & y) << "s"_mst) | // e=e_x*e_y*s_x*s_y
#     154                 :         40 :             (x & y & "dzm"_mst) | // d=d_x*d_y, z=z_x*z_y, m=m_x*m_y
#     155 [ +  + ][ -  + ]:         40 :             "f"_mst.If(((x & y) << "f"_mst) || (x << "sf"_mst) || (y << "sf"_mst)) | // f=f_x*f_y + f_x*s_x + f_y*s_y
#                 [ -  + ]
#     156                 :         40 :             ((x | y) & "s"_mst) | // s=s_x+s_y
#     157                 :         40 :             "ux"_mst | // u, x
#     158                 :         40 :             ((x | y) & "ghij"_mst) | // g=g_x+g_y, h=h_x+h_y, i=i_x+i_y, j=j_x+j_y
#     159         [ +  - ]:         40 :             "k"_mst.If(((x & y) << "k"_mst) &&
#     160 [ +  + ][ +  - ]:         40 :                 !(((x << "g"_mst) && (y << "h"_mst)) ||
#     161 [ +  + ][ -  + ]:         40 :                 ((x << "h"_mst) && (y << "g"_mst)) ||
#     162 [ -  + ][ #  # ]:         40 :                 ((x << "i"_mst) && (y << "j"_mst)) ||
#     163 [ +  + ][ +  - ]:         40 :                 ((x << "j"_mst) && (y << "i"_mst)))); // k=k_x*k_y*!(g_x*h_y + h_x*g_y + i_x*j_y + j_x*i_y)
#     164         [ +  + ]:         32 :         case Fragment::OR_B: return
#     165 [ +  + ][ +  + ]:         32 :             "B"_mst.If(x << "Bd"_mst && y << "Wd"_mst) | // B=B_x*d_x*W_x*d_y
#     166                 :         32 :             ((x | y) & "o"_mst).If((x | y) << "z"_mst) | // o=o_x*z_y+z_x*o_y
#     167 [ +  + ][ +  + ]:         32 :             (x & y & "m"_mst).If((x | y) << "s"_mst && (x & y) << "e"_mst) | // m=m_x*m_y*e_x*e_y*(s_x+s_y)
#     168                 :         32 :             (x & y & "zse"_mst) | // z=z_x*z_y, s=s_x*s_y, e=e_x*e_y
#     169                 :         32 :             "dux"_mst | // d, u, x
#     170                 :         32 :             ((x | y) & "ghij"_mst) | // g=g_x+g_y, h=h_x+h_y, i=i_x+i_y, j=j_x+j_y
#     171                 :         32 :             (x & y & "k"_mst); // k=k_x*k_y
#     172         [ +  + ]:         40 :         case Fragment::OR_D: return
#     173                 :         40 :             (y & "B"_mst).If(x << "Bdu"_mst) | // B=B_y*B_x*d_x*u_x
#     174                 :         40 :             (x & "o"_mst).If(y << "z"_mst) | // o=o_x*z_y
#     175 [ +  + ][ +  + ]:         40 :             (x & y & "m"_mst).If(x << "e"_mst && (x | y) << "s"_mst) | // m=m_x*m_y*e_x*(s_x+s_y)
#     176                 :         40 :             (x & y & "zes"_mst) | // z=z_x*z_y, e=e_x*e_y, s=s_x*s_y
#     177                 :         40 :             (y & "ufd"_mst) | // u=u_y, f=f_y, d=d_y
#     178                 :         40 :             "x"_mst | // x
#     179                 :         40 :             ((x | y) & "ghij"_mst) | // g=g_x+g_y, h=h_x+h_y, i=i_x+i_y, j=j_x+j_y
#     180                 :         40 :             (x & y & "k"_mst); // k=k_x*k_y
#     181         [ +  + ]:         24 :         case Fragment::OR_C: return
#     182                 :         24 :             (y & "V"_mst).If(x << "Bdu"_mst) | // V=V_y*B_x*u_x*d_x
#     183                 :         24 :             (x & "o"_mst).If(y << "z"_mst) | // o=o_x*z_y
#     184 [ +  + ][ +  + ]:         24 :             (x & y & "m"_mst).If(x << "e"_mst && (x | y) << "s"_mst) | // m=m_x*m_y*e_x*(s_x+s_y)
#     185                 :         24 :             (x & y & "zs"_mst) | // z=z_x*z_y, s=s_x*s_y
#     186                 :         24 :             "fx"_mst | // f, x
#     187                 :         24 :             ((x | y) & "ghij"_mst) | // g=g_x+g_y, h=h_x+h_y, i=i_x+i_y, j=j_x+j_y
#     188                 :         24 :             (x & y & "k"_mst); // k=k_x*k_y
#     189         [ +  + ]:        180 :         case Fragment::OR_I: return
#     190                 :        180 :             (x & y & "VBKufs"_mst) | // V=V_x*V_y, B=B_x*B_y, K=K_x*K_y, u=u_x*u_y, f=f_x*f_y, s=s_x*s_y
#     191                 :        180 :             "o"_mst.If((x & y) << "z"_mst) | // o=z_x*z_y
#     192                 :        180 :             ((x | y) & "e"_mst).If((x | y) << "f"_mst) | // e=e_x*f_y+f_x*e_y
#     193                 :        180 :             (x & y & "m"_mst).If((x | y) << "s"_mst) | // m=m_x*m_y*(s_x+s_y)
#     194                 :        180 :             ((x | y) & "d"_mst) | // d=d_x+d_y
#     195                 :        180 :             "x"_mst | // x
#     196                 :        180 :             ((x | y) & "ghij"_mst) | // g=g_x+g_y, h=h_x+h_y, i=i_x+i_y, j=j_x+j_y
#     197                 :        180 :             (x & y & "k"_mst); // k=k_x*k_y
#     198         [ +  + ]:         68 :         case Fragment::ANDOR: return
#     199                 :         68 :             (y & z & "BKV"_mst).If(x << "Bdu"_mst) | // B=B_x*d_x*u_x*B_y*B_z, K=B_x*d_x*u_x*K_y*K_z, V=B_x*d_x*u_x*V_y*V_z
#     200                 :         68 :             (x & y & z & "z"_mst) | // z=z_x*z_y*z_z
#     201                 :         68 :             ((x | (y & z)) & "o"_mst).If((x | (y & z)) << "z"_mst) | // o=o_x*z_y*z_z+z_x*o_y*o_z
#     202                 :         68 :             (y & z & "u"_mst) | // u=u_y*u_z
#     203 [ +  + ][ +  + ]:         68 :             (z & "f"_mst).If((x << "s"_mst) || (y << "f"_mst)) | // f=(s_x+f_y)*f_z
#     204                 :         68 :             (z & "d"_mst) | // d=d_z
#     205 [ +  + ][ +  + ]:         68 :             (x & z & "e"_mst).If(x << "s"_mst || y << "f"_mst) | // e=e_x*e_z*(s_x+f_y)
#     206 [ +  + ][ +  + ]:         68 :             (x & y & z & "m"_mst).If(x << "e"_mst && (x | y | z) << "s"_mst) | // m=m_x*m_y*m_z*e_x*(s_x+s_y+s_z)
#     207                 :         68 :             (z & (x | y) & "s"_mst) | // s=s_z*(s_x+s_y)
#     208                 :         68 :             "x"_mst | // x
#     209                 :         68 :             ((x | y | z) & "ghij"_mst) | // g=g_x+g_y+g_z, h=h_x+h_y+h_z, i=i_x+i_y+i_z, j=j_x+j_y_j_z
#     210         [ +  + ]:         68 :             "k"_mst.If(((x & y & z) << "k"_mst) &&
#     211 [ -  + ][ #  # ]:         68 :                 !(((x << "g"_mst) && (y << "h"_mst)) ||
#     212 [ -  + ][ #  # ]:         64 :                 ((x << "h"_mst) && (y << "g"_mst)) ||
#     213 [ -  + ][ #  # ]:         64 :                 ((x << "i"_mst) && (y << "j"_mst)) ||
#     214 [ +  + ][ -  + ]:         64 :                 ((x << "j"_mst) && (y << "i"_mst)))); // k=k_x*k_y*k_z* !(g_x*h_y + h_x*g_y + i_x*j_y + j_x*i_y)
#     215         [ +  + ]:         50 :         case Fragment::MULTI: return "Bnudemsk"_mst;
#     216         [ +  + ]:         32 :         case Fragment::THRESH: {
#     217                 :         32 :             bool all_e = true;
#     218                 :         32 :             bool all_m = true;
#     219                 :         32 :             uint32_t args = 0;
#     220                 :         32 :             uint32_t num_s = 0;
#     221                 :         32 :             Type acc_tl = "k"_mst;
#     222         [ +  + ]:        124 :             for (size_t i = 0; i < sub_types.size(); ++i) {
#     223                 :         92 :                 Type t = sub_types[i];
#     224 [ -  + ][ +  + ]:         92 :                 if (!(t << (i ? "Wdu"_mst : "Bdu"_mst))) return ""_mst; // Require Bdu, Wdu, Wdu, ...
#     225         [ +  + ]:         92 :                 if (!(t << "e"_mst)) all_e = false;
#     226         [ -  + ]:         92 :                 if (!(t << "m"_mst)) all_m = false;
#     227         [ +  + ]:         92 :                 if (t << "s"_mst) num_s += 1;
#     228 [ -  + ][ +  + ]:         92 :                 args += (t << "z"_mst) ? 0 : (t << "o"_mst) ? 1 : 2;
#     229                 :         92 :                 acc_tl = ((acc_tl | t) & "ghij"_mst) |
#     230                 :            :                     // Thresh contains a combination of timelocks if it has threshold > 1 and
#     231                 :            :                     // it contains two different children that have different types of timelocks
#     232                 :            :                     // Note how if any of the children don't have "k", the parent also does not have "k"
#     233 [ +  + ][ +  + ]:         92 :                     "k"_mst.If(((acc_tl & t) << "k"_mst) && ((k <= 1) ||
#     234 [ +  - ][ -  + ]:         88 :                         ((k > 1) && !(((acc_tl << "g"_mst) && (t << "h"_mst)) ||
#                 [ #  # ]
#     235 [ -  + ][ #  # ]:         56 :                         ((acc_tl << "h"_mst) && (t << "g"_mst)) ||
#     236 [ +  + ][ +  - ]:         56 :                         ((acc_tl << "i"_mst) && (t << "j"_mst)) ||
#     237 [ -  + ][ #  # ]:         56 :                         ((acc_tl << "j"_mst) && (t << "i"_mst))))));
#     238                 :         92 :             }
#     239                 :         32 :             return "Bdu"_mst |
#     240                 :         32 :                    "z"_mst.If(args == 0) | // z=all z
#     241                 :         32 :                    "o"_mst.If(args == 1) | // o=all z except one o
#     242 [ +  + ][ +  + ]:         32 :                    "e"_mst.If(all_e && num_s == n_subs) | // e=all e and all s
#     243 [ +  + ][ +  - ]:         32 :                    "m"_mst.If(all_e && all_m && num_s >= n_subs - k) | // m=all e, >=(n-k) s
#                 [ +  + ]
#     244                 :         32 :                    "s"_mst.If(num_s >= n_subs - k + 1) |  // s= >=(n-k+1) s
#     245                 :         32 :                    acc_tl; // timelock info
#     246                 :         32 :             }
#     247                 :       2054 :     }
#     248                 :          0 :     assert(false);
#     249                 :          0 :     return ""_mst;
#     250                 :       2054 : }
#     251                 :            : 
#     252                 :       2054 : size_t ComputeScriptLen(Fragment nodetype, Type sub0typ, size_t subsize, uint32_t k, size_t n_subs, size_t n_keys) {
#     253         [ -  + ]:       2054 :     switch (nodetype) {
#     254         [ +  + ]:        234 :         case Fragment::JUST_1:
#     255         [ +  + ]:        450 :         case Fragment::JUST_0: return 1;
#     256         [ +  + ]:         98 :         case Fragment::PK_K: return 34;
#     257         [ +  + ]:         52 :         case Fragment::PK_H: return 3 + 21;
#     258         [ +  + ]:         88 :         case Fragment::OLDER:
#     259         [ +  + ]:        226 :         case Fragment::AFTER: return 1 + BuildScript(k).size();
#     260         [ +  + ]:         28 :         case Fragment::HASH256:
#     261         [ +  + ]:         76 :         case Fragment::SHA256: return 4 + 2 + 33;
#     262         [ +  + ]:         12 :         case Fragment::HASH160:
#     263         [ +  + ]:         28 :         case Fragment::RIPEMD160: return 4 + 2 + 21;
#     264         [ +  + ]:         50 :         case Fragment::MULTI: return 3 + (n_keys > 16) + (k > 16) + 34 * n_keys;
#     265         [ +  + ]:        154 :         case Fragment::AND_V: return subsize;
#     266         [ +  + ]:        186 :         case Fragment::WRAP_V: return subsize + (sub0typ << "x"_mst);
#     267         [ +  + ]:         22 :         case Fragment::WRAP_S:
#     268         [ +  + ]:        134 :         case Fragment::WRAP_C:
#     269         [ +  + ]:        162 :         case Fragment::WRAP_N:
#     270         [ +  + ]:        202 :         case Fragment::AND_B:
#     271         [ +  + ]:        234 :         case Fragment::OR_B: return subsize + 1;
#     272         [ +  + ]:        128 :         case Fragment::WRAP_A:
#     273         [ +  + ]:        152 :         case Fragment::OR_C: return subsize + 2;
#     274         [ +  + ]:          8 :         case Fragment::WRAP_D:
#     275         [ +  + ]:         48 :         case Fragment::OR_D:
#     276         [ +  + ]:        228 :         case Fragment::OR_I:
#     277         [ +  + ]:        296 :         case Fragment::ANDOR: return subsize + 3;
#     278         [ +  + ]:         20 :         case Fragment::WRAP_J: return subsize + 4;
#     279         [ +  + ]:         32 :         case Fragment::THRESH: return subsize + n_subs + BuildScript(k).size();
#     280                 :       2054 :     }
#     281                 :          0 :     assert(false);
#     282                 :          0 :     return 0;
#     283                 :       2054 : }
#     284                 :            : 
#     285                 :            : bool DecomposeScript(const CScript& script, std::vector<std::pair<opcodetype, std::vector<unsigned char>>>& out)
#     286                 :        130 : {
#     287                 :        130 :     out.clear();
#     288                 :        130 :     CScript::const_iterator it = script.begin(), itend = script.end();
#     289         [ +  + ]:       1888 :     while (it != itend) {
#     290                 :       1762 :         std::vector<unsigned char> push_data;
#     291                 :       1762 :         opcodetype opcode;
#     292         [ -  + ]:       1762 :         if (!script.GetOp(it, opcode, push_data)) {
#     293                 :          0 :             out.clear();
#     294                 :          0 :             return false;
#     295 [ +  + ][ +  + ]:       1762 :         } else if (opcode >= OP_1 && opcode <= OP_16) {
#     296                 :            :             // Deal with OP_n (GetOp does not turn them into pushes).
#     297                 :        166 :             push_data.assign(1, CScript::DecodeOP_N(opcode));
#     298         [ -  + ]:       1596 :         } else if (opcode == OP_CHECKSIGVERIFY) {
#     299                 :            :             // Decompose OP_CHECKSIGVERIFY into OP_CHECKSIG OP_VERIFY
#     300                 :          0 :             out.emplace_back(OP_CHECKSIG, std::vector<unsigned char>());
#     301                 :          0 :             opcode = OP_VERIFY;
#     302         [ +  + ]:       1596 :         } else if (opcode == OP_CHECKMULTISIGVERIFY) {
#     303                 :            :             // Decompose OP_CHECKMULTISIGVERIFY into OP_CHECKMULTISIG OP_VERIFY
#     304                 :          8 :             out.emplace_back(OP_CHECKMULTISIG, std::vector<unsigned char>());
#     305                 :          8 :             opcode = OP_VERIFY;
#     306         [ +  + ]:       1588 :         } else if (opcode == OP_EQUALVERIFY) {
#     307                 :            :             // Decompose OP_EQUALVERIFY into OP_EQUAL OP_VERIFY
#     308                 :         92 :             out.emplace_back(OP_EQUAL, std::vector<unsigned char>());
#     309                 :         92 :             opcode = OP_VERIFY;
#     310         [ +  + ]:       1496 :         } else if (IsPushdataOp(opcode)) {
#     311         [ +  + ]:        312 :             if (!CheckMinimalPush(push_data, opcode)) return false;
#     312 [ +  + ][ +  + ]:       1184 :         } else if (it != itend && (opcode == OP_CHECKSIG || opcode == OP_CHECKMULTISIG || opcode == OP_EQUAL) && (*it == OP_VERIFY)) {
#         [ +  + ][ +  + ]
#                 [ +  + ]
#     313                 :            :             // Rule out non minimal VERIFY sequences
#     314                 :          2 :             return false;
#     315                 :          2 :         }
#     316                 :       1758 :         out.emplace_back(opcode, std::move(push_data));
#     317                 :       1758 :     }
#     318                 :        126 :     std::reverse(out.begin(), out.end());
#     319                 :        126 :     return true;
#     320                 :        130 : }
#     321                 :            : 
#     322                 :        226 : bool ParseScriptNumber(const std::pair<opcodetype, std::vector<unsigned char>>& in, int64_t& k) {
#     323         [ -  + ]:        226 :     if (in.first == OP_0) {
#     324                 :          0 :         k = 0;
#     325                 :          0 :         return true;
#     326                 :          0 :     }
#     327         [ +  - ]:        226 :     if (!in.second.empty()) {
#     328 [ +  + ][ -  + ]:        226 :         if (IsPushdataOp(in.first) && !CheckMinimalPush(in.second, in.first)) return false;
#     329                 :        226 :         try {
#     330                 :        226 :             k = CScriptNum(in.second, true).GetInt64();
#     331                 :        226 :             return true;
#     332                 :        226 :         } catch(const scriptnum_error&) {}
#     333                 :        226 :     }
#     334                 :          0 :     return false;
#     335                 :        226 : }
#     336                 :            : 
#     337                 :            : int FindNextChar(Span<const char> sp, const char m)
#     338                 :        380 : {
#     339         [ +  - ]:      14520 :     for (int i = 0; i < (int)sp.size(); ++i) {
#     340         [ +  + ]:      14520 :         if (sp[i] == m) return i;
#     341                 :            :         // We only search within the current parentheses
#     342         [ +  + ]:      14166 :         if (sp[i] == ')') break;
#     343                 :      14166 :     }
#     344                 :         26 :     return -1;
#     345                 :        380 : }
#     346                 :            : 
#     347                 :            : } // namespace internal
#     348                 :            : } // namespace miniscript

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a