Instructions
Requirements and Specifications
Source Code
POW CHECK
import sys
import hashlib
def hash(bytes):
hex = hashlib.sha256(bytes).hexdigest()
return hex
def get_leading_zeros(hex):
# Take each element of the hex and convert to binary
bin_str = hex_to_bin(hex)
# Convert to binary
# Get the first n_leading bits
# Count until there is no leading zero
counter = 0
for c in bin_str:
if c == '0':
counter += 1
else:
break
return counter
def hex_to_bin(hex):
bin_str = ""
hex_int = int('1'+hex, 16)
c_bin = bin(hex_int)[3:].zfill(4)
bin_str = str(c_bin)
# for c in hex:
# c_int = int(c, 16)
# c_bin = bin(c_int)[2:].zfill(4)
# bin_str += str(c_bin)
return bin_str
if __name__ == '__main__':
# Variable to ccount the number of tests passed
tests_passed = 0
# Get file from command line arguments
if len(sys.argv) < 3:
print("You must give a filename and the number of leading zeros.")
sys.exit(0)
powheader = sys.argv[1]
file = sys.argv[2]
# First, read the hex in the file
f = open(file, 'rb')
bytes = f.read()
initial_hash = hash(bytes)
# Now open the headerfile
header = open(powheader, 'r')
# Read lines
lines = header.readlines()
# The initial hash is in the second file (index 1)
header_initial_hash = lines[1].strip().split(' ')[1]
# The hash is in the 3rd line
header_hash = lines[3].strip().split(' ')[1]
# Get reported number of leading zeros
zeros_reported = int(lines[4].strip().split(' ')[1])
# Get proof of work
reported_pow = lines[2].strip().split(' ')[1]
# Check that initial hashes are the same
if header_initial_hash == initial_hash:
print("PASSED:", "initial file hashes match")
tests_passed += 1
else:
print("ERROR:", "initial hashes don't match")
print("\thash in header:", header_initial_hash)
print("\tfile hash:", initial_hash)
# Check the number of leading bits
# Take the original content of the file and append the new pow
file_text = bytes.decode('utf-8') + reported_pow
new_bytes = file_text.encode('utf-8')
new_hash = hash(new_bytes)
new_hash_bin = hex_to_bin(new_hash)
# Compute number of leading zeros
zeros = get_leading_zeros(new_hash_bin)
if zeros == zeros_reported:
print("PASSED:","leading bits is correct")
tests_passed += 1
else:
print("ERROR:",f"Leading zero-bits value: {zeros_reported} but hash has {zeros} leading zero bits")
# Now, check for final hash
if new_hash == header_hash:
print("PASSED:", "pow hash matches Hash header")
tests_passed += 1
else:
print("ERROR:", "pow hash does not match Hash header")
print("\texpected:", new_hash)
print("\tfile hash:", header_hash)
if tests_passed == 3:
print("pass")
else:
print("fail")
POW CREATE
import hashlib
import itertools
import string
import time
import sys
def hex_to_bin(hex):
bin_str = ""
hex_int = int('1'+hex, 16)
c_bin = bin(hex_int)[3:].zfill(4)
bin_str = str(c_bin)
# for c in hex:
# c_int = int(c, 16)
# c_bin = bin(c_int)[2:].zfill(4)
# bin_str += str(c_bin)
return bin_str
def hash(bytes):
hex = hashlib.sha256(bytes).hexdigest()
return hex
def iter_all_strings(count):
# Get all chars
charIds = range(33, 126+1) # ascii values for all characters
ascii_chars = [chr(id) for id in charIds if id != 34]
for s in itertools.product(ascii_chars, repeat=count):
yield "".join(s)
def pow_text(hex, text, n_leading):
#hex = hash(text)
# Take the first n_leading
charIds = range(33, 126+1) # ascii values for all characters
current = ''
n = n_leading//4-1
if n < 1:
n = 1
iters = 1
F = ""
found = False
while not found:
# Get all combinations of chars of length 'n'. Append each one to the string and check hash
for s in iter_all_strings(n):
F = s
new_text = text + s
# Get hash
bytes =new_text.encode('utf-8')
hex = hash(bytes)
# Take each element of the hex and convert to binary
bin_str = hex_to_bin(hex)
# Convert to binary
# Get the first n_leading bits
leading_bits = bin_str[:n_leading]
leading_zeros = get_leading_zeros(hex)
#if leading_bits == '0'*n_leading:
if leading_zeros >= n_leading:
found = True
break
iters = iters + 1
n = n + 1
return F, iters
def get_leading_zeros(hex):
# Take each element of the hex and convert to binary
bin_str = hex_to_bin(hex)
# Convert to binary
# Get the first n_leading bits
# Count until there is no leading zero
counter = 0
for c in bin_str:
if c == '0':
counter += 1
else:
break
return counter
if __name__ == '__main__':
# Get file from command line arguments
if len(sys.argv) < 3:
print("You must give a filename and the number of leading zeros.")
sys.exit(0)
n_leading = int(sys.argv[1])
filename = sys.argv[2]
file = open(filename, 'rb')
bytes = file.read()
text = bytes.decode('utf-8')
initial_hash = hash(bytes)
start_time = time.time()
pow, iters = pow_text(initial_hash, text, n_leading)
end_time = time.time()
new_text = text + pow
bytes = new_text.encode('utf-8')
final_hash = hash(bytes)
print("File:", filename)
print("Initial-hash:", initial_hash)
print("Proof-of-work:", pow)
print("Hash:", final_hash)
print("Leading-zero-bits:", get_leading_zeros(final_hash))
print("Iterations:", iters)
print("Compute-time:", end_time-start_time)
# text = 'The grass is green'
# start_time = time.time()
# F, iters = pow_text(text, 31)
# end_time = time.time()
# print(F, iters)
# print("Execution time: {:.2f} (s)".format(end_time-start_time))