Skip to content

Instantly share code, notes, and snippets.

@Rustem
Last active April 26, 2018 09:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Rustem/ba4095a3b1cdb36481d1e005895e96e8 to your computer and use it in GitHub Desktop.
Save Rustem/ba4095a3b1cdb36481d1e005895e96e8 to your computer and use it in GitHub Desktop.
import hashlib
import binascii
"""
Simplified implementation of HashCash proof-of-work algorithm.
"""
difficulty = 3
def hash_msg(message, hex=False):
"""
Return sha-256 hash from any binary message
:param message: binary string
:type message: bytes
:param hex: flag, that signals to encode result in hex
:return: sha-256 hash
:rtype: bytes|str
"""
hash_algo = hashlib.sha256()
hash_algo.update(message)
digest = hash_algo.digest()
if not hex:
return digest
return binascii.hexlify(digest).decode()
def check_difficulty(pow_hash):
"""
Checks whether proof-of-work hash has {difficulty} number of leading zeroes.
:param pow_hash: proof-of-work hash
:type pow_hash: str
:return: true if check succeeds, otherwise - false
:rtype: bool
"""
n = len(pow_hash)
cnt = 0
for i in range(n):
if pow_hash[i] != '0':
break
cnt += 1
return cnt >= difficulty
def proof_of_work(mining_hash):
"""
Simplified hashimoto proof-of-work.
:param mining_hash: mining hash
:type mining_hash: str
:return: tuple of nonce and proof-of-work hash
:rtype: tuple[int, str]
"""
pow_hash, nonce = None, -1
while True:
byte_msg = ("%s%s" % (nonce + 1, mining_hash)).encode()
# Prepare proof-of-work sha256 hash with candidate nonce
pow_hash = hash_msg(byte_msg, hex=True)
# Check if the resulting hash is valid pow hash
isvalid = check_difficulty(pow_hash)
nonce += 1
if isvalid:
break
if isvalid:
return nonce, pow_hash
return None, None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment