diff --git a/.gitignore b/.gitignore index d52b6ab..8300d53 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ AI/MCP/* .fuse_hidde* *.pyc +MINE/rin/mining_log.txt diff --git a/MINE/rin/README.md b/MINE/rin/README.md index d8f6f1d..6869eef 100644 --- a/MINE/rin/README.md +++ b/MINE/rin/README.md @@ -152,6 +152,7 @@ Your Stratum proxy can be enhanced to work as a **full mining pool** that distri # 2. Miners connect with: ./cpuminer -a rinhash -o stratum+tcp://YOUR_IP:3333 -u username.workername -p x +# submit every share cd /mnt/shared/DEV/repos/d-popov.com/scripts/MINE/rin && python3 stratum_proxy.py --submit-all-blocks ``` diff --git a/MINE/rin/mining_log.txt b/MINE/rin/mining_log.txt index bf927ec..4729580 100644 --- a/MINE/rin/mining_log.txt +++ b/MINE/rin/mining_log.txt @@ -1,10 +1,10 @@ ================================================================================ RinCoin Mining Log ================================================================================ -Started: 2025-09-23 13:41:11 +Started: 2025-09-23 18:00:59 Target Address: rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q Stratum: 0.0.0.0:3334 RPC: 127.0.0.1:9556 ================================================================================ -[2025-09-23 13:41:11] 💰 Wallet Balance: 25.00000000 RIN +[2025-09-23 18:00:59] 💰 Wallet Balance: 25.00000000 RIN diff --git a/MINE/rin/stratum_proxy.py b/MINE/rin/stratum_proxy.py index 28d2fad..fe37e3d 100644 --- a/MINE/rin/stratum_proxy.py +++ b/MINE/rin/stratum_proxy.py @@ -49,7 +49,10 @@ class RinCoinStratumProxy: 'rejected_shares': 0, 'blocks_found': 0, 'total_hashrate': 0, - 'connections': 0 + 'connections': 0, + 'last_share_time': time.time(), + 'shares_last_minute': [], + 'current_share_rate': 0.0 } self.max_connections = 50 # Production limit @@ -397,35 +400,18 @@ class RinCoinStratumProxy: network_diff = self.calculate_network_difficulty(self.current_job['target']) if self.current_job else 1.0 if is_new_client: - # For new clients, start with a conservative estimate - # Assuming typical CPU miner does 500kH/s, aim for 1 share per 30 seconds - # Difficulty calculation: target_shares_per_second = hashrate / (difficulty * 2^32 / 65535) - # Rearranged: difficulty = hashrate / (target_shares_per_second * 2^32 / 65535) - estimated_hashrate = 500000 # 500 kH/s conservative estimate - target_shares_per_second = 1.0 / self.target_share_interval + # Start new clients at 0.5% of network difficulty + initial_difficulty = network_diff * 0.005 # 0.5% of network difficulty - # Bitcoin-style difficulty calculation - diff1_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000 - optimal_difficulty = (estimated_hashrate * diff1_target) / (target_shares_per_second * (2**256)) + # Ensure reasonable bounds + min_difficulty = 0.000001 # Absolute minimum + max_difficulty = network_diff * 0.05 # Maximum 5% of network + initial_difficulty = max(min_difficulty, min(max_difficulty, initial_difficulty)) - # Calculate proper difficulty based on expected hashrate for solo mining - # Target: 1 share every 2 minutes (120 seconds) - # Conservative estimate: 500 kH/s for CPU mining - estimated_hashrate = 500000 # 500 kH/s - target_shares_per_second = 1.0 / self.target_share_interval - - # Calculate difficulty to achieve target share rate - # Formula: difficulty = hashrate / (target_shares_per_second * 2^32 / max_target) - max_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000 - optimal_difficulty = (estimated_hashrate * target_shares_per_second) / (max_target / (2**32)) - - # Ensure it's not too low or too high - optimal_difficulty = max(0.0000001, min(optimal_difficulty, network_diff * 0.01)) - - print(f" 📊 New client {addr}: Network diff {network_diff:.6f}, starting with {optimal_difficulty:.6f}") - return optimal_difficulty + print(f" 📊 NEW CLIENT {addr}: Network diff {network_diff:.6f}, starting with {initial_difficulty:.6f} (0.5% of network)") + return initial_difficulty - # For existing clients, adjust based on actual performance + # For existing clients, adjust based on actual hashrate performance client_data = self.clients.get(addr, {}) if not client_data: return self.calculate_optimal_difficulty(addr, is_new_client=True) @@ -433,34 +419,30 @@ class RinCoinStratumProxy: current_time = time.time() connect_time = client_data.get('connect_time', current_time) share_count = client_data.get('share_count', 0) - current_difficulty = client_data.get('stratum_difficulty', 0.001) + current_difficulty = client_data.get('stratum_difficulty', network_diff * 0.005) + estimated_hashrate = client_data.get('estimated_hashrate', 0) - # Calculate actual share rate - mining_duration = current_time - connect_time - if mining_duration < 60: # Need at least 1 minute of data + # Need at least 3 shares to make adjustments + if share_count < 3: return current_difficulty - actual_share_rate = share_count / mining_duration # shares per second - target_share_rate = 1.0 / self.target_share_interval - - # Adjust difficulty to hit target share rate - if actual_share_rate > 0: - difficulty_multiplier = actual_share_rate / target_share_rate - new_difficulty = current_difficulty * difficulty_multiplier + # Calculate target difficulty based on hashrate and desired share interval + # Target: 1 share every 60 seconds (self.target_share_interval) + if estimated_hashrate > 0: + # Formula: difficulty = (hashrate * target_time) / (2^32) + diff1_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000 + target_difficulty = (estimated_hashrate * self.target_share_interval) / (2**32) - # Apply conservative adjustment (don't change too dramatically) - max_change = 2.0 # Don't change by more than 2x in one adjustment - if difficulty_multiplier > max_change: - new_difficulty = current_difficulty * max_change - elif difficulty_multiplier < (1.0 / max_change): - new_difficulty = current_difficulty / max_change + # Bounds checking + min_difficulty = network_diff * 0.0001 # 0.01% of network + max_difficulty = network_diff * 0.02 # 2% of network + target_difficulty = max(min_difficulty, min(max_difficulty, target_difficulty)) - # Bounds checking for solo mining - min_difficulty = 0.00000001 # Extremely low minimum for CPU mining - max_difficulty = 0.0001 # Maximum 0.01% of typical network diff - new_difficulty = max(min_difficulty, min(max_difficulty, new_difficulty)) + # Conservative adjustment - move only 50% towards target each time + adjustment_factor = 0.5 + new_difficulty = current_difficulty + (target_difficulty - current_difficulty) * adjustment_factor - print(f" 📊 {addr}: {share_count} shares in {mining_duration:.0f}s ({actual_share_rate:.4f}/s), adjusting {current_difficulty:.6f} → {new_difficulty:.6f}") + print(f" 📊 {addr}: {estimated_hashrate:.0f} H/s, {share_count} shares, adjusting {current_difficulty:.6f} → {new_difficulty:.6f}") return new_difficulty return current_difficulty @@ -470,6 +452,38 @@ class RinCoinStratumProxy: # Fallback to conservative difficulty network_diff = self.calculate_network_difficulty(self.current_job['target']) if self.current_job else 1.0 return max(network_diff * 0.001, 0.0001) + + def adjust_global_difficulty_if_needed(self): + """Adjust difficulty globally if share rate is too high/low""" + try: + current_rate = self.stats['current_share_rate'] + + # Target: 0.5-2 shares per second (30-120 second intervals) + target_min_rate = 0.008 # ~1 share per 2 minutes + target_max_rate = 0.033 # ~1 share per 30 seconds + + if current_rate > target_max_rate: + # Too many shares - increase difficulty for all clients + multiplier = min(2.0, current_rate / target_max_rate) + print(f" 🚨 HIGH SHARE RATE: {current_rate:.3f}/s > {target_max_rate:.3f}/s - increasing difficulty by {multiplier:.2f}x") + for addr in self.clients: + current_diff = self.clients[addr].get('stratum_difficulty', 0.001) + new_diff = min(0.001, current_diff * multiplier) + self.clients[addr]['stratum_difficulty'] = new_diff + print(f" 📈 {addr}: {current_diff:.6f} → {new_diff:.6f}") + + elif current_rate < target_min_rate and current_rate > 0: + # Too few shares - decrease difficulty for all clients + multiplier = max(0.5, target_min_rate / current_rate) + print(f" 🐌 LOW SHARE RATE: {current_rate:.3f}/s < {target_min_rate:.3f}/s - decreasing difficulty by {multiplier:.2f}x") + for addr in self.clients: + current_diff = self.clients[addr].get('stratum_difficulty', 0.001) + new_diff = max(0.000001, current_diff / multiplier) + self.clients[addr]['stratum_difficulty'] = new_diff + print(f" 📉 {addr}: {current_diff:.6f} → {new_diff:.6f}") + + except Exception as e: + print(f"Global difficulty adjustment error: {e}") def adjust_client_difficulty(self, addr): """Adjust difficulty for a specific client if needed""" @@ -549,6 +563,13 @@ class RinCoinStratumProxy: meets_stratum_difficulty = share_difficulty >= client_stratum_diff meets_network_difficulty = share_difficulty >= network_difficulty + # Track share rate + current_time = time.time() + self.stats['shares_last_minute'].append(current_time) + # Remove shares older than 60 seconds + self.stats['shares_last_minute'] = [t for t in self.stats['shares_last_minute'] if current_time - t <= 60] + self.stats['current_share_rate'] = len(self.stats['shares_last_minute']) / 60.0 + # Enhanced logging timestamp = time.strftime("%Y-%m-%d %H:%M:%S") network_percentage = (share_difficulty / network_difficulty) * 100 if network_difficulty > 0 else 0 @@ -571,6 +592,7 @@ class RinCoinStratumProxy: print(f"[{timestamp}] {progress_icon} SHARE: job={job['job_id']} | nonce={nonce} | hash={block_hash_hex[:16]}...") print(f" 🎯 Share Diff: {share_difficulty:.2e} | Stratum Diff: {client_stratum_diff:.6f} | Network Diff: {network_difficulty:.6f}") print(f" 📈 Progress: {network_percentage:.4f}% of network, {stratum_percentage:.1f}% of stratum") + print(f" 📊 Share Rate: {self.stats['current_share_rate']:.2f}/s | Total: {len(self.stats['shares_last_minute'])}/min") print(f" 📍 Target: {job['target'][:16]}... | Height: {job['height']}") print(f" ⏰ Time: {ntime} | Extranonce: {extranonce1}:{extranonce2}") print(f" 🔍 Difficulty Check: Share {share_difficulty:.2e} vs Stratum {client_stratum_diff:.6f} = {'✅' if meets_stratum_difficulty else '❌'}") @@ -596,8 +618,34 @@ class RinCoinStratumProxy: # Valid stratum share! Update client stats if addr and addr in self.clients: + current_time = time.time() self.clients[addr]['share_count'] = self.clients[addr].get('share_count', 0) + 1 - self.clients[addr]['last_share_time'] = time.time() + self.clients[addr]['last_share_time'] = current_time + + # Calculate hashrate from this share + # Hashrate = difficulty * 2^32 / time_to_find_share + client_difficulty = self.clients[addr].get('stratum_difficulty', 0.001) + last_share_time = self.clients[addr].get('last_share_time', current_time - 60) + time_since_last = max(1, current_time - last_share_time) # Avoid division by zero + + # Calculate instantaneous hashrate for this share + diff1_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000 + instant_hashrate = (client_difficulty * (2**32)) / time_since_last + + # Store hashrate sample (keep last 10 samples) + if 'hashrate_samples' not in self.clients[addr]: + self.clients[addr]['hashrate_samples'] = [] + self.clients[addr]['hashrate_samples'].append((current_time, instant_hashrate)) + # Keep only last 10 samples + if len(self.clients[addr]['hashrate_samples']) > 10: + self.clients[addr]['hashrate_samples'] = self.clients[addr]['hashrate_samples'][-10:] + + # Calculate average hashrate from recent samples + if self.clients[addr]['hashrate_samples']: + total_hashrate = sum(hr for _, hr in self.clients[addr]['hashrate_samples']) + self.clients[addr]['estimated_hashrate'] = total_hashrate / len(self.clients[addr]['hashrate_samples']) + + print(f" ⛏️ Miner {addr}: {self.clients[addr]['estimated_hashrate']:.0f} H/s (avg of {len(self.clients[addr]['hashrate_samples'])} samples)") # Update global stats self.stats['total_shares'] += 1 @@ -605,6 +653,9 @@ class RinCoinStratumProxy: # Check if we should adjust difficulty self.adjust_client_difficulty(addr) + + # Global difficulty adjustment based on share rate + self.adjust_global_difficulty_if_needed() # Only submit if it meets network difficulty in normal mode should_submit = meets_network_difficulty @@ -727,6 +778,8 @@ class RinCoinStratumProxy: self.clients[addr]['last_share_time'] = time.time() self.clients[addr]['share_count'] = 0 self.clients[addr]['connect_time'] = time.time() + self.clients[addr]['hashrate_samples'] = [] # Store recent hashrate measurements + self.clients[addr]['estimated_hashrate'] = 0 # Current estimated hashrate self.send_stratum_notification(client, "mining.set_difficulty", [initial_difficulty]) print(f" 🎯 Set initial difficulty {initial_difficulty:.6f} for {addr}")