Coverage Report

Created: 2026-04-29 19:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/util/hasher.h
Line
Count
Source
1
// Copyright (c) 2019-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#ifndef BITCOIN_UTIL_HASHER_H
6
#define BITCOIN_UTIL_HASHER_H
7
8
#include <crypto/common.h>
9
#include <crypto/siphash.h>
10
#include <primitives/transaction.h>
11
#include <uint256.h>
12
13
#include <cstdint>
14
#include <cstring>
15
#include <span>
16
17
class SaltedUint256Hasher
18
{
19
    const PresaltedSipHasher m_hasher;
20
21
public:
22
    SaltedUint256Hasher();
23
24
    size_t operator()(const uint256& hash) const
25
269
    {
26
269
        return m_hasher(hash);
27
269
    }
28
};
29
30
class SaltedTxidHasher
31
{
32
    const PresaltedSipHasher m_hasher;
33
34
public:
35
    SaltedTxidHasher();
36
37
    size_t operator()(const Txid& txid) const
38
33.2M
    {
39
33.2M
        return m_hasher(txid.ToUint256());
40
33.2M
    }
41
};
42
43
class SaltedWtxidHasher
44
{
45
    const PresaltedSipHasher m_hasher;
46
47
public:
48
    SaltedWtxidHasher();
49
50
    size_t operator()(const Wtxid& wtxid) const
51
21.6M
    {
52
21.6M
        return m_hasher(wtxid.ToUint256());
53
21.6M
    }
54
};
55
56
class SaltedOutpointHasher
57
{
58
    const PresaltedSipHasher m_hasher;
59
60
public:
61
    SaltedOutpointHasher(bool deterministic = false);
62
63
    /**
64
     * Having the hash noexcept allows libstdc++'s unordered_map to recalculate
65
     * the hash during rehash, so it does not have to cache the value. This
66
     * reduces node's memory by sizeof(size_t). The required recalculation has
67
     * a slight performance penalty (around 1.6%), but this is compensated by
68
     * memory savings of about 9% which allow for a larger dbcache setting.
69
     *
70
     * @see https://gcc.gnu.org/onlinedocs/gcc-13.2.0/libstdc++/manual/manual/unordered_associative.html
71
     */
72
    size_t operator()(const COutPoint& id) const noexcept
73
311M
    {
74
311M
        return m_hasher(id.hash.ToUint256(), id.n);
75
311M
    }
76
};
77
78
/**
79
 * We're hashing a nonce into the entries themselves, so we don't need extra
80
 * blinding in the set hash computation.
81
 *
82
 * This may exhibit platform endian dependent behavior but because these are
83
 * nonced hashes (random) and this state is only ever used locally it is safe.
84
 * All that matters is local consistency.
85
 */
86
class SignatureCacheHasher
87
{
88
public:
89
    template <uint8_t hash_select>
90
    uint32_t operator()(const uint256& key) const
91
34.6M
    {
92
34.6M
        static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
93
34.6M
        uint32_t u;
94
34.6M
        std::memcpy(&u, key.begin()+4*hash_select, 4);
95
34.6M
        return u;
96
34.6M
    }
unsigned int SignatureCacheHasher::operator()<(unsigned char)0>(uint256 const&) const
Line
Count
Source
91
4.33M
    {
92
4.33M
        static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
93
4.33M
        uint32_t u;
94
4.33M
        std::memcpy(&u, key.begin()+4*hash_select, 4);
95
4.33M
        return u;
96
4.33M
    }
unsigned int SignatureCacheHasher::operator()<(unsigned char)1>(uint256 const&) const
Line
Count
Source
91
4.33M
    {
92
4.33M
        static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
93
4.33M
        uint32_t u;
94
4.33M
        std::memcpy(&u, key.begin()+4*hash_select, 4);
95
4.33M
        return u;
96
4.33M
    }
unsigned int SignatureCacheHasher::operator()<(unsigned char)2>(uint256 const&) const
Line
Count
Source
91
4.33M
    {
92
4.33M
        static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
93
4.33M
        uint32_t u;
94
4.33M
        std::memcpy(&u, key.begin()+4*hash_select, 4);
95
4.33M
        return u;
96
4.33M
    }
unsigned int SignatureCacheHasher::operator()<(unsigned char)3>(uint256 const&) const
Line
Count
Source
91
4.33M
    {
92
4.33M
        static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
93
4.33M
        uint32_t u;
94
4.33M
        std::memcpy(&u, key.begin()+4*hash_select, 4);
95
4.33M
        return u;
96
4.33M
    }
unsigned int SignatureCacheHasher::operator()<(unsigned char)4>(uint256 const&) const
Line
Count
Source
91
4.33M
    {
92
4.33M
        static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
93
4.33M
        uint32_t u;
94
4.33M
        std::memcpy(&u, key.begin()+4*hash_select, 4);
95
4.33M
        return u;
96
4.33M
    }
unsigned int SignatureCacheHasher::operator()<(unsigned char)5>(uint256 const&) const
Line
Count
Source
91
4.33M
    {
92
4.33M
        static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
93
4.33M
        uint32_t u;
94
4.33M
        std::memcpy(&u, key.begin()+4*hash_select, 4);
95
4.33M
        return u;
96
4.33M
    }
unsigned int SignatureCacheHasher::operator()<(unsigned char)6>(uint256 const&) const
Line
Count
Source
91
4.33M
    {
92
4.33M
        static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
93
4.33M
        uint32_t u;
94
4.33M
        std::memcpy(&u, key.begin()+4*hash_select, 4);
95
4.33M
        return u;
96
4.33M
    }
unsigned int SignatureCacheHasher::operator()<(unsigned char)7>(uint256 const&) const
Line
Count
Source
91
4.33M
    {
92
4.33M
        static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
93
4.33M
        uint32_t u;
94
4.33M
        std::memcpy(&u, key.begin()+4*hash_select, 4);
95
4.33M
        return u;
96
4.33M
    }
97
};
98
99
struct BlockHasher
100
{
101
    // this used to call `GetCheapHash()` in uint256, which was later moved; the
102
    // cheap hash function simply calls ReadLE64() however, so the end result is
103
    // identical
104
1.47M
    size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); }
105
};
106
107
class SaltedSipHasher
108
{
109
private:
110
    /** Salt */
111
    const uint64_t m_k0, m_k1;
112
113
public:
114
    SaltedSipHasher();
115
116
    size_t operator()(const std::span<const unsigned char>& script) const;
117
};
118
119
#endif // BITCOIN_UTIL_HASHER_H