stratum - dynamic difficulty
This commit is contained in:
@@ -33,6 +33,11 @@ class RinCoinStratumProxy:
|
||||
self.running = True
|
||||
self.extranonce1_counter = 0
|
||||
|
||||
# Dynamic difficulty adjustment
|
||||
self.share_stats = {} # Track shares per client
|
||||
self.last_difficulty_adjustment = time.time()
|
||||
self.target_share_interval = 30 # Target: 1 share every 30 seconds per miner
|
||||
|
||||
# Logging setup
|
||||
self.log_file = "mining_log.txt"
|
||||
self.init_log_file()
|
||||
@@ -370,6 +375,102 @@ class RinCoinStratumProxy:
|
||||
print(f"Network difficulty calculation error: {e}")
|
||||
return 1.0
|
||||
|
||||
def calculate_optimal_difficulty(self, addr, is_new_client=False):
|
||||
"""Calculate optimal stratum difficulty for a client based on hashrate and network conditions"""
|
||||
try:
|
||||
# Get current network difficulty
|
||||
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
|
||||
|
||||
# Bitcoin-style difficulty calculation
|
||||
diff1_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000
|
||||
optimal_difficulty = (estimated_hashrate * diff1_target) / (target_shares_per_second * (2**256))
|
||||
|
||||
# More practical approach: start with network difficulty scaled down
|
||||
optimal_difficulty = max(network_diff * 0.001, 0.0001) # 0.1% of network, min 0.0001
|
||||
|
||||
print(f" 📊 New client {addr}: Network diff {network_diff:.6f}, starting with {optimal_difficulty:.6f}")
|
||||
return optimal_difficulty
|
||||
|
||||
# For existing clients, adjust based on actual performance
|
||||
client_data = self.clients.get(addr, {})
|
||||
if not client_data:
|
||||
return self.calculate_optimal_difficulty(addr, is_new_client=True)
|
||||
|
||||
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)
|
||||
|
||||
# Calculate actual share rate
|
||||
mining_duration = current_time - connect_time
|
||||
if mining_duration < 60: # Need at least 1 minute of data
|
||||
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
|
||||
|
||||
# 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.00001 # 0.001% of network minimum
|
||||
max_difficulty = network_diff * 0.1 # 10% of network maximum
|
||||
new_difficulty = max(min_difficulty, min(max_difficulty, new_difficulty))
|
||||
|
||||
print(f" 📊 {addr}: {share_count} shares in {mining_duration:.0f}s ({actual_share_rate:.4f}/s), adjusting {current_difficulty:.6f} → {new_difficulty:.6f}")
|
||||
return new_difficulty
|
||||
|
||||
return current_difficulty
|
||||
|
||||
except Exception as e:
|
||||
print(f"Difficulty calculation error: {e}")
|
||||
# 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_client_difficulty(self, addr):
|
||||
"""Adjust difficulty for a specific client if needed"""
|
||||
try:
|
||||
current_time = time.time()
|
||||
|
||||
# Only adjust every 2 minutes minimum
|
||||
last_adjustment = self.clients[addr].get('last_difficulty_adjustment', 0)
|
||||
if current_time - last_adjustment < 120:
|
||||
return
|
||||
|
||||
new_difficulty = self.calculate_optimal_difficulty(addr, is_new_client=False)
|
||||
current_difficulty = self.clients[addr].get('stratum_difficulty', 0.001)
|
||||
|
||||
# Only send update if difficulty changed significantly (>20%)
|
||||
if abs(new_difficulty - current_difficulty) / current_difficulty > 0.2:
|
||||
self.clients[addr]['stratum_difficulty'] = new_difficulty
|
||||
self.clients[addr]['last_difficulty_adjustment'] = current_time
|
||||
|
||||
# Send new difficulty to client
|
||||
if 'socket' in self.clients[addr]:
|
||||
self.send_stratum_notification(self.clients[addr]['socket'], "mining.set_difficulty", [new_difficulty])
|
||||
print(f" 🎯 Updated difficulty for {addr}: {current_difficulty:.6f} → {new_difficulty:.6f}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Difficulty adjustment error for {addr}: {e}")
|
||||
|
||||
def submit_share(self, job, extranonce1, extranonce2, ntime, nonce, addr=None, target_address=None):
|
||||
"""Validate share and submit block if valid - FIXED VERSION"""
|
||||
try:
|
||||
@@ -449,7 +550,15 @@ class RinCoinStratumProxy:
|
||||
print(f" ❌ Share rejected (hash > stratum target)")
|
||||
return False, "Share too high"
|
||||
|
||||
# Valid stratum share! Check if it's also a valid network block
|
||||
# Valid stratum share! Update client stats
|
||||
if addr and addr in self.clients:
|
||||
self.clients[addr]['share_count'] = self.clients[addr].get('share_count', 0) + 1
|
||||
self.clients[addr]['last_share_time'] = time.time()
|
||||
|
||||
# Check if we should adjust difficulty
|
||||
self.adjust_client_difficulty(addr)
|
||||
|
||||
# Check if it's also a valid network block
|
||||
if meets_network_target:
|
||||
print(f" 🎉 BLOCK FOUND! Hash: {block_hash_hex}")
|
||||
print(f" 💰 Reward: {job['coinbasevalue']/100000000:.2f} RIN -> {address}")
|
||||
@@ -549,14 +658,18 @@ class RinCoinStratumProxy:
|
||||
4 # extranonce2 size
|
||||
])
|
||||
|
||||
# Send difficulty - set to reasonable level for stratum mining
|
||||
network_diff = self.calculate_network_difficulty(self.current_job['target']) if self.current_job else 1.0
|
||||
stratum_difficulty = min(network_diff * 0.001, 0.01) # Adaptive difficulty, max 0.01
|
||||
# Calculate optimal stratum difficulty for this client
|
||||
initial_difficulty = self.calculate_optimal_difficulty(addr, is_new_client=True)
|
||||
# Store stratum difficulty for this client
|
||||
if addr not in self.clients:
|
||||
self.clients[addr] = {}
|
||||
self.clients[addr]['stratum_difficulty'] = stratum_difficulty
|
||||
self.send_stratum_notification(client, "mining.set_difficulty", [stratum_difficulty])
|
||||
self.clients[addr]['stratum_difficulty'] = initial_difficulty
|
||||
self.clients[addr]['last_share_time'] = time.time()
|
||||
self.clients[addr]['share_count'] = 0
|
||||
self.clients[addr]['connect_time'] = time.time()
|
||||
|
||||
self.send_stratum_notification(client, "mining.set_difficulty", [initial_difficulty])
|
||||
print(f" 🎯 Set initial difficulty {initial_difficulty:.6f} for {addr}")
|
||||
|
||||
# Send initial job
|
||||
if self.current_job:
|
||||
|
Reference in New Issue
Block a user