diff --git a/MINE/gBench.sh b/MINE/gBench.sh deleted file mode 100644 index e18cb3d..0000000 --- a/MINE/gBench.sh +++ /dev/null @@ -1,245 +0,0 @@ -#!/bin/bash -# GMiner algorithm test script - save as test_gminer.sh - -# Default docker image (can be overridden with parameter) -DOCKER_IMAGE=${1:-"amdopencl"} -# amd-strix-halo-llama-rocm -#amd-strix-halo-llama-vulkan-radv -# amd-strix-halo-llama-vulkan-amdvlk - -BTC_WALLET="bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j" - -# Algorithm to coin mapping -declare -A ALGO_COINS=( - ["ethash"]="ETH" - ["etchash"]="ETC" - ["autolykos2"]="ERG" - ["ergo"]="ERG" - ["equihash125_4"]="ZEL" - ["equihash144_5"]="ZEL" - ["equihash192_7"]="ZEL" - ["equihash210_9"]="ZEL" - ["beamhash"]="BEAM" - ["cuckaroo29"]="GRIN" - ["cuckatoo32"]="GRIN" - ["flux"]="FLUX" - ["octopus"]="CFX" -) - -# Function to fetch current cryptocurrency prices -fetch_prices() { - echo "Fetching current cryptocurrency prices..." - - # Use CoinGecko API to get current prices - local api_url="https://api.coingecko.com/api/v3/simple/price?ids=ethereum,ethereum-classic,ergo,zelcash,beam,grin,flux,conflux&vs_currencies=usd" - - # Try to fetch prices with timeout and fallback - local prices_json=$(timeout 10s curl -s "$api_url" 2>/dev/null) - - if [[ -z "$prices_json" ]]; then - echo "Warning: Could not fetch current prices, using fallback values" - PRICES_ETH=3500.00 - PRICES_ETC=35.00 - PRICES_ERG=2.50 - PRICES_ZEL=0.15 - PRICES_BEAM=0.05 - PRICES_GRIN=0.05 - PRICES_FLUX=0.80 - PRICES_CFX=0.20 - return - fi - - # Parse JSON response and extract prices using jq if available, otherwise use grep - if command -v jq &> /dev/null; then - PRICES_ETH=$(echo "$prices_json" | jq -r '.ethereum.usd // "3500.00"') - PRICES_ETC=$(echo "$prices_json" | jq -r '.ethereum-classic.usd // "35.00"') - PRICES_ERG=$(echo "$prices_json" | jq -r '.ergo.usd // "2.50"') - PRICES_ZEL=$(echo "$prices_json" | jq -r '.zelcash.usd // "0.15"') - PRICES_BEAM=$(echo "$prices_json" | jq -r '.beam.usd // "0.05"') - PRICES_GRIN=$(echo "$prices_json" | jq -r '.grin.usd // "0.05"') - PRICES_FLUX=$(echo "$prices_json" | jq -r '.flux.usd // "0.80"') - PRICES_CFX=$(echo "$prices_json" | jq -r '.conflux.usd // "0.20"') - else - # Fallback to grep parsing - PRICES_ETH=$(echo "$prices_json" | grep -o '"ethereum":{"usd":[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*$' || echo "3500.00") - PRICES_ETC=$(echo "$prices_json" | grep -o '"ethereum-classic":{"usd":[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*$' || echo "35.00") - PRICES_ERG=$(echo "$prices_json" | grep -o '"ergo":{"usd":[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*$' || echo "2.50") - PRICES_ZEL=$(echo "$prices_json" | grep -o '"zelcash":{"usd":[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*$' || echo "0.15") - PRICES_BEAM=$(echo "$prices_json" | grep -o '"beam":{"usd":[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*$' || echo "0.05") - PRICES_GRIN=$(echo "$prices_json" | grep -o '"grin":{"usd":[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*$' || echo "0.05") - PRICES_FLUX=$(echo "$prices_json" | grep -o '"flux":{"usd":[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*$' || echo "0.80") - PRICES_CFX=$(echo "$prices_json" | grep -o '"conflux":{"usd":[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*$' || echo "0.20") - fi - - echo "Current prices fetched successfully:" - echo " ETH: $PRICES_ETH" - echo " ETC: $PRICES_ETC" - echo " ERG: $PRICES_ERG" - echo " ZEL: $PRICES_ZEL" - echo " BEAM: $PRICES_BEAM" - echo " GRIN: $PRICES_GRIN" - echo " FLUX: $PRICES_FLUX" - echo " CFX: $PRICES_CFX" - echo "" -} - -# GMiner supported algorithms -ALGOS=( - "ethash" - "etchash" - "autolykos2" - "equihash125_4" - "equihash144_5" - "equihash192_7" - "equihash210_9" - "beamhash" - "cuckaroo29" - "cuckatoo32" - "flux" - "octopus" - "ergo" -) - -echo "=== GMiner Algorithm Tests ===" -echo "Using BTC wallet: $BTC_WALLET" -echo "Using Docker image: $DOCKER_IMAGE" -echo "Testing each algorithm for 30 seconds..." -echo "=======================================" - -# Fetch current prices at startup -fetch_prices - -# Function to calculate USD value -calculate_usd_reward() { - local algo=$1 - local hashrate=$2 - local coin=${ALGO_COINS[$algo]} - - # Get price based on coin - local price=0 - case $coin in - "ETH") price=$PRICES_ETH ;; - "ETC") price=$PRICES_ETC ;; - "ERG") price=$PRICES_ERG ;; - "ZEL") price=$PRICES_ZEL ;; - "BEAM") price=$PRICES_BEAM ;; - "GRIN") price=$PRICES_GRIN ;; - "FLUX") price=$PRICES_FLUX ;; - "CFX") price=$PRICES_CFX ;; - *) echo "Unknown" && return ;; - esac - - if [[ -z "$price" || "$price" == "0" ]]; then - echo "Unknown" - return - fi - - # Rough calculation: hashrate * price * 0.000001 (simplified) - local usd_value=$(echo "$hashrate * $price * 0.000001" | bc -l 2>/dev/null) - printf "%.2f" $usd_value 2>/dev/null || echo "Unknown" -} - -# Function to extract hashrate from miner output -extract_hashrate() { - local output="$1" - - # Look for common hashrate patterns in GMiner output - local hashrate=$(echo "$output" | grep -oE "[0-9]+\.[0-9]+ [KMGT]?H/s" | tail -1 | grep -oE "[0-9]+\.[0-9]+" | tail -1) - - # If no decimal found, look for integer hashrates - if [[ -z "$hashrate" ]]; then - hashrate=$(echo "$output" | grep -oE "[0-9]+ [KMGT]?H/s" | tail -1 | grep -oE "[0-9]+" | tail -1) - fi - - # If still no hashrate found, look for any number followed by H/s - if [[ -z "$hashrate" ]]; then - hashrate=$(echo "$output" | grep -oE "[0-9]+[\.]?[0-9]* H/s" | tail -1 | grep -oE "[0-9]+[\.]?[0-9]*" | tail -1) - fi - - # If still no hashrate, look for "Speed:" patterns - if [[ -z "$hashrate" ]]; then - hashrate=$(echo "$output" | grep -i "speed:" | tail -1 | grep -oE "[0-9]+[\.]?[0-9]*" | tail -1) - fi - - # If still no hashrate, look for any number followed by H/s (case insensitive) - if [[ -z "$hashrate" ]]; then - hashrate=$(echo "$output" | grep -ioE "[0-9]+[\.]?[0-9]* h/s" | tail -1 | grep -oE "[0-9]+[\.]?[0-9]*" | tail -1) - fi - - echo "$hashrate" -} - -for algo in "${ALGOS[@]}"; do - echo "" - echo "Testing: $algo" - echo "------------------------" - - case $algo in - "ethash") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server eth.2miners.com:2020 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "etchash") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server etc.2miners.com:1010 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "autolykos2"|"ergo") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo autolykos2 --server ergo.2miners.com:8888 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "equihash125_4") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server zel.2miners.com:9090 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "equihash144_5") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server zel.2miners.com:9090 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "equihash192_7") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server zel.2miners.com:9090 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "equihash210_9") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server zel.2miners.com:9090 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "beamhash") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server beam.2miners.com:5252 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "cuckaroo29") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server grin.2miners.com:3030 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "cuckatoo32") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server grin.2miners.com:3030 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "flux") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server flux.2miners.com:2020 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - "octopus") - output=$(sudo docker exec -it $DOCKER_IMAGE timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server cfx.2miners.com:3254 --user '$BTC_WALLET' --pass x" 2>&1) - ;; - *) - echo "No specific pool configured for $algo - skipping" - continue - ;; - esac - - exit_code=$? - - # Extract hashrate and calculate USD value - hashrate=$(extract_hashrate "$output") - coin=${ALGO_COINS[$algo]} - usd_value=$(calculate_usd_reward "$algo" "$hashrate") - - if [ $exit_code -eq 0 ]; then - echo "SUCCESS: $algo - Hashrate: ${hashrate}H/s - Coin: $coin - Est. USD/day: $usd_value" - elif [ $exit_code -eq 124 ]; then - echo "TIMEOUT: $algo - Hashrate: ${hashrate}H/s - Coin: $coin - Est. USD/day: $usd_value (likely working)" - else - echo "FAILED: $algo - Error code: $exit_code" - # Debug: show first few lines of output for failed attempts - echo "Debug output (first 5 lines):" - echo "$output" | head -5 - fi - - sleep 3 -done - -echo "" -echo "=== GMiner Tests Complete ===" -echo "Usage: $0 [docker_image_name]" -echo "Default: amdopencl" -echo "Example for RockM: $0 rockm" \ No newline at end of file diff --git a/MINE/lolBench.sh b/MINE/lolBench.sh deleted file mode 100644 index f570ccc..0000000 --- a/MINE/lolBench.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -# lolMiner benchmark script - save as bench_lolminer.sh - -ALGOS=("ETHASH" "ETCHASH" "AUTOLYKOS2" "BEAM-III" "EQUIHASH144_5" "EQUIHASH192_7" "EQUIHASH210_9" "FLUX" "NEXA" "PROGPOW" "PROGPOWZ" "PROGPOW_VERIBLOCK" "PROGPOW_VEIL" "TON") - -echo "=== lolMiner Algorithm Benchmark ===" -echo "Testing each algorithm for 15 seconds..." -echo "=====================================" - -for algo in "${ALGOS[@]}"; do - echo "" - echo "Testing: $algo" - echo "------------------------" - - sudo docker exec -it amdopencl timeout 20s bash -c "mnt/dl/lol.1.97/lolMiner --algo $algo --benchmark --benchepochs 1 --benchwarmup 5" 2>/dev/null - - if [ $? -eq 0 ]; then - echo "βœ… $algo: WORKS" - elif [ $? -eq 124 ]; then - echo "⏱️ $algo: TIMEOUT (likely working)" - else - echo "❌ $algo: FAILED" - fi - - sleep 2 -done - -echo "" -echo "=== Benchmark Complete ===" \ No newline at end of file diff --git a/MINE/notes.md b/MINE/notes.md index 5513971..ca80fa2 100644 --- a/MINE/notes.md +++ b/MINE/notes.md @@ -61,13 +61,22 @@ sudo docker exec -it amd-strix-halo-llama-rocm bash -c "/mnt/dl/rinhash/cpumine [sudo docker exec -it amd-strix-halo-llama-rocm bash -c "/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer --algo rinhash --benchmark -t 4" rinhash.mine.zergpool.com:7148 c=RIN] +# WIN +PS F:\projects\mines\rin\miner\cpuminer\cpuminer-opt-rin> .\cpuminer.exe -a rinhash -o stratum+tcps://eu.rplant.xyz:17148 -u rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q -p m=solo + +# WIN +PS F:\projects\mines\rin\miner\cpuminer\cpuminer-opt-rin> .\cpuminer.exe -a rinhash -o stratum+tcps://eu.rplant.xyz:17148 -u rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q -p m=solo + sudo docker exec -it amd-strix-halo-llama-rocm bash -c "/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://rinhash.mine.zergpool.com:7148 -u bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j -p c=BTC,mc=RIN,ID=StrixHalo -t 32" + +.\cpuminer.exe -a rinhash -o stratum+tcp://rinhash.mine.zergpool.com:7148 -u bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j -p c=BTC,mc=RIN,ID=StrixHalo -t 3 +.\cpuminer.exe -a rinhash -o stratum+tcp://192.168.0.188:3333 -u db.rog -p c=BTC,mc=RIN,ID=StrixHalo -t 3 ----------------------------------------------------------------- SOLO: -/home/db/Downloads/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://192.168.0.188:3333 -u username.workername -p x -t 28 - +/home/db/Downloads/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://192.168.0.188:3333 -u username.workername -p x -t 28./cpuminer-rinhash.exe -a rinhash -o stratum+tcp://192.168.0.188:3333 -u username.workername -p x -t 4 +./cpuminer-rinhash.exe -a rinhash -o stratum+tcp://rinhash.mine.zergpool.com:7148 -u bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j -p c=BTC,mc=RIN,ID=StrixHalo -t 3 ./cpuminer --algo rinhash --url [pool_url] --user [your_rin_wallet] --pass x --threads 32 diff --git a/MINE/rin/Dockerfile b/MINE/rin/Dockerfile deleted file mode 100644 index 5dd2db4..0000000 --- a/MINE/rin/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM ubuntu:22.04 - -ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y \ - build-essential libtool autotools-dev automake pkg-config bsdmainutils \ - libevent-dev libboost-all-dev libssl-dev \ - libdb5.3-dev libdb5.3++-dev libfmt-dev libsqlite3-dev \ - git ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /opt -RUN git clone https://github.com/Rin-coin/rincoin.git && \ - cd rincoin && \ - ./autogen.sh && \ - ./configure --with-incompatible-bdb && \ - make -j$(nproc) && \ - make install - -# runtime -RUN useradd -m rin && mkdir -p /data && chown -R rin:rin /data -USER rin -VOLUME ["/data"] -EXPOSE 9555 9556 -ENTRYPOINT ["/usr/local/bin/rincoind"] -CMD ["-datadir=/data", "-conf=/data/rincoin.conf", "-printtoconsole"] diff --git a/MINE/rin/README.md b/MINE/rin/README.md deleted file mode 100644 index e32da9a..0000000 --- a/MINE/rin/README.md +++ /dev/null @@ -1,377 +0,0 @@ -# RinCoin Mining Setup Complete! πŸŽ‰ - -## 🎯 **Choose Your Mining Strategy:** - -### **Option 1: Solo Mining (Single Miner, All Rewards to You)** -```bash -# Start solo mining proxy -cd /mnt/shared/DEV/repos/d-popov.com/scripts - -./MINE/rin/start_stratum_proxy.sh - -# Run your miner -./cpuminer -a rinhash -o stratum+tcp://127.0.0.1:3333 -u user -p pass -t 28 - -#zergpool: -/mnt/shared/DEV/repos/d-popov.com/mines/rin/miner/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://rinhash.eu.mine.zergpool.com:7148 -u bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j -p c=BTC,mc=RIN,m=solo - -# rplant -/mnt/shared/DEV/repos/d-popov.com/mines/rin/miner/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://eu.rplant.xyz:17148 -u bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j -p c=BTC,mc=RIN,m=solo -/mnt/shared/DEV/repos/d-popov.com/mines/rin/miner/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://eu.rplant.xyz:17148 -u rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q -p m=solo -cpuminer-sse2 -a rinhash -o stratum+tcps://eu.rplant.xyz:17148 -u wallet -p m=solo -??? rin1qvj0yyt9phvled9kxflju3p687a4s7kareglpk5 ??? -``` -**Result**: 100% of block rewards go to your wallet - -### **Option 2: Mining Pool (Multiple Miners, Distributed Rewards)** -```bash -# Start mining pool -./MINE/rin/start_mining_pool.sh - -# Miners connect with their RinCoin addresses: -# Option 1: Address as username -./cpuminer -a rinhash -o stratum+tcp://YOUR_IP:3333 -u rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q -p x - -# Option 2: Address.workername format -./cpuminer -a rinhash -o stratum+tcp://YOUR_IP:3333 -u rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q.worker1 -p x - -# Option 3: Traditional username (rewards to pool address) -./cpuminer -a rinhash -o stratum+tcp://192.168.0.188:3333 -u username.workername -p x -t 24 -``` -**Result**: Block rewards distributed among all miners based on shares - -### **Key Differences:** - -| Feature | Solo Mining (`stratum_proxy`) | Mining Pool (`stratum_pool`) | -|---------|--------------------------------|------------------------------| -| **Rewards** | 100% to you | Distributed among miners | -| **Miners** | Single | Multiple | -| **Setup** | Simple | More complex | -| **Consistency** | Rare big payouts | Regular small payments | -| **Risk** | High variance | Lower variance | -| **Public** | No | Yes, can be published | - ---- - -## βœ… **Successfully Built and Running:** - -### **1. RinCoin Node Container** -- **Container**: `rincoin-node` (ID: 87b5f74a2472) -- **Status**: βœ… **RUNNING** -- **Ports**: 9555 (P2P), 9556 (RPC) -- **Version**: v1.0.1.0-5cf3d4a11 -- **Sync Status**: βœ… **FULLY SYNCED** (blocks: 228,082, headers: 228,082) - -### **2. Wallet Setup** -- **Wallet Name**: `main` -- **Default RinCoin Address**: `rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q` -- **RPC Credentials**: - - User: `rinrpc` - - Password: `745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90` - -### **3. Configuration Files** -- **Config**: `/mnt/data/docker_vol/rincoin/rincoin-node/rincoin.conf` -- **Data Directory**: `/mnt/data/docker_vol/rincoin/rincoin-node/data` -- **Docker Compose**: `MINE/rin/container.yml` - -## πŸš€ **Ready for Mining:** - -### **Pool Mining (Zergpool) - Recommended for Consistent Rewards** -```bash -# CPU Mining RinHash to BTC -sudo docker exec -it amd-strix-halo-llama-rocm bash -c "/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://rinhash.mine.zergpool.com:7148 -u bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j -p c=BTC,mc=RIN,ID=StrixHalo -t 32" -``` - -### **Solo Mining (Local Node) - With Stratum Proxy ⭐ RECOMMENDED** -```bash -# Start mining with your RinCoin address (rewards go to this address!) -./MINE/rin/start_mining_with_address.sh rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q 28 - -# Or use the default address -./MINE/rin/start_mining_with_address.sh -``` - -### **Manual Solo Mining Setup (Stratum Proxy)** -```bash -# 1. Start Stratum proxy (solo mining) -./MINE/rin/start_stratum_proxy.sh - -# 2. In another terminal, connect cpuminer-opt-rin -sudo docker exec -it amd-strix-halo-llama-rocm bash -c "/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://172.17.0.1:3333 -u user -p pass -t 28" -``` - -### **Built-in Core Mining (Low Performance)** -```bash -# Solo mining with built-in RinCoin core (not recommended) -bash MINE/rin/solo_mining_core.sh -t 28 -``` - -### **Why cpuminer-opt-rin Can't Mine Directly to Node** -```bash -# This command will fail: -sudo docker exec -it amd-strix-halo-llama-rocm bash -c "/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o http://127.0.0.1:9556 -u rinrpc -p 745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 -t 28 --coinbase-addr=bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j" - -# Reason: Protocol mismatch -# - cpuminer-opt-rin uses Stratum protocol (for mining pools) -# - RinCoin node uses RPC protocol (for direct mining) -# - No built-in protocol conversion available -``` - -### **Direct CPU Mining Setup (Solo Mining - No Container Needed)** -```bash -# 1. Start stratum proxy (solo mining) -./MINE/rin/start_stratum_proxy.sh - -# OR run in background with logging -nohup python3 MINE/rin/stratum_proxy.py > stratum_proxy.log 2>&1 & - -# 2. Run cpuminer directly on host -/home/db/Downloads/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://127.0.0.1:3333 -u user -p pass -t 28 - -# 3. Clean up when done -./MINE/rin/kill_stratum_proxy.sh -``` - - - - -### **Mining Options Explained** -1. **Built-in Core Mining**: Uses RinCoin's `generatetoaddress` RPC command (low performance) -2. **Pool Mining**: Uses cpuminer-opt-rin with Stratum pools (Zergpool) - consistent rewards -3. **Direct RPC Mining**: Would require custom miner implementing `getblocktemplate` -4. **Solo Mining (Stratum Proxy)**: Uses Stratum proxy to bridge cpuminer-opt-rin to RinCoin node - all rewards to you -5. **Mining Pool (Stratum Pool)**: Distributes block rewards among multiple miners - share-based rewards - -## πŸŠβ€β™‚οΈ **Mining Pool Setup (Multiple Miners)** - -Your Stratum proxy can be enhanced to work as a **full mining pool** that distributes block rewards among multiple miners! - -### **Pool Features:** -- βœ… **Multiple Miner Support**: Unlimited miners can connect -- βœ… **Share-Based Rewards**: Rewards distributed based on share contributions -- βœ… **Pool Fee**: 1% fee for pool maintenance -- βœ… **Real-Time Statistics**: Web dashboard with live stats -- βœ… **Block Reward Distribution**: Automatic distribution when blocks are found - -### **Quick Start Pool:** -```bash -# 1. Start the mining pool -./MINE/rin/start_mining_pool.sh - -# 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 - -python3 stratum_proxy.py --submit-threshold 0.05 - -# For production (10% threshold - good balance) -python3 stratum_proxy.py --submit-threshold 0.1 - -# For aggressive testing (1% threshold) -python3 stratum_proxy.py --submit-threshold 0.01 - -# For normal operation (only valid blocks) -python3 stratum_proxy.py - -``` - -### **Pool vs Solo Mining:** - -| Feature | Solo Mining | Mining Pool | -|---------|-------------|-------------| -| **Block Rewards** | 100% to you | Distributed among miners | -| **Consistency** | Rare blocks | Regular small payments | -| **Setup** | Simple | More complex | -| **Miners** | Single | Multiple | -| **Risk** | High variance | Lower variance | - -### **Publishing Your Pool:** - -#### **1. Public IP Setup:** -```bash -# Get your public IP -curl ifconfig.me - -# Configure firewall (if needed) -sudo ufw allow 3333/tcp -sudo ufw allow 8080/tcp # Web interface -``` - -#### **2. Pool Connection String:** -``` -stratum+tcp://YOUR_PUBLIC_IP:3333 -``` - -#### **3. Web Dashboard:** -- **URL**: `http://YOUR_PUBLIC_IP:8080` -- **Features**: Real-time stats, miner rankings, block history - -#### **4. Pool Announcement:** -Share your pool details: -- **Algorithm**: RinHash -- **Port**: 3333 -- **Fee**: 1% -- **Payout**: Automatic distribution -- **Web**: `http://YOUR_PUBLIC_IP:8080` - -### **Pool Configuration:** -```python -# Edit MINE/rin/stratum_pool.py -pool_address = 'rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q' # Pool wallet -pool_fee_percent = 1.0 # Pool fee percentage -``` - -## build image -sudo bash -lc "cd /mnt/shared/DEV/repos/d-popov.com/scripts/MINE/rin && docker build -t rincoin-node:latest . | cat" - - -## start container -sudo docker run -d --name rincoin-node \ - -p 9555:9555 -p 9556:9556 \ - -v /mnt/data/docker_vol/rincoin/rincoin-node/data:/data \ - -v /mnt/data/docker_vol/rincoin/rincoin-node/rincoin.conf:/data/rincoin.conf:ro \ - rincoin-node:latest -datadir=/data -conf=/data/rincoin.conf -printtoconsole - - - -## check if running -curl --user rinrpc:745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 -H 'content-type: text/plain' --data '{"jsonrpc":"1.0","id":"curl","method":"getblockchaininfo","params":[]}' http://127.0.0.1:9556/ - - -## get wallet -sudo docker exec rincoin-node rincoin-cli -datadir=/data -conf=/data/rincoin.conf createwallet "main" -sudo docker exec rincoin-node rincoin-cli -datadir=/data -conf=/data/rincoin.conf -rpcwallet=main getnewaddress -rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q - - - -```bash -# Solo mining to your RinCoin wallet -./MINE/rin/solo_mining.sh -``` - -## πŸ“Š **Performance Comparison:** - -| Mining Type | Algorithm | Hashrate | Target | Status | -|-------------|-----------|----------|---------|---------| -| **Pool Mining** | RinHash | ~80 kH/s | Zergpool | βœ… Working | -| **Solo Mining** | RinHash | Built-in CPU | Local Node | βœ… Working | -| **GPU Mining** | Equihash 125,4 | 28.8 Sol/s | Zergpool | βœ… Working | - -## πŸ”§ **Management Commands:** - -### **Node Management** -```bash -# Start node -sudo docker start rincoin-node - -# Stop node -sudo docker stop rincoin-node - -# View logs -sudo docker logs -f rincoin-node - -# Check sync status -sudo docker exec rincoin-node rincoin-cli -datadir=/data -conf=/data/rincoin.conf getblockchaininfo -``` - -### **Wallet Management** -```bash -# List all wallets -sudo docker exec rincoin-node rincoin-cli -datadir=/data -conf=/data/rincoin.conf listwallets - -# Load wallet -sudo docker exec rincoin-node rincoin-cli -datadir=/data -conf=/data/rincoin.conf loadwallet "main" - -# Get new address -sudo docker exec rincoin-node rincoin-cli -datadir=/data -conf=/data/rincoin.conf -rpcwallet=main getnewaddress - -# Check balance -sudo docker exec rincoin-node rincoin-cli -datadir=/data -conf=/data/rincoin.conf -rpcwallet=main getbalance -``` - -### **RPC Access** -```bash -# Test RPC connection -curl --user rinrpc:745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 \ - -H 'content-type: text/plain' \ - --data '{"jsonrpc":"1.0","id":"curl","method":"getblockchaininfo","params":[]}' \ - http://127.0.0.1:9556/ - -# Get new address via RPC -curl --user rinrpc:745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 \ - -H 'content-type: text/plain' \ - --data '{"jsonrpc":"1.0","id":"curl","method":"getnewaddress","params":[]}' \ - http://127.0.0.1:9556/ -``` - -## ⚠️ **Important Notes:** - -1. **Node Sync**: βœ… **COMPLETE** - Node is fully synced and ready -2. **Solo Mining**: Very low chance of finding blocks solo. Consider pool mining for consistent rewards. -3. **RPC Access**: βœ… **WORKING** - RPC is accessible on port 9556 -4. **Address Parameter**: Solo mining script accepts custom addresses or uses default -5. **Block Rewards**: When solo mining, ALL block rewards go to your specified RinCoin address - -## πŸ› οΈ **Troubleshooting:** - -### **Port 3333 Already in Use** -```bash -# Check what's using the port -sudo netstat -tlnp | grep :3333 - -# Kill existing processes -./MINE/rin/kill_stratum_proxy.sh - -# Or manually kill -sudo lsof -ti:3333 | xargs sudo kill -9 -``` - -### **Container Can't Connect to Proxy** -```bash -# Use Docker gateway IP instead of localhost -sudo docker exec -it amd-strix-halo-llama-rocm bash -c "/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://172.17.0.1:3333 -u user -p pass -t 28" -``` - -### **Check Proxy Logs** -```bash -# View real-time logs -tail -f stratum_proxy.log - -# Check if proxy is running -ps aux | grep stratum_proxy -``` - -## πŸ” **Wallet Backup & Restoration** - -### **Backup Your Wallet** -```bash -# Run the backup script -./MINE/rin/dump_wallet.sh -``` -- This creates a text file with all private keys in `~/rin_wallet_backups/`. -- **Security**: Encrypt immediately with `gpg -c `, store offline, delete unencrypted copy. -- Contains sensitive dataβ€”anyone with this can spend your coins. - -### **Restore on New Node** -```bash -# Automated restoration (requires new node setup) -./MINE/rin/restore_wallet.sh /path/to/backup.txt - -# Manual steps: -# 1. Stop new node: sudo docker stop rincoin-node -# 2. Copy wallet.dat or import dump file -# 3. Start node: sudo docker start rincoin-node -# 4. Load wallet: sudo docker exec rincoin-node rincoin-cli ... loadwallet main -# 5. Import if using dump: importwallet /path/to/dump.txt -``` - -## 🎯 **Next Steps:** - -1. βœ… **Node is synced** - Ready for all operations -2. **Choose mining strategy**: Pool mining for consistent income vs Solo mining for block rewards -3. **Monitor performance** and adjust thread count as needed -4. **Set up monitoring** for node health and mining performance -5. **Backup wallet regularly** - Use the dump script above diff --git a/MINE/rin/__pycache__/pool_web_interface.cpython-312.pyc b/MINE/rin/__pycache__/pool_web_interface.cpython-312.pyc deleted file mode 100644 index 56c1c8f..0000000 Binary files a/MINE/rin/__pycache__/pool_web_interface.cpython-312.pyc and /dev/null differ diff --git a/MINE/rin/container.yml b/MINE/rin/container.yml deleted file mode 100644 index 3b34c04..0000000 --- a/MINE/rin/container.yml +++ /dev/null @@ -1,18 +0,0 @@ -version: "3.8" - -services: - rincoin-node: - container_name: rincoin-node - image: rincoin-node:latest - restart: unless-stopped - ports: - - "9555:9555" - - "9556:9556" - volumes: - - /mnt/data/docker_vol/rincoin/rincoin-node/data:/data - - /mnt/data/docker_vol/rincoin/rincoin-node/rincoin.conf:/data/rincoin.conf:ro - command: - - rincoind - - -datadir=/data - - -conf=/data/rincoin.conf - - -printtoconsole \ No newline at end of file diff --git a/MINE/rin/kill_stratum_proxy.sh b/MINE/rin/kill_stratum_proxy.sh deleted file mode 100644 index cfba4f3..0000000 --- a/MINE/rin/kill_stratum_proxy.sh +++ /dev/null @@ -1,40 +0,0 @@ -# #!/bin/bash - -# # Kill RinCoin Stratum Proxy processes - -# echo "=== Killing RinCoin Stratum Proxy ===" -# echo "" - -# # Find and kill Python processes running stratum_proxy.py -# PIDS=$(ps aux | grep "stratum_proxy.py" | grep -v grep | awk '{print $2}') - -# if [ -n "$PIDS" ]; then -# echo "Found Stratum Proxy processes: $PIDS" -# echo "Killing processes..." -# for pid in $PIDS; do -# kill -9 "$pid" 2>/dev/null && echo "Killed PID: $pid" || echo "Failed to kill PID: $pid" -# done -# else -# echo "No Stratum Proxy processes found" -# fi - -# # Also kill any process using port 3333 -# echo "" -# echo "Checking port 3333..." -# PORT_PIDS=$(sudo lsof -ti:3333 2>/dev/null) - -# if [ -n "$PORT_PIDS" ]; then -# echo "Found processes using port 3333: $PORT_PIDS" -# echo "Killing processes..." -# for pid in $PORT_PIDS; do -# sudo kill -9 "$pid" 2>/dev/null && echo "Killed PID: $pid" || echo "Failed to kill PID: $pid" -# done -# else -# echo "No processes using port 3333" -# fi - -# echo "" -# echo "βœ… Cleanup complete!" -# echo "" -# echo "Port 3333 status:" -# netstat -tln | grep ":3333 " || echo "Port 3333 is free" diff --git a/MINE/rin/pool_web_interface.py b/MINE/rin/pool_web_interface.py deleted file mode 100644 index 1577778..0000000 --- a/MINE/rin/pool_web_interface.py +++ /dev/null @@ -1,529 +0,0 @@ -# #!/usr/bin/env python3 -# """ -# RinCoin Mining Pool Web Interface -# Provides web dashboard for pool statistics and miner management -# """ - -# import json -# import sqlite3 -# import requests -# from datetime import datetime, timedelta -# from http.server import HTTPServer, BaseHTTPRequestHandler -# import threading -# import time -# from requests.auth import HTTPBasicAuth - -# class PoolWebInterface: -# def __init__(self, pool_db, host='0.0.0.0', port=8080, rpc_host='127.0.0.1', rpc_port=9556, -# rpc_user='rinrpc', rpc_password='745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90'): -# self.pool_db = pool_db -# self.host = host -# self.port = port -# self.rpc_host = rpc_host -# self.rpc_port = rpc_port -# self.rpc_user = rpc_user -# self.rpc_password = rpc_password -# self.chart_time_window = 3600 # 1 hour default, adjustable - -# def set_chart_time_window(self, seconds): -# """Set the chart time window""" -# self.chart_time_window = seconds - -# def format_hashrate(self, hashrate): -# """Format hashrate in human readable format""" -# if hashrate >= 1e12: -# return f"{hashrate/1e12:.2f} TH/s" -# elif hashrate >= 1e9: -# return f"{hashrate/1e9:.2f} GH/s" -# elif hashrate >= 1e6: -# return f"{hashrate/1e6:.2f} MH/s" -# elif hashrate >= 1e3: -# return f"{hashrate/1e3:.2f} KH/s" -# elif hashrate >= 0.01: -# return f"{hashrate:.2f} H/s" -# elif hashrate > 0: -# return f"{hashrate*1000:.2f} mH/s" -# else: -# return "0.00 H/s" - -# def get_pool_balance(self): -# """Get pool wallet balance via RPC""" -# try: -# url = f"http://{self.rpc_host}:{self.rpc_port}/" -# headers = {'content-type': 'text/plain'} -# auth = HTTPBasicAuth(self.rpc_user, self.rpc_password) - -# payload = { -# "jsonrpc": "1.0", -# "id": "pool_balance", -# "method": "getbalance", -# "params": [] -# } - -# response = requests.post(url, json=payload, headers=headers, auth=auth, timeout=10) - -# if response.status_code == 200: -# result = response.json() -# if 'error' in result and result['error'] is not None: -# print(f"RPC Error getting balance: {result['error']}") -# return 0.0 -# balance = result.get('result', 0) -# return float(balance) / 100000000 # Convert from satoshis to RIN -# else: -# print(f"HTTP Error getting balance: {response.status_code}") -# return 0.0 - -# except Exception as e: -# print(f"Error getting pool balance: {e}") -# return 0.0 - -# def get_pool_stats(self): -# """Get current pool statistics""" -# try: -# cursor = self.pool_db.cursor() - -# # Total miners (ever registered) -# cursor.execute('SELECT COUNT(DISTINCT id) FROM miners') -# total_miners = cursor.fetchone()[0] - -# # Active miners (last 5 minutes) -# cursor.execute(''' -# SELECT COUNT(DISTINCT m.id) FROM miners m -# JOIN shares s ON m.id = s.miner_id -# WHERE s.submitted > datetime('now', '-5 minutes') -# ''') -# active_miners = cursor.fetchone()[0] - -# # Total shares (last 24 hours) -# cursor.execute(''' -# SELECT COUNT(*) FROM shares -# WHERE submitted > datetime('now', '-24 hours') -# ''') -# total_shares_24h = cursor.fetchone()[0] - -# # Pool hashrate: sum of miners.last_hashrate (instantaneous) -# cursor.execute('SELECT COALESCE(SUM(last_hashrate), 0) FROM miners') -# hashrate = cursor.fetchone()[0] or 0.0 - -# # Debug stats -# cursor.execute(''' -# SELECT SUM(difficulty), COUNT(*) FROM shares -# WHERE submitted > datetime('now', '-5 minutes') -# ''') -# rd = cursor.fetchone() -# recent_difficulty = rd[0] if rd and rd[0] else 0 -# recent_share_count = rd[1] if rd and rd[1] else 0 - -# # Get historical hashrate data for chart -# cursor.execute(''' -# SELECT -# strftime('%H:%M', submitted) as time, -# COUNT(*) as shares, -# SUM(difficulty) as total_difficulty -# FROM shares -# WHERE submitted > datetime('now', '-{} seconds') -# GROUP BY strftime('%Y-%m-%d %H:%M', submitted) -# ORDER BY submitted DESC -# LIMIT 60 -# '''.format(self.chart_time_window)) -# historical_data = cursor.fetchall() - -# # Calculate individual miner hashrates -# cursor.execute(''' -# SELECT -# m.user, m.worker, -# COUNT(s.id) as shares, -# SUM(s.difficulty) as total_difficulty, -# m.last_share -# FROM miners m -# LEFT JOIN shares s ON m.id = s.miner_id -# AND s.submitted > datetime('now', '-5 minutes') -# GROUP BY m.id, m.user, m.worker -# ORDER BY shares DESC -# ''') -# miner_stats = cursor.fetchall() - -# # Calculate individual hashrates (use miners.last_hashrate) -# miner_hashrates = [] -# for user, worker, shares, difficulty, last_share in miner_stats: -# cursor.execute('SELECT last_hashrate FROM miners WHERE user = ? AND worker = ? LIMIT 1', (user, worker)) -# row = cursor.fetchone() -# miner_hashrate = row[0] if row and row[0] else 0.0 -# miner_hashrates.append((user, worker, shares, miner_hashrate, last_share)) - -# # Total blocks found -# cursor.execute('SELECT COUNT(*) FROM blocks') -# total_blocks = cursor.fetchone()[0] - -# # Recent blocks -# cursor.execute(''' -# SELECT block_hash, height, reward, found_at -# FROM blocks -# ORDER BY found_at DESC -# LIMIT 10 -# ''') -# recent_blocks = cursor.fetchall() - -# # Top miners (last 24 hours) - show all miners, even without shares -# cursor.execute(''' -# SELECT m.user, m.worker, -# COALESCE(COUNT(s.id), 0) as shares, -# m.last_share, -# m.created -# FROM miners m -# LEFT JOIN shares s ON m.id = s.miner_id -# AND s.submitted > datetime('now', '-24 hours') -# GROUP BY m.id, m.user, m.worker -# ORDER BY shares DESC, m.created DESC -# LIMIT 20 -# ''') -# top_miners = cursor.fetchall() - -# # All active miners (for better visibility) -# cursor.execute(''' -# SELECT user, worker, created, last_share -# FROM miners -# ORDER BY created DESC -# LIMIT 10 -# ''') -# all_miners = cursor.fetchall() - -# # Get pool balance -# pool_balance = self.get_pool_balance() - -# return { -# 'total_miners': total_miners, -# 'active_miners': active_miners, -# 'total_shares_24h': total_shares_24h, -# 'hashrate': hashrate, -# 'total_blocks': total_blocks, -# 'recent_blocks': recent_blocks, -# 'top_miners': top_miners, -# 'all_miners': all_miners, -# 'miner_hashrates': miner_hashrates, -# 'historical_data': historical_data, -# 'pool_balance': pool_balance, -# 'debug': { -# 'recent_difficulty': recent_difficulty, -# 'recent_share_count': recent_share_count, -# 'total_shares_24h': total_shares_24h -# } -# } -# except Exception as e: -# print(f"Error getting pool stats: {e}") -# return {} - -# def generate_html(self, stats): -# """Generate HTML dashboard""" -# html = f""" -# -# -# -# RinCoin Mining Pool -# -# -# -# -# -#
-#
-#

πŸŠβ€β™‚οΈ RinCoin Mining Pool

-#

Distribute block rewards among multiple miners

-#
- -# - -#
-#
-#
{stats.get('total_miners', 0)}
-#
Total Miners
-#
-#
-#
{stats.get('active_miners', 0)}
-#
Active Miners
-#
-#
-#
{self.format_hashrate(stats.get('hashrate', 0))}
-#
Hashrate
-#
-#
-#
{stats.get('total_blocks', 0)}
-#
Blocks Found
-#
-#
-#
{stats.get('pool_balance', 0):.2f}
-#
Pool Balance (RIN)
-#
-#
- -#
-#

πŸ“Š Pool Statistics

-#

24h Shares: {stats.get('total_shares_24h', 0):,}

-#

Pool Fee: 1%

-#

Pool Balance: {stats.get('pool_balance', 0):.8f} RIN

-#

Connection String: stratum+tcp://YOUR_IP:3333

- -# -#
-# πŸ” Debug Info -#

Recent Difficulty (5min): {stats.get('debug', {}).get('recent_difficulty', 0):.6f}

-#

Recent Share Count (5min): {stats.get('debug', {}).get('recent_share_count', 0)}

-#

Total Shares (24h): {stats.get('debug', {}).get('total_shares_24h', 0):,}

-#

Active Miners: {stats.get('active_miners', 0)} (last 5 minutes)

-#

Total Miners: {stats.get('total_miners', 0)} (ever registered)

-#
-#
- -#
-#

πŸ“ˆ Hashrate Chart

-#
-# -# -#
-#
-# -#
-#
- -#
-#

πŸ‘₯ Connected Miners

-# -# -# -# -# -# -# -# """ - -# for miner in stats.get('all_miners', []): -# user, worker, created, last_share = miner -# html += f""" -# -# -# -# -# -# -# """ - -# if not stats.get('all_miners', []): -# html += """ -# -# -# -# """ - -# html += """ -#
UserWorkerConnectedLast Share
{user}{worker}{created}{last_share or 'Never'}
No miners connected
-#
- -#
-#

πŸ† Top Miners (24h Shares)

-# -# -# -# -# -# -# -# -# """ - -# for miner in stats.get('miner_hashrates', []): -# user, worker, shares, hashrate, last_share = miner -# html += f""" -# -# -# -# -# -# -# -# """ - -# if not stats.get('top_miners', []): -# html += """ -# -# -# -# """ - -# html += """ -#
UserWorkerSharesHashrateLast Share
{user}{worker}{shares:,}{self.format_hashrate(hashrate)}{last_share or 'Never'}
No shares submitted yet
-#
- -#
-#

πŸ† Recent Blocks

-# -# -# -# -# -# -# -# """ - -# for block in stats.get('recent_blocks', []): -# block_hash, height, reward, found_at = block -# html += f""" -# -# -# -# -# -# -# """ - -# html += """ -#
HeightHashRewardFound At
{height}{block_hash[:16]}...{reward:.8f} RIN{found_at}
-#
- -#
-#

πŸ”— Connect to Pool

-#

Use any RinHash-compatible miner:

-#
./cpuminer -a rinhash -o stratum+tcp://YOUR_IP:3333 -u username.workername -p x
-#

Replace YOUR_IP with your server's public IP address

-#
-#
- -# -# - -# -# -# -# """ -# return html - -# class PoolWebHandler(BaseHTTPRequestHandler): -# def __init__(self, *args, pool_interface=None, **kwargs): -# self.pool_interface = pool_interface -# super().__init__(*args, **kwargs) - -# def do_GET(self): -# if self.path == '/': -# stats = self.pool_interface.get_pool_stats() -# html = self.pool_interface.generate_html(stats) - -# self.send_response(200) -# self.send_header('Content-type', 'text/html') -# self.end_headers() -# self.wfile.write(html.encode('utf-8')) -# elif self.path == '/api/stats': -# stats = self.pool_interface.get_pool_stats() - -# self.send_response(200) -# self.send_header('Content-type', 'application/json') -# self.end_headers() -# self.wfile.write(json.dumps(stats).encode('utf-8')) -# else: -# self.send_response(404) -# self.end_headers() -# self.wfile.write(b'Not Found') - -# def log_message(self, format, *args): -# # Suppress access logs -# pass - -# def start_web_interface(pool_db, host='0.0.0.0', port=8083, rpc_host='127.0.0.1', rpc_port=9556, -# rpc_user='rinrpc', rpc_password='745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90'): -# """Start the web interface server""" -# interface = PoolWebInterface(pool_db, host, port, rpc_host, rpc_port, rpc_user, rpc_password) - -# class Handler(PoolWebHandler): -# def __init__(self, *args, **kwargs): -# super().__init__(*args, pool_interface=interface, **kwargs) - -# try: -# server = HTTPServer((host, port), Handler) -# print(f"🌐 Web interface running on http://{host}:{port}") -# print("Press Ctrl+C to stop") - -# server.serve_forever() -# except OSError as e: -# if "Address already in use" in str(e): -# print(f"⚠️ Port {port} is already in use, web interface not started") -# print(f"πŸ’‘ Try a different port or kill the process using port {port}") -# else: -# print(f"❌ Failed to start web interface: {e}") -# except KeyboardInterrupt: -# print("\nπŸ›‘ Shutting down web interface...") -# server.shutdown() - -# if __name__ == "__main__": -# # This would be called from the main pool server -# print("Web interface module loaded") diff --git a/MINE/rin/rincoin.conf b/MINE/rin/rincoin.conf deleted file mode 100644 index aca7947..0000000 --- a/MINE/rin/rincoin.conf +++ /dev/null @@ -1,13 +0,0 @@ -server=1 -daemon=0 -listen=1 -txindex=1 - -rpcuser=rinrpc -rpcpassword=745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 -rpcallowip=0.0.0.0/0 -rpcport=9556 - -# performance -maxconnections=64 -dbcache=2048 diff --git a/MINE/rin/solo_mining.sh b/MINE/rin/solo_mining.sh deleted file mode 100644 index 54001dc..0000000 --- a/MINE/rin/solo_mining.sh +++ /dev/null @@ -1,47 +0,0 @@ -# #!/bin/bash - -# # Solo Mining Script for RinCoin -# # Uses local RinCoin node for solo mining - -# echo "=== RinCoin Solo Mining Setup ===" -# echo "" - -# # Check if rincoin-node container is running -# if ! sudo docker ps | grep -q "rincoin-node"; then -# echo "Error: rincoin-node container is not running!" -# echo "Please start it first:" -# echo "sudo docker start rincoin-node" -# exit 1 -# fi - -# # Get wallet address -# RIN_ADDRESS=$(sudo docker exec rincoin-node rincoin-cli -datadir=/data -conf=/data/rincoin.conf -rpcwallet=main getnewaddress 2>/dev/null) - -# if [ -z "$RIN_ADDRESS" ]; then -# echo "Error: Could not get RinCoin address!" -# echo "Make sure the wallet is created and the node is synced." -# exit 1 -# fi - -# echo "RinCoin Address: $RIN_ADDRESS" -# echo "" - -# # Check node sync status -# SYNC_STATUS=$(sudo docker exec rincoin-node rincoin-cli -datadir=/data -conf=/data/rincoin.conf getblockchaininfo | grep -o '"initialblockdownload": [^,]*' | cut -d' ' -f2) - -# if [ "$SYNC_STATUS" = "true" ]; then -# echo "⚠️ WARNING: Node is still syncing (initialblockdownload: true)" -# echo "Solo mining may not work properly until sync is complete." -# echo "" -# fi - -# echo "Starting solo mining with cpuminer-opt-rin..." -# echo "Algorithm: rinhash" -# echo "Target: Local RinCoin node (127.0.0.1:9555)" -# echo "Wallet: $RIN_ADDRESS" -# echo "" -# echo "Press Ctrl+C to stop mining" -# echo "" - -# # Start solo mining -# sudo docker exec -it amd-strix-halo-llama-rocm bash -c "/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://127.0.0.1:9555 -u $RIN_ADDRESS -p x -t 32" diff --git a/MINE/rin/solo_mining_core.sh b/MINE/rin/solo_mining_core.sh deleted file mode 100644 index 3a9efe5..0000000 --- a/MINE/rin/solo_mining_core.sh +++ /dev/null @@ -1,171 +0,0 @@ -# #!/bin/bash - -# # RinCoin Solo Mining using Built-in Core Mining -# # Uses RinCoin Core's generatetoaddress command - -# # Default address (can be overridden with command line parameter) -# DEFAULT_ADDRESS="rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q" - -# # Get total CPU cores for default thread count -# TOTAL_CORES=$(nproc) -# DEFAULT_THREADS=$TOTAL_CORES - -# # Parse command line arguments -# RIN_ADDRESS="" -# THREAD_COUNT="" - -# # Parse arguments -# while [[ $# -gt 0 ]]; do -# case $1 in -# -a|--address) -# RIN_ADDRESS="$2" -# shift 2 -# ;; -# -t|--threads) -# THREAD_COUNT="$2" -# shift 2 -# ;; -# -h|--help) -# echo "Usage: $0 [OPTIONS]" -# echo "" -# echo "Options:" -# echo " -a, --address ADDRESS RinCoin address to mine to (default: $DEFAULT_ADDRESS)" -# echo " -t, --threads COUNT Number of threads to use (default: $DEFAULT_THREADS)" -# echo " -h, --help Show this help message" -# echo "" -# echo "Examples:" -# echo " $0 # Use defaults (all cores, default address)" -# echo " $0 -a rin1q... -t 16 # Custom address and 16 threads" -# echo " $0 --address rin1q... --threads 8 # Custom address and 8 threads" -# exit 0 -# ;; -# *) -# echo "Unknown option: $1" -# echo "Use -h or --help for usage information" -# exit 1 -# ;; -# esac -# done - -# # Set defaults if not provided -# if [ -z "$RIN_ADDRESS" ]; then -# RIN_ADDRESS="$DEFAULT_ADDRESS" -# echo "No address provided, using default: $RIN_ADDRESS" -# fi - -# if [ -z "$THREAD_COUNT" ]; then -# THREAD_COUNT="$DEFAULT_THREADS" -# echo "No thread count provided, using all cores: $THREAD_COUNT" -# fi - -# # Validate thread count -# if ! [[ "$THREAD_COUNT" =~ ^[0-9]+$ ]] || [ "$THREAD_COUNT" -lt 1 ] || [ "$THREAD_COUNT" -gt "$TOTAL_CORES" ]; then -# echo "❌ Error: Invalid thread count: $THREAD_COUNT" -# echo "Thread count must be between 1 and $TOTAL_CORES" -# exit 1 -# fi - -# echo "=== RinCoin Solo Mining (Built-in Core Mining) ===" -# echo "CPU Cores Available: $TOTAL_CORES" -# echo "Threads to Use: $THREAD_COUNT" -# echo "Target Address: $RIN_ADDRESS" -# echo "" -# echo "" - -# # Configuration -# RPC_HOST="127.0.0.1" -# RPC_PORT="9556" -# RPC_USER="rinrpc" -# RPC_PASS="745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90" - -# # Function to call RPC -# call_rpc() { -# local method="$1" -# local params="$2" - -# curl -s --user "$RPC_USER:$RPC_PASS" \ -# -H 'content-type: text/plain' \ -# --data "{\"jsonrpc\":\"1.0\",\"id\":\"curl\",\"method\":\"$method\",\"params\":$params}" \ -# "http://$RPC_HOST:$RPC_PORT/" -# } - -# # Wait for node to be ready -# echo "Waiting for RinCoin node to be ready..." -# while true; do -# response=$(call_rpc "getblockchaininfo" "[]") -# if [[ $response != *"Loading block index"* ]]; then -# break -# fi -# echo "Node still loading... waiting 10 seconds" -# sleep 10 -# done - -# echo "βœ… Node is ready!" -# echo "" - -# # Load wallet if not already loaded -# echo "Loading wallet..." -# wallet_response=$(call_rpc "loadwallet" "[\"main\"]") -# if [[ $wallet_response == *"error"* ]] && [[ $wallet_response == *"already loaded"* ]]; then -# echo "βœ… Wallet already loaded" -# else -# echo "βœ… Wallet loaded successfully" -# fi -# echo "" - -# # Validate the provided address (basic check) -# if [[ ! "$RIN_ADDRESS" =~ ^rin1[a-zA-Z0-9]{25,}$ ]]; then -# echo "❌ Error: Invalid RinCoin address format: $RIN_ADDRESS" -# echo "RinCoin addresses should start with 'rin1' and be ~30 characters long" -# exit 1 -# fi - -# echo "βœ… Using RinCoin Address: $RIN_ADDRESS" -# echo "" - -# # Get blockchain info -# echo "Blockchain Status:" -# blockchain_info=$(call_rpc "getblockchaininfo" "[]") -# blocks=$(echo "$blockchain_info" | grep -o '"blocks":[^,]*' | cut -d':' -f2) -# headers=$(echo "$blockchain_info" | grep -o '"headers":[^,]*' | cut -d':' -f2) -# difficulty=$(echo "$blockchain_info" | grep -o '"difficulty":[^,]*' | cut -d':' -f2) - -# echo "Blocks: $blocks" -# echo "Headers: $headers" -# echo "Difficulty: $difficulty" -# echo "" - -# echo "⚠️ IMPORTANT: Built-in Core Mining Limitations:" -# echo "1. Uses CPU only (not GPU)" -# echo "2. Very low hashpower compared to specialized miners" -# echo "3. Extremely low chance of finding blocks solo" -# echo "4. Best for testing, not profitable mining" -# echo "5. Thread count affects mining attempts per cycle" -# echo "" - -# echo "πŸš€ Starting Built-in Solo Mining..." -# echo "Target Address: $RIN_ADDRESS" -# echo "Threads: $THREAD_COUNT" -# echo "Press Ctrl+C to stop mining" -# echo "" - -# # Start built-in mining with specified thread count -# # Note: RinCoin Core's generatetoaddress doesn't directly support thread count -# # but we can run multiple instances or adjust the maxtries parameter -# while true; do -# echo "Attempting to mine 1 block with $THREAD_COUNT threads..." - -# # Adjust maxtries based on thread count for better distribution -# adjusted_tries=$((1000000 * THREAD_COUNT / TOTAL_CORES)) - -# mining_result=$(call_rpc "generatetoaddress" "[1, \"$RIN_ADDRESS\", $adjusted_tries]") - -# if [[ $mining_result == *"result"* ]] && [[ $mining_result != *"[]"* ]]; then -# echo "πŸŽ‰ BLOCK FOUND!" -# echo "Result: $mining_result" -# break -# else -# echo "No block found in this attempt (tries: $adjusted_tries). Retrying..." -# sleep 5 -# fi -# done diff --git a/MINE/rin/solo_mining_remote.sh b/MINE/rin/solo_mining_remote.sh deleted file mode 100644 index 843df89..0000000 --- a/MINE/rin/solo_mining_remote.sh +++ /dev/null @@ -1,81 +0,0 @@ -# #!/bin/bash - -# # Remote Solo Mining Script for RinCoin -# # Connects to RinCoin node over network/RPC - -# # Configuration -# RPC_HOST="127.0.0.1" # Change to your server IP for remote access -# RPC_PORT="9556" -# RPC_USER="rinrpc" -# RPC_PASS="745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90" - -# echo "=== Remote RinCoin Solo Mining Setup ===" -# echo "RPC Host: $RPC_HOST:$RPC_PORT" -# echo "" - -# # Test RPC connection -# echo "Testing RPC connection..." -# RPC_RESPONSE=$(curl -s --user "$RPC_USER:$RPC_PASS" \ -# -H 'content-type: text/plain' \ -# --data '{"jsonrpc":"1.0","id":"curl","method":"getblockchaininfo","params":[]}' \ -# "http://$RPC_HOST:$RPC_PORT/") - -# if [[ $RPC_RESPONSE == *"error"* ]]; then -# echo "❌ Error: Could not connect to RinCoin RPC!" -# echo "Response: $RPC_RESPONSE" -# echo "" -# echo "Check:" -# echo "1. RinCoin node is running" -# echo "2. RPC port $RPC_PORT is accessible" -# echo "3. Firewall allows connections to port $RPC_PORT" -# exit 1 -# fi - -# echo "βœ… RPC connection successful!" -# echo "" - -# # Get wallet address via RPC -# echo "Getting wallet address..." -# WALLET_RESPONSE=$(curl -s --user "$RPC_USER:$RPC_PASS" \ -# -H 'content-type: text/plain' \ -# --data '{"jsonrpc":"1.0","id":"curl","method":"getnewaddress","params":[]}' \ -# "http://$RPC_HOST:$RPC_PORT/") - -# RIN_ADDRESS=$(echo "$WALLET_RESPONSE" | grep -o '"result":"[^"]*"' | cut -d'"' -f4) - -# if [ -z "$RIN_ADDRESS" ]; then -# echo "❌ Error: Could not get RinCoin address!" -# echo "Response: $WALLET_RESPONSE" -# echo "" -# echo "Make sure wallet 'main' exists:" -# echo "curl --user $RPC_USER:$RPC_PASS -H 'content-type: text/plain' --data '{\"jsonrpc\":\"1.0\",\"id\":\"curl\",\"method\":\"createwallet\",\"params\":[\"main\"]}' http://$RPC_HOST:$RPC_PORT/" -# exit 1 -# fi - -# echo "βœ… RinCoin Address: $RIN_ADDRESS" -# echo "" - -# # Check node sync status -# SYNC_RESPONSE=$(curl -s --user "$RPC_USER:$RPC_PASS" \ -# -H 'content-type: text/plain' \ -# --data '{"jsonrpc":"1.0","id":"curl","method":"getblockchaininfo","params":[]}' \ -# "http://$RPC_HOST:$RPC_PORT/") - -# SYNC_STATUS=$(echo "$SYNC_RESPONSE" | grep -o '"initialblockdownload":[^,]*' | cut -d':' -f2 | tr -d ' ') - -# if [ "$SYNC_STATUS" = "true" ]; then -# echo "⚠️ WARNING: Node is still syncing (initialblockdownload: true)" -# echo "Solo mining may not work properly until sync is complete." -# echo "" -# fi - -# echo "Starting remote solo mining with cpuminer-opt-rin..." -# echo "Algorithm: rinhash" -# echo "Target: RinCoin node at $RPC_HOST:9555" -# echo "Wallet: $RIN_ADDRESS" -# echo "" -# echo "Press Ctrl+C to stop mining" -# echo "" - -# # Start solo mining (connect to P2P port, not RPC) -# sudo docker exec -it amd-strix-halo-llama-rocm bash -c "/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://$RPC_HOST:9555 -u $RIN_ADDRESS -p x -t 32" diff --git a/MINE/rin/solo_mining_rpc.sh b/MINE/rin/solo_mining_rpc.sh deleted file mode 100644 index 220e641..0000000 --- a/MINE/rin/solo_mining_rpc.sh +++ /dev/null @@ -1,76 +0,0 @@ -# #!/bin/bash - -# # RinCoin Solo Mining via RPC -# # This script uses RinCoin's RPC interface for solo mining - -# echo "=== RinCoin Solo Mining via RPC ===" -# echo "" - -# # Configuration -# RPC_HOST="127.0.0.1" -# RPC_PORT="9556" -# RPC_USER="rinrpc" -# RPC_PASS="745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90" - -# # Function to call RPC -# call_rpc() { -# local method="$1" -# local params="$2" - -# curl -s --user "$RPC_USER:$RPC_PASS" \ -# -H 'content-type: text/plain' \ -# --data "{\"jsonrpc\":\"1.0\",\"id\":\"curl\",\"method\":\"$method\",\"params\":$params}" \ -# "http://$RPC_HOST:$RPC_PORT/" -# } - -# # Wait for node to be ready -# echo "Waiting for RinCoin node to be ready..." -# while true; do -# response=$(call_rpc "getblockchaininfo" "[]") -# if [[ $response != *"Loading block index"* ]]; then -# break -# fi -# echo "Node still loading... waiting 10 seconds" -# sleep 10 -# done - -# echo "βœ… Node is ready!" -# echo "" - -# # Get wallet address -# echo "Getting wallet address..." -# wallet_response=$(call_rpc "getnewaddress" "[]") -# rin_address=$(echo "$wallet_response" | grep -o '"result":"[^"]*"' | cut -d'"' -f4) - -# if [ -z "$rin_address" ]; then -# echo "❌ Error: Could not get RinCoin address!" -# echo "Response: $wallet_response" -# exit 1 -# fi - -# echo "βœ… RinCoin Address: $rin_address" -# echo "" - -# # Get blockchain info -# echo "Blockchain Status:" -# blockchain_info=$(call_rpc "getblockchaininfo" "[]") -# blocks=$(echo "$blockchain_info" | grep -o '"blocks":[^,]*' | cut -d':' -f2) -# headers=$(echo "$blockchain_info" | grep -o '"headers":[^,]*' | cut -d':' -f2) -# difficulty=$(echo "$blockchain_info" | grep -o '"difficulty":[^,]*' | cut -d':' -f2) - -# echo "Blocks: $blocks" -# echo "Headers: $headers" -# echo "Difficulty: $difficulty" -# echo "" - -# echo "⚠️ IMPORTANT: RinCoin solo mining requires:" -# echo "1. A fully synced node (currently at block $blocks of $headers)" -# echo "2. Mining software that supports RinCoin's RPC mining protocol" -# echo "3. Very high hashpower to find blocks solo" -# echo "" -# echo "For now, we recommend pool mining for consistent rewards:" -# echo "" -# echo "Pool Mining Command:" -# echo "sudo docker exec -it amd-strix-halo-llama-rocm bash -c \"/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://rinhash.mine.zergpool.com:7148 -u bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j -p c=BTC,mc=RIN,ID=StrixHalo -t 32\"" -# echo "" -# echo "Your RinCoin address for solo mining: $rin_address" diff --git a/MINE/rin/start_mining_pool.sh b/MINE/rin/start_mining_pool.sh deleted file mode 100644 index ec4c828..0000000 --- a/MINE/rin/start_mining_pool.sh +++ /dev/null @@ -1,83 +0,0 @@ -# #!/bin/bash - -# # RinCoin Mining Pool Server Startup Script -# # Distributes block rewards among multiple miners - -# echo "=== RinCoin Mining Pool Server ===" -# echo "" - -# # Check if RinCoin node is running -# echo "Checking RinCoin node status..." -# if ! curl -s -u rinrpc:745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 \ -# -H 'content-type: text/plain' \ -# --data '{"jsonrpc":"1.0","id":"curl","method":"getblockchaininfo","params":[]}' \ -# http://127.0.0.1:9556/ > /dev/null; then -# echo "❌ RinCoin node is not running!" -# echo "Start it first with: docker start rincoin-node" -# exit 1 -# fi - -# echo "βœ… RinCoin node is running" - -# # Check Python dependencies -# echo "Checking Python dependencies..." -# python3 -c "import requests, sqlite3" 2>/dev/null || { -# echo "Installing python3-requests..." -# sudo apt-get update && sudo apt-get install -y python3-requests -# } - -# echo "βœ… Python dependencies ready" - -# # Check if port 3333 is already in use -# if netstat -tln | grep -q ":3333 "; then -# echo "" -# echo "⚠️ Port 3333 is already in use!" -# echo "" -# echo "πŸ” Process using port 3333:" -# sudo netstat -tlnp | grep ":3333 " || echo "Could not determine process" -# echo "" -# echo "πŸ›‘ To kill existing process:" -# echo "sudo lsof -ti:3333 | xargs sudo kill -9" -# echo "" -# read -p "Kill existing process and continue? (y/N): " -n 1 -r -# echo -# if [[ $REPLY =~ ^[Yy]$ ]]; then -# echo "Killing processes using port 3333..." -# sudo lsof -ti:3333 | xargs sudo kill -9 2>/dev/null || echo "No processes to kill" -# sleep 2 -# else -# echo "Exiting..." -# exit 1 -# fi -# fi - -# echo "" -# echo "πŸš€ Starting Mining Pool Server..." -# echo "This will distribute block rewards among multiple miners" -# echo "" -# echo "Pool Features:" -# echo "- Multiple miner support" -# echo "- Share-based reward distribution" -# echo "- Pool fee: 1%" -# echo "- Real-time statistics" -# echo "- Web dashboard on port 8083" -# echo "" - -# echo "After it starts, miners can connect with:" -# echo "" -# echo "Option 1: Address as username" -# echo "./cpuminer -a rinhash -o stratum+tcp://YOUR_IP:3333 -u rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q -p x" -# echo "" -# echo "Option 2: Address.workername format" -# echo "./cpuminer -a rinhash -o stratum+tcp://YOUR_IP:3333 -u rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q.worker1 -p x" -# echo "" -# echo "Option 3: Traditional username (rewards to pool address)" -# echo "./cpuminer -a rinhash -o stratum+tcp://YOUR_IP:3333 -u username.workername -p x" -# echo "" -# echo "🌐 Web Dashboard: http://YOUR_IP:8083" -# echo "πŸ“Š View real-time pool statistics, miners, and blocks" -# echo "" -# echo "Press Ctrl+C to stop the pool" - -# # Start the mining pool -# python3 MINE/rin/stratum_pool.py diff --git a/MINE/rin/start_stratum_proxy.sh b/MINE/rin/start_stratum_proxy.sh deleted file mode 100644 index 1e317f1..0000000 --- a/MINE/rin/start_stratum_proxy.sh +++ /dev/null @@ -1,68 +0,0 @@ -# #!/bin/bash - -# # Start RinCoin Stratum Proxy Server -# # Bridges cpuminer-opt-rin to RinCoin node - -# echo "=== RinCoin Stratum Proxy Server ===" -# echo "" - -# # Check if RinCoin node is running -# if ! sudo docker ps | grep -q "rincoin-node"; then -# echo "❌ Error: rincoin-node container is not running!" -# echo "Please start it first:" -# echo "sudo docker start rincoin-node" -# exit 1 -# fi - -# echo "βœ… RinCoin node is running" - -# # Check if Python3 and requests are available -# if ! command -v python3 &> /dev/null; then -# echo "❌ Error: python3 is not installed!" -# echo "Please install it: sudo apt-get install python3" -# exit 1 -# fi - -# # Install requests if not available -# python3 -c "import requests" 2>/dev/null || { -# echo "Installing python3-requests..." -# sudo apt-get update && sudo apt-get install -y python3-requests -# } - -# echo "βœ… Python dependencies ready" - -# # Check if port 3334 is already in use -# if netstat -tln | grep -q ":3334 "; then -# echo "" -# echo "⚠️ Port 3334 is already in use!" -# echo "" -# echo "πŸ” Process using port 3334:" -# sudo netstat -tlnp | grep ":3334 " || echo "Could not determine process" -# echo "" -# echo "πŸ›‘ To kill existing process:" -# echo "sudo lsof -ti:3334 | xargs sudo kill -9" -# echo "" -# read -p "Kill existing process and continue? (y/N): " -n 1 -r -# echo -# if [[ $REPLY =~ ^[Yy]$ ]]; then -# echo "Killing processes using port 3334..." -# sudo lsof -ti:3334 | xargs sudo kill -9 2>/dev/null || echo "No processes to kill" -# sleep 2 -# else -# echo "Exiting..." -# exit 1 -# fi -# fi - -# echo "" -# echo "πŸš€ Starting Stratum Proxy Server..." -# echo "" -# echo "After it starts, connect your miner with:" -# echo "sudo docker exec -it amd-strix-halo-llama-rocm bash -c \"/mnt/dl/rinhash/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://127.0.0.1:3334 -u user -p pass -t 28\"" -# echo "" -# echo "Press Ctrl+C to stop the proxy" -# echo "" - -# # Start the proxy -# cd "$(dirname "$0")" -# python3 stratum_proxy.py --submit-all-blocks diff --git a/MINE/rin/stratum_pool.py b/MINE/rin/stratum_pool.py deleted file mode 100644 index 5ef3e8a..0000000 --- a/MINE/rin/stratum_pool.py +++ /dev/null @@ -1,602 +0,0 @@ -# #!/usr/bin/env python3 -# """ -# RinCoin Mining Pool Server -# Distributes block rewards among multiple miners based on share contributions -# """ - -# import socket -# import threading -# import json -# import time -# import requests -# import hashlib -# import struct -# import sqlite3 -# from datetime import datetime -# from requests.auth import HTTPBasicAuth - -# # Import web interface -# from pool_web_interface import start_web_interface - -# # Import stratum base class -# from stratum_proxy import RinCoinStratumBase - -# class RinCoinMiningPool(RinCoinStratumBase): -# def __init__(self, stratum_host='0.0.0.0', stratum_port=3333, -# rpc_host='127.0.0.1', rpc_port=9556, -# rpc_user='rinrpc', rpc_password='745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90', -# pool_address='rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q', -# pool_fee_percent=1.0): - -# # Initialize base class -# super().__init__(stratum_host, stratum_port, rpc_host, rpc_port, rpc_user, rpc_password, pool_address) - -# self.pool_address = pool_address -# self.pool_fee_percent = pool_fee_percent - -# # Pool statistics -# self.total_shares = 0 -# self.total_blocks = 0 -# self.pool_hashrate = 0 - -# # Database for persistent storage -# self.init_database() - -# print(f"=== RinCoin Mining Pool Server ===") -# print(f"Stratum: {stratum_host}:{stratum_port}") -# print(f"RPC: {rpc_host}:{rpc_port}") -# print(f"Pool Address: {pool_address}") -# print(f"Pool Fee: {pool_fee_percent}%") - -# def init_database(self): -# """Initialize SQLite database for miner tracking""" -# self.db = sqlite3.connect(':memory:', check_same_thread=False) -# cursor = self.db.cursor() - -# # Create tables -# cursor.execute(''' -# CREATE TABLE IF NOT EXISTS miners ( -# id INTEGER PRIMARY KEY, -# user TEXT NOT NULL, -# worker TEXT NOT NULL, -# address TEXT, -# shares INTEGER DEFAULT 0, -# last_share TIMESTAMP, -# last_hashrate REAL DEFAULT 0, -# created TIMESTAMP DEFAULT CURRENT_TIMESTAMP -# ) -# ''') - -# cursor.execute(''' -# CREATE TABLE IF NOT EXISTS shares ( -# id INTEGER PRIMARY KEY, -# miner_id INTEGER, -# job_id TEXT, -# difficulty REAL, -# submitted TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -# FOREIGN KEY (miner_id) REFERENCES miners (id) -# ) -# ''') - -# cursor.execute(''' -# CREATE TABLE IF NOT EXISTS blocks ( -# id INTEGER PRIMARY KEY, -# block_hash TEXT, -# height INTEGER, -# reward REAL, -# pool_fee REAL, -# miner_rewards TEXT, -- JSON of {address: amount} -# found_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -# ) -# ''') - -# # Samples for pool hashrate chart -# cursor.execute(''' -# CREATE TABLE IF NOT EXISTS hashrate_samples ( -# id INTEGER PRIMARY KEY, -# ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -# hashrate REAL -# ) -# ''') - -# self.db.commit() - -# def get_pool_block_template(self): -# """Get new block template and create pool-style job""" -# template = super().get_block_template() -# if template: -# # Convert to pool-style job format if needed -# job = self.current_job -# if job: -# # Add pool-specific fields -# job["coinb1"] = "01000000" + "0" * 60 -# job["coinb2"] = "ffffffff" -# job["merkle_branch"] = [] -# job["clean_jobs"] = True -# return job -# return None - -# def validate_rincoin_address(self, address): -# """Validate if an address is a valid RinCoin address""" -# try: -# return self.decode_bech32_address(address) is not None -# except: -# return False - -# def register_miner(self, user, worker, address=None): -# """Register or update miner in database""" -# cursor = self.db.cursor() - -# # Check if miner exists -# cursor.execute('SELECT id, address FROM miners WHERE user = ? AND worker = ?', (user, worker)) -# result = cursor.fetchone() - -# if result: -# miner_id, existing_address = result -# if address and not existing_address: -# cursor.execute('UPDATE miners SET address = ? WHERE id = ?', (address, miner_id)) -# self.db.commit() -# return miner_id -# else: -# # Create new miner -# cursor.execute('INSERT INTO miners (user, worker, address) VALUES (?, ?, ?)', (user, worker, address)) -# self.db.commit() -# return cursor.lastrowid - -# def record_share(self, miner_id, job_id, difficulty): -# """Record a share submission""" -# cursor = self.db.cursor() - -# # Record share -# cursor.execute('INSERT INTO shares (miner_id, job_id, difficulty) VALUES (?, ?, ?)', -# (miner_id, job_id, difficulty)) - -# # Update miner stats -# cursor.execute('UPDATE miners SET shares = shares + 1, last_share = CURRENT_TIMESTAMP WHERE id = ?', (miner_id,)) - -# self.db.commit() -# self.total_shares += 1 - -# def distribute_block_reward(self, block_hash, block_height, total_reward): -# """Distribute block reward among miners based on their shares""" -# cursor = self.db.cursor() - -# # Calculate pool fee -# pool_fee = total_reward * (self.pool_fee_percent / 100.0) -# miner_reward = total_reward - pool_fee - -# # Get shares from last 24 hours -# cursor.execute(''' -# SELECT m.address, COUNT(s.id) as share_count, SUM(s.difficulty) as total_difficulty -# FROM miners m -# JOIN shares s ON m.id = s.miner_id -# WHERE s.submitted > datetime('now', '-1 day') -# GROUP BY m.id, m.address -# HAVING share_count > 0 -# ''') - -# miners = cursor.fetchall() - -# if not miners: -# print("No miners with shares in last 24 hours") -# return - -# # 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 = {} - -# # 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) -# VALUES (?, ?, ?, ?, ?) -# ''', (block_hash, block_height, total_reward, pool_fee, json.dumps(miner_rewards))) - -# self.db.commit() -# self.total_blocks += 1 - -# 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)") - -# # Use inherited send_stratum_response and send_stratum_notification from base class - -# def handle_stratum_message(self, client, addr, message): -# """Handle incoming Stratum message from miner""" -# try: -# data = json.loads(message.strip()) -# method = data.get("method") -# msg_id = data.get("id") -# params = data.get("params", []) - -# print(f"[{addr}] {method}: {params}") - -# if method == "mining.subscribe": -# # Subscribe response -# self.send_stratum_response(client, msg_id, [ -# [["mining.set_difficulty", "subscription_id"], ["mining.notify", "subscription_id"]], -# "extranonce1", -# 4 -# ]) - -# # Send difficulty (lower for CPU mining) -# self.send_stratum_notification(client, "mining.set_difficulty", [0.0001]) - -# # Send initial job -# if self.get_pool_block_template(): -# job = self.current_job -# self.send_stratum_notification(client, "mining.notify", [ -# job["job_id"], -# job["prevhash"], -# job["coinb1"], -# job["coinb2"], -# job["merkle_branch"], -# f"{job['version']:08x}", -# job["bits"], -# job["ntime"], -# job["clean_jobs"] -# ]) - -# elif method == "mining.extranonce.subscribe": -# # Handle extranonce subscription -# print(f"[{addr}] Extranonce subscription requested") -# self.send_stratum_response(client, msg_id, True) - -# elif method == "mining.authorize": -# # Parse user.worker format -# if len(params) >= 2: -# user_worker = params[0] -# password = params[1] if len(params) > 1 else "" - -# # Extract user and worker -# if '.' in user_worker: -# user, worker = user_worker.split('.', 1) -# else: -# user = user_worker -# worker = "default" - -# # Check if user contains a RinCoin address (starts with 'rin') -# miner_address = None -# if user.startswith('rin'): -# # User is a RinCoin address -# if self.validate_rincoin_address(user): -# miner_address = user -# user = f"miner_{miner_address[:8]}" # Create a user ID from address -# print(f"[{addr}] βœ… Miner using valid RinCoin address: {miner_address}") -# else: -# print(f"[{addr}] ❌ Invalid RinCoin address: {user}") -# self.send_stratum_response(client, msg_id, False, "Invalid RinCoin address") -# return -# elif '.' in user and user.split('.')[0].startswith('rin'): -# # Format: rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q.workername -# address_part, worker_part = user.split('.', 1) -# if address_part.startswith('rin'): -# if self.validate_rincoin_address(address_part): -# miner_address = address_part -# user = f"miner_{miner_address[:8]}" -# worker = worker_part -# print(f"[{addr}] βœ… Miner using valid RinCoin address format: {miner_address}.{worker}") -# else: -# print(f"[{addr}] ❌ Invalid RinCoin address: {address_part}") -# self.send_stratum_response(client, msg_id, False, "Invalid RinCoin address") -# return - -# # Register miner with address -# miner_id = self.register_miner(user, worker, miner_address) - -# # Store client info -# self.clients[addr] = { -# 'client': client, -# 'user': user, -# 'worker': worker, -# 'miner_id': miner_id, -# 'address': miner_address, -# 'shares': 0, -# 'last_share': time.time(), -# 'extranonce1': '00000000' # Default extranonce1 -# } - -# if miner_address: -# print(f"[{addr}] βœ… Authorized: {user}.{worker} -> {miner_address}") -# else: -# 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") - -# elif method == "mining.submit": -# # Submit share -# if addr not in self.clients: -# self.send_stratum_response(client, msg_id, False, "Not authorized") -# return - -# miner_info = self.clients[addr] - -# try: -# if self.current_job and len(params) >= 5: -# username = params[0] -# job_id = params[1] -# extranonce2 = params[2] -# ntime = params[3] -# nonce = params[4] - -# # Use base class to validate and submit share -# extranonce1 = miner_info.get('extranonce1', '00000000') -# miner_address = miner_info.get('address') - -# # For pool mining, always mine to pool address -# success, message = self.submit_share( -# self.current_job, extranonce1, extranonce2, ntime, nonce, -# target_address=self.pool_address -# ) - -# if success: -# # Record share with estimated difficulty -# actual_difficulty = 0.00133 # Estimated for ~381 kH/s -# self.record_share(miner_info['miner_id'], job_id, actual_difficulty) - -# # Update miner stats -# now_ts = time.time() -# prev_ts = miner_info.get('last_share') or now_ts -# dt = max(now_ts - prev_ts, 1e-3) -# miner_hashrate = actual_difficulty * (2**32) / dt - -# if miner_info['shares'] == 0: -# miner_hashrate = 381000 # Default estimate -# miner_info['shares'] += 1 -# miner_info['last_share'] = now_ts - -# # Update database -# try: -# cursor = self.db.cursor() -# cursor.execute('UPDATE miners SET last_share = CURRENT_TIMESTAMP, last_hashrate = ? WHERE id = ?', -# (miner_hashrate, miner_info['miner_id'])) -# self.db.commit() -# except Exception as e: -# print(f"DB update error: {e}") - -# print(f"[{addr}] βœ… Share accepted from {miner_info['user']}.{miner_info['worker']} (Total: {miner_info['shares']})") -# self.send_stratum_response(client, msg_id, True) - -# # If block was found, distribute rewards -# if "Block found" in message: -# print(f"πŸŽ‰ [{addr}] BLOCK FOUND!") -# # Get block info and distribute rewards -# total_reward = self.current_job['coinbasevalue'] / 100000000 if self.current_job else 25.0 -# self.distribute_block_reward("pending", self.current_job['height'] if self.current_job else 0, total_reward) -# else: -# # Accept as share for pool statistics even if block validation fails -# self.send_stratum_response(client, msg_id, True) -# else: -# print(f"[{addr}] Invalid share parameters") -# self.send_stratum_response(client, msg_id, False, "Invalid parameters") - -# except Exception as e: -# print(f"[{addr}] Share processing error: {e}") -# # Still accept the share for mining statistics -# self.send_stratum_response(client, msg_id, True) - -# else: -# print(f"[{addr}] ⚠️ Unknown method: {method}") -# # Send null result for unknown methods (standard Stratum behavior) -# self.send_stratum_response(client, msg_id, None, None) - -# except json.JSONDecodeError: -# print(f"[{addr}] Invalid JSON: {message}") -# except Exception as e: -# print(f"[{addr}] Message handling error: {e}") - -# def handle_client(self, client, addr): -# """Handle individual client connection""" -# print(f"[{addr}] Connected") - -# try: -# while self.running: -# data = client.recv(4096) -# if not data: -# break - -# # Handle multiple messages in one packet -# messages = data.decode('utf-8').strip().split('\n') -# for message in messages: -# if message: -# self.handle_stratum_message(client, addr, message) - -# except Exception as e: -# print(f"[{addr}] Client error: {e}") -# finally: -# client.close() -# if addr in self.clients: -# del self.clients[addr] -# print(f"[{addr}] Disconnected") - -# def job_updater(self): -# """Periodically update mining jobs""" -# last_job_time = 0 -# last_block_height = 0 - -# while self.running: -# try: -# # Check for new blocks every 10 seconds -# time.sleep(10) - -# # Get current blockchain info -# blockchain_info = self.rpc_call("getblockchaininfo") -# if blockchain_info: -# current_height = blockchain_info.get('blocks', 0) - -# # Create new job if: -# # 1. New block detected -# # 2. 30+ seconds since last job -# # 3. No current job exists -# should_create_job = ( -# current_height != last_block_height or -# time.time() - last_job_time > 30 or -# not self.current_job -# ) - -# if should_create_job: -# if self.get_pool_block_template(): -# job = self.current_job -# last_job_time = time.time() -# last_block_height = current_height - -# print(f"πŸ“¦ New job created: {job['job_id']} (block {current_height})") - -# # Send to all connected clients -# for addr, miner_info in list(self.clients.items()): -# try: -# self.send_stratum_notification(miner_info['client'], "mining.notify", [ -# job["job_id"], -# job["prevhash"], -# job["coinb1"], -# job["coinb2"], -# job["merkle_branch"], -# f"{job['version']:08x}", -# job["bits"], -# job["ntime"], -# job["clean_jobs"] -# ]) -# except Exception as e: -# print(f"Failed to send job to {addr}: {e}") - -# except Exception as e: -# print(f"Job updater error: {e}") - -# def stats_updater(self): -# """Periodically update pool statistics""" -# while self.running: -# try: -# time.sleep(60) # Update every minute -# cursor = self.db.cursor() -# # Pool hashrate is the sum of miners' last hashrates -# cursor.execute('SELECT COALESCE(SUM(last_hashrate), 0) FROM miners') -# self.pool_hashrate = cursor.fetchone()[0] or 0.0 -# # Sample for chart -# cursor.execute('INSERT INTO hashrate_samples (hashrate) VALUES (?)', (self.pool_hashrate,)) -# self.db.commit() -# print(f"πŸ“Š Pool Stats: {len(self.clients)} miners, {self.total_shares} shares, {self.pool_hashrate/1000:.2f} kH/s") - -# except Exception as e: -# print(f"Stats updater error: {e}") - -# def start(self): -# """Start the mining pool server""" -# try: -# # Test RPC connection -# blockchain_info = self.rpc_call("getblockchaininfo") -# if not blockchain_info: -# print("❌ Failed to connect to RinCoin node!") -# return - -# print(f"βœ… Connected to RinCoin node (block {blockchain_info.get('blocks', 'unknown')})") - -# # Start background threads -# job_thread = threading.Thread(target=self.job_updater, daemon=True) -# job_thread.start() - -# stats_thread = threading.Thread(target=self.stats_updater, daemon=True) -# stats_thread.start() - -# # Start web interface in background -# web_thread = threading.Thread(target=start_web_interface, -# args=(self.db, '0.0.0.0', 8083, -# self.rpc_host, self.rpc_port, -# self.rpc_user, self.rpc_password), -# daemon=True) -# web_thread.start() - -# print(f"🌐 Web dashboard started on http://0.0.0.0:8083") - -# # Start Stratum server -# server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -# server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) -# server_socket.bind((self.stratum_host, self.stratum_port)) -# server_socket.listen(10) - -# print(f"πŸš€ Mining pool listening on {self.stratum_host}:{self.stratum_port}") -# print("Ready for multiple miners...") -# print("") -# print(f"πŸ’° Pool address: {self.pool_address}") -# print(f"πŸ’° Pool fee: {self.pool_fee_percent}%") -# print("") -# print("Connect miners with:") -# print(f"./cpuminer -a rinhash -o stratum+tcp://{self.stratum_host}:{self.stratum_port} -u username.workername -p x") -# print("") - -# while self.running: -# try: -# client, addr = server_socket.accept() -# client_thread = threading.Thread(target=self.handle_client, args=(client, addr), daemon=True) -# client_thread.start() -# except KeyboardInterrupt: -# print("\nπŸ›‘ Shutting down pool...") -# self.running = False -# break -# except Exception as e: -# print(f"Server error: {e}") - -# except OSError as e: -# if "Address already in use" in str(e): -# print(f"❌ Port {self.stratum_port} is already in use!") -# print("") -# print("πŸ” Check what's using the port:") -# print(f"sudo netstat -tlnp | grep :{self.stratum_port}") -# print("") -# print("πŸ›‘ Kill existing process:") -# print(f"sudo lsof -ti:{self.stratum_port} | xargs sudo kill -9") -# print("") -# print("πŸ”„ Or use a different port by editing the script") -# else: -# print(f"Failed to start server: {e}") -# except Exception as e: -# print(f"Failed to start server: {e}") -# finally: -# print("Pool server stopped") - -# if __name__ == "__main__": -# pool = RinCoinMiningPool() -# pool.start() diff --git a/MINE/rin/stratum_proxy.py b/MINE/rin/stratum_proxy.py deleted file mode 100644 index 3833e9d..0000000 --- a/MINE/rin/stratum_proxy.py +++ /dev/null @@ -1,1350 +0,0 @@ -# #!/usr/bin/env python3 -# """ -# stratum_proxy.py -# RinCoin Stratum Proxy Server -# DEBUG RPC: we get node logs with 'docker logs --tail=200 rincoin-node' -# MINE: /mnt/shared/DEV/repos/d-popov.com/mines/rin/miner/cpuminer-opt-rin/cpuminer -a rinhash -o stratum+tcp://localhost:3334 -u x -p x -t 32 -# """ - -# import socket -# import threading -# import json -# import time -# import requests -# import hashlib -# import struct -# from requests.auth import HTTPBasicAuth - -# class RinCoinStratumProxy: -# def __init__(self, stratum_host='0.0.0.0', stratum_port=3334, -# rpc_host='127.0.0.1', rpc_port=9556, -# rpc_user='rinrpc', rpc_password='745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90', -# target_address='rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q', -# submit_all_blocks=False, submit_threshold=0.1): - -# self.stratum_host = stratum_host -# self.stratum_port = stratum_port -# self.rpc_host = rpc_host -# self.rpc_port = rpc_port -# self.rpc_user = rpc_user -# self.rpc_password = rpc_password -# self.target_address = target_address -# self.submit_all_blocks = submit_all_blocks -# # For debugging: submit blocks that meet this fraction of network difficulty -# self.submit_threshold = submit_threshold # Configurable percentage of network difficulty - -# self.clients = {} -# self.job_counter = 0 -# self.current_job = None -# 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 = 15 # Target: 1 share every 15 seconds (optimal for 1-min blocks) - -# # Production monitoring -# self.stats = { -# 'start_time': time.time(), -# 'total_shares': 0, -# 'accepted_shares': 0, -# 'rejected_shares': 0, -# 'blocks_found': 0, -# 'total_hashrate': 0, -# 'connections': 0, -# 'last_share_time': time.time(), -# 'shares_last_minute': [], -# 'current_share_rate': 0.0 -# } -# self.max_connections = 50 # Production limit - -# # Logging setup -# self.log_file = "mining_log.txt" -# self.init_log_file() - -# print(f"RinCoin Stratum Proxy Server") -# print(f"Stratum: {stratum_host}:{stratum_port}") -# print(f"RPC: {rpc_host}:{rpc_port}") -# print(f"Target: {target_address}") - -# def init_log_file(self): -# """Initialize mining log file with header""" -# try: -# with open(self.log_file, 'w') as f: -# f.write("=" * 80 + "\n") -# f.write("RinCoin Mining Log\n") -# f.write("=" * 80 + "\n") -# f.write(f"Started: {time.strftime('%Y-%m-%d %H:%M:%S')}\n") -# f.write(f"Target Address: {self.target_address}\n") -# f.write(f"Stratum: {self.stratum_host}:{self.stratum_port}\n") -# f.write(f"RPC: {self.rpc_host}:{self.rpc_port}\n") -# f.write("=" * 80 + "\n\n") -# except Exception as e: -# print(f"Failed to initialize log file: {e}") - -# def log_hash_found(self, hash_hex, difficulty, height, reward, nonce, ntime): -# """Log found hash to file""" -# try: -# timestamp = time.strftime('%Y-%m-%d %H:%M:%S') -# with open(self.log_file, 'a') as f: -# f.write(f"[{timestamp}] πŸŽ‰ HASH FOUND!\n") -# f.write(f" Hash: {hash_hex}\n") -# f.write(f" Difficulty: {difficulty:.6f}\n") -# f.write(f" Height: {height}\n") -# f.write(f" Reward: {reward:.8f} RIN\n") -# f.write(f" Nonce: {nonce}\n") -# f.write(f" Time: {ntime}\n") -# f.write("-" * 40 + "\n") -# except Exception as e: -# print(f"Failed to log hash: {e}") - -# def log_wallet_balance(self): -# """Log current wallet balance to file""" -# try: -# balance = self.rpc_call("getbalance") -# if balance is not None: -# timestamp = time.strftime('%Y-%m-%d %H:%M:%S') -# with open(self.log_file, 'a') as f: -# f.write(f"[{timestamp}] πŸ’° Wallet Balance: {balance:.8f} RIN\n") -# except Exception as e: -# print(f"Failed to log wallet balance: {e}") - -# def rpc_call(self, method, params=[]): -# """Make RPC call to RinCoin node""" -# try: -# url = f"http://{self.rpc_host}:{self.rpc_port}/" -# headers = {'content-type': 'text/plain'} -# auth = HTTPBasicAuth(self.rpc_user, self.rpc_password) - -# payload = { -# "jsonrpc": "1.0", -# "id": "stratum_proxy", -# "method": method, -# "params": params -# } - -# response = requests.post(url, json=payload, headers=headers, auth=auth, timeout=30) - -# if response.status_code == 200: -# result = response.json() -# if 'error' in result and result['error'] is not None: -# print(f"RPC Error: {result['error']}") -# return None -# return result.get('result') -# else: -# print(f"HTTP Error: {response.status_code}") -# return None - -# except Exception as e: -# print(f"RPC Call Error: {e}") -# return None - -# def encode_varint(self, n): -# """Encode integer as Bitcoin-style varint""" -# if n < 0xfd: -# return bytes([n]) -# elif n <= 0xffff: -# return b"\xfd" + struct.pack(' bytes: -# outputs_blob = b'' -# outputs_list = [] -# # Main output -# outputs_list.append(struct.pack(' 1: -# if len(hashes) % 2 == 1: -# hashes.append(hashes[-1]) # Duplicate last hash if odd - -# next_level = [] -# for i in range(0, len(hashes), 2): -# combined = hashes[i] + hashes[i + 1] -# next_level.append(hashlib.sha256(hashlib.sha256(combined).digest()).digest()) - -# hashes = next_level - -# return hashes[0] if hashes else b'\x00' * 32 - -# except Exception as e: -# print(f"Merkle root calculation error: {e}") -# return b'\x00' * 32 - -# def calculate_merkle_branches(self, tx_hashes, tx_index): -# """Calculate merkle branches for a specific transaction index""" -# try: -# if not tx_hashes or tx_index >= len(tx_hashes): -# return [] - -# branches = [] -# current_index = tx_index - -# # Start with the full list of transaction hashes -# hashes = tx_hashes[:] - -# while len(hashes) > 1: -# if len(hashes) % 2 == 1: -# hashes.append(hashes[-1]) # Duplicate last hash if odd - -# # Find the partner for current_index -# partner_index = current_index ^ 1 # Flip the least significant bit - -# if partner_index < len(hashes): -# # Add the partner hash to branches (in big-endian for stratum) -# branches.append(hashes[partner_index][::-1].hex()) -# else: -# # This shouldn't happen, but add the duplicate if it does -# branches.append(hashes[current_index][::-1].hex()) - -# # Move to next level -# next_level = [] -# for i in range(0, len(hashes), 2): -# combined = hashes[i] + hashes[i + 1] -# next_level.append(hashlib.sha256(hashlib.sha256(combined).digest()).digest()) - -# hashes = next_level -# current_index //= 2 - -# return branches - -# except Exception as e: -# print(f"Merkle branches calculation error: {e}") -# return [] - -# def bits_to_target(self, bits_hex): -# """Convert bits to target - FIXED VERSION""" -# try: -# bits = int(bits_hex, 16) -# exponent = bits >> 24 -# mantissa = bits & 0xffffff - -# # Bitcoin target calculation -# if exponent <= 3: -# target = mantissa >> (8 * (3 - exponent)) -# else: -# target = mantissa << (8 * (exponent - 3)) - -# return f"{target:064x}" -# except Exception as e: -# print(f"Bits to target error: {e}") -# return "0000ffff00000000000000000000000000000000000000000000000000000000" - -# def get_block_template(self): -# """Get new block template and create Stratum job""" -# try: -# template = self.rpc_call("getblocktemplate", [{"rules": ["segwit", "mweb"]}]) -# if not template: -# return None - -# self.job_counter += 1 - -# job = { -# "job_id": f"job_{self.job_counter:08x}", -# "template": template, -# "prevhash": template.get("previousblockhash", "0" * 64), -# "version": template.get('version', 1), -# "bits": template.get('bits', '1d00ffff'), -# "ntime": f"{int(time.time()):08x}", -# "target": self.bits_to_target(template.get('bits', '1d00ffff')), -# "height": template.get('height', 0), -# "coinbasevalue": template.get('coinbasevalue', 0), -# "transactions": template.get('transactions', []) -# } - -# self.current_job = job -# timestamp = time.strftime("%Y-%m-%d %H:%M:%S") -# network_difficulty = self.calculate_network_difficulty(job['target']) -# print(f"[{timestamp}] πŸ†• NEW JOB: {job['job_id']} | Height: {job['height']} | Reward: {job['coinbasevalue']/100000000:.2f} RIN") -# print(f" 🎯 Network Difficulty: {network_difficulty:.6f} | Bits: {job['bits']}") -# print(f" πŸ“ Target: {job['target'][:16]}... | Transactions: {len(job['transactions'])}") -# return job - -# except Exception as e: -# print(f"Get block template error: {e}") -# return None - -# def calculate_share_difficulty(self, hash_hex, target_hex): -# """Calculate actual share difficulty from hash - FIXED""" -# try: -# hash_int = int(hash_hex, 16) - -# if hash_int == 0: -# return float('inf') # Perfect hash - -# # Bitcoin-style difficulty calculation using difficulty 1 target -# # Difficulty 1 target for mainnet -# diff1_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000 - -# # Share difficulty = how much harder this hash was compared to diff 1 -# difficulty = diff1_target / hash_int - -# return difficulty -# except Exception as e: -# print(f"Difficulty calculation error: {e}") -# return 0.0 - -# def calculate_network_difficulty(self, target_hex): -# """Calculate network difficulty from target - FIXED""" -# try: -# target_int = int(target_hex, 16) - -# # Bitcoin difficulty 1.0 target -# diff1_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000 - -# # Network difficulty = how much harder than difficulty 1.0 -# network_difficulty = diff1_target / target_int - -# return network_difficulty -# except Exception as e: -# 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: -# # Calculate difficulty for 4 shares per minute (15 second intervals) -# # Formula: difficulty = (shares_per_second * 2^32) / hashrate -# target_shares_per_second = 4 / 60 # 4 shares per minute -# assumed_hashrate = 680000 # H/s (conservative estimate) -# calculated_difficulty = (target_shares_per_second * (2**32)) / assumed_hashrate - -# # Scale based on network difficulty to maintain relative percentage -# target_percentage = calculated_difficulty / network_diff if network_diff > 0 else 0.32 -# scaled_difficulty = network_diff * target_percentage - -# # Use the calculated difficulty (should be around 421 for 680kH/s) -# initial_difficulty = calculated_difficulty - -# # Ensure reasonable bounds -# min_difficulty = 0.0001 # Absolute minimum -# # IMPORTANT: DO NOT CHANGE THIS VALUE. our pool may grow big in the future, so we need to be able to handle it. -# max_difficulty = network_diff * 0.1 # Maximum 10% of network -# initial_difficulty = max(min_difficulty, min(max_difficulty, initial_difficulty)) - -# percentage = (initial_difficulty / network_diff) * 100 -# print(f" πŸ“Š NEW CLIENT {addr}: Network diff {network_diff:.6f}") -# print(f" 🎯 Starting difficulty: {initial_difficulty:.6f} ({percentage:.4f}% of network)") -# miner_hashrate = self.clients.get(addr, {}).get('estimated_hashrate', 0) -# if miner_hashrate > 0: -# print(f" Target: 1 share every {self.target_share_interval}s @ {miner_hashrate:.0f} H/s") -# else: -# print(f" Target: 1 share every {self.target_share_interval}s (miner hashrate unknown)") -# print(f" πŸ”§ Per-miner adjustment: Difficulty will adapt to each device's actual hashrate") -# return initial_difficulty - -# # 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) - -# 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', network_diff * 0.005) -# estimated_hashrate = client_data.get('estimated_hashrate', 0) - -# # Need at least 3 shares to make adjustments -# if share_count < 3: -# return current_difficulty - -# # Calculate target difficulty based on hashrate and desired share interval -# # Target: 1 share every 15 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) - -# # 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)) - -# # 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}: {estimated_hashrate:.0f} H/s, {share_count} shares, 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_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""" -# 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: -# # Use provided address or default -# address = target_address or self.target_address - -# # Build coinbase (with and without witness) -# coinbase_wit, coinbase_nowit = self.build_coinbase_transaction_for_address( -# job['template'], extranonce1, extranonce2, address) -# if not coinbase_wit or not coinbase_nowit: -# return False, "Coinbase construction failed" - -# # Calculate coinbase txid (non-witness serialization) -# coinbase_txid = hashlib.sha256(hashlib.sha256(coinbase_nowit).digest()).digest()[::-1] - -# # Calculate merkle root -# merkle_root = self.calculate_merkle_root(coinbase_txid, job['transactions']) - -# # Build block header - FIXED ENDIANNESS -# header = b'' -# header += struct.pack('= 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 -# stratum_percentage = (share_difficulty / client_stratum_diff) * 100 if client_stratum_diff > 0 else 0 - -# # Progress indicator based on difficulty comparison -# if meets_network_difficulty: -# progress_icon = "πŸŽ‰" # Block found! -# elif meets_stratum_difficulty: -# progress_icon = "βœ…" # Valid share for stratum -# elif network_percentage >= 50: -# progress_icon = "πŸ”₯" # Very close to network -# elif network_percentage >= 10: -# progress_icon = "⚑" # Getting warm -# elif network_percentage >= 1: -# progress_icon = "πŸ’«" # Some progress -# else: -# progress_icon = "πŸ“Š" # Low progress - -# # Calculate network and pool hashrates -# block_time = 60 # RinCoin 1-minute blocks -# network_hashrate = (network_difficulty * (2**32)) / block_time -# network_mhs = network_hashrate / 1e6 - -# # Calculate pool hashrate (sum of all connected miners) -# pool_hashrate = 0 -# for client_addr, client_data in self.clients.items(): -# pool_hashrate += client_data.get('estimated_hashrate', 0) -# pool_mhs = pool_hashrate / 1e6 - -# # Calculate percentages -# pool_network_percentage = (pool_mhs / network_mhs) * 100 if network_mhs > 0 else 0 -# miner_pool_percentage = (0.87 / pool_mhs) * 100 if pool_mhs > 0 else 0 # Assuming 870kH/s miner - -# 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" 🌐 Network: {network_mhs:.1f} MH/s | Pool: {pool_mhs:.1f} MH/s ({pool_network_percentage:.2f}% of network)") -# print(f" ⛏️ Miner: 0.87 MH/s ({miner_pool_percentage:.1f}% of pool) | Expected solo: {network_mhs/0.87:.0f}h") -# 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 '❌'}") -# print(f" πŸ” Difficulty Check: Share {share_difficulty:.2e} vs Network {network_difficulty:.6f} = {'βœ…' if meets_network_difficulty else '❌'}") - -# # Initialize submission variables -# submit_network_difficulty = meets_network_difficulty -# submit_debug_threshold = share_difficulty >= (network_difficulty * self.submit_threshold) - -# if submit_network_difficulty: -# submit_reason = "meets network difficulty" -# elif submit_debug_threshold: -# submit_reason = f"meets debug threshold ({self.submit_threshold*100:.0f}% of network)" -# else: -# submit_reason = "does not meet minimum requirements" - -# # Handle submit_all_blocks mode - bypass all difficulty checks -# if self.submit_all_blocks: -# print(f" πŸ§ͺ TEST MODE: Submitting ALL shares to node for validation") -# # Update stats for test mode -# self.stats['total_shares'] += 1 -# self.stats['accepted_shares'] += 1 - -# # Always submit in test mode -# should_submit = True -# else: -# # Normal mode - check stratum difficulty properly -# if not meets_stratum_difficulty: -# # Share doesn't meet minimum stratum difficulty - reject -# print(f" ❌ Share rejected (difficulty too low: {share_difficulty:.2e} < {client_stratum_diff:.6f})") -# self.stats['total_shares'] += 1 -# self.stats['rejected_shares'] += 1 -# return False, "Share does not meet stratum difficulty" - -# # 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'] = 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 -# self.stats['accepted_shares'] += 1 - -# # Check if we should adjust difficulty -# self.adjust_client_difficulty(addr) - -# # Global difficulty adjustment based on share rate -# self.adjust_global_difficulty_if_needed() - -# should_submit = submit_network_difficulty or submit_debug_threshold - -# # Submit block if conditions are met -# if should_submit: -# if submit_network_difficulty: -# print(f" πŸŽ‰ VALID BLOCK FOUND! Hash: {block_hash_hex}") -# print(f" πŸ’° Reward: {job['coinbasevalue']/100000000:.2f} RIN -> {address}") -# print(f" πŸ“Š Block height: {job['height']}") -# print(f" πŸ” Difficulty: {share_difficulty:.6f} (target: {network_difficulty:.6f})") -# print(f" πŸ“‹ Submit reason: {submit_reason}") - -# # Log the found hash - ONLY for actual network-valid blocks -# reward_rin = job['coinbasevalue'] / 100000000 -# self.log_hash_found(block_hash_hex, share_difficulty, job['height'], reward_rin, nonce, ntime) -# elif submit_debug_threshold: -# print(f" πŸ§ͺ DEBUG SUBMISSION! Hash: {block_hash_hex} ({submit_reason})") -# print(f" πŸ“Š Block height: {job['height']} | Difficulty: {share_difficulty:.6f}") -# print(f" πŸ’‘ This is a test submission - not a real block") -# else: -# print(f" πŸ§ͺ TEST BLOCK SUBMISSION! Hash: {block_hash_hex} (submit_all_blocks=True)") -# print(f" πŸ“Š Block height: {job['height']} | Difficulty: {share_difficulty:.6f}") -# print(f" πŸ’‘ This is a test submission - not a real block") - -# # Build complete block -# block = header - -# # Transaction count -# tx_count = 1 + len(job['transactions']) -# block += self.encode_varint(tx_count) - -# # Add coinbase transaction (witness variant for block body) -# block += coinbase_wit - -# # Add other transactions -# for tx in job['transactions']: -# block += bytes.fromhex(tx['data']) - -# # Submit block -# block_hex = block.hex() -# print(f" πŸ“¦ Submitting block of size {len(block_hex)//2} bytes...") -# print(f" πŸš€ Calling RPC: submitblock([block_hex={len(block_hex)//2}_bytes])") - -# result = self.rpc_call("submitblock", [block_hex]) -# print(f" πŸ“‘ RPC RESPONSE: {result}") # Log the actual RPC response - -# if result is None: -# print(f" βœ… Block accepted by network!") -# print(f" 🎊 SUCCESS: Block {job['height']} submitted successfully!") -# print(f" πŸ’° Reward earned: {job['coinbasevalue']/100000000:.8f} RIN") -# # Update block stats -# self.stats['blocks_found'] += 1 -# # Log wallet balance after successful block submission -# self.log_wallet_balance() -# return True, "Block found and submitted" -# else: -# print(f" ❌ Block rejected: {result}") -# print(f" πŸ” Debug: Block size {len(block_hex)//2} bytes, {len(job['transactions'])} transactions") -# print(f" πŸ“‹ Full RPC error details: {result}") -# return False, f"Block rejected: {result}" -# else: -# # Valid stratum share but not network-valid block (normal mode only) -# if not self.submit_all_blocks: -# print(f" βœ… Valid stratum share accepted") -# return True, "Valid stratum share" -# else: -# # This shouldn't happen in test mode since should_submit would be True -# return True, "Test mode share processed" - -# except Exception as e: -# print(f"Share submission error: {e}") -# return False, f"Submission error: {e}" - -# def send_stratum_response(self, client, msg_id, result, error=None): -# """Send Stratum response to client""" -# try: -# response = { -# "id": msg_id, -# "result": result, -# "error": error -# } -# message = json.dumps(response) + "\n" -# client.send(message.encode('utf-8')) -# except Exception as e: -# print(f"Send response error: {e}") - -# def send_stratum_notification(self, client, method, params): -# """Send Stratum notification to client""" -# try: -# notification = { -# "id": None, -# "method": method, -# "params": params -# } -# message = json.dumps(notification) + "\n" -# client.send(message.encode('utf-8')) -# except Exception as e: -# print(f"Send notification error: {e}") - -# def handle_stratum_message(self, client, addr, message): -# """Handle incoming Stratum message from miner""" -# try: -# # Debug: log raw message -# print(f"[{addr}] Raw message: {repr(message)}") - -# data = json.loads(message.strip()) -# method = data.get("method") -# msg_id = data.get("id") -# params = data.get("params", []) - -# print(f"[{addr}] Parsed: method={method}, id={msg_id}, params={params}") - -# if method == "mining.subscribe": -# # Generate unique extranonce1 for this connection -# self.extranonce1_counter += 1 -# extranonce1 = f"{self.extranonce1_counter:08x}" - -# # Store extranonce1 for this client -# if addr not in self.clients: -# self.clients[addr] = {} -# self.clients[addr]['extranonce1'] = extranonce1 - -# # Subscribe response -# self.send_stratum_response(client, msg_id, [ -# [["mining.set_difficulty", "subscription_id"], ["mining.notify", "subscription_id"]], -# extranonce1, -# 4 # extranonce2 size -# ]) - -# # 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'] = initial_difficulty -# 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}") - -# # Send initial job -# if self.current_job: -# self.send_job_to_client(client, self.current_job) -# else: -# if self.get_block_template(): -# self.send_job_to_client(client, self.current_job) - -# elif method == "mining.authorize": -# username = params[0] if params else "anonymous" -# self.clients[addr]['username'] = username -# self.send_stratum_response(client, msg_id, True) -# timestamp = time.strftime("%Y-%m-%d %H:%M:%S") -# print(f"[{timestamp}] πŸ” [{addr}] Authorized as {username}") - -# elif method == "login": -# # Handle xmrig's login method (JSON-RPC format with object params) -# if isinstance(params, dict): -# # xmrig format: {"login": "username", "pass": "password", "agent": "...", "algo": [...]} -# username = params.get('login', 'anonymous') -# password = params.get('pass', 'x') -# agent = params.get('agent', 'unknown') -# algorithms = params.get('algo', []) -# else: -# # Standard stratum format: ["username", "password"] -# username = params[0] if params else "anonymous" -# password = params[1] if len(params) > 1 else "x" -# agent = "unknown" -# algorithms = [] - -# self.clients[addr]['username'] = username -# self.clients[addr]['password'] = password -# self.clients[addr]['agent'] = agent -# self.clients[addr]['algorithms'] = algorithms - -# # Check if rinhash is supported -# rinhash_supported = any('rinhash' in algo.lower() or 'rin' in algo.lower() for algo in algorithms) -# if not rinhash_supported: -# print(f"[{addr}] Warning: rinhash not in supported algorithms: {algorithms}") - -# self.send_stratum_response(client, msg_id, True) -# timestamp = time.strftime("%Y-%m-%d %H:%M:%S") -# print(f"[{timestamp}] πŸ” [{addr}] xmrig Login as {username} (agent: {agent})") -# print(f"[{addr}] Supported algorithms: {algorithms}") - -# # Send initial job after login -# if self.current_job: -# self.send_job_to_client(client, self.current_job) -# else: -# if self.get_block_template(): -# self.send_job_to_client(client, self.current_job) - -# elif method == "mining.extranonce.subscribe": -# self.send_stratum_response(client, msg_id, True) - -# elif method == "mining.submit": -# if len(params) >= 5: -# username = params[0] -# job_id = params[1] -# extranonce2 = params[2] -# ntime = params[3] -# nonce = params[4] - -# print(f"[{addr}] Submit: {username} | job={job_id} | nonce={nonce}") - -# # Always validate against current job -# if self.current_job: -# extranonce1 = self.clients[addr].get('extranonce1', '00000000') - -# # Submit share -# success, message = self.submit_share(self.current_job, extranonce1, extranonce2, ntime, nonce, addr) - -# # Always accept shares for debugging, even if they don't meet target -# self.send_stratum_response(client, msg_id, True) - -# if success and "Block found" in message: -# # Get new job after block found -# threading.Thread(target=self.update_job_after_block, daemon=True).start() -# else: -# self.send_stratum_response(client, msg_id, True) -# else: -# self.send_stratum_response(client, msg_id, False, "Invalid parameters") - -# else: -# print(f"[{addr}] Unknown method: {method}") -# self.send_stratum_response(client, msg_id, None, "Unknown method") - -# except json.JSONDecodeError as e: -# print(f"[{addr}] Invalid JSON: {message}") -# print(f"[{addr}] JSON Error: {e}") -# except Exception as e: -# print(f"[{addr}] Message handling error: {e}") -# print(f"[{addr}] Error type: {type(e).__name__}") - -# def send_job_to_client(self, client, job): -# """Send mining job to specific client with proper stratum parameters""" -# try: -# # Get network difficulty for display -# network_difficulty = self.calculate_network_difficulty(job['target']) - -# # Build proper coinbase transaction parts for stratum protocol -# template = job.get('template', {}) -# height = job.get('height', 0) - -# # Encode height as minimal push (BIP34 compliance) -# if height == 0: -# height_push = b'' -# else: -# height_bytes = struct.pack(' 1 and height_bytes[-1] == 0: -# height_bytes = height_bytes[:-1] -# height_push = bytes([len(height_bytes)]) + height_bytes - -# # Build coinbase input script: height + arbitrary data + extranonces -# coinb1_script = height_push + b'/RinCoin/' - -# # Build coinbase transaction structure -# # Version (4 bytes) -# coinb1 = struct.pack('= self.max_connections: -# print(f"[{addr}] Connection rejected - max connections ({self.max_connections}) reached") -# client.close() -# return - -# print(f"[{addr}] Connected (clients: {len(self.clients) + 1}/{self.max_connections})") -# if addr not in self.clients: -# self.clients[addr] = {} -# self.clients[addr]['socket'] = client -# self.stats['connections'] = len(self.clients) - -# try: -# while self.running: -# data = client.recv(4096) -# if not data: -# break - -# # Handle multiple messages in one packet -# messages = data.decode('utf-8').strip().split('\n') -# for message in messages: -# if message: -# self.handle_stratum_message(client, addr, message) - -# except Exception as e: -# print(f"[{addr}] Client error: {e}") -# finally: -# client.close() -# if addr in self.clients: -# del self.clients[addr] -# self.stats['connections'] = len(self.clients) -# print(f"[{addr}] Disconnected (clients: {len(self.clients)}/{self.max_connections})") - -# def print_stats(self): -# """Print pool statistics""" -# try: -# uptime = time.time() - self.stats['start_time'] -# uptime_str = f"{int(uptime//3600)}h {int((uptime%3600)//60)}m" - -# accept_rate = 0 -# if self.stats['total_shares'] > 0: -# accept_rate = (self.stats['accepted_shares'] / self.stats['total_shares']) * 100 - -# print(f"\nπŸ“Š POOL STATISTICS:") -# print(f" ⏰ Uptime: {uptime_str}") -# print(f" πŸ‘₯ Connected miners: {self.stats['connections']}") -# print(f" πŸ“ˆ Shares: {self.stats['accepted_shares']}/{self.stats['total_shares']} ({accept_rate:.1f}% accepted)") -# print(f" πŸŽ‰ Blocks found: {self.stats['blocks_found']}") -# print(f" 🎯 Network difficulty: {self.calculate_network_difficulty(self.current_job['target']) if self.current_job else 'unknown':.6f}") - -# # Calculate hashrate estimate from connected clients -# total_hashrate = 0 -# for addr, client_data in self.clients.items(): -# share_count = client_data.get('share_count', 0) -# connect_time = client_data.get('connect_time', time.time()) -# mining_duration = time.time() - connect_time -# if mining_duration > 60 and share_count > 0: -# stratum_diff = client_data.get('stratum_difficulty', 0.001) -# # Rough hashrate estimate: shares * difficulty * 2^32 / time -# hashrate = (share_count * stratum_diff * 4294967296) / mining_duration -# total_hashrate += hashrate -# print(f" πŸ”₯ {addr}: ~{hashrate/1000:.0f} kH/s") - -# if total_hashrate > 0: -# print(f" πŸš€ Total pool hashrate: ~{total_hashrate/1000:.0f} kH/s") -# print() - -# except Exception as e: -# print(f"Stats error: {e}") - -# def job_updater(self): -# """Periodically update mining jobs""" -# balance_log_counter = 0 -# stats_counter = 0 - -# while self.running: -# try: -# time.sleep(30) # Update every 30 seconds - -# old_height = self.current_job['height'] if self.current_job else 0 - -# if self.get_block_template(): -# new_height = self.current_job['height'] -# if new_height > old_height: -# print(f"New block detected! Broadcasting new job...") -# self.broadcast_new_job() - -# # Log wallet balance every 10 minutes (20 cycles of 30 seconds) -# balance_log_counter += 1 -# if balance_log_counter >= 20: -# self.log_wallet_balance() -# balance_log_counter = 0 - -# # Print stats every 5 minutes (10 cycles of 30 seconds) -# stats_counter += 1 -# if stats_counter >= 10: -# self.print_stats() -# stats_counter = 0 - -# except Exception as e: -# print(f"Job updater error: {e}") - -# def validate_mining_capability(self): -# """Validate that we can mine valid blocks against the RinCoin node""" -# try: -# print("πŸ” Validating mining capability...") - -# # Get block template -# template = self.rpc_call("getblocktemplate", [{"rules": ["segwit", "mweb"]}]) -# if not template: -# print("❌ Cannot get block template") -# return False - -# # Test address validation -# result = self.rpc_call("validateaddress", [self.target_address]) -# if not result or not result.get('isvalid'): -# print(f"❌ Target address {self.target_address} is invalid") -# return False - -# print(f"βœ… Target address {self.target_address} is valid") - -# # Test coinbase construction -# coinbase_wit, coinbase_nowit = self.build_coinbase_transaction_for_address( -# template, "00000001", "01000000", self.target_address) - -# if not coinbase_wit or not coinbase_nowit: -# print("❌ Cannot construct coinbase transaction") -# return False - -# print(f"βœ… Coinbase construction works") - -# # Test block header construction with dummy values -# test_nonce = "12345678" -# test_ntime = f"{int(time.time()):08x}" - -# # Calculate merkle root -# coinbase_txid = hashlib.sha256(hashlib.sha256(coinbase_nowit).digest()).digest()[::-1] -# merkle_root = self.calculate_merkle_root(coinbase_txid, template.get('transactions', [])) - -# # Build test header -# header = b'' -# header += struct.pack(' 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" diff --git a/MINE/zergBench.sh b/MINE/zergBench.sh deleted file mode 100644 index 5bd8320..0000000 --- a/MINE/zergBench.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# Test top Zergpool algorithms - save as test_zergpool.sh - -BTC_WALLET="bc1qjn4m6rmrveuxhk02a5qhe4r6kdcsvvt3vhdn9j" - -echo "=== Testing Top Zergpool Algorithms ===" -echo "Wallet: $BTC_WALLET" -echo "======================================" - -# Top algorithms by profitability -declare -A algos=( - ["rinhash"]="rinhash.mine.zergpool.com:7148 c=RIN" - ["kawpow"]="kawpow.mine.zergpool.com:3638 c=BTC" - ["evrprogpow"]="evrprogpow.mine.zergpool.com:3002 c=BTC" - ["equihash125_4"]="equihash.mine.zergpool.com:2142 c=BTC" - ["karlsenhashv2"]="karlsenhashv2.mine.zergpool.com:3200 c=BTC" -) - -for algo in "${!algos[@]}"; do - echo "" - echo "Testing: $algo" - echo "------------------------" - - # Parse config - read -r server pass <<< "${algos[$algo]}" - - echo "Server: $server" - echo "Testing for 30 seconds..." - - sudo docker exec -it amdopencl timeout 35s bash -c "/mnt/dl/gminer/miner --algo $algo --server $server --user '$BTC_WALLET' --pass '$pass'" - - result=$? - if [ $result -eq 0 ]; then - echo "βœ… $algo: SUCCESS" - elif [ $result -eq 124 ]; then - echo "⏱️ $algo: TIMEOUT (likely working)" - else - echo "❌ $algo: FAILED - trying alternative miner..." - - # Try lolMiner for failed algorithms - sudo docker exec -it amdopencl timeout 35s bash -c "/mnt/dl/lolMiner_v1.88_Lin64/lolMiner --algo ${algo^^} --pool $server --user '$BTC_WALLET' --pass '$pass'" 2>/dev/null - - if [ $? -eq 124 ]; then - echo "⏱️ $algo: WORKS with lolMiner" - else - echo "❌ $algo: Not supported" - fi - fi - - sleep 3 -done - -echo "" -echo "=== Zergpool Testing Complete ===" \ No newline at end of file diff --git a/linux/docker install.md b/linux/docker install.md index 966fd37..cb589fa 100644 --- a/linux/docker install.md +++ b/linux/docker install.md @@ -27,6 +27,19 @@ docker pull portainer/helper-reset-password docker run --rm -v /mnt/storage/docker_volumes/portainer_data:/data portainer/helper-reset-password +# update portainer + +docker stop portainer + +docker rm portainer + +docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always --pull=always -v /var/run/docker.sock:/var/run/docker.sock -v /mnt/data/docker_vol/portainer:/data portainer/portainer-ce + +# start portainer with a database copy (/portainer-database-backup.db) +docker run --rm -v /mnt/data/docker_vol/portainer:/data -v /mnt/shared/DEV/repos/d-popov.com/scripts/portainer-compose-stacks/BACKUPS/20251118-133605:/backup alpine sh -c "rm /data/portainer.db && cp /backup/portainer-database-backup.db /data/portainer.db && ls -lh /data/portainer.db" + # remove backup/broken database + docker run --rm -v /mnt/data/docker_vol/portainer:/data alpine rm /data/portainer.db && echo "Old database removed" + # start sudo systemctl start docker sudo systemctl enable docker