Instantly share code, notes, and snippets.

Embed
What would you like to do?
Showing of Bitcoin's Proof of Work difficulty is calculated and changed.
import datetime
###################################################################
#
# Showing the way bits, difficulty, target, and hash work together.
#
###################################################################
print "Calculating target from bits, verifying the block's hash is valid, and verify the calculated difficulty."
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
def run_difficulty_information(bits, block_difficulty, block_hash):
target = get_target_from_bits(bits)
padded_hex_target = pad_leading_zeros(hex(target))
#making sure that the block's hash is less than the target
block_hash_hex = '0x%s' % block_hash
block_hash_int = int(block_hash, 16)
assert block_hash_hex < padded_hex_target
assert block_hash_int < target
print 'Padded target hex: %s' % padded_hex_target
print 'Block hash in hex: %s' % block_hash_hex
calculated_difficulty = get_difficulty_from_bits(bits)
allowed_error = 0.01
assert abs(float(block_difficulty) - calculated_difficulty) <= allowed_error
print 'Difficulty: %s' % block_difficulty
print 'Calculated Difficulty: %s' % calculated_difficulty
print #print that new line
#genesis block
print 'Block 0'
difficulty = '1.0'
bits = '486604799'
block_hash = '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'
run_difficulty_information(bits, difficulty, block_hash)
#first block with difficulty not 1.0
print 'Block 32256'
difficulty = '1.18'
bits = '486594666'
block_hash = '000000004f2886a170adb7204cb0c7a824217dd24d11a74423d564c4e0904967'
run_difficulty_information(bits, difficulty, block_hash)
#block 11138
print 'Block 111388'
difficulty = '55589.52'
bits = '453062093'
block_hash = '00000000000019c6573a179d385f6b15f4b0645764c4960ee02b33a3c7117d1e'
run_difficulty_information(bits, difficulty, block_hash)
#block 493955
print 'Block 493955'
difficulty = '1364422081125.15'
bits = '402705995'
block_hash = '000000000000000000af4c179fcd65679f659947b0af164433fc1b99a186ff48'
run_difficulty_information(bits, difficulty, block_hash)
################################################################
#
# Shows how difficulty is changed when BLOCK_NUMBER % 2016 == 0
#
################################################################
print "Adjusting difficulty after every 2016 blocks"
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
TARGET_TIMESPAN = 1209600
def change_target(prev_bits, starting_time_secs, prev_time_secs):
old_target = get_target_from_bits(int(prev_bits))
time_span = prev_time_secs - starting_time_secs
time_span_seconds = int(time_span.total_seconds())
new_target = old_target
new_target *= time_span_seconds
new_target /= TARGET_TIMESPAN
return new_target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment