You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

41 lines
1.8 KiB

import hashlib
from .support import bintohex
def get_pow(data, noncelen=10, hashfn=hashlib.sha512,
hashlen=64, nbits=1, truncate=0, maxiterations=10**8):
""" Arguments:
data - a string of bytes.
noncelen - an int, the number of additional bytes to be appended
to the bytestring `data` which will be used for grinding.
hashfn - a function that outputs a finalized hash state that can
be converted to a bytestring with .digest() (see hashlib).
hashlen - the length of the bytestring created with the .digest()
call just mentioned.
nbits - an integer, the number of bits of proof of work required.
truncate - an integer number of bytes to be truncated from the end
of the hash digest created.
maxiterations - an integer, how many grinding attempts maximum allowed
to attempt to reach the target, before giving up.
Returns:
(nonceval, pow-preimage, niterations)
where pow-preimage is data+nonce-in-bytes
or
(None, failure-reason, None)
"""
maxbits = (hashlen-truncate)*8
pow_target = 2 ** (maxbits - nbits)
# note since we are using a trivial counter, two
# elements of returned tuple are the same, this needn't be the case.
for nonceval in range(maxiterations):
x = data + bintohex(nonceval.to_bytes(noncelen, "big")).encode(
"utf-8")
pow_candidate = hashfn(x).digest()[:truncate]
if int.from_bytes(pow_candidate, "big") < pow_target:
return (nonceval, x, nonceval)
return (None, "exceeded max-iterations: {}".format(maxiterations), None)
def verify_pow(data, hashfn=hashlib.sha512, hashlen=64, nbits=1, truncate=0):
return int.from_bytes(hashfn(data).digest()[:truncate],
"big") < 2 ** ((hashlen - truncate) * 8 - nbits)