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

libbitcoin / libbitcoin-system / 14921455122

09 May 2025 04:30AM UTC coverage: 82.479% (-0.2%) from 82.702%
14921455122

push

github

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

tapscript: sigop budget, call schnorr parse/validate, mask bip342 flag for !tapscript.

102 of 152 new or added lines in 2 files covered. (67.11%)

2 existing lines in 1 file now uncovered.

10286 of 12471 relevant lines covered (82.48%)

3863519.66 hits per line

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

90.95
/include/bitcoin/system/impl/machine/program.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_MACHINE_PROGRAM_IPP
20
#define LIBBITCOIN_SYSTEM_MACHINE_PROGRAM_IPP
21

22
#include <iterator>
23
#include <utility>
24
#include <variant>
25
#include <bitcoin/system/chain/chain.hpp>
26
#include <bitcoin/system/crypto/crypto.hpp>
27
#include <bitcoin/system/data/data.hpp>
28
#include <bitcoin/system/define.hpp>
29
#include <bitcoin/system/math/math.hpp>
30

31
namespace libbitcoin {
32
namespace system {
33
namespace machine {
34

35
// Constructors.
36
// ----------------------------------------------------------------------------
37

38
// Input script run (default/empty stack).
39
// 'tx' must remain in scope, this holds state referenced by weak pointers.
40
// This expectation is guaranteed by the retained tx reference.
41
TEMPLATE
42
inline CLASS::
1,559✔
43
program(const transaction& tx, const input_iterator& input,
44
     uint32_t active_flags) NOEXCEPT
45
  : transaction_(tx),
1,559✔
46
    input_(input),
1,559✔
47
    script_((*input)->script_ptr()),
1,559✔
48
    flags_(bit_and(active_flags, bip342_mask)),
1,559✔
49
    value_(max_uint64),
1,559✔
50
    version_(script_version::unversioned),
1,559✔
51
    primary_()
1,559✔
52
{
53
}
1,559✔
54

55
// Legacy p2sh or prevout script run (copied input stack - use first).
56
// 'other' must remain in scope, this holds state referenced by weak pointers.
57
// This expectation is guaranteed by the retained transaction_ member reference
58
// and copied program tether (which is not tx state).
59
TEMPLATE
60
inline CLASS::
1,496✔
61
program(const program& other, const script::cptr& script) NOEXCEPT
62
  : transaction_(other.transaction_),
1,496✔
63
    input_(other.input_),
1,496✔
64
    script_(script),
65
    flags_(other.flags_),
1,496✔
66
    value_(other.value_),
1,496✔
67
    version_(other.version_),
1,496✔
68
    primary_(other.primary_)
1,496✔
69
{
70
}
1,496✔
71

72
// Legacy p2sh or prevout script run (moved input stack/tether - use last).
73
TEMPLATE
74
inline CLASS::
17✔
75
program(program&& other, const script::cptr& script) NOEXCEPT
76
  : transaction_(other.transaction_),
17✔
77
    input_(other.input_),
17✔
78
    script_(script),
79
    flags_(other.flags_),
17✔
80
    value_(other.value_),
17✔
81
    version_(other.version_),
17✔
82
    primary_(std::move(other.primary_))
17✔
83
{
84
}
17✔
85

86
// Segwit script run (witness-initialized stack).
87
// 'tx', 'input' (and iterated chain::input) must remain in scope, as these
88
// hold chunk state weak references. A witness pointer is explicitly retained
89
// to guarantee the lifetime of its elements.
90
TEMPLATE
91
inline CLASS::
23✔
92
program(const transaction& tx, const input_iterator& input,
93
    const script::cptr& script, uint32_t active_flags,
94
    script_version version, const chunk_cptrs_ptr& witness) NOEXCEPT
95
  : transaction_(tx),
23✔
96
    input_(input),
23✔
97
    script_(script),
98
    flags_(bit_and(active_flags, bip342_mask)),
23✔
99
    value_((*input)->prevout->value()),
23✔
100
    version_(version),
23✔
101
    witness_(witness),
102
    primary_(projection<Stack>(*witness))
69✔
103
{
104
}
23✔
105

106
// Taproot script run (witness-initialized stack).
107
// Same as segwit but with with budget and unstripped bip342 flag.
108
// Sigop budget is 50 plus size of prefixed serialized witness [bip342].
109
// Budget is initialized +51 to make it zero-based, avoiding signed type.
110
TEMPLATE
NEW
111
inline CLASS::
×
112
program(const transaction& tx, const input_iterator& input,
113
    const script::cptr& script, uint32_t active_flags,
114
    script_version version, const chunk_cptrs_ptr& witness,
115
    size_t witness_size) NOEXCEPT
NEW
116
  : transaction_(tx),
×
NEW
117
    input_(input),
×
118
    script_(script),
NEW
119
    flags_(active_flags),
×
NEW
120
    value_((*input)->prevout->value()),
×
NEW
121
    version_(version),
×
122
    witness_(witness),
NEW
123
    primary_(projection<Stack>(*witness)),
×
NEW
124
    budget_(ceilinged_add(add1(chain::signature_budget), witness_size))
×
125
{
NEW
126
}
×
127

128
// Public.
129
// ----------------------------------------------------------------------------
130

131
TEMPLATE
132
inline bool CLASS::
1,088✔
133
is_true(bool clean_stack) const NOEXCEPT
134
{
135
    return (!clean_stack || is_stack_clean()) && !is_stack_empty() &&
3,244✔
136
        peek_bool_();
1,088✔
137
}
138

139
TEMPLATE
140
inline const data_chunk& CLASS::
17✔
141
pop() NOEXCEPT
142
{
143
    BC_ASSERT_MSG(!is_stack_empty(), "pop from empty stack");
144

145
    return *pop_chunk_();
17✔
146
}
147

148
// Non-public.
149
// ============================================================================
150

151
TEMPLATE
152
INLINE error::script_error_t CLASS::
3,095✔
153
initialize() const NOEXCEPT
154
{
155
    // TODO: nops rule must first be enabled in tests and config.
156
    const auto nops = true; ////is_enabled(flags::nops_rule);
157
    const auto bip141 = is_enabled(flags::bip141_rule);
158
    const auto bip342 = is_enabled(flags::bip342_rule);
159

160
    // Apply stack element limit (520) to initial witness [bip141][bip342].
161
    if (bip141 && witness_ && !chain::witness::is_push_size(*witness_))
1,508✔
162
        return error::invalid_witness_stack;
163

164
    // Script size limit (10,000) [0.3.7+], removed [bip342].
165
    if (!bip342 && nops && script_->is_oversized())
3,095✔
166
        return error::invalid_script_size;
167

168
    // Stacks element limit (1,000) applied to initial stack [bip342].
169
    if (bip342 && is_stack_overflow())
×
170
        return error::invalid_stack_size;
171

172
    // Succeed if any success code, one overrides all codes [bip342].
173
    if (bip342 && script_->is_prevalid())
×
174
        return error::prevalid_script;
175

176
    // Fail if last op underflow, lower priority than easy [bip342].
177
    if (script_->is_underflow())
3,093✔
178
        return error::invalid_script;
179

180
    // Fail if any op invalid (invalid codes reduced in tapscript).
181
    if (script_->is_prefail())
3,093✔
182
        return error::prefail_script;
183

184
    return error::script_success;
185
}
186

187
TEMPLATE
188
INLINE typename CLASS::op_iterator CLASS::
3,033✔
189
begin() const NOEXCEPT
190
{
191
    return script_->ops().begin();
3,033✔
192
}
193

194
TEMPLATE
195
INLINE typename CLASS::op_iterator CLASS::
25,009✔
196
end() const NOEXCEPT
197
{
198
    return script_->ops().end();
25,009✔
199
}
200

201
TEMPLATE
202
INLINE const chain::transaction& CLASS::
7✔
203
tx() const NOEXCEPT
204
{
205
    return transaction_;
7✔
206
}
207

208
TEMPLATE
209
INLINE const chain::input& CLASS::
18✔
210
input() const NOEXCEPT
211
{
212
    return **input_;
213
}
214

215
TEMPLATE
216
INLINE bool CLASS::
36,934✔
217
is_enabled(flags flag) const NOEXCEPT
218
{
219
    return to_bool(flags_ & flag);
7,906✔
220
}
221

222
// Primary stack (conversions).
223
// ----------------------------------------------------------------------------
224

225
// static
226
TEMPLATE
227
INLINE bool CLASS::
560✔
228
equal_chunks(const stack_variant& left, const stack_variant& right) NOEXCEPT
229
{
230
    return primary_stack::equal_chunks(left, right);
560✔
231
}
232

233
TEMPLATE
234
INLINE bool CLASS::
1,593✔
235
peek_bool_() const NOEXCEPT
236
{
237
    return primary_.peek_bool();
1,593✔
238
}
239

240
TEMPLATE
241
INLINE chunk_xptr CLASS::
3,578✔
242
peek_chunk_() const NOEXCEPT
243
{
244
    return primary_.peek_chunk();
3,578✔
245
}
246

247
TEMPLATE
248
INLINE size_t CLASS::
58✔
249
peek_size() const NOEXCEPT
250
{
251
    return primary_.peek_size();
58✔
252
}
253

254
// Primary stack (push).
255
// ----------------------------------------------------------------------------
256

257
// This is the only source of push (write) tethering.
258
TEMPLATE
259
INLINE void CLASS::
167✔
260
push_chunk(data_chunk&& datum) NOEXCEPT
261
{
262
    primary_.push(std::move(datum));
263
}
264

265
// Passing data_chunk& would be poor interface design, as it would allow
266
// derived callers to (unsafely) store raw pointers to unshared data_chunk.
267
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
268
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
269
TEMPLATE
270
INLINE void CLASS::
4,474✔
271
push_chunk(const chunk_cptr& datum) NOEXCEPT
272
BC_POP_WARNING()
273
BC_POP_WARNING()
274
{
275
    primary_.emplace_chunk(datum.get());
8,948✔
276
}
277

278
// private
279
TEMPLATE
280
INLINE void CLASS::
281
push_chunk(const chunk_xptr& datum) NOEXCEPT
282
{
283
    primary_.emplace_chunk(datum);
284
}
285

286
TEMPLATE
287
INLINE void CLASS::
2,018✔
288
push_bool(bool value) NOEXCEPT
289
{
290
    primary_.emplace_boolean(value);
2,018✔
291
}
292

293
TEMPLATE
294
INLINE void CLASS::
7,256✔
295
push_signed64(int64_t value) NOEXCEPT
296
{
297
    primary_.emplace_integer(value);
7,073✔
298
}
299

300
TEMPLATE
301
INLINE void CLASS::
241✔
302
push_length(size_t value) NOEXCEPT
303
{
304
    // This is guarded by stack size and push data limits.
305
    BC_ASSERT_MSG(value <= max_int64, "integer overflow");
306

307
    push_signed64(possible_narrow_sign_cast<int64_t>(value));
241✔
308
}
309

310
// Primary stack (pop).
311
// ----------------------------------------------------------------------------
312

313
// This tethers a chunk if the stack value is not chunk.
314
TEMPLATE
315
INLINE chunk_xptr CLASS::
3,552✔
316
pop_chunk_() NOEXCEPT
317
{
318
    const auto value = peek_chunk_();
319
    drop_();
320
    return value;
193✔
321
}
322

323
// This tethers chunks if the stack values are not chunk.
324
TEMPLATE
325
INLINE bool CLASS::
4,102✔
326
pop_chunks(chunk_xptrs& data, size_t count) NOEXCEPT
327
{
328
    if (stack_size() < count)
4,102✔
329
        return false;
330

331
    data.reserve(count);
4,102✔
332
    for (size_t index = 0; index < count; ++index)
7,444✔
333
        data.push_back(pop_chunk_());
3,342✔
334

335
    return true;
336
}
337

338
TEMPLATE
339
INLINE bool CLASS::
2,050✔
340
pop_strict_bool_() NOEXCEPT
341
{
342
    const auto value = primary_.peek_strict_bool();
2,050✔
343
    drop_();
344
    return value;
345
}
346

347
TEMPLATE
348
INLINE bool CLASS::
446✔
349
pop_bool_(bool& value, bool minimal) NOEXCEPT
350
{
351
    if (!minimal)
446✔
352
        value = peek_bool_();
446✔
353
    else if (!primary_.peek_minimal_bool(value))
×
354
        return false;
355

356
    drop_();
357
    return true;
358
}
359

360
TEMPLATE
361
INLINE bool CLASS::
4,738✔
362
pop_signed32_(int32_t& value) NOEXCEPT
363
{
364
    const auto result = peek_signed32_(value);
365
    drop_();
366
    return result;
367
}
368

369
TEMPLATE
370
INLINE bool CLASS::
4,272✔
371
pop_signed32(int32_t& value) NOEXCEPT
372
{
373
    if (is_stack_empty())
4,272✔
374
        return false;
375

376
    return pop_signed32_(value);
377
}
378

379
TEMPLATE
380
INLINE bool CLASS::
242✔
381
pop_binary32(int32_t& left, int32_t& right) NOEXCEPT
382
{
383
    if (stack_size() < 2)
242✔
384
        return false;
385

386
    // The right hand side operand is at the top of the stack.
387
    return pop_signed32_(right) && pop_signed32_(left);
430✔
388
}
389

390
TEMPLATE
391
INLINE bool CLASS::
18✔
392
pop_ternary32(int32_t& upper, int32_t& lower,
393
    int32_t& value) NOEXCEPT
394
{
395
    if (stack_size() < 3)
18✔
396
        return false;
397

398
    // The upper bound is at stack top, lower bound next, value next.
399
    return pop_signed32_(upper) && pop_signed32_(lower) &&
48✔
400
        pop_signed32_(value);
401
}
402

403
// ****************************************************************************
404
// CONSENSUS: Satoshi limits this value to the int32_t domain (getint()).
405
// This value is only used for stack indexing (key/sig counts & pick/roll).
406
// The upper bound of int32_t always exceeds the possible stack size, which
407
// is checked downstream. Similarly, a negative causes a downstream script
408
// failure. As such it is sufficient to fail on non-idexability here,
409
// allowing the value to be returned as a valid and unsigned stack index.
410
// ****************************************************************************
411
TEMPLATE
412
INLINE bool CLASS::
4,160✔
413
pop_index32(size_t& index) NOEXCEPT
414
{
415
    int32_t value;
416
    if (!pop_signed32(value))
4,160✔
417
        return false;
418

419
    if (is_negative(value))
4,160✔
420
        return false;
421

422
    // Cast guarded by stack size.
423
    index = limit<size_t>(value);
46✔
424

425
    // True if popped value valid post-pop stack index (precluded if size < 2).
426
    return index < stack_size();
4,156✔
427
}
428

429
// private
430
TEMPLATE
431
INLINE bool CLASS::
246✔
432
peek_signed32_(int32_t& value) const NOEXCEPT
433
{
434
    return primary_.peek_signed4(value);
4,492✔
435
}
436

437
// private
438
TEMPLATE
439
INLINE bool CLASS::
12✔
440
peek_signed40_(int64_t& value) const NOEXCEPT
441
{
442
    return primary_.peek_signed5(value);
12✔
443
}
444

445
// ****************************************************************************
446
// CONSENSUS: Read of 40 bit (vs. 32 bit) value for comparison against uint32_t
447
// input.sequence allows use of the full unsigned 32 bit domain, without use of
448
// the negative range.
449
// ****************************************************************************
450
TEMPLATE
451
INLINE bool CLASS::
×
452
peek_unsigned32(uint32_t& value) const NOEXCEPT
453
{
454
    if (is_stack_empty())
×
455
        return false;
456

457
    int64_t signed64;
458
    if (!peek_signed40_(signed64) || is_negative(signed64))
×
459
        return false;
460

461
    // 32 bits are used in unsigned input.sequence compare.
462
    value = narrow_sign_cast<uint32_t>(signed64);
463
    return true;
×
464
}
465

466
// ****************************************************************************
467
// CONSENSUS: Read of 40 bit (vs. 32 bit) value for comparison against uint32_t
468
// input.locktime allows use of the full unsigned 32 bit domain, without use of
469
// the negative range. Otherwise a 2038 limit (vs. the inherent 2106 limit)
470
// would have been introduced.
471
// ****************************************************************************
472
TEMPLATE
473
INLINE bool CLASS::
18✔
474
peek_unsigned40(uint64_t& value) const NOEXCEPT
475
{
476
    if (is_stack_empty())
18✔
477
        return false;
478

479
    int64_t signed64;
480
    if (!peek_signed40_(signed64) || is_negative(signed64))
12✔
481
        return false;
482

483
    // 40 bits are usable in unsigned tx.locktime compare.
484
    value = sign_cast<uint64_t>(signed64);
485
    return true;
7✔
486
}
487

488
// Primary stack (variant - index).
489
// ----------------------------------------------------------------------------
490
// Stack index is zero-based, back() is element zero.
491

492
// This swaps the variant elements of the stack vector.
493
TEMPLATE
494
INLINE void CLASS::
174✔
495
swap_(size_t left_index, size_t right_index) NOEXCEPT
496
{
497
    primary_.swap(left_index, right_index);
498
}
499

500
TEMPLATE
501
INLINE void CLASS::
16✔
502
erase_(size_t index) NOEXCEPT
503
{
504
    primary_.erase(index);
505
}
506

507
TEMPLATE
508
INLINE const stack_variant& CLASS::
9,916✔
509
peek_(size_t index) const NOEXCEPT
510
{
511
    return primary_.peek(index);
512
}
513

514
// Primary stack (variant - top).
515
// ----------------------------------------------------------------------------
516

517
TEMPLATE
518
INLINE void CLASS::
10,901✔
519
drop_() NOEXCEPT
520
{
521
    primary_.drop();
522
}
523

524
TEMPLATE
525
INLINE void CLASS::
9,957✔
526
push_variant(const stack_variant& vary) NOEXCEPT
527
{
528
    primary_.push(vary);
529
}
4✔
530

531
TEMPLATE
532
INLINE const stack_variant& CLASS::
35✔
533
peek_() const NOEXCEPT
534
{
535
    return primary_.top();
536
}
537

538
TEMPLATE
539
INLINE stack_variant CLASS::
1,138✔
540
pop_() NOEXCEPT
541
{
542
    return primary_.pop();
543
}
544

545
// Primary stack state (untyped).
546
// ----------------------------------------------------------------------------
547

548
TEMPLATE
549
INLINE size_t CLASS::
12,749✔
550
stack_size() const NOEXCEPT
551
{
552
    return primary_.size();
553
}
554

555
TEMPLATE
556
INLINE bool CLASS::
8,289✔
557
is_stack_empty() const NOEXCEPT
558
{
559
    return primary_.empty();
560
}
561

562
TEMPLATE
563
INLINE bool CLASS::
20,900✔
564
is_stack_overflow() const NOEXCEPT
565
{
566
    // Addition is safe due to stack size constraint.
567
    // Limit of 1000 elements in stack and altstack remains [bip342]. 
568
    return (stack_size() + alternate_.size()) > chain::max_unified_stack_size;
20,900✔
569
}
570

571
// private
572
TEMPLATE
573
INLINE bool CLASS::
21✔
574
is_stack_clean() const NOEXCEPT
575
{
576
    return is_one(stack_size());
577
}
578

579
// Alternate stack.
580
// ----------------------------------------------------------------------------
581

582
TEMPLATE
583
INLINE bool CLASS::
10✔
584
is_alternate_empty() const NOEXCEPT
585
{
586
    return alternate_.empty();
587
}
588

589
// Moving a shared pointer to the alternate stack is optimal and acceptable.
590
BC_PUSH_WARNING(NO_RVALUE_REF_SHARED_PTR)
591
TEMPLATE
592
INLINE void CLASS::
18✔
593
push_alternate(stack_variant&& vary) NOEXCEPT
594
BC_POP_WARNING()
595
{
596
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
597
    alternate_.push_back(std::move(vary));
18✔
598
    BC_POP_WARNING()
599
}
600

601
TEMPLATE
602
INLINE stack_variant CLASS::
6✔
603
pop_alternate_() NOEXCEPT
604
{
605
    BC_ASSERT(!alternate_.empty());
606

607
    stack_variant value{ std::move(alternate_.back()) };
6✔
608
    alternate_.pop_back();
6✔
609
    return value;
6✔
610
}
611

612
// Conditional stack.
613
// ----------------------------------------------------------------------------
614

615
TEMPLATE
616
INLINE void CLASS::
474✔
617
begin_if(bool value) NOEXCEPT
618
{
619
    // Addition is safe due to script size constraint.
620
    BC_ASSERT(value || !is_add_overflow(negative_conditions_, one));
621

622
    negative_conditions_ += (value ? 0 : 1);
474✔
623
    condition_.push_back(value);
474✔
624
}
625

626
// ****************************************************************************
627
// CONSENSUS: "You may have noticed the strange behavior of Bitcoin's ELSE
628
// statement. Bitcoin allows one to switch between true and false conditions
629
// several times. For example, the following script is valid and leaves the
630
// value 2 on the stack: 1 OP_IF OP_ELSE OP_ELSE 2 OP_ENDIF"
631
// bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts
632
// ****************************************************************************
633
TEMPLATE
634
INLINE void CLASS::
442✔
635
else_if_() NOEXCEPT
636
{
637
    // Subtraction must be guarded by caller logical constraints.
638
    BC_ASSERT(!is_balanced());
639

640
    // Addition is safe due to script size constraint.
641
    BC_ASSERT(condition_.back() || !is_add_overflow(negative_conditions_, one));
642

643
    negative_conditions_ += (condition_.back() ? 1 : -1);
442✔
644
    condition_.back() = !condition_.back();
442✔
645
}
646

647
TEMPLATE
648
INLINE void CLASS::
308✔
649
end_if_() NOEXCEPT
650
{
651
    // Subtraction must be guarded by caller logical constraints.
652
    BC_ASSERT(!is_balanced());
653

654
    negative_conditions_ += (condition_.back() ? 0 : -1);
308✔
655
    condition_.pop_back();
308✔
656
}
657

658
TEMPLATE
659
INLINE bool CLASS::
3,368✔
660
is_balanced() const NOEXCEPT
661
{
662
    return condition_.empty();
3,368✔
663
}
664

665
TEMPLATE
666
INLINE bool CLASS::
21,630✔
667
is_succeess() const NOEXCEPT
668
{
669
    // Optimization changes O(n) search [for every operation] to O(1).
670
    // bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts
671
    return is_zero(negative_conditions_);
21,630✔
672
}
673

674
TEMPLATE
675
INLINE bool CLASS::
22,402✔
676
if_(const operation& op) const NOEXCEPT
677
{
678
    // Conditional op execution is not predicated on conditional stack.
679
    return op.is_conditional() || is_succeess();
22,402✔
680
}
681

682
//  Accumulator.
683
// ----------------------------------------------------------------------------
684

685
// ****************************************************************************
686
// CONSENSUS:
687
// Satoshi compares the count to 200 with a composed postfix increment, which
688
// makes the actual maximum 201, not the presumably-intended 200. The code was
689
// later revised to make this explicit, by use of a prefix increment against a
690
// limit of 201.
691
// ****************************************************************************
692
INLINE constexpr bool operation_count_exceeded(size_t count) NOEXCEPT
693
{
694
    return count > chain::max_counted_ops;
695
}
696

697
TEMPLATE
NEW
698
INLINE bool CLASS::
×
699
sigops_increment() NOEXCEPT
700
{
701
    BC_ASSERT(is_enabled(flags::bip342_rule));
702

703
    // Executing signature op with non-empty signature decrements budget by 50.
704
    // If the budget falls below zero script fails immediately [bip342].
705

706
    // Budget is initialized +51 to make it zero-based, avoiding signed type.
NEW
707
    budget_ = floored_subtract(budget_, chain::max_counted_ops);
×
708
    return !is_zero(budget_);
709
}
710

711
TEMPLATE
712
INLINE bool CLASS::
22,409✔
713
ops_increment(const operation& op) NOEXCEPT
714
{
715
    // Non-push opcodes limit of 201 per script does not apply [bip342].
716
    if (is_enabled(flags::bip342_rule))
22,409✔
717
        return true;
718

719
    // Addition is safe due to script size constraint.
720
    BC_ASSERT(!is_add_overflow(operations_, one));
721

722
    if (operation::is_counted(op.code()))
22,409✔
723
        ++operations_;
10,530✔
724

725
    return operations_ <= chain::max_counted_ops;
22,409✔
726
}
727

728
TEMPLATE
729
INLINE bool CLASS::
2,058✔
730
ops_increment(size_t public_keys) NOEXCEPT
731
{
732
    // Non-push opcodes limit of 201 per script does not apply [bip342].
733
    if (is_enabled(flags::bip342_rule))
2,058✔
734
        return true;
735

736
    // Addition is safe due to script size constraint.
737
    BC_ASSERT(!is_add_overflow(operations_, public_keys));
738

739
    operations_ += public_keys;
2,058✔
740
    return !operation_count_exceeded(operations_);
2,058✔
741
}
742

743
// Signature validation helpers.
744
// ----------------------------------------------------------------------------
745

746
// Subscripts are referenced by script.offset mutable metadata. This allows for
747
// efficient subscripting with no copying. However, concurrent execution of any
748
// one input script instance is not thread safe (unnecessary scenario).
749
TEMPLATE
750
inline void CLASS::
9✔
751
set_subscript(const op_iterator& op) NOEXCEPT
752
{
753
    // Not possible unless op is not an element of script_.
754
    BC_ASSERT(!script_->ops().empty() && op != script_->ops().end());
755

756
    // Advance the offset to the op following the found code separator.
757
    // This is non-const because changes script state (despite being mutable).
758
    script_->offset = std::next(op);
9✔
759
}
760

761
inline chain::strippers create_strip_ops(
1,958✔
762
    const chunk_xptrs& endorsements) NOEXCEPT
763
{
764
    chain::strippers strip{};
1,958✔
765

766
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
767
    strip.reserve(add1(endorsements.size()));
1,958✔
768

769
    for (const auto& endorsement: endorsements)
1,980✔
770
        strip.emplace_back(endorsement);
22✔
771

772
    strip.emplace_back(chain::opcode::codeseparator);
1,958✔
773
    BC_POP_WARNING()
774

775
    return strip;
1,958✔
776
}
777

778
// ****************************************************************************
779
// CONSENSUS: Endorsement and code separator stripping are always performed in
780
// conjunction and are limited to non-witness signature hash subscripts.
781
// The order of operations is inconsequential, as they are all removed.
782
// Subscripts are not evaluated, they are limited to signature hash creation.
783
// ****************************************************************************
784
TEMPLATE
785
inline chain::script::cptr CLASS::
1,975✔
786
subscript(const chunk_xptrs& endorsements) const NOEXCEPT
787
{
788
    // bip141: establishes the version property.
789
    // bip143: op stripping is not applied to bip141 v0 scripts.
790
    if (is_enabled(flags::bip143_rule) &&
1,975✔
791
        version_ == script_version::segwit)
600✔
792
        return script_;
793

794
    // Transform into a set of endorsement push ops and one op_codeseparator.
795
    const auto strip = create_strip_ops(endorsements);
1,958✔
796
    const auto stop = script_->ops().end();
1,958✔
797
    const op_iterator offset{ script_->offset };
1,958✔
798
    using namespace chain;
799

800
    // If none of the strip ops are found, return the subscript.
801
    if (!is_intersecting<operations>(offset, stop, strip))
1,958✔
802
        return script_;
803

804
    // Create new script from stripped copy of subscript operations.
805
    return to_shared<script>(difference<operations>(offset, stop, strip));
8✔
806
}
1,958✔
807

808
// TODO: use sighash and key to generate signature in sign mode.
809
TEMPLATE
810
inline bool CLASS::
26✔
811
prepare(ec_signature& signature, const data_chunk&, hash_digest& hash,
812
    const chunk_xptr& endorsement) const NOEXCEPT
813
{
814
    uint8_t sighash_flags;
815
    data_slice distinguished;
26✔
816

817
    // Parse Bitcoin endorsement into DER signature and sighash flags.
818
    if (!parse_endorsement(sighash_flags, distinguished, *endorsement))
26✔
819
        return false;
820

821
    // Obtain the signature hash from subscript and sighash flags.
822
    hash = signature_hash(*subscript({ endorsement }), sighash_flags);
78✔
823

824
    // Parse DER signature into an ECDSA signature (bip66 sets strict).
825
    const auto bip66 = is_enabled(flags::bip66_rule);
826
    return parse_signature(signature, distinguished, bip66);
26✔
827
}
828

829
// TODO: use sighash and key to generate signature in sign mode.
830
TEMPLATE
831
inline bool CLASS::
20✔
832
prepare(ec_signature& signature, const data_chunk&, hash_cache& cache,
833
    uint8_t& sighash_flags, const data_chunk& endorsement,
834
    const script& subscript) const NOEXCEPT
835
{
836
    data_slice distinguished;
20✔
837

838
    // Parse Bitcoin endorsement into DER signature and sighash flags.
839
    if (!parse_endorsement(sighash_flags, distinguished, endorsement))
20✔
840
        return false;
841

842
    // Obtain the signature hash from subscript and sighash flags.
843
    signature_hash(cache, subscript, sighash_flags);
20✔
844

845
    // Parse DER signature into an ECDSA signature (bip66 sets strict).
846
    const auto bip66 = is_enabled(flags::bip66_rule);
847
    return parse_signature(signature, distinguished, bip66);
20✔
848
}
849

850
// Signature hashing.
851
// ----------------------------------------------------------------------------
852

853
TEMPLATE
854
INLINE hash_digest CLASS::
26✔
855
signature_hash(const script& subscript, uint8_t flags) const NOEXCEPT
856
{
857
    // The bip141 fork establishes witness version, hashing is a distinct fork.
858
    const auto bip143 = is_enabled(flags::bip143_rule);
859

860
    // bip143: the method of signature hashing is changed for v0 scripts.
861
    return transaction_.signature_hash(input_, subscript, value_, flags,
36✔
862
        version_, bip143);
36✔
863
}
864

865
// Caches signature hashes in a map against sighash flags.
866
// Prevents recomputation in the common case where flags are the same.
867
TEMPLATE
868
INLINE void CLASS::
20✔
869
signature_hash(hash_cache& cache, const script& subscript,
870
    uint8_t sighash_flags) const NOEXCEPT
871
{
872
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
873
    if (cache.find(sighash_flags) == cache.end())
20✔
874
        cache.emplace(sighash_flags, signature_hash(subscript, sighash_flags));
10✔
875
    BC_POP_WARNING()
876
}
877

878
} // namespace machine
879
} // namespace system
880
} // namespace libbitcoin
881

882
#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