stratum - dynamic difficulty
This commit is contained in:
@@ -33,6 +33,11 @@ class RinCoinStratumProxy:
|
|||||||
self.running = True
|
self.running = True
|
||||||
self.extranonce1_counter = 0
|
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
|
# Logging setup
|
||||||
self.log_file = "mining_log.txt"
|
self.log_file = "mining_log.txt"
|
||||||
self.init_log_file()
|
self.init_log_file()
|
||||||
@@ -370,6 +375,102 @@ class RinCoinStratumProxy:
|
|||||||
print(f"Network difficulty calculation error: {e}")
|
print(f"Network difficulty calculation error: {e}")
|
||||||
return 1.0
|
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):
|
def submit_share(self, job, extranonce1, extranonce2, ntime, nonce, addr=None, target_address=None):
|
||||||
"""Validate share and submit block if valid - FIXED VERSION"""
|
"""Validate share and submit block if valid - FIXED VERSION"""
|
||||||
try:
|
try:
|
||||||
@@ -449,7 +550,15 @@ class RinCoinStratumProxy:
|
|||||||
print(f" ❌ Share rejected (hash > stratum target)")
|
print(f" ❌ Share rejected (hash > stratum target)")
|
||||||
return False, "Share too high"
|
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:
|
if meets_network_target:
|
||||||
print(f" 🎉 BLOCK FOUND! Hash: {block_hash_hex}")
|
print(f" 🎉 BLOCK FOUND! Hash: {block_hash_hex}")
|
||||||
print(f" 💰 Reward: {job['coinbasevalue']/100000000:.2f} RIN -> {address}")
|
print(f" 💰 Reward: {job['coinbasevalue']/100000000:.2f} RIN -> {address}")
|
||||||
@@ -549,14 +658,18 @@ class RinCoinStratumProxy:
|
|||||||
4 # extranonce2 size
|
4 # extranonce2 size
|
||||||
])
|
])
|
||||||
|
|
||||||
# Send difficulty - set to reasonable level for stratum mining
|
# Calculate optimal stratum difficulty for this client
|
||||||
network_diff = self.calculate_network_difficulty(self.current_job['target']) if self.current_job else 1.0
|
initial_difficulty = self.calculate_optimal_difficulty(addr, is_new_client=True)
|
||||||
stratum_difficulty = min(network_diff * 0.001, 0.01) # Adaptive difficulty, max 0.01
|
|
||||||
# Store stratum difficulty for this client
|
# Store stratum difficulty for this client
|
||||||
if addr not in self.clients:
|
if addr not in self.clients:
|
||||||
self.clients[addr] = {}
|
self.clients[addr] = {}
|
||||||
self.clients[addr]['stratum_difficulty'] = stratum_difficulty
|
self.clients[addr]['stratum_difficulty'] = initial_difficulty
|
||||||
self.send_stratum_notification(client, "mining.set_difficulty", [stratum_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
|
# Send initial job
|
||||||
if self.current_job:
|
if self.current_job:
|
||||||
|
Reference in New Issue
Block a user