Files
nosys_libs/lockbox/miner.py
2026-01-25 13:55:46 +10:00

162 lines
5.0 KiB
Python

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(),
})