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

libbitcoin / libbitcoin-system / 9352252904

03 Jun 2024 02:41PM UTC coverage: 82.751%. Remained the same
9352252904

push

github

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

Use block_success in header validation, comments, style.

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

2 existing lines in 1 file now uncovered.

9854 of 11908 relevant lines covered (82.75%)

4789258.99 hits per line

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

83.33
/src/chain/header.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/header.hpp>
20

21
#include <chrono>
22
#include <utility>
23
#include <bitcoin/system/chain/chain_state.hpp>
24
#include <bitcoin/system/chain/compact.hpp>
25
#include <bitcoin/system/data/data.hpp>
26
#include <bitcoin/system/define.hpp>
27
#include <bitcoin/system/hash/hash.hpp>
28
#include <bitcoin/system/error/error.hpp>
29
#include <bitcoin/system/stream/stream.hpp>
30

31
namespace libbitcoin {
32
namespace system {
33
namespace chain {
34

35
// Use system clock because we require accurate time of day.
36
using wall_clock = std::chrono::system_clock;
37

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

41
header::header() NOEXCEPT
74✔
42
  : header(0, {}, {}, 0, 0, 0, false)
74✔
43
{
44
}
74✔
45

46
header::header(uint32_t version, hash_digest&& previous_block_hash,
8✔
47
    hash_digest&& merkle_root, uint32_t timestamp, uint32_t bits,
48
    uint32_t nonce) NOEXCEPT
49
  : header(version, std::move(previous_block_hash), std::move(merkle_root),
50
      timestamp, bits, nonce, true)
51
{
52
}
8✔
53

54
header::header(uint32_t version, const hash_digest& previous_block_hash,
8✔
55
    const hash_digest& merkle_root, uint32_t timestamp, uint32_t bits,
56
    uint32_t nonce) NOEXCEPT
57
  : header(version, previous_block_hash, merkle_root, timestamp, bits, nonce,
58
      true)
59
{
60
}
6✔
61

62
header::header(const data_slice& data) NOEXCEPT
1✔
63
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
64
  : header(stream::in::copy(data))
1✔
65
    BC_POP_WARNING()
66
{
67
}
1✔
68

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

74
header::header(stream::in::fast& stream) NOEXCEPT
1✔
75
  : header(read::bytes::fast(stream))
1✔
76
{
77
}
1✔
78

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

84
header::header(std::istream& stream) NOEXCEPT
3✔
85
  : header(read::bytes::istream(stream))
3✔
86
{
87
}
3✔
88

89
header::header(reader&& source) NOEXCEPT
5✔
90
  : header(from_data(source))
5✔
91
{
92
}
5✔
93

94
header::header(reader& source) NOEXCEPT
77✔
95
  : header(from_data(source))
77✔
96
{
97
}
77✔
98

99
// protected
100
header::header(uint32_t version, hash_digest&& previous_block_hash,
164✔
101
    hash_digest&& merkle_root, uint32_t timestamp, uint32_t bits,
102
    uint32_t nonce, bool valid) NOEXCEPT
82✔
103
  : version_(version),
164✔
104
    previous_block_hash_(std::move(previous_block_hash)),
8✔
105
    merkle_root_(std::move(merkle_root)),
164✔
106
    timestamp_(timestamp),
164✔
107
    bits_(bits),
164✔
108
    nonce_(nonce),
164✔
109
    valid_(valid)
164✔
110
{
111
}
×
112

113
// protected
114
header::header(uint32_t version, const hash_digest& previous_block_hash,
8✔
115
    const hash_digest& merkle_root, uint32_t timestamp, uint32_t bits,
116
    uint32_t nonce, bool valid) NOEXCEPT
6✔
117
  : version_(version),
8✔
118
    previous_block_hash_(previous_block_hash),
8✔
119
    merkle_root_(merkle_root),
8✔
120
    timestamp_(timestamp),
8✔
121
    bits_(bits),
8✔
122
    nonce_(nonce),
8✔
123
    valid_(valid)
2✔
124
{
125
}
×
126

127
// Operators.
128
// ----------------------------------------------------------------------------
129

130
bool header::operator==(const header& other) const NOEXCEPT
27✔
131
{
132
    return (version_ == other.version_)
27✔
133
        && (previous_block_hash_ == other.previous_block_hash_)
20✔
134
        && (merkle_root_ == other.merkle_root_)
20✔
135
        && (timestamp_ == other.timestamp_)
20✔
136
        && (bits_ == other.bits_)
137
        && (nonce_ == other.nonce_);
47✔
138
}
139

140
bool header::operator!=(const header& other) const NOEXCEPT
2✔
141
{
142
    return !(*this == other);
2✔
143
}
144

145
// Deserialization.
146
// ----------------------------------------------------------------------------
147

148
// static/private
149
header header::from_data(reader& source) NOEXCEPT
82✔
150
{
151
    return
82✔
152
    {
153
        source.read_4_bytes_little_endian(),
82✔
154
        source.read_hash(),
82✔
155
        source.read_hash(),
82✔
156
        source.read_4_bytes_little_endian(),
82✔
157
        source.read_4_bytes_little_endian(),
82✔
158
        source.read_4_bytes_little_endian(),
82✔
159
        source
160
    };
164✔
161
}
162

163
// Serialization.
164
// ----------------------------------------------------------------------------
165

166
data_chunk header::to_data() const NOEXCEPT
7✔
167
{
168
    data_chunk data(serialized_size());
7✔
169

170
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
171
    stream::out::copy ostream(data);
7✔
172
    BC_POP_WARNING()
173

174
    to_data(ostream);
7✔
175
    return data;
14✔
176
}
7✔
177

178
void header::to_data(std::ostream& stream) const NOEXCEPT
8✔
179
{
180
    write::bytes::ostream out(stream);
8✔
181
    to_data(out);
8✔
182
}
8✔
183

184
void header::to_data(writer& sink) const NOEXCEPT
76✔
185
{
186
    sink.write_4_bytes_little_endian(version_);
76✔
187
    sink.write_bytes(previous_block_hash_);
76✔
188
    sink.write_bytes(merkle_root_);
76✔
189
    sink.write_4_bytes_little_endian(timestamp_);
76✔
190
    sink.write_4_bytes_little_endian(bits_);
76✔
191
    sink.write_4_bytes_little_endian(nonce_);
76✔
192
}
76✔
193

194
// Properties.
195
// ----------------------------------------------------------------------------
196

197
bool header::is_valid() const NOEXCEPT
11✔
198
{
199
    return valid_;
11✔
200
}
201

202
uint32_t header::version() const NOEXCEPT
6✔
203
{
204
    return version_;
4✔
205
}
206

207
const hash_digest& header::previous_block_hash() const NOEXCEPT
6✔
208
{
209
    return previous_block_hash_;
6✔
210
}
211

212
const hash_digest& header::merkle_root() const NOEXCEPT
17✔
213
{
214
    return merkle_root_;
17✔
215
}
216

217
uint32_t header::timestamp() const NOEXCEPT
6✔
218
{
219
    return timestamp_;
4✔
220
}
221

222
uint32_t header::bits() const NOEXCEPT
6✔
223
{
224
    return bits_;
4✔
225
}
226

227
uint32_t header::nonce() const NOEXCEPT
6✔
228
{
229
    return nonce_;
4✔
230
}
231

232
void header::set_hash(hash_digest&& hash) const NOEXCEPT
×
233
{
234
    hash_ = to_shared(std::move(hash));
×
235
}
×
236

237
// computed
238
hash_digest header::hash() const NOEXCEPT
39✔
239
{
240
    if (hash_)
39✔
241
        return *hash_;
×
242

243
    BC_PUSH_WARNING(LOCAL_VARIABLE_NOT_INITIALIZED)
244
    hash_digest digest;
39✔
245
    BC_POP_WARNING()
246

247
    stream::out::fast stream{ digest };
39✔
248
    hash::sha256x2::fast sink{ stream };
39✔
249
    to_data(sink);
39✔
250
    sink.flush();
39✔
251
    return digest;
39✔
252
}
39✔
253

254
// static
255
uint256_t header::proof(uint32_t bits) NOEXCEPT
1✔
256
{
257
    auto target = compact::expand(bits);
1✔
258

259
    //*************************************************************************
260
    // CONSENSUS: bits may be overflowed, which is guarded here.
261
    // A target of zero is disallowed so is useful as a sentinel value.
262
    //*************************************************************************
263
    if (is_zero(target))
1✔
264
        return target;
×
265

266
    //*************************************************************************
267
    // CONSENSUS: If target is (2^256)-1, division would fail, however compact
268
    // compression is lossy, and therefore unable to produce negative one.
269
    //*************************************************************************
270

271
    // We need to compute 2**256 / (target + 1), but we can't represent 2**256
272
    // as it's too large for uint256. However as 2**256 is at least as large as
273
    // target + 1, it is equal to ((2**256 - target - 1) / (target + 1)) + 1, or
274
    // (~target / (target + 1)) + 1.
275
    return ++(~target / (target + one));
2✔
276
}
277

278
// computed
279
uint256_t header::proof() const NOEXCEPT
1✔
280
{
281
    // Returns zero if bits_ mantissa is less than one or bits_ is overflowed.
282
    return proof(bits_);
1✔
283
}
284

285
// Check.
286
// ----------------------------------------------------------------------------
287

288
bool header::is_invalid_proof_of_work(uint32_t proof_of_work_limit,
6✔
289
    bool scrypt) const NOEXCEPT
290
{
291
    static const auto limit = compact::expand(proof_of_work_limit);
6✔
292
    const auto target = compact::expand(bits_);
6✔
293

294
    //*************************************************************************
295
    // CONSENSUS: bits_ may be overflowed, which is guarded here.
296
    // A target of zero is disallowed so is useful as a sentinel value.
297
    //*************************************************************************
298
    if (is_zero(target))
6✔
299
        return true;
300

301
    // Ensure claimed work is at or above minimum (less is more).
302
    if (target > limit)
5✔
303
        return true;
304

305
    // Conditionally use scrypt proof of work (e.g. Litecoin).
306
    return to_uintx(scrypt ? scrypt_hash(to_data()) : hash()) > target;
10✔
307
}
308

309
// ****************************************************************************
310
// CONSENSUS: bitcoin 32bit unix time: en.wikipedia.org/wiki/Year_2038_problem
311
// ****************************************************************************
312
bool header::is_invalid_timestamp(
2✔
313
    uint32_t timestamp_limit_seconds) const NOEXCEPT
314
{
315
    using namespace std::chrono;
2✔
316
    static const auto two_hours = seconds(timestamp_limit_seconds);
2✔
317
    const auto time = wall_clock::from_time_t(timestamp_);
2✔
318
    const auto future = wall_clock::now() + two_hours;
2✔
319
    return time > future;
2✔
320
}
321

322
// Validation.
323
// ----------------------------------------------------------------------------
324

325
code header::check(uint32_t timestamp_limit_seconds,
×
326
    uint32_t proof_of_work_limit, bool scrypt) const NOEXCEPT
327
{
328
    if (is_invalid_proof_of_work(proof_of_work_limit, scrypt))
×
329
        return error::invalid_proof_of_work;
×
330
    if (is_invalid_timestamp(timestamp_limit_seconds))
×
331
        return error::futuristic_timestamp;
×
332

NEW
333
    return error::block_success;
×
334
}
335

336
// minimum_block_version
337
// median_time_past
338
// work_required
339

340
// Checkpoints and previous_block_hash are chain validation (not here).
341
// bits_ below is the consensus direct comparison of the header.bits value.
342
// All other work comparisons performed on expanded/normalized bits values.
343
code header::accept(const context& ctx) const NOEXCEPT
×
344
{
345
    if (version_ < ctx.minimum_block_version)
×
346
        return error::invalid_block_version;
×
347
    if (timestamp_ <= ctx.median_time_past)
×
348
        return error::timestamp_too_early;
×
349
    if (bits_ != ctx.work_required)
×
350
        return error::incorrect_proof_of_work;
×
351

NEW
352
    return error::block_success;
×
353
}
354

355
// JSON value convertors.
356
// ----------------------------------------------------------------------------
357

358
namespace json = boost::json;
359

360
// boost/json will soon have NOEXCEPT: github.com/boostorg/json/pull/636
361
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
362

363
header tag_invoke(json::value_to_tag<header>,
2✔
364
    const json::value& value) NOEXCEPT
365
{
366
    hash_digest previous, merkle_root;
2✔
367
    if (!decode_hash(previous, value.at("previous").get_string().c_str()) ||
4✔
368
        !decode_hash(merkle_root, value.at("merkle_root").get_string().c_str()))
2✔
369
        return {};
×
370

371
    return
2✔
372
    {
373
        value.at("version").to_number<uint32_t>(),
2✔
374
        previous,
375
        merkle_root,
376
        value.at("timestamp").to_number<uint32_t>(),
2✔
377
        value.at("bits").to_number<uint32_t>(),
2✔
378
        value.at("nonce").to_number<uint32_t>()
4✔
379
    };
8✔
380
}
381

382
void tag_invoke(json::value_from_tag, json::value& value,
4✔
383
    const header& tx) NOEXCEPT
384
{
385
    value =
16✔
386
    {
387
        { "version", tx.version() },
388
        { "previous", encode_hash(tx.previous_block_hash()) },
4✔
389
        { "merkle_root", encode_hash(tx.merkle_root()) },
8✔
390
        { "timestamp", tx.timestamp() },
391
        { "bits", tx.bits() },
392
        { "nonce", tx.nonce() }
393
    };
4✔
394
}
4✔
395

396
BC_POP_WARNING()
397

398
header::cptr tag_invoke(json::value_to_tag<header::cptr>,
×
399
    const json::value& value) NOEXCEPT
400
{
401
    return to_shared(tag_invoke(json::value_to_tag<header>{}, value));
×
402
}
403

404
// Shared pointer overload is required for navigation.
405
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
406
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
407

408
void tag_invoke(json::value_from_tag tag, json::value& value,
×
409
    const header::cptr& tx) NOEXCEPT
410
{
411
    tag_invoke(tag, value, *tx);
×
412
}
×
413

414
BC_POP_WARNING()
415
BC_POP_WARNING()
416

417
} // namespace chain
418
} // namespace system
419
} // 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