2.9 PROOF OF WORK
EXERCISE 2.9 PROOF OF WORK
Write a program that feeds a counter in SHA-256, taking the output hash and converting it to an integer (we did this earlier before converting to binary). Have the program repeat until it finds a hash that is less than a target number. The target number should start out pretty big, like \(2^{255}\). To make this more like blockchain, include some arbitrary bytes to be combined with the counter.
# ex2_9.py
import hashlib
import secrets
def convert_to_decimal(number: str, base: int) -> int:
'''
Taken from https://github.com/noahabe/numrep/blob/master/numrep.py
Changes the first parameter (which is expected to be a hexadecimal number)
into a base 10 integer.
'''
########### [FOR HEXADECIMAL ONLY]############
if base == 16:
convertion_table = {
'A': 10,
'B': 11,
'C': 12,
'D': 13,
'E': 14,
'F': 15,
}
def CONVERT(x: str): return convertion_table[x.upper()]
#############################################
decimal = 0
position = len(number)-1
for single_digit in number:
if single_digit.isalpha():
single_digit = CONVERT(single_digit)
decimal += int(single_digit) * base**position
position -= 1
return decimal
def proof_of_work(random_block: bytes, target_number_exp: int) -> dict[str, str | bytes]:
counter = 0
target_number = 2 ** target_number_exp
try:
while True:
h = hashlib.sha256()
h.update(random_block)
h.update(str(counter).encode('utf-8'))
if convert_to_decimal(h.hexdigest(), 16) < target_number:
return {
"nonce": str(counter),
"hash": h.hexdigest(),
"random_block": random_block[0:3],
"target_number": f"2^{target_number_exp}"
}
counter += 1
except KeyboardInterrupt:
print("Exiting...")
exit()
def main(start_target_number_exponent: int = 255, end_target_number_exponent: int = 250):
# the random_block makes it look more like blockchain
random_block = secrets.token_bytes(1000) # 1 Kilobyte of random bytes.
for target_number_exp in range(start_target_number_exponent, end_target_number_exponent, -1):
retval = proof_of_work(random_block, target_number_exp)
print(retval)
if __name__ == '__main__':
start_target_number_exponent = int(input("Start target number exponent: "))
end_target_number_exponent = int(input("End target number exponent: "))
main(start_target_number_exponent, end_target_number_exponent)The following video shows the execution of the above script:
