• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

libbitcoin / libbitcoin-system / 24331809217

13 Apr 2026 07:45AM UTC coverage: 75.852% (-5.8%) from 81.681%
24331809217

push

github

web-flow
Merge pull request #1811 from pmienk/installer-rewrite

Rewritten build/install scripts.

16733 of 22060 relevant lines covered (75.85%)

2499729.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.44
/include/bitcoin/system/impl/machine/stack_variant.ipp
1
/**
2
 * Copyright (c) 2011-2026 libbitcoin developers (see AUTHORS)
3
 *
4
 * This file is part of libbitcoin.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
#ifndef LIBBITCOIN_SYSTEM_MACHINE_STACK_VARIANT_IPP
20
#define LIBBITCOIN_SYSTEM_MACHINE_STACK_VARIANT_IPP
21

22
#include <tuple>
23
#include <utility>
24
#include <bitcoin/system/data/data.hpp>
25
#include <bitcoin/system/define.hpp>
26
#include <bitcoin/system/math/math.hpp>
27

28
namespace libbitcoin {
29
namespace system {
30
namespace machine {
31

32
// private
33
// Generalized integer peek for varying bit widths up to 8 bytes.
34
// Chunk to integer conversions are constrained by caller (4 or 5 bytes).
35
// False result implies value overflow, from integer or chunk conversion.
36
TEMPLATE
37
template<size_t Bytes, typename Integer,
38
    if_not_lesser<sizeof(Integer), Bytes>,
39
    if_signed_integral_integer<Integer>>
40
inline bool CLASS::
4,750✔
41
peek_signed(Integer& value) const NOEXCEPT
42
{
43
    using namespace number;
44
    auto result{ true };
4,750✔
45

46
    std::visit(overload
4,750✔
47
    {
48
        [&](bool vary) NOEXCEPT
×
49
        {
50
            // This is never executed in standard scripts.
51
            value = to_int(vary);
80✔
52
        },
53
        [&](int64_t vary) NOEXCEPT
4,419✔
54
        {
55
            // This is the canonical use case.
56
            result = integer<Bytes>::from_integer(value, vary);
8,838✔
57
        },
58
        [&](const chunk_xptr& vary) NOEXCEPT
291✔
59
        {
60
            // This is never executed in standard scripts.
61
            result = integer<Bytes>::from_chunk(value, *vary);
291✔
62
        }
63
    }, top());
64

65
    return result;
4,750✔
66
}
67

68
/// Variant data conversions.
69
/// ---------------------------------------------------------------------------
70
/// P2SH and P2WSH redeem scripts and P2TR tapscripts are not subjectable to
71
/// standardness and are therefore not considered "stadnard" in comments below.
72

73
TEMPLATE
74
inline bool CLASS::
1,593✔
75
peek_bool() const NOEXCEPT
76
{
77
    using namespace number;
78
    bool value{};
1,593✔
79

80
    std::visit(overload
1,593✔
81
    {
82
        [&](bool vary) NOEXCEPT
713✔
83
        {
84
            // This is the canonical use case.
85
            value = vary;
713✔
86
        },
87
        [&](int64_t vary) NOEXCEPT
828✔
88
        {
89
            // This is never executed in standard scripts.
90
            value = boolean::from_integer(vary);
828✔
91
        },
92
        [&](const chunk_xptr& vary) NOEXCEPT
52✔
93
        {
94
            // This is never executed in standard scripts.
95
            value = boolean::from_chunk(*vary);
52✔
96
        }
97
    }, top());
98

99
    return value;
1,593✔
100
}
101

102
// Differs from peek_bool in that a chunk false must be empty [].
103
TEMPLATE
104
inline bool CLASS::
2,050✔
105
peek_strict_bool() const NOEXCEPT
106
{
107
    using namespace number;
108
    bool value{};
2,050✔
109

110
    std::visit(overload
2,050✔
111
    {
112
        [&](bool vary) NOEXCEPT
1,200✔
113
        {
114
            // This is the canonical use case (with bip147).
115
            value = vary;
1,200✔
116
        },
117
        [&](int64_t vary) NOEXCEPT
848✔
118
        {
119
            // This may be executed in standard scripts (without bip147).
120
            value = boolean::from_integer(vary);
848✔
121
        },
122
        [&](const chunk_xptr& vary) NOEXCEPT
2✔
123
        {
124
            // This may be executed in standard scripts (without bip147).
125
            value = boolean::from_chunk_strict(*vary);
2✔
126
        }
127
    }, top());
128

129
    return value;
2,050✔
130
}
131

132
// This is the only convertor with both a return value and a result.
133
// A chunk false must be [] and chunk true must be [0x01], otherwise fails.
134
TEMPLATE
135
inline bool CLASS::
×
136
peek_minimal_bool(bool& value) const NOEXCEPT
137
{
138
    using namespace number;
139
    auto result{ true };
×
140

141
    std::visit(overload
×
142
    {
143
        [&](bool vary) NOEXCEPT
×
144
        {
145
            // This is the canonical use case (tapscript).
146
            value = vary;
×
147
        },
148
        [&](int64_t vary) NOEXCEPT
×
149
        {
150
            // This may be executed in tapscripts.
151
            result = boolean::from_integer(value, vary);
×
152
        },
153
        [&](const chunk_xptr& vary) NOEXCEPT
×
154
        {
155
            // This may be executed in tapscripts.
156
            result = boolean::from_chunk(value, *vary);
×
157
        }
158
    }, top());
159

160
    return result;
×
161
}
162

163
// Could use peek_chunk but this overload skips allocation and tethering.
164
TEMPLATE
165
inline size_t CLASS::
58✔
166
peek_size() const NOEXCEPT
167
{
168
    using namespace number;
169
    size_t value{};
58✔
170

171
    std::visit(overload
58✔
172
    {
173
        [&](bool vary) NOEXCEPT
4✔
174
        {
175
            // This is never executed in standard scripts.
176
            value = chunk::from_bool(vary).size();
2✔
177
        },
178
        [&](int64_t vary) NOEXCEPT
20✔
179
        {
180
            // This is never executed in standard scripts.
181
            value = chunk::from_integer(vary).size();
10✔
182
        },
183
        [&](const chunk_xptr& vary) NOEXCEPT
46✔
184
        {
185
            // This is never executed in standard scripts.
186
            value = vary->size();
46✔
187
        }
188
    }, top());
189

190
    return value;
58✔
191
}
192

193
// This is the only source of peek/pop (read) tethering.
194
TEMPLATE
195
inline chunk_xptr CLASS::
3,578✔
196
peek_chunk() const NOEXCEPT
197
{
198
    using namespace number;
199
    chunk_xptr value{};
200

201
    // The following script operations will ONLY tether chunks in case where
202
    // the *popped* element was originally bool/int64_t but required as chunk.
203
    // This is never the case in standard scripts. make_external attaches moved
204
    // chunk to tether and returns weak pointer (chunk_xptr).
205
    //
206
    // op_ripemd160         (0..1)
207
    // op_sha1              (0..1)
208
    // op_sha256            (0..1)
209
    // op_hash160           (0..1)
210
    // op_hash256           (0..1)
211
    // op_size              (0..1)
212
    // op_check_sig_add     (0..2)
213
    // op_check_sig         (0..2, and m (endorsements) + n (keys))
214
    // op_check_sig_verify  (0..2, and m (endorsements) + n (keys))
215

216
    std::visit(overload
3,578✔
217
    {
218
        [&](bool vary) NOEXCEPT
×
219
        {
220
            // This is never executed in standard scripts.
221
            value = make_external(chunk::from_bool(vary), tether_);
×
222
        },
223
        [&](int64_t vary) NOEXCEPT
76✔
224
        {
225
            // This is never executed in standard scripts.
226
            value = make_external(chunk::from_integer(vary), tether_);
38✔
227
        },
228
        [&](const chunk_xptr& vary) NOEXCEPT
3,540✔
229
        {
230
            // This is the canonical use case.
231
            value = vary;
3,540✔
232
        }
233
    }, top());
234

235
    return value;
3,578✔
236
}
237

238
// Static variant compare with conversion.
239
// Methods bound at compile time (free).
240
// One runtime switch on variant index (cheap).
241
// bool/int conversions are compile-time (free).
242
// chunk conversions reduce to conventional bitcoin design.
243
// Integers are unconstrained as these are stack chunk equality comparisons.
244
TEMPLATE
245
inline bool CLASS::
560✔
246
equal_chunks(const stack_variant& left, const stack_variant& right) NOEXCEPT
247
{
248
    using namespace number;
249
    auto same{ true };
560✔
250

251
    std::visit(overload
560✔
252
    {
253
        // This is never executed in standard scripts.
254
        [&](bool vary) NOEXCEPT
24✔
255
        {
256
            switch (right.index())
12✔
257
            {
258
                case stack_type::bool_:
×
259
                    same = std::get<bool>(right) == vary;
×
260
                    break;
×
261
                case stack_type::int64_:
12✔
262
                    same = std::get<int64_t>(right) == to_int(vary);
12✔
263
                    break;
12✔
264
                case stack_type::pchunk_:
×
265
                    same = *std::get<chunk_xptr>(right) == chunk::from_bool(vary);
×
266
            }
267
        },
268

269
        // This is never executed in standard scripts.
270
        [&](int64_t vary) NOEXCEPT
700✔
271
        {
272
            switch (right.index())
350✔
273
            {
274
                case stack_type::bool_:
×
275
                    same = to_int(std::get<bool>(right)) == vary;
×
276
                    break;
×
277
                case stack_type::int64_:
322✔
278
                    same = std::get<int64_t>(right) == vary;
322✔
279
                    break;
322✔
280
                case stack_type::pchunk_:
28✔
281
                    same = *std::get<chunk_xptr>(right) == chunk::from_integer(vary);
28✔
282
            }
283
        },
284

285
        // This is the canonical use case.
286
        [&](chunk_xptr vary) NOEXCEPT
396✔
287
        {
288
            switch (right.index())
198✔
289
            {
290
                case stack_type::bool_:
291
                    // This is never executed in standard scripts.
292
                    same = chunk::from_bool(std::get<bool>(right)) == *vary;
×
293
                    break;
×
294
                case stack_type::int64_:
295
                    // This is never executed in standard scripts.
296
                    same = chunk::from_integer(std::get<int64_t>(right)) == *vary;
14✔
297
                    break;
14✔
298
                case stack_type::pchunk_:
299
                    // This is the canonical use case.
300
                    same = *std::get<chunk_xptr>(right) == *vary;
184✔
301
            }
302
        }
303
    }, left);
304

305
    return same;
560✔
306
}
307

308
} // namespace machine
309
} // namespace system
310
} // namespace libbitcoin
311

312
#endif
313

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc