def get_temperature(self): response = request(self.device, b'ZLX') if len(response) < 23 or response[0] != b'T' or response[-1:] != b'\n': say_line('%s: bad response for temperature: %s', (self.id(), response)) return 0 return float(response[23:-1])
def set_server_index(self, server_index): self.server_index = server_index user = self.servers[server_index].user name = self.servers[server_index].name #say_line('Setting server %s (%s @ %s)', (name, user, host)) say_line('Setting server (%s @ %s)', (user, name)) log.server = name
def request(self, connection, url, headers, data=None, timeout=0): result = response = None try: if data: connection.request('POST', url, data, headers) else: connection.request('GET', url, headers=headers) response = self.timeout_response(connection, timeout) if not response: return None if response.status == httplib.UNAUTHORIZED: say_line('Wrong username or password for %s', self.server().name) self.authorization_failed = True raise NotAuthorized() r = self.max_redirects while response.status == httplib.TEMPORARY_REDIRECT: response.read() url = response.getheader('Location', '') if r == 0 or url == '': raise HTTPException('Too much or bad redirects') connection.request('GET', url, headers=headers) response = self.timeout_response(connection, timeout) r -= 1 self.long_poll_url = response.getheader('X-Long-Polling', '') self.switch.update_time = bool(response.getheader('X-Roll-NTime', '')) hostList = response.getheader('X-Host-List', '') self.stratum_header = response.getheader('x-stratum', '') if (not self.options.nsf) and hostList: self.switch.add_servers(loads(hostList)) result = loads(response.read()) if result['error']: say_line('server error: %s', result['error']['message']) raise RPCError(result['error']['message']) return (connection, result) finally: if not result or not response or (response.version == 10 and response.getheader('connection', '') != 'keep-alive') or response.getheader('connection', '') == 'close': connection.close() connection = None
def report(self, miner, nonce, accepted): is_block, hash6, hash5 = self.sent[nonce] miner.share_count[1 if accepted else 0] += 1 hash_ = hash6 + hash5 if is_block else hash6 if self.options.verbose or is_block: say_line('%s %s%s, %s', (miner.id(), 'block ' if is_block else '', hash_, 'accepted' if accepted else '_rejected_')) del self.sent[nonce]
def __init__(self, options): self.lock = RLock() self.miners = [] self.options = options self.last_work = 0 self.update_time = True self.max_update_time = options.max_update_time self.backup_server_index = 1 self.errors = 0 self.failback_attempt_count = 0 self.server_index = -1 self.last_server = None self.server_map = {} self.user_agent = 'poclbm/' + options.version self.difficulty = 0 self.true_target = None self.last_block = '' self.sent = {} if self.options.proxy: self.options.proxy = self.parse_server(self.options.proxy, False) self.servers = [] for server in self.options.servers: try: self.servers.append(self.parse_server(server)) except ValueError: if self.options.verbose: say_exception() say_line("Ignored invalid server entry: %s", server) continue
def detect_stratum_proxy(host): s = None try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) s.sendto( dumps({ "id": 0, "method": "mining.get_upstream", "params": [] }), ('239.3.3.3', 3333)) say_line('Searching stratum proxy for %s', host) s.settimeout(2) try: while True: response, address = s.recvfrom(128) try: response = loads(response) response_host = response['result'][0][0] + ':' + str( response['result'][0][1]) if response_host == host: proxy_address = address[0] + ':' + str( response['result'][1]) say_line('Using stratum proxy at %s', proxy_address) return proxy_address except ValueError: pass except socket.timeout: pass finally: if s != None: s.close()
def report(self, miner, nonce, accepted): is_block, hash6, hash5 = self.sent[nonce] miner.share_count[if_else(accepted, 1, 0)] += 1 hash_ = if_else(is_block, hash6 + hash5, hash6) if self.options.verbose or is_block: say_line('%s %s%s, %s', (miner.id(), if_else(is_block, 'block ', ''), hash_, if_else(accepted, 'accepted', '_rejected_'))) del self.sent[nonce]
def send(self, result, send_callback): for nonce in result.miner.nonce_generator(result.nonces): h = hash(result.state, result.merkle_end, result.time, result.difficulty, nonce) if h[7] != 0: hash6 = pack('<I', long(h[6])).encode('hex') say_line('Verification failed, check hardware! (%s, %s)', (result.miner.id(), hash6)) return True # consume this particular result else: self.diff1_found(bytereverse(h[6]), result.target[6]) if belowOrEquals(h[:7], result.target[:7]): is_block = belowOrEquals(h[:7], self.true_target[:7]) hash6 = pack('<I', long(h[6])).encode('hex') hash5 = pack('<I', long(h[5])).encode('hex') self.sent[nonce] = (is_block, hash6, hash5) ntime = long(pack('<I', long(result.time)).encode('hex'),16) resnonce = long(pack('<I', long(nonce)).encode('hex'),16) block = self.source.create_block_header(self.source.merkle_root, ntime, self.source.bits, resnonce) hash_header = hashlib.sha256(hashlib.sha256(block).digest()).digest()[::-1] shouldSend = int(hash_header.encode('hex_codec'), 16) < self.source.server_difficulty print "t->" + str(ntime) + " nonce->" + str(resnonce) + " shouldSend->" + str(shouldSend) if shouldSend: if not send_callback(result, nonce): return False return True
def detect_stratum_proxy(host): s = None try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) s.sendto(dumps({"id": 0, "method": "mining.get_upstream", "params": []}), ('239.3.3.3', 3333)) say_line('Searching stratum proxy for %s', host) s.settimeout(2) try: while True: response, address = s.recvfrom(128) try: response = loads(response) response_host = response['result'][0][0] + ':' + str(response['result'][0][1]) if response_host == host: proxy_address = address[0] + ':' + str(response['result'][1]) say_line('Using stratum proxy at %s', proxy_address) return proxy_address except ValueError: pass except socket.timeout: pass finally: if s != None: s.close()
def loop(self): super(StratumSource, self).loop() self.switch.update_time = True while True: if self.should_stop: return if self.current_job: miner = self.switch.updatable_miner() while miner: self.current_job = self.refresh_job(self.current_job) self.queue_work(self.current_job, miner) miner = self.switch.updatable_miner() if self.check_failback(): return True if not self.handler: try: #socket = ssl.wrap_socket(socket) address, port = self.server().host.split(':', 1) if not self.options.proxy: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((address, int(port))) else: self.socket = socks.socksocket() p = self.options.proxy self.socket.setproxy(p.type, p.host, p.port, True, p.user, p.pwd) try: self.socket.connect((address, int(port))) except socks.Socks5AuthError: say_exception('Proxy error:') self.stop() self.handler = Handler(self.socket, self.channel_map, self) thread = Thread(target=self.asyncore_thread) thread.daemon = True thread.start() if not self.subscribe(): say_line('Failed to subscribe') self.stop() elif not self.authorize(): self.stop() elif not self.suggest_difficulty(128): say_line('Failed to suggest_difficulty') except socket.error: say_exception() self.stop() continue with self.send_lock: self.process_result_queue() sleep(1)
def check_result(self): response = request(self.device, b'ZFX') if response[0] == b'B': return False if response == b'NO-NONCE\n': return response if response[:12] != 'NONCE-FOUND:' or response[-1:] != '\n': say_line('%s: bad response checking result: %s', (self.id(), response)) return None return response[12:-1]
def loop(self): super(StratumSource, self).loop() self.switch.update_time = True while True: if self.should_stop: return if self.current_job: miner = self.switch.updatable_miner() while miner: self.current_job = self.refresh_job(self.current_job) self.queue_work(self.current_job, miner) miner = self.switch.updatable_miner() if self.check_failback(): return True if not self.handler: try: #socket = ssl.wrap_socket(socket) address, port = self.server().host.split(':', 1) if not self.options.proxy: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((address, int(port))) else: self.socket = socks.socksocket() p = self.options.proxy self.socket.setproxy(p.type, p.host, p.port, True, p.user, p.pwd) try: self.socket.connect((address, int(port))) except socks.Socks5AuthError: say_exception('Proxy error:') self.stop() self.handler = Handler(self.socket, self.channel_map, self) thread = Thread(target=self.asyncore_thread) thread.daemon = True thread.start() if not self.subscribe(): say_line('Failed to subscribe') self.stop() elif not self.authorize(): self.stop() except socket.error: say_exception() self.stop() continue with self.send_lock: self.process_result_queue() sleep(1)
def load_kernel(self): self.context = cl.Context([self.device], None, None) if self.device.extensions.find('cl_amd_media_ops') != -1: self.defines += ' -DBITALIGN' if self.device_name in ['Cedar', 'Redwood', 'Juniper', 'Cypress', 'Hemlock', 'Caicos', 'Turks', 'Barts', 'Cayman', 'Antilles', 'Wrestler', 'Zacate', 'WinterPark', 'BeaverCreek']: self.defines += ' -DBFI_INT' kernel_file = open('skein.cl', 'r') kernel = kernel_file.read() kernel_file.close() m = md5(); m.update(''.join([self.device.platform.name, self.device.platform.version, self.device.name, self.defines, kernel])) cache_name = '%s.elf' % m.hexdigest() binary = None compile = False try: binary = open(cache_name, 'rb') self.program = cl.Program(self.context, [self.device], [binary.read()]).build(self.defines) say_line("Loaded existing compiled kernel: %s", cache_name) except (IOError, cl.LogicError) as e: say_line("Error loading compiled kernel: %s", cache_name) say_line("Recompiling kernel ...") compile = True finally: if binary: binary.close() if compile: self.program = cl.Program(self.context, kernel).build(self.defines) if self.defines.find('-DBFI_INT') != -1: patchedBinary = self.patch(self.program.binaries[0]) self.program = cl.Program(self.context, [self.device], [patchedBinary]).build(self.defines) binaryW = open(cache_name, 'wb') binaryW.write(self.program.binaries[0]) binaryW.close() say_line("Compiled kernel: %s", cache_name) self.kernel = self.program.search if not self.worksize: self.worksize = self.kernel.get_work_group_info(cl.kernel_work_group_info.WORK_GROUP_SIZE, self.device) say_line("Worksize: %d" % self.worksize)
def add_stratum_source(self): if self.options.stratum_proxies: stratum_proxy = StratumSource.detect_stratum_proxy(self.server().host) if stratum_proxy: original_server = copy(self.server()) original_server.source = StratumSource.StratumSource(self) self.servers.insert(self.backup_server_index, original_server) self.server().host = stratum_proxy self.server().name += '(p)' log.server = self.server().name else: say_line('No proxy found') self.server().source = StratumSource.StratumSource(self)
def queue_kernel_parameters(self, work): state = skeinhashmid(pack('>16I', *work.dataX[:16])) for i in xrange(8): self.kernel.set_arg(i, state[i * 8:i * 8 + 8]) for i in range(16, 19): self.kernel.set_arg(i - 8, pack('>I', work.dataX[i])) if work.target[6] != self.target6 or work.target[7] != self.target7: say_line("Calling with tgt %.8x %.8x", (work.target[6], work.target[7])) self.target6 = work.target[6] self.target7 = work.target[7]
def check(port, likely=True): result = False try: device = open_device(port) response = init_device(device) device.close() result = is_good_init(response) except SerialException: if likely: say_exception() if not likely and result: say_line('Found BitFORCE on %s', port) elif likely and not result: say_line('No valid response from BitFORCE on %s', port) return result
def send(self, result, send_callback): for nonce in result.miner.nonce_generator(result.nonces): h = hash(result.state, result.merkle_end, result.time, result.difficulty, nonce) if h[7] != 0: hash6 = pack('I', long(h[6])).encode('hex') say_line('Verification failed, check hardware! (%s, %s)', (result.miner.id(), hash6)) return True # consume this particular result else: self.diff1_found(bytereverse(h[6]), result.target[6]) if belowOrEquals(h[:7], result.target[:7]): is_block = belowOrEquals(h[:7], self.true_target[:7]) hash6 = pack('I', long(h[6])).encode('hex') hash5 = pack('I', long(h[5])).encode('hex') self.sent[nonce] = (is_block, hash6, hash5) if not send_callback(result, nonce): return False return True
def long_poll_thread(self): last_host = None while True: if self.should_stop or self.authorization_failed: return url = self.long_poll_url if url != '': proto = self.server().proto host = self.server().host parsedUrl = urlsplit(url) if parsedUrl.scheme != '': proto = parsedUrl.scheme if parsedUrl.netloc != '': host = parsedUrl.netloc url = url[url.find(host) + len(host):] if url == '': url = '/' try: if host != last_host: self.close_lp_connection() self.lp_connection, changed = self.ensure_connected( self.lp_connection, proto, host) if changed: say_line("LP connected to %s", self.server().name) last_host = host self.long_poll_active = True response = self.request(self.lp_connection, url, self.headers, timeout=self.long_poll_timeout) self.long_poll_active = False if response: (self.lp_connection, result) = response self.queue_work(result['result']) if self.options.verbose: say_line('long poll: new block %s%s', (result['result']['data'][56:64], result['result']['data'][48:56])) except (IOError, httplib.HTTPException, ValueError, socks.ProxyError, NotAuthorized, RPCError): say_exception('long poll IO error') self.close_lp_connection() sleep(.5) except Exception: say_exception()
def server_source(self): if not hasattr(self.server(), 'source'): if self.server().proto == 'stratum': self.add_stratum_source() else: getwork_source = GetworkSource.GetworkSource(self) say_line('checking for stratum...') stratum_host = getwork_source.detect_stratum() if stratum_host: getwork_source.close_connection() self.server().proto = 'stratum' self.server().host = stratum_host self.add_stratum_source() else: self.server().source = getwork_source return self.server().source
def long_poll_thread(self): last_host = None while True: if self.should_stop or self.authorization_failed: return url = self.long_poll_url if url != '': proto = self.server().proto host = self.server().host parsedUrl = urlsplit(url) if parsedUrl.scheme != '': proto = parsedUrl.scheme if parsedUrl.netloc != '': host = parsedUrl.netloc url = url[url.find(host) + len(host):] if url == '': url = '/' try: if host != last_host: self.close_lp_connection() self.lp_connection, changed = self.ensure_connected(self.lp_connection, proto, host) if changed: say_line("LP connected to %s", self.server().name) last_host = host self.long_poll_active = True response = self.request(self.lp_connection, url, self.headers, timeout=self.long_poll_timeout) self.long_poll_active = False if response: (self.lp_connection, result) = response self.queue_work(result['result']) if self.options.verbose: say_line('long poll: new block %s%s', (result['result']['data'][56:64], result['result']['data'][48:56])) except (IOError, httplib.HTTPException, ValueError, socks.ProxyError, NotAuthorized, RPCError): say_exception('long poll IO error') self.close_lp_connection() sleep(.5) except Exception: say_exception()
def send(self, result, send_callback): for nonce in result.miner.nonce_generator(result.nonces): # h = hash(result.state, result.merkle_end, result.time, result.difficulty, nonce) hx = ''.join(pack('>19I', *result.dataX)) qh = skeinhash(''.join([hx, pack('>I', long(nonce))])) h = unpack('>8I', qh) #if h[6] & 0xf == 0: # say_line('Nonce: %08x, hash: %s, h6: %08x', (nonce, qh.encode('hex'), h[6])) if qh[-3:] != '\x00\x00\x00': hash7 = pack('<I', long(h[7])).encode('hex') say_line('Verification failed, check hardware! (%s, %s, %08x)', (result.miner.id(), hash7, nonce)) say_line('data %s' % ''.join([hx, pack('>I', long(nonce))]).encode('hex')) return True # consume this particular result else: self.diff1_found(bytereverse(h[6]), result.target[6]) if belowOrEquals(h[:7], result.target[:7]): is_block = belowOrEquals(h[:7], self.true_target[:7]) hash6 = pack('<I', long(h[6])).encode('hex') hash5 = pack('<I', long(h[5])).encode('hex') self.sent[nonce] = (is_block, hash6, hash5) if not send_callback(result, nonce): return False return True
def loop(self): self.should_stop = False if not self.servers: print '\nAt least one server is required' return else: self.set_server_index(0) while True: if self.should_stop: return failback = self.server_source().loop() sleep(1) if failback: say_line("Attempting to fail back to primary server") self.last_server = self.server_index self.set_server_index(0) continue if self.last_server: self.failback_attempt_count += 1 self.set_server_index(self.last_server) say_line( 'Still unable to reconnect to primary server (attempt %s), failing over', self.failback_attempt_count) self.last_server = None continue self.errors += 1 say_line('IO errors - %s, tolerance %s', (self.errors, self.options.tolerance)) if self.errors > self.options.tolerance: self.errors = 0 if self.backup_server_index >= len(self.servers): say_line( "No more backup servers left. Using primary and starting over." ) new_server_index = 0 self.backup_server_index = 1 else: new_server_index = self.backup_server_index self.backup_server_index += 1 self.set_server_index(new_server_index)
def loop(self): self.should_stop = False if not self.servers: print '\nAt least one server is required' return else: self.set_server_index(0) while True: if self.should_stop: return failback = self.server_source().loop() sleep(1) if failback: say_line("Attempting to fail back to primary server") self.last_server = self.server_index self.set_server_index(0) continue if self.last_server: self.failback_attempt_count += 1 self.set_server_index(self.last_server) say_line('Still unable to reconnect to primary server (attempt %s), failing over', self.failback_attempt_count) self.last_server = None continue self.errors += 1 say_line('IO errors - %s, tolerance %s', (self.errors, self.options.tolerance)) if self.errors > self.options.tolerance: self.errors = 0 if self.backup_server_index >= len(self.servers): say_line("No more backup servers left. Using primary and starting over.") new_server_index = 0 self.backup_server_index = 1 else: new_server_index = self.backup_server_index self.backup_server_index += 1 self.set_server_index(new_server_index)
def get_adapter_info(self): adapter_info = [] num_adapters = c_int(-1) if ADL_Adapter_NumberOfAdapters_Get(byref(num_adapters)) != ADL_OK: say_line( "ADL_Adapter_NumberOfAdapters_Get failed, cutoff temperature disabled for %s", self.id()) return AdapterInfoArray = (AdapterInfo * num_adapters.value)() if ADL_Adapter_AdapterInfo_Get(cast(AdapterInfoArray, LPAdapterInfo), sizeof(AdapterInfoArray)) != ADL_OK: say_line( "ADL_Adapter_AdapterInfo_Get failed, cutoff temperature disabled for %s", self.id()) return deviceAdapter = namedtuple( 'DeviceAdapter', ['AdapterIndex', 'AdapterID', 'BusNumber', 'UDID']) devices = [] for adapter in AdapterInfoArray: index = adapter.iAdapterIndex busNum = adapter.iBusNumber udid = adapter.strUDID adapterID = c_int(-1) if ADL_Adapter_ID_Get(index, byref(adapterID)) != ADL_OK: say_line( "ADL_Adapter_ID_Get failed, cutoff temperature disabled for %s", self.id()) return found = False for device in devices: if (device.AdapterID.value == adapterID.value): found = True break if (found == False): devices.append(deviceAdapter(index, adapterID, busNum, udid)) for device in devices: adapter_info.append(AdapterInfoArray[device.AdapterIndex]) return adapter_info
def put_job(self): if self.busy: return temperature = self.get_temperature() if temperature < self.cutoff_temp: response = request(self.device, b'ZDX') if self.is_ok(response): if self.switch.update_time: 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) ]) response = request(self.device, b''.join([b'>>>>>>>>', data, b'>>>>>>>>'])) if self.is_ok(response): self.busy = True self.job_started = time() self.last_job = Object() self.last_job.header = self.job.header self.last_job.merkle_end = self.job.merkle_end self.last_job.time = self.job.time self.last_job.difficulty = self.job.difficulty self.last_job.target = self.job.target self.last_job.state = self.job.state self.last_job.job_id = self.job.job_id self.last_job.extranonce2 = self.job.extranonce2 self.last_job.server = self.job.server self.last_job.miner = self self.check_interval = CHECK_INTERVAL if not self.switch.update_time or bytereverse( self.job.time) - bytereverse( self.job.original_time) > 55: self.update = True self.job = None else: say_line('%s: bad response when sending block data: %s', (self.id(), response)) else: say_line('%s: bad response when submitting job (ZDX): %s', (self.id(), response)) else: say_line('%s: temperature exceeds cutoff, waiting...', self.id())
def get_adapter_info(self): adapter_info = [] num_adapters = c_int(-1) if ADL_Adapter_NumberOfAdapters_Get(byref(num_adapters)) != ADL_OK: say_line("ADL_Adapter_NumberOfAdapters_Get failed, cutoff temperature disabled for %s", self.id()) return AdapterInfoArray = (AdapterInfo * num_adapters.value)() if ADL_Adapter_AdapterInfo_Get(cast(AdapterInfoArray, LPAdapterInfo), sizeof(AdapterInfoArray)) != ADL_OK: say_line("ADL_Adapter_AdapterInfo_Get failed, cutoff temperature disabled for %s", self.id()) return deviceAdapter = namedtuple('DeviceAdapter', ['AdapterIndex', 'AdapterID', 'BusNumber', 'UDID']) devices = [] for adapter in AdapterInfoArray: index = adapter.iAdapterIndex busNum = adapter.iBusNumber udid = adapter.strUDID adapterID = c_int(-1) if ADL_Adapter_ID_Get(index, byref(adapterID)) != ADL_OK: say_line("ADL_Adapter_Active_Get failed, cutoff temperature disabled for %s", self.id()) return found = False for device in devices: if (device.AdapterID.value == adapterID.value): found = True break if (found == False): devices.append(deviceAdapter(index, adapterID, busNum, udid)) for device in devices: adapter_info.append(AdapterInfoArray[device.AdapterIndex]) return adapter_info
def detect_stratum(self): work = self.getwork() if self.authorization_failed: return False if work: if self.stratum_header: host = self.stratum_header proto = host.find('://') if proto != -1: host = self.stratum_header[proto+3:] #this doesn't work in windows/python 2.6 #host = urlparse.urlparse(self.stratum_header).netloc say_line('diverted to stratum on %s', host) return host else: say_line('using JSON-RPC (no stratum header)') self.queue_work(work) return False say_line('no response to getwork, using as stratum') return self.server().host
def detect_stratum(self): work = self.getwork() if self.authorization_failed: return False if work: if self.stratum_header: host = self.stratum_header proto = host.find('://') if proto != -1: host = self.stratum_header[proto + 3:] #this doesn't work in windows/python 2.6 #host = urlparse.urlparse(self.stratum_header).netloc say_line('diverted to stratum on %s', host) return host else: say_line('using JSON-RPC (no stratum header)') self.queue_work(work) return False say_line('no response to getwork, using as stratum') return self.server().host
def put_job(self): if self.busy: return temperature = self.get_temperature() if temperature < self.cutoff_temp: response = request(self.device, b'ZDX') if self.is_ok(response): if self.switch.update_time: self.job.time = (np.uint32(time()) - self.job.time_delta).byteswap() data = b''.join([self.job.state.tostring(), self.job.merkle_end.tostring(), self.job.time.tostring(), self.job.difficulty.tostring()]) response = request(self.device, b''.join([b'>>>>>>>>', data, b'>>>>>>>>'])) if self.is_ok(response): self.busy = True self.job_started = time() self.last_job = Object() self.last_job.header = self.job.header self.last_job.merkle_end = self.job.merkle_end self.last_job.time = self.job.time self.last_job.difficulty = self.job.difficulty self.last_job.target = self.job.target self.last_job.state = self.job.state self.last_job.job_id = self.job.job_id self.last_job.extranonce2 = self.job.extranonce2 self.last_job.server = self.job.server self.last_job.miner = self self.check_interval = CHECK_INTERVAL if not self.switch.update_time or self.job.time.byteswap() - self.job.original_time.byteswap() > 55: self.update = True self.job = None else: say_line('%s: bad response when sending block data: %s', (self.id(), response)) else: say_line('%s: bad response when submitting job (ZDX): %s', (self.id(), response)) else: say_line('%s: temperature exceeds cutoff, waiting...', self.id())
def mining_thread(self): say_line('started BFL miner on %s', (self.id())) while not self.should_stop: try: self.device = open_device(self.port) response = init_device(self.device) if not is_good_init(response): say_line('Failed to initialize %s (response: %s), retrying...', (self.id(), response)) self.device.close() self.device = None sleep(1) continue last_rated = time() iterations = 0 self.job = None self.busy = False while not self.should_stop: if (not self.job) or (not self.work_queue.empty()): try: self.job = self.work_queue.get(True, 1) except Empty: if not self.busy: continue else: if not self.job and not self.busy: continue targetQ = self.job.targetQ self.job.original_time = self.job.time self.job.time_delta = np.uint32(time()) - self.job.time.byteswap() if not self.busy: self.put_job() else: result = self.check_result() if result: now = time() self.busy = False r = self.last_job job_duration = now - self.job_started self.put_job() self.min_interval = min(self.min_interval, job_duration) iterations += 4294967296 t = now - last_rated if t > self.options.rate: self.update_rate(now, iterations, t, targetQ) last_rated = now; iterations = 0 if result != b'NO-NONCE\n': r.nonces = result self.switch.put(r) sleep(self.min_interval - (CHECK_INTERVAL * 2)) else: if result is None: self.check_interval = min(self.check_interval * 2, 1) sleep(self.check_interval) except Exception: say_exception() if self.device: self.device.close() self.device = None sleep(1)
def diff1_found(self, hash_, target): if self.options.verbose and target < 0xFFFF0000L: say_line('checking %s <= %s', (hash_, target))
def loop(self): super(StratumSource, self).loop() self.switch.update_time = True while True: if self.should_stop: return if self.current_job: miner = self.switch.updatable_miner() while miner: self.current_job = self.refresh_job(self.current_job) self.queue_work(self.current_job, miner) miner = self.switch.updatable_miner() if self.check_failback(): return True if not self.handler: try: #socket = ssl.wrap_socket(socket) address, port = self.server().host.split(':', 1) if not self.options.proxy: self.socket = socket.nodelay_socket( socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((address, int(port))) else: proxy_proto, user, pwd, proxy_host = self.options.proxy[: 4] proxy_port = 9050 proxy_host = proxy_host.split(':') if len(proxy_host) > 1: proxy_port = int(proxy_host[1]) proxy_host = proxy_host[0] self.socket = socks.socksocket() proxy_type = socks.PROXY_TYPE_SOCKS5 if proxy_proto == 'http': proxy_type = socks.PROXY_TYPE_HTTP elif proxy_proto == 'socks4': proxy_type = socks.PROXY_TYPE_SOCKS4 self.socket.setproxy(proxy_type, proxy_host, proxy_port, True, user, pwd) try: self.socket.connect((address, int(port))) except socks.Socks5AuthError: say_exception('Proxy error:') self.stop() self.handler = Handler(self.socket, self.channel_map, self) thread = Thread(target=self.asyncore_thread) thread.daemon = True thread.start() if not self.subscribe(): say_line('Failed to subscribe') self.stop() elif not self.authorize(): self.stop() except socket.error: say_exception() self.stop() continue with self.send_lock: self.process_result_queue() sleep(1)
def reconnect(self): say_line("%s reconnecting to %s", (self.server().name, self.server().host)) self.handler.close()
def get_temperature(self): response = request(self.device, b'ZLX') if response[0] != b'T' or len(response) < 23 or response[-1:] != b'\n': say_line('%s: bad response for temperature: %s', (self.id(), response)) return 0 return float(response[23:-1])
def handle_message(self, message): #Miner API if 'method' in message: #mining.notify if message['method'] == 'mining.notify': params = message['params'] j = Object() j.job_id = params[0] j.prevhash = params[1] j.coinbase1 = params[2] j.coinbase2 = params[3] j.merkle_branch = params[4] j.version = params[5] j.nbits = params[6] j.ntime = params[7] clear_jobs = params[8] if clear_jobs: self.jobs.clear() j.extranonce2 = self.extranonce2_size * '00' j = self.refresh_job(j) self.jobs[j.job_id] = j self.current_job = j self.queue_work(j) self.switch.connection_ok() #mining.get_version if message['method'] == 'mining.get_version': with self.send_lock: self.send_message({ "error": None, "id": message['id'], "result": self.user_agent }) #mining.set_difficulty elif message['method'] == 'mining.set_difficulty': say_line("Setting new difficulty: %s", message['params'][0]) self.server_difficulty = BASE_DIFFICULTY / message['params'][0] #client.reconnect elif message['method'] == 'client.reconnect': address, port = self.server().host.split(':', 1) (new_address, new_port, timeout) = message['params'][:3] if new_address: address = new_address if new_port != None: port = new_port say_line("%s asked us to reconnect to %s:%d in %d seconds", (self.server().name, address, port, timeout)) self.server().host = address + ':' + str(port) Timer(timeout, self.reconnect).start() #client.add_peers elif message['method'] == 'client.add_peers': hosts = [{ 'host': host[0], 'port': host[1] } for host in message['params'][0]] self.switch.add_servers(hosts) #responses to server API requests elif 'result' in message: #response to mining.subscribe #store extranonce and extranonce2_size if message['id'] == 's': self.extranonce = message['result'][1] self.extranonce2_size = message['result'][2] self.subscribed = True #check if this is submit confirmation (message id should be in submits dictionary) #cleanup if necessary elif message['id'] in self.submits: miner, nonce = self.submits[message['id']][:2] accepted = message['result'] self.switch.report(miner, nonce, accepted) del self.submits[message['id']] if time() - self.last_submits_cleanup > 3600: now = time() for key, value in self.submits.items(): if now - value[2] > 3600: del self.submits[key] self.last_submits_cleanup = now #response to mining.authorize elif message['id'] == self.server().user: if not message['result']: say_line('authorization failed with %s:%s@%s', (self.server().user, self.server().pwd, self.server().host)) self.authorized = False else: self.authorized = True
def mining_thread(self): say_line('started OpenCL miner on platform %d, device %d (%s)', (self.options.platform, self.device_index, self.device_name)) (self.defines, rate_divisor, hashspace) = if_else(self.vectors, ('-DVECTORS', 500, 0x7FFFFFFF), ('', 1000, 0xFFFFFFFF)) self.defines += (' -DOUTPUT_SIZE=' + str(self.output_size)) self.defines += (' -DOUTPUT_MASK=' + str(self.output_size - 1)) self.load_kernel() frame = 1.0 / max(self.frames, 3) unit = self.worksize * 256 global_threads = unit * 10 queue = cl.CommandQueue(self.context) last_rated_pace = last_rated = last_n_time = last_temperature = time() base = last_hash_rate = threads_run_pace = threads_run = 0 output = np.zeros(self.output_size + 1, np.uint32) output_buffer = cl.Buffer(self.context, cl.mem_flags.WRITE_ONLY | cl.mem_flags.USE_HOST_PTR, hostbuf=output) self.kernel.set_arg(20, output_buffer) work = None temperature = 0 while True: if self.should_stop: return sleep(self.frameSleep) if (not work) or (not self.work_queue.empty()): try: work = self.work_queue.get(True, 1) except Empty: continue else: if not work: continue nonces_left = hashspace state = work.state state2 = work.state2 f = work.f self.kernel.set_arg(0, state[0]) self.kernel.set_arg(1, state[1]) self.kernel.set_arg(2, state[2]) self.kernel.set_arg(3, state[3]) self.kernel.set_arg(4, state[4]) self.kernel.set_arg(5, state[5]) self.kernel.set_arg(6, state[6]) self.kernel.set_arg(7, state[7]) self.kernel.set_arg(8, state2[1]) self.kernel.set_arg(9, state2[2]) self.kernel.set_arg(10, state2[3]) self.kernel.set_arg(11, state2[5]) self.kernel.set_arg(12, state2[6]) self.kernel.set_arg(13, state2[7]) self.kernel.set_arg(15, f[0]) self.kernel.set_arg(16, f[1]) self.kernel.set_arg(17, f[2]) self.kernel.set_arg(18, f[3]) self.kernel.set_arg(19, f[4]) if temperature < self.cutoff_temp: self.kernel.set_arg(14, pack('I', base)) cl.enqueue_nd_range_kernel(queue, self.kernel, (global_threads,), (self.worksize,)) nonces_left -= global_threads threads_run_pace += global_threads threads_run += global_threads base = uint32(base + global_threads) else: threads_run_pace = 0 last_rated_pace = time() sleep(self.cutoff_interval) now = time() if self.adapterIndex != None: t = now - last_temperature if temperature >= self.cutoff_temp or t > 1: last_temperature = now with adl_lock: temperature = self.get_temperature() t = now - last_rated_pace if t > 1: rate = (threads_run_pace / t) / rate_divisor last_rated_pace = now; threads_run_pace = 0 r = last_hash_rate / rate if r < 0.9 or r > 1.1: global_threads = max(unit * int((rate * frame * rate_divisor) / unit), unit) last_hash_rate = rate t = now - last_rated if t > self.options.rate: self.update_rate(now, threads_run, t, work.targetQ, rate_divisor) last_rated = now; threads_run = 0 queue.finish() cl.enqueue_read_buffer(queue, output_buffer, output) queue.finish() if output[self.output_size]: result = Object() result.header = work.header result.merkle_end = work.merkle_end result.time = work.time result.difficulty = work.difficulty result.target = work.target result.state = np.array(state) result.nonces = np.array(output) result.job_id = work.job_id result.extranonce2 = work.extranonce2 result.server = work.server result.miner = self self.switch.put(result) output.fill(0) cl.enqueue_write_buffer(queue, output_buffer, output) if not self.switch.update_time: if nonces_left < 3 * global_threads * self.frames: self.update = True nonces_left += 0xFFFFFFFFFFFF elif 0xFFFFFFFFFFF < nonces_left < 0xFFFFFFFFFFFF: say_line('warning: job finished, %s is idle', self.id()) work = None elif now - last_n_time > 1: work.time = bytereverse(bytereverse(work.time) + 1) state2 = partial(state, work.merkle_end, work.time, work.difficulty, f) calculateF(state, work.merkle_end, work.time, work.difficulty, f, state2) self.kernel.set_arg(8, state2[1]) self.kernel.set_arg(9, state2[2]) self.kernel.set_arg(10, state2[3]) self.kernel.set_arg(11, state2[5]) self.kernel.set_arg(12, state2[6]) self.kernel.set_arg(13, state2[7]) self.kernel.set_arg(15, f[0]) self.kernel.set_arg(16, f[1]) self.kernel.set_arg(17, f[2]) self.kernel.set_arg(18, f[3]) self.kernel.set_arg(19, f[4]) last_n_time = now self.update_time_counter += 1 if self.update_time_counter >= self.switch.max_update_time: self.update = True self.update_time_counter = 1
def handle_message(self, message): #Miner API if 'method' in message: #mining.notify if message['method'] == 'mining.notify': params = message['params'] j = Object() j.job_id = params[0] j.prevhash = params[1] j.coinbase1 = params[2] j.coinbase2 = params[3] j.merkle_branch = params[4] j.version = params[5] j.nbits = params[6] j.ntime = params[7] clear_jobs = params[8] if clear_jobs: self.jobs.clear() j.extranonce2 = self.extranonce2_size * '00' j = self.refresh_job(j) self.jobs[j.job_id] = j self.current_job = j self.queue_work(j) self.switch.connection_ok() #mining.get_version if message['method'] == 'mining.get_version': with self.send_lock: self.send_message({"error": None, "id": message['id'], "result": self.user_agent}) #mining.set_difficulty elif message['method'] == 'mining.set_difficulty': say_line("Setting new difficulty: %s", message['params'][0]) self.server_difficulty = BASE_DIFFICULTY / message['params'][0] #client.reconnect elif message['method'] == 'client.reconnect': address, port = self.server().host.split(':', 1) (new_address, new_port, timeout) = message['params'][:3] if new_address: address = new_address if new_port != None: port = new_port say_line("%s asked us to reconnect to %s:%d in %d seconds", (self.server().name, address, port, timeout)) self.server().host = address + ':' + str(port) Timer(timeout, self.reconnect).start() #client.add_peers elif message['method'] == 'client.add_peers': hosts = [{'host': host[0], 'port': host[1]} for host in message['params'][0]] self.switch.add_servers(hosts) #responses to server API requests elif 'result' in message: #response to mining.subscribe #store extranonce and extranonce2_size if message['id'] == 's': self.extranonce = message['result'][1] self.extranonce2_size = message['result'][2] self.subscribed = True #check if this is submit confirmation (message id should be in submits dictionary) #cleanup if necessary elif message['id'] in self.submits: miner, nonce = self.submits[message['id']][:2] accepted = message['result'] self.switch.report(miner, nonce, accepted) del self.submits[message['id']] if time() - self.last_submits_cleanup > 3600: now = time() for key, value in self.submits.items(): if now - value[2] > 3600: del self.submits[key] self.last_submits_cleanup = now #response to mining.authorize elif message['id'] == self.server().user: if not message['result']: say_line('authorization failed with %s:%s@%s', (self.server().user, self.server().pwd, self.server().host)) self.authorized = False else: self.authorized = True
def mining_thread(self): say_line('started OpenCL miner on platform %d, device %d (%s)', (self.options.platform, self.device_index, self.device_name)) (self.defines, rate_divisor, hashspace) = ('', 1000, 0xFFFFFFFF) self.defines += (' -D%sOUTPUT_SIZE=%s' % (self.defspace, str(self.output_size))) self.defines += (' -D%sOUTPUT_MASK=%s' % (self.defspace, str(self.output_size - 1))) self.defines += (' -D%sENDIAN_LITTLE=%d' % (self.defspace, self.device.endian_little)) self.defines += (' -D%sGPU_AMD=%d' % (self.defspace, self.gpu_amd)) self.defines += (' -I%s%s' % (self.defspace, os.getcwd())) say_line("Compiler defines: %s", self.defines) self.load_kernel() frame = 1.0 / max(self.frames, 3) unit = self.worksize * 256 global_threads = unit * 10 queue = cl.CommandQueue(self.context) last_rated_pace = last_rated = last_n_time = last_temperature = time() base = last_hash_rate = threads_run_pace = threads_run = 0 output = bytearray((self.output_size + 1) * 4) output_buffer = cl.Buffer(self.context, cl.mem_flags.WRITE_ONLY | cl.mem_flags.USE_HOST_PTR, hostbuf=output) self.kernel.set_arg(12, output_buffer) work = None temperature = 0 while True: if self.should_stop: return sleep(self.frameSleep) if (not work) or (not self.work_queue.empty()): try: work = self.work_queue.get(True, 1) except Empty: continue else: if not work: continue nonces_left = hashspace self.queue_kernel_parameters(work) if temperature < self.cutoff_temp: self.kernel.set_arg(11, pack('<I', base)) cl.enqueue_nd_range_kernel(queue, self.kernel, (global_threads,), (self.worksize,)) nonces_left -= global_threads threads_run_pace += global_threads threads_run += global_threads base = uint32(base + global_threads) else: threads_run_pace = 0 last_rated_pace = time() sleep(self.cutoff_interval) now = time() if self.adapterIndex is not None: t = now - last_temperature if temperature >= self.cutoff_temp or t > 1: last_temperature = now with adl_lock: self.temperature = self.get_temperature() temperature = self.temperature t = now - last_rated_pace if t > 1: rate = (threads_run_pace / t) / rate_divisor last_rated_pace = now; threads_run_pace = 0 r = last_hash_rate / rate if r < 0.9 or r > 1.1: global_threads = max(unit * int((rate * frame * rate_divisor) / unit), unit) last_hash_rate = rate t = now - last_rated if t > self.options.rate: self.update_rate(now, threads_run, t, work.targetQ, rate_divisor) last_rated = now; threads_run = 0 queue.finish() cl.enqueue_read_buffer(queue, output_buffer, output) queue.finish() if output[-1]: result = Object() result.header = work.header result.headerX = work.headerX result.merkle_end = work.merkle_end result.time = work.time result.difficulty = work.difficulty result.target = work.target result.dataX = work.dataX[:] result.nonces = output[:] result.job_id = work.job_id result.extranonce2 = work.extranonce2 result.server = work.server result.miner = self self.switch.put(result) output[:] = b'\x00' * len(output) cl.enqueue_write_buffer(queue, output_buffer, output) for miner in self.switch.miners: miner.update = True if not self.switch.update_time: if nonces_left < 6 * global_threads * self.frames: self.update = True nonces_left += 0xFFFFFFFFFFFF elif 0xFFFFFFFFFFF < nonces_left < 0xFFFFFFFFFFFF: say_line('warning: job finished, %s is idle', self.id()) work = None elif now - last_n_time > 1: last_n_time = now self.update_time_counter += 1 if self.update_time_counter >= self.switch.max_update_time: self.update = True self.update_time_counter = 1