I am working on a project where I am trying to create a very simple blockchain-based cryptocurrency. This is an oversimplified version of the way I try to hash a block object (obviously the fields of the Block
class are much more complicated, but this is the main idea):
from Crypto.Hash import SHA
import json
from collections import OrderedDict
from random import random
class Block(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def to_dict(self):
d = OrderedDict({
'x' : self.x,
'y' : self.y,
'z' : self.z
})
return d
def json(self):
return json.dumps(self.to_dict())
def hash(self):
return SHA.new(self.json().encode('utf8')).hexdigest()
# driver code to test hashing
while True:
x, y, z = [random() for _ in range(3)]
b = Block(x, y, z)
if not bin(int(b.hash(), 16)).startswith('0b1'):
break
The above driver program loops forever. The problem is that (regardless of the number and/or value of the fields) the hash ALWAYS starts with 0b1
, which messes with the whole idea of mining difficulty and proof-of-work. More importantly, though, this is not the expected behavior of a hashing function. What do I miss?
Python doesn't zero pad the front of binary numbers by default, so the first digit of any binary number will be one.
>>> bin(1)
'0b1'
>>> bin(2)
'0b10'
>>> bin(3)
'0b11'
>>> bin(8)
'0b1000'
If you want fixed with binary strings, use string formatting
>>> "{:04b}".format(1)
'0001'
>>> "{:04b}".format(2)
'0010'
>>> "{:04b}".format(8)
'1000'
>>> "{:04b}".format(15)
'1111'
Otherwise, just use a binary and (&
) to check if the specific bit is set.
>>> bool(1 & 0b1000)
False
>>> bool(3 & 0b1000)
False
>>> bool(8 & 0b1000)
True
>>> bool(15 & 0b1000)
True