Bitcoin Core 32.1.0
P2P Digital Currency
Loading...
Searching...
No Matches
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://github.com/veorq/SipHash/blob/master/vectors.h
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
PresaltedSipHasher(uint64_t k0, uint64_t k1) noexcept
Definition siphash.h:209
A custom weaker variant of SipHash-1-3 without padding, and supporting "jumbo" inputs.
Definition siphash.h:161
SipHasher13UJ & Write(uint64_t data) noexcept
Hash a normal 64-bit value.
Definition siphash.cpp:52
SipHasher13UJ & WriteJumbo(const uint256 &hash) noexcept
Hash a 256-bit value as a jumbo block.
Definition siphash.cpp:58
uint64_t Finalize() const noexcept
Compute the 64-bit SipHash-1-3-UJ of the data written so far.
Definition siphash.cpp:64
ALWAYS_INLINE uint64_t Hash(const uint256 &hash) const noexcept
Hash a jumbo block after the data written so far and finalize without modifying the object.
Definition siphash.h:175
const std::string & get_str() const
const std::vector< UniValue > & getValues() const
static constexpr unsigned int size()
Definition uint256.h:107
constexpr const unsigned char * data() const
Definition uint256.h:98
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()
static uint64_t CalculateSipHash13UJ(const UniValue &input, uint64_t k0, uint64_t k1, bool normal_as_jumbo)
static uint256 FromHex256(const UniValue &value)
static uint64_t CalculateSipHash24(const UniValue &input, uint64_t k0, uint64_t k1)
static uint64_t FromHex64(const UniValue &value)
uint64_t siphash_4_2_testvec[]
static bool HasByteLength(const UniValue &value, size_t length)
#define T(expected, seed, data)
BOOST_AUTO_TEST_CASE(ipc_tests)
UniValue read_json(std::string_view jsondata)
Definition json.cpp:12
#define BOOST_CHECK_EQUAL(v1, v2)
Definition object.cpp:17
constexpr TransactionSerParams TX_WITH_WITNESS
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
std::optional< T > ToIntegral(std::string_view str, size_t base=10)
Convert string to integral type T.
Basic testing setup.
A mutable version of CTransaction.
DataStream ss
constexpr std::array tests