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