# Path: bitcoinpy/lib/hash.py
# def MurmurHash3(nHashSeed, vDataToHash):
#     """MurmurHash3 (x86_32)
# 
#     Used for bloom filters. See http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
#     """
# 
#     assert nHashSeed <= 0xFFFFFFFF
# 
#     h1 = nHashSeed
#     c1 = 0xcc9e2d51
#     c2 = 0x1b873593
# 
#     # body
#     i = 0
#     while i < len(vDataToHash) - len(vDataToHash) % 4 \
#           and len(vDataToHash) - i >= 4:
# 
#         k1 = struct.unpack(b"<L", vDataToHash[i:i+4])[0]
# 
#         k1 = (k1 * c1) & 0xFFFFFFFF
#         k1 = ROTL32(k1, 15)
#         k1 = (k1 * c2) & 0xFFFFFFFF
# 
#         h1 ^= k1
#         h1 = ROTL32(h1, 13)
#         h1 = (((h1*5) & 0xFFFFFFFF) + 0xe6546b64) & 0xFFFFFFFF
# 
#         i += 4
# 
#     # tail
#     k1 = 0
#     j = (len(vDataToHash) // 4) * 4
#     import sys
#     bord = ord
#     if sys.version > '3':
#         # In Py3 indexing bytes returns numbers, not characters
#         bord = lambda x: x
#     if len(vDataToHash) & 3 >= 3:
#         k1 ^= bord(vDataToHash[j+2]) << 16
#     if len(vDataToHash) & 3 >= 2:
#         k1 ^= bord(vDataToHash[j+1]) << 8
#     if len(vDataToHash) & 3 >= 1:
#         k1 ^= bord(vDataToHash[j])
# 
#     k1 &= 0xFFFFFFFF
#     k1 = (k1 * c1) & 0xFFFFFFFF
#     k1 = ROTL32(k1, 15)
#     k1 = (k1 * c2) & 0xFFFFFFFF
#     h1 ^= k1
# 
#     # finalization
#     h1 ^= len(vDataToHash) & 0xFFFFFFFF
#     h1 ^= (h1 & 0xFFFFFFFF) >> 16
#     h1 *= 0x85ebca6b
#     h1 ^= (h1 & 0xFFFFFFFF) >> 13
#     h1 *= 0xc2b2ae35
#     h1 ^= (h1 & 0xFFFFFFFF) >> 16
# 
#     return h1 & 0xFFFFFFFF


import struct
import math
from bitcoinpy.lib.serialize import *
from bitcoinpy.lib.coredefs import *
from bitcoinpy.lib.core import *
from bitcoinpy.lib.hash import MurmurHash3
    UPDATE_NONE = 0
    UPDATE_ALL = 1
    UPDATE_P2PUBKEY_ONLY = 2
    UPDATE_MASK = 3

    def __init__(self, nElements, nFPRate, nTweak, nFlags):
        """Create a new bloom filter

        The filter will have a given false-positive rate when filled with the
        given number of elements.

        Note that if the given parameters will result in a filter outside the
        bounds of the protocol limits, the filter created will be as close to
        the given parameters as possible within the protocol limits. This will
        apply if nFPRate is very low or nElements is unreasonably high.

        nTweak is a constant which is added to the seed value passed to the
        hash function It should generally always be a random value (and is
        largely only exposed for unit testing)

        nFlags should be one of the UPDATE_* enums (but not _MASK)
        """
        LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455
        LN2 = 0.6931471805599453094172321214581765680755001343602552
        self.vData = bytearray(int(min(-1  / LN2SQUARED * nElements * math.log(nFPRate), self.MAX_BLOOM_FILTER_SIZE * 8) / 8))
        self.nHashFuncs = int(min(len(self.vData) * 8 / nElements * LN2, self.MAX_HASH_FUNCS))
        self.nTweak = nTweak
        self.nFlags = nFlags

    def bloom_hash(self, nHashNum, vDataToHash):

# Path: bitcoinpy/lib/hash.py
# def MurmurHash3(nHashSeed, vDataToHash):
#     """MurmurHash3 (x86_32)
# 
#     Used for bloom filters. See http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
#     """
# 
#     assert nHashSeed <= 0xFFFFFFFF
# 
#     h1 = nHashSeed
#     c1 = 0xcc9e2d51
#     c2 = 0x1b873593
# 
#     # body
#     i = 0
#     while i < len(vDataToHash) - len(vDataToHash) % 4 \
#           and len(vDataToHash) - i >= 4:
# 
#         k1 = struct.unpack(b"<L", vDataToHash[i:i+4])[0]
# 
#         k1 = (k1 * c1) & 0xFFFFFFFF
#         k1 = ROTL32(k1, 15)
#         k1 = (k1 * c2) & 0xFFFFFFFF
# 
#         h1 ^= k1
#         h1 = ROTL32(h1, 13)
#         h1 = (((h1*5) & 0xFFFFFFFF) + 0xe6546b64) & 0xFFFFFFFF
# 
#         i += 4
# 
#     # tail
#     k1 = 0
#     j = (len(vDataToHash) // 4) * 4
#     import sys
#     bord = ord
#     if sys.version > '3':
#         # In Py3 indexing bytes returns numbers, not characters
#         bord = lambda x: x
#     if len(vDataToHash) & 3 >= 3:
#         k1 ^= bord(vDataToHash[j+2]) << 16
#     if len(vDataToHash) & 3 >= 2:
#         k1 ^= bord(vDataToHash[j+1]) << 8
#     if len(vDataToHash) & 3 >= 1:
#         k1 ^= bord(vDataToHash[j])
# 
#     k1 &= 0xFFFFFFFF
#     k1 = (k1 * c1) & 0xFFFFFFFF
#     k1 = ROTL32(k1, 15)
#     k1 = (k1 * c2) & 0xFFFFFFFF
#     h1 ^= k1
# 
#     # finalization
#     h1 ^= len(vDataToHash) & 0xFFFFFFFF
#     h1 ^= (h1 & 0xFFFFFFFF) >> 16
#     h1 *= 0x85ebca6b
#     h1 ^= (h1 & 0xFFFFFFFF) >> 13
#     h1 *= 0xc2b2ae35
#     h1 ^= (h1 & 0xFFFFFFFF) >> 16
# 
#     return h1 & 0xFFFFFFFF


# Path: bitcoinpy/lib/bloom.py
import struct
import math
from bitcoinpy.lib.serialize import *
from bitcoinpy.lib.coredefs import *
from bitcoinpy.lib.core import *
from bitcoinpy.lib.hash import MurmurHash3

    UPDATE_NONE = 0
    UPDATE_ALL = 1
    UPDATE_P2PUBKEY_ONLY = 2
    UPDATE_MASK = 3

    def __init__(self, nElements, nFPRate, nTweak, nFlags):
        """Create a new bloom filter

        The filter will have a given false-positive rate when filled with the
        given number of elements.

        Note that if the given parameters will result in a filter outside the
        bounds of the protocol limits, the filter created will be as close to
        the given parameters as possible within the protocol limits. This will
        apply if nFPRate is very low or nElements is unreasonably high.

        nTweak is a constant which is added to the seed value passed to the
        hash function It should generally always be a random value (and is
        largely only exposed for unit testing)

        nFlags should be one of the UPDATE_* enums (but not _MASK)
        """
        LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455
        LN2 = 0.6931471805599453094172321214581765680755001343602552
        self.vData = bytearray(int(min(-1  / LN2SQUARED * nElements * math.log(nFPRate), self.MAX_BLOOM_FILTER_SIZE * 8) / 8))
        self.nHashFuncs = int(min(len(self.vData) * 8 / nElements * LN2, self.MAX_HASH_FUNCS))
        self.nTweak = nTweak
        self.nFlags = nFlags

    def bloom_hash(self, nHashNum, vDataToHash):

        return MurmurHash3(((nHashNum * 0xFBA4C795) + self.nTweak) & 0xFFFFFFFF, vDataToHash) % (len(self.vData) * 8)