reward distributions

This commit is contained in:
Dobromir Popov
2025-09-02 12:16:56 +03:00
parent 3dd0e55fde
commit b3ec402a2e
3 changed files with 158 additions and 4 deletions

View File

@@ -0,0 +1,40 @@
# Reward Distribution Example
## Scenario: Block Reward = 50 RIN (49 RIN after 1% pool fee)
### Miners Connected:
1. **Miner A**: `rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q.worker1` (30 difficulty)
2. **Miner B**: `user.worker2` (20 difficulty) - No address specified
3. **Miner C**: `rin1qxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.worker3` (50 difficulty) - **INVALID ADDRESS**
### Total Difficulty: 100
### Reward Distribution:
#### **Step 1: Calculate Individual Shares**
- **Miner A**: (30/100) × 49 = **14.7 RIN**`rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q`
- **Miner B**: (20/100) × 49 = **9.8 RIN****Pool address** (no valid address)
- **Miner C**: (50/100) × 49 = **24.5 RIN****Pool address** (invalid address)
#### **Step 2: Final Distribution**
- **Pool Address**: 1 RIN (fee) + 9.8 RIN (from Miner B) + 24.5 RIN (from Miner C) = **35.3 RIN**
- **Miner A**: **14.7 RIN**
### Pool Logs:
```
[127.0.0.1] ✅ Authorized: miner_rin1qah.worker1 -> rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q
[127.0.0.1] ⚠️ Authorized: user.worker2 (rewards will go to pool address)
[127.0.0.1] ❌ Invalid RinCoin address: rin1qxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
💰 Miner rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q: 14.70000000 RIN (30 difficulty)
⚠️ Miner without address: 20 difficulty -> 9.80000000 RIN to pool
⚠️ Miner without address: 50 difficulty -> 24.50000000 RIN to pool
💰 Pool keeps 34.30000000 RIN from miners without addresses
📊 Summary: 1 miners with addresses, 2 without (rewards to pool)
```
### Key Points:
-**Miners with valid addresses**: Get their full share
- ⚠️ **Miners without addresses**: Contribute to difficulty but rewards go to pool
-**Miners with invalid addresses**: Rejected at connection time
- 💰 **Pool benefits**: Gets additional rewards from careless miners
- 📊 **Transparent**: All distributions clearly logged

View File

@@ -15,6 +15,9 @@ import sqlite3
from datetime import datetime
from requests.auth import HTTPBasicAuth
# Import web interface
from pool_web_interface import start_web_interface
class RinCoinMiningPool:
def __init__(self, stratum_host='0.0.0.0', stratum_port=3333,
rpc_host='127.0.0.1', rpc_port=9556,
@@ -226,15 +229,47 @@ class RinCoinMiningPool:
# Calculate total difficulty
total_difficulty = sum(row[2] for row in miners)
# Separate miners with and without addresses
miners_with_addresses = []
miners_without_addresses = []
total_difficulty_with_addresses = 0
total_difficulty_without_addresses = 0
for address, share_count, difficulty in miners:
if address:
miners_with_addresses.append((address, share_count, difficulty))
total_difficulty_with_addresses += difficulty
else:
miners_without_addresses.append((address, share_count, difficulty))
total_difficulty_without_addresses += difficulty
# Calculate total difficulty
total_difficulty = total_difficulty_with_addresses + total_difficulty_without_addresses
if total_difficulty == 0:
print("No valid difficulty found")
return
# Distribute rewards
miner_rewards = {}
for address, share_count, difficulty in miners:
if address and total_difficulty > 0:
# First, distribute to miners with valid addresses
if miners_with_addresses:
for address, share_count, difficulty in miners_with_addresses:
reward_share = (difficulty / total_difficulty) * miner_reward
miner_rewards[address] = reward_share
print(f"💰 Miner {address}: {reward_share:.8f} RIN ({difficulty} difficulty)")
# Calculate undistributed rewards (from miners without addresses)
if miners_without_addresses:
undistributed_reward = 0
for address, share_count, difficulty in miners_without_addresses:
undistributed_reward += (difficulty / total_difficulty) * miner_reward
print(f"⚠️ Miner without address: {difficulty} difficulty -> {undistributed_reward:.8f} RIN to pool")
# Keep undistributed rewards for pool (no redistribution)
print(f"💰 Pool keeps {undistributed_reward:.8f} RIN from miners without addresses")
# Record block
cursor.execute('''
INSERT INTO blocks (block_hash, height, reward, pool_fee, miner_rewards)
@@ -247,6 +282,10 @@ class RinCoinMiningPool:
print(f"🎉 Block {block_height} reward distributed!")
print(f"💰 Pool fee: {pool_fee:.8f} RIN")
print(f"💰 Total distributed: {sum(miner_rewards.values()):.8f} RIN")
# Summary
if miners_without_addresses:
print(f"📊 Summary: {len(miners_with_addresses)} miners with addresses, {len(miners_without_addresses)} without (rewards to pool)")
def send_stratum_response(self, client, msg_id, result, error=None):
"""Send Stratum response to client"""
@@ -373,7 +412,7 @@ class RinCoinMiningPool:
if miner_address:
print(f"[{addr}] ✅ Authorized: {user}.{worker} -> {miner_address}")
else:
print(f"[{addr}] ⚠️ Authorized: {user}.{worker} (no address specified)")
print(f"[{addr}] ⚠️ Authorized: {user}.{worker} (rewards will go to pool address)")
self.send_stratum_response(client, msg_id, True)
else:
self.send_stratum_response(client, msg_id, False, "Invalid authorization")

View File

@@ -0,0 +1,75 @@
#!/bin/bash
# Test Reward Redistribution Logic
echo "=== Testing Reward Redistribution Logic ==="
echo ""
# Kill any existing processes
./MINE/rin/kill_stratum_proxy.sh
echo "🧪 Testing reward distribution scenarios:"
echo ""
echo "Scenario 1: All miners have valid addresses"
echo "Expected: Normal distribution"
echo ""
echo "Scenario 2: Some miners without addresses"
echo "Expected: Redistribution of their rewards to miners with addresses"
echo ""
echo "Scenario 3: All miners without addresses"
echo "Expected: All rewards go to pool"
echo ""
echo "🚀 Starting mining pool..."
./MINE/rin/start_mining_pool.sh &
POOL_PID=$!
echo ""
echo "⏳ Waiting for pool to start..."
sleep 5
echo ""
echo "🧪 Test 1: Miner with valid address"
echo "Expected: Gets full share of rewards"
timeout 5s ./cpuminer -a rinhash -o stratum+tcp://127.0.0.1:3333 -u rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q.worker1 -p x -t 1
echo ""
echo "🧪 Test 2: Miner without address"
echo "Expected: Contributes to difficulty but gets no direct rewards"
timeout 5s ./cpuminer -a rinhash -o stratum+tcp://127.0.0.1:3333 -u user.worker2 -p x -t 1
echo ""
echo "🧪 Test 3: Another miner with valid address"
echo "Expected: Gets base reward + redistribution from miner without address"
timeout 5s ./cpuminer -a rinhash -o stratum+tcp://127.0.0.1:3333 -u rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q.worker3 -p x -t 1
echo ""
echo "📊 Pool Log Analysis:"
echo "Look for these patterns in the logs above:"
echo "1. '💰 Miner rin1q...: X.XX RIN (difficulty)' - Base rewards"
echo "2. '⚠️ Miner without address: X difficulty -> X.XX RIN to pool' - Undistributed"
echo "3. '💰 Pool keeps X.XX RIN from miners without addresses' - Pool keeps rewards"
echo "4. '📊 Summary: X miners with addresses, Y without (rewards to pool)' - Final summary"
echo ""
echo "🧹 Cleaning up..."
kill $POOL_PID 2>/dev/null
./MINE/rin/kill_stratum_proxy.sh
echo ""
echo "📋 Reward Distribution Logic Summary:"
echo ""
echo "✅ Miners with valid RinCoin addresses:"
echo " - Get reward based on their difficulty"
echo " - Rewards sent directly to their addresses"
echo ""
echo "⚠️ Miners without addresses:"
echo " - Contribute to total difficulty"
echo " - Their reward share goes to pool address"
echo " - No direct rewards received"
echo ""
echo "💰 Pool fee: Always 1% of total block reward"
echo "💰 Pool bonus: Additional rewards from miners without addresses"