Fix SSL certificate verification on macOS by adding certifi support and proper SSL context
This commit is contained in:
+65
-48
@@ -19,6 +19,7 @@ import re
|
|||||||
import threading
|
import threading
|
||||||
import tempfile
|
import tempfile
|
||||||
import shutil
|
import shutil
|
||||||
|
import ssl
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Optional, Tuple, List
|
from typing import Dict, Optional, Tuple, List
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -33,6 +34,7 @@ class MoneroMiner:
|
|||||||
self.stats_thread = None
|
self.stats_thread = None
|
||||||
self.stop_stats = False
|
self.stop_stats = False
|
||||||
self.has_nvidia_gpu = False
|
self.has_nvidia_gpu = False
|
||||||
|
self.ssl_context = self.setup_ssl_context()
|
||||||
|
|
||||||
# Known mining pools (with minimum payout amounts)
|
# Known mining pools (with minimum payout amounts)
|
||||||
self.known_pools = [
|
self.known_pools = [
|
||||||
@@ -43,9 +45,24 @@ class MoneroMiner:
|
|||||||
{"name": "HeroMiners", "address": "monero.herominers.com:1111", "tls": False, "coin": "XMR", "min_payout": "0.1 XMR"},
|
{"name": "HeroMiners", "address": "monero.herominers.com:1111", "tls": False, "coin": "XMR", "min_payout": "0.1 XMR"},
|
||||||
{"name": "C3Pool", "address": "mine.c3pool.com:13333", "tls": False, "coin": None, "min_payout": "0.001 XMR", "no_api": True},
|
{"name": "C3Pool", "address": "mine.c3pool.com:13333", "tls": False, "coin": None, "min_payout": "0.001 XMR", "no_api": True},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def setup_ssl_context(self):
|
||||||
|
# Setup SSL context with proper certificates for macOS
|
||||||
|
try:
|
||||||
|
import certifi
|
||||||
|
# Create SSL context with certifi certificates
|
||||||
|
context = ssl.create_default_context(cafile=certifi.where())
|
||||||
|
return context
|
||||||
|
except ImportError:
|
||||||
|
# Fallback: use default SSL context
|
||||||
|
try:
|
||||||
|
return ssl.create_default_context()
|
||||||
|
except:
|
||||||
|
# Last resort: unverified context (not recommended but works)
|
||||||
|
return ssl._create_unverified_context()
|
||||||
|
|
||||||
def detect_os(self) -> str:
|
def detect_os(self) -> str:
|
||||||
"""Detect the operating system"""
|
# Detect the operating system
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
if system == 'Darwin':
|
if system == 'Darwin':
|
||||||
return 'macos'
|
return 'macos'
|
||||||
@@ -57,7 +74,7 @@ class MoneroMiner:
|
|||||||
return 'unknown'
|
return 'unknown'
|
||||||
|
|
||||||
def detect_cpu_arch(self) -> str:
|
def detect_cpu_arch(self) -> str:
|
||||||
"""Detect CPU architecture"""
|
# Detect CPU architecture
|
||||||
machine = platform.machine().lower()
|
machine = platform.machine().lower()
|
||||||
if machine in ['arm64', 'aarch64']:
|
if machine in ['arm64', 'aarch64']:
|
||||||
return 'arm64'
|
return 'arm64'
|
||||||
@@ -69,7 +86,7 @@ class MoneroMiner:
|
|||||||
return machine
|
return machine
|
||||||
|
|
||||||
def detect_cpu_model(self) -> str:
|
def detect_cpu_model(self) -> str:
|
||||||
"""Detect the specific CPU model for worker naming"""
|
# Detect the specific CPU model for worker naming
|
||||||
try:
|
try:
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
|
|
||||||
@@ -146,7 +163,7 @@ class MoneroMiner:
|
|||||||
return "arm64" if arch == 'arm64' else "x64"
|
return "arm64" if arch == 'arm64' else "x64"
|
||||||
|
|
||||||
def detect_nvidia_gpu(self) -> bool:
|
def detect_nvidia_gpu(self) -> bool:
|
||||||
"""Detect if an NVIDIA GPU is present"""
|
# Detect if an NVIDIA GPU is present
|
||||||
os_type = self.detect_os()
|
os_type = self.detect_os()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -185,13 +202,13 @@ class MoneroMiner:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def get_latest_xmrig_release(self) -> Optional[Tuple[str, list]]:
|
def get_latest_xmrig_release(self) -> Optional[Tuple[str, list]]:
|
||||||
"""Fetch the latest XMRig version and available files from GitHub"""
|
# Fetch the latest XMRig version and available files from GitHub
|
||||||
try:
|
try:
|
||||||
url = "https://api.github.com/repos/xmrig/xmrig/releases/latest"
|
url = "https://api.github.com/repos/xmrig/xmrig/releases/latest"
|
||||||
req = urllib.request.Request(url)
|
req = urllib.request.Request(url)
|
||||||
req.add_header('User-Agent', 'Mozilla/5.0')
|
req.add_header('User-Agent', 'Mozilla/5.0')
|
||||||
|
|
||||||
with urllib.request.urlopen(req, timeout=10) as response:
|
with urllib.request.urlopen(req, timeout=10, context=self.ssl_context) as response:
|
||||||
data = json.loads(response.read().decode())
|
data = json.loads(response.read().decode())
|
||||||
version = data['tag_name'].lstrip('v')
|
version = data['tag_name'].lstrip('v')
|
||||||
|
|
||||||
@@ -204,13 +221,13 @@ class MoneroMiner:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def get_latest_gminer_release(self) -> Optional[Tuple[str, List[dict]]]:
|
def get_latest_gminer_release(self) -> Optional[Tuple[str, List[dict]]]:
|
||||||
"""Fetch the latest GMiner version and available files from GitHub"""
|
# Fetch the latest GMiner version and available files from GitHub
|
||||||
try:
|
try:
|
||||||
url = "https://api.github.com/repos/develsoftware/GMinerRelease/releases/latest"
|
url = "https://api.github.com/repos/develsoftware/GMinerRelease/releases/latest"
|
||||||
req = urllib.request.Request(url)
|
req = urllib.request.Request(url)
|
||||||
req.add_header('User-Agent', 'Mozilla/5.0')
|
req.add_header('User-Agent', 'Mozilla/5.0')
|
||||||
|
|
||||||
with urllib.request.urlopen(req, timeout=10) as response:
|
with urllib.request.urlopen(req, timeout=10, context=self.ssl_context) as response:
|
||||||
data = json.loads(response.read().decode())
|
data = json.loads(response.read().decode())
|
||||||
version = data['tag_name'].lstrip('v')
|
version = data['tag_name'].lstrip('v')
|
||||||
|
|
||||||
@@ -228,7 +245,7 @@ class MoneroMiner:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def find_matching_file(self, assets: list, os_type: str, arch: str) -> Optional[str]:
|
def find_matching_file(self, assets: list, os_type: str, arch: str) -> Optional[str]:
|
||||||
"""Find the matching file for the given OS and architecture"""
|
# Find the matching file for the given OS and architecture
|
||||||
# Build search patterns based on OS and architecture
|
# Build search patterns based on OS and architecture
|
||||||
if os_type == 'macos':
|
if os_type == 'macos':
|
||||||
if arch == 'arm64':
|
if arch == 'arm64':
|
||||||
@@ -263,7 +280,7 @@ class MoneroMiner:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def find_matching_gminer_file(self, assets: List[dict], os_type: str) -> Optional[dict]:
|
def find_matching_gminer_file(self, assets: List[dict], os_type: str) -> Optional[dict]:
|
||||||
"""Find the matching GMiner file for the given OS"""
|
# Find the matching GMiner file for the given OS
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
name = asset['name'].lower()
|
name = asset['name'].lower()
|
||||||
if os_type == 'windows' and 'windows' in name and name.endswith('.zip'):
|
if os_type == 'windows' and 'windows' in name and name.endswith('.zip'):
|
||||||
@@ -273,7 +290,7 @@ class MoneroMiner:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def check_xmrig_installed(self) -> bool:
|
def check_xmrig_installed(self) -> bool:
|
||||||
"""Check if xmrig is installed"""
|
# Check if xmrig is installed
|
||||||
# Check in script directory first
|
# Check in script directory first
|
||||||
local_paths = [
|
local_paths = [
|
||||||
os.path.join(self.script_dir, 'xmrig'),
|
os.path.join(self.script_dir, 'xmrig'),
|
||||||
@@ -310,7 +327,7 @@ class MoneroMiner:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def check_gminer_installed(self) -> bool:
|
def check_gminer_installed(self) -> bool:
|
||||||
"""Check if GMiner is installed in script directory"""
|
# Check if GMiner is installed in script directory
|
||||||
os_type = self.detect_os()
|
os_type = self.detect_os()
|
||||||
|
|
||||||
if os_type == 'windows':
|
if os_type == 'windows':
|
||||||
@@ -321,14 +338,14 @@ class MoneroMiner:
|
|||||||
return os.path.exists(gminer_path) and os.access(gminer_path, os.X_OK if os.name != 'nt' else os.F_OK)
|
return os.path.exists(gminer_path) and os.access(gminer_path, os.X_OK if os.name != 'nt' else os.F_OK)
|
||||||
|
|
||||||
def download_file_with_progress(self, url: str, local_filename: str, max_retries: int = 3) -> bool:
|
def download_file_with_progress(self, url: str, local_filename: str, max_retries: int = 3) -> bool:
|
||||||
"""Download a file with progress indication and retry logic"""
|
# Download a file with progress indication and retry logic
|
||||||
for attempt in range(max_retries):
|
for attempt in range(max_retries):
|
||||||
try:
|
try:
|
||||||
req = urllib.request.Request(url)
|
req = urllib.request.Request(url)
|
||||||
req.add_header('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36')
|
req.add_header('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36')
|
||||||
req.add_header('Accept', '*/*')
|
req.add_header('Accept', '*/*')
|
||||||
|
|
||||||
with urllib.request.urlopen(req, timeout=30) as response:
|
with urllib.request.urlopen(req, timeout=30, context=self.ssl_context) as response:
|
||||||
total_size = int(response.headers.get('Content-Length', 0))
|
total_size = int(response.headers.get('Content-Length', 0))
|
||||||
downloaded = 0
|
downloaded = 0
|
||||||
|
|
||||||
@@ -365,7 +382,7 @@ class MoneroMiner:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def download_and_install_xmrig(self) -> bool:
|
def download_and_install_xmrig(self) -> bool:
|
||||||
"""Download and install XMRig based on OS and architecture"""
|
# Download and install XMRig based on OS and architecture
|
||||||
os_type = self.detect_os()
|
os_type = self.detect_os()
|
||||||
arch = self.detect_cpu_arch()
|
arch = self.detect_cpu_arch()
|
||||||
|
|
||||||
@@ -551,7 +568,7 @@ class MoneroMiner:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def download_and_install_gminer(self) -> bool:
|
def download_and_install_gminer(self) -> bool:
|
||||||
"""Download and install GMiner for GPU mining"""
|
# Download and install GMiner for GPU mining
|
||||||
os_type = self.detect_os()
|
os_type = self.detect_os()
|
||||||
|
|
||||||
# GMiner only supports Windows and Linux
|
# GMiner only supports Windows and Linux
|
||||||
@@ -671,7 +688,7 @@ class MoneroMiner:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def prompt_wallet_address(self) -> str:
|
def prompt_wallet_address(self) -> str:
|
||||||
"""Prompt user for wallet address"""
|
# Prompt user for wallet address
|
||||||
default_wallet = "85NGrygcwq36kjLaNKZevT53H4EeHRQYeje5Y3gq3GYkKsEpwKpGjqd1tGxAVEjDfxEha6SYtyNYPbmPXduYqy47Q6JwbuW"
|
default_wallet = "85NGrygcwq36kjLaNKZevT53H4EeHRQYeje5Y3gq3GYkKsEpwKpGjqd1tGxAVEjDfxEha6SYtyNYPbmPXduYqy47Q6JwbuW"
|
||||||
|
|
||||||
print("\n" + "="*60)
|
print("\n" + "="*60)
|
||||||
@@ -692,7 +709,7 @@ class MoneroMiner:
|
|||||||
return wallet
|
return wallet
|
||||||
|
|
||||||
def prompt_pool_selection(self) -> Tuple[str, bool, Optional[str]]:
|
def prompt_pool_selection(self) -> Tuple[str, bool, Optional[str]]:
|
||||||
"""Prompt user to select a mining pool"""
|
# Prompt user to select a mining pool
|
||||||
print("\n" + "="*60)
|
print("\n" + "="*60)
|
||||||
print("Mining Pool Selection")
|
print("Mining Pool Selection")
|
||||||
print("="*60)
|
print("="*60)
|
||||||
@@ -748,7 +765,7 @@ class MoneroMiner:
|
|||||||
print("Please enter a valid number or press ENTER for default")
|
print("Please enter a valid number or press ENTER for default")
|
||||||
|
|
||||||
def check_windows_admin(self) -> bool:
|
def check_windows_admin(self) -> bool:
|
||||||
"""Check if script is running with Administrator privileges on Windows"""
|
# Check if script is running with Administrator privileges on Windows
|
||||||
try:
|
try:
|
||||||
import ctypes
|
import ctypes
|
||||||
return ctypes.windll.shell32.IsUserAnAdmin() != 0
|
return ctypes.windll.shell32.IsUserAnAdmin() != 0
|
||||||
@@ -756,7 +773,7 @@ class MoneroMiner:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def prompt_msr_mod(self, os_type: str) -> bool:
|
def prompt_msr_mod(self, os_type: str) -> bool:
|
||||||
"""Prompt user to enable MSR MOD for performance optimization"""
|
# Prompt user to enable MSR MOD for performance optimization
|
||||||
# MSR MOD is only supported on Windows and Linux
|
# MSR MOD is only supported on Windows and Linux
|
||||||
if os_type not in ['windows', 'linux']:
|
if os_type not in ['windows', 'linux']:
|
||||||
return False
|
return False
|
||||||
@@ -806,7 +823,7 @@ class MoneroMiner:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def setup_linux_msr(self):
|
def setup_linux_msr(self):
|
||||||
"""Setup MSR kernel module on Linux"""
|
# Setup MSR kernel module on Linux
|
||||||
try:
|
try:
|
||||||
# Check if msr module is loaded
|
# Check if msr module is loaded
|
||||||
result = subprocess.run(['lsmod'], capture_output=True, text=True)
|
result = subprocess.run(['lsmod'], capture_output=True, text=True)
|
||||||
@@ -841,7 +858,7 @@ class MoneroMiner:
|
|||||||
print(" 2. Start miner with: sudo python3 miner-monero.py")
|
print(" 2. Start miner with: sudo python3 miner-monero.py")
|
||||||
|
|
||||||
def prompt_gpu_mining(self) -> bool:
|
def prompt_gpu_mining(self) -> bool:
|
||||||
"""Prompt user to enable GPU mining if NVIDIA GPU is detected"""
|
# Prompt user to enable GPU mining if NVIDIA GPU is detected
|
||||||
print("\n" + "="*60)
|
print("\n" + "="*60)
|
||||||
print("GPU Mining Configuration")
|
print("GPU Mining Configuration")
|
||||||
print("="*60)
|
print("="*60)
|
||||||
@@ -866,7 +883,7 @@ class MoneroMiner:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def setup_initial_config(self):
|
def setup_initial_config(self):
|
||||||
"""Setup initial configuration with user input"""
|
# Setup initial configuration with user input
|
||||||
os_type = self.detect_os()
|
os_type = self.detect_os()
|
||||||
arch = self.detect_cpu_arch()
|
arch = self.detect_cpu_arch()
|
||||||
is_mac = os_type == 'macos'
|
is_mac = os_type == 'macos'
|
||||||
@@ -930,7 +947,7 @@ class MoneroMiner:
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
def load_config(self) -> Dict:
|
def load_config(self) -> Dict:
|
||||||
"""Load configuration from JSON file"""
|
# Load configuration from JSON file
|
||||||
if not os.path.exists(self.config_file):
|
if not os.path.exists(self.config_file):
|
||||||
print(f"Configuration file '{self.config_file}' not found.")
|
print(f"Configuration file '{self.config_file}' not found.")
|
||||||
print("Setting up initial configuration...")
|
print("Setting up initial configuration...")
|
||||||
@@ -949,7 +966,7 @@ class MoneroMiner:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def validate_config(self, config: Dict):
|
def validate_config(self, config: Dict):
|
||||||
"""Validate required configuration fields"""
|
# Validate required configuration fields
|
||||||
required_fields = ['wallet_address', 'mining_mode']
|
required_fields = ['wallet_address', 'mining_mode']
|
||||||
|
|
||||||
for field in required_fields:
|
for field in required_fields:
|
||||||
@@ -963,7 +980,7 @@ class MoneroMiner:
|
|||||||
raise ValueError("pool_address is required for pool mining")
|
raise ValueError("pool_address is required for pool mining")
|
||||||
|
|
||||||
def is_supportxmr_pool(self) -> bool:
|
def is_supportxmr_pool(self) -> bool:
|
||||||
"""Check if the configured pool is SupportXMR"""
|
# Check if the configured pool is SupportXMR
|
||||||
if self.config['mining_mode'] != 'pool':
|
if self.config['mining_mode'] != 'pool':
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -971,7 +988,7 @@ class MoneroMiner:
|
|||||||
return 'supportxmr.com' in pool_addr
|
return 'supportxmr.com' in pool_addr
|
||||||
|
|
||||||
def is_moneroocean_pool(self) -> bool:
|
def is_moneroocean_pool(self) -> bool:
|
||||||
"""Check if the configured pool is MoneroOcean"""
|
# Check if the configured pool is MoneroOcean
|
||||||
if self.config['mining_mode'] != 'pool':
|
if self.config['mining_mode'] != 'pool':
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -979,7 +996,7 @@ class MoneroMiner:
|
|||||||
return 'moneroocean' in pool_addr
|
return 'moneroocean' in pool_addr
|
||||||
|
|
||||||
def is_nanopool_pool(self) -> bool:
|
def is_nanopool_pool(self) -> bool:
|
||||||
"""Check if the configured pool is NanoPool"""
|
# Check if the configured pool is NanoPool
|
||||||
if self.config['mining_mode'] != 'pool':
|
if self.config['mining_mode'] != 'pool':
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -987,7 +1004,7 @@ class MoneroMiner:
|
|||||||
return 'nanopool' in pool_addr
|
return 'nanopool' in pool_addr
|
||||||
|
|
||||||
def is_hashvault_pool(self) -> bool:
|
def is_hashvault_pool(self) -> bool:
|
||||||
"""Check if the configured pool is HashVault"""
|
# Check if the configured pool is HashVault
|
||||||
if self.config['mining_mode'] != 'pool':
|
if self.config['mining_mode'] != 'pool':
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -995,7 +1012,7 @@ class MoneroMiner:
|
|||||||
return 'hashvault' in pool_addr
|
return 'hashvault' in pool_addr
|
||||||
|
|
||||||
def is_herominers_pool(self) -> bool:
|
def is_herominers_pool(self) -> bool:
|
||||||
"""Check if the configured pool is HeroMiners"""
|
# Check if the configured pool is HeroMiners
|
||||||
if self.config['mining_mode'] != 'pool':
|
if self.config['mining_mode'] != 'pool':
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -1003,7 +1020,7 @@ class MoneroMiner:
|
|||||||
return 'herominers' in pool_addr
|
return 'herominers' in pool_addr
|
||||||
|
|
||||||
def fetch_pool_stats(self) -> Optional[Dict]:
|
def fetch_pool_stats(self) -> Optional[Dict]:
|
||||||
"""Fetch mining statistics from pool API"""
|
# Fetch mining statistics from pool API
|
||||||
try:
|
try:
|
||||||
wallet = self.config['wallet_address']
|
wallet = self.config['wallet_address']
|
||||||
|
|
||||||
@@ -1023,7 +1040,7 @@ class MoneroMiner:
|
|||||||
req = urllib.request.Request(url)
|
req = urllib.request.Request(url)
|
||||||
req.add_header('User-Agent', 'Mozilla/5.0')
|
req.add_header('User-Agent', 'Mozilla/5.0')
|
||||||
|
|
||||||
with urllib.request.urlopen(req, timeout=10) as response:
|
with urllib.request.urlopen(req, timeout=10, context=self.ssl_context) as response:
|
||||||
data = json.loads(response.read().decode())
|
data = json.loads(response.read().decode())
|
||||||
|
|
||||||
# NanoPool wraps data differently
|
# NanoPool wraps data differently
|
||||||
@@ -1064,7 +1081,7 @@ class MoneroMiner:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def format_hashrate(self, hash_rate: float) -> str:
|
def format_hashrate(self, hash_rate: float) -> str:
|
||||||
"""Format hash rate in human-readable format"""
|
# Format hash rate in human-readable format
|
||||||
if hash_rate >= 1000000:
|
if hash_rate >= 1000000:
|
||||||
return f"{hash_rate / 1000000:.2f} MH/s"
|
return f"{hash_rate / 1000000:.2f} MH/s"
|
||||||
elif hash_rate >= 1000:
|
elif hash_rate >= 1000:
|
||||||
@@ -1073,12 +1090,12 @@ class MoneroMiner:
|
|||||||
return f"{hash_rate:.2f} H/s"
|
return f"{hash_rate:.2f} H/s"
|
||||||
|
|
||||||
def format_xmr(self, piconero: int) -> str:
|
def format_xmr(self, piconero: int) -> str:
|
||||||
"""Convert piconero to XMR"""
|
# Convert piconero to XMR
|
||||||
xmr = piconero / 1000000000000
|
xmr = piconero / 1000000000000
|
||||||
return f"{xmr:.12f} XMR"
|
return f"{xmr:.12f} XMR"
|
||||||
|
|
||||||
def format_time_ago(self, timestamp: int) -> str:
|
def format_time_ago(self, timestamp: int) -> str:
|
||||||
"""Format timestamp as time ago"""
|
# Format timestamp as time ago
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
diff = now - timestamp
|
diff = now - timestamp
|
||||||
|
|
||||||
@@ -1092,7 +1109,7 @@ class MoneroMiner:
|
|||||||
return f"{diff // 86400} days ago"
|
return f"{diff // 86400} days ago"
|
||||||
|
|
||||||
def display_pool_stats(self, stats: Dict):
|
def display_pool_stats(self, stats: Dict):
|
||||||
"""Display pool statistics in a readable format"""
|
# Display pool statistics in a readable format
|
||||||
print("\n" + "="*60)
|
print("\n" + "="*60)
|
||||||
print(f"Pool Statistics - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
print(f"Pool Statistics - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
print("="*60)
|
print("="*60)
|
||||||
@@ -1246,7 +1263,7 @@ class MoneroMiner:
|
|||||||
print("="*60 + "\n")
|
print("="*60 + "\n")
|
||||||
|
|
||||||
def stats_monitor_thread(self):
|
def stats_monitor_thread(self):
|
||||||
"""Background thread to periodically fetch and display pool stats"""
|
# Background thread to periodically fetch and display pool stats
|
||||||
interval = self.config.get('stats_update_interval', 300)
|
interval = self.config.get('stats_update_interval', 300)
|
||||||
|
|
||||||
# Display stats immediately
|
# Display stats immediately
|
||||||
@@ -1274,7 +1291,7 @@ class MoneroMiner:
|
|||||||
self.display_pool_stats(stats)
|
self.display_pool_stats(stats)
|
||||||
|
|
||||||
def start_stats_monitor(self):
|
def start_stats_monitor(self):
|
||||||
"""Start the stats monitoring thread"""
|
# Start the stats monitoring thread
|
||||||
if not self.is_supportxmr_pool() and not self.is_moneroocean_pool() and not self.is_nanopool_pool() and not self.is_hashvault_pool() and not self.is_herominers_pool():
|
if not self.is_supportxmr_pool() and not self.is_moneroocean_pool() and not self.is_nanopool_pool() and not self.is_hashvault_pool() and not self.is_herominers_pool():
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1298,13 +1315,13 @@ class MoneroMiner:
|
|||||||
self.stats_thread.start()
|
self.stats_thread.start()
|
||||||
|
|
||||||
def stop_stats_monitor(self):
|
def stop_stats_monitor(self):
|
||||||
"""Stop the stats monitoring thread"""
|
# Stop the stats monitoring thread
|
||||||
if self.stats_thread:
|
if self.stats_thread:
|
||||||
self.stop_stats = True
|
self.stop_stats = True
|
||||||
self.stats_thread.join(timeout=2)
|
self.stats_thread.join(timeout=2)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
"""Initialize the miner - check for xmrig and setup config"""
|
# Initialize the miner - check for xmrig and setup config
|
||||||
# Check for NVIDIA GPU first
|
# Check for NVIDIA GPU first
|
||||||
print("\nChecking for NVIDIA GPU...")
|
print("\nChecking for NVIDIA GPU...")
|
||||||
self.has_nvidia_gpu = self.detect_nvidia_gpu()
|
self.has_nvidia_gpu = self.detect_nvidia_gpu()
|
||||||
@@ -1382,7 +1399,7 @@ class MoneroMiner:
|
|||||||
self.config['gpu_mining'] = False
|
self.config['gpu_mining'] = False
|
||||||
|
|
||||||
def build_command(self) -> list:
|
def build_command(self) -> list:
|
||||||
"""Build the XMRig mining command based on configuration"""
|
# Build the XMRig mining command based on configuration
|
||||||
cmd = [self.config.get('miner_executable', 'xmrig')]
|
cmd = [self.config.get('miner_executable', 'xmrig')]
|
||||||
|
|
||||||
# Add wallet address
|
# Add wallet address
|
||||||
@@ -1468,7 +1485,7 @@ class MoneroMiner:
|
|||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
def build_gminer_command(self) -> list:
|
def build_gminer_command(self) -> list:
|
||||||
"""Build the GMiner command for GPU mining"""
|
# Build the GMiner command for GPU mining
|
||||||
os_type = self.detect_os()
|
os_type = self.detect_os()
|
||||||
|
|
||||||
if os_type == 'windows':
|
if os_type == 'windows':
|
||||||
@@ -1493,7 +1510,7 @@ class MoneroMiner:
|
|||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
def start_gpu_mining(self):
|
def start_gpu_mining(self):
|
||||||
"""Start the GPU mining process with GMiner"""
|
# Start the GPU mining process with GMiner
|
||||||
if not self.config.get('gpu_mining', False):
|
if not self.config.get('gpu_mining', False):
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1538,7 +1555,7 @@ class MoneroMiner:
|
|||||||
print(f"Error starting GPU miner: {e}")
|
print(f"Error starting GPU miner: {e}")
|
||||||
|
|
||||||
def stop_gpu_mining(self):
|
def stop_gpu_mining(self):
|
||||||
"""Stop the GPU mining process"""
|
# Stop the GPU mining process
|
||||||
if self.gpu_process:
|
if self.gpu_process:
|
||||||
print("Stopping GPU miner...")
|
print("Stopping GPU miner...")
|
||||||
self.gpu_process.terminate()
|
self.gpu_process.terminate()
|
||||||
@@ -1550,7 +1567,7 @@ class MoneroMiner:
|
|||||||
print("GPU miner stopped.")
|
print("GPU miner stopped.")
|
||||||
|
|
||||||
def start_mining(self):
|
def start_mining(self):
|
||||||
"""Start the mining process"""
|
# Start the mining process
|
||||||
cmd = self.build_command()
|
cmd = self.build_command()
|
||||||
|
|
||||||
# Check if MSR is enabled but not running with proper privileges
|
# Check if MSR is enabled but not running with proper privileges
|
||||||
@@ -1646,7 +1663,7 @@ class MoneroMiner:
|
|||||||
self.stop_gpu_mining()
|
self.stop_gpu_mining()
|
||||||
|
|
||||||
def stop_mining(self):
|
def stop_mining(self):
|
||||||
"""Stop the mining process"""
|
# Stop the mining process
|
||||||
self.stop_stats_monitor()
|
self.stop_stats_monitor()
|
||||||
self.stop_gpu_mining()
|
self.stop_gpu_mining()
|
||||||
|
|
||||||
@@ -1661,14 +1678,14 @@ class MoneroMiner:
|
|||||||
print("CPU miner stopped.")
|
print("CPU miner stopped.")
|
||||||
|
|
||||||
def show_stats(self):
|
def show_stats(self):
|
||||||
"""Display mining statistics if API is enabled"""
|
# Display mining statistics if API is enabled
|
||||||
api_port = self.config.get('api_port', 0)
|
api_port = self.config.get('api_port', 0)
|
||||||
if api_port > 0:
|
if api_port > 0:
|
||||||
print(f"\nMining stats available at: http://127.0.0.1:{api_port}")
|
print(f"\nMining stats available at: http://127.0.0.1:{api_port}")
|
||||||
print("You can view real-time statistics in your browser")
|
print("You can view real-time statistics in your browser")
|
||||||
|
|
||||||
def signal_handler(signum, frame):
|
def signal_handler(signum, frame):
|
||||||
"""Handle interrupt signals"""
|
# Handle interrupt signals
|
||||||
print("\n\nShutdown signal received...")
|
print("\n\nShutdown signal received...")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user