Spaces:
Runtime error
Runtime error
| #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() |