import time import copy import threading import uuid import string, random, hashlib, datetime from multiprocessing import Process, Manager, Event from libs.noSys.noSysModule import NoSysModule from .minerApiBlueprint import Blueprint from .minerSocketio import HandlerSocketio class Miner(NoSysModule): def __init__(self, nosys_core): super().__init__(nosys_core) self.manager = Manager() self.tasks = {} def setup(self): self.nosys_core.modules.api.register_blueprint(Blueprint(self).blueprint) self.socketio = HandlerSocketio(self) self.nosys_core.modules.api.register_socketio(self.socketio) def monitor_task_result(self, task_id, result): last_state = {} while True: try: current_state = dict(result) except Exception: break if current_state != last_state: self.socketio.emit("taskUpdated", { "task_id": task_id, "result": current_state }) last_state = copy.deepcopy(current_state) if current_state.get("status") in ("completed", "cancelled", "error"): break time.sleep(1) def start_mining(self, force, data, nonce_length): task_id = str(uuid.uuid4()) result = self.manager.dict({ "status": "running", "target_force": force, "data": data, "nonce": None, "hash": None, "best_nonce": None, "best_hash": None, "best_force": 0, "attempts": 0, "duration": 0, }) stop_event = Event() pause_event = Event() proc = Process(target=self.mine_worker, args=(data, force, nonce_length, result, stop_event, pause_event)) proc.start() monitor_thread = threading.Thread( target=self.monitor_task_result, args=(task_id, result), daemon=True ) monitor_thread.start() self.tasks[task_id] = { "process": proc, "result": result, "stop_event": stop_event, "pause_event": pause_event, } return task_id def pause_task(self, task_id): task = self.tasks.get(task_id) if not task: return False task["pause_event"].set() task["result"]["status"] = "paused" return True def resume_task(self, task_id): task = self.tasks.get(task_id) if not task: return False task["pause_event"].clear() task["result"]["status"] = "running" return True def cancel_task(self, task_id): task = self.tasks.get(task_id) if not task: return False task["stop_event"].set() task["process"].terminate() task["process"].join() task["result"]["status"] = "cancelled" return True @staticmethod def mine_worker(public_key, force, nonce_length, result_dict, stop_event, pause_event): def hash_string(text): return hashlib.sha256(text.encode('utf-8')).hexdigest() def random_nonce(characters, length): return ''.join(random.choices(characters, k=length)) def count_leading_zeros(hex_hash): return len(hex_hash) - len(hex_hash.lstrip("0")) characters = string.ascii_letters + string.digits + '[@_!#$%^&*()<>?/\\|}{~:]' attempts = 0 best_force = -1 start_time = datetime.datetime.now() while not stop_event.is_set(): if pause_event.is_set(): pause_event.wait(1) continue nonce = random_nonce(characters, nonce_length) hash_result = hash_string(public_key + nonce) attempts += 1 leading_zeros = count_leading_zeros(hash_result) if leading_zeros > best_force: best_force = leading_zeros result_dict.update({ "best_nonce": nonce, "best_hash": hash_result, "best_force": best_force, "attempts": attempts, }) if leading_zeros >= force: duration = (datetime.datetime.now() - start_time).total_seconds() result_dict.update({ "status": "completed", "nonce": nonce, "hash": hash_result, "attempts": attempts, "duration": duration, "best_force": leading_zeros, "best_nonce": nonce, "best_hash": hash_result, }) stop_event.set() break if stop_event.is_set() and result_dict.get("status") not in ("completed", "cancelled"): result_dict.update({ "status": "cancelled", "duration": (datetime.datetime.now() - start_time).total_seconds(), })