Bitcoin Core 31.99.0
P2P Digital Currency
hash_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2013-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/common.h>
6#include <crypto/siphash.h>
7#include <hash.h>
8#include <test/data/siphash.json.h>
9#include <test/util/json.h>
11#include <uint256.h>
12#include <util/strencodings.h>
13
14#include <boost/test/unit_test.hpp>
15
17
18static uint64_t FromHex64(const UniValue& value) { return ToIntegral<uint64_t>(value.get_str(), /*base=*/16).value(); }
19static uint256 FromHex256(const UniValue& value) { return uint256{ParseHex(value.get_str())}; }
20static bool HasByteLength(const UniValue& value, size_t length) { return value.get_str().size() == 2 * length; }
21
22static uint64_t CalculateSipHash24(const UniValue& input, uint64_t k0, uint64_t k1)
23{
24 CSipHasher hasher{k0, k1};
25 for (auto& block : input.getValues()) {
26 hasher.Write(ParseHex(block.get_str()));
27 }
28 const uint64_t result{hasher.Finalize()};
29 BOOST_CHECK_EQUAL(hasher.Finalize(), result);
30 return result;
31}
32
33static uint64_t CalculateSipHash13UJ(const UniValue& input, uint64_t k0, uint64_t k1, bool normal_as_jumbo)
34{
35 SipHasher13UJ hasher{k0, k1};
36 for (auto& value : input.getValues()) {
37 const auto block{ParseHex(value.get_str())};
38 if (block.size() == sizeof(uint64_t)) {
39 if (!normal_as_jumbo) {
40 hasher.Write(ReadLE64(block.data()));
41 } else {
42 uint256 data256{};
43 WriteLE64(data256.data(), ReadLE64(block.data()));
44 hasher.WriteJumbo(data256);
45 }
46 } else {
47 BOOST_REQUIRE_EQUAL(block.size(), uint256::size());
48 hasher.WriteJumbo(uint256{block});
49 }
50 }
51 const uint64_t result{hasher.Finalize()};
52 BOOST_CHECK_EQUAL(hasher.Finalize(), result);
53 return result;
54}
55
57{
58
59#define T(expected, seed, data) BOOST_CHECK_EQUAL(MurmurHash3(seed, ParseHex(data)), expected)
60
61 // Test MurmurHash3 with various inputs. Of course this is retested in the
62 // bloom filter tests - they would fail if MurmurHash3() had any problems -
63 // but is useful for those trying to implement Bitcoin libraries as a
64 // source of test data for their MurmurHash3() primitive during
65 // development.
66 //
67 // The magic number 0xFBA4C795 comes from CBloomFilter::Hash()
68
69 T(0x00000000U, 0x00000000, "");
70 T(0x6a396f08U, 0xFBA4C795, "");
71 T(0x81f16f39U, 0xffffffff, "");
72
73 T(0x514e28b7U, 0x00000000, "00");
74 T(0xea3f0b17U, 0xFBA4C795, "00");
75 T(0xfd6cf10dU, 0x00000000, "ff");
76
77 T(0x16c6b7abU, 0x00000000, "0011");
78 T(0x8eb51c3dU, 0x00000000, "001122");
79 T(0xb4471bf8U, 0x00000000, "00112233");
80 T(0xe2301fa8U, 0x00000000, "0011223344");
81 T(0xfc2e4a15U, 0x00000000, "001122334455");
82 T(0xb074502cU, 0x00000000, "00112233445566");
83 T(0x8034d2a0U, 0x00000000, "0011223344556677");
84 T(0xb4698defU, 0x00000000, "001122334455667788");
85
86#undef T
87}
88
89/*
90 SipHash-2-4 output with
91 k = 00 01 02 ...
92 and
93 in = (empty string)
94 in = 00 (1 byte)
95 in = 00 01 (2 bytes)
96 in = 00 01 02 (3 bytes)
97 ...
98 in = 00 01 02 ... 3e (63 bytes)
99
100 from: https://131002.net/siphash/siphash24.c
101*/
103 0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d,
104 0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137,
105 0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7,
106 0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5,
107 0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd,
108 0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8,
109 0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad,
110 0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342,
111 0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae,
112 0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c,
113 0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95,
114 0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb,
115 0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a,
116 0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499,
117 0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93,
118 0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572
119};
120
122{
123 CSipHasher hasher(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
124 BOOST_CHECK_EQUAL(hasher.Finalize(), 0x726fdb47dd0e0e31ull);
125 static const unsigned char t0[1] = {0};
126 hasher.Write(t0);
127 BOOST_CHECK_EQUAL(hasher.Finalize(), 0x74f839c593dc67fdull);
128 static const unsigned char t1[7] = {1,2,3,4,5,6,7};
129 hasher.Write(t1);
130 BOOST_CHECK_EQUAL(hasher.Finalize(), 0x93f5f5799a932462ull);
131 hasher.Write(0x0F0E0D0C0B0A0908ULL);
132 BOOST_CHECK_EQUAL(hasher.Finalize(), 0x3f2acc7f57c29bdbull);
133 static const unsigned char t2[2] = {16,17};
134 hasher.Write(t2);
135 BOOST_CHECK_EQUAL(hasher.Finalize(), 0x4bc1b3f0968dd39cull);
136 static const unsigned char t3[9] = {18,19,20,21,22,23,24,25,26};
137 hasher.Write(t3);
138 BOOST_CHECK_EQUAL(hasher.Finalize(), 0x2f2e6163076bcfadull);
139 static const unsigned char t4[5] = {27,28,29,30,31};
140 hasher.Write(t4);
141 BOOST_CHECK_EQUAL(hasher.Finalize(), 0x7127512f72f27cceull);
142 hasher.Write(0x2726252423222120ULL);
143 BOOST_CHECK_EQUAL(hasher.Finalize(), 0x0e3ea96b5304a7d0ull);
144 hasher.Write(0x2F2E2D2C2B2A2928ULL);
145 BOOST_CHECK_EQUAL(hasher.Finalize(), 0xe612a3cb9ecba951ull);
146
147 // Check test vectors from spec, one byte at a time
148 CSipHasher hasher2(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
149 for (uint8_t x=0; x<std::size(siphash_4_2_testvec); ++x)
150 {
152 hasher2.Write(std::span{&x, 1});
153 }
154 // Check test vectors from spec, eight bytes at a time
155 CSipHasher hasher3(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
156 for (uint8_t x=0; x<std::size(siphash_4_2_testvec); x+=8)
157 {
159 hasher3.Write(uint64_t(x)|(uint64_t(x+1)<<8)|(uint64_t(x+2)<<16)|(uint64_t(x+3)<<24)|
160 (uint64_t(x+4)<<32)|(uint64_t(x+5)<<40)|(uint64_t(x+6)<<48)|(uint64_t(x+7)<<56));
161 }
162
163 HashWriter ss{};
165 // Note these tests were originally written with tx.version=1
166 // and the test would be affected by default tx version bumps if not fixed.
167 tx.version = 1;
168 ss << TX_WITH_WITNESS(tx);
169 BOOST_CHECK_EQUAL(PresaltedSipHasher(1, 2)(ss.GetHash()), 0x79751e980c2a0a35ULL);
170}
171
172BOOST_AUTO_TEST_CASE(siphash_test_vectors)
173{
174 for (UniValue tests{read_json(json_tests::siphash)}; auto& test : tests.getValues()) {
175 const uint64_t k0{FromHex64(test["key"][0])}, k1{FromHex64(test["key"][1])};
176 auto& input{test["input"]};
177 const bool starts_with_hash{!input.empty() && HasByteLength(input[0], uint256::size())};
178 const bool hash_only{starts_with_hash && input.size() == 1};
179 const bool hash_extra{starts_with_hash && input.size() == 2};
180 const uint64_t expected24{FromHex64(test["expected"]["siphash24"])};
181 BOOST_CHECK_EQUAL(CalculateSipHash24(input, k0, k1), expected24);
182 if (hash_only) {
183 BOOST_CHECK_EQUAL(PresaltedSipHasher(k0, k1)(FromHex256(input[0])), expected24);
184 } else if (hash_extra && HasByteLength(input[1], sizeof(uint32_t))) {
185 const auto extra{ParseHex(input[1].get_str())};
186 BOOST_CHECK_EQUAL(PresaltedSipHasher(k0, k1)(FromHex256(input[0]), ReadLE32(extra.data())), expected24);
187 }
188 if (auto& expected_value{test["expected"]["siphash13uj"]}; !expected_value.isNull()) {
189 const uint64_t expected13uj{FromHex64(expected_value)};
190 BOOST_CHECK_EQUAL(CalculateSipHash13UJ(input, k0, k1, /*normal_as_jumbo=*/false), expected13uj);
191 BOOST_CHECK_EQUAL(CalculateSipHash13UJ(input, k0, k1, /*normal_as_jumbo=*/true), expected13uj);
192 const SipHasher13UJ fixed_hasher{k0, k1};
193 if (hash_only) {
194 BOOST_CHECK_EQUAL(fixed_hasher.Hash(FromHex256(input[0])), expected13uj);
195 } else if (hash_extra && HasByteLength(input[1], sizeof(uint64_t))) {
196 const auto extra{ParseHex(input[1].get_str())};
197 BOOST_CHECK_EQUAL(fixed_hasher.Hash(FromHex256(input[0]), ReadLE64(extra.data())), expected13uj);
198 }
199 }
200 }
201}
202
General SipHash-2-4 implementation.
Definition: siphash.h:99
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
Definition: siphash.cpp:45
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
Definition: siphash.cpp:14
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:109
Optimized SipHash-2-4 implementation for uint256.
Definition: siphash.h:205
A custom weaker variant of SipHash-1-3 without padding, and supporting "jumbo" inputs.
Definition: siphash.h:161
const std::string & get_str() const
const std::vector< UniValue > & getValues() const
static constexpr unsigned int size()
Definition: uint256.h:107
256-bit opaque blob.
Definition: uint256.h:196
uint64_t ReadLE64(const B *ptr)
Definition: common.h:35
void WriteLE64(B *ptr, uint64_t x)
Definition: common.h:57
uint32_t ReadLE32(const B *ptr)
Definition: common.h:27
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(murmurhash3)
Definition: hash_tests.cpp:56
static uint64_t CalculateSipHash13UJ(const UniValue &input, uint64_t k0, uint64_t k1, bool normal_as_jumbo)
Definition: hash_tests.cpp:33
static uint256 FromHex256(const UniValue &value)
Definition: hash_tests.cpp:19
static uint64_t CalculateSipHash24(const UniValue &input, uint64_t k0, uint64_t k1)
Definition: hash_tests.cpp:22
static uint64_t FromHex64(const UniValue &value)
Definition: hash_tests.cpp:18
uint64_t siphash_4_2_testvec[]
Definition: hash_tests.cpp:102
static bool HasByteLength(const UniValue &value, size_t length)
Definition: hash_tests.cpp:20
#define T(expected, seed, data)
BOOST_CHECK_EQUAL(headers.FindFirst("key"), "value")
UniValue read_json(std::string_view jsondata)
Definition: json.cpp:12
static constexpr TransactionSerParams TX_WITH_WITNESS
Definition: transaction.h:180
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
Definition: strencodings.h:68
Basic testing setup.
Definition: setup_common.h:58
A mutable version of CTransaction.
Definition: transaction.h:358
constexpr std::array tests
Definition: unitester.cpp:101