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

libbitcoin / libbitcoin-system / 4637370737

pending completion
4637370737

push

github

GitHub
Merge pull request #1353 from evoskuil/master

102 of 102 new or added lines in 5 files covered. (100.0%)

9438 of 11391 relevant lines covered (82.85%)

6703526.24 hits per line

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

84.57
/src/chain/header.cpp
1
/**
2
 * Copyright (c) 2011-2022 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
67✔
42
  : header(0, {}, {}, 0, 0, 0, false)
67✔
43
{
44
}
67✔
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
8✔
49
  : header(version, std::move(previous_block_hash), std::move(merkle_root),
50
      timestamp, bits, nonce, true)
8✔
51
{
52
}
8✔
53

54
header::header(uint32_t version, const hash_digest& previous_block_hash,
7✔
55
    const hash_digest& merkle_root, uint32_t timestamp, uint32_t bits,
56
    uint32_t nonce) NOEXCEPT
7✔
57
  : header(version, previous_block_hash, merkle_root, timestamp, bits, nonce,
58
      true)
7✔
59
{
60
}
7✔
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(std::istream&& stream) NOEXCEPT
1✔
70
  : header(read::bytes::istream(stream))
1✔
71
{
72
}
1✔
73

74
header::header(std::istream& stream) NOEXCEPT
3✔
75
  : header(read::bytes::istream(stream))
3✔
76
{
77
}
3✔
78

79
header::header(reader&& source) NOEXCEPT
4✔
80
  : header(from_data(source))
4✔
81
{
82
}
4✔
83

84
header::header(reader& source) NOEXCEPT
71✔
85
  : header(from_data(source))
71✔
86
{
87
}
71✔
88

89
// protected
90
header::header(uint32_t version, hash_digest&& previous_block_hash,
150✔
91
    hash_digest&& merkle_root, uint32_t timestamp, uint32_t bits,
92
    uint32_t nonce, bool valid) NOEXCEPT
150✔
93
  : version_(version),
150✔
94
    previous_block_hash_(std::move(previous_block_hash)),
150✔
95
    merkle_root_(std::move(merkle_root)),
150✔
96
    timestamp_(timestamp),
150✔
97
    bits_(bits),
150✔
98
    nonce_(nonce),
150✔
99
    valid_(valid)
150✔
100
{
101
}
150✔
102

103
// protected
104
header::header(uint32_t version, const hash_digest& previous_block_hash,
7✔
105
    const hash_digest& merkle_root, uint32_t timestamp, uint32_t bits,
106
    uint32_t nonce, bool valid) NOEXCEPT
7✔
107
  : version_(version),
7✔
108
    previous_block_hash_(previous_block_hash),
7✔
109
    merkle_root_(merkle_root),
7✔
110
    timestamp_(timestamp),
7✔
111
    bits_(bits),
7✔
112
    nonce_(nonce),
7✔
113
    valid_(valid)
7✔
114
{
115
}
7✔
116

117
// Operators.
118
// ----------------------------------------------------------------------------
119

120
bool header::operator==(const header& other) const NOEXCEPT
26✔
121
{
122
    return (version_ == other.version_)
26✔
123
        && (previous_block_hash_ == other.previous_block_hash_)
19✔
124
        && (merkle_root_ == other.merkle_root_)
19✔
125
        && (timestamp_ == other.timestamp_)
19✔
126
        && (bits_ == other.bits_)
127
        && (nonce_ == other.nonce_);
45✔
128
}
129

130
bool header::operator!=(const header& other) const NOEXCEPT
2✔
131
{
132
    return !(*this == other);
2✔
133
}
134

135
// Deserialization.
136
// ----------------------------------------------------------------------------
137

138
// static/private
139
header header::from_data(reader& source) NOEXCEPT
75✔
140
{
141
    return
75✔
142
    {
143
        source.read_4_bytes_little_endian(),
75✔
144
        source.read_hash(),
75✔
145
        source.read_hash(),
75✔
146
        source.read_4_bytes_little_endian(),
75✔
147
        source.read_4_bytes_little_endian(),
75✔
148
        source.read_4_bytes_little_endian(),
75✔
149
        source
150
    };
150✔
151
}
152

153
// Serialization.
154
// ----------------------------------------------------------------------------
155

156
data_chunk header::to_data() const NOEXCEPT
6✔
157
{
158
    data_chunk data(serialized_size());
6✔
159

160
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
161
    stream::out::copy ostream(data);
6✔
162
    BC_POP_WARNING()
163

164
    to_data(ostream);
6✔
165
    return data;
12✔
166
}
6✔
167

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

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

184
// Properties.
185
// ----------------------------------------------------------------------------
186

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

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

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

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

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

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

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

222
void header::set_hash(hash_digest&& hash) const NOEXCEPT
×
223
{
224
    hash_ = to_shared(std::move(hash));
×
225
}
×
226

227
// computed
228
hash_digest header::hash() const NOEXCEPT
37✔
229
{
230
    if (hash_)
37✔
231
        return *hash_;
×
232

233
    hash_digest digest{};
37✔
234
    hash::sha256x2::copy sink(digest);
37✔
235
    to_data(sink);
37✔
236
    sink.flush();
37✔
237
    return digest;
37✔
238
}
37✔
239

240
// static/private
241
uint256_t header::difficulty(uint32_t bits) NOEXCEPT
1✔
242
{
243
    auto target = compact::expand(bits);
1✔
244

245
    //*************************************************************************
246
    // CONSENSUS: bits may be overflowed, which is guarded here.
247
    // A target of zero is disallowed so is useful as a sentinel value.
248
    //*************************************************************************
249
    if (is_zero(target))
1✔
250
        return target;
×
251

252
    //*************************************************************************
253
    // CONSENSUS: If target is (2^256)-1, division would fail, however compact
254
    // compression is lossy, and therefore unable to produce negative one.
255
    //*************************************************************************
256

257
    // We need to compute 2**256 / (target + 1), but we can't represent 2**256
258
    // as it's too large for uint256. However as 2**256 is at least as large as
259
    // target + 1, it is equal to ((2**256 - target - 1) / (target + 1)) + 1, or
260
    // (~target / (target + 1)) + 1.
261
    return ++(~target / (target + one));
2✔
262
}
263

264
// computed
265
uint256_t header::difficulty() const NOEXCEPT
1✔
266
{
267
    // Returns zero if bits_ mantissa is less than one or bits_ is overflowed.
268
    return difficulty(bits_);
1✔
269
}
270

271
// Check.
272
// ----------------------------------------------------------------------------
273

274
bool header::is_invalid_proof_of_work(uint32_t proof_of_work_limit,
6✔
275
    bool scrypt) const NOEXCEPT
276
{
277
    static const auto limit = compact::expand(proof_of_work_limit);
6✔
278
    const auto target = compact::expand(bits_);
6✔
279

280
    //*************************************************************************
281
    // CONSENSUS: bits_ may be overflowed, which is guarded here.
282
    // A target of zero is disallowed so is useful as a sentinel value.
283
    //*************************************************************************
284
    if (is_zero(target))
6✔
285
        return true;
286

287
    // Ensure claimed work is at or above minimum (less is more).
288
    if (target > limit)
5✔
289
        return true;
290

291
    // Conditionally use scrypt proof of work (e.g. Litecoin).
292
    return to_uintx(scrypt ? scrypt_hash(to_data()) : hash()) > target;
12✔
293
}
294

295
// ****************************************************************************
296
/// CONSENSUS: bitcoin 32bit unix time: en.wikipedia.org/wiki/Year_2038_problem
297
// ****************************************************************************
298
bool header::is_invalid_timestamp(
2✔
299
    uint32_t timestamp_limit_seconds) const NOEXCEPT
300
{
301
    using namespace std::chrono;
2✔
302
    static const auto two_hours = seconds(timestamp_limit_seconds);
2✔
303
    const auto time = wall_clock::from_time_t(timestamp_);
2✔
304
    const auto future = wall_clock::now() + two_hours;
2✔
305
    return time > future;
2✔
306
}
307

308
// Validation.
309
// ----------------------------------------------------------------------------
310

311
code header::check(uint32_t timestamp_limit_seconds,
×
312
    uint32_t proof_of_work_limit, bool scrypt) const NOEXCEPT
313
{
314
    if (is_invalid_proof_of_work(proof_of_work_limit, scrypt))
×
315
        return error::invalid_proof_of_work;
×
316
    if (is_invalid_timestamp(timestamp_limit_seconds))
×
317
        return error::futuristic_timestamp;
×
318

319
    return error::success;
×
320
}
321

322
// Checkpoints and previous_block_hash are chain validation (not here).
323
// bits_ below is the consensus direct comparison of the header.bits value.
324
// All other work comparisons performed on expanded/normalized bits values.
325
code header::accept(const context& ctx) const NOEXCEPT
×
326
{
327
    if (version_ < ctx.minimum_block_version)
×
328
        return error::invalid_block_version;
×
329
    if (timestamp_ <= ctx.median_time_past)
×
330
        return error::timestamp_too_early;
×
331
    if (bits_ != ctx.work_required)
×
332
        return error::incorrect_proof_of_work;
×
333

334
    return error::success;
×
335
}
336

337
// JSON value convertors.
338
// ----------------------------------------------------------------------------
339

340
namespace json = boost::json;
341

342
// boost/json will soon have NOEXCEPT: github.com/boostorg/json/pull/636
343
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
344

345
header tag_invoke(json::value_to_tag<header>,
2✔
346
    const json::value& value) NOEXCEPT
347
{
348
    hash_digest previous, merkle_root;
2✔
349
    if (!decode_hash(previous, value.at("previous").get_string().c_str()) ||
6✔
350
        !decode_hash(merkle_root, value.at("merkle_root").get_string().c_str()))
4✔
351
        return {};
×
352

353
    return
2✔
354
    {
355
        value.at("version").to_number<uint32_t>(),
2✔
356
        previous,
357
        merkle_root,
358
        value.at("timestamp").to_number<uint32_t>(),
2✔
359
        value.at("bits").to_number<uint32_t>(),
2✔
360
        value.at("nonce").to_number<uint32_t>()
4✔
361
    };
8✔
362
}
363

364
void tag_invoke(json::value_from_tag, json::value& value,
4✔
365
    const header& tx) NOEXCEPT
366
{
367
    value =
12✔
368
    {
369
        { "version", tx.version() },
370
        { "previous", encode_hash(tx.previous_block_hash()) },
4✔
371
        { "merkle_root", encode_hash(tx.merkle_root()) },
8✔
372
        { "timestamp", tx.timestamp() },
373
        { "bits", tx.bits() },
374
        { "nonce", tx.nonce() }
375
    };
4✔
376
}
4✔
377

378
BC_POP_WARNING()
379

380
header::cptr tag_invoke(json::value_to_tag<header::cptr>,
×
381
    const json::value& value) NOEXCEPT
382
{
383
    return to_shared(tag_invoke(json::value_to_tag<header>{}, value));
×
384
}
385

386
// Shared pointer overload is required for navigation.
387
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
388
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
389

390
void tag_invoke(json::value_from_tag tag, json::value& value,
×
391
    const header::cptr& tx) NOEXCEPT
392
{
393
    tag_invoke(tag, value, *tx);
×
394
}
×
395

396
BC_POP_WARNING()
397
BC_POP_WARNING()
398

399
} // namespace chain
400
} // namespace system
401
} // 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