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

libbitcoin / libbitcoin-system / 9950156475

16 Jul 2024 03:16AM UTC coverage: 83.203% (+0.3%) from 82.874%
9950156475

push

github

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

Optimizing deserializations.

205 of 222 new or added lines in 12 files covered. (92.34%)

14 existing lines in 8 files now uncovered.

10090 of 12127 relevant lines covered (83.2%)

4761709.16 hits per line

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

82.83
/src/chain/output.cpp
1
/**
2
 * Copyright (c) 2011-2023 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

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

38
// Constructors.
39
// ----------------------------------------------------------------------------
40

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

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

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

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

63
output::output(const data_slice& data) NOEXCEPT
4✔
64
  : output(stream::in::copy(data))
4✔
65
{
66
}
4✔
67

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

73
output::output(stream::in::fast& stream) NOEXCEPT
×
74
  : output(read::bytes::fast(stream))
×
75
{
76
}
×
77

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

83
output::output(std::istream& stream) NOEXCEPT
2✔
84
  : output(read::bytes::istream(stream))
2✔
85
{
86
}
2✔
87

88
output::output(reader&& source) NOEXCEPT
6✔
89
  : output(source/*from_data(source)*/)
6✔
90
{
UNCOV
91
}
×
92

93
output::output(reader& source) NOEXCEPT
255✔
94
////: output(from_data(source))
95
  : value_(source.read_8_bytes_little_endian()),
510✔
96
    script_(
510✔
97
        source.get_allocator().new_object<chain::script>(source, true),
255✔
98
        source.get_allocator().deleter<chain::script>(source.get_arena())),
255✔
99
    valid_(source),
255✔
100
    size_(serialized_size(*script_, value_))
510✔
101
{
102
    ////assign_data(source);
103
}
255✔
104

105
// protected
106
output::output(uint64_t value, const chain::script::cptr& script,
938✔
107
    bool valid) NOEXCEPT
938✔
108
  : value_(value),
938✔
109
    script_(script),
110
    valid_(valid),
938✔
111
    size_(serialized_size(*script, value))
938✔
112
{
113
}
938✔
114

115
// Operators.
116
// ----------------------------------------------------------------------------
117

118
bool output::operator==(const output& other) const NOEXCEPT
35✔
119
{
120
    return (value_ == other.value_)
35✔
121
        && (script_ == other.script_ || *script_ == *other.script_);
35✔
122
}
123

124
bool output::operator!=(const output& other) const NOEXCEPT
2✔
125
{
126
    return !(*this == other);
2✔
127
}
128

129
// Deserialization.
130
// ----------------------------------------------------------------------------
131

132
// static/private
133
////output output::from_data(reader& source) NOEXCEPT
134
////{
135
////    return
136
////    {
137
////        source.read_8_bytes_little_endian(),
138
////        to_shared<chain::script>(source, true),
139
////        source
140
////    };
141
////}
142

143
// private
NEW
144
void output::assign_data(reader&) NOEXCEPT
×
145
{
146
    ////auto& allocator = source.get_allocator();
147
    ////
148
    ////value_ = source.read_8_bytes_little_endian();
149
    ////
150
    ////allocator.construct<chain::script::cptr>(&script_,
151
    ////    allocator.new_object<chain::script>(source, true),
152
    ////    allocator.deleter<chain::script>(source.get_arena()));
153
    ////
154
    ////size_ = serialized_size(*script_, value_);
155
    ////valid_ = source;
UNCOV
156
}
×
157

158
// Serialization.
159
// ----------------------------------------------------------------------------
160

161
data_chunk output::to_data() const NOEXCEPT
2✔
162
{
163
    data_chunk data(serialized_size());
2✔
164
    stream::out::copy ostream(data);
2✔
165
    to_data(ostream);
2✔
166
    return data;
4✔
167
}
2✔
168

169
void output::to_data(std::ostream& stream) const NOEXCEPT
3✔
170
{
171
    write::bytes::ostream out(stream);
3✔
172
    to_data(out);
3✔
173
}
3✔
174

175
void output::to_data(writer& sink) const NOEXCEPT
1,719✔
176
{
177
    sink.write_8_bytes_little_endian(value_);
1,719✔
178
    script_->to_data(sink, true);
1,719✔
179
}
1,719✔
180

181
// static/private
182
size_t output::serialized_size(const chain::script& script,
1,193✔
183
    uint64_t value) NOEXCEPT
184
{
185
    return ceilinged_add(sizeof(value), script.serialized_size(true));
1,193✔
186
}
187

188
size_t output::serialized_size() const NOEXCEPT
592✔
189
{
190
    return size_;
2✔
191
}
192

193
// Properties.
194
// ----------------------------------------------------------------------------
195

196
bool output::is_valid() const NOEXCEPT
9✔
197
{
198
    return valid_;
9✔
199
}
200

201
uint64_t output::value() const NOEXCEPT
55✔
202
{
203
    return value_;
10✔
204
}
205

206
const chain::script& output::script() const NOEXCEPT
174✔
207
{
208
    return *script_;
10✔
209
}
210

211
const chain::script::cptr& output::script_ptr() const NOEXCEPT
1,492✔
212
{
213
    return script_;
1,492✔
214
}
215

216
// Methods.
217
// ----------------------------------------------------------------------------
218

219
bool output::committed_hash(hash_digest& out) const NOEXCEPT
×
220
{
221
    const auto& ops = script_->ops();
×
222
    if (!script::is_commitment_pattern(ops))
×
223
        return false;
224

225
    // The four byte offset for the witness commitment hash (bip141).
226

227
    // More efficient [] dereference is guarded above.
228
    BC_PUSH_WARNING(NO_ARRAY_INDEXING)
229
    const auto start = std::next(ops[1].data().begin(), sizeof(witness_head));
×
230
    BC_POP_WARNING()
231

232
    std::copy_n(start, hash_size, out.begin());
×
233
    return true;
×
234
}
235

236
// Product overflows guarded by script size limit.
237
static_assert(max_script_size < max_size_t / multisig_default_sigops / 
238
    heavy_sigops_factor, "output sigop overflow guard");
239

240
size_t output::signature_operations(bool bip141) const NOEXCEPT
1✔
241
{
242
    // Penalize quadratic signature operations (bip141).
243
    const auto factor = bip141 ? heavy_sigops_factor : one;
1✔
244

245
    // Count heavy sigops in the output script.
246
    return script_->signature_operations(false) * factor;
1✔
247
}
248

249
bool output::is_dust(uint64_t minimum_value) const NOEXCEPT
9✔
250
{
251
    // If provably unspendable it does not expand the unspent output set. Dust
252
    // is all about prunability. Miners can be expected take the largest fee
253
    // independent of dust, so this is an attempt to prevent miners from seeing
254
    // transactions with unprunable outputs.
255
    return value_ < minimum_value && !script_->is_unspendable();
9✔
256
}
257

258
BC_POP_WARNING()
259

260
// JSON value convertors.
261
// ----------------------------------------------------------------------------
262

263
namespace json = boost::json;
264

265
// boost/json will soon have NOEXCEPT: github.com/boostorg/json/pull/636
266
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
267

268
output tag_invoke(json::value_to_tag<output>,
5✔
269
    const json::value& value) NOEXCEPT
270
{
271
    return
5✔
272
    {
273
        value.at("value").to_number<uint64_t>(),
5✔
274
        json::value_to<chain::script>(value.at("script"))
10✔
275
    };
10✔
276
}
277

278
void tag_invoke(json::value_from_tag, json::value& value,
10✔
279
    const output& output) NOEXCEPT
280
{
281
    value =
10✔
282
    {
283
        { "value", output.value() },
284
        { "script", output.script() },
285
    };
10✔
286
}
10✔
287

288
BC_POP_WARNING()
289

290
output::cptr tag_invoke(json::value_to_tag<output::cptr>,
×
291
    const json::value& value) NOEXCEPT
292
{
293
    return to_shared(tag_invoke(json::value_to_tag<output>{}, value));
×
294
}
295

296
// Shared pointer overload is required for navigation.
297
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
298
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
299

300
void tag_invoke(json::value_from_tag tag, json::value& value,
8✔
301
    const output::cptr& output) NOEXCEPT
302
{
303
    tag_invoke(tag, value, *output);
8✔
304
}
8✔
305

306
BC_POP_WARNING()
307
BC_POP_WARNING()
308

309
} // namespace chain
310
} // namespace system
311
} // 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

© 2025 Coveralls, Inc