소스 검색

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.
tags/v0.15.1
Wladimir J. van der Laan 7 년 전
부모
커밋
403c1bf0fb
4개의 변경된 파일0개의 추가작업 그리고 313개의 파일을 삭제
  1. 0
    4
      contrib/README.md
  2. 0
    8
      contrib/pyminer/README.md
  3. 0
    32
      contrib/pyminer/example-config.cfg
  4. 0
    269
      contrib/pyminer/pyminer.py

+ 0
- 4
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.

+ 0
- 8
contrib/pyminer/README.md 파일 보기

@@ -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)

+ 0
- 32
contrib/pyminer/example-config.cfg 파일 보기

@@ -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



+ 0
- 269
contrib/pyminer/pyminer.py 파일 보기

@@ -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']))

Loading…
취소
저장