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

libbitcoin / libbitcoin-system / 13025432554

29 Jan 2025 05:52AM UTC coverage: 82.735% (+0.1%) from 82.637%
13025432554

push

github

web-flow
Merge pull request #1602 from pmienk/master

Regenerate artifacts.

10049 of 12146 relevant lines covered (82.74%)

3868132.18 hits per line

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

95.41
/include/bitcoin/system/impl/hash/rmd/algorithm.ipp
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
#ifndef LIBBITCOIN_SYSTEM_HASH_RMD_ALGORITHM_IPP
20
#define LIBBITCOIN_SYSTEM_HASH_RMD_ALGORITHM_IPP
21

22
#include <bit>
23
#include <iostream>
24

25
namespace libbitcoin {
26
namespace system {
27
namespace rmd {
28

29
// Bogus warning suggests constexpr when declared consteval.
30
BC_PUSH_WARNING(USE_CONSTEXPR_FOR_FUNCTION)
31
BC_PUSH_WARNING(NO_UNGUARDED_POINTERS)
32
BC_PUSH_WARNING(NO_POINTER_ARITHMETIC)
33
BC_PUSH_WARNING(NO_ARRAY_INDEXING)
34

35
// Functions.
36
// ----------------------------------------------------------------------------
37

38
TEMPLATE
39
INLINE constexpr auto CLASS::
522,169✔
40
f0(auto x, auto y, auto z) NOEXCEPT
41
{
42
    return f::xor_(f::xor_(x, y), z);
506,496✔
43
}
44

45
TEMPLATE
46
INLINE constexpr auto CLASS::
506,496✔
47
f1(auto x, auto y, auto z) NOEXCEPT
48
{
49
    return f::or_(f::and_(x, y), f::and_(f::not_(x), z));
506,496✔
50
}
51

52
TEMPLATE
53
INLINE constexpr auto CLASS::
522,169✔
54
f2(auto x, auto y, auto z) NOEXCEPT
55
{
56
    return f::xor_(f::or_(x, f::not_(y)), z);
506,496✔
57
}
58

59
TEMPLATE
60
INLINE constexpr auto CLASS::
522,169✔
61
f3(auto x, auto y, auto z) NOEXCEPT
62
{
63
    return f::or_(f::and_(x, z), f::and_(y, f::not_(z)));
506,496✔
64
}
65

66
TEMPLATE
67
INLINE constexpr auto CLASS::
506,496✔
68
f4(auto x, auto y, auto z) NOEXCEPT
69
{
70
    return f::xor_(x, f::or_(y, f::not_(z)));
506,496✔
71
}
72

73
// Rounds
74
// ---------------------------------------------------------------------------
75

76
TEMPLATE
77
template<size_t Round, typename Auto>
78
CONSTEVAL auto CLASS::
79
functor() NOEXCEPT
80
{
81
    using self = CLASS;
82
    constexpr auto fn = Round / K::columns;
83

84
    // Select function by column.
85
    if constexpr (RMD::strength == 128)
86
    {
87
        if constexpr (fn == 0u || fn == 7u)
88
            return &self::template f0<Auto, Auto, Auto>;
89
        else if constexpr (fn == 1u || fn == 6u)
90
            return &self::template f1<Auto, Auto, Auto>;
91
        else if constexpr (fn == 2u || fn == 5u)
92
            return &self::template f2<Auto, Auto, Auto>;
93
        else if constexpr (fn == 3u || fn == 4u)
94
            return &self::template f3<Auto, Auto, Auto>;
95
    }
96
    else
97
    {
98
        if constexpr (fn == 0u || fn == 9u)
99
            return &self::template f0<Auto, Auto, Auto>;
100
        else if constexpr (fn == 1u || fn == 8u)
101
            return &self::template f1<Auto, Auto, Auto>;
102
        else if constexpr (fn == 2u || fn == 7u)
103
            return &self::template f2<Auto, Auto, Auto>;
104
        else if constexpr (fn == 3u || fn == 6u)
105
            return &self::template f3<Auto, Auto, Auto>;
106
        else if constexpr (fn == 4u || fn == 5u)
107
            return &self::template f4<Auto, Auto, Auto>;
108
    }
109
}
110

111
TEMPLATE
112
template<size_t Round>
113
INLINE constexpr auto CLASS::
15,673✔
114
round(auto& a, auto b, auto c, auto d, auto x) NOEXCEPT
115
{
116
    constexpr auto s = K::rot[Round];
117
    constexpr auto k = K::get[Round / K::columns];
118
    constexpr auto fn = functor<Round, decltype(a)>();
119

120
    a = /*b =*/ f::rol<s>(f::addc<k>(f::add(f::add(a, fn(b, c, d)), x)));
15,673✔
121
}
122

123
TEMPLATE
124
template<size_t Round>
125
INLINE constexpr auto CLASS::
2,532,480✔
126
round(auto& a, auto b, auto& c, auto d, auto e, auto x) NOEXCEPT
127
{
128
    constexpr auto s = K::rot[Round];
129
    constexpr auto k = K::get[Round / K::columns];
130
    constexpr auto fn = functor<Round, decltype(a)>();
131

132
    a = /*b =*/ f::add(f::rol<s>(f::addc<k>(f::add(f::add(a, fn(b, c, d)), x))), e);
2,532,480✔
133
    c = /*d =*/ f::rol<10>(c);
2,532,480✔
134
}
135

136
TEMPLATE
137
template<size_t Round>
138
INLINE constexpr void CLASS::
2,548,153✔
139
round(auto& state, const auto& words) NOEXCEPT
140
{
141
    if constexpr (RMD::strength == 128)
142
    {
143
        round<Round>(
15,673✔
144
            state[(RMD::rounds + 0 - Round) % RMD::state_words], // b->a
15,673✔
145
            state[(RMD::rounds + 1 - Round) % RMD::state_words],
15,673✔
146
            state[(RMD::rounds + 2 - Round) % RMD::state_words],
15,673✔
147
            state[(RMD::rounds + 3 - Round) % RMD::state_words],
15,673✔
148
            words[K::word[Round]]);
15,673✔
149
    }
150
    else
151
    {
152
        round<Round>(
2,279,232✔
153
            state[(RMD::rounds + 0 - Round) % RMD::state_words], // b->a
31,656✔
154
            state[(RMD::rounds + 1 - Round) % RMD::state_words],
31,656✔
155
            state[(RMD::rounds + 2 - Round) % RMD::state_words], // d->c
31,656✔
156
            state[(RMD::rounds + 3 - Round) % RMD::state_words],
31,656✔
157
            state[(RMD::rounds + 4 - Round) % RMD::state_words],
31,656✔
158
            words[K::word[Round]]);
237,420✔
159
    }
160
}
161

162
TEMPLATE
163
constexpr void CLASS::
31,501✔
164
compress(state_t& state, const words_t& words) NOEXCEPT
165
{
166
    constexpr auto offset = to_half(RMD::rounds);
167

168
    state_t left{ state };
31,501✔
169
    state_t right{ state };
31,501✔
170

171
    // RMD160:f0/f4, RMD128:f0/f3
172
    round< 0>(left, words); round< 0 + offset>(right, words);
173
    round< 1>(left, words); round< 1 + offset>(right, words);
174
    round< 2>(left, words); round< 2 + offset>(right, words);
175
    round< 3>(left, words); round< 3 + offset>(right, words);
176
    round< 4>(left, words); round< 4 + offset>(right, words);
177
    round< 5>(left, words); round< 5 + offset>(right, words);
178
    round< 6>(left, words); round< 6 + offset>(right, words);
179
    round< 7>(left, words); round< 7 + offset>(right, words);
180
    round< 8>(left, words); round< 8 + offset>(right, words);
181
    round< 9>(left, words); round< 9 + offset>(right, words);
182
    round<10>(left, words); round<10 + offset>(right, words);
183
    round<11>(left, words); round<11 + offset>(right, words);
184
    round<12>(left, words); round<12 + offset>(right, words);
185
    round<13>(left, words); round<13 + offset>(right, words);
186
    round<14>(left, words); round<14 + offset>(right, words);
187
    round<15>(left, words); round<15 + offset>(right, words);
188

189
    // RMD160:f1/f3, RMD128:f1/f2
190
    round<16>(left, words); round<16 + offset>(right, words);
191
    round<17>(left, words); round<17 + offset>(right, words);
192
    round<18>(left, words); round<18 + offset>(right, words);
193
    round<19>(left, words); round<19 + offset>(right, words);
194
    round<20>(left, words); round<20 + offset>(right, words);
195
    round<21>(left, words); round<21 + offset>(right, words);
196
    round<22>(left, words); round<22 + offset>(right, words);
197
    round<23>(left, words); round<23 + offset>(right, words);
198
    round<24>(left, words); round<24 + offset>(right, words);
199
    round<25>(left, words); round<25 + offset>(right, words);
200
    round<26>(left, words); round<26 + offset>(right, words);
201
    round<27>(left, words); round<27 + offset>(right, words);
202
    round<28>(left, words); round<28 + offset>(right, words);
203
    round<29>(left, words); round<29 + offset>(right, words);
204
    round<30>(left, words); round<30 + offset>(right, words);
205
    round<31>(left, words); round<31 + offset>(right, words);
206

207
    // RMD160:f2/f2, RMD128:f2/f1
208
    round<32>(left, words); round<32 + offset>(right, words);
209
    round<33>(left, words); round<33 + offset>(right, words);
210
    round<34>(left, words); round<34 + offset>(right, words);
211
    round<35>(left, words); round<35 + offset>(right, words);
212
    round<36>(left, words); round<36 + offset>(right, words);
213
    round<37>(left, words); round<37 + offset>(right, words);
214
    round<38>(left, words); round<38 + offset>(right, words);
215
    round<39>(left, words); round<39 + offset>(right, words);
216
    round<40>(left, words); round<40 + offset>(right, words);
217
    round<41>(left, words); round<41 + offset>(right, words);
218
    round<42>(left, words); round<42 + offset>(right, words);
219
    round<43>(left, words); round<43 + offset>(right, words);
220
    round<44>(left, words); round<44 + offset>(right, words);
221
    round<45>(left, words); round<45 + offset>(right, words);
222
    round<46>(left, words); round<46 + offset>(right, words);
223
    round<47>(left, words); round<47 + offset>(right, words);
224

225
    // RMD160:f3/f1, RMD128:f3/f0
226
    round<48>(left, words); round<48 + offset>(right, words);
227
    round<49>(left, words); round<49 + offset>(right, words);
228
    round<50>(left, words); round<50 + offset>(right, words);
229
    round<51>(left, words); round<51 + offset>(right, words);
230
    round<52>(left, words); round<52 + offset>(right, words);
231
    round<53>(left, words); round<53 + offset>(right, words);
232
    round<54>(left, words); round<54 + offset>(right, words);
233
    round<55>(left, words); round<55 + offset>(right, words);
234
    round<56>(left, words); round<56 + offset>(right, words);
235
    round<57>(left, words); round<57 + offset>(right, words);
236
    round<58>(left, words); round<58 + offset>(right, words);
237
    round<59>(left, words); round<59 + offset>(right, words);
238
    round<60>(left, words); round<60 + offset>(right, words);
239
    round<61>(left, words); round<61 + offset>(right, words);
240
    round<62>(left, words); round<62 + offset>(right, words);
241
    round<63>(left, words); round<63 + offset>(right, words);
242

243
    // RMD160:f4/f0
244
    if constexpr (RMD::strength == 160)
245
    {
246
        round<64>(left, words); round<64 + offset>(right, words);
247
        round<65>(left, words); round<65 + offset>(right, words);
248
        round<66>(left, words); round<66 + offset>(right, words);
249
        round<67>(left, words); round<67 + offset>(right, words);
250
        round<68>(left, words); round<68 + offset>(right, words);
251
        round<69>(left, words); round<69 + offset>(right, words);
252
        round<70>(left, words); round<70 + offset>(right, words);
253
        round<71>(left, words); round<71 + offset>(right, words);
254
        round<72>(left, words); round<72 + offset>(right, words);
255
        round<73>(left, words); round<73 + offset>(right, words);
256
        round<74>(left, words); round<74 + offset>(right, words);
257
        round<75>(left, words); round<75 + offset>(right, words);
258
        round<76>(left, words); round<76 + offset>(right, words);
259
        round<77>(left, words); round<77 + offset>(right, words);
260
        round<78>(left, words); round<78 + offset>(right, words);
261
        round<79>(left, words); round<79 + offset>(right, words);
262
    }
263

264
    summarize(state, left, right);
265
}
31,501✔
266

267
TEMPLATE
268
INLINE constexpr void CLASS::
31,501✔
269
summarize(state_t& state, const state_t& batch1,
270
    const state_t& batch2) NOEXCEPT
271
{
272
    if constexpr (RMD::strength == 128)
273
    {
274
        const auto state_0_ = state[0];
15,673✔
275
        state[0] = f::add(f::add(state[1], batch1[2]), batch2[3]);
15,673✔
276
        state[1] = f::add(f::add(state[2], batch1[3]), batch2[0]);
15,673✔
277
        state[2] = f::add(f::add(state[3], batch1[0]), batch2[1]);
15,673✔
278
        state[3] = f::add(f::add(state_0_, batch1[1]), batch2[2]);
15,673✔
279
    }
280
    else
281
    {
282
        const auto state_0_ = state[0];
15,828✔
283
        state[0] = f::add(f::add(state[1], batch1[2]), batch2[3]);
15,828✔
284
        state[1] = f::add(f::add(state[2], batch1[3]), batch2[4]);
15,828✔
285
        state[2] = f::add(f::add(state[3], batch1[4]), batch2[0]);
15,828✔
286
        state[3] = f::add(f::add(state[4], batch1[0]), batch2[1]);
15,828✔
287
        state[4] = f::add(f::add(state_0_, batch1[1]), batch2[2]);
15,828✔
288
    }
289
}
290

291
// Parsing
292
// ---------------------------------------------------------------------------
293
// little-endian I/O is conventional for RMD.
294

295
TEMPLATE
296
INLINE constexpr void CLASS::
31,322✔
297
input(words_t& words, const block_t& block) NOEXCEPT
298
{
299
    if (std::is_constant_evaluated())
300
    {
301
        constexpr auto size = RMD::word_bytes;
302
        from_little< 0 * size>(words.at( 0), block);
303
        from_little< 1 * size>(words.at( 1), block);
304
        from_little< 2 * size>(words.at( 2), block);
305
        from_little< 3 * size>(words.at( 3), block);
306
        from_little< 4 * size>(words.at( 4), block);
307
        from_little< 5 * size>(words.at( 5), block);
308
        from_little< 6 * size>(words.at( 6), block);
309
        from_little< 7 * size>(words.at( 7), block);
310
        from_little< 8 * size>(words.at( 8), block);
311
        from_little< 9 * size>(words.at( 9), block);
312
        from_little<10 * size>(words.at(10), block);
313
        from_little<11 * size>(words.at(11), block);
314
        from_little<12 * size>(words.at(12), block);
315
        from_little<13 * size>(words.at(13), block);
316
        from_little<14 * size>(words.at(14), block);
317
        from_little<15 * size>(words.at(15), block);
318
    }
319
    else if constexpr (bc::is_big_endian)
320
    {
321
        const auto& in = array_cast<word_t>(block);
322
        words[0] = native_from_little_end(in[0]);
323
        words[1] = native_from_little_end(in[1]);
324
        words[2] = native_from_little_end(in[2]);
325
        words[3] = native_from_little_end(in[3]);
326
        words[4] = native_from_little_end(in[4]);
327
        words[5] = native_from_little_end(in[5]);
328
        words[6] = native_from_little_end(in[6]);
329
        words[7] = native_from_little_end(in[7]);
330
        words[8] = native_from_little_end(in[8]);
331
        words[9] = native_from_little_end(in[9]);
332
        words[10] = native_from_little_end(in[10]);
333
        words[11] = native_from_little_end(in[11]);
334
        words[12] = native_from_little_end(in[12]);
335
        words[13] = native_from_little_end(in[13]);
336
        words[14] = native_from_little_end(in[14]);
337
        words[15] = native_from_little_end(in[15]);
338
    }
339
    else
340
    {
341
        words = array_cast<word_t>(block);
31,372✔
342
    }
343
}
344

345
TEMPLATE
346
INLINE constexpr void CLASS::
155✔
347
input(words_t& words, const half_t& half) NOEXCEPT
348
{
349
    if (std::is_constant_evaluated())
350
    {
351
        constexpr auto size = RMD::word_bytes;
352
        from_little<0 * size>(words.at(0), half);
353
        from_little<1 * size>(words.at(1), half);
354
        from_little<2 * size>(words.at(2), half);
355
        from_little<3 * size>(words.at(3), half);
356
        from_little<4 * size>(words.at(4), half);
357
        from_little<5 * size>(words.at(5), half);
358
        from_little<6 * size>(words.at(6), half);
359
        from_little<7 * size>(words.at(7), half);
360
    }
361
    else if constexpr (bc::is_big_endian)
362
    {
363
        const auto& in = array_cast<word_t>(half);
364
        words[0] = native_from_little_end(in[0]);
365
        words[1] = native_from_little_end(in[1]);
366
        words[2] = native_from_little_end(in[2]);
367
        words[3] = native_from_little_end(in[3]);
368
        words[4] = native_from_little_end(in[4]);
369
        words[5] = native_from_little_end(in[5]);
370
        words[6] = native_from_little_end(in[6]);
371
        words[7] = native_from_little_end(in[7]);
372
    }
373
    else
374
    {
375
        array_cast<word_t, array_count<chunk_t>>(words) =
161✔
376
            array_cast<word_t>(half);
377
    }
378
}
379

380
TEMPLATE
381
INLINE constexpr typename CLASS::digest_t CLASS::
209✔
382
output(const state_t& state) NOEXCEPT
383
{
384
    digest_t digest{};
×
385

386
    if (std::is_constant_evaluated())
387
    {
388
        constexpr auto size = RMD::word_bytes;
389
        to_little<0 * size>(digest, state.at(0));
390
        to_little<1 * size>(digest, state.at(1));
391
        to_little<2 * size>(digest, state.at(2));
392
        to_little<3 * size>(digest, state.at(3));
393

394
        if constexpr (RMD::strength == 160)
395
        {
396
            to_little<4 * size>(digest, state.at(4));
397
        }
398
    }
399
    else if constexpr (bc::is_big_endian)
400
    {
401
        auto& out = array_cast<word_t>(digest);
402
        out[0] = native_to_little_end(state[0]);
403
        out[1] = native_to_little_end(state[1]);
404
        out[2] = native_to_little_end(state[2]);
405
        out[3] = native_to_little_end(state[3]);
406

407
        if constexpr (RMD::strength == 160)
408
        {
409
            out[4] = native_to_little_end(state[4]);
410
        }
411
    }
412
    else
413
    {
414
        array_cast<word_t>(digest) = state;
209✔
415
    }
416

417
    return digest;
29✔
418
}
419

420
// Padding
421
// ---------------------------------------------------------------------------
422

423
TEMPLATE
424
CONSTEVAL typename CLASS::words_t CLASS::
425
block_pad() NOEXCEPT
426
{
427
    // See comments in accumulator regarding padding endianness.
428
    constexpr auto bytes = possible_narrow_cast<word_t>(array_count<block_t>);
429
    constexpr auto hi = sub1(array_count<words_t>);
430
    constexpr auto lo = sub1(hi);
431

432
    words_t words{};
433
    words.front() = bit_hi<byte_t>;
434
    words[lo] = to_bits(bytes);
435
    return words;
436
}
437

438
TEMPLATE
439
CONSTEVAL typename CLASS::chunk_t CLASS::
440
chunk_pad() NOEXCEPT
441
{
442
    // See comments in accumulator regarding padding endianness.
443
    constexpr auto bytes = possible_narrow_cast<word_t>(array_count<half_t>);
444
    constexpr auto hi = sub1(array_count<chunk_t>);
445
    constexpr auto lo = sub1(hi);
446

447
    chunk_t words{};
448
    words.front() = bit_hi<byte_t>;
449
    words[lo] = to_bits(bytes);
450
    return words;
451
}
452

453
TEMPLATE
454
CONSTEVAL typename CLASS::pad_t CLASS::
455
stream_pad() NOEXCEPT
456
{
457
    // See comments in accumulator regarding padding endianness.
458
    pad_t words{};
459
    words.front() = bit_hi<byte_t>;
460
    return words;
461
}
462

463
TEMPLATE
464
constexpr void CLASS::
12✔
465
pad_one(words_t& words) NOEXCEPT
466
{
467
    // Pad a single whole block with pre-prepared buffer.
468
    constexpr auto pad = block_pad();
12✔
469
    words = pad;
12✔
470
}
12✔
471

472
TEMPLATE
473
constexpr void CLASS::
155✔
474
pad_half(words_t& words) NOEXCEPT
475
{
476
    // Pad a half block.
477
    constexpr auto pad = chunk_pad();
155✔
478

479
    if (std::is_constant_evaluated())
480
    {
481
        words.at(8)  = pad.at(0);
482
        words.at(9)  = pad.at(1);
483
        words.at(10) = pad.at(2);
484
        words.at(11) = pad.at(3);
485
        words.at(12) = pad.at(4);
486
        words.at(13) = pad.at(5);
487
        words.at(14) = pad.at(6);
488
        words.at(15) = pad.at(7);
489
    }
490
    else
491
    {
492
        constexpr auto size = array_count<chunk_t>;
493
        array_cast<word_t, size, size>(words) = pad;
155✔
494
    }
495
}
155✔
496

497
TEMPLATE
498
constexpr void CLASS::
12✔
499
pad_n(words_t& words, count_t blocks) NOEXCEPT
500
{
501
    // Pad any number of whole blocks.
502
    constexpr auto pad = stream_pad();
12✔
503
    const auto bits = to_bits(blocks * array_count<block_t>);
504

505
    if (std::is_constant_evaluated())
506
    {
507
        words.at(0)  = pad.at(0);
508
        words.at(1)  = pad.at(1);
509
        words.at(2)  = pad.at(2);
510
        words.at(3)  = pad.at(3);
511
        words.at(4)  = pad.at(4);
512
        words.at(5)  = pad.at(5);
513
        words.at(6)  = pad.at(6);
514
        words.at(7)  = pad.at(7);
515
        words.at(8)  = pad.at(8);
516
        words.at(9)  = pad.at(9);
517
        words.at(10) = pad.at(10);
518
        words.at(11) = pad.at(11);
519
        words.at(12) = pad.at(12);
520
        words.at(13) = pad.at(13);
521
        words.at(14) = lo_word<word_t>(bits);
522
        words.at(15) = hi_word<word_t>(bits);
523
    }
524
    else
525
    {
526
        array_cast<word_t, array_count<pad_t>>(words) = pad;
12✔
527

528
        // Split count into hi/low words and assign end of padded buffer (LE).
529
        words[14] = lo_word<word_t>(bits);
12✔
530
        words[15] = hi_word<word_t>(bits);
12✔
531
    }
532
}
12✔
533

534
// Finalized hash functions.
535
// ---------------------------------------------------------------------------
536

537
TEMPLATE
538
typename CLASS::digest_t CLASS::
6✔
539
hash(iblocks_t&& blocks) NOEXCEPT
540
{
541
    words_t words{};
6✔
542
    auto state = H::get;
6✔
543

544
    for (auto& block: blocks)
31,264✔
545
    {
546
        input(words, block);
547
        compress(state, words);
31,258✔
548
    }
549

550
    pad_n(words, blocks.size());
6✔
551
    compress(state, words);
6✔
552
    return output(state);
6✔
553
}
554

555
TEMPLATE
556
template <size_t Size>
557
constexpr typename CLASS::digest_t CLASS::
4✔
558
hash(const ablocks_t<Size>& blocks) NOEXCEPT
559
{
560
    words_t words{};
4✔
561
    auto state = H::get;
4✔
562

563
    for (auto& block: blocks)
12✔
564
    {
565
        input(words, block);
566
        compress(state, words);
8✔
567
    }
568

569
    pad_n(words, blocks.size());
4✔
570
    compress(state, words);
4✔
571
    return output(state);
4✔
572
}
573

574
TEMPLATE
575
constexpr typename CLASS::digest_t CLASS::
12✔
576
hash(const block_t& block) NOEXCEPT
577
{
578
    words_t words{};
579
    auto state = H::get;
12✔
580
    input(words, block);
581
    compress(state, words);
12✔
582
    pad_one(words);
12✔
583
    compress(state, words);
12✔
584
    return output(state);
12✔
585
}
586

587
TEMPLATE
588
constexpr typename CLASS::digest_t CLASS::
155✔
589
hash(const half_t& half) NOEXCEPT
590
{
591
    words_t words{};
155✔
592
    auto state = H::get;
155✔
593
    input(words, half);
594
    pad_half(words);
155✔
595
    compress(state, words);
155✔
596
    return output(state);
155✔
597
}
598

599
// Streaming hash functions and finalizers.
600
// ---------------------------------------------------------------------------
601

602
TEMPLATE
603
void CLASS::
×
604
accumulate(state_t& state, iblocks_t&& blocks) NOEXCEPT
605
{
606
    words_t words{};
607
    for (auto& block: blocks)
×
608
    {
609
        input(words, block);
610
        compress(state, words);
×
611
    }
612
}
×
613

614
TEMPLATE
615
constexpr void CLASS::
44✔
616
accumulate(state_t& state, const block_t& block) NOEXCEPT
617
{
618
    words_t words{};
619
    input(words, block);
620
    compress(state, words);
44✔
621
}
44✔
622

623
TEMPLATE
624
constexpr typename CLASS::digest_t CLASS::
2✔
625
finalize(state_t& state, size_t blocks) NOEXCEPT
626
{
627
    words_t words{};
2✔
628
    pad_n(words, blocks);
2✔
629
    compress(state, words);
2✔
630
    return output(state);
2✔
631
}
632

633
TEMPLATE
634
constexpr typename CLASS::digest_t CLASS::
19✔
635
normalize(const state_t& state) NOEXCEPT
636
{
637
    return output(state);
11✔
638
}
639

640
BC_POP_WARNING()
641
BC_POP_WARNING()
642
BC_POP_WARNING()
643
BC_POP_WARNING()
644

645
} // namespace rmd
646
} // namespace system
647
} // namespace libbitcoin
648

649
#endif
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