pyflo/pybtc/functions/block.py
2018-06-30 21:37:17 +04:00

126 lines
4.0 KiB
Python

def merkle_root(tx_hash_list, hex=True):
"""
Calculate merkle root from transaction hash list
:param tx_hash_list: list of transaction hashes in bytes or HEX encoded string.
:param hex: (optional) If set to True return result in HEX format, by default is True.
:return: merkle root in bytes or HEX encoded string corresponding hex flag.
"""
tx_hash_list = [h if isinstance(h, bytes) else s2rh(h) for h in tx_hash_list]
if len(tx_hash_list) == 1:
return tx_hash_list[0]
while True:
new_hash_list = list()
while tx_hash_list:
h1 = tx_hash_list.pop(0)
try:
h2 = tx_hash_list.pop(0)
except:
h2 = h1
new_hash_list.append(double_sha256(h1 + h2))
if len(new_hash_list) > 1:
tx_hash_list = new_hash_list
else:
return new_hash_list[0] if not hex else hexlify(new_hash_list[0]).decode()
def merkle_branches(tx_hash_list, hex=True):
"""
Calculate merkle branches for coinbase transacton
:param tx_hash_list: list of transaction hashes in bytes or HEX encoded string.
:param hex: (optional) If set to True return result in HEX format, by default is True.
:return: list of merkle branches in bytes or HEX encoded string corresponding hex flag.
"""
tx_hash_list = [h if isinstance(h, bytes) else s2rh(h) for h in tx_hash_list]
branches = []
if len(tx_hash_list) == 1:
return []
tx_hash_list.pop(0)
while True:
branches.append(tx_hash_list.pop(0))
new_hash_list = list()
while tx_hash_list:
h1 = tx_hash_list.pop(0)
try:
h2 = tx_hash_list.pop(0)
except:
h2 = h1
new_hash_list.append(double_sha256(h1 + h2))
if len(new_hash_list) > 1:
tx_hash_list = new_hash_list
else:
if new_hash_list:
branches.append(new_hash_list.pop(0))
return branches if not hex else [hexlify(h).decode() for h in branches]
def merkleroot_from_branches(merkle_branches, coinbase_hash, hex=True):
"""
Calculate merkle root from merkle branches and coinbase transacton hash
:param merkle_branches: list merkle branches in bytes or HEX encoded string.
:param coinbase_hash: list coinbase transaction hash in bytes or HEX encoded string.
:param hex: (optional) If set to True return result in HEX format, by default is True.
:return: merkle root in bytes or HEX encoded string corresponding hex flag.
"""
merkle_root = coinbase_hash if not isinstance(coinbase_hash, str) else unhexlify(coinbase_hash)
for h in merkle_branches:
if type(h) == str:
h = unhexlify(h)
merkle_root = double_sha256(merkle_root + h)
return merkle_root if not hex else hexlify(merkle_root).decode()
# Difficulty
def bits_to_target(bits):
"""
Calculate target from bits
:param bits: HEX string, bytes string or integer representation of bits.
:return: integer.
"""
if type(bits) == str:
bits = unhexlify(bits)
if type(bits) == bytes:
return int.from_bytes(bits[1:], 'big') * (2 ** (8 * (bits[0] - 3)))
else:
shift = bits >> 24
target = (bits & 0xffffff) * (1 << (8 * (shift - 3)))
return target
def target_to_difficulty(target):
"""
Calculate difficulty from target
:param target: integer.
:return: float.
"""
return 0x00000000FFFF0000000000000000000000000000000000000000000000000000 / target
def bits_to_difficulty(bits):
"""
Calculate difficulty from bits
:param bits: HEX string, bytes string or integer representation of bits.
:return: integer.
"""
return target_to_difficulty(bits_to_target(bits))
def difficulty_to_target(difficulty):
"""
Calculate target from difficulty
:param target: integer.
:return: float.
"""
return int(0x00000000FFFF0000000000000000000000000000000000000000000000000000 / difficulty)