Coverage Report

Created: 2024-10-21 15:10

/root/bitcoin/src/crypto/muhash.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2017-2021 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_CRYPTO_MUHASH_H
6
#define BITCOIN_CRYPTO_MUHASH_H
7
8
#include <serialize.h>
9
#include <uint256.h>
10
11
#include <stdint.h>
12
13
class Num3072
14
{
15
private:
16
    void FullReduce();
17
    bool IsOverflow() const;
18
    Num3072 GetInverse() const;
19
20
public:
21
    static constexpr size_t BYTE_SIZE = 384;
22
23
#ifdef __SIZEOF_INT128__
24
    typedef unsigned __int128 double_limb_t;
25
    typedef uint64_t limb_t;
26
    static constexpr int LIMBS = 48;
27
    static constexpr int LIMB_SIZE = 64;
28
#else
29
    typedef uint64_t double_limb_t;
30
    typedef uint32_t limb_t;
31
    static constexpr int LIMBS = 96;
32
    static constexpr int LIMB_SIZE = 32;
33
#endif
34
    limb_t limbs[LIMBS];
35
36
    // Sanity check for Num3072 constants
37
    static_assert(LIMB_SIZE * LIMBS == 3072, "Num3072 isn't 3072 bits");
38
    static_assert(sizeof(double_limb_t) == sizeof(limb_t) * 2, "bad size for double_limb_t");
39
    static_assert(sizeof(limb_t) * 8 == LIMB_SIZE, "LIMB_SIZE is incorrect");
40
41
    // Hard coded values in MuHash3072 constructor and Finalize
42
    static_assert(sizeof(limb_t) == 4 || sizeof(limb_t) == 8, "bad size for limb_t");
43
44
    void Multiply(const Num3072& a);
45
    void Divide(const Num3072& a);
46
    void SetToOne();
47
    void Square();
48
    void ToBytes(unsigned char (&out)[BYTE_SIZE]);
49
50
0
    Num3072() { this->SetToOne(); };
51
    Num3072(const unsigned char (&data)[BYTE_SIZE]);
52
53
    SERIALIZE_METHODS(Num3072, obj)
54
0
    {
55
0
        for (auto& limb : obj.limbs) {
56
0
            READWRITE(limb);
57
0
        }
58
0
    }
Unexecuted instantiation: _ZN7Num307216SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_
Unexecuted instantiation: _ZN7Num307216SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_
59
};
60
61
/** A class representing MuHash sets
62
 *
63
 * MuHash is a hashing algorithm that supports adding set elements in any
64
 * order but also deleting in any order. As a result, it can maintain a
65
 * running sum for a set of data as a whole, and add/remove when data
66
 * is added to or removed from it. A downside of MuHash is that computing
67
 * an inverse is relatively expensive. This is solved by representing
68
 * the running value as a fraction, and multiplying added elements into
69
 * the numerator and removed elements into the denominator. Only when the
70
 * final hash is desired, a single modular inverse and multiplication is
71
 * needed to combine the two. The combination is also run on serialization
72
 * to allow for space-efficient storage on disk.
73
 *
74
 * As the update operations are also associative, H(a)+H(b)+H(c)+H(d) can
75
 * in fact be computed as (H(a)+H(b)) + (H(c)+H(d)). This implies that
76
 * all of this is perfectly parallellizable: each thread can process an
77
 * arbitrary subset of the update operations, allowing them to be
78
 * efficiently combined later.
79
 *
80
 * MuHash does not support checking if an element is already part of the
81
 * set. That is why this class does not enforce the use of a set as the
82
 * data it represents because there is no efficient way to do so.
83
 * It is possible to add elements more than once and also to remove
84
 * elements that have not been added before. However, this implementation
85
 * is intended to represent a set of elements.
86
 *
87
 * See also https://cseweb.ucsd.edu/~mihir/papers/inchash.pdf and
88
 * https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-May/014337.html.
89
 */
90
class MuHash3072
91
{
92
private:
93
    Num3072 m_numerator;
94
    Num3072 m_denominator;
95
96
    Num3072 ToNum3072(Span<const unsigned char> in);
97
98
public:
99
    /* The empty set. */
100
0
    MuHash3072() noexcept = default;
101
102
    /* A singleton with variable sized data in it. */
103
    explicit MuHash3072(Span<const unsigned char> in) noexcept;
104
105
    /* Insert a single piece of data into the set. */
106
    MuHash3072& Insert(Span<const unsigned char> in) noexcept;
107
108
    /* Remove a single piece of data from the set. */
109
    MuHash3072& Remove(Span<const unsigned char> in) noexcept;
110
111
    /* Multiply (resulting in a hash for the union of the sets) */
112
    MuHash3072& operator*=(const MuHash3072& mul) noexcept;
113
114
    /* Divide (resulting in a hash for the difference of the sets) */
115
    MuHash3072& operator/=(const MuHash3072& div) noexcept;
116
117
    /* Finalize into a 32-byte hash. Does not change this object's value. */
118
    void Finalize(uint256& out) noexcept;
119
120
    SERIALIZE_METHODS(MuHash3072, obj)
121
0
    {
122
0
        READWRITE(obj.m_numerator);
123
0
        READWRITE(obj.m_denominator);
124
0
    }
Unexecuted instantiation: _ZN10MuHash307216SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_
Unexecuted instantiation: _ZN10MuHash307216SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_
125
};
126
127
#endif // BITCOIN_CRYPTO_MUHASH_H