aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/README.md4
-rw-r--r--contrib/debian/examples/bitcoin.conf2
-rw-r--r--contrib/debian/manpages/bitcoin-qt.18
-rw-r--r--contrib/debian/manpages/bitcoind.12
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml2
-rwxr-xr-xcontrib/pyminer/pyminer.py457
6 files changed, 243 insertions, 232 deletions
diff --git a/contrib/README.md b/contrib/README.md
index 92d0a343db..63b1875d30 100644
--- a/contrib/README.md
+++ b/contrib/README.md
@@ -21,11 +21,11 @@ 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, for study.
+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 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.
+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.
### [Seeds](/contrib/seeds) ###
Utility to generate the pnSeed[] array that is compiled into the client.
diff --git a/contrib/debian/examples/bitcoin.conf b/contrib/debian/examples/bitcoin.conf
index 0aa8674af9..31cca981e0 100644
--- a/contrib/debian/examples/bitcoin.conf
+++ b/contrib/debian/examples/bitcoin.conf
@@ -10,7 +10,7 @@
# Run a regression test network
#regtest=0
-# Connect via a socks4 proxy
+# Connect via a SOCKS5 proxy
#proxy=127.0.0.1:9050
##############################################################
diff --git a/contrib/debian/manpages/bitcoin-qt.1 b/contrib/debian/manpages/bitcoin-qt.1
index 25a423f9c4..a023582bc0 100644
--- a/contrib/debian/manpages/bitcoin-qt.1
+++ b/contrib/debian/manpages/bitcoin-qt.1
@@ -32,10 +32,7 @@ Set database cache size in megabytes (default: 25)
Specify connection timeout in milliseconds (default: 5000)
.TP
\fB\-proxy=\fR<ip:port>
-Connect through socks proxy
-.TP
-\fB\-socks=\fR<n>
-Select the version of socks proxy to use (4\-5, default: 5)
+Connect through SOCKS5 proxy
.TP
\fB\-tor=\fR<ip:port>
Use proxy to reach tor hidden services (default: same as \fB\-proxy\fR)
@@ -139,9 +136,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash
\fB\-walletnotify=\fR<cmd>
Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)
.TP
-\fB\-respendnotify=\fR<cmd>
-Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)
-.TP
\fB\-alertnotify=\fR<cmd>
Execute command when a relevant alert is received (%s in cmd is replaced by message)
.TP
diff --git a/contrib/debian/manpages/bitcoind.1 b/contrib/debian/manpages/bitcoind.1
index 0c191b6043..a1b17d6077 100644
--- a/contrib/debian/manpages/bitcoind.1
+++ b/contrib/debian/manpages/bitcoind.1
@@ -28,7 +28,7 @@ Start minimized
Specify data directory
.TP
\fB\-proxy=\fR<ip:port>
-Connect through socks4 proxy
+Connect through SOCKS5 proxy
.TP
\fB\-addnode=\fR<ip>
Add a node to connect to
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index 65a6c3c1e9..30b0227bdd 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -59,7 +59,7 @@ script: |
local: *;
};' > $LINKER_SCRIPT
function do_configure {
- ./configure "$@" --enable-upnp-default --prefix=$STAGING --with-protoc-bindir=$STAGING/host/bin --with-qt-bindir=$STAGING/bin --with-boost=$STAGING --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include ${OPTFLAGS}" LDFLAGS="-L$STAGING/lib -Wl,--version-script=$LINKER_SCRIPT ${OPTFLAGS}" CXXFLAGS="-frandom-seed=bitcoin ${OPTFLAGS}" BOOST_CHRONO_EXTRALIBS="-lrt" --enable-glibc-back-compat
+ ./configure "$@" --enable-upnp-default --prefix=$STAGING --with-protoc-bindir=$STAGING/host/bin --with-qt-bindir=$STAGING/bin --with-boost=$STAGING --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include ${OPTFLAGS}" LDFLAGS="-L$STAGING/lib -Wl,--version-script=$LINKER_SCRIPT ${OPTFLAGS}" CXXFLAGS="-frandom-seed=bitcoin ${OPTFLAGS}" --enable-glibc-back-compat
}
#
cd bitcoin
diff --git a/contrib/pyminer/pyminer.py b/contrib/pyminer/pyminer.py
index 0a2932d66e..706a10b39d 100755
--- a/contrib/pyminer/pyminer.py
+++ b/contrib/pyminer/pyminer.py
@@ -5,248 +5,265 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
+import sys
+from multiprocessing import Process
import time
-import json
-import pprint
-import hashlib
import struct
-import re
+import hashlib
import base64
+import re
import httplib
-import sys
-from multiprocessing import Process
+import json
ERR_SLEEP = 15
MAX_NONCE = 1000000L
settings = {}
-pp = pprint.PrettyPrinter(indent=4)
+
class BitcoinRPC:
- OBJID = 1
-
- def __init__(self, host, port, username, password):
- authpair = "%s:%s" % (username, password)
- self.authhdr = "Basic %s" % (base64.b64encode(authpair))
- self.conn = httplib.HTTPConnection(host, port, False, 30)
- def rpc(self, method, params=None):
- self.OBJID += 1
- obj = { 'version' : '1.1',
- 'method' : method,
- 'id' : self.OBJID }
- if params is None:
- obj['params'] = []
- else:
- obj['params'] = params
- 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)
+ 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
+ return x & 0xffffffffL
def bytereverse(x):
- return uint32(( ((x) << 24) | (((x) << 8) & 0x00ff0000) |
- (((x) >> 8) & 0x0000ff00) | ((x) >> 24) ))
+ 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)
+ 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)
+ 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')
- l = long(hash_str, 16)
-
- # proof-of-work test: hash < target
- if l < target:
- print time.asctime(), "PROOF-OF-WORK found: %064x" % (l,)
- return (nonce + 1, nonce_bin)
- else:
- print time.asctime(), "PROOF-OF-WORK false positive %064x" % (l,)
-# return (nonce + 1, nonce_bin)
-
- 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" % (
- 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 None:
- return
-
- while True:
- self.iterate(rpc)
+ 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()
+ miner = Miner(id)
+ miner.loop()
if __name__ == '__main__':
- if len(sys.argv) != 2:
- print "Usage: pyminer.py CONFIG-FILE"
- sys.exit(1)
-
- f = open(sys.argv[1])
- 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)
- f.close()
-
- if 'host' not in settings:
- settings['host'] = '127.0.0.1'
- if 'port' not in settings:
- settings['port'] = 8332
- if 'threads' not in settings:
- settings['threads'] = 1
- if 'hashmeter' not in settings:
- settings['hashmeter'] = 0
- if 'scantime' not in settings:
- settings['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'])
-
- thr_list = []
- for thr_id in range(settings['threads']):
- p = Process(target=miner_thread, args=(thr_id,))
- p.start()
- thr_list.append(p)
- time.sleep(1) # stagger threads
-
- print settings['threads'], "mining threads started"
-
- print time.asctime(), "Miner Starts - %s:%s" % (settings['host'], settings['port'])
- try:
- for thr_proc in thr_list:
- thr_proc.join()
- except KeyboardInterrupt:
- pass
- print time.asctime(), "Miner Stops - %s:%s" % (settings['host'], settings['port'])
-
+ 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']))