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

libbitcoin / libbitcoin-system / 24331809217

13 Apr 2026 07:45AM UTC coverage: 75.852% (-5.8%) from 81.681%
24331809217

push

github

web-flow
Merge pull request #1811 from pmienk/installer-rewrite

Rewritten build/install scripts.

16733 of 22060 relevant lines covered (75.85%)

2499729.97 hits per line

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

94.64
/include/bitcoin/system/impl/hash/rmd/algorithm.ipp
1
/**
2
 * Copyright (c) 2011-2026 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

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

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

34
// Functions.
35
// ----------------------------------------------------------------------------
36

37
TEMPLATE
38
INLINE constexpr auto CLASS::
1,008,192✔
39
f0(auto x, auto y, auto z) NOEXCEPT
40
{
41
    return f::xor_(f::xor_(x, y), z);
506,656✔
42
}
43

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

51
TEMPLATE
52
INLINE constexpr auto CLASS::
1,008,192✔
53
f2(auto x, auto y, auto z) NOEXCEPT
54
{
55
    return f::xor_(f::or_(x, f::not_(y)), z);
506,656✔
56
}
57

58
TEMPLATE
59
INLINE constexpr auto CLASS::
1,008,192✔
60
f3(auto x, auto y, auto z) NOEXCEPT
61
{
62
    return f::or_(f::and_(x, z), f::and_(y, f::not_(z)));
506,656✔
63
}
64

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

72
// Rounds
73
// ---------------------------------------------------------------------------
74

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

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

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

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

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

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

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

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

167
    state_t left{ state };
31,506✔
168
    state_t right{ state };
31,506✔
169

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

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

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

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

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

263
    summarize(state, left, right);
264
}
31,506✔
265

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

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

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

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

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

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

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

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

416
    return digest;
29✔
417
}
418

419
// Padding
420
// ---------------------------------------------------------------------------
421

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

632
TEMPLATE
633
constexpr typename CLASS::digest_t CLASS::
30✔
634
normalize(const state_t& state) NOEXCEPT
635
{
636
    // Caller must pad state first.
637
    return output(state);
×
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