Add specialization of SipHash for 256 + 32 bit data

We'll need a version of SipHash for tuples of 256 bits and 32 bits
data, when CCoinsViewCache switches from using txids to COutPoints as
keys.
This commit is contained in:
Pieter Wuille 2017-04-25 11:29:16 -07:00
parent e484652fc3
commit 7e00322906
3 changed files with 59 additions and 0 deletions

View File

@ -208,3 +208,44 @@ uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val)
SIPROUND; SIPROUND;
return v0 ^ v1 ^ v2 ^ v3; 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 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;
SIPROUND;
SIPROUND;
v0 ^= d;
d = val.GetUint64(1);
v3 ^= d;
SIPROUND;
SIPROUND;
v0 ^= d;
d = val.GetUint64(2);
v3 ^= d;
SIPROUND;
SIPROUND;
v0 ^= d;
d = val.GetUint64(3);
v3 ^= d;
SIPROUND;
SIPROUND;
v0 ^= d;
d = (((uint64_t)36) << 56) | extra;
v3 ^= d;
SIPROUND;
SIPROUND;
v0 ^= d;
v2 ^= 0xFF;
SIPROUND;
SIPROUND;
SIPROUND;
SIPROUND;
return v0 ^ v1 ^ v2 ^ v3;
}

View File

@ -241,5 +241,6 @@ public:
* .Finalize() * .Finalize()
*/ */
uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val); 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);
#endif // BITCOIN_HASH_H #endif // BITCOIN_HASH_H

View File

@ -128,6 +128,23 @@ BOOST_AUTO_TEST_CASE(siphash)
tx.nVersion = 1; tx.nVersion = 1;
ss << tx; ss << tx;
BOOST_CHECK_EQUAL(SipHashUint256(1, 2, ss.GetHash()), 0x79751e980c2a0a35ULL); BOOST_CHECK_EQUAL(SipHashUint256(1, 2, ss.GetHash()), 0x79751e980c2a0a35ULL);
// Check consistency between CSipHasher and SipHashUint256[Extra].
FastRandomContext ctx;
for (int i = 0; i < 16; ++i) {
uint64_t k1 = ctx.rand64();
uint64_t k2 = ctx.rand64();
uint256 x = GetRandHash();
uint32_t n = ctx.rand32();
uint8_t nb[4];
WriteLE32(nb, n);
CSipHasher sip256(k1, k2);
sip256.Write(x.begin(), 32);
CSipHasher sip288 = sip256;
sip288.Write(nb, 4);
BOOST_CHECK_EQUAL(SipHashUint256(k1, k2, x), sip256.Finalize());
BOOST_CHECK_EQUAL(SipHashUint256Extra(k1, k2, x, n), sip288.Finalize());
}
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()