aboutsummaryrefslogtreecommitdiff
path: root/contrib/pyminer/pyminer.py
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2014-07-29 09:58:14 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2014-07-29 09:58:14 +0200
commit403c1bf0fbff2c7cb20afbd4413f36267029deef (patch)
tree7aa13852bbf1c4075567df17ae12d2c9846eda7a /contrib/pyminer/pyminer.py
parent29203228710de3e180914c1d66f48dd7e41270a0 (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-xcontrib/pyminer/pyminer.py269
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']))