From 89e13e91d666312607009db58a89b5ac80bcab24 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Tue, 2 Sep 2025 13:21:43 +0300 Subject: [PATCH] dashboard --- .../pool_web_interface.cpython-312.pyc | Bin 12512 -> 15931 bytes MINE/rin/miner/readme.md | 1 + MINE/rin/pool_web_interface.py | 132 +++++++++++++++--- MINE/rin/stratum_pool.py | 9 +- 4 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 MINE/rin/miner/readme.md diff --git a/MINE/rin/__pycache__/pool_web_interface.cpython-312.pyc b/MINE/rin/__pycache__/pool_web_interface.cpython-312.pyc index a7a32aa1d47d7e3b8e5d1f462a5dbfe99b10eebb..7280286b98079ea44a10577bfca200d241d9f2af 100644 GIT binary patch delta 4190 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 1e12: + return f"{hashrate/1e12:.2f} TH/s" + elif hashrate >= 1e9: + return f"{hashrate/1e9:.2f} GH/s" + elif hashrate >= 1e6: + return f"{hashrate/1e6:.2f} MH/s" + elif hashrate >= 1e3: + return f"{hashrate/1e3:.2f} KH/s" + elif hashrate >= 0.01: + return f"{hashrate:.2f} H/s" + elif hashrate > 0: + return f"{hashrate*1000:.2f} mH/s" + else: + return "0.00 H/s" + def get_pool_stats(self): """Get current pool statistics""" try: cursor = self.pool_db.cursor() - # Total miners + # Total miners (ever registered) cursor.execute('SELECT COUNT(DISTINCT id) FROM miners') total_miners = cursor.fetchone()[0] - # Active miners (last 10 minutes) + # Active miners (last 5 minutes) cursor.execute(''' SELECT COUNT(DISTINCT m.id) FROM miners m JOIN shares s ON m.id = s.miner_id - WHERE s.submitted > datetime('now', '-10 minutes') + WHERE s.submitted > datetime('now', '-5 minutes') ''') active_miners = cursor.fetchone()[0] @@ -41,13 +58,22 @@ class PoolWebInterface: ''') total_shares_24h = cursor.fetchone()[0] - # Pool hashrate estimate + # Better hashrate calculation (shares per second * difficulty) cursor.execute(''' - SELECT COUNT(*) FROM shares + SELECT SUM(difficulty), COUNT(*) FROM shares WHERE submitted > datetime('now', '-5 minutes') ''') - recent_shares = cursor.fetchone()[0] - hashrate = recent_shares * 12 # Rough estimate + result = cursor.fetchone() + recent_difficulty = result[0] if result[0] else 0 + recent_share_count = result[1] if result[1] else 0 + + # Convert to hashrate (difficulty per second) + hashrate = recent_difficulty / 300.0 # 5 minutes = 300 seconds + + # Alternative calculation if difficulty is 0 but we have shares + if hashrate == 0 and recent_share_count > 0: + # Estimate based on share count (assume difficulty 0.001) + hashrate = (recent_share_count * 0.001) / 300.0 # Total blocks found cursor.execute('SELECT COUNT(*) FROM blocks') @@ -62,18 +88,30 @@ class PoolWebInterface: ''') recent_blocks = cursor.fetchall() - # Top miners + # Top miners (last 24 hours) - show all miners, even without shares cursor.execute(''' - SELECT m.user, m.worker, COUNT(s.id) as shares, m.last_share + SELECT m.user, m.worker, + COALESCE(COUNT(s.id), 0) as shares, + m.last_share, + m.created FROM miners m - JOIN shares s ON m.id = s.miner_id - WHERE s.submitted > datetime('now', '-24 hours') - GROUP BY m.id - ORDER BY shares DESC - LIMIT 10 + LEFT JOIN shares s ON m.id = s.miner_id + AND s.submitted > datetime('now', '-24 hours') + GROUP BY m.id, m.user, m.worker + ORDER BY shares DESC, m.created DESC + LIMIT 20 ''') top_miners = cursor.fetchall() + # All active miners (for better visibility) + cursor.execute(''' + SELECT user, worker, created, last_share + FROM miners + ORDER BY created DESC + LIMIT 10 + ''') + all_miners = cursor.fetchall() + return { 'total_miners': total_miners, 'active_miners': active_miners, @@ -81,7 +119,13 @@ class PoolWebInterface: 'hashrate': hashrate, 'total_blocks': total_blocks, 'recent_blocks': recent_blocks, - 'top_miners': top_miners + 'top_miners': top_miners, + 'all_miners': all_miners, + 'debug': { + 'recent_difficulty': recent_difficulty, + 'recent_share_count': recent_share_count, + 'total_shares_24h': total_shares_24h + } } except Exception as e: print(f"Error getting pool stats: {e}") @@ -133,8 +177,8 @@ class PoolWebInterface:
Active Miners
-
{stats.get('hashrate', 0):.2f}
-
Hashrate (H/s)
+
{self.format_hashrate(stats.get('hashrate', 0))}
+
Hashrate
{stats.get('total_blocks', 0)}
@@ -147,10 +191,53 @@ class PoolWebInterface:

24h Shares: {stats.get('total_shares_24h', 0):,}

Pool Fee: 1%

Connection String: stratum+tcp://YOUR_IP:3333

+ + +
+ 🔍 Debug Info +

Recent Difficulty (5min): {stats.get('debug', {}).get('recent_difficulty', 0):.6f}

+

Recent Share Count (5min): {stats.get('debug', {}).get('recent_share_count', 0)}

+

Total Shares (24h): {stats.get('debug', {}).get('total_shares_24h', 0):,}

+

Active Miners: {stats.get('active_miners', 0)} (last 5 minutes)

+

Total Miners: {stats.get('total_miners', 0)} (ever registered)

+
-

👥 Top Miners (24h)

+

👥 Connected Miners

+ + + + + + + + """ + + for miner in stats.get('all_miners', []): + user, worker, created, last_share = miner + html += f""" + + + + + + + """ + + if not stats.get('all_miners', []): + html += """ + + + + """ + + html += """ +
UserWorkerConnectedLast Share
{user}{worker}{created}{last_share or 'Never'}
No miners connected
+
+ +
+

🏆 Top Miners (24h Shares)

@@ -161,7 +248,7 @@ class PoolWebInterface: """ for miner in stats.get('top_miners', []): - user, worker, shares, last_share = miner + user, worker, shares, last_share, created = miner html += f""" @@ -171,6 +258,13 @@ class PoolWebInterface: """ + if not stats.get('top_miners', []): + html += """ + + + + """ + html += """
User
{user}
No shares submitted yet
diff --git a/MINE/rin/stratum_pool.py b/MINE/rin/stratum_pool.py index a2a259a..4da3277 100644 --- a/MINE/rin/stratum_pool.py +++ b/MINE/rin/stratum_pool.py @@ -333,8 +333,8 @@ class RinCoinMiningPool: 4 ]) - # Send difficulty - self.send_stratum_notification(client, "mining.set_difficulty", [1]) + # Send difficulty (lower for CPU mining) + self.send_stratum_notification(client, "mining.set_difficulty", [0.001]) # Send initial job if self.get_block_template(): @@ -433,12 +433,15 @@ class RinCoinMiningPool: nonce = params[3] # Record share - self.record_share(miner_info['miner_id'], job_id, 1.0) # Simplified difficulty + self.record_share(miner_info['miner_id'], job_id, 0.001) # Use actual difficulty miner_info['shares'] += 1 miner_info['last_share'] = time.time() print(f"[{addr}] ✅ Share accepted from {miner_info['user']}.{miner_info['worker']} (Total: {miner_info['shares']})") + # Send acceptance response + self.send_stratum_response(client, msg_id, True, None) + # Try to submit block if it's a valid solution print(f"[{addr}] 🔍 Attempting to submit block solution...")