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

libbitcoin / libbitcoin-system / 14957620207

11 May 2025 04:23PM UTC coverage: 82.287% (-0.2%) from 82.469%
14957620207

push

github

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

Refactor sig operations, reintroduce multisighash caching.

54 of 124 new or added lines in 8 files covered. (43.55%)

9 existing lines in 6 files now uncovered.

10299 of 12516 relevant lines covered (82.29%)

3849629.69 hits per line

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

84.26
/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_()
3,118✔
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,
120
    size_t witness_size) NOEXCEPT
121
  : transaction_(tx),
×
122
    input_(input),
×
123
    script_(script),
124
    flags_(active_flags),
×
125
    value_((*input)->prevout->value()),
×
126
    version_(version),
×
127
    witness_(witness),
128
    primary_(projection<Stack>(*witness)),
×
129
    budget_(ceilinged_add(add1(chain::signature_budget), witness_size))
×
130
{
131
    script_->clear_offset();
×
132
}
×
133

134
// Public.
135
// ----------------------------------------------------------------------------
136

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

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

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

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

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

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

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

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

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

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

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

194
    return error::script_success;
195
}
196

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

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

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

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

225
TEMPLATE
226
INLINE bool CLASS::
36,926✔
227
is_enabled(flags flag) const NOEXCEPT
228
{
229
    return to_bool(flags_ & flag);
7,952✔
230
}
231

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

345
    return true;
346
}
347

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

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

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

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

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

386
    return pop_signed32_(value);
387
}
388

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

589
// Alternate stack.
590
// ----------------------------------------------------------------------------
591

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

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

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

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

620
// Conditional stack.
621
// ----------------------------------------------------------------------------
622

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

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

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

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

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

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

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

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

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

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

690
//  Accumulator.
691
// ----------------------------------------------------------------------------
692

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

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

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

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

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

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

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

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

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

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

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

751
// Endorsement parsing.
752
// ----------------------------------------------------------------------------
753

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

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

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

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

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

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

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

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

827
// Signature subscripting.
828
// ----------------------------------------------------------------------------
829

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

942
// Signature hashing.
943
// ----------------------------------------------------------------------------
944

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

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

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

965
} // namespace machine
966
} // namespace system
967
} // namespace libbitcoin
968

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