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

libbitcoin / libbitcoin-system / 13069453084

31 Jan 2025 08:55AM UTC coverage: 82.728% (-0.007%) from 82.735%
13069453084

push

github

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

Set _CRTDBG_MAP_ALLOC for vc++ debug mode leak tracking.

2 of 2 new or added lines in 1 file covered. (100.0%)

15 existing lines in 11 files now uncovered.

10039 of 12135 relevant lines covered (82.73%)

3871639.49 hits per line

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

96.74
/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/machine/interpreter.hpp>
30
#include <bitcoin/system/math/math.hpp>
31

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

36
using namespace system::chain;
37
using namespace system::error;
38

39
// Constructors.
40
// ----------------------------------------------------------------------------
41

42
// Input script run (default/empty stack).
43
// 'tx' must remain in scope, this holds state referenced by weak pointers.
44
// This expectation is guaranteed by the retained tx reference.
45
template <typename Stack>
46
inline program<Stack>::
1,559✔
47
program(const chain::transaction& tx, const input_iterator& input,
48
     uint32_t active_flags) NOEXCEPT
49
  : transaction_(tx),
1,559✔
50
    input_(input),
1,559✔
51
    script_((*input)->script_ptr()),
1,559✔
52
    flags_(active_flags),
1,559✔
53
    value_(max_uint64),
1,559✔
54
    version_(script_version::unversioned),
1,559✔
55
    witness_(),
56
    primary_()
1,559✔
57
{
58
}
1,559✔
59

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

78
// Legacy p2sh or prevout script run (moved input stack/tether - use last).
79
template <typename Stack>
80
inline program<Stack>::
17✔
81
program(program&& other, const script::cptr& script) NOEXCEPT
82
  : transaction_(other.transaction_),
17✔
83
    input_(other.input_),
17✔
84
    script_(script),
85
    flags_(other.flags_),
17✔
86
    value_(other.value_),
17✔
87
    version_(other.version_),
17✔
88
    witness_(),
89
    primary_(std::move(other.primary_))
17✔
90
{
91
}
17✔
92

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

113
// Public.
114
// ----------------------------------------------------------------------------
115

116
template <typename Stack>
117
inline bool program<Stack>::
1,088✔
118
is_true(bool clean_stack) const NOEXCEPT
119
{
120
    return (!clean_stack || is_stack_clean()) && !is_stack_empty() &&
3,244✔
121
        peek_bool_();
1,088✔
122
}
123

124
template <typename Stack>
125
inline const data_chunk& program<Stack>::
17✔
126
pop() NOEXCEPT
127
{
128
    BC_ASSERT_MSG(!is_stack_empty(), "pop from empty stack");
129

130
    return *pop_chunk_();
17✔
131
}
132

133
// Non-public.
134
// ============================================================================
135

136
template <typename Stack>
137
INLINE bool program<Stack>::
3,095✔
138
is_prefail() const NOEXCEPT
139
{
140
    return script_->is_prefail();
3,095✔
141
}
142

143
template <typename Stack>
144
INLINE typename program<Stack>::op_iterator program<Stack>::
3,033✔
145
begin() const NOEXCEPT
146
{
147
    return script_->ops().begin();
3,033✔
148
}
149

150
template <typename Stack>
151
INLINE typename program<Stack>::op_iterator program<Stack>::
25,009✔
152
end() const NOEXCEPT
153
{
154
    return script_->ops().end();
25,009✔
155
}
156

157
template <typename Stack>
158
INLINE const chain::input& program<Stack>::
18✔
159
input() const NOEXCEPT
160
{
161
    return **input_;
162
}
163

164
template <typename Stack>
165
INLINE const chain::transaction& program<Stack>::
7✔
166
transaction() const NOEXCEPT
167
{
168
    return transaction_;
7✔
169
}
170

171
template <typename Stack>
172
INLINE bool program<Stack>::
8,606✔
173
is_enabled(chain::flags flag) const NOEXCEPT
174
{
175
    return to_bool(flags_ & flag);
1,396✔
176
}
177

178
// TODO: only perform is_push_size check on witness initialized stack.
179
// TODO: others are either empty or presumed push_size from prevout script run.
180
template <typename Stack>
181
INLINE script_error_t program<Stack>::
3,095✔
182
validate() const NOEXCEPT
183
{
184
    // TODO: nops rule must first be enabled in tests and config.
185
    const auto bip141 = is_enabled(flags::bip141_rule);
186

187
    // The script was determined by the parser to contain an invalid opcode.
188
    if (is_prefail())
3,095✔
189
        return error::prefail_script;
190

191
    // bip_141 introduces an initialized stack, so must validate.
192
    if (bip141 && witness_ && !witness::is_push_size(*witness_))
3,035✔
193
        return error::invalid_witness_stack;
194

195
    // The nops_rule establishes script size limit.
196
    return script_->is_oversized() ? error::invalid_script_size :
3,035✔
197
        error::script_success;
198
}
199

200
// Primary stack (conversions).
201
// ----------------------------------------------------------------------------
202

203
// static
204
template <typename Stack>
205
INLINE bool program<Stack>::
560✔
206
equal_chunks(const stack_variant& left, const stack_variant& right) NOEXCEPT
207
{
208
    return primary_stack::equal_chunks(left, right);
560✔
209
}
210

211
template <typename Stack>
212
INLINE bool program<Stack>::
1,593✔
213
peek_bool_() const NOEXCEPT
214
{
215
    return primary_.peek_bool();
1,147✔
216
}
217

218
template <typename Stack>
219
INLINE chunk_xptr program<Stack>::
3,578✔
220
peek_chunk_() const NOEXCEPT
221
{
222
    return primary_.peek_chunk();
3,578✔
223
}
224

225
template <typename Stack>
226
INLINE size_t program<Stack>::
58✔
227
peek_size() const NOEXCEPT
228
{
229
    return primary_.peek_size();
58✔
230
}
231

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

235
// This is the only source of push (write) tethering.
236
template <typename Stack>
237
INLINE void program<Stack>::
167✔
238
push_chunk(data_chunk&& datum) NOEXCEPT
239
{
240
    primary_.push(std::move(datum));
241
}
242

243
// Passing data_chunk& would be poor interface design, as it would allow
244
// derived callers to (unsafely) store raw pointers to unshared data_chunk.
245
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
246
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
247
template <typename Stack>
248
INLINE void program<Stack>::
4,474✔
249
push_chunk(const chunk_cptr& datum) NOEXCEPT
250
BC_POP_WARNING()
251
BC_POP_WARNING()
252
{
253
    primary_.emplace_chunk(datum.get());
8,948✔
254
}
255

256
// private
257
template <typename Stack>
258
INLINE void program<Stack>::
259
push_chunk(const chunk_xptr& datum) NOEXCEPT
260
{
261
    primary_.emplace_chunk(datum);
262
}
263

264
template <typename Stack>
265
INLINE void program<Stack>::
2,018✔
266
push_bool(bool value) NOEXCEPT
267
{
268
    primary_.emplace_boolean(value);
2,018✔
269
}
270

271
template <typename Stack>
272
INLINE void program<Stack>::
7,256✔
273
push_signed64(int64_t value) NOEXCEPT
274
{
275
    primary_.emplace_integer(value);
7,073✔
276
}
277

278
template <typename Stack>
279
INLINE void program<Stack>::
241✔
280
push_length(size_t value) NOEXCEPT
281
{
282
    // This is guarded by stack size and push data limits.
283
    BC_ASSERT_MSG(value <= max_int64, "integer overflow");
284

285
    push_signed64(possible_narrow_sign_cast<int64_t>(value));
241✔
286
}
287

288
// Primary stack (pop).
289
// ----------------------------------------------------------------------------
290

291
// This tethers a chunk if the stack value is not chunk.
292
template <typename Stack>
293
INLINE chunk_xptr program<Stack>::
3,578✔
294
pop_chunk_() NOEXCEPT
295
{
296
    const auto value = peek_chunk_();
297
    drop_();
298
    return value;
219✔
299
}
300

301
// This tethers chunks if the stack values are not chunk.
302
template <typename Stack>
303
INLINE bool program<Stack>::
4,102✔
304
pop_chunks(chunk_xptrs& data, size_t count) NOEXCEPT
305
{
306
    if (stack_size() < count)
4,102✔
307
        return false;
308

309
    data.reserve(count);
4,102✔
310
    for (size_t index = 0; index < count; ++index)
7,444✔
311
        data.push_back(pop_chunk_());
3,342✔
312

313
    return true;
314
}
315

316
template <typename Stack>
317
INLINE bool program<Stack>::
446✔
318
pop_bool_() NOEXCEPT
319
{
320
    const auto value = peek_bool_();
321
    drop_();
322
    return value;
323
}
324

325
template <typename Stack>
326
INLINE bool program<Stack>::
2,050✔
327
pop_strict_bool_() NOEXCEPT
328
{
329
    const auto value = primary_.peek_strict_bool();
2,050✔
330
    drop_();
331
    return value;
332
}
333

334
// private
335
template <typename Stack>
336
INLINE bool program<Stack>::
4,738✔
337
pop_signed32_(int32_t& value) NOEXCEPT
338
{
339
    const auto result = peek_signed32_(value);
340
    drop_();
341
    return result;
342
}
343

344
template <typename Stack>
345
INLINE bool program<Stack>::
4,272✔
346
pop_signed32(int32_t& value) NOEXCEPT
347
{
348
    if (is_stack_empty())
4,272✔
349
        return false;
350

351
    return pop_signed32_(value);
352
}
353

354
template <typename Stack>
355
INLINE bool program<Stack>::
242✔
356
pop_binary32(int32_t& left, int32_t& right) NOEXCEPT
357
{
358
    if (stack_size() < 2)
242✔
359
        return false;
360

361
    // The right hand side operand is at the top of the stack.
362
    return pop_signed32_(right) && pop_signed32_(left);
430✔
363
}
364

365
template <typename Stack>
366
INLINE bool program<Stack>::
18✔
367
pop_ternary32(int32_t& upper, int32_t& lower,
368
    int32_t& value) NOEXCEPT
369
{
370
    if (stack_size() < 3)
18✔
371
        return false;
372

373
    // The upper bound is at stack top, lower bound next, value next.
374
    return pop_signed32_(upper) && pop_signed32_(lower) &&
48✔
375
        pop_signed32_(value);
376
}
377

378
// ************************************************************************
379
// CONSENSUS: Satoshi limits this value to the int32_t domain (getint()).
380
// This value is only used for stack indexing (key/sig counts & pick/roll).
381
// The upper bound of int32_t always exceeds the possible stack size, which
382
// is checked downstream. Similarly, a negative causes a downstream script
383
// failure. As such it is sufficient to fail on non-idexability here,
384
// allowing the value to be returned as a valid and unsigned stack index.
385
// ************************************************************************
386
template <typename Stack>
387
INLINE bool program<Stack>::
4,160✔
388
pop_index32(size_t& index) NOEXCEPT
389
{
390
    int32_t value;
391
    if (!pop_signed32(value))
4,160✔
392
        return false;
393

394
    if (is_negative(value))
4,160✔
395
        return false;
396

397
    // Cast guarded by stack size.
398
    index = limit<size_t>(value);
46✔
399

400
    // True if popped value valid post-pop stack index (precluded if size < 2).
401
    return index < stack_size();
4,156✔
402
}
403

404
// private
405
template <typename Stack>
406
INLINE bool program<Stack>::
246✔
407
peek_signed32_(int32_t& value) const NOEXCEPT
408
{
409
    return primary_.peek_signed4(value);
4,492✔
410
}
411

412
// private
413
template <typename Stack>
414
INLINE bool program<Stack>::
12✔
415
peek_signed40_(int64_t& value) const NOEXCEPT
416
{
417
    return primary_.peek_signed5(value);
12✔
418
}
419

420
// ****************************************************************************
421
// CONSENSUS: Read of 40 bit (vs. 32 bit) value for comparison against uint32_t
422
// input.sequence allows use of the full unsigned 32 bit domain, without use of
423
// the negative range.
424
// ****************************************************************************
425
template <typename Stack>
426
INLINE bool program<Stack>::
×
427
peek_unsigned32(uint32_t& value) const NOEXCEPT
428
{
429
    if (is_stack_empty())
×
430
        return false;
431

432
    int64_t signed64;
433
    if (!peek_signed40_(signed64) || is_negative(signed64))
×
434
        return false;
435

436
    // 32 bits are used in unsigned input.sequence compare.
437
    value = narrow_sign_cast<uint32_t>(signed64);
438
    return true;
×
439
}
440

441
// ****************************************************************************
442
// CONSENSUS: Read of 40 bit (vs. 32 bit) value for comparison against uint32_t
443
// input.locktime allows use of the full unsigned 32 bit domain, without use of
444
// the negative range. Otherwise a 2038 limit (vs. the inherent 2106 limit)
445
// would have been introduced.
446
// ****************************************************************************
447
template <typename Stack>
448
INLINE bool program<Stack>::
18✔
449
peek_unsigned40(uint64_t& value) const NOEXCEPT
450
{
451
    if (is_stack_empty())
18✔
452
        return false;
453

454
    int64_t signed64;
455
    if (!peek_signed40_(signed64) || is_negative(signed64))
12✔
456
        return false;
457

458
    // 40 bits are usable in unsigned tx.locktime compare.
459
    value = sign_cast<uint64_t>(signed64);
460
    return true;
7✔
461
}
462

463
// Primary stack (variant - index).
464
// ----------------------------------------------------------------------------
465
// Stack index is zero-based, back() is element zero.
466

467
// This swaps the variant elements of the stack vector.
468
template <typename Stack>
469
INLINE void program<Stack>::
174✔
470
swap_(size_t left_index, size_t right_index) NOEXCEPT
471
{
472
    primary_.swap(left_index, right_index);
473
}
474

475
template <typename Stack>
476
INLINE void program<Stack>::
16✔
477
erase_(size_t index) NOEXCEPT
478
{
479
    primary_.erase(index);
480
}
481

482
template <typename Stack>
483
INLINE const stack_variant& program<Stack>::
9,916✔
484
peek_(size_t index) const NOEXCEPT
485
{
486
    return primary_.peek(index);
487
}
488

489
// Primary stack (variant - top).
490
// ----------------------------------------------------------------------------
491

492
template <typename Stack>
493
INLINE void program<Stack>::
10,927✔
494
drop_() NOEXCEPT
495
{
496
    primary_.drop();
497
}
498

499
template <typename Stack>
500
INLINE void program<Stack>::
9,957✔
501
push_variant(const stack_variant& vary) NOEXCEPT
502
{
503
    primary_.push(vary);
504
}
36✔
505

506
template <typename Stack>
507
INLINE const stack_variant& program<Stack>::
35✔
508
peek_() const NOEXCEPT
509
{
510
    return primary_.top();
511
}
512

513
template <typename Stack>
514
INLINE stack_variant program<Stack>::
1,138✔
515
pop_() NOEXCEPT
516
{
517
    return primary_.pop();
518
}
519

520
// Primary stack state (untyped).
521
// ----------------------------------------------------------------------------
522

523
template <typename Stack>
524
INLINE size_t program<Stack>::
12,749✔
525
stack_size() const NOEXCEPT
526
{
527
    return primary_.size();
528
}
529

530
template <typename Stack>
531
INLINE bool program<Stack>::
8,289✔
532
is_stack_empty() const NOEXCEPT
533
{
534
    return primary_.empty();
535
}
536

537
template <typename Stack>
538
INLINE bool program<Stack>::
20,900✔
539
is_stack_overflow() const NOEXCEPT
540
{
541
    // Addition is safe due to stack size constraint.
542
    return (stack_size() + alternate_.size()) > max_unified_stack_size;
20,900✔
543
}
544

545
// private
546
template <typename Stack>
547
INLINE bool program<Stack>::
21✔
548
is_stack_clean() const NOEXCEPT
549
{
550
    return is_one(stack_size());
551
}
552

553
// Alternate stack.
554
// ----------------------------------------------------------------------------
555

556
template <typename Stack>
557
INLINE bool program<Stack>::
10✔
558
is_alternate_empty() const NOEXCEPT
559
{
560
    return alternate_.empty();
561
}
562

563
// Moving a shared pointer to the alternate stack is optimal and acceptable.
564
BC_PUSH_WARNING(NO_RVALUE_REF_SHARED_PTR)
565
template <typename Stack>
566
INLINE void program<Stack>::
18✔
567
push_alternate(stack_variant&& vary) NOEXCEPT
568
BC_POP_WARNING()
569
{
570
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
571
    alternate_.push_back(std::move(vary));
18✔
572
    BC_POP_WARNING()
573
}
574

575
template <typename Stack>
576
INLINE stack_variant program<Stack>::
6✔
577
pop_alternate_() NOEXCEPT
578
{
579
    BC_ASSERT(!alternate_.empty());
580

581
    stack_variant value{ std::move(alternate_.back()) };
6✔
582
    alternate_.pop_back();
6✔
583
    return value;
6✔
584
}
585

586
// Conditional stack.
587
// ----------------------------------------------------------------------------
588

589
template <typename Stack>
590
INLINE void program<Stack>::
446✔
591
begin_if(bool value) NOEXCEPT
592
{
593
    // Addition is safe due to script size constraint.
594
    BC_ASSERT(value || !is_add_overflow(negative_condition_count_, one));
595

596
    negative_condition_count_ += (value ? 0 : 1);
446✔
597
    condition_.push_back(value);
474✔
598
}
599

600
// ****************************************************************************
601
// CONSENSUS: "You may have noticed the strange behavior of Bitcoin's ELSE
602
// statement. Bitcoin allows one to switch between true and false conditions
603
// several times. For example, the following script is valid and leaves the
604
// value 2 on the stack: 1 OP_IF OP_ELSE OP_ELSE 2 OP_ENDIF"
605
// bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts
606
// ****************************************************************************
607
template <typename Stack>
608
INLINE void program<Stack>::
442✔
609
else_if_() NOEXCEPT
610
{
611
    // Subtraction must be guarded by caller logical constraints.
612
    BC_ASSERT(!is_balanced());
613

614
    // Addition is safe due to script size constraint.
615
    BC_ASSERT(condition_.back() ||
616
        !is_add_overflow(negative_condition_count_, one));
617

618
    negative_condition_count_ += (condition_.back() ? 1 : -1);
442✔
619
    condition_.back() = !condition_.back();
442✔
620
}
621

622
template <typename Stack>
623
INLINE void program<Stack>::
308✔
624
end_if_() NOEXCEPT
625
{
626
    // Subtraction must be guarded by caller logical constraints.
627
    BC_ASSERT(!is_balanced());
628

629
    negative_condition_count_ += (condition_.back() ? 0 : -1);
308✔
630
    condition_.pop_back();
308✔
631
}
632

633
template <typename Stack>
634
INLINE bool program<Stack>::
3,368✔
635
is_balanced() const NOEXCEPT
636
{
637
    return condition_.empty();
3,368✔
638
}
639

640
template <typename Stack>
641
INLINE bool program<Stack>::
21,630✔
642
is_succeess() const NOEXCEPT
643
{
644
    // Optimization changes O(n) search [for every operation] to O(1).
645
    // bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts
646
    return is_zero(negative_condition_count_);
21,630✔
647
}
648

649
template <typename Stack>
650
INLINE bool program<Stack>::
22,402✔
651
if_(const operation& op) const NOEXCEPT
652
{
653
    // Conditional op execution is not predicated on conditional stack.
654
    return op.is_conditional() || is_succeess();
22,402✔
655
}
656

657
//  Accumulator.
658
// ----------------------------------------------------------------------------
659

660
// ****************************************************************************
661
// CONSENSUS:
662
// Satoshi compares the count to 200 with a composed postfix increment, which
663
// makes the actual maximum 201, not the presumably-intended 200. The code was
664
// later revised to make this explicit, by use of a prefix increment against a
665
// limit of 201.
666
// ****************************************************************************
667
INLINE constexpr bool operation_count_exceeded(size_t count) NOEXCEPT
668
{
669
    return count > max_counted_ops;
670
}
671

672
template <typename Stack>
673
INLINE bool program<Stack>::
22,409✔
674
ops_increment(const operation& op) NOEXCEPT
675
{
676
    // Addition is safe due to script size constraint.
677
    BC_ASSERT(!is_add_overflow(operation_count_, one));
678

679
    if (operation::is_counted(op.code()))
22,409✔
680
        ++operation_count_;
10,530✔
681

682
    return operation_count_ <= max_counted_ops;
22,409✔
683
}
684

685
template <typename Stack>
686
INLINE bool program<Stack>::
2,058✔
687
ops_increment(size_t public_keys) NOEXCEPT
688
{
689
    // Addition is safe due to script size constraint.
690
    BC_ASSERT(!is_add_overflow(operation_count_, public_keys));
691

692
    operation_count_ += public_keys;
2,058✔
693
    return !operation_count_exceeded(operation_count_);
694
}
695

696
// Signature validation helpers.
697
// ----------------------------------------------------------------------------
698

699
// Subscripts are referenced by script.offset mutable metadata. This allows for
700
// efficient subscripting with no copying. However, concurrent execution of any
701
// one input script instance is not thread safe (unnecessary scenario).
702
template <typename Stack>
703
inline bool program<Stack>::
9✔
704
set_subscript(const op_iterator& op) NOEXCEPT
705
{
706
    // End is not reachable if op is an element of script_.
707
    if (script_->ops().empty() || op == script_->ops().end())
9✔
708
        return false;
×
709

710
    // Advance the offset to the op following the found code separator.
711
    // This is non-const because changes script state (despite being mutable).
712
    script_->offset = std::next(op);
9✔
713
    return true;
9✔
714
}
715

716
inline chain::strippers create_strip_ops(
1,958✔
717
    const chunk_xptrs& endorsements) NOEXCEPT
718
{
719
    chain::strippers strip{};
1,958✔
720

721
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
722
    strip.reserve(add1(endorsements.size()));
1,958✔
723

724
    for (const auto& endorsement: endorsements)
1,980✔
725
        strip.emplace_back(endorsement);
22✔
726

727
    strip.emplace_back(opcode::codeseparator);
1,958✔
728
    BC_POP_WARNING()
729

730
    return strip;
1,958✔
UNCOV
731
}
×
732

733
// ****************************************************************************
734
// CONSENSUS: Endorsement and code separator stripping are always performed in
735
// conjunction and are limited to non-witness signature hash subscripts.
736
// The order of operations is inconsequential, as they are all removed.
737
// Subscripts are not evaluated, they are limited to signature hash creation.
738
// ****************************************************************************
739
template <typename Stack>
740
inline script::cptr program<Stack>::
1,975✔
741
subscript(const chunk_xptrs& endorsements) const NOEXCEPT
742
{
743
    // bip141: establishes the version property.
744
    // bip143: op stripping is not applied to bip141 v0 scripts.
745
    if (is_enabled(flags::bip143_rule) && version_ == script_version::zero)
1,975✔
746
        return script_;
747

748
    // Transform into a set of endorsement push ops and one op_codeseparator.
749
    const auto strip = create_strip_ops(endorsements);
1,958✔
750
    const auto stop = script_->ops().end();
1,958✔
751
    const op_iterator offset{ script_->offset };
1,958✔
752

753
    // If none of the strip ops are found, return the subscript.
754
    // Prefail is not circumvented as subscript used only for signature hash.
755
    if (!is_intersecting<operations>(offset, stop, strip))
1,958✔
756
        return script_;
757

758
    // Create new script from stripped copy of subscript operations.
759
    // Prefail is not copied to the subscript, used only for signature hash.
760
    return to_shared<script>(difference<operations>(offset, stop, strip));
8✔
761
}
1,958✔
762

763
// TODO: use sighash and key to generate signature in sign mode.
764
template <typename Stack>
765
inline bool program<Stack>::
26✔
766
prepare(ec_signature& signature, const data_chunk&, hash_digest& hash,
767
    const chunk_xptr& endorsement) const NOEXCEPT
768
{
769
    uint8_t sighash_flags;
770
    data_slice distinguished;
26✔
771

772
    // Parse Bitcoin endorsement into DER signature and sighash flags.
773
    if (!parse_endorsement(sighash_flags, distinguished, *endorsement))
26✔
774
        return false;
775

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

779
    // Parse DER signature into an EC signature (bip66 sets strict).
780
    const auto bip66 = is_enabled(flags::bip66_rule);
781
    return parse_signature(signature, distinguished, bip66);
26✔
782
}
783

784
// TODO: use sighash and key to generate signature in sign mode.
785
template <typename Stack>
786
inline bool program<Stack>::
20✔
787
prepare(ec_signature& signature, const data_chunk&, hash_cache& cache,
788
    uint8_t& sighash_flags, const data_chunk& endorsement,
789
    const script& sub) const NOEXCEPT
790
{
791
    data_slice distinguished;
20✔
792

793
    // Parse Bitcoin endorsement into DER signature and sighash flags.
794
    if (!parse_endorsement(sighash_flags, distinguished, endorsement))
20✔
795
        return false;
796

797
    // Obtain the signature hash from subscript and sighash flags.
798
    signature_hash(cache, sub, sighash_flags);
20✔
799

800
    // Parse DER signature into an EC signature (bip66 sets strict).
801
    const auto bip66 = is_enabled(flags::bip66_rule);
802
    return parse_signature(signature, distinguished, bip66);
20✔
803
}
804

805
// Signature hashing.
806
// ----------------------------------------------------------------------------
807

808
template <typename Stack>
809
INLINE hash_digest program<Stack>::
26✔
810
signature_hash(const script& sub, uint8_t flags) const NOEXCEPT
811
{
812
    // The bip141 fork establishes witness version, hashing is a distinct fork.
813
    const auto bip143 = is_enabled(flags::bip143_rule);
814

815
    // bip143: the method of signature hashing is changed for v0 scripts.
816
    return transaction_.signature_hash(input_, sub, value_, flags, version_,
36✔
817
        bip143);
26✔
818
}
819

820
// Caches signature hashes in a map against sighash flags.
821
// Prevents recomputation in the common case where flags are the same.
822
template <typename Stack>
823
INLINE void program<Stack>::
20✔
824
signature_hash(hash_cache& cache, const script& sub,
825
    uint8_t sighash_flags) const NOEXCEPT
826
{
827
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
828
    if (cache.find(sighash_flags) == cache.end())
20✔
829
        cache.emplace(sighash_flags, signature_hash(sub, sighash_flags));
10✔
830
    BC_POP_WARNING()
831
}
832

833
} // namespace machine
834
} // namespace system
835
} // namespace libbitcoin
836

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

© 2025 Coveralls, Inc