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

libbitcoin / libbitcoin-system / 15078892484

16 May 2025 11:04PM UTC coverage: 81.885% (-0.3%) from 82.18%
15078892484

push

github

web-flow
Merge pull request #1673 from evoskuil/master

Refactor all signature_hash methods to return bool (tapscript).

293 of 491 new or added lines in 17 files covered. (59.67%)

5 existing lines in 3 files now uncovered.

10365 of 12658 relevant lines covered (81.88%)

3781254.62 hits per line

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

93.33
/include/bitcoin/system/impl/chain/operation_patterns.ipp
1
/**
2
 * Copyright (c) 2011-2025 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_CHAIN_OPERATION_PATTERNS_IPP
20
#define LIBBITCOIN_SYSTEM_CHAIN_OPERATION_PATTERNS_IPP
21

22
#include <bitcoin/system/define.hpp>
23
#include <bitcoin/system/chain/enums/numbers.hpp>
24
#include <bitcoin/system/chain/enums/opcode.hpp>
25
#include <bitcoin/system/chain/enums/coverage.hpp>
26
#include <bitcoin/system/chain/enums/flags.hpp>
27
#include <bitcoin/system/chain/enums/magic_numbers.hpp>
28
#include <bitcoin/system/crypto/crypto.hpp>
29

30
namespace libbitcoin {
31
namespace system {
32
namespace chain {
33

34
// Conversions.
35
// ----------------------------------------------------------------------------
36

37
// Convert the opcode to the corresponding [1..16] value (or undefined).
38
constexpr uint8_t operation::opcode_to_positive(opcode code) NOEXCEPT
×
39
{
40
    ////BC_ASSERT(is_positive(code));
41
    constexpr auto op_81 = static_cast<uint8_t>(opcode::push_positive_1);
×
42
    return static_cast<uint8_t>(code) - sub1(op_81);
×
43
}
44

45
// Compute maximum push data size for the opcode (without script limit).
46
constexpr size_t operation::opcode_to_maximum_size(opcode code) NOEXCEPT
4,474✔
47
{
48
    constexpr auto op_75 = static_cast<uint8_t>(opcode::push_size_75);
4,474✔
49

50
    switch (code)
4,474✔
51
    {
52
        case opcode::push_one_size:
53
            return max_uint8;
54
        case opcode::push_two_size:
55
            return max_uint16;
56
        case opcode::push_four_size:
57
            return max_uint32;
58
        default:
4,364✔
59
            const auto byte = static_cast<uint8_t>(code);
4,364✔
60
            return byte <= op_75 ? byte : zero;
4,364✔
61
    }
62
}
63

64
// Compute nominal data opcode based on size alone.
65
// ****************************************************************************
66
// CONSENSUS: non-minial encoding consensus critical for find_and_delete.
67
// ****************************************************************************
68
constexpr opcode operation::opcode_from_size(size_t size) NOEXCEPT
1,910✔
69
{
70
    ////BC_ASSERT(size <= max_uint32);
71
    constexpr auto op_75 = static_cast<uint8_t>(opcode::push_size_75);
1,910✔
72

73
    if (size <= op_75)
1,910✔
74
        return static_cast<opcode>(size);
1,842✔
75
    else if (size <= max_uint8)
68✔
76
        return opcode::push_one_size;
77
    else if (size <= max_uint16)
61✔
78
        return opcode::push_two_size;
79
    else
80
        return opcode::push_four_size;
×
81
}
82

83
// Convert the [0..16] value to the corresponding opcode (or undefined).
84
constexpr opcode operation::opcode_from_version(uint8_t value) NOEXCEPT
10✔
85
{
86
    ////BC_ASSERT(value <= numbers::positive_16);
87
    return (value == numbers::number_0) ? opcode::push_size_0 :
10✔
88
        operation::opcode_from_positive(value);
89
}
90

91
// Convert the [1..16] value to the corresponding opcode (or undefined).
92
constexpr opcode operation::opcode_from_positive(uint8_t value) NOEXCEPT
7✔
93
{
94
    ////BC_ASSERT(value >= numbers::positive_1);
95
    ////BC_ASSERT(value <= numbers::positive_16);
96
    constexpr auto op_81 = static_cast<uint8_t>(opcode::push_positive_1);
7✔
97
    return static_cast<opcode>(value + sub1(op_81));
7✔
98
}
99

100
// Compute the minimal data opcode for a given chunk of data.
101
// Caller should clear data if converting to non-payload opcode.
102
constexpr opcode operation::minimal_opcode_from_data(
143✔
103
    const data_chunk& data) NOEXCEPT
104
{
105
    const auto size = data.size();
143✔
106

107
    if (is_one(size))
143✔
108
    {
109
        const auto value = data.front();
4✔
110

111
        if (value == numbers::negative_1)
4✔
112
            return opcode::push_negative_1;
113

114
        if (value == numbers::number_0)
4✔
115
            return opcode::push_size_0;
116

117
        if (value >= numbers::positive_1 &&
4✔
118
            value <= numbers::positive_16)
119
            return opcode_from_positive(value);
3✔
120
    }
121

122
    // Nominal encoding is minimal for multiple bytes and non-numerics.
123
    return opcode_from_size(size);
140✔
124
}
125

126
// Compute the nominal data opcode for a given chunk of data.
127
// Restricted to sized data, avoids conversion to numeric opcodes.
128
constexpr opcode operation::nominal_opcode_from_data(
1,731✔
129
    const data_chunk& data) NOEXCEPT
130
{
131
    return opcode_from_size(data.size());
1,731✔
132
}
133

134
// Categories of opcodes.
135
// ----------------------------------------------------------------------------
136

137
// opcode: [0..96].
138
// ****************************************************************************
139
// CONSENSUS: this test explicitly includes the satoshi 'reserved' code.
140
// This affects the operation count in p2sh script evaluation.
141
// Presumably this was an unintended consequence of range testing enums.
142
// ****************************************************************************
143
constexpr bool operation::is_relaxed_push(opcode code) NOEXCEPT
144
{
145
    constexpr auto op_96 = opcode::push_positive_16;
146
    return code <= op_96;
147
}
148

149
// opcode: [0..79, 81..96].
150
constexpr bool operation::is_push(opcode code) NOEXCEPT
108✔
151
{
152
    constexpr auto op_80 = opcode::reserved_80;
108✔
153
    return is_relaxed_push(code) && code != op_80;
108✔
154
}
155

156
// opcode: [1..78].
157
constexpr bool operation::is_payload(opcode code) NOEXCEPT
49✔
158
{
159
    constexpr auto op_1 = opcode::push_size_1;
49✔
160
    constexpr auto op_78 = opcode::push_four_size;
49✔
161
    return code >= op_1 && code <= op_78;
49✔
162
}
163

164
// stack: [1..16].
165
constexpr bool operation::is_positive(opcode code) NOEXCEPT
95✔
166
{
167
    constexpr auto op_81 = opcode::push_positive_1;
95✔
168
    constexpr auto op_96 = opcode::push_positive_16;
95✔
169
    return code >= op_81 && code <= op_96;
95✔
170
}
171

172
// stack: [0, 1..16].
173
constexpr bool operation::is_nonnegative(opcode code) NOEXCEPT
206✔
174
{
175
    constexpr auto op_0 = opcode::push_size_0;
206✔
176
    return code == op_0 || is_positive(code);
206✔
177
}
178

179
// stack: [-1, 0, 1..16].
180
constexpr bool operation::is_number(opcode code) NOEXCEPT
181
{
182
    constexpr auto op_79 = opcode::push_negative_1;
183
    return code == op_79 || is_nonnegative(code);
184
}
185

186
// opcode: [122].
187
constexpr bool operation::is_roller(opcode code) NOEXCEPT
93,885✔
188
{
189
    constexpr auto op_122 = opcode::roll;
93,885✔
190
    return code == op_122;
93,885✔
191
}
192

193
// opcode: [97..255].
194
constexpr bool operation::is_counted(opcode code) NOEXCEPT
195
{
196
    constexpr auto op_97 = opcode::nop;
197
    return code >= op_97;
198
}
199

200
// This condition is only applicable with bip342 active. bip342: If any opcode
201
// 80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254 is encountered,
202
// validation succeeds. This is most reserved and most invalid, but not all. We
203
// are not renaming these codes to op_successX as succested by bip342, because:
204
// (1) they remain unimplemented.
205
// (2) they are not evaluated during script execution.
206
// (3) they are only conditionally successful (tapscript).
207
// (4) renaming them would lose important historical context.
208
// Regarding op_verif and op_vernotif, it seems that these were not promoted
209
// because authors failed to recognize that following their demotion from
210
// conditionals, these codes became unconditionally invalid, just as others.
211
// Regarding reserved_255, there is no good reason to have left this reserved,
212
// as op_return already provides that operation, but it's likely the authors
213
// felt it exhibits special benavior as the highest value code (it does not).
214
constexpr bool operation::is_success(opcode code) NOEXCEPT
93,885✔
215
{
216
    constexpr auto op_187 = opcode::reserved_187;
93,885✔
217
    constexpr auto op_254 = opcode::reserved_254;
93,885✔
218

219
    switch (code)
93,885✔
220
    {
221
        case opcode::reserved_80:
222
        case opcode::op_ver:
223
        ////case opcode::op_verif:      // stays invalid (why)
224
        ////case opcode::op_vernotif:   // stays invalid (why)
225
        ////case opcode::op_return:     // stays reserved
226
        case opcode::op_cat:
227
        case opcode::op_substr:
228
        case opcode::op_left:
229
        case opcode::op_right:
230
        case opcode::op_invert:
231
        case opcode::op_and:
232
        case opcode::op_or:
233
        case opcode::op_xor:
234
        case opcode::reserved_137:
235
        case opcode::reserved_138:
236
        case opcode::op_mul2:
237
        case opcode::op_div2:
238
        case opcode::op_mul:
239
        case opcode::op_div:
240
        case opcode::op_mod:
241
        case opcode::op_lshift:
242
        case opcode::op_rshift:
243
        ////case opcode::reserved_186:  // checksigadd subsumes
244
        ////case opcode::reserved_255:  // stays reserved (why)
245
            return true;
246
        default:
93,587✔
247
            return code >= op_187 && code <= op_254;
93,587✔
248
    }
249
}
250

251
// opcode: [101, 102, 126..129, 131..134, 141, 142, 149..153]
252
// ****************************************************************************
253
// CONSENSUS: These fail script even if wrapped by a conditional operation.
254
// ****************************************************************************
255
constexpr bool operation::is_invalid(opcode code) NOEXCEPT
94,062✔
256
{
257
    switch (code)
94,062✔
258
    {
259
        // Demoted to invalid by [0.3.6] soft fork.
260
        case opcode::op_verif:
261
        case opcode::op_vernotif:
262

263
        // Demoted to invalid by [0.3.10] soft fork.
264
        case opcode::op_cat:
265
        case opcode::op_substr:
266
        case opcode::op_left:
267
        case opcode::op_right:
268
        case opcode::op_invert:
269
        case opcode::op_and:
270
        case opcode::op_or:
271
        case opcode::op_xor:
272
        case opcode::op_mul2:
273
        case opcode::op_div2:
274
        case opcode::op_mul:
275
        case opcode::op_div:
276
        case opcode::op_mod:
277
        case opcode::op_lshift:
278
        case opcode::op_rshift:
279
            return true;
280
        default:
93,955✔
281
            return false;
93,955✔
282
    }
283
}
284

285
// opcode: [99..100, 103..104]
286
constexpr bool operation::is_conditional(opcode code) NOEXCEPT
22,402✔
287
{
288
    switch (code)
22,402✔
289
    {
290
        case opcode::if_:
291
        case opcode::notif:
292
        case opcode::else_:
293
        case opcode::endif:
294
            return true;
295
        default:
21,152✔
296
            return false;
21,152✔
297
    }
298
}
299

300
// opcode: [80, 98, 106, 137..138, 186..255]
301
// ****************************************************************************
302
// CONSENSUS: These fail script unless excluded by a conditional operation.
303
//
304
// Satoshi tests incorrectly refer to op_ver and op_verif as "reserved".
305
// Reserved refers to unused but conditionally acceptable codes. When the
306
// conditional operator skips over them, the script may be valid. On the
307
// other hand, "disabled" codes are unconditionally invalid - such as
308
// op_cat. The "disabled" codes are in a group outside of the evaluation
309
// switch, which makes their unconditional invalidity obvious. The other
310
// two disabled codes are not so obvious in behavior, and misidentified in
311
// satoshi test vectors:
312
//
313
// These fail because the scripts are unconditional with both reserved and
314
// disabled codes, yet they are all referred to as reserved.
315
// { "1", "ver", "op_ver is reserved" }
316
// { "1", "verif", "op_verif is reserved" }
317
// { "1", "vernotif", "op_vernotif is reserved" }
318
// { "1", "reserved", "op_reserved is reserved" }
319
// { "1", "reserved1", "op_reserved1 is reserved" }
320
// { "1", "reserved2", "op_reserved2 is reserved" }
321
//
322
// These fail because they either execute conditionally invalid codes
323
// (op_ver) or include unconditionally invalid codes, without execution
324
// (op_verif, op_vernotif). The comments are correct, contradicting above.
325
// { "1", "if ver else 1 endif", "ver is reserved" }
326
// { "0", "if verif else 1 endif", "verif illegal everywhere" }
327
// { "0", "if else 1 else verif endif", "verif illegal everywhere" }
328
// { "0", "if vernotif else 1 endif", "vernotif illegal everywhere" }
329
// { "0", "if else 1 else vernotif endif", "vernotif illegal everywhere" }
330
//
331
// These fail regardless of conditional exclusion because they are also
332
// disabled codes.
333
// { "'a' 'b'", "cat", "cat disabled" }
334
// { "'a' 'b' 0", "if cat else 1 endif", "cat disabled" }
335
// { "'abc' 1 1", "substr", "substr disabled" }
336
// { "'abc' 1 1 0", "if substr else 1 endif", "substr disabled" }
337
// { "'abc' 2 0", "if left else 1 endif", "left disabled" }
338
// { "'abc' 2 0", "if right else 1 endif", "right disabled" }
339
// { "'abc'", "if invert else 1 endif", "invert disabled" }
340
// { "1 2 0 if and else 1 endif", "nop", "and disabled" }
341
// { "1 2 0 if or else 1 endif", "nop", "or disabled" }
342
// { "1 2 0 if xor else 1 endif", "nop", "xor disabled" }
343
// { "2 0 if 2mul else 1 endif", "nop", "2mul disabled" }
344
// { "2 0 if 2div else 1 endif", "nop", "2div disabled" }
345
// { "2 2 0 if mul else 1 endif", "nop", "mul disabled" }
346
// { "2 2 0 if div else 1 endif", "nop", "div disabled" }
347
// { "2 2 0 if mod else 1 endif", "nop", "mod disabled" }
348
// { "2 2 0 if lshift else 1 endif", "nop", "lshift disabled" }
349
// { "2 2 0 if rshift else 1 endif", "nop", "rshift disabled" }
350
//
351
// The reason op_verif and op_vernotif are unconditionally invalid (and
352
// therefore behave exactly as "disabled" codes is they are conditionals.
353
// Note that op_ver is not a conditional, so despite similar name, when
354
// it was disabled it became a "reserved" code. The former conditonals
355
// are not excludable by remaining conditions. They pass this condition:
356
//      else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
357
// which evaluates all codes, yet there were removed from the evaluation.
358
// They were part of this case, but now this break is not hit by them:
359
//      case OP_IF:
360
//      case OP_NOTIF: {...}
361
//          break;
362
// So they fall through to the conditional default case, just as any
363
// reserved code would, and halt the evaluation with the bad_opcode error:
364
//      default:
365
//          return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
366
// Yet because they do not bypass any conditional evaluation they hit this
367
// default unconditionally. So they are "disabled" codes. We use the term
368
// "invalid" above because of the confusion that can cause. The only truly
369
// "reserved" codes are op_nop# codes, which were promoted by a hard fork.
370
// ****************************************************************************
371
constexpr bool operation::is_reserved(opcode code) NOEXCEPT
3✔
372
{
373
    constexpr auto op_186 = opcode::reserved_186;
3✔
374

375
    switch (code)
3✔
376
    {
377
        // Demoted to reserved by [0.3.6] soft fork.
378
        case opcode::op_ver:
379
        case opcode::op_return:
380

381
        // Unimplemented.
382
        case opcode::reserved_80:
383
        case opcode::reserved_137:
384
        case opcode::reserved_138:
385
            return true;
386
        default:
3✔
387
            return code >= op_186;
3✔
388
    }
389
}
390

391
// Categories of operations.
392
// ----------------------------------------------------------------------------
393

394
bool operation::is_relaxed_push() const NOEXCEPT
395
{
396
    return is_relaxed_push(code_);
397
}
398

399
bool operation::is_push() const NOEXCEPT
1✔
400
{
401
    return is_push(code_);
1✔
402
}
403

404
bool operation::is_payload() const NOEXCEPT
405
{
406
    return is_payload(code_);
407
}
408

409
bool operation::is_positive() const NOEXCEPT
410
{
411
    return is_positive(code_);
412
}
413

414
bool operation::is_nonnegative() const NOEXCEPT
206✔
415
{
416
    return is_nonnegative(code_);
206✔
417
}
418

419
bool operation::is_number() const NOEXCEPT
420
{
421
    return is_number(code_);
422
}
423

424
bool operation::is_roller() const NOEXCEPT
93,885✔
425
{
426
    return is_roller(code_);
93,885✔
427
}
428

429
bool operation::is_counted() const NOEXCEPT
430
{
431
    return is_counted(code_);
432
}
433

434
bool operation::is_success() const NOEXCEPT
93,885✔
435
{
436
    return is_success(code_);
93,885✔
437
}
438

439
bool operation::is_invalid() const NOEXCEPT
93,897✔
440
{
441
    return is_invalid(code_);
93,897✔
442
}
443

444
bool operation::is_conditional() const NOEXCEPT
22,402✔
445
{
446
    return is_conditional(code_);
22,402✔
447
}
448

449
bool operation::is_reserved() const NOEXCEPT
450
{
451
    return is_reserved(code_);
452
}
453

454
bool operation::is_minimal_push() const NOEXCEPT
129✔
455
{
456
    return code_ == minimal_opcode_from_data(get_data());
129✔
457
}
458

NEW
459
bool operation::is_nominal_push() const NOEXCEPT
×
460
{
NEW
461
    return code_ == nominal_opcode_from_data(get_data());
×
462
}
463

464
bool operation::is_underclaimed() const NOEXCEPT
4,474✔
465
{
466
    return data_size() > operation::opcode_to_maximum_size(code_);
4,474✔
467
}
468

469
bool operation::is_oversized() const NOEXCEPT
22,413✔
470
{
471
    // Rule max_push_data_size imposed by [0.3.6] soft fork.
472
    return data_size() > max_push_data_size;
22,413✔
473
}
474

475
// ****************************************************************************
476
// CONSENSUS: An underflow is sized op-undersized data. Behavior is the same as
477
// invalid opcode, invalidating the script if executed and not success coded.
478
// ****************************************************************************
479
bool operation::is_underflow() const NOEXCEPT
1,491,511✔
480
{
481
    return underflow_;
1,491,511✔
482
}
483

484
} // namespace chain
485
} // namespace system
486
} // namespace libbitcoin
487

488
#endif
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