diff --git a/contrib/README.md b/contrib/README.md index 63b1875d3..dae975e9e 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -19,10 +19,6 @@ Contains the script `github-merge.sh` for merging github pull requests securely ### [Linearize](/contrib/linearize) ### Construct a linear, no-fork, best version of the blockchain. -### [PyMiner](/contrib/pyminer) ### - -This is a 'getwork' CPU mining client for Bitcoin. It is pure-python, and therefore very, very slow. The purpose is to provide a reference implementation of a miner in order to study and develop other mining programs. - ### [Qos](/contrib/qos) ### A Linux bash script that will set up traffic control (tc) to limit the outgoing bandwidth for connections to the Bitcoin network. This means one can have an always-on bitcoind instance running, and another local bitcoind/bitcoin-qt instance which connects to this node and receives blocks from it. diff --git a/contrib/pyminer/README.md b/contrib/pyminer/README.md deleted file mode 100644 index 3b20f2fde..000000000 --- a/contrib/pyminer/README.md +++ /dev/null @@ -1,8 +0,0 @@ -### PyMiner ### - -This is a 'getwork' CPU mining client for Bitcoin. It is pure-python, and therefore very, very slow. The purpose is to provide a reference implementation of a miner, for study. - -### Other Resources ### - -- [BitcoinTalk Thread](https://bitcointalk.org/index.php?topic=3546.0) -- [Jgarzik Repo](https://github.com/jgarzik/pyminer) \ No newline at end of file diff --git a/contrib/pyminer/example-config.cfg b/contrib/pyminer/example-config.cfg deleted file mode 100644 index 103e7c137..000000000 --- a/contrib/pyminer/example-config.cfg +++ /dev/null @@ -1,32 +0,0 @@ - -# -# RPC login details -# -host=127.0.0.1 -port=8332 - -rpcuser=myusername -rpcpass=mypass - - -# -# mining details -# - -threads=4 - -# periodic rate for requesting new work, if solution not found -scantime=60 - - -# -# misc. -# - -# not really used right now -logdir=/tmp/pyminer - -# set to 1, to enable hashmeter output -hashmeter=0 - - diff --git a/contrib/pyminer/pyminer.py b/contrib/pyminer/pyminer.py deleted file mode 100755 index 706a10b39..000000000 --- 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(" 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']))