#A stratum compatible miniminer #based in the documentation #https://slushpool.com/help/#!/manual/stratum-protocol #2017-2019 Martin Nadal https://martinnadal.eu import socket import json import hashlib import binascii from pprint import pprint import time import random address = '1GvSP13YjQAu9VAa8J1Hvbc4n3N8kUE3Ch' nonce = hex(random.randint(0,2**32-1))[2:].zfill(8) host = 'solo.ckpool.org' port = 3333 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 https://bitcoin.stackexchange.com/a/36228/44319 target = (nbits[2:]+'00'*(int(nbits[:2],16) - 3)).zfill(64) print('nbits:{} target:{}\n'.format(nbits,target)) extranonce2 = '00'*extranonce2_size 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)) 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 < target : print('success!!') payload = '{"params": ["'+address+'", "'+job_id+'", "'+extranonce2 \ +'", "'+ntime+'", "'+nonce+'"], "id": 1, "method": "mining.submit"}\n' sock.sendall(payload) print(sock.recv(1024)) else: print('failed mine, hash is greater than target') sock.close()