'Python bitcoin miner not letting me define variable after mine

I have been trying to create a python bitcoin miner, that ACTUALLY puts the coins somewhere, so thats the first part of my quesiton, and the second part is how do I fix this error?

This is all of my code:

import hashlib
import time

max_nonce = 2 ** 32 # 4 billion

def proof_of_work(header, difficulty_bits):

    # calculate the difficulty target
    target = 2 ** (256-difficulty_bits)

    for nonce in range(max_nonce):
        hash_result = hashlib.sha256(str(header)+str(nonce)).hexdigest()

        # check if this is a valid result, below the target
        if int(hash_result, 16) < target:
            print ("Success with nonce %d" % nonce)
            print ("Hash is %s" % hash_result)
            return (hash_result,nonce)

    print ("Failed after %d (max_nonce) tries" % nonce)
    return nonce


if __name__ == '__main__':

    nonce = 0
    hash_result = ''

    # difficulty from 0 to 31 bits
    for difficulty_bits in range(32):

        difficulty = 2 ** difficulty_bits
        print ("Difficulty: %ld (%d bits)" % (difficulty, difficulty_bits))

        print ("Starting search...")

        # checkpoint the current time
        start_time = time.time()

        # make a new block which includes the hash from the previous block
        # we fake a block of transactions - just a string
        new_block = 'test block with transactions' + hash_result

        # find a valid nonce for the new block
        (hash_result, nonce) = proof_of_work((new_block, difficulty_bits).hexdigest()

        # checkpoint how long it took to find a result
        end_time = time.time()

The line above this, The end_time seems to get an error, with no definition to what the error is. Please help.

Please note that I have tried a great deal of commenting out a bunch of things, changing code, and this is in python 3



Solution 1:[1]

I'm writing this as an answer because of the many issues.

First, hashllib requires byte strings. You would need

    hash_result = hashlib.sha256((header+str(nonce)).encode('utf-8')).hexdigest()

Second, you're doing proof_of_work(...).hexdigest(), but that function isn't returning a hash object. You are already calling hexdigest. Your function either returns a 2-tuple, or a nonce. You want to remove the hexdigest call:

        # find a valid nonce for the new block
        (hash_result, nonce) = proof_of_work((new_block, difficulty_bits)

And, in the final line of proof_of_work change

    return nonce

to

    return (None, nonce)

Next, you are converting the nonce to decimal digits to tack it on to the block. That is completely wrong. The nonce needs to be a 4-byte value. Something like:

    enonce = struct.pack('I', nonce)
    hash_result = hashlib.sha256(header.encode('utf-8')+enonce).hexdigest()

Finally, this whole thing is silly. Have you timed that inner loop to see how long it takes? On my box, it takes about 500 microseconds per loop. To run that 4 billion times would require a month and a half. To repeat that for all 32 difficult values would make it take 4 years.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tim Roberts