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

libbitcoin / libbitcoin-system / 14967864636

12 May 2025 08:47AM UTC coverage: 82.12% (-0.2%) from 82.297%
14967864636

push

github

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

Taproot stack extraction WIP.

38 of 82 new or added lines in 4 files covered. (46.34%)

6 existing lines in 2 files now uncovered.

10320 of 12567 relevant lines covered (82.12%)

3834007.69 hits per line

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

84.65
/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_()
4,677✔
52
{
53
    script_->clear_offset();
1,559✔
54
}
1,559✔
55

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

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

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

110
// Taproot script run (witness-initialized stack).
111
// Same as segwit but with with budget and unstripped bip342 flag.
112
// Sigop budget is 50 plus size of prefixed serialized witness [bip342].
113
// Budget is initialized add1(50) to make it zero-based, avoiding signed type.
114
// This program is never used to construct another, so masked flags_ never mix.
115
TEMPLATE
116
inline CLASS::
×
117
program(const transaction& tx, const input_iterator& input,
118
    const script::cptr& script, uint32_t active_flags,
119
    script_version version, const chunk_cptrs_ptr& witness, bool) NOEXCEPT
UNCOV
120
  : transaction_(tx),
×
121
    input_(input),
×
122
    script_(script),
123
    flags_(active_flags),
×
124
    value_((*input)->prevout->value()),
×
125
    version_(version),
×
126
    witness_(witness),
127
    primary_(projection<Stack>(*witness)),
×
NEW
128
    budget_(ceilinged_add(
×
129
        add1(chain::signature_budget),
NEW
130
        chain::witness::serialized_size(*witness_, true)))
×
131
{
132
    script_->clear_offset();
×
133
}
×
134

135
// Public.
136
// ----------------------------------------------------------------------------
137

138
TEMPLATE
139
inline bool CLASS::
1,088✔
140
is_true(bool clean_stack) const NOEXCEPT
141
{
142
    return (!clean_stack || is_stack_clean()) && !is_stack_empty() &&
3,244✔
143
        peek_bool_();
1,088✔
144
}
145

146
TEMPLATE
147
inline const data_chunk& CLASS::
17✔
148
pop() NOEXCEPT
149
{
150
    BC_ASSERT_MSG(!is_stack_empty(), "pop from empty stack");
151

152
    return *pop_chunk_();
17✔
153
}
154

155
// Non-public.
156
// ============================================================================
157

158
TEMPLATE
159
INLINE error::script_error_t CLASS::
3,095✔
160
initialize() const NOEXCEPT
161
{
162
    // TODO: nops rule must first be enabled in tests and config.
163
    constexpr auto nops = true; ////is_enabled(flags::nops_rule);
164
    const auto bip141 = is_enabled(flags::bip141_rule);
165
    const auto bip342 = is_enabled(flags::bip342_rule);
166

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

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

175
    // Stacks element limit (1,000) applied to initial stack [bip342].
176
    if (bip342 && is_stack_overflow())
×
177
        return error::invalid_stack_size;
178

179
    // Succeed if any success code, one overrides all codes [bip342].
180
    if (bip342 && script_->is_prevalid())
×
181
        return error::prevalid_script;
182

183
    // Fail if last op underflow, lower priority than success codes [bip342].
184
    if (script_->is_underflow())
3,093✔
185
        return error::invalid_script;
186

187
    // Fail if any op invalid (invalid codes reduced in tapscript).
188
    // Should be after underflow check since underflow is also an invalid op.
189
    // Promoted success codes are not reachable here due to is_prevalid above.
190
    // So only op_verif/op_vernotif (unpromoted invalids) are caught here for
191
    // tapscript, otherwise is_prevalid bypassed and all invalids caught here.
192
    if (script_->is_prefail())
3,093✔
193
        return error::prefail_script;
194

195
    return error::script_success;
196
}
197

198
TEMPLATE
199
INLINE typename CLASS::op_iterator CLASS::
3,033✔
200
begin() const NOEXCEPT
201
{
202
    return script_->ops().begin();
3,033✔
203
}
204

205
TEMPLATE
206
INLINE typename CLASS::op_iterator CLASS::
25,009✔
207
end() const NOEXCEPT
208
{
209
    return script_->ops().end();
25,009✔
210
}
211

212
TEMPLATE
213
INLINE const chain::transaction& CLASS::
7✔
214
tx() const NOEXCEPT
215
{
216
    return transaction_;
7✔
217
}
218

219
TEMPLATE
220
INLINE const chain::input& CLASS::
18✔
221
input() const NOEXCEPT
222
{
223
    return **input_;
224
}
225

226
TEMPLATE
227
INLINE bool CLASS::
38,855✔
228
is_enabled(flags flag) const NOEXCEPT
229
{
230
    return to_bool(flags_ & flag);
9,881✔
231
}
232

233
// Primary stack (conversions).
234
// ----------------------------------------------------------------------------
235

236
// static
237
TEMPLATE
238
INLINE bool CLASS::
560✔
239
equal_chunks(const stack_variant& left, const stack_variant& right) NOEXCEPT
240
{
241
    return primary_stack::equal_chunks(left, right);
560✔
242
}
243

244
TEMPLATE
245
INLINE bool CLASS::
1,593✔
246
peek_bool_() const NOEXCEPT
247
{
248
    return primary_.peek_bool();
1,593✔
249
}
250

251
TEMPLATE
252
INLINE chunk_xptr CLASS::
3,578✔
253
peek_chunk_() const NOEXCEPT
254
{
255
    return primary_.peek_chunk();
3,578✔
256
}
257

258
TEMPLATE
259
INLINE size_t CLASS::
58✔
260
peek_size() const NOEXCEPT
261
{
262
    return primary_.peek_size();
58✔
263
}
264

265
// Primary stack (push).
266
// ----------------------------------------------------------------------------
267

268
// This is the only source of push (write) tethering.
269
TEMPLATE
270
INLINE void CLASS::
167✔
271
push_chunk(data_chunk&& datum) NOEXCEPT
272
{
273
    primary_.push(std::move(datum));
274
}
275

276
// Passing data_chunk& would be poor interface design, as it would allow
277
// derived callers to (unsafely) store raw pointers to unshared data_chunk.
278
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
279
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
280
TEMPLATE
281
INLINE void CLASS::
4,474✔
282
push_chunk(const chunk_cptr& datum) NOEXCEPT
283
BC_POP_WARNING()
284
BC_POP_WARNING()
285
{
286
    primary_.emplace_chunk(datum.get());
8,948✔
287
}
288

289
// private
290
TEMPLATE
291
INLINE void CLASS::
292
push_chunk(const chunk_xptr& datum) NOEXCEPT
293
{
294
    primary_.emplace_chunk(datum);
295
}
296

297
TEMPLATE
298
INLINE void CLASS::
2,018✔
299
push_bool(bool value) NOEXCEPT
300
{
301
    primary_.emplace_boolean(value);
2,018✔
302
}
303

304
TEMPLATE
305
INLINE void CLASS::
7,256✔
306
push_signed64(int64_t value) NOEXCEPT
307
{
308
    primary_.emplace_integer(value);
7,073✔
309
}
310

311
TEMPLATE
312
INLINE void CLASS::
241✔
313
push_length(size_t value) NOEXCEPT
314
{
315
    // This is guarded by stack size and push data limits.
316
    BC_ASSERT_MSG(value <= max_int64, "integer overflow");
317

318
    push_signed64(possible_narrow_sign_cast<int64_t>(value));
241✔
319
}
320

321
// Primary stack (pop).
322
// ----------------------------------------------------------------------------
323

324
// This tethers a chunk if the stack value is not chunk.
325
TEMPLATE
326
INLINE chunk_xptr CLASS::
3,552✔
327
pop_chunk_() NOEXCEPT
328
{
329
    const auto value = peek_chunk_();
330
    drop_();
331
    return value;
193✔
332
}
333

334
// This tethers chunks if the stack values are not chunk.
335
TEMPLATE
336
INLINE bool CLASS::
4,102✔
337
pop_chunks(chunk_xptrs& data, size_t count) NOEXCEPT
338
{
339
    if (stack_size() < count)
4,102✔
340
        return false;
341

342
    data.reserve(count);
4,102✔
343
    for (size_t index = 0; index < count; ++index)
7,444✔
344
        data.push_back(pop_chunk_());
3,342✔
345

346
    return true;
347
}
348

349
TEMPLATE
350
INLINE bool CLASS::
2,050✔
351
pop_strict_bool_() NOEXCEPT
352
{
353
    const auto value = primary_.peek_strict_bool();
2,050✔
354
    drop_();
355
    return value;
356
}
357

358
TEMPLATE
359
INLINE bool CLASS::
446✔
360
pop_bool_(bool& value, bool minimal) NOEXCEPT
361
{
362
    if (!minimal)
446✔
363
        value = peek_bool_();
446✔
364
    else if (!primary_.peek_minimal_bool(value))
×
365
        return false;
366

367
    drop_();
368
    return true;
369
}
370

371
TEMPLATE
372
INLINE bool CLASS::
4,738✔
373
pop_signed32_(int32_t& value) NOEXCEPT
374
{
375
    const auto result = peek_signed32_(value);
376
    drop_();
377
    return result;
378
}
379

380
TEMPLATE
381
INLINE bool CLASS::
4,272✔
382
pop_signed32(int32_t& value) NOEXCEPT
383
{
384
    if (is_stack_empty())
4,272✔
385
        return false;
386

387
    return pop_signed32_(value);
388
}
389

390
TEMPLATE
391
INLINE bool CLASS::
242✔
392
pop_binary32(int32_t& left, int32_t& right) NOEXCEPT
393
{
394
    if (stack_size() < 2)
242✔
395
        return false;
396

397
    // The right hand side operand is at the top of the stack.
398
    return pop_signed32_(right) && pop_signed32_(left);
430✔
399
}
400

401
TEMPLATE
402
INLINE bool CLASS::
18✔
403
pop_ternary32(int32_t& upper, int32_t& lower,
404
    int32_t& value) NOEXCEPT
405
{
406
    if (stack_size() < 3)
18✔
407
        return false;
408

409
    // The upper bound is at stack top, lower bound next, value next.
410
    return pop_signed32_(upper) && pop_signed32_(lower) &&
48✔
411
        pop_signed32_(value);
412
}
413

414
// ****************************************************************************
415
// CONSENSUS: Satoshi limits this value to the int32_t domain (getint()).
416
// This value is only used for stack indexing (key/sig counts & pick/roll).
417
// The upper bound of int32_t always exceeds the possible stack size, which
418
// is checked downstream. Similarly, a negative causes a downstream script
419
// failure. As such it is sufficient to fail on non-idexability here,
420
// allowing the value to be returned as a valid and unsigned stack index.
421
// ****************************************************************************
422
TEMPLATE
423
INLINE bool CLASS::
4,160✔
424
pop_index32(size_t& index) NOEXCEPT
425
{
426
    int32_t value;
427
    if (!pop_signed32(value))
4,160✔
428
        return false;
429

430
    if (is_negative(value))
4,160✔
431
        return false;
432

433
    // Cast guarded by stack size.
434
    index = limit<size_t>(value);
46✔
435

436
    // True if popped value valid post-pop stack index (precluded if size < 2).
437
    return index < stack_size();
4,156✔
438
}
439

440
// private
441
TEMPLATE
442
INLINE bool CLASS::
246✔
443
peek_signed32_(int32_t& value) const NOEXCEPT
444
{
445
    return primary_.peek_signed4(value);
4,492✔
446
}
447

448
// private
449
TEMPLATE
450
INLINE bool CLASS::
12✔
451
peek_signed40_(int64_t& value) const NOEXCEPT
452
{
453
    return primary_.peek_signed5(value);
12✔
454
}
455

456
// ****************************************************************************
457
// CONSENSUS: Read of 40 bit (vs. 32 bit) value for comparison against uint32_t
458
// input.sequence allows use of the full unsigned 32 bit domain, without use of
459
// the negative range.
460
// ****************************************************************************
461
TEMPLATE
462
INLINE bool CLASS::
×
463
peek_unsigned32(uint32_t& value) const NOEXCEPT
464
{
465
    if (is_stack_empty())
×
466
        return false;
467

468
    int64_t signed64;
469
    if (!peek_signed40_(signed64) || is_negative(signed64))
×
470
        return false;
471

472
    // 32 bits are used in unsigned input.sequence compare.
473
    value = narrow_sign_cast<uint32_t>(signed64);
474
    return true;
×
475
}
476

477
// ****************************************************************************
478
// CONSENSUS: Read of 40 bit (vs. 32 bit) value for comparison against uint32_t
479
// input.locktime allows use of the full unsigned 32 bit domain, without use of
480
// the negative range. Otherwise a 2038 limit (vs. the inherent 2106 limit)
481
// would have been introduced.
482
// ****************************************************************************
483
TEMPLATE
484
INLINE bool CLASS::
18✔
485
peek_unsigned40(uint64_t& value) const NOEXCEPT
486
{
487
    if (is_stack_empty())
18✔
488
        return false;
489

490
    int64_t signed64;
491
    if (!peek_signed40_(signed64) || is_negative(signed64))
12✔
492
        return false;
493

494
    // 40 bits are usable in unsigned tx.locktime compare.
495
    value = sign_cast<uint64_t>(signed64);
496
    return true;
7✔
497
}
498

499
// Primary stack (variant - index).
500
// ----------------------------------------------------------------------------
501
// Stack index is zero-based, back() is element zero.
502

503
// This swaps the variant elements of the stack vector.
504
TEMPLATE
505
INLINE void CLASS::
174✔
506
swap_(size_t left_index, size_t right_index) NOEXCEPT
507
{
508
    primary_.swap(left_index, right_index);
509
}
510

511
TEMPLATE
512
INLINE void CLASS::
16✔
513
erase_(size_t index) NOEXCEPT
514
{
515
    primary_.erase(index);
516
}
517

518
TEMPLATE
519
INLINE const stack_variant& CLASS::
9,916✔
520
peek_(size_t index) const NOEXCEPT
521
{
522
    return primary_.peek(index);
523
}
524

525
// Primary stack (variant - top).
526
// ----------------------------------------------------------------------------
527

528
TEMPLATE
529
INLINE void CLASS::
10,901✔
530
drop_() NOEXCEPT
531
{
532
    primary_.drop();
533
}
534

535
TEMPLATE
536
INLINE void CLASS::
9,957✔
537
push_variant(const stack_variant& vary) NOEXCEPT
538
{
539
    primary_.push(vary);
540
}
4✔
541

542
TEMPLATE
543
INLINE const stack_variant& CLASS::
35✔
544
peek_() const NOEXCEPT
545
{
546
    return primary_.top();
547
}
548

549
TEMPLATE
550
INLINE stack_variant CLASS::
1,138✔
551
pop_() NOEXCEPT
552
{
553
    return primary_.pop();
554
}
555

556
// Primary stack state (untyped).
557
// ----------------------------------------------------------------------------
558

559
TEMPLATE
560
INLINE size_t CLASS::
12,749✔
561
stack_size() const NOEXCEPT
562
{
563
    return primary_.size();
564
}
565

566
TEMPLATE
567
INLINE bool CLASS::
8,289✔
568
is_stack_empty() const NOEXCEPT
569
{
570
    return primary_.empty();
571
}
572

573
TEMPLATE
574
INLINE bool CLASS::
20,900✔
575
is_stack_overflow() const NOEXCEPT
576
{
577
    // Addition is safe due to stack size constraint.
578
    // Limit of 1000 elements in stack and altstack remains [bip342]. 
579
    return (stack_size() + alternate_.size()) > chain::max_unified_stack_size;
20,900✔
580
}
581

582
// private
583
TEMPLATE
584
INLINE bool CLASS::
21✔
585
is_stack_clean() const NOEXCEPT
586
{
587
    return is_one(stack_size());
588
}
589

590
// Alternate stack.
591
// ----------------------------------------------------------------------------
592

593
TEMPLATE
594
INLINE bool CLASS::
10✔
595
is_alternate_empty() const NOEXCEPT
596
{
597
    return alternate_.empty();
598
}
599

600
// Moving a shared pointer to the alternate stack is optimal and acceptable.
601
BC_PUSH_WARNING(NO_RVALUE_REF_SHARED_PTR)
602
TEMPLATE
603
INLINE void CLASS::
18✔
604
push_alternate(stack_variant&& vary) NOEXCEPT
605
BC_POP_WARNING()
606
{
607
    alternate_.push_back(std::move(vary));
18✔
608
}
609

610
TEMPLATE
611
INLINE stack_variant CLASS::
6✔
612
pop_alternate_() NOEXCEPT
613
{
614
    BC_ASSERT(!alternate_.empty());
615

616
    stack_variant value{ std::move(alternate_.back()) };
6✔
617
    alternate_.pop_back();
6✔
618
    return value;
6✔
619
}
620

621
// Conditional stack.
622
// ----------------------------------------------------------------------------
623

624
TEMPLATE
625
INLINE void CLASS::
474✔
626
begin_if(bool value) NOEXCEPT
627
{
628
    // Addition is safe due to script size constraint.
629
    BC_ASSERT(value || !is_add_overflow(negative_conditions_, one));
630

631
    negative_conditions_ += (value ? 0 : 1);
474✔
632
    condition_.push_back(value);
474✔
633
}
634

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

649
    // Addition is safe due to script size constraint.
650
    BC_ASSERT(condition_.back() || !is_add_overflow(negative_conditions_, one));
651

652
    negative_conditions_ += (condition_.back() ? 1 : -1);
442✔
653
    condition_.back() = !condition_.back();
442✔
654
}
655

656
TEMPLATE
657
INLINE void CLASS::
308✔
658
end_if_() NOEXCEPT
659
{
660
    // Subtraction must be guarded by caller logical constraints.
661
    BC_ASSERT(!is_balanced());
662

663
    negative_conditions_ += (condition_.back() ? 0 : -1);
308✔
664
    condition_.pop_back();
308✔
665
}
666

667
TEMPLATE
668
INLINE bool CLASS::
3,368✔
669
is_balanced() const NOEXCEPT
670
{
671
    return condition_.empty();
3,368✔
672
}
673

674
TEMPLATE
675
INLINE bool CLASS::
21,630✔
676
is_succeess() const NOEXCEPT
677
{
678
    // Optimization changes O(n) search [for every operation] to O(1).
679
    // bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts
680
    return is_zero(negative_conditions_);
21,630✔
681
}
682

683
TEMPLATE
684
INLINE bool CLASS::
22,402✔
685
if_(const operation& op) const NOEXCEPT
686
{
687
    // Conditional op execution is not predicated on conditional stack.
688
    return op.is_conditional() || is_succeess();
22,402✔
689
}
690

691
//  Accumulator.
692
// ----------------------------------------------------------------------------
693

694
// ****************************************************************************
695
// CONSENSUS:
696
// Satoshi compares the count to 200 with a composed postfix increment, which
697
// makes the actual maximum 201, not the presumably-intended 200. The code was
698
// later revised to make this explicit, by use of a prefix increment against a
699
// limit of 201.
700
// ****************************************************************************
701
INLINE constexpr bool operation_count_exceeded(size_t count) NOEXCEPT
702
{
703
    return count > chain::max_counted_ops;
704
}
705

706
TEMPLATE
707
INLINE bool CLASS::
×
708
sigops_increment() NOEXCEPT
709
{
710
    BC_ASSERT(is_enabled(flags::bip342_rule));
711

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

715
    // Budget initialized add1(50) to make it zero-based, avoiding signed type.
716
    budget_ = floored_subtract(budget_, chain::max_counted_ops);
×
717
    return !is_zero(budget_);
718
}
719

720
TEMPLATE
721
INLINE bool CLASS::
22,409✔
722
ops_increment(const operation& op) NOEXCEPT
723
{
724
    // Non-push opcodes limit of 201 per script does not apply [bip342].
725
    if (is_enabled(flags::bip342_rule))
22,409✔
726
        return true;
727

728
    // Addition is safe due to script size constraint.
729
    BC_ASSERT(!is_add_overflow(operations_, one));
730

731
    if (operation::is_counted(op.code()))
22,409✔
732
        ++operations_;
10,530✔
733

734
    return operations_ <= chain::max_counted_ops;
22,409✔
735
}
736

737
TEMPLATE
738
INLINE bool CLASS::
2,058✔
739
ops_increment(size_t public_keys) NOEXCEPT
740
{
741
    // Non-push opcodes limit of 201 per script does not apply [bip342].
742
    if (is_enabled(flags::bip342_rule))
2,058✔
743
        return true;
744

745
    // Addition is safe due to script size constraint.
746
    BC_ASSERT(!is_add_overflow(operations_, public_keys));
747

748
    operations_ += public_keys;
2,058✔
749
    return !operation_count_exceeded(operations_);
2,058✔
750
}
751

752
// Endorsement parsing.
753
// ----------------------------------------------------------------------------
754

755
// static
756
// BIP341: Using any undefined hash_type causes validation failure if violated.
757
// defined types: 0x00, 0x01, 0x02, 0x03, 0x81, 0x82, or 0x83. [zero is the
758
// default and cannot be explicit, but is serialized for signature hashing].
759
TEMPLATE
760
inline bool CLASS::
×
761
is_schnorr_sighash(uint8_t sighash_flags) NOEXCEPT
762
{
763
    using namespace chain;
764

765
    switch (sighash_flags)
×
766
    {
767
        // BIP341: zero is invalid sighash, must be explicit to prevent mally.
768
        ////case coverage::hash_default:
769
        case coverage::hash_all:
770
        case coverage::hash_none:
771
        case coverage::hash_single:
772
        case coverage::all_anyone_can_pay:
773
        case coverage::none_anyone_can_pay:
774
        case coverage::single_anyone_can_pay:
775
            return true;
776
        default:
×
777
            return false;
×
778
    }
779
}
780

781
// static
782
TEMPLATE
783
inline const ec_signature& CLASS::
×
784
schnorr_split(uint8_t& sighash_flags, const data_chunk& endorsement) NOEXCEPT
785
{
786
    using namespace chain;
787
    using namespace schnorr;
788

789
    sighash_flags = coverage::invalid;
×
790
    const auto size = endorsement.size();
791

792
    if (size == signature_size)
×
793
    {
794
        // BIP341: if [sighash byte] is omitted the resulting signatures are 64
795
        // bytes, and [default == 0] mode is implied (implies SIGHASH_ALL).
796
        sighash_flags = coverage::hash_default;
×
797
    }
798
    else if (size == add1(signature_size))
×
799
    {
800
        // BIP341: signature has sighash byte appended in the usual fashion.
801
        const auto byte = endorsement.back();
×
802
        if (is_schnorr_sighash(byte))
×
803
            sighash_flags = byte;
×
804
    }
805
    else
806
    {
807
        // This makes an invalid return safe to dereference, and may be
808
        // compiled out unless a caller does in fact access it.
809
        static constexpr ec_signature empty{};
810
        return empty;
811
    }
812

813
    return unsafe_array_cast<uint8_t, signature_size>(endorsement.data());
×
814
}
815

816
// static
817
TEMPLATE
818
inline data_slice CLASS::
46✔
819
ecdsa_split(uint8_t& sighash_flags, const data_chunk& endorsement) NOEXCEPT
820
{
821
    BC_ASSERT(!endorsement.empty());
822
    sighash_flags = endorsement.back();
46✔
823

824
    // data_slice is returned since the size of the DER encoding is not fixed.
825
    return { endorsement.begin(), std::prev(endorsement.end()) };
46✔
826
}
827

828
// Signature subscripting.
829
// ----------------------------------------------------------------------------
830

831
// Subscripts are referenced by script.offset mutable metadata. This allows for
832
// efficient subscripting with no copying. As a result concurrent execution of
833
// any one input script instance is not thread safe.
834
TEMPLATE
835
inline void CLASS::
9✔
836
set_subscript(const op_iterator& op) NOEXCEPT
837
{
838
    // Not possible unless op is not an element of script_.
839
    BC_ASSERT(!script_->ops().empty() && op != script_->ops().end());
840

841
    // Advance the offset to the op following the found code separator.
842
    // This is non-const because changes script state (despite being mutable).
843
    script_->offset = std::next(op);
9✔
844
}
845

846
// static/private
847
TEMPLATE
848
inline chain::strippers CLASS::
1,948✔
849
create_strip_ops(const chunk_xptrs& endorsements) NOEXCEPT
850
{
851
    chain::strippers strip{};
1,948✔
852
    strip.reserve(add1(endorsements.size()));
1,948✔
853
    for (const auto& endorsement: endorsements)
1,960✔
854
        strip.emplace_back(endorsement);
12✔
855

856
    strip.emplace_back(chain::opcode::codeseparator);
1,948✔
857
    return strip;
1,948✔
858
}
859

860
// static/private
861
TEMPLATE
862
inline chain::strippers CLASS::
10✔
863
create_strip_ops(const chunk_xptr& endorsement) NOEXCEPT
864
{
865
    using namespace chain;
866
    return { stripper{ endorsement }, stripper{ opcode::codeseparator } };
20✔
867
}
868

869
// ****************************************************************************
870
// CONSENSUS: Endorsement and code separator stripping are always performed in
871
// conjunction and are limited to non-witness signature hash subscripts.
872
// The order of operations is inconsequential, as they are all removed.
873
// Subscripts are not evaluated, they are limited to signature hash creation.
874
// ****************************************************************************
875
TEMPLATE
876
inline chain::script::cptr CLASS::
1,949✔
877
subscript(const chunk_xptrs& endorsements) const NOEXCEPT
878
{
879
    // bip141: establishes the version property.
880
    // bip143: op stripping is not applied to bip141 v0 scripts.
881
    if (is_enabled(flags::bip143_rule) && version_ == script_version::segwit)
1,949✔
882
        return script_;
883

884
    // Transform into a set of endorsement push ops and one op_codeseparator.
885
    const auto strip = create_strip_ops(endorsements);
1,948✔
886
    const auto stop = script_->ops().end();
1,948✔
887
    const op_iterator start{ script_->offset };
1,948✔
888

889
    // If none of the strip ops are found, return the subscript.
890
    if (!is_intersecting<operations>(start, stop, strip))
1,948✔
891
        return script_;
892

893
    // Create new script from stripped copy of subscript operations.
894
    return to_shared<script>(difference<operations>(start, stop, strip));
2✔
895
}
896

897
TEMPLATE
898
inline chain::script::cptr CLASS::
26✔
899
subscript(const chunk_xptr& endorsement) const NOEXCEPT
900
{
901
    // bip141: establishes the version property.
902
    // bip143: op stripping is not applied to bip141 v0 scripts.
903
    if (is_enabled(flags::bip143_rule) && version_ == script_version::segwit)
26✔
904
        return script_;
905

906
    // Transform into a set with one endorsement push op and op_codeseparator.
907
    const auto strip = create_strip_ops(endorsement);
10✔
908
    const auto stop = script_->ops().end();
10✔
909
    const op_iterator start{ script_->offset };
10✔
910

911
    // If none of the strip ops are found, return the subscript.
912
    if (!is_intersecting<operations>(start, stop, strip))
10✔
913
        return script_;
914

915
    // Create new script from stripped copy of subscript operations.
916
    return to_shared<script>(difference<operations>(start, stop, strip));
6✔
917
}
918

919
TEMPLATE
920
inline const chain::script& CLASS::
×
921
subscript() const NOEXCEPT
922
{
923
    return *script_;
924
}
925

926
// private/static
927
TEMPLATE
928
inline uint32_t CLASS::
929
subscript(const script& script) NOEXCEPT
930
{
931
    // This method is only called from the run loop, which means there are ops.
932
    BC_ASSERT(!script.ops().empty());
933

934
    // BIP342: zero-based opcode position of the last executed op_codeseparator
935
    // before currently executed signature opcode (0xffffffff if none).
936
    const auto start = script.ops().begin();
937
    const auto span = std::distance(start, script.offset);
938
    const auto slot = possible_narrow_and_sign_cast<uint32_t>(span);
939
    const auto none = is_zero(slot) && start->code() != opcode::codeseparator;
940
    return none ? chain::default_separators : slot;
941
}
942

943
// Signature hashing.
944
// ----------------------------------------------------------------------------
945

946
TEMPLATE
947
INLINE hash_digest CLASS::
×
948
signature_hash(uint8_t sighash_flags) const NOEXCEPT
949
{
950
    return signature_hash(subscript(), sighash_flags);
951
}
952

953
TEMPLATE
954
INLINE hash_digest CLASS::
26✔
955
signature_hash(const script& subscript, uint8_t sighash_flags) const NOEXCEPT
956
{
957
    // bip143: the method of signature hashing is changed for v0 scripts.
958
    // bip342: the method of signature hashing is changed for v1 scripts.
959
    const auto bip143 = is_enabled(flags::bip143_rule);
960
    const auto bip342 = is_enabled(flags::bip342_rule);
961

962
    return transaction_.signature_hash(input_, subscript, value_,
36✔
963
        sighash_flags, version_, bip143, bip342);
36✔
964
}
965

966
/// Multisig signature hash caching.
967
/// -----------------------------------------------------------------------
968

969
TEMPLATE
970
INLINE void CLASS::
1,949✔
971
initialize_cache() NOEXCEPT
972
{
973
    cache_.first = true;
1,949✔
974
}
975

976
TEMPLATE
977
INLINE bool CLASS::
20✔
978
uncached(uint8_t sighash_flags) const NOEXCEPT
979
{
980
    return cache_.first || cache_.flags != sighash_flags;
20✔
981
}
982

983
TEMPLATE
984
INLINE void CLASS::
10✔
985
set_hash(const chain::script& subscript,
986
    uint8_t sighash_flags) NOEXCEPT
987
{
988
    cache_.first = false;
10✔
989
    cache_.flags = sighash_flags;
10✔
990
    cache_.hash = signature_hash(subscript, sighash_flags);
10✔
991
}
10✔
992

993
TEMPLATE
994
INLINE const hash_digest& CLASS::
20✔
995
cached_hash() const NOEXCEPT
996
{
997
    return cache_.hash;
20✔
998
}
999

1000
} // namespace machine
1001
} // namespace system
1002
} // namespace libbitcoin
1003

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