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

libbitcoin / libbitcoin-system / 14509835486

17 Apr 2025 06:50AM UTC coverage: 82.762% (-0.06%) from 82.822%
14509835486

push

github

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

Refactor is_invalid_witness_commitment, use cref to avoid copies.

0 of 24 new or added lines in 4 files covered. (0.0%)

4 existing lines in 3 files now uncovered.

10183 of 12304 relevant lines covered (82.76%)

3819104.78 hits per line

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

81.25
/src/chain/output.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/output.hpp>
20

21
#include <algorithm>
22
#include <iterator>
23
#include <memory>
24
#include <bitcoin/system/chain/enums/magic_numbers.hpp>
25
#include <bitcoin/system/define.hpp>
26
#include <bitcoin/system/math/math.hpp>
27
#include <bitcoin/system/stream/stream.hpp>
28

29
namespace libbitcoin {
30
namespace system {
31
namespace chain {
32

33
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
34
BC_PUSH_WARNING(NO_ARRAY_INDEXING)
35

36
// This is a consensus critical value that must be set on reset.
37
const uint64_t output::not_found = sighash_null_value;
38

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

42
// Invalid default used in signature hashing (validity ignored).
43
// Invalidity is also used to determine that a prevout is not found.
44
output::output() NOEXCEPT
10✔
45
  : output(output::not_found, to_shared<chain::script>(), false)
10✔
46
{
47
}
10✔
48

49
output::output(uint64_t value, chain::script&& script) NOEXCEPT
196✔
50
  : output(value, to_shared(std::move(script)), true)
196✔
51
{
52
}
196✔
53

54
output::output(uint64_t value, const chain::script& script) NOEXCEPT
734✔
55
  : output(value, to_shared(script), true)
734✔
56
{
57
}
734✔
58

59
output::output(uint64_t value, const chain::script::cptr& script) NOEXCEPT
×
60
  : output(value, script ? script : to_shared<chain::script>(), true)
×
61
{
62
}
×
63

64
output::output(stream::in::fast&& stream) NOEXCEPT
4✔
65
  : output(read::bytes::fast(stream))
4✔
66
{
67
}
4✔
68

69
output::output(stream::in::fast& stream) NOEXCEPT
×
70
  : output(read::bytes::fast(stream))
×
71
{
72
}
×
73

74
output::output(std::istream&& stream) NOEXCEPT
×
75
  : output(read::bytes::istream(stream))
×
76
{
77
}
×
78

79
output::output(std::istream& stream) NOEXCEPT
2✔
80
  : output(read::bytes::istream(stream))
2✔
81
{
82
}
2✔
83

84
output::output(reader&& source) NOEXCEPT
6✔
85
  : output(source)
6✔
86
{
87
}
×
88

89
output::output(reader& source) NOEXCEPT
280✔
90
  : value_(source.read_8_bytes_little_endian()),
560✔
91
    script_(CREATE(chain::script, source.get_allocator(), source, true)),
280✔
92
    valid_(source),
280✔
93
    size_(serialized_size(*script_, value_))
560✔
94
{
95
}
280✔
96

97
// protected
98
output::output(uint64_t value, const chain::script::cptr& script,
940✔
99
    bool valid) NOEXCEPT
940✔
100
  : value_(value),
940✔
101
    script_(script),
102
    valid_(valid),
940✔
103
    size_(serialized_size(*script, value))
940✔
104
{
105
}
940✔
106

107
// Operators.
108
// ----------------------------------------------------------------------------
109

110
bool output::operator==(const output& other) const NOEXCEPT
45✔
111
{
112
    return (value_ == other.value_)
45✔
113
        && (script_ == other.script_ || *script_ == *other.script_);
45✔
114
}
115

116
bool output::operator!=(const output& other) const NOEXCEPT
2✔
117
{
118
    return !(*this == other);
2✔
119
}
120

121
// Deserialization.
122
// ----------------------------------------------------------------------------
123

124
// Serialization.
125
// ----------------------------------------------------------------------------
126

127
data_chunk output::to_data() const NOEXCEPT
2✔
128
{
129
    data_chunk data(serialized_size());
2✔
130
    stream::out::fast ostream(data);
2✔
131
    write::bytes::fast out(ostream);
2✔
132
    to_data(out);
2✔
133
    return data;
4✔
134
}
2✔
135

136
void output::to_data(std::ostream& stream) const NOEXCEPT
1✔
137
{
138
    write::bytes::ostream out(stream);
1✔
139
    to_data(out);
1✔
140
}
1✔
141

142
void output::to_data(writer& sink) const NOEXCEPT
1,717✔
143
{
144
    sink.write_8_bytes_little_endian(value_);
1,717✔
145
    script_->to_data(sink, true);
1,717✔
146
}
1,717✔
147

148
// static/private
149
size_t output::serialized_size(const chain::script& script,
1,220✔
150
    uint64_t value) NOEXCEPT
151
{
152
    return ceilinged_add(sizeof(value), script.serialized_size(true));
1,220✔
153
}
154

155
size_t output::serialized_size() const NOEXCEPT
397✔
156
{
157
    return size_;
2✔
158
}
159

160
// Properties.
161
// ----------------------------------------------------------------------------
162

163
bool output::is_valid() const NOEXCEPT
9✔
164
{
165
    return valid_;
9✔
166
}
167

168
uint64_t output::value() const NOEXCEPT
55✔
169
{
170
    return value_;
10✔
171
}
172

173
const chain::script& output::script() const NOEXCEPT
174✔
174
{
175
    return *script_;
10✔
176
}
177

178
const chain::script::cptr& output::script_ptr() const NOEXCEPT
1,496✔
179
{
180
    return script_;
1,496✔
181
}
182

183
// Methods.
184
// ----------------------------------------------------------------------------
185

NEW
186
bool output::committed_hash(hash_cref& out) const NOEXCEPT
×
187
{
188
    const auto& ops = script_->ops();
×
189
    if (!script::is_commitment_pattern(ops))
×
190
        return false;
191

192
    // Offset four bytes for witness commitment head (bip141).
NEW
193
    const auto start = std::next(ops[1].data().data(), sizeof(witness_head));
×
194

195
    // Guarded by is_commitment_pattern.
NEW
196
    out = unsafe_array_cast<uint8_t, hash_size>(start);
×
UNCOV
197
    return true;
×
198
}
199

200
// Product overflows guarded by script size limit.
201
static_assert(max_script_size < max_size_t / multisig_default_sigops / 
202
    heavy_sigops_factor, "output sigop overflow guard");
203

204
size_t output::signature_operations(bool bip141) const NOEXCEPT
1✔
205
{
206
    // Penalize quadratic signature operations (bip141).
207
    const auto factor = bip141 ? heavy_sigops_factor : one;
1✔
208

209
    // Count heavy sigops in the output script.
210
    return script_->signature_operations(false) * factor;
1✔
211
}
212

213
bool output::is_dust(uint64_t minimum_value) const NOEXCEPT
9✔
214
{
215
    // If provably unspendable it does not expand the unspent output set. Dust
216
    // is all about prunability. Miners can be expected take the largest fee
217
    // independent of dust, so this is an attempt to prevent miners from seeing
218
    // transactions with unprunable outputs.
219
    return value_ < minimum_value && !script_->is_unspendable();
9✔
220
}
221

222
BC_POP_WARNING()
223
BC_POP_WARNING()
224

225
// JSON value convertors.
226
// ----------------------------------------------------------------------------
227

228
namespace json = boost::json;
229

230
// boost/json will soon have NOEXCEPT: github.com/boostorg/json/pull/636
231
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
232

233
output tag_invoke(json::value_to_tag<output>,
5✔
234
    const json::value& value) NOEXCEPT
235
{
236
    return
5✔
237
    {
238
        value.at("value").to_number<uint64_t>(),
5✔
239
        json::value_to<chain::script>(value.at("script"))
10✔
240
    };
10✔
241
}
242

243
void tag_invoke(json::value_from_tag, json::value& value,
10✔
244
    const output& output) NOEXCEPT
245
{
246
    value =
10✔
247
    {
248
        { "value", output.value() },
249
        { "script", output.script() },
250
    };
10✔
251
}
10✔
252

253
BC_POP_WARNING()
254

255
output::cptr tag_invoke(json::value_to_tag<output::cptr>,
×
256
    const json::value& value) NOEXCEPT
257
{
258
    return to_shared(tag_invoke(json::value_to_tag<output>{}, value));
×
259
}
260

261
// Shared pointer overload is required for navigation.
262
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
263
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
264

265
void tag_invoke(json::value_from_tag tag, json::value& value,
8✔
266
    const output::cptr& output) NOEXCEPT
267
{
268
    tag_invoke(tag, value, *output);
8✔
269
}
8✔
270

271
BC_POP_WARNING()
272
BC_POP_WARNING()
273

274
} // namespace chain
275
} // namespace system
276
} // 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