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

libbitcoin / libbitcoin-system / 20611099764

31 Dec 2025 03:13AM UTC coverage: 81.203% (+0.07%) from 81.134%
20611099764

push

github

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

Add header::difficulty, and config::version (4 segment uint32_t).

67 of 71 new or added lines in 4 files covered. (94.37%)

10843 of 13353 relevant lines covered (81.2%)

3546466.5 hits per line

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

78.02
/src/chain/header.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/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
102✔
42
  : header(0, {}, {}, 0, 0, 0, false)
102✔
43
{
44
}
102✔
45

46
header::header(uint32_t version, hash_digest&& previous_block_hash,
10✔
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
}
10✔
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
}
8✔
61

62
header::header(const data_slice& data) NOEXCEPT
1✔
63
  : header(stream::in::fast(data))
1✔
64
{
65
}
1✔
66

67
// protected
68
header::header(stream::in::fast&& stream) NOEXCEPT
1✔
69
  : header(read::bytes::fast(stream))
1✔
70
{
71
}
1✔
72

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

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

83
// protected
84
header::header(reader&& source) NOEXCEPT
5✔
85
  : header(source)
5✔
86
{
87
}
×
88

89
header::header(reader& source) NOEXCEPT
122✔
90
{
91
    assign_data(source);
122✔
92
}
122✔
93

94
// protected
95
header::header(uint32_t version, hash_digest&& previous_block_hash,
112✔
96
    hash_digest&& merkle_root, uint32_t timestamp, uint32_t bits,
97
    uint32_t nonce, bool valid) NOEXCEPT
112✔
98
  : version_(version),
112✔
99
    previous_block_hash_(std::move(previous_block_hash)),
112✔
100
    merkle_root_(std::move(merkle_root)),
112✔
101
    timestamp_(timestamp),
112✔
102
    bits_(bits),
112✔
103
    nonce_(nonce),
112✔
104
    valid_(valid)
112✔
105
{
106
}
×
107

108
// protected
109
header::header(uint32_t version, const hash_digest& previous_block_hash,
8✔
110
    const hash_digest& merkle_root, uint32_t timestamp, uint32_t bits,
111
    uint32_t nonce, bool valid) NOEXCEPT
8✔
112
  : version_(version),
8✔
113
    previous_block_hash_(previous_block_hash),
8✔
114
    merkle_root_(merkle_root),
8✔
115
    timestamp_(timestamp),
8✔
116
    bits_(bits),
8✔
117
    nonce_(nonce),
8✔
118
    valid_(valid)
8✔
119
{
120
}
×
121

122
// Operators.
123
// ----------------------------------------------------------------------------
124

125
bool header::operator==(const header& other) const NOEXCEPT
44✔
126
{
127
    return (version_ == other.version_)
44✔
128
        && (previous_block_hash_ == other.previous_block_hash_)
37✔
129
        && (merkle_root_ == other.merkle_root_)
37✔
130
        && (timestamp_ == other.timestamp_)
37✔
131
        && (bits_ == other.bits_)
132
        && (nonce_ == other.nonce_);
81✔
133
}
134

135
bool header::operator!=(const header& other) const NOEXCEPT
2✔
136
{
137
    return !(*this == other);
2✔
138
}
139

140
// Deserialization.
141
// ----------------------------------------------------------------------------
142

143
// private
144
void header::assign_data(reader& source) NOEXCEPT
122✔
145
{
146
    // Hashes are copied directly into to header-allocated space.
147
    // Integrals are stack-allocated and copied to header-allocated space.
148
    version_ = source.read_4_bytes_little_endian();
122✔
149
    source.read_bytes(previous_block_hash_.data(), hash_size);
122✔
150
    source.read_bytes(merkle_root_.data(), hash_size);
122✔
151
    timestamp_ = source.read_4_bytes_little_endian();
122✔
152
    bits_ = source.read_4_bytes_little_endian();
122✔
153
    nonce_ = source.read_4_bytes_little_endian();
122✔
154
    valid_ = source;
122✔
155
}
122✔
156

157
// Serialization.
158
// ----------------------------------------------------------------------------
159

160
data_chunk header::to_data() const NOEXCEPT
9✔
161
{
162
    data_chunk data(serialized_size());
9✔
163
    stream::out::fast ostream(data);
9✔
164
    write::bytes::fast out(ostream);
9✔
165
    to_data(out);
9✔
166
    return data;
18✔
167
}
9✔
168

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

175
void header::to_data(writer& sink) const NOEXCEPT
97✔
176
{
177
    sink.write_4_bytes_little_endian(version_);
97✔
178
    sink.write_bytes(previous_block_hash_);
97✔
179
    sink.write_bytes(merkle_root_);
97✔
180
    sink.write_4_bytes_little_endian(timestamp_);
97✔
181
    sink.write_4_bytes_little_endian(bits_);
97✔
182
    sink.write_4_bytes_little_endian(nonce_);
97✔
183
}
97✔
184

185
// Properties.
186
// ----------------------------------------------------------------------------
187

188
bool header::is_valid() const NOEXCEPT
11✔
189
{
190
    return valid_;
11✔
191
}
192

193
uint32_t header::version() const NOEXCEPT
6✔
194
{
195
    return version_;
4✔
196
}
197

198
const hash_digest& header::previous_block_hash() const NOEXCEPT
6✔
199
{
200
    return previous_block_hash_;
6✔
201
}
202

203
const hash_digest& header::merkle_root() const NOEXCEPT
20✔
204
{
205
    return merkle_root_;
20✔
206
}
207

208
uint32_t header::timestamp() const NOEXCEPT
6✔
209
{
210
    return timestamp_;
4✔
211
}
212

213
uint32_t header::bits() const NOEXCEPT
6✔
214
{
215
    return bits_;
4✔
216
}
217

218
uint32_t header::nonce() const NOEXCEPT
6✔
219
{
220
    return nonce_;
4✔
221
}
222

223
// static/computed
224
uint256_t header::proof(uint32_t bits) NOEXCEPT
1✔
225
{
226
    auto target = compact::expand(bits);
1✔
227

228
    //*************************************************************************
229
    // CONSENSUS: bits may be overflowed, which is guarded here.
230
    // A target of zero is disallowed so is useful as a sentinel value.
231
    //*************************************************************************
232
    if (is_zero(target))
1✔
233
        return target;
×
234

235
    //*************************************************************************
236
    // CONSENSUS: If target is (2^256)-1, division would fail, however compact
237
    // compression is lossy, and therefore unable to produce negative one.
238
    //*************************************************************************
239

240
    // We need to compute 2**256 / (target + 1), but we can't represent 2**256
241
    // as it's too large for uint256. However as 2**256 is at least as large as
242
    // target + 1, it is equal to ((2**256 - target - 1) / (target + 1)) + 1, or
243
    // (~target / (target + 1)) + 1.
244
    return ++(~target / (target + one));
2✔
245
}
246

247
// computed
248
uint256_t header::proof() const NOEXCEPT
1✔
249
{
250
    // Returns zero if bits_ mantissa is less than one or bits_ is overflowed.
251
    return proof(bits_);
1✔
252
}
253

254
// computed
255
hash_digest header::hash() const NOEXCEPT
46✔
256
{
257
    if (hash_)
46✔
258
        return *hash_;
×
259

260
    BC_PUSH_WARNING(LOCAL_VARIABLE_NOT_INITIALIZED)
261
    hash_digest digest;
46✔
262
    BC_POP_WARNING()
263

264
    stream::out::fast stream{ digest };
46✔
265
    hash::sha256x2::fast sink{ stream };
46✔
266
    to_data(sink);
46✔
267
    sink.flush();
46✔
268
    return digest;
46✔
269
}
46✔
270

271
// computed, not used in consensus.
272
double header::difficulty() const NOEXCEPT
1✔
273
{
274
    auto shift = bit_and(shift_right(bits_, 24), 0xff_u32);
1✔
275
    auto difference =
1✔
276
        static_cast<double>(0x0000ffff_u32) /
277
        static_cast<double>(bit_and(bits_, 0x00ffffff_u32));
1✔
278

279
    while (shift < 29u)
1✔
280
    {
NEW
281
        difference *= 256.0;
×
NEW
282
        ++shift;
×
283
    }
284

285
    while (shift > 29u)
1✔
286
    {
NEW
287
        difference /= 256.0;
×
NEW
288
        --shift;
×
289
    }
290

291
    return difference;
1✔
292
}
293

294
// Cache and metadata.
295
// ----------------------------------------------------------------------------
296

297
void header::set_hash(const hash_digest& hash) const NOEXCEPT
×
298
{
299
    hash_ = hash;
×
300
}
×
301

302
const hash_digest& header::get_hash() const NOEXCEPT
×
303
{
304
    if (!hash_)
×
305
        set_hash(hash());
×
306

307
    return *hash_;
×
308
}
309

310
const chain_state::cptr& header::get_state() const NOEXCEPT
×
311
{
312
    return state_;
×
313
}
314

315
void header::set_state(const chain_state::cptr& state) const NOEXCEPT
×
316
{
317
    state_ = state;
×
318
}
×
319

320
// Check.
321
// ----------------------------------------------------------------------------
322

323
bool header::is_invalid_proof_of_work(uint32_t proof_of_work_limit,
5✔
324
    bool scrypt) const NOEXCEPT
325
{
326
    static const auto limit = compact::expand(proof_of_work_limit);
5✔
327
    const auto target = compact::expand(bits_);
5✔
328

329
    //*************************************************************************
330
    // CONSENSUS: bits_ may be overflowed, which is guarded here.
331
    // A target of zero is disallowed so is useful as a sentinel value.
332
    //*************************************************************************
333
    if (is_zero(target))
5✔
334
        return true;
335

336
    // Ensure claimed work is at or above minimum (less is more).
337
    if (target > limit)
4✔
338
        return true;
339

340
    // Conditionally use scrypt proof of work (e.g. Litecoin).
341
    return to_uintx(scrypt ? scrypt_hash(to_data()) : hash()) > target;
10✔
342
}
343

344
// ****************************************************************************
345
// CONSENSUS: 32 bit unsigned unix time overflows in 2106.
346
// ****************************************************************************
347
bool header::is_futuristic_timestamp(
2✔
348
    uint32_t timestamp_limit_seconds) const NOEXCEPT
349
{
350
    using namespace std::chrono;
2✔
351
    static const auto two_hours = seconds(timestamp_limit_seconds);
2✔
352
    const auto time = wall_clock::from_time_t(timestamp_);
2✔
353
    const auto future = wall_clock::now() + two_hours;
2✔
354
    return time > future;
2✔
355
}
356

357
// Validation.
358
// ----------------------------------------------------------------------------
359

360
code header::check(uint32_t timestamp_limit_seconds,
×
361
    uint32_t proof_of_work_limit, bool scrypt) const NOEXCEPT
362
{
363
    if (is_invalid_proof_of_work(proof_of_work_limit, scrypt))
×
364
        return error::invalid_proof_of_work;
×
365
    if (is_futuristic_timestamp(timestamp_limit_seconds))
×
366
        return error::futuristic_timestamp;
×
367

368
    return error::block_success;
×
369
}
370

371
// minimum_block_version
372
// median_time_past
373
// work_required
374

375
// Checkpoints and previous_block_hash are chain validation (not here).
376
// bits_ below is the consensus direct comparison of the header.bits value.
377
// All other work comparisons performed on expanded/normalized bits values.
378
code header::accept(const context& ctx) const NOEXCEPT
×
379
{
380
    if (ctx.is_insufficient_version(version_))
×
381
        return error::insufficient_block_version;
×
382
    if (ctx.is_anachronistic_timestamp(timestamp_))
×
383
        return error::anachronistic_timestamp;
×
384
    if (ctx.is_invalid_work(bits_))
×
385
        return error::incorrect_proof_of_work;
×
386

387
    return error::block_success;
×
388
}
389

390
// JSON value convertors.
391
// ----------------------------------------------------------------------------
392

393
namespace json = boost::json;
394

395
DEFINE_JSON_TO_TAG(header)
2✔
396
{
397
    return
2✔
398
    {
399
        value.at("version").to_number<uint32_t>(),
2✔
400
        decode_hash<hash_size>(value.at("previous").as_string()),
2✔
401
        decode_hash<hash_size>(value.at("merkle_root").as_string()),
2✔
402
        value.at("timestamp").to_number<uint32_t>(),
2✔
403
        value.at("bits").to_number<uint32_t>(),
2✔
404
        value.at("nonce").to_number<uint32_t>()
2✔
405
    };
8✔
406
}
407

408
DEFINE_JSON_FROM_TAG(header)
4✔
409
{
410
    value =
20✔
411
    {
412
        // hash is computed property
413
        { "hash", encode_hash(instance.hash()) },
4✔
414
        { "version", instance.version() },
415
        { "previous", encode_hash(instance.previous_block_hash()) },
8✔
416
        { "merkle_root", encode_hash(instance.merkle_root()) },
8✔
417
        { "timestamp", instance.timestamp() },
418
        { "bits", instance.bits() },
419
        { "nonce", instance.nonce() }
420
    };
4✔
421
}
4✔
422

423
DEFINE_JSON_TO_TAG(header::cptr)
×
424
{
425
    return to_shared(tag_invoke(to_tag<header>{}, value));
×
426
}
427

428
DEFINE_JSON_FROM_TAG(header::cptr)
×
429
{
430
    tag_invoke(from_tag{}, value, *instance);
×
431
}
×
432

433
} // namespace chain
434
} // namespace system
435
} // namespace libbitcoin
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc