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

libbitcoin / libbitcoin-system / 15084267089

17 May 2025 10:23AM UTC coverage: 81.33% (-0.5%) from 81.805%
15084267089

push

github

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

Use shared_ptr to make annex a safe copyable object.

33 of 136 new or added lines in 9 files covered. (24.26%)

5 existing lines in 2 files now uncovered.

10385 of 12769 relevant lines covered (81.33%)

3748385.55 hits per line

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

74.51
/src/chain/input.cpp
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
#include <bitcoin/system/chain/input.hpp>
20

21
#include <algorithm>
22
#include <memory>
23
#include <utility>
24
#include <bitcoin/system/chain/context.hpp>
25
#include <bitcoin/system/chain/enums/magic_numbers.hpp>
26
#include <bitcoin/system/chain/point.hpp>
27
#include <bitcoin/system/chain/prevout.hpp>
28
#include <bitcoin/system/chain/script.hpp>
29
#include <bitcoin/system/chain/witness.hpp>
30
#include <bitcoin/system/define.hpp>
31
#include <bitcoin/system/math/math.hpp>
32
#include <bitcoin/system/stream/stream.hpp>
33

34
namespace libbitcoin {
35
namespace system {
36
namespace chain {
37

38
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
39

40
// Product overflows guarded by script size limit.
41
static_assert(max_script_size <
42
    max_size_t / multisig_default_sigops / heavy_sigops_factor,
43
    "input sigop overflow guard");
44

45
// Null witness helpers.
46
// ----------------------------------------------------------------------------
47

48
// static/private
49
const witness& input::no_witness() NOEXCEPT
×
50
{
51
    static const chain::witness empty{};
×
52
    return empty;
×
53
}
54

55
// static/private
56
const witness::cptr& input::no_witness_cptr() NOEXCEPT
×
57
{
NEW
58
    static const auto empty = to_shared<const chain::witness>();
×
59
    return empty;
×
60
}
61

62
const chain::witness& input::get_witness() const NOEXCEPT
1,985✔
63
{
64
    return witness_ ? *witness_ : no_witness();
1,985✔
65
}
66

67
const chain::witness::cptr& input::get_witness_cptr() const NOEXCEPT
×
68
{
69
    return witness_ ? witness_ : no_witness_cptr();
×
70
}
71

72
// Constructors.
73
// ----------------------------------------------------------------------------
74

75
// Default point is null_hash and point::null_index. 
76
// Default metadata is spent, invalid, max_size_t value. 
77
input::input() NOEXCEPT
22✔
78
  : input(
79
      to_shared<chain::point>(),
22✔
80
      to_shared<chain::script>(),
22✔
81
      to_shared<chain::witness>(),
22✔
82
      0, false)
66✔
83
{
84
}
22✔
85

86
input::input(chain::point&& point, chain::script&& script,
160✔
87
    uint32_t sequence) NOEXCEPT
160✔
88
  : input(
89
      to_shared(std::move(point)),
160✔
90
      to_shared(std::move(script)),
160✔
91
      to_shared<chain::witness>(),
160✔
92
      sequence, true)
160✔
93
{
94
}
160✔
95

96
input::input(const chain::point& point, const chain::script& script,
736✔
97
    uint32_t sequence) NOEXCEPT
736✔
98
  : input(
99
      to_shared(point),
736✔
100
      to_shared(script),
736✔
101
      to_shared<chain::witness>(),
736✔
102
      sequence, true)
736✔
103
{
104
}
736✔
105

106
input::input(const chain::point::cptr& point,
×
107
    const chain::script::cptr& script, uint32_t sequence) NOEXCEPT
×
108
  : input(
109
      point ? point : to_shared<chain::point>(),
×
110
      script ? script : to_shared<chain::script>(),
×
111
      to_shared<chain::witness>(),
×
112
      sequence, true)
×
113
{
114
}
×
115

116
input::input(chain::point&& point, chain::script&& script,
14✔
117
    chain::witness&& witness, uint32_t sequence) NOEXCEPT
14✔
118
  : input(
119
      to_shared(std::move(point)),
14✔
120
      to_shared(std::move(script)),
14✔
121
      to_shared(std::move(witness)),
14✔
122
      sequence, true)
14✔
123
{
124
}
14✔
125

126
input::input(const chain::point& point, const chain::script& script,
1✔
127
    const chain::witness& witness, uint32_t sequence) NOEXCEPT
1✔
128
  : input(
129
      to_shared(point),
1✔
130
      to_shared(script),
1✔
131
      to_shared(witness),
1✔
132
      sequence, true)
1✔
133
{
134
}
1✔
135

136
input::input(const chain::point::cptr& point, const chain::script::cptr& script,
×
137
    const chain::witness::cptr& witness, uint32_t sequence) NOEXCEPT
×
138
  : input(point, script, witness, sequence, true)
×
139
{
140
}
×
141

142
input::input(stream::in::fast&& stream) NOEXCEPT
5✔
143
  : input(read::bytes::fast(stream))
5✔
144
{
145
}
5✔
146

147
input::input(stream::in::fast& stream) NOEXCEPT
1✔
148
  : input(read::bytes::fast(stream))
1✔
149
{
150
}
1✔
151

152
input::input(std::istream&& stream) NOEXCEPT
×
153
  : input(read::bytes::istream(stream))
×
154
{
155
}
×
156

157
input::input(std::istream& stream) NOEXCEPT
3✔
158
  : input(read::bytes::istream(stream))
3✔
159
{
160
}
3✔
161

162
input::input(reader&& source) NOEXCEPT
9✔
163
  : input(source)
9✔
164
{
165
}
×
166

167
// Witness is deserialized and assigned by transaction.
168
input::input(reader& source) NOEXCEPT
281✔
169
  : point_(CREATE(chain::point, source.get_allocator(), source)),
281✔
170
    script_(CREATE(chain::script, source.get_allocator(), source, true)),
281✔
171
    witness_(CREATE(chain::witness, source.get_allocator())),
281✔
172
    sequence_(source.read_4_bytes_little_endian()),
281✔
173
    valid_(source),
281✔
174
    size_(serialized_size(*script_))
562✔
175
{
176
}
281✔
177

178
// protected
179
input::input(const chain::point::cptr& point, const chain::script::cptr& script,
933✔
180
    const chain::witness::cptr& witness, uint32_t sequence, bool valid) NOEXCEPT
933✔
181
  : point_(point),
182
    script_(script),
183
    witness_(witness),
184
    sequence_(sequence),
933✔
185
    valid_(valid),
933✔
186
    size_(serialized_size(*script, *witness))
1,866✔
187
{
188
}
933✔
189

190
// Operators.
191
// ----------------------------------------------------------------------------
192

193
bool input::operator==(const input& other) const NOEXCEPT
53✔
194
{
195
    return (sequence_ == other.sequence_)
53✔
196
        && (point_ == other.point_ || *point_ == *other.point_)
51✔
197
        && (script_ == other.script_ || *script_ == *other.script_)
51✔
198
        && (witness_ == other.witness_ || get_witness() == other.get_witness());
104✔
199
}
200

201
bool input::operator!=(const input& other) const NOEXCEPT
2✔
202
{
203
    return !(*this == other);
2✔
204
}
205

206
// Constant reference optimizers.
207

208
bool operator<(const cref_point& left, const cref_point& right) NOEXCEPT
×
209
{
210
    // Arbitrary compare, for uniqueness sorting.
211
    return left.index == right.index ?
×
212
        left.hash.get() < right.hash.get() :
×
213
        left.index < right.index;
×
214
}
215

216
bool operator==(const cref_point& left, const cref_point& right) NOEXCEPT
×
217
{
218
    return (left.hash.get() == right.hash.get())
×
219
        && (left.index == right.index);
×
220
}
221

222
bool operator!=(const cref_point& left, const cref_point& right) NOEXCEPT
×
223
{
224
    return !(left == right);
×
225
}
226

227
// Deserialization.
228
// ----------------------------------------------------------------------------
229

230
// Serialization.
231
// ----------------------------------------------------------------------------
232

233
data_chunk input::to_data() const NOEXCEPT
1✔
234
{
235
    data_chunk data(serialized_size(false));
1✔
236
    stream::out::fast ostream(data);
1✔
237
    write::bytes::fast out(ostream);
1✔
238
    to_data(out);
1✔
239
    return data;
2✔
240
}
1✔
241

242
void input::to_data(std::ostream& stream) const NOEXCEPT
1✔
243
{
244
    write::bytes::ostream out(stream);
1✔
245
    to_data(out);
1✔
246
}
1✔
247

248
// Witness is serialized by transaction.
249
void input::to_data(writer& sink) const NOEXCEPT
1,389✔
250
{
251
    point_->to_data(sink);
1,389✔
252
    script_->to_data(sink, true);
1,389✔
253
    sink.write_4_bytes_little_endian(sequence_);
1,389✔
254
}
1,389✔
255

256
// static/private
257
input::sizes input::serialized_size(const chain::script& script) NOEXCEPT
281✔
258
{
259
    constexpr auto const_size = ceilinged_add(point::serialized_size(),
281✔
260
        sizeof(sequence_));
261

262
    const auto nominal_size = ceilinged_add(const_size,
281✔
263
        script.serialized_size(true));
264

265
    // Non-segregated input serialization requires an empty witness stack size.
266
    // when serializing with witness included (witnessed_size for non-witness).
267
    // This does not affect tx serialiation as does not set witness paramter.
268
    return { nominal_size, add1(nominal_size) };
281✔
269
}
270

271
// static/private
272
input::sizes input::serialized_size(const chain::script& script,
933✔
273
    const chain::witness& witness) NOEXCEPT
274
{
275
    constexpr auto const_size = ceilinged_add(point::serialized_size(),
933✔
276
        sizeof(sequence_));
277

278
    const auto nominal_size = ceilinged_add(const_size,
933✔
279
        script.serialized_size(true));
280

281
    // The input has no way to determine if its tx is segregated, as an empty
282
    // witness applies to segregated tx as a one byte (zero) serialization.
283
    // This determination is therefore left to the transaction, and witness
284
    // retains both serialization options from construction.
285
    const auto witnessed_size = ceilinged_add(nominal_size,
933✔
286
        witness.serialized_size(true));
287

288
    // Values are the same for non-segregated transactions.
289
    return { nominal_size, witnessed_size };
933✔
290
}
291

292
// input.serialized_size(witness) provides sizing for witness, however
293
// witnesses are serialized by the transaction. This is an ugly hack as a
294
// consequence of bip144 not serializing witnesses as part of inputs, which
295
// is logically the proper association.
296
size_t input::serialized_size(bool witness) const NOEXCEPT
2✔
297
{
298
    return witness ? size_.witnessed : size_.nominal;
2✔
299
}
300

301
// Friend accessors (private).
302
// ----------------------------------------------------------------------------
303

304
size_t input::nominal_size() const NOEXCEPT
1,184✔
305
{
306
    return size_.nominal;
1,184✔
307
}
308

309
size_t input::witnessed_size() const NOEXCEPT
32✔
310
{
311
    return size_.witnessed;
32✔
312
}
313

314
////void input::set_witness(reader& source) NOEXCEPT
315
////{
316
////    witness_ = to_shared<chain::witness>(source, true);
317
////    size_.witnessed = ceilinged_add(size_.nominal,
318
////        witness_->serialized_size(true));
319
////}
320

321
void input::set_witness(reader& source) NOEXCEPT
20✔
322
{
323
    auto& allocator = source.get_allocator();
20✔
324
    witness_.reset(CREATE(chain::witness, allocator, source, true));
20✔
325
    size_.witnessed = ceilinged_add(size_.nominal,
20✔
326
        witness_->serialized_size(true));
327
}
20✔
328

329
// Properties.
330
// ----------------------------------------------------------------------------
331

332
bool input::is_valid() const NOEXCEPT
16✔
333
{
334
    return valid_;
16✔
335
}
336

337
const point& input::point() const NOEXCEPT
169✔
338
{
339
    return *point_;
10✔
340
}
341

342
const chain::script& input::script() const NOEXCEPT
75✔
343
{
344
    return *script_;
10✔
345
}
346

347
const chain::witness& input::witness() const NOEXCEPT
1,899✔
348
{
349
    return get_witness();
1,899✔
350
}
351

352
const point::cptr& input::point_ptr() const NOEXCEPT
×
353
{
354
    return point_;
×
355
}
356

357
const chain::script::cptr& input::script_ptr() const NOEXCEPT
1,559✔
358
{
359
    return script_;
1,559✔
360
}
361

362
const chain::witness::cptr& input::witness_ptr() const NOEXCEPT
×
363
{
364
    return get_witness_cptr();
×
365
}
366

367
uint32_t input::sequence() const NOEXCEPT
73✔
368
{
369
    return sequence_;
10✔
370
}
371

372
// Methods.
373
// ----------------------------------------------------------------------------
374

375
bool input::is_final() const NOEXCEPT
22✔
376
{
377
    return sequence_ == max_input_sequence;
22✔
378
}
379

380
bool input::is_roller() const NOEXCEPT
4✔
381
{
382
    return script_->is_roller() || (prevout && prevout->script().is_roller());
4✔
383
}
384

385
// static
386
bool input::is_relative_locktime_applied(uint32_t sequence) NOEXCEPT
10✔
387
{
388
    // BIP68: if bit 31 is set then no consensus meaning is applied.
389
    return !get_right(sequence, relative_locktime_disabled_bit);
10✔
390
}
391

392
// static
393
bool input::is_relative_locked(uint32_t sequence, size_t height,
10✔
394
    uint32_t median_time_past, size_t prevout_height,
395
    uint32_t prevout_median_time_past) NOEXCEPT
396
{
397
    if (!is_relative_locktime_applied(sequence))
10✔
398
        return false;
399

400
    // BIP68: the low 16 bits of the sequence apply to relative lock-time.
401
    const auto blocks = mask_left(sequence, relative_locktime_mask_left);
8✔
402

403
    // BIP68: bit 22 determines if relative lock is time or block based.
404
    if (get_right(sequence, relative_locktime_time_locked_bit))
8✔
405
    {
406
        // BIP68: references to median time past are as defined by bip113.
407
        // BIP68: change sequence to seconds by shift up by 9 bits (x 512).
408
        auto time = shift_left(blocks, relative_locktime_seconds_shift_left);
3✔
409
        auto age = floored_subtract(median_time_past, prevout_median_time_past);
3✔
410
        return age < time;
3✔
411
    }
412

413
    // BIP68: when the relative lock time is block based, it is interpreted as
414
    // a minimum block height constraint over the age of the input.
415
    const auto age = floored_subtract(height, prevout_height);
5✔
416
    return age < blocks;
5✔
417
}
418

419
bool input::is_relative_locked(size_t height,
10✔
420
    uint32_t median_time_past) const NOEXCEPT
421
{
422
    // Prevout must be found and height/median_time_past metadata populated.
423
    ////BC_ASSERT(!is_zero(metadata.height));
424
    return is_relative_locked(sequence_, height, median_time_past,
10✔
425
        metadata.height, metadata.median_time_past);
10✔
426
}
427

428
bool input::reserved_hash(hash_cref& out) const NOEXCEPT
×
429
{
430
    const auto& stack = witness().stack();
×
431
    if (!witness::is_reserved_pattern(stack))
×
432
        return false;
433

434
    // Guarded by is_reserved_pattern.
435
    out = unsafe_array_cast<uint8_t, hash_size>(stack.front()->data());
×
436
    return true;
×
437
}
438

439
// TODO: Prior to block 79400 sigops were limited only by policy.
440
// TODO: Create legacy sigops fork/flag and pass here, return 0 if false.
441
// TODO: this was an unbipped flag day soft fork, prior to BIP16/141.
442
// TODO: if (nHeight > 79400 && GetSigOpCount() > MAX_BLOCK_SIGOPS).
443
// ****************************************************************************
444
// CONSENSUS: coinbase input cannot execute, but legacy sigops counted anyway.
445
// ****************************************************************************
446
size_t input::signature_operations(bool bip16, bool bip141) const NOEXCEPT
7✔
447
{
448
    // Sigops in the current output script, input script, and P2SH embedded
449
    // script are counted at four times their previous value (heavy) [bip141].
450
    const auto factor = bip141 ? heavy_sigops_factor : one;
7✔
451

452
    // Count heavy sigops in the input script (inaccurate).
453
    const auto sigops = script_->signature_operations(false) * factor;
7✔
454

455
    // Null prevout/input (coinbase) cannot have witness or embedded script.
456
    // Embedded/witness scripts are deserialized here and again on script eval.
457
    if (!prevout)
7✔
458
        return sigops;
459

460
    chain::script script;
×
461
    if (bip141 && witness_->extract_sigop_script(script, prevout->script()))
×
462
    {
463
        // Add sigops in the witness script (accurate) [bip141].
464
        return ceilinged_add(sigops, script.signature_operations(true));
×
465
    }
466

467
    chain::script embedded;
×
468
    if (bip16 && script_->extract_sigop_script(embedded, prevout->script()))
×
469
    {
470
        if (bip141 && witness_->extract_sigop_script(script, embedded))
×
471
        {
472
            // Add sigops in the embedded witness script (accurate) [bip141].
473
            return ceilinged_add(sigops, script.signature_operations(true));
×
474
        }
475
        else
476
        {
477
            // Add heavy sigops in the embedded script (accurate) [bip16].
478
            return ceilinged_add(sigops, embedded.signature_operations(true) *
×
479
                factor);
480
        }
481
    }
482

483
    return sigops;
484
}
×
485

486
BC_POP_WARNING()
487

488
// JSON value convertors.
489
// ----------------------------------------------------------------------------
490

491
namespace json = boost::json;
492

493
// boost/json will soon have NOEXCEPT: github.com/boostorg/json/pull/636
494
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
495

496
input tag_invoke(json::value_to_tag<input>, const json::value& value) NOEXCEPT
5✔
497
{
498
    return
5✔
499
    {
500
        json::value_to<chain::point>(value.at("point")),
5✔
501
        json::value_to<chain::script>(value.at("script")),
5✔
502
        json::value_to<chain::witness>(value.at("witness")),
10✔
503
        value.at("sequence").to_number<uint32_t>()
10✔
504
    };
5✔
505
}
506

507
void tag_invoke(json::value_from_tag, json::value& value,
10✔
508
    const input& input) NOEXCEPT
509
{
510
    value =
20✔
511
    {
512
        { "point", input.point() },
513
        { "script", input.script() },
514
        { "witness", input.witness() },
515
        { "sequence", input.sequence() }
516
    };
10✔
517
}
10✔
518

519
BC_POP_WARNING()
520

521
input::cptr tag_invoke(json::value_to_tag<input::cptr>,
×
522
    const json::value& value) NOEXCEPT
523
{
524
    return to_shared(tag_invoke(json::value_to_tag<input>{}, value));
×
525
}
526

527
// Shared pointer overload is required for navigation.
528
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
529
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
530

531
void tag_invoke(json::value_from_tag tag, json::value& value,
8✔
532
    const input::cptr& input) NOEXCEPT
533
{
534
    tag_invoke(tag, value, *input);
8✔
535
}
8✔
536

537
BC_POP_WARNING()
538
BC_POP_WARNING()
539

540
} // namespace chain
541
} // namespace system
542
} // namespace libbitcoin
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