Skip to content

Commit

Permalink
use getwork only on explicit 'http';
Browse files Browse the repository at this point in the history
moved patch() from util to OpenCLMiner;
explicit use of '<' throughout
  • Loading branch information
m0mchil committed Mar 20, 2013
1 parent 886c4ab commit a5ab744
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 89 deletions.
4 changes: 2 additions & 2 deletions BFLMiner.py
Expand Up @@ -90,7 +90,7 @@ def put_job(self):
if self.is_ok(response): if self.is_ok(response):
if self.switch.update_time: if self.switch.update_time:
self.job.time = bytereverse(uint32(long(time())) - self.job.time_delta) self.job.time = bytereverse(uint32(long(time())) - self.job.time_delta)
data = b''.join([pack('8I', *self.job.state), pack('3I', self.job.merkle_end, self.job.time, self.job.difficulty)]) data = b''.join([pack('<8I', *self.job.state), pack('<3I', self.job.merkle_end, self.job.time, self.job.difficulty)])
response = request(self.device, b''.join([b'>>>>>>>>', data, b'>>>>>>>>'])) response = request(self.device, b''.join([b'>>>>>>>>', data, b'>>>>>>>>']))
if self.is_ok(response): if self.is_ok(response):
self.busy = True self.busy = True
Expand Down Expand Up @@ -139,7 +139,7 @@ def nonce_generator(self, nonces):
for nonce in nonces.split(b','): for nonce in nonces.split(b','):
if len(nonce) != 8: continue if len(nonce) != 8: continue
try: try:
yield unpack('I', nonce.decode('hex')[::-1])[0] yield unpack('<I', nonce.decode('hex')[::-1])[0]
except error: except error:
pass pass


Expand Down
2 changes: 1 addition & 1 deletion GetworkSource.py
Expand Up @@ -151,7 +151,7 @@ def getwork(self, data=None):
say_exception() say_exception()


def send_internal(self, result, nonce): def send_internal(self, result, nonce):
data = ''.join([result.header.encode('hex'), pack('III', long(result.time), long(result.difficulty), long(nonce)).encode('hex'), '000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000']) data = ''.join([result.header.encode('hex'), pack('<3I', long(result.time), long(result.difficulty), long(nonce)).encode('hex'), '000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000'])
accepted = self.getwork(data) accepted = self.getwork(data)
if accepted != None: if accepted != None:
self.switch.report(result.miner, nonce, accepted) self.switch.report(result.miner, nonce, accepted)
Expand Down
104 changes: 68 additions & 36 deletions OpenCLMiner.py
Expand Up @@ -3,10 +3,11 @@
from hashlib import md5 from hashlib import md5
from log import say_line from log import say_line
from sha256 import partial, calculateF from sha256 import partial, calculateF
from struct import pack from struct import pack, unpack, error
from threading import Lock from threading import Lock
from time import sleep, time from time import sleep, time
from util import if_else, uint32, Object, bytereverse, patch, tokenize, bytearray_to_uint32 from util import if_else, uint32, Object, bytereverse, tokenize, \
bytearray_to_uint32
import sys import sys




Expand Down Expand Up @@ -70,6 +71,7 @@ def shutdown():


def initialize(options): def initialize(options):
if not OPENCL: if not OPENCL:
options.no_ocl = True
return [] return []


options.worksize = tokenize(options.worksize, 'worksize') options.worksize = tokenize(options.worksize, 'worksize')
Expand Down Expand Up @@ -183,30 +185,30 @@ def mining_thread(self):
state2 = partial(state, work.merkle_end, work.time, work.difficulty, f) state2 = partial(state, work.merkle_end, work.time, work.difficulty, f)
calculateF(state, work.merkle_end, work.time, work.difficulty, f, state2) calculateF(state, work.merkle_end, work.time, work.difficulty, f, state2)


self.kernel.set_arg(0, pack('I', state[0])) self.kernel.set_arg(0, pack('<I', state[0]))
self.kernel.set_arg(1, pack('I', state[1])) self.kernel.set_arg(1, pack('<I', state[1]))
self.kernel.set_arg(2, pack('I', state[2])) self.kernel.set_arg(2, pack('<I', state[2]))
self.kernel.set_arg(3, pack('I', state[3])) self.kernel.set_arg(3, pack('<I', state[3]))
self.kernel.set_arg(4, pack('I', state[4])) self.kernel.set_arg(4, pack('<I', state[4]))
self.kernel.set_arg(5, pack('I', state[5])) self.kernel.set_arg(5, pack('<I', state[5]))
self.kernel.set_arg(6, pack('I', state[6])) self.kernel.set_arg(6, pack('<I', state[6]))
self.kernel.set_arg(7, pack('I', state[7])) self.kernel.set_arg(7, pack('<I', state[7]))


self.kernel.set_arg(8, pack('I', state2[1])) self.kernel.set_arg(8, pack('<I', state2[1]))
self.kernel.set_arg(9, pack('I', state2[2])) self.kernel.set_arg(9, pack('<I', state2[2]))
self.kernel.set_arg(10, pack('I', state2[3])) self.kernel.set_arg(10, pack('<I', state2[3]))
self.kernel.set_arg(11, pack('I', state2[5])) self.kernel.set_arg(11, pack('<I', state2[5]))
self.kernel.set_arg(12, pack('I', state2[6])) self.kernel.set_arg(12, pack('<I', state2[6]))
self.kernel.set_arg(13, pack('I', state2[7])) self.kernel.set_arg(13, pack('<I', state2[7]))


self.kernel.set_arg(15, pack('I', f[0])) self.kernel.set_arg(15, pack('<I', f[0]))
self.kernel.set_arg(16, pack('I', f[1])) self.kernel.set_arg(16, pack('<I', f[1]))
self.kernel.set_arg(17, pack('I', f[2])) self.kernel.set_arg(17, pack('<I', f[2]))
self.kernel.set_arg(18, pack('I', f[3])) self.kernel.set_arg(18, pack('<I', f[3]))
self.kernel.set_arg(19, pack('I', f[4])) self.kernel.set_arg(19, pack('<I', f[4]))


if temperature < self.cutoff_temp: if temperature < self.cutoff_temp:
self.kernel.set_arg(14, pack('I', base)) self.kernel.set_arg(14, pack('<I', base))
cl.enqueue_nd_range_kernel(queue, self.kernel, (global_threads,), (self.worksize,)) cl.enqueue_nd_range_kernel(queue, self.kernel, (global_threads,), (self.worksize,))


nonces_left -= global_threads nonces_left -= global_threads
Expand Down Expand Up @@ -272,17 +274,17 @@ def mining_thread(self):
work.time = bytereverse(bytereverse(work.time) + 1) work.time = bytereverse(bytereverse(work.time) + 1)
state2 = partial(state, work.merkle_end, work.time, work.difficulty, f) state2 = partial(state, work.merkle_end, work.time, work.difficulty, f)
calculateF(state, work.merkle_end, work.time, work.difficulty, f, state2) calculateF(state, work.merkle_end, work.time, work.difficulty, f, state2)
self.kernel.set_arg(8, pack('I', state2[1])) self.kernel.set_arg(8, pack('<I', state2[1]))
self.kernel.set_arg(9, pack('I', state2[2])) self.kernel.set_arg(9, pack('<I', state2[2]))
self.kernel.set_arg(10, pack('I', state2[3])) self.kernel.set_arg(10, pack('<I', state2[3]))
self.kernel.set_arg(11, pack('I', state2[5])) self.kernel.set_arg(11, pack('<I', state2[5]))
self.kernel.set_arg(12, pack('I', state2[6])) self.kernel.set_arg(12, pack('<I', state2[6]))
self.kernel.set_arg(13, pack('I', state2[7])) self.kernel.set_arg(13, pack('<I', state2[7]))
self.kernel.set_arg(15, pack('I', f[0])) self.kernel.set_arg(15, pack('<I', f[0]))
self.kernel.set_arg(16, pack('I', f[1])) self.kernel.set_arg(16, pack('<I', f[1]))
self.kernel.set_arg(17, pack('I', f[2])) self.kernel.set_arg(17, pack('<I', f[2]))
self.kernel.set_arg(18, pack('I', f[3])) self.kernel.set_arg(18, pack('<I', f[3]))
self.kernel.set_arg(19, pack('I', f[4])) self.kernel.set_arg(19, pack('<I', f[4]))
last_n_time = now last_n_time = now
self.update_time_counter += 1 self.update_time_counter += 1
if self.update_time_counter >= self.switch.max_update_time: if self.update_time_counter >= self.switch.max_update_time:
Expand Down Expand Up @@ -321,7 +323,7 @@ def load_kernel(self):
except (IOError, cl.LogicError): except (IOError, cl.LogicError):
self.program = cl.Program(self.context, kernel).build(self.defines) self.program = cl.Program(self.context, kernel).build(self.defines)
if (self.defines.find('-DBFI_INT') != -1): if (self.defines.find('-DBFI_INT') != -1):
patchedBinary = patch(self.program.binaries[0]) patchedBinary = self.patch(self.program.binaries[0])
self.program = cl.Program(self.context, [self.device], [patchedBinary]).build(self.defines) self.program = cl.Program(self.context, [self.device], [patchedBinary]).build(self.defines)
binaryW = open(cache_name, 'wb') binaryW = open(cache_name, 'wb')
binaryW.write(self.program.binaries[0]) binaryW.write(self.program.binaries[0])
Expand Down Expand Up @@ -382,3 +384,33 @@ def get_adapter_info(self):
adapter_info.append(AdapterInfoArray[device.AdapterIndex]) adapter_info.append(AdapterInfoArray[device.AdapterIndex])


return adapter_info return adapter_info

def patch(self, data):
pos = data.find('\x7fELF', 1)
if pos != -1 and data.find('\x7fELF', pos+1) == -1:
data2 = data[pos:]
try:
(id, a, b, c, d, e, f, offset, g, h, i, j, entrySize, count, index) = unpack('QQHHIIIIIHHHHHH', data2[:52])
if id == 0x64010101464c457f and offset != 0:
(a, b, c, d, nameTableOffset, size, e, f, g, h) = unpack('IIIIIIIIII', data2[offset+index * entrySize : offset+(index+1) * entrySize])
header = data2[offset : offset+count * entrySize]
firstText = True
for i in xrange(count):
entry = header[i * entrySize : (i+1) * entrySize]
(nameIndex, a, b, c, offset, size, d, e, f, g) = unpack('IIIIIIIIII', entry)
nameOffset = nameTableOffset + nameIndex
name = data2[nameOffset : data2.find('\x00', nameOffset)]
if name == '.text':
if firstText: firstText = False
else:
data2 = data2[offset : offset + size]
patched = ''
for i in xrange(len(data2) / 8):
instruction, = unpack('Q', data2[i * 8 : i * 8 + 8])
if (instruction&0x9003f00002001000) == 0x0001a00000000000:
instruction ^= (0x0001a00000000000 ^ 0x0000c00000000000)
patched += pack('Q', instruction)
return ''.join([data[:pos+offset], patched, data[pos + offset + size:]])
except error:
pass
return data
8 changes: 3 additions & 5 deletions StratumSource.py
Expand Up @@ -133,9 +133,8 @@ def stop(self):
def refresh_job(self, j): def refresh_job(self, j):
j.extranonce2 = self.increment_nonce(j.extranonce2) j.extranonce2 = self.increment_nonce(j.extranonce2)
coinbase = j.coinbase1 + self.extranonce + j.extranonce2 + j.coinbase2 coinbase = j.coinbase1 + self.extranonce + j.extranonce2 + j.coinbase2
coinbase_hash = sha256(sha256(unhexlify(coinbase)).digest()).digest() merkle_root = sha256(sha256(unhexlify(coinbase)).digest()).digest()


merkle_root = coinbase_hash
for hash_ in j.merkle_branch: for hash_ in j.merkle_branch:
merkle_root = sha256(sha256(merkle_root + unhexlify(hash_)).digest()).digest() merkle_root = sha256(sha256(merkle_root + unhexlify(hash_)).digest()).digest()
merkle_root_reversed = '' merkle_root_reversed = ''
Expand All @@ -146,7 +145,6 @@ def refresh_job(self, j):
j.block_header = ''.join([j.version, j.prevhash, merkle_root, j.ntime, j.nbits]) j.block_header = ''.join([j.version, j.prevhash, merkle_root, j.ntime, j.nbits])
j.time = time() j.time = time()
return j return j



def increment_nonce(self, nonce): def increment_nonce(self, nonce):
next_nonce = long(nonce, 16) + 1 next_nonce = long(nonce, 16) + 1
Expand Down Expand Up @@ -266,8 +264,8 @@ def send_internal(self, result, nonce):
if not job_id in self.jobs: if not job_id in self.jobs:
return True return True
extranonce2 = result.extranonce2 extranonce2 = result.extranonce2
ntime = pack('I', long(result.time)).encode('hex') ntime = pack('<I', long(result.time)).encode('hex')
hex_nonce = pack('I', long(nonce)).encode('hex') hex_nonce = pack('<I', long(nonce)).encode('hex')
id_ = job_id + hex_nonce id_ = job_id + hex_nonce
self.submits[id_] = (result.miner, nonce, time()) self.submits[id_] = (result.miner, nonce, time())
return self.send_message({'params': [self.server().user, job_id, extranonce2, ntime, hex_nonce], 'id': id_, 'method': u'mining.submit'}) return self.send_message({'params': [self.server().user, job_id, extranonce2, ntime, hex_nonce], 'id': id_, 'method': u'mining.submit'})
Expand Down
27 changes: 13 additions & 14 deletions Switch.py
@@ -1,12 +1,10 @@

from copy import copy from copy import copy
from log import say_exception, say_line, say_quiet from log import say_exception, say_line, say_quiet
from sha256 import hash, sha256, STATE from sha256 import hash, sha256, STATE
from struct import pack, unpack from struct import pack, unpack
from threading import RLock from threading import RLock
from time import time, sleep from time import time, sleep
from util import if_else, Object, chunks, bytereverse, belowOrEquals, uint32 from util import if_else, Object, chunks, bytereverse, belowOrEquals, uint32
import GetworkSource
import StratumSource import StratumSource
import log import log
import socks import socks
Expand Down Expand Up @@ -156,13 +154,13 @@ def decode(self, server, block_header, target, job_id = None, extranonce2 = None
job = Object() job = Object()


binary_data = block_header.decode('hex') binary_data = block_header.decode('hex')
data0 = list(unpack('16I', binary_data[:64])) + ([0] * 48) data0 = list(unpack('<16I', binary_data[:64])) + ([0] * 48)


job.target = unpack('8I', target.decode('hex')) job.target = unpack('<8I', target.decode('hex'))
job.header = binary_data[:68] job.header = binary_data[:68]
job.merkle_end = uint32(unpack('I', binary_data[64:68])[0]) job.merkle_end = uint32(unpack('<I', binary_data[64:68])[0])
job.time = uint32(unpack('I', binary_data[68:72])[0]) job.time = uint32(unpack('<I', binary_data[68:72])[0])
job.difficulty = uint32(unpack('I', binary_data[72:76])[0]) job.difficulty = uint32(unpack('<I', binary_data[72:76])[0])
job.state = sha256(STATE, data0) job.state = sha256(STATE, data0)
job.targetQ = 2**256 / int(''.join(list(chunks(target, 2))[::-1]), 16) job.targetQ = 2**256 / int(''.join(list(chunks(target, 2))[::-1]), 16)
job.job_id = job_id job.job_id = job_id
Expand All @@ -179,21 +177,21 @@ def set_difficulty(self, difficulty):
bits = '%08x' % bytereverse(difficulty) bits = '%08x' % bytereverse(difficulty)
true_target = '%064x' % (int(bits[2:], 16) * 2 ** (8 * (int(bits[:2], 16) - 3)),) true_target = '%064x' % (int(bits[2:], 16) * 2 ** (8 * (int(bits[:2], 16) - 3)),)
true_target = ''.join(list(chunks(true_target, 2))[::-1]) true_target = ''.join(list(chunks(true_target, 2))[::-1])
self.true_target = unpack('8I', true_target.decode('hex')) self.true_target = unpack('<8I', true_target.decode('hex'))


def send(self, result, send_callback): def send(self, result, send_callback):
for nonce in result.miner.nonce_generator(result.nonces): for nonce in result.miner.nonce_generator(result.nonces):
h = hash(result.state, result.merkle_end, result.time, result.difficulty, nonce) h = hash(result.state, result.merkle_end, result.time, result.difficulty, nonce)
if h[7] != 0: if h[7] != 0:
hash6 = pack('I', long(h[6])).encode('hex') hash6 = pack('<I', long(h[6])).encode('hex')
say_line('Verification failed, check hardware! (%s, %s)', (result.miner.id(), hash6)) say_line('Verification failed, check hardware! (%s, %s)', (result.miner.id(), hash6))
return True # consume this particular result return True # consume this particular result
else: else:
self.diff1_found(bytereverse(h[6]), result.target[6]) self.diff1_found(bytereverse(h[6]), result.target[6])
if belowOrEquals(h[:7], result.target[:7]): if belowOrEquals(h[:7], result.target[:7]):
is_block = belowOrEquals(h[:7], self.true_target[:7]) is_block = belowOrEquals(h[:7], self.true_target[:7])
hash6 = pack('I', long(h[6])).encode('hex') hash6 = pack('<I', long(h[6])).encode('hex')
hash5 = pack('I', long(h[5])).encode('hex') hash5 = pack('<I', long(h[5])).encode('hex')
self.sent[nonce] = (is_block, hash6, hash5) self.sent[nonce] = (is_block, hash6, hash5)
if not send_callback(result, nonce): if not send_callback(result, nonce):
return False return False
Expand Down Expand Up @@ -265,9 +263,8 @@ def clear_result_queue(self, server):


def server_source(self): def server_source(self):
if not hasattr(self.server(), 'source'): if not hasattr(self.server(), 'source'):
if self.server().proto == 'stratum': if self.server().proto == 'http':
self.add_stratum_source() import GetworkSource
else:
getwork_source = GetworkSource.GetworkSource(self) getwork_source = GetworkSource.GetworkSource(self)
say_line('checking for stratum...') say_line('checking for stratum...')


Expand All @@ -279,6 +276,8 @@ def server_source(self):
self.add_stratum_source() self.add_stratum_source()
else: else:
self.server().source = getwork_source self.server().source = getwork_source
else:
self.add_stratum_source()


return self.server().source return self.server().source


Expand Down
31 changes: 0 additions & 31 deletions util.py
@@ -1,5 +1,4 @@
from log import say_exception from log import say_exception
from struct import pack, unpack, error
import sys import sys


class Object(object): class Object(object):
Expand Down Expand Up @@ -41,33 +40,3 @@ def tokenize(option, name, default=[0], cast=int):
say_exception('Invalid %s(s) specified: %s\n\n' % (name, option)) say_exception('Invalid %s(s) specified: %s\n\n' % (name, option))
sys.exit() sys.exit()
return default return default

def patch(data):
pos = data.find('\x7fELF', 1)
if pos != -1 and data.find('\x7fELF', pos+1) == -1:
data2 = data[pos:]
try:
(id, a, b, c, d, e, f, offset, g, h, i, j, entrySize, count, index) = unpack('QQHHIIIIIHHHHHH', data2[:52])
if id == 0x64010101464c457f and offset != 0:
(a, b, c, d, nameTableOffset, size, e, f, g, h) = unpack('IIIIIIIIII', data2[offset+index * entrySize : offset+(index+1) * entrySize])
header = data2[offset : offset+count * entrySize]
firstText = True
for i in xrange(count):
entry = header[i * entrySize : (i+1) * entrySize]
(nameIndex, a, b, c, offset, size, d, e, f, g) = unpack('IIIIIIIIII', entry)
nameOffset = nameTableOffset + nameIndex
name = data2[nameOffset : data2.find('\x00', nameOffset)]
if name == '.text':
if firstText: firstText = False
else:
data2 = data2[offset : offset + size]
patched = ''
for i in xrange(len(data2) / 8):
instruction, = unpack('Q', data2[i * 8 : i * 8 + 8])
if (instruction&0x9003f00002001000) == 0x0001a00000000000:
instruction ^= (0x0001a00000000000 ^ 0x0000c00000000000)
patched += pack('Q', instruction)
return ''.join([data[:pos+offset], patched, data[pos + offset + size:]])
except error:
pass
return data

0 comments on commit a5ab744

Please sign in to comment.