mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-13 11:35:20 +01:00
Merge 31e1a49acf
into a50af6e4c4
This commit is contained in:
commit
d852996361
7 changed files with 142 additions and 33 deletions
|
@ -2,7 +2,6 @@
|
|||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
#include <bench/bench.h>
|
||||
#include <crypto/muhash.h>
|
||||
#include <crypto/ripemd160.h>
|
||||
|
@ -12,9 +11,11 @@
|
|||
#include <crypto/sha512.h>
|
||||
#include <crypto/siphash.h>
|
||||
#include <random.h>
|
||||
#include <span.h>
|
||||
#include <tinyformat.h>
|
||||
#include <uint256.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <util/hasher.h>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
@ -205,6 +206,98 @@ static void SipHash_32b(benchmark::Bench& bench)
|
|||
});
|
||||
}
|
||||
|
||||
static void SaltedOutpointHasherBench_hash(benchmark::Bench& bench)
|
||||
{
|
||||
FastRandomContext rng{/*fDeterministic=*/true};
|
||||
constexpr size_t size{1000};
|
||||
|
||||
std::vector<COutPoint> outpoints(size);
|
||||
for (auto& outpoint : outpoints) {
|
||||
outpoint = {Txid::FromUint256(rng.rand256()), rng.rand32()};
|
||||
}
|
||||
|
||||
const SaltedOutpointHasher hasher;
|
||||
bench.batch(size).run([&] {
|
||||
size_t result{0};
|
||||
for (const auto& outpoint : outpoints) {
|
||||
result ^= hasher(outpoint);
|
||||
}
|
||||
ankerl::nanobench::doNotOptimizeAway(result);
|
||||
});
|
||||
}
|
||||
|
||||
static void SaltedOutpointHasherBench_match(benchmark::Bench& bench)
|
||||
{
|
||||
FastRandomContext rng{/*fDeterministic=*/true};
|
||||
constexpr size_t size{1000};
|
||||
|
||||
std::unordered_set<COutPoint, SaltedOutpointHasher> values;
|
||||
std::vector<COutPoint> value_vector;
|
||||
values.reserve(size);
|
||||
value_vector.reserve(size);
|
||||
|
||||
for (size_t i{0}; i < size; ++i) {
|
||||
COutPoint outpoint{Txid::FromUint256(rng.rand256()), rng.rand32()};
|
||||
values.emplace(outpoint);
|
||||
value_vector.push_back(outpoint);
|
||||
assert(values.contains(outpoint));
|
||||
}
|
||||
|
||||
bench.batch(size).run([&] {
|
||||
bool result{true};
|
||||
for (const auto& outpoint : value_vector) {
|
||||
result ^= values.contains(outpoint);
|
||||
}
|
||||
ankerl::nanobench::doNotOptimizeAway(result);
|
||||
});
|
||||
}
|
||||
|
||||
static void SaltedOutpointHasherBench_mismatch(benchmark::Bench& bench)
|
||||
{
|
||||
FastRandomContext rng{/*fDeterministic=*/true};
|
||||
constexpr size_t size{1000};
|
||||
|
||||
std::unordered_set<COutPoint, SaltedOutpointHasher> values;
|
||||
std::vector<COutPoint> missing_value_vector;
|
||||
values.reserve(size);
|
||||
missing_value_vector.reserve(size);
|
||||
|
||||
for (size_t i{0}; i < size; ++i) {
|
||||
values.emplace(Txid::FromUint256(rng.rand256()), rng.rand32());
|
||||
COutPoint missing_outpoint{Txid::FromUint256(rng.rand256()), rng.rand32()};
|
||||
missing_value_vector.push_back(missing_outpoint);
|
||||
assert(!values.contains(missing_outpoint));
|
||||
}
|
||||
|
||||
bench.batch(size).run([&] {
|
||||
bool result{false};
|
||||
for (const auto& outpoint : missing_value_vector) {
|
||||
result ^= values.contains(outpoint);
|
||||
}
|
||||
ankerl::nanobench::doNotOptimizeAway(result);
|
||||
});
|
||||
}
|
||||
|
||||
static void SaltedOutpointHasherBench_create_set(benchmark::Bench& bench)
|
||||
{
|
||||
FastRandomContext rng{/*fDeterministic=*/true};
|
||||
constexpr size_t size{1000};
|
||||
|
||||
std::vector<COutPoint> outpoints(size);
|
||||
for (auto& outpoint : outpoints) {
|
||||
outpoint = {Txid::FromUint256(rng.rand256()), rng.rand32()};
|
||||
}
|
||||
|
||||
bench.batch(size).run([&] {
|
||||
std::unordered_set<COutPoint, SaltedOutpointHasher> set;
|
||||
set.reserve(size);
|
||||
for (const auto& outpoint : outpoints) {
|
||||
set.emplace(outpoint);
|
||||
}
|
||||
ankerl::nanobench::doNotOptimizeAway(set.size());
|
||||
});
|
||||
}
|
||||
|
||||
static void MuHash(benchmark::Bench& bench)
|
||||
{
|
||||
MuHash3072 acc;
|
||||
|
@ -276,6 +369,10 @@ BENCHMARK(SHA256_32b_SSE4, benchmark::PriorityLevel::HIGH);
|
|||
BENCHMARK(SHA256_32b_AVX2, benchmark::PriorityLevel::HIGH);
|
||||
BENCHMARK(SHA256_32b_SHANI, benchmark::PriorityLevel::HIGH);
|
||||
BENCHMARK(SipHash_32b, benchmark::PriorityLevel::HIGH);
|
||||
BENCHMARK(SaltedOutpointHasherBench_hash, benchmark::PriorityLevel::HIGH);
|
||||
BENCHMARK(SaltedOutpointHasherBench_match, benchmark::PriorityLevel::HIGH);
|
||||
BENCHMARK(SaltedOutpointHasherBench_mismatch, benchmark::PriorityLevel::HIGH);
|
||||
BENCHMARK(SaltedOutpointHasherBench_create_set, benchmark::PriorityLevel::HIGH);
|
||||
BENCHMARK(SHA256D64_1024_STANDARD, benchmark::PriorityLevel::HIGH);
|
||||
BENCHMARK(SHA256D64_1024_SSE4, benchmark::PriorityLevel::HIGH);
|
||||
BENCHMARK(SHA256D64_1024_AVX2, benchmark::PriorityLevel::HIGH);
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
|
||||
CSipHasher::CSipHasher(uint64_t k0, uint64_t k1)
|
||||
{
|
||||
v[0] = 0x736f6d6570736575ULL ^ k0;
|
||||
v[1] = 0x646f72616e646f6dULL ^ k1;
|
||||
v[2] = 0x6c7967656e657261ULL ^ k0;
|
||||
v[3] = 0x7465646279746573ULL ^ k1;
|
||||
v[0] = C0 ^ k0;
|
||||
v[1] = C1 ^ k1;
|
||||
v[2] = C2 ^ k0;
|
||||
v[3] = C3 ^ k1;
|
||||
count = 0;
|
||||
tmp = 0;
|
||||
}
|
||||
|
@ -97,10 +97,10 @@ uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val)
|
|||
/* Specialized implementation for efficiency */
|
||||
uint64_t d = val.GetUint64(0);
|
||||
|
||||
uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
|
||||
uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
|
||||
uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
|
||||
uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
|
||||
uint64_t v0 = CSipHasher::C0 ^ k0;
|
||||
uint64_t v1 = CSipHasher::C1 ^ k1;
|
||||
uint64_t v2 = CSipHasher::C2 ^ k0;
|
||||
uint64_t v3 = CSipHasher::C3 ^ k1 ^ d;
|
||||
|
||||
SIPROUND;
|
||||
SIPROUND;
|
||||
|
@ -132,16 +132,12 @@ uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val)
|
|||
return v0 ^ v1 ^ v2 ^ v3;
|
||||
}
|
||||
|
||||
uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra)
|
||||
/* Specialized implementation for efficiency */
|
||||
uint64_t Uint256ExtraSipHasher::operator()(const uint256& val, uint32_t extra) const noexcept
|
||||
{
|
||||
/* Specialized implementation for efficiency */
|
||||
uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
|
||||
uint64_t d = val.GetUint64(0);
|
||||
|
||||
uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
|
||||
uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
|
||||
uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
|
||||
uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
|
||||
|
||||
v3 ^= d;
|
||||
SIPROUND;
|
||||
SIPROUND;
|
||||
v0 ^= d;
|
||||
|
|
|
@ -19,6 +19,11 @@ private:
|
|||
uint8_t count; // Only the low 8 bits of the input size matter.
|
||||
|
||||
public:
|
||||
static constexpr uint64_t C0{0x736f6d6570736575ULL};
|
||||
static constexpr uint64_t C1{0x646f72616e646f6dULL};
|
||||
static constexpr uint64_t C2{0x6c7967656e657261ULL};
|
||||
static constexpr uint64_t C3{0x7465646279746573ULL};
|
||||
|
||||
/** Construct a SipHash calculator initialized with 128-bit key (k0, k1) */
|
||||
CSipHasher(uint64_t k0, uint64_t k1);
|
||||
/** Hash a 64-bit integer worth of data
|
||||
|
@ -43,6 +48,19 @@ public:
|
|||
* .Finalize()
|
||||
*/
|
||||
uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val);
|
||||
uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra);
|
||||
|
||||
class Uint256ExtraSipHasher {
|
||||
uint64_t v[4];
|
||||
|
||||
public:
|
||||
Uint256ExtraSipHasher(const uint64_t k0, const uint64_t k1) noexcept {
|
||||
v[0] = CSipHasher::C0 ^ k0;
|
||||
v[1] = CSipHasher::C1 ^ k1;
|
||||
v[2] = CSipHasher::C2 ^ k0;
|
||||
v[3] = CSipHasher::C3 ^ k1;
|
||||
}
|
||||
|
||||
uint64_t operator()(const uint256& val, uint32_t extra) const noexcept;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CRYPTO_SIPHASH_H
|
||||
|
|
|
@ -119,7 +119,7 @@ FUZZ_TARGET(integer, .init = initialize_integer)
|
|||
(void)MillisToTimeval(i64);
|
||||
(void)SighashToStr(uch);
|
||||
(void)SipHashUint256(u64, u64, u256);
|
||||
(void)SipHashUint256Extra(u64, u64, u256, u32);
|
||||
(void)Uint256ExtraSipHasher(u64, u64)(u256, u32);
|
||||
(void)ToLower(ch);
|
||||
(void)ToUpper(ch);
|
||||
{
|
||||
|
|
|
@ -130,21 +130,21 @@ BOOST_AUTO_TEST_CASE(siphash)
|
|||
ss << TX_WITH_WITNESS(tx);
|
||||
BOOST_CHECK_EQUAL(SipHashUint256(1, 2, ss.GetHash()), 0x79751e980c2a0a35ULL);
|
||||
|
||||
// Check consistency between CSipHasher and SipHashUint256[Extra].
|
||||
// Check consistency between CSipHasher and SipHashUint256 and Uint256ExtraSipHasher.
|
||||
FastRandomContext ctx;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
uint64_t k0 = ctx.rand64();
|
||||
uint64_t k1 = ctx.rand64();
|
||||
uint64_t k2 = ctx.rand64();
|
||||
uint256 x = m_rng.rand256();
|
||||
uint32_t n = ctx.rand32();
|
||||
uint8_t nb[4];
|
||||
WriteLE32(nb, n);
|
||||
CSipHasher sip256(k1, k2);
|
||||
CSipHasher sip256(k0, k1);
|
||||
sip256.Write(x);
|
||||
CSipHasher sip288 = sip256;
|
||||
sip288.Write(nb);
|
||||
BOOST_CHECK_EQUAL(SipHashUint256(k1, k2, x), sip256.Finalize());
|
||||
BOOST_CHECK_EQUAL(SipHashUint256Extra(k1, k2, x, n), sip288.Finalize());
|
||||
BOOST_CHECK_EQUAL(SipHashUint256(k0, k1, x), sip256.Finalize());
|
||||
BOOST_CHECK_EQUAL(Uint256ExtraSipHasher(k0, k1)(x, n), sip288.Finalize());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ SaltedTxidHasher::SaltedTxidHasher() :
|
|||
k0{FastRandomContext().rand64()},
|
||||
k1{FastRandomContext().rand64()} {}
|
||||
|
||||
SaltedOutpointHasher::SaltedOutpointHasher(bool deterministic) :
|
||||
k0{deterministic ? 0x8e819f2607a18de6 : FastRandomContext().rand64()},
|
||||
k1{deterministic ? 0xf4020d2e3983b0eb : FastRandomContext().rand64()}
|
||||
SaltedOutpointHasher::SaltedOutpointHasher(bool deterministic) : hasher{
|
||||
deterministic ? 0x8e819f2607a18de6 : FastRandomContext().rand64(),
|
||||
deterministic ? 0xf4020d2e3983b0eb : FastRandomContext().rand64()}
|
||||
{}
|
||||
|
||||
SaltedSipHasher::SaltedSipHasher() :
|
||||
|
|
|
@ -30,12 +30,10 @@ public:
|
|||
|
||||
class SaltedOutpointHasher
|
||||
{
|
||||
private:
|
||||
/** Salt */
|
||||
const uint64_t k0, k1;
|
||||
const Uint256ExtraSipHasher hasher;
|
||||
|
||||
public:
|
||||
SaltedOutpointHasher(bool deterministic = false);
|
||||
explicit SaltedOutpointHasher(bool deterministic = false);
|
||||
|
||||
/**
|
||||
* Having the hash noexcept allows libstdc++'s unordered_map to recalculate
|
||||
|
@ -47,7 +45,7 @@ public:
|
|||
* @see https://gcc.gnu.org/onlinedocs/gcc-13.2.0/libstdc++/manual/manual/unordered_associative.html
|
||||
*/
|
||||
size_t operator()(const COutPoint& id) const noexcept {
|
||||
return SipHashUint256Extra(k0, k1, id.hash, id.n);
|
||||
return hasher(id.hash, id.n);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue