mirror of
https://github.com/dashpay/dash.git
synced 2024-12-29 13:59:06 +01:00
56 lines
2.1 KiB
Python
56 lines
2.1 KiB
Python
|
# Copyright (c) 2020 Pieter Wuille
|
||
|
# Distributed under the MIT software license, see the accompanying
|
||
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||
|
"""Native Python MuHash3072 implementation."""
|
||
|
|
||
|
import hashlib
|
||
|
import unittest
|
||
|
|
||
|
from .chacha20 import chacha20_block
|
||
|
|
||
|
def data_to_num3072(data):
|
||
|
"""Hash a 32-byte array data to a 3072-bit number using 6 Chacha20 operations."""
|
||
|
bytes384 = b""
|
||
|
for counter in range(6):
|
||
|
bytes384 += chacha20_block(data, bytes(12), counter)
|
||
|
return int.from_bytes(bytes384, 'little')
|
||
|
|
||
|
class MuHash3072:
|
||
|
"""Class representing the MuHash3072 computation of a set.
|
||
|
|
||
|
See https://cseweb.ucsd.edu/~mihir/papers/inchash.pdf and https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-May/014337.html
|
||
|
"""
|
||
|
|
||
|
MODULUS = 2**3072 - 1103717
|
||
|
|
||
|
def __init__(self):
|
||
|
"""Initialize for an empty set."""
|
||
|
self.numerator = 1
|
||
|
self.denominator = 1
|
||
|
|
||
|
def insert(self, data):
|
||
|
"""Insert a byte array data in the set."""
|
||
|
data_hash = hashlib.sha256(data).digest()
|
||
|
self.numerator = (self.numerator * data_to_num3072(data_hash)) % self.MODULUS
|
||
|
|
||
|
def remove(self, data):
|
||
|
"""Remove a byte array from the set."""
|
||
|
data_hash = hashlib.sha256(data).digest()
|
||
|
self.denominator = (self.denominator * data_to_num3072(data_hash)) % self.MODULUS
|
||
|
|
||
|
def digest(self):
|
||
|
"""Extract the final hash. Does not modify this object."""
|
||
|
val = (self.numerator * pow(self.denominator, -1, self.MODULUS)) % self.MODULUS
|
||
|
bytes384 = val.to_bytes(384, 'little')
|
||
|
return hashlib.sha256(bytes384).digest()
|
||
|
|
||
|
class TestFrameworkMuhash(unittest.TestCase):
|
||
|
def test_muhash(self):
|
||
|
muhash = MuHash3072()
|
||
|
muhash.insert(b'\x00' * 32)
|
||
|
muhash.insert((b'\x01' + b'\x00' * 31))
|
||
|
muhash.remove((b'\x02' + b'\x00' * 31))
|
||
|
finalized = muhash.digest()
|
||
|
# This mirrors the result in the C++ MuHash3072 unit test
|
||
|
self.assertEqual(finalized[::-1].hex(), "10d312b100cbd32ada024a6646e40d3482fcff103668d2625f10002a607d5863")
|