diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2014-07-29 09:58:14 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2014-07-29 09:58:14 +0200 |
commit | 403c1bf0fbff2c7cb20afbd4413f36267029deef (patch) | |
tree | 7aa13852bbf1c4075567df17ae12d2c9846eda7a /contrib/pyminer/pyminer.py | |
parent | 29203228710de3e180914c1d66f48dd7e41270a0 (diff) |
contrib: remove getwork-based pyminer
As the `getwork` API doesn't exist anymore, currently this script is useless.
It would be nice to have a `getblocktemplate`-based Python example of a
miner, but there is no point in keeping this one around except to
confuse people.
Diffstat (limited to 'contrib/pyminer/pyminer.py')
-rwxr-xr-x | contrib/pyminer/pyminer.py | 269 |
1 files changed, 0 insertions, 269 deletions
diff --git a/contrib/pyminer/pyminer.py b/contrib/pyminer/pyminer.py deleted file mode 100755 index 706a10b39d..0000000000 --- a/contrib/pyminer/pyminer.py +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2011 The Bitcoin developers -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# - -import sys -from multiprocessing import Process -import time -import struct -import hashlib -import base64 -import re -import httplib -import json - -ERR_SLEEP = 15 -MAX_NONCE = 1000000L - -settings = {} - - -class BitcoinRPC: - object_id = 1 - - def __init__(self, host, port, username, password): - authpair = "{0}:{1}".format(username, password) - self.authhdr = "Basic {0}".format(base64.b64encode(authpair)) - self.conn = httplib.HTTPConnection(host, port, strict=False, timeout=30) - - def rpc(self, method, params=None): - self.object_id += 1 - obj = {'version' : '1.1', - 'method' : method, - 'id' : self.object_id, - 'params' : params or []} - - self.conn.request('POST', '/', json.dumps(obj), - { 'Authorization' : self.authhdr, - 'Content-type' : 'application/json' }) - - resp = self.conn.getresponse() - - if resp is None: - print("JSON-RPC: no response") - return None - - body = resp.read() - resp_obj = json.loads(body) - - if resp_obj is None: - print("JSON-RPC: cannot JSON-decode body") - return None - - if 'error' in resp_obj and resp_obj['error'] != None: - return resp_obj['error'] - - if 'result' not in resp_obj: - print("JSON-RPC: no result in object") - return None - - return resp_obj['result'] - - def getblockcount(self): - return self.rpc('getblockcount') - - def getwork(self, data=None): - return self.rpc('getwork', data) - -def uint32(x): - return x & 0xffffffffL - -def bytereverse(x): - return uint32(( ((x) << 24) | (((x) << 8) & 0x00ff0000) | - (((x) >> 8) & 0x0000ff00) | ((x) >> 24) )) - -def bufreverse(in_buf): - out_words = [] - - for i in range(0, len(in_buf), 4): - word = struct.unpack('@I', in_buf[i:i+4])[0] - out_words.append(struct.pack('@I', bytereverse(word))) - - return ''.join(out_words) - -def wordreverse(in_buf): - out_words = [] - - for i in range(0, len(in_buf), 4): - out_words.append(in_buf[i:i+4]) - - out_words.reverse() - - return ''.join(out_words) - - -class Miner: - def __init__(self, id): - self.id = id - self.max_nonce = MAX_NONCE - - def work(self, datastr, targetstr): - # decode work data hex string to binary - static_data = datastr.decode('hex') - static_data = bufreverse(static_data) - - # the first 76b of 80b do not change - blk_hdr = static_data[:76] - - # decode 256-bit target value - targetbin = targetstr.decode('hex') - targetbin = targetbin[::-1] # byte-swap and dword-swap - targetbin_str = targetbin.encode('hex') - target = long(targetbin_str, 16) - - # pre-hash first 76b of block header - static_hash = hashlib.sha256() - static_hash.update(blk_hdr) - - for nonce in xrange(self.max_nonce): - - # encode 32-bit nonce value - nonce_bin = struct.pack("<I", nonce) - - # hash final 4b, the nonce value - hash1_o = static_hash.copy() - hash1_o.update(nonce_bin) - hash1 = hash1_o.digest() - - # sha256 hash of sha256 hash - hash_o = hashlib.sha256() - hash_o.update(hash1) - hash = hash_o.digest() - - # quick test for winning solution: high 32 bits zero? - if hash[-4:] != '\0\0\0\0': - continue - - # convert binary hash to 256-bit Python long - hash = bufreverse(hash) - hash = wordreverse(hash) - - hash_str = hash.encode('hex') - long_hash = long(hash_str, 16) - - # proof-of-work test: hash < target - if long_hash < target: - print(time.asctime(), "PROOF-OF-WORK found: " - "{0:064x}".format(long_hash)) - return (nonce + 1, nonce_bin) - else: - print(time.asctime(), "PROOF-OF-WORK false" - "positive {0:064x}".format(long_hash)) - - return (nonce + 1, None) - - def submit_work(self, rpc, original_data, nonce_bin): - nonce_bin = bufreverse(nonce_bin) - nonce = nonce_bin.encode('hex') - solution = original_data[:152] + nonce + original_data[160:256] - param_arr = [ solution ] - result = rpc.getwork(param_arr) - - print(time.asctime(), "--> Upstream RPC result:", result) - - def iterate(self, rpc): - work = rpc.getwork() - - if work is None: - time.sleep(ERR_SLEEP) - return - - if 'data' not in work or 'target' not in work: - time.sleep(ERR_SLEEP) - return - - time_start = time.time() - - (hashes_done, nonce_bin) = self.work(work['data'], - work['target']) - - time_end = time.time() - time_diff = time_end - time_start - - self.max_nonce = long( - (hashes_done * settings['scantime']) / time_diff) - - if self.max_nonce > 0xfffffffaL: - self.max_nonce = 0xfffffffaL - - if settings['hashmeter']: - print("HashMeter({:d}): {:d} hashes, {:.2f} Khash/sec".format( - self.id, hashes_done, (hashes_done / 1000.0) / time_diff)) - - if nonce_bin is not None: - self.submit_work(rpc, work['data'], nonce_bin) - - def loop(self): - rpc = BitcoinRPC(settings['host'], settings['port'], - settings['rpcuser'], settings['rpcpass']) - - if rpc is not None: - - while True: - self.iterate(rpc) - - self.conn.close() - - -def miner_thread(id): - miner = Miner(id) - miner.loop() - -if __name__ == '__main__': - if len(sys.argv) != 2: - print("Usage: pyminer.py CONFIG-FILE") - sys.exit(1) - - with open(sys.argv[1]) as f: - - for line in f: - # skip comment lines - m = re.search('^\s*#', line) - if m: - continue - - # parse key=value lines - m = re.search('^(\w+)\s*=\s*(\S.*)$', line) - if m is None: - continue - - settings[m.group(1)] = m.group(2) - - settings.setdefault('host', '127.0.0.1') - settings.setdefault('port', 8332) - settings.setdefault('threads', 1) - settings.setdefault('hashmeter', 0) - settings.setdefault('scantime', 30L) - - if 'rpcuser' not in settings or 'rpcpass' not in settings: - print("Missing username and/or password in cfg file") - sys.exit(1) - - settings['port'] = int(settings['port']) - settings['threads'] = int(settings['threads']) - settings['hashmeter'] = int(settings['hashmeter']) - settings['scantime'] = long(settings['scantime']) - - thread_list = [] - - for thread_id in range(settings['threads']): - p = Process(target=miner_thread, args=(thread_id,)) - p.start() - thread_list.append(p) - time.sleep(1) # stagger threads - - print(settings['threads'], "mining threads started") - - print(time.asctime(), "Miner Starts - {0}:{1}".format(settings['host'], - settings['port'])) - try: - for thread_process in thread_list: - thread_process.join() - except KeyboardInterrupt: - pass - - print(time.asctime(), "Miner Stops - {0}:{1}".format(settings['host'], - settings['port'])) |