def partial(state, merkle_end, time, difficulty, f): state2 = list(state) data0 = merkle_end data1 = time data2 = difficulty data = (data0, data1, data2) for i in range(3): (state2[~(i - 4) & 7], state2[~(i - 8) & 7]) = sharound(state2[(~(i - 1) & 7)], state2[~(i - 2) & 7], state2[~(i - 3) & 7], state2[~(i - 4) & 7], state2[~(i - 5) & 7], state2[~(i - 6) & 7], state2[~(i - 7) & 7], state2[~(i - 8) & 7], data[i], K[i]) f[0] = uint32(data0 + (rotr(data1, 7) ^ rotr(data1, 18) ^ (data1 >> 3))) f[1] = uint32(data1 + (rotr(data2, 7) ^ rotr(data2, 18) ^ (data2 >> 3)) + 0x01100000) f[2] = uint32(data2 + (rotr(f[0], 17) ^ rotr(f[0], 19) ^ (f[0] >> 10))) f[3] = uint32(0x11002000 + (rotr(f[1], 17) ^ rotr(f[1], 19) ^ (f[1] >> 10))) f[4] = uint32(0x00000280 + (rotr(f[0], 7) ^ rotr(f[0], 18) ^ (f[0] >> 3))) f[5] = uint32(f[0] + (rotr(f[1], 7) ^ rotr(f[1], 18) ^ (f[1] >> 3))) f[6] = uint32(state[4] + (rotr(state2[1], 6) ^ rotr(state2[1], 11) ^ rotr(state2[1], 25)) + ( state2[3] ^ (state2[1] & (state2[2] ^ state2[3]))) + 0xe9b5dba5) f[7] = uint32((rotr(state2[5], 2) ^ rotr(state2[5], 13) ^ rotr(state2[5], 22)) + ( (state2[5] & state2[6]) | (state2[7] & (state2[5] | state2[6])))) return state2
def calculateF(state, merkle_end, time, difficulty, f, state2): data0 = merkle_end data1 = time data2 = difficulty # W2 f[0] = uint32(data2) # W16 f[1] = uint32(data0 + (rotr(data1, 7) ^ rotr(data1, 18) ^ (data1 >> 3))) # W17 f[2] = uint32(data1 + (rotr(data2, 7) ^ rotr(data2, 18) ^ (data2 >> 3)) + 0x01100000) # 2 parts of the first SHA round f[3] = uint32(state[4] + (rotr(state2[1], 6) ^ rotr(state2[1], 11) ^ rotr(state2[1], 25)) + (state2[3] ^ (state2[1] & (state2[2] ^ state2[3]))) + 0xe9b5dba5) f[4] = uint32((rotr(state2[5], 2) ^ rotr(state2[5], 13) ^ rotr(state2[5], 22)) + ((state2[5] & state2[6]) | (state2[7] & (state2[5] | state2[6]))))
def decode(self, server, block_header, target, job_id=None, extranonce2=None): if block_header: job = Object() binary_data = unhexlify(block_header) data0 = list(unpack('<16I', binary_data[:64])) + ([0] * 48) job.target = unpack('<8I', unhexlify(target)) job.header = binary_data[:68] job.merkle_end = uint32(unpack('<I', binary_data[64:68])[0]) job.time = uint32(unpack('<I', binary_data[68:72])[0]) job.difficulty = uint32(unpack('<I', binary_data[72:76])[0]) job.state = sha256(STATE, data0) job.targetQ = 2 ** 256 // int(''.join(list(chunks(target, 2))[::-1]), 16) job.job_id = job_id job.extranonce2 = extranonce2 job.server = server if job.difficulty != self.difficulty: self.set_difficulty(job.difficulty) return job
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(int(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 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(int(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 sha256(state, data): digest = list(state) for i in range(64): if i > 15: data[i] = R(data[i - 2], data[i - 7], data[i - 15], data[i - 16]) (digest[~(i - 4) & 7], digest[~(i - 8) & 7]) = sharound(digest[(~(i - 1) & 7)], digest[~(i - 2) & 7], digest[~(i - 3) & 7], digest[~(i - 4) & 7], digest[~(i - 5) & 7], digest[~(i - 6) & 7], digest[~(i - 7) & 7], digest[~(i - 8) & 7], data[i], K[i]) result = [ uint32(digest[0] + state[0]), uint32(digest[1] + state[1]), uint32(digest[2] + state[2]), uint32(digest[3] + state[3]), uint32(digest[4] + state[4]), uint32(digest[5] + state[5]), uint32(digest[6] + state[6]), uint32(digest[7] + state[7]) ] return result
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 = uint32(int( time())) - bytereverse(self.job.time) 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 mining_thread(self): say_line('started OpenCL miner on platform %d, device %d (%s)', (self.options.platform, self.device_idx, self.device_name)) self.defines, rate_divisor, hashspace = ( '-D VECTORS', 500, 0x7FFFFFFF ) if self.vectors else ( '', 1000, 0xFFFFFFFF ) self.defines += ( f' -D OUTPUT_SIZE={self.output_size}' f' -D OUTPUT_MASK={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 = monotonic() base = last_hash_rate = threads_run_pace = threads_run = 0 blank_output = b'\x00' * ((self.output_size + 1) * 4) host_output = bytearray(blank_output) cl_output = cl.Buffer( self.context, cl.mem_flags.WRITE_ONLY, size=len(host_output) ) cl.enqueue_copy(queue, cl_output, blank_output) self.kernel.set_arg(20, cl_output) work = None temperature = 0 while True: if self.should_stop: return sleep(self.frame_sleep) 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 f = [0, 0, 0, 0, 0, 0, 0, 0] state2 = partial(state, work.merkle_end, work.time, work.difficulty, f) calculateF(state, work.merkle_end, work.time, work.difficulty, f, state2) set_arg = self.kernel.set_arg set_arg(0, uint32_as_bytes(state[0])) set_arg(1, uint32_as_bytes(state[1])) set_arg(2, uint32_as_bytes(state[2])) set_arg(3, uint32_as_bytes(state[3])) set_arg(4, uint32_as_bytes(state[4])) set_arg(5, uint32_as_bytes(state[5])) set_arg(6, uint32_as_bytes(state[6])) set_arg(7, uint32_as_bytes(state[7])) set_arg(8, uint32_as_bytes(state2[1])) set_arg(9, uint32_as_bytes(state2[2])) set_arg(10, uint32_as_bytes(state2[3])) set_arg(11, uint32_as_bytes(state2[5])) set_arg(12, uint32_as_bytes(state2[6])) set_arg(13, uint32_as_bytes(state2[7])) set_arg(15, uint32_as_bytes(f[0])) set_arg(16, uint32_as_bytes(f[1])) set_arg(17, uint32_as_bytes(f[2])) set_arg(18, uint32_as_bytes(f[3])) set_arg(19, uint32_as_bytes(f[4])) if temperature < self.cutoff_temp: self.kernel.set_arg(14, uint32_as_bytes(base)) cl.enqueue_nd_range_kernel(queue, self.kernel, (global_threads,), self.execution_local_dims) 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 = monotonic() sleep(self.cutoff_interval) now = monotonic() if self.adapter_idx is not 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 cl.enqueue_copy(queue, host_output, cl_output) queue.finish() if host_output[-1]: 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 = tuple(state) result.nonces = host_output[:] result.job_id = work.job_id result.extranonce2 = work.extranonce2 result.transactions = work.transactions result.server = work.server result.miner = self self.switch.put(result) cl.enqueue_copy(queue, cl_output, blank_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) set_arg = self.kernel.set_arg set_arg(8, uint32_as_bytes(state2[1])) set_arg(9, uint32_as_bytes(state2[2])) set_arg(10, uint32_as_bytes(state2[3])) set_arg(11, uint32_as_bytes(state2[5])) set_arg(12, uint32_as_bytes(state2[6])) set_arg(13, uint32_as_bytes(state2[7])) set_arg(15, uint32_as_bytes(f[0])) set_arg(16, uint32_as_bytes(f[1])) set_arg(17, uint32_as_bytes(f[2])) set_arg(18, uint32_as_bytes(f[3])) set_arg(19, uint32_as_bytes(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 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) = ( vectors_definition(), 500, 0x7FFFFFFF) if self.vectors else ( '', 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 = 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(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 f = [0] * 8 state2 = partial(state, work.merkle_end, work.time, work.difficulty, f) calculateF(state, work.merkle_end, work.time, work.difficulty, f, state2) set_arg = self.kernel.set_arg set_arg(0, uint32_as_bytes(state[0])) set_arg(1, uint32_as_bytes(state[1])) set_arg(2, uint32_as_bytes(state[2])) set_arg(3, uint32_as_bytes(state[3])) set_arg(4, uint32_as_bytes(state[4])) set_arg(5, uint32_as_bytes(state[5])) set_arg(6, uint32_as_bytes(state[6])) set_arg(7, uint32_as_bytes(state[7])) set_arg(8, uint32_as_bytes(state2[1])) set_arg(9, uint32_as_bytes(state2[2])) set_arg(10, uint32_as_bytes(state2[3])) set_arg(11, uint32_as_bytes(state2[5])) set_arg(12, uint32_as_bytes(state2[6])) set_arg(13, uint32_as_bytes(state2[7])) set_arg(15, uint32_as_bytes(f[0])) set_arg(16, uint32_as_bytes(f[1])) set_arg(17, uint32_as_bytes(f[2])) set_arg(18, uint32_as_bytes(f[3])) set_arg(19, uint32_as_bytes(f[4])) if temperature < self.cutoff_temp: self.kernel.set_arg(14, uint32_as_bytes(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_copy(queue, output_buffer, output) queue.finish() if output[-1]: 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 = list(state) result.nonces = output[:] result.job_id = work.job_id result.extranonce2 = work.extranonce2 result.transactions = work.transactions result.server = work.server result.miner = self self.switch.put(result) output[:] = b'\x00' * len(output) cl.enqueue_copy(queue, output, output_buffer) 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) set_arg = self.kernel.set_arg set_arg(8, uint32_as_bytes(state2[1])) set_arg(9, uint32_as_bytes(state2[2])) set_arg(10, uint32_as_bytes(state2[3])) set_arg(11, uint32_as_bytes(state2[5])) set_arg(12, uint32_as_bytes(state2[6])) set_arg(13, uint32_as_bytes(state2[7])) set_arg(15, uint32_as_bytes(f[0])) set_arg(16, uint32_as_bytes(f[1])) set_arg(17, uint32_as_bytes(f[2])) set_arg(18, uint32_as_bytes(f[3])) set_arg(19, uint32_as_bytes(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 try_kernel(platform_idx, device_idx): platforms = cl.get_platforms() device = platforms[platform_idx].get_devices()[device_idx] worksize = device.get_info(cl.device_info.MAX_WORK_GROUP_SIZE) context = cl.Context([device], None, None) output_size = 256 host_out_buffer = bytearray((output_size + 1) * 4) cl_out_buffer = cl.Buffer(context, cl.mem_flags.WRITE_ONLY, size=len(host_out_buffer) # hostbuf=host_out_buffer ) defines = ( f'-D OUTPUT_SIZE={output_size} -D OUTPUT_MASK={output_size - 1} ' f'-D WORK_GROUP_SIZE={worksize}') if device.extensions.find('cl_amd_media_ops') != -1: print('AMD bitalign defined!') defines += ' -DBITALIGN' kernel_code = pkgutil.get_data('apoclypsebm', 'apoclypse-0.cl').decode('ascii') print(f'Building with {defines}') program = cl.Program(context, kernel_code).build(defines) kernel_bin_file_name = file_safe_sanitize( f'{device.platform.name}-{device.platform.version}-{device.name}.elf') with open(kernel_bin_file_name, 'wb') as binary: binary.write(program.binaries[0]) print(f'Wrote kernel to {kernel_bin_file_name}') kernel = program.search frame = 1.0 / DEFAULT_FRAMES unit = worksize * 256 global_threads = unit * 10 print( f'worksize: {worksize}, unit: {unit}, global_threads: {global_threads}' ) kernel.set_arg(20, cl_out_buffer) base = 0 work = None # TODO rate_divisor, hashspace = 1000, 0xFFFFFFFF # assumes not vectorized nonces_left = hashspace with open('../example_blochheader_block.txt') as block_file: binary_data = unhexlify(block_file.read())[:76] # Swap every uint32 for sha256… swapped_bin = bytearray() for i in range(-1, len(binary_data) - 1, 4): new_word = binary_data[i + 4:None if i == -1 else i:-1] swapped_bin += new_word # print(f'slicing {i + 3}:{i or None}:{-1} gives {new_word.hex()}') print(f'Initial: {binary_data.hex()}') print(f'SHA2 chunked: {swapped_bin.hex()}') midstate_input = list(unpack('<16I', swapped_bin[:64])) + ([0] * 48) midstate = sha256(STATE, midstate_input) merkle_end = uint32(unpack('<I', swapped_bin[64:68])[0]) time = uint32(unpack('<I', swapped_bin[68:72])[0]) difficulty = uint32(unpack('<I', swapped_bin[72:76])[0]) base = 316141196 - 0 # -10 from the winner print(f'') state = list(midstate) f = [0] * 8 state2 = partial(state, merkle_end, time, difficulty, f) print(f'state2 and f: {state2}, {f}') calculateF(state, merkle_end, time, difficulty, f, state2) print(f'state and f after fcalc: {state}, {f}') kernel.set_arg(0, uint32_as_bytes(state[0])) kernel.set_arg(1, uint32_as_bytes(state[1])) kernel.set_arg(2, uint32_as_bytes(state[2])) kernel.set_arg(3, uint32_as_bytes(state[3])) kernel.set_arg(4, uint32_as_bytes(state[4])) kernel.set_arg(5, uint32_as_bytes(state[5])) kernel.set_arg(6, uint32_as_bytes(state[6])) kernel.set_arg(7, uint32_as_bytes(state[7])) kernel.set_arg(8, uint32_as_bytes(state2[1])) kernel.set_arg(9, uint32_as_bytes(state2[2])) kernel.set_arg(10, uint32_as_bytes(state2[3])) kernel.set_arg(11, uint32_as_bytes(state2[5])) kernel.set_arg(12, uint32_as_bytes(state2[6])) kernel.set_arg(13, uint32_as_bytes(state2[7])) kernel.set_arg(15, uint32_as_bytes(f[0])) kernel.set_arg(16, uint32_as_bytes(f[1])) kernel.set_arg(17, uint32_as_bytes(f[2])) kernel.set_arg(18, uint32_as_bytes(f[3])) kernel.set_arg(19, uint32_as_bytes(f[4])) # This part usually done after temperature check: print(f'Starting with base {base}') kernel.set_arg(14, uint32_as_bytes(base)[::-1]) cmd_queue = cl.CommandQueue(context) cl.enqueue_copy(cmd_queue, cl_out_buffer, host_out_buffer) cl.enqueue_nd_range_kernel(cmd_queue, kernel, (global_threads, ), (worksize, )) cl.enqueue_copy(cmd_queue, host_out_buffer, cl_out_buffer) cmd_queue.finish() print(f'Got {len(host_out_buffer)} outputs:') print(' '.join([f'{nonce:02x}' for nonce in host_out_buffer])) nonces_left -= global_threads # threads_run_pace += global_threads # threads_run += global_threads base = uint32(base + global_threads)
def sharound(a, b, c, d, e, f, g, h, x, k): t1 = h + (rot(e, 26) ^ rot(e, 21) ^ rot(e, 7)) + (g ^ (e & (f ^ g))) + k + x t2 = (rot(a, 30) ^ rot(a, 19) ^ rot(a, 10)) + ((a & b) | (c & (a | b))) return (uint32(d + t1), uint32(t1 + t2))
def R(x2, x7, x15, x16): return uint32((rot(x2, 15) ^ rot(x2, 13) ^ ((x2) >> 10)) + x7 + (rot(x15, 25) ^ rot(x15, 14) ^ ((x15) >> 3)) + x16)
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 = uint32( int(time())) - bytereverse(self.job.time) 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)