Bitcoin Core 30.99.0
P2P Digital Currency
siphash.cpp
Go to the documentation of this file.
1// Copyright (c) 2016-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#include <crypto/siphash.h>
6
7#include <uint256.h>
8
9#include <bit>
10#include <cassert>
11#include <span>
12
13#define SIPROUND do { \
14 v0 += v1; v1 = std::rotl(v1, 13); v1 ^= v0; \
15 v0 = std::rotl(v0, 32); \
16 v2 += v3; v3 = std::rotl(v3, 16); v3 ^= v2; \
17 v0 += v3; v3 = std::rotl(v3, 21); v3 ^= v0; \
18 v2 += v1; v1 = std::rotl(v1, 17); v1 ^= v2; \
19 v2 = std::rotl(v2, 32); \
20} while (0)
21
22CSipHasher::CSipHasher(uint64_t k0, uint64_t k1) : m_state{k0, k1} {}
23
25{
26 uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
27
28 assert(m_count % 8 == 0);
29
30 v3 ^= data;
33 v0 ^= data;
34
35 m_state.v[0] = v0;
36 m_state.v[1] = v1;
37 m_state.v[2] = v2;
38 m_state.v[3] = v3;
39
40 m_count += 8;
41 return *this;
42}
43
44CSipHasher& CSipHasher::Write(std::span<const unsigned char> data)
45{
46 uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
47 uint64_t t = m_tmp;
48 uint8_t c = m_count;
49
50 while (data.size() > 0) {
51 t |= uint64_t{data.front()} << (8 * (c % 8));
52 c++;
53 if ((c & 7) == 0) {
54 v3 ^= t;
57 v0 ^= t;
58 t = 0;
59 }
60 data = data.subspan(1);
61 }
62
63 m_state.v[0] = v0;
64 m_state.v[1] = v1;
65 m_state.v[2] = v2;
66 m_state.v[3] = v3;
67 m_count = c;
68 m_tmp = t;
69
70 return *this;
71}
72
73uint64_t CSipHasher::Finalize() const
74{
75 uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
76
77 uint64_t t = m_tmp | (((uint64_t)m_count) << 56);
78
79 v3 ^= t;
82 v0 ^= t;
83 v2 ^= 0xFF;
88 return v0 ^ v1 ^ v2 ^ v3;
89}
90
91uint64_t PresaltedSipHasher::operator()(const uint256& val) const noexcept
92{
93 uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
94 uint64_t d = val.GetUint64(0);
95 v3 ^= d;
96
99 v0 ^= d;
100 d = val.GetUint64(1);
101 v3 ^= d;
102 SIPROUND;
103 SIPROUND;
104 v0 ^= d;
105 d = val.GetUint64(2);
106 v3 ^= d;
107 SIPROUND;
108 SIPROUND;
109 v0 ^= d;
110 d = val.GetUint64(3);
111 v3 ^= d;
112 SIPROUND;
113 SIPROUND;
114 v0 ^= d;
115 v3 ^= (uint64_t{4}) << 59;
116 SIPROUND;
117 SIPROUND;
118 v0 ^= (uint64_t{4}) << 59;
119 v2 ^= 0xFF;
120 SIPROUND;
121 SIPROUND;
122 SIPROUND;
123 SIPROUND;
124 return v0 ^ v1 ^ v2 ^ v3;
125}
126
128uint64_t PresaltedSipHasher::operator()(const uint256& val, uint32_t extra) const noexcept
129{
130 uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
131 uint64_t d = val.GetUint64(0);
132 v3 ^= d;
133 SIPROUND;
134 SIPROUND;
135 v0 ^= d;
136 d = val.GetUint64(1);
137 v3 ^= d;
138 SIPROUND;
139 SIPROUND;
140 v0 ^= d;
141 d = val.GetUint64(2);
142 v3 ^= d;
143 SIPROUND;
144 SIPROUND;
145 v0 ^= d;
146 d = val.GetUint64(3);
147 v3 ^= d;
148 SIPROUND;
149 SIPROUND;
150 v0 ^= d;
151 d = ((uint64_t{36}) << 56) | extra;
152 v3 ^= d;
153 SIPROUND;
154 SIPROUND;
155 v0 ^= d;
156 v2 ^= 0xFF;
157 SIPROUND;
158 SIPROUND;
159 SIPROUND;
160 SIPROUND;
161 return v0 ^ v1 ^ v2 ^ v3;
162}
General SipHash-2-4 implementation.
Definition: siphash.h:27
uint8_t m_count
Only the low 8 bits of the input size matter.
Definition: siphash.h:30
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
Definition: siphash.cpp:73
uint64_t m_tmp
Definition: siphash.h:29
SipHashState m_state
Definition: siphash.h:28
CSipHasher(uint64_t k0, uint64_t k1)
Construct a SipHash calculator initialized with 128-bit key (k0, k1).
Definition: siphash.cpp:22
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
Definition: siphash.cpp:24
uint64_t operator()(const uint256 &val) const noexcept
Equivalent to CSipHasher(k0, k1).Write(val).Finalize().
Definition: siphash.cpp:91
std::array< uint64_t, 4 > v
Definition: siphash.h:22
256-bit opaque blob.
Definition: uint256.h:195
#define SIPROUND
Definition: siphash.cpp:13
assert(!tx.IsCoinBase())