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

libbitcoin / libbitcoin-system / 14945433772

10 May 2025 12:40PM UTC coverage: 82.466% (-0.01%) from 82.479%
14945433772

push

github

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

Refactoring to support tapscript signature hash generation.

48 of 63 new or added lines in 6 files covered. (76.19%)

10 existing lines in 6 files now uncovered.

10286 of 12473 relevant lines covered (82.47%)

3862936.9 hits per line

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

88.94
/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
    BC_ASSERT(script_->offset == script_->ops().begin());
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_)
1,496✔
70
{
71
    BC_ASSERT(script_->offset == script_->ops().begin());
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_))
17✔
85
{
86
    BC_ASSERT(script_->offset == script_->ops().begin());
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
    BC_ASSERT(script_->offset == script_->ops().begin());
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
    BC_ASSERT(script_->offset == script_->ops().begin());
UNCOV
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,936✔
227
is_enabled(flags flag) const NOEXCEPT
228
{
229
    return to_bool(flags_ & flag);
7,906✔
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
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
607
    alternate_.push_back(std::move(vary));
18✔
608
    BC_POP_WARNING()
609
}
610

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

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

622
// Conditional stack.
623
// ----------------------------------------------------------------------------
624

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

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

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

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

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

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

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

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

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

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

692
//  Accumulator.
693
// ----------------------------------------------------------------------------
694

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

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

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

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

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

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

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

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

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

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

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

753
// Signature validation helpers.
754
// ----------------------------------------------------------------------------
755

756
// Subscripts are referenced by script.offset mutable metadata. This allows for
757
// efficient subscripting with no copying. However, concurrent execution of any
758
// one input script instance is not thread safe (unnecessary scenario).
759
TEMPLATE
760
inline void CLASS::
9✔
761
set_subscript(const op_iterator& op) NOEXCEPT
762
{
763
    // Not possible unless op is not an element of script_.
764
    BC_ASSERT(!script_->ops().empty() && op != script_->ops().end());
765

766
    // Advance the offset to the op following the found code separator.
767
    // This is non-const because changes script state (despite being mutable).
768
    script_->offset = std::next(op);
9✔
769
}
770

771
inline chain::strippers create_strip_ops(
1,958✔
772
    const chunk_xptrs& endorsements) NOEXCEPT
773
{
774
    chain::strippers strip{};
1,958✔
775

776
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
777
    strip.reserve(add1(endorsements.size()));
1,958✔
778

779
    for (const auto& endorsement: endorsements)
1,980✔
780
        strip.emplace_back(endorsement);
22✔
781

782
    strip.emplace_back(chain::opcode::codeseparator);
1,958✔
783
    BC_POP_WARNING()
784

785
    return strip;
1,958✔
786
}
787

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

803
    // Transform into a set of endorsement push ops and one op_codeseparator.
804
    const auto strip = create_strip_ops(endorsements);
1,958✔
805
    const auto stop = script_->ops().end();
1,958✔
806
    const op_iterator offset{ script_->offset };
1,958✔
807

808
    // If none of the strip ops are found, return the subscript.
809
    if (!is_intersecting<operations>(offset, stop, strip))
1,958✔
810
        return script_;
811

812
    // Create new script from stripped copy of subscript operations.
813
    return to_shared<script>(difference<operations>(offset, stop, strip));
8✔
814
}
1,958✔
815

816
// private/static
817
TEMPLATE
818
inline uint32_t CLASS::
819
subscript(const script& script) NOEXCEPT
820
{
821
    // This method is only called from the run loop, which means there are ops.
822
    BC_ASSERT(!script.ops().empty());
823

824
    // BIP342: zero-based opcode position of the last executed op_codeseparator
825
    // before currently executed signature opcode (0xffffffff if none).
826
    const auto start = script.ops().begin();
827
    const auto span = std::distance(start, script.offset);
828
    const auto slot = possible_narrow_and_sign_cast<uint32_t>(span);
829
    const auto none = is_zero(slot) && start->code() != opcode::codeseparator;
830
    return none ? chain::default_separators : slot;
831
}
832

833
// TODO: use sighash and key to generate signature in sign mode.
834
TEMPLATE
835
inline bool CLASS::
20✔
836
ecdsa_prepare(ec_signature& signature, hash_digest& hash,
837
    const chunk_xptr& endorsement, const script& subscript) const NOEXCEPT
838
{
839
    uint8_t sighash_flags;
840
    data_slice distinguished;
20✔
841
    if (!ecdsa::parse_endorsement(sighash_flags, distinguished, *endorsement))
20✔
842
        return false;
843

844
    // TODO: re-evaluate multisig hash caching.
845
    ////hash_cache cache{};
846
    ////const auto& hash = cache.at(sighash_flags);
847

848
    hash = signature_hash(subscript, sighash_flags);
20✔
849
    const auto bip66 = is_enabled(flags::bip66_rule);
850
    return ecdsa::parse_signature(signature, distinguished, bip66);
20✔
851
}
852

853
// TODO: use sighash and key to generate signature in sign mode.
854
TEMPLATE
855
inline bool CLASS::
26✔
856
ecdsa_prepare(ec_signature& signature, hash_digest& hash,
857
    const chunk_xptr& endorsement) const NOEXCEPT
858
{
859
    uint8_t sighash_flags;
860
    data_slice distinguished;
26✔
861
    if (!ecdsa::parse_endorsement(sighash_flags, distinguished, *endorsement))
26✔
862
        return false;
863

864
    hash = signature_hash(*subscript({ endorsement }), sighash_flags);
78✔
865
    const auto bip66 = is_enabled(flags::bip66_rule);
866
    return ecdsa::parse_signature(signature, distinguished, bip66);
26✔
867
}
868

869
// TODO: can we use sighash and key to generate signature in sign mode?
870
TEMPLATE
NEW
871
inline bool CLASS::
×
872
schnorr_prepare(ec_signature& signature, hash_digest& hash,
873
    const chunk_xptr& endorsement) const NOEXCEPT
874
{
875
    uint8_t sighash_flags;
NEW
876
    if (!schnorr::parse(sighash_flags, signature, *endorsement))
×
877
        return false;
878

NEW
879
    hash = signature_hash(*script_, sighash_flags);
×
NEW
880
    return true;
×
881
}
882

883
// Signature hashing.
884
// ----------------------------------------------------------------------------
885

886
TEMPLATE
887
INLINE hash_digest CLASS::
46✔
888
signature_hash(const script& subscript, uint8_t sighash_flags) const NOEXCEPT
889
{
890
    // bip143: the method of signature hashing is changed for v0 scripts.
891
    // bip342: the method of signature hashing is changed for v1 scripts.
892
    const auto bip143 = is_enabled(flags::bip143_rule);
893
    const auto bip342 = is_enabled(flags::bip342_rule);
894

895
    return transaction_.signature_hash(input_, subscript, value_,
46✔
896
        sighash_flags, version_, bip143, bip342);
46✔
897
}
898

899
// Caches signature hashes in a map against sighash flags.
900
// Prevents recomputation in the common case where flags are the same.
901
TEMPLATE
902
INLINE void CLASS::
903
signature_hash(hash_cache& cache, const script& subscript,
904
    uint8_t sighash_flags) const NOEXCEPT
905
{
906
    if (cache.find(sighash_flags) == cache.end())
907
        cache.emplace(sighash_flags, signature_hash(subscript, sighash_flags));
908
}
909

910
} // namespace machine
911
} // namespace system
912
} // namespace libbitcoin
913

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