finaly working difficulty!

This commit is contained in:
Dobromir Popov
2025-09-23 18:09:55 +03:00
parent ba93f8807b
commit 5f9db3836f
4 changed files with 107 additions and 52 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
AI/MCP/*
.fuse_hidde*
*.pyc
MINE/rin/mining_log.txt

View File

@@ -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
```

View File

@@ -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

View File

@@ -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}")