Skip to content

Commit 25ee74d

Browse files
committed
test: add SipHash implementation for generic data in Python
We will need this in the next commit to calculate ranged hashes of scriptPubKeys as defined in BIP158.
1 parent a97791d commit 25ee74d

File tree

1 file changed

+29
-27
lines changed

1 file changed

+29
-27
lines changed
Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
#!/usr/bin/env python3
2-
# Copyright (c) 2016-2018 The Bitcoin Core developers
2+
# Copyright (c) 2016-2022 The Bitcoin Core developers
33
# Distributed under the MIT software license, see the accompanying
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5-
"""Specialized SipHash-2-4 implementations.
5+
"""SipHash-2-4 implementation.
66
7-
This implements SipHash-2-4 for 256-bit integers.
7+
This implements SipHash-2-4. For convenience, an interface taking 256-bit
8+
integers is provided in addition to the one accepting generic data.
89
"""
910

1011
def rotl64(n, b):
1112
return n >> (64 - b) | (n & ((1 << (64 - b)) - 1)) << b
1213

14+
1315
def siphash_round(v0, v1, v2, v3):
1416
v0 = (v0 + v1) & ((1 << 64) - 1)
1517
v1 = rotl64(v1, 13)
@@ -27,37 +29,37 @@ def siphash_round(v0, v1, v2, v3):
2729
v2 = rotl64(v2, 32)
2830
return (v0, v1, v2, v3)
2931

30-
def siphash256(k0, k1, h):
31-
n0 = h & ((1 << 64) - 1)
32-
n1 = (h >> 64) & ((1 << 64) - 1)
33-
n2 = (h >> 128) & ((1 << 64) - 1)
34-
n3 = (h >> 192) & ((1 << 64) - 1)
32+
33+
def siphash(k0, k1, data):
34+
assert(type(data) == bytes)
3535
v0 = 0x736f6d6570736575 ^ k0
3636
v1 = 0x646f72616e646f6d ^ k1
3737
v2 = 0x6c7967656e657261 ^ k0
38-
v3 = 0x7465646279746573 ^ k1 ^ n0
39-
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
40-
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
41-
v0 ^= n0
42-
v3 ^= n1
43-
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
44-
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
45-
v0 ^= n1
46-
v3 ^= n2
38+
v3 = 0x7465646279746573 ^ k1
39+
c = 0
40+
t = 0
41+
for d in data:
42+
t |= d << (8 * (c % 8))
43+
c = (c + 1) & 0xff
44+
if (c & 7) == 0:
45+
v3 ^= t
46+
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
47+
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
48+
v0 ^= t
49+
t = 0
50+
t = t | (c << 56)
51+
v3 ^= t
4752
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
4853
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
49-
v0 ^= n2
50-
v3 ^= n3
51-
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
52-
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
53-
v0 ^= n3
54-
v3 ^= 0x2000000000000000
55-
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
56-
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
57-
v0 ^= 0x2000000000000000
58-
v2 ^= 0xFF
54+
v0 ^= t
55+
v2 ^= 0xff
5956
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
6057
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
6158
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
6259
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
6360
return v0 ^ v1 ^ v2 ^ v3
61+
62+
63+
def siphash256(k0, k1, num):
64+
assert(type(num) == int)
65+
return siphash(k0, k1, num.to_bytes(32, 'little'))

0 commit comments

Comments
 (0)