Post
Topic
Board Development & Technical Discussion
Re: Python based Solo miner for CPU | Learn Basic Bitcoin Mining | Just for fun
by
Sha256explorer
on 20/04/2023, 20:56:20 UTC
I made some small improvements:
1) I called the noncework function 2**32 times, not just 10 million million times
2) every time i called the noncework function, i passed the loop value k, using that number as the nounce and not a random number

I could also have used the time parameter, another 5000 or 6000 times cycle, so that the root merkle only resets once every 5000*2**32.

if we had a 100 TH/S asic instead of a CPU, it would have to recalculate the nounce every 4 or 5 seconds, if I'm not mistaken.

Code:
# -*- coding: utf-8 -*-

import socket
import json
import hashlib
import binascii
from pprint import pprint
import random


address = 'YourBitcoinAddress'
nonce   = hex(0)[2:].zfill(8)
host    = 'solo.ckpool.org'
port    = 3333
#host    = 'pool.mainnet.bitcoin-global.io'
#port    = 9223

def main():
    print("address:{} nonce:{}".format(address,nonce))
    print("host:{} port:{}".format(host,port))
   
    sock    = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((host,port))
   
    #server connection
    sock.sendall(b'{"id": 1, "method": "mining.subscribe", "params": []}\n')
    lines = sock.recv(1024).decode().split('\n')
    response = json.loads(lines[0])
    sub_details,extranonce1,extranonce2_size = response['result']
   
    #authorize workers
    sock.sendall(b'{"params": ["'+address.encode()+b'", "password"], "id": 2, "method": "mining.authorize"}\n')
   
    #we read until 'mining.notify' is reached
    response = b''
    while response.count(b'\n') < 4 and not(b'mining.notify' in response):
        response += sock.recv(1024)
   
   
    #get rid of empty lines
    responses = [json.loads(res) for res in response.decode().split('\n') if len(res.strip())>0 and 'mining.notify' in res]
    pprint(responses)
   
    job_id,prevhash,coinb1,coinb2,merkle_branch,version,nbits,ntime,clean_jobs \
        = responses[0]['params']
   
    target = (nbits[2:]+'00'*(int(nbits[:2],16) - 3)).zfill(64)

    print('nbits:{} target:{}\n'.format(nbits,target))
   
    # extranonce2 = '00'*extranonce2_size
    extranonce2 = hex(random.randint(0,2**32-1))[2:].zfill(2*extranonce2_size)      # create random
   
    coinbase = coinb1 + extranonce1 + extranonce2 + coinb2
    coinbase_hash_bin = hashlib.sha256(hashlib.sha256(binascii.unhexlify(coinbase)).digest()).digest()
   
    print('coinbase:\n{}\n\ncoinbase hash:{}\n'.format(coinbase,binascii.hexlify(coinbase_hash_bin)))
    merkle_root = coinbase_hash_bin
    for h in merkle_branch:
        merkle_root = hashlib.sha256(hashlib.sha256(merkle_root + binascii.unhexlify(h)).digest()).digest()
   
    merkle_root = binascii.hexlify(merkle_root).decode()
   
    #little endian
    merkle_root = ''.join([merkle_root[i]+merkle_root[i+1] for i in range(0,len(merkle_root),2)][::-1])
   
    print('merkle_root:{}\n'.format(merkle_root))
   
    def noncework(k):
        nonce   = hex(k)[2:].zfill(8)   #hex(int(nonce,16)+1)[2:]
        blockheader = version + prevhash + merkle_root + nbits + ntime + nonce +\
            '000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000'
       
        # print('blockheader:\n{}\n'.format(blockheader))
       
        hash = hashlib.sha256(hashlib.sha256(binascii.unhexlify(blockheader)).digest()).digest()
        hash = binascii.hexlify(hash).decode()
        # print('hash: {}'.format(hash))
        if(hash[:5] == '00000'): print('hash: {}'.format(hash))
        if hash < target :
    #    if(hash[:10] == '0000000000'):
            print('success!!')
            print('hash: {}'.format(hash))
            payload = bytes('{"params": ["'+address+'", "'+job_id+'", "'+extranonce2 \
                +'", "'+ntime+'", "'+nonce+'"], "id": 1, "method": "mining.submit"}\n', 'utf-8')
            sock.sendall(payload)
            print(sock.recv(1024))
            input("Press Enter to continue...")
    #    else:
    #        print('failed mine, hash is greater than target')
   
    for k in range(2**32):
        noncework(k)
    print("Finished 10M Search. Regaining Information.")
    sock.close()
    main()

main()