import struct
import binascii

def get_target_from_bits(bits):
    if type(bits) == str:
        bits = int(bits)
    shift = bits >> 24
    value = bits & 0x007fffff
    value <<= 8 * (shift - 3)
    return value

def get_difficulty_from_bits(bits):
    difficulty_one_target = 0x00ffff * 2 ** (8 * (0x1d - 3))
    target = get_target_from_bits(bits)
    calculated_difficulty = difficulty_one_target / float(target)
    return calculated_difficulty

def get_bits_from_target(target):
    bitlength = target.bit_length() + 1 #look on bitcoin cpp for info
    size = (bitlength + 7) / 8
    value = target >> 8 * (size - 3)
    value |= size << 24 #shift size 24 bits to the left, and taks those on the front of compact
    return value

def pad_leading_zeros(hex_str):
    hex_num_chars = hex_str[2:-1]
    num_zeros_needed = 64 - len(hex_num_chars)
    padded_hex_str = '0x%s%s' % ('0' * num_zeros_needed, hex_num_chars)
    return padded_hex_str

# https://en.bitcoin.it/wiki/Difficulty
#DO NOT CHANGE THIS SECTION
bits = 0x1d00ffff
exponent = bits >> 24
coefficient = bits & 0xffffff
#print "Hex bits:", format(bits,'02x')
#print "Numeric bits:", bits
#print "exponent:", exponent
#print "coefficient: ", coefficient
target_hexstr = '%064x' % (coefficient * (1<<(8*(exponent - 3))))
#print "bit shifted target_hexster:", target_hexstr
target_hexstr = '%064x' % (coefficient * 2**(8*(exponent - 3)))
#print "NUMERATOR:  difficulty_1_target"
#print "calculated  target_hexster:", target_hexstr
target_str = target_hexstr.decode('hex')
diff1 = float.fromhex(target_hexstr)
#print "Difficulty1:", diff1

print

# CHANGE THIS:  THIS IS THE BITS TO CALCULATE:
#bits = 0x1b0404cb #from difficulty web page
#bits = 0x1fffffff
#bits = 0x1d00ffff #difficulty on TESTNET
#bits = 0x207fffff #difficulty on REGTEST
#bits = 0x1903a30c #from Antonopoulos p. 235
#bits = 0x201fffff #playground
#bits =  0x1e080000 #playground
bits =  0x1e200000 #playground
print "CALCULATING for Hex bits:", format(bits,'02x')
print "Numeric bits:",bits
exponent = bits >> 24
coefficient = bits & 0xffffff
print "exponent:", hex(exponent)
print "coefficient: ", hex(coefficient)
print "coefficient: ", format(coefficient,'06x')
target_hexstr2 = '%064x' % (coefficient * 2**(8*(exponent - 3)))
#print "DENOMINATOR:  current_target"
print "target_hexster:", target_hexstr2
print "target decimal:", int(target_hexstr2,16)
target_str2 = target_hexstr2.decode('hex')
diff2 = float.fromhex(target_hexstr2)
#print "Difficulty2:",diff2

print
d = diff1/diff2
print '******************************************************'
print "DIFFICULTY CALCULATED: %10.12f (bdiff)" % d
print '******************************************************'
print
#print "Average Network Hash Rate over previous 2016 blocks was %6.2f Ghashs/second" % ((d * 2**32) / 600 / 10**9)


#b = diff1/d
##s = format(int(b), 'x')
#print "Target Reversed from Difficulty: ",s.zfill(64)
#bitsback = get_bits_from_target(int(s,16))
#print "Hex bits reversed from Target value: %x" % bitsback
#print "Int bits reversed from Target value: %d" % bitsback
#print
##print "deffunc target:",get_target_from_bits(bits)
##print "deffunc target hex:",pad_leading_zeros(hex(get_target_from_bits(bits)))
#print
#print '******************************************************'

print "USING FUNCTIONS:"
target = get_target_from_bits(bits)
print "Target value:",target
difficulty = get_difficulty_from_bits(bits)
print "difficulty: ",difficulty
print "funcdiff: {0:,f}".format(difficulty)
bitsback = get_bits_from_target(target)
print "Numeric bits from target:",bitsback
print "hex bits from target: %x" % bitsback

