diff --git a/MINE/rin/QUICK_REFERENCE.md b/MINE/rin/QUICK_REFERENCE.md index 4fb079f..6debf73 100644 --- a/MINE/rin/QUICK_REFERENCE.md +++ b/MINE/rin/QUICK_REFERENCE.md @@ -43,4 +43,25 @@ ./MINE/rin/start_stratum_proxy.sh & sleep 5 ./cpuminer -a rinhash -o stratum+tcp://127.0.0.1:3333 -u user -p pass -t 4 + + + +## Check wallets + +# First, check available wallets and load one if needed +curl -u rinrpc:745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 -d '{"jsonrpc":"1.0","id":"1","method":"listwalletdir","params":[]}' -H 'content-type: text/plain;' http://127.0.0.1:9556/ + +# Load wallet (replace "main" with your wallet name) +curl -u rinrpc:745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 -d '{"jsonrpc":"1.0","id":"1","method":"loadwallet","params":["main"]}' -H 'content-type: text/plain;' http://127.0.0.1:9556/ + +# Total received by your address +curl -u rinrpc:745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 -d '{"jsonrpc":"1.0","id":"1","method":"getreceivedbyaddress","params":["rin1qahvvv9d5f3443wtckeqavwp9950wacxfmwv20q",0]}' -H 'content-type: text/plain;' http://127.0.0.1:9556/ + +# Wallet balance +curl -u rinrpc:745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 -d '{"jsonrpc":"1.0","id":"1","method":"getbalance","params":[]}' -H 'content-type: text/plain;' http://127.0.0.1:9556/ + +# Recent transactions +curl -u rinrpc:745ce784d5d537fc06105a1b935b7657903cfc71a5fb3b90 -d '{"jsonrpc":"1.0","id":"1","method":"listtransactions","params":[]}' -H 'content-type: text/plain;' http://127.0.0.1:9556/ ``` + + diff --git a/MINE/rin/README.md b/MINE/rin/README.md index 3d898fd..97fcf50 100644 --- a/MINE/rin/README.md +++ b/MINE/rin/README.md @@ -27,7 +27,7 @@ cd /mnt/shared/DEV/repos/d-popov.com/scripts ./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 4 +./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 diff --git a/MINE/rin/miner/readme.md b/MINE/rin/miner/readme.md deleted file mode 100644 index 53fb967..0000000 --- a/MINE/rin/miner/readme.md +++ /dev/null @@ -1,23 +0,0 @@ -from https://github.com/StickyFingaz420/CPUminer-opt-rinhash - - - -Option 1: Build from Source (Recommended) -bash - -Copy -# Install build dependencies -sudo apt update -sudo apt install build-essential autotools-dev autoconf pkg-config libcurl4-openssl-dev libjansson-dev libssl-dev libgmp-dev zlib1g-dev git automake libtool - -# Clone the repository (if you haven't already) -git clone https://github.com/rplant8/cpuminer-opt-rinhash.git -cd cpuminer-opt-rinhash - -# Build it -./autogen.sh -./configure CFLAGS="-O3 -march=native -funroll-loops -fomit-frame-pointer" -make -j$(nproc) - -# Test the newly built binary -./cpuminer -a rinhash -o stratum+tcp://192.168.0.188:3333 -u username.workername -p x -t 4 \ No newline at end of file diff --git a/MINE/rin/stratum_pool.py b/MINE/rin/stratum_pool.py index be7dea6..f32b699 100644 --- a/MINE/rin/stratum_pool.py +++ b/MINE/rin/stratum_pool.py @@ -344,7 +344,7 @@ class RinCoinMiningPool: ]) # Send difficulty (lower for CPU mining) - self.send_stratum_notification(client, "mining.set_difficulty", [0.001]) + self.send_stratum_notification(client, "mining.set_difficulty", [0.0001]) # Send initial job if self.get_block_template(): diff --git a/MINE/rin/stratum_proxy.py b/MINE/rin/stratum_proxy.py index d780f32..e9f2e2e 100644 --- a/MINE/rin/stratum_proxy.py +++ b/MINE/rin/stratum_proxy.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ -RinCoin Stratum Proxy Server -Bridges cpuminer-opt-rin (Stratum protocol) to RinCoin node (RPC protocol) +RinCoin Stratum Proxy Server - REAL MINING VERSION +Properly constructs Stratum jobs and validates/submits real blocks """ import socket @@ -31,8 +31,9 @@ class RinCoinStratumProxy: self.job_counter = 0 self.current_job = None self.running = True + self.extranonce1_counter = 0 - print(f"RinCoin Stratum Proxy Server") + print(f"RinCoin Stratum Proxy Server - REAL MINING") print(f"Stratum: {stratum_host}:{stratum_port}") print(f"RPC: {rpc_host}:{rpc_port}") print(f"Target: {target_address}") @@ -51,7 +52,7 @@ class RinCoinStratumProxy: "params": params } - response = requests.post(url, json=payload, headers=headers, auth=auth, timeout=10) + response = requests.post(url, json=payload, headers=headers, auth=auth, timeout=30) if response.status_code == 200: result = response.json() @@ -66,37 +67,230 @@ class RinCoinStratumProxy: 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(' 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 bits_to_target(self, bits_hex): + """Convert bits to target""" + try: + bits = int(bits_hex, 16) + exponent = bits >> 24 + mantissa = bits & 0xffffff + target = mantissa * (256 ** (exponent - 3)) + return f"{target:064x}" + except: + return "0000ffff00000000000000000000000000000000000000000000000000000000" + def get_block_template(self): - """Get new block template from RinCoin node""" + """Get new block template and create Stratum job""" try: template = self.rpc_call("getblocktemplate", [{"rules": ["segwit", "mweb"]}]) - if template: - self.job_counter += 1 + if not template: + return None - # Store the full template for later block construction - job = { - "job_id": f"job_{self.job_counter}", - "template": template, # Store full template - "prevhash": template.get("previousblockhash", "0" * 64), - "coinb1": "01000000" + "0" * 60, # Simplified coinbase (will be properly constructed on submission) - "coinb2": "ffffffff", - "merkle_branch": [], - "version": f"{template.get('version', 1):08x}", - "nbits": template.get("bits", "1d00ffff"), - "ntime": f"{int(time.time()):08x}", - "clean_jobs": True, - "target": template.get("target", "0000ffff00000000000000000000000000000000000000000000000000000000") - } - - self.current_job = job - print(f"New job created: {job['job_id']} (coinbase value: {template.get('coinbasevalue', 0)} satoshis)") - return job - 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 + print(f"New job: {job['job_id']} | Height: {job['height']} | Reward: {job['coinbasevalue']/100000000:.2f} RIN") + return job + except Exception as e: print(f"Get block template error: {e}") return None - + + def submit_share(self, job, extranonce1, extranonce2, ntime, nonce): + """Validate share and submit block if valid""" + try: + print(f"Share: job={job['job_id']} nonce={nonce}") + + # Build coinbase transaction + coinbase = self.build_coinbase_transaction(job['template'], extranonce1, extranonce2) + if not coinbase: + return False, "Coinbase construction failed" + + # Calculate coinbase transaction hash + coinbase_hash = hashlib.sha256(hashlib.sha256(coinbase).digest()).digest()[::-1] + + # Calculate merkle root + merkle_root = self.calculate_merkle_root(coinbase_hash, job['transactions']) + + # Build block header + header = b'' + header += struct.pack(' target_int: + # Valid share but not a block + return True, "Share accepted" + + # Valid block! Build full block and submit + print(f"BLOCK FOUND! Hash: {block_hash_hex}") + + # Build complete block + block = header + + # Transaction count + tx_count = 1 + len(job['transactions']) + block += self.encode_varint(tx_count) + + # Add coinbase transaction + block += coinbase + + # Add other transactions + for tx in job['transactions']: + block += bytes.fromhex(tx['data']) + + # Submit block + block_hex = block.hex() + result = self.rpc_call("submitblock", [block_hex]) + + if result is None: + print(f"Block accepted: {block_hash_hex}") + print(f"Reward: {job['coinbasevalue']/100000000:.2f} RIN -> {self.target_address}") + return True, "Block found and submitted" + else: + print(f"Block rejected: {result}") + return False, f"Block rejected: {result}" + + 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: @@ -105,12 +299,11 @@ class RinCoinStratumProxy: "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: @@ -119,12 +312,11 @@ class RinCoinStratumProxy: "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: @@ -133,75 +325,71 @@ class RinCoinStratumProxy: msg_id = data.get("id") params = data.get("params", []) - print(f"[{addr}] {method}: {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 + extranonce1, + 4 # extranonce2 size ]) # Send difficulty - self.send_stratum_notification(client, "mining.set_difficulty", [1]) + self.send_stratum_notification(client, "mining.set_difficulty", [0.0001]) # Send initial job - if self.get_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"], - job["version"], - job["nbits"], - job["ntime"], - job["clean_jobs"] - ]) + 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": - # Authorization + username = params[0] if params else "anonymous" + self.clients[addr]['username'] = username + self.send_stratum_response(client, msg_id, True) + print(f"[{addr}] Authorized as {username}") + + elif method == "mining.extranonce.subscribe": + # Handle extranonce subscription self.send_stratum_response(client, msg_id, True) - print(f"[{addr}] Authorized") elif method == "mining.submit": - # Submit share - print(f"[{addr}] Share submitted: {params}") - - # Try to submit block if it's a valid solution - try: - if self.current_job and len(params) >= 5: - job_id = params[0] - extranonce2 = params[1] - ntime = params[2] - nonce = params[3] + 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}") + + # Validate submission + if self.current_job and job_id == self.current_job['job_id']: + extranonce1 = self.clients[addr].get('extranonce1', '00000000') - print(f"[{addr}] Attempting to submit block solution...") - print(f" Job: {job_id}, Nonce: {nonce}, Time: {ntime}") + # Submit share + success, message = self.submit_share(self.current_job, extranonce1, extranonce2, ntime, nonce) - # Use generatetoaddress to submit the mining result - # This is a simplified approach - the real block construction would be more complex - result = self.rpc_call("generatetoaddress", [1, self.target_address, 1]) - - if result and len(result) > 0: - block_hash = result[0] - print(f"🎉 [{addr}] BLOCK FOUND! Hash: {block_hash}") - print(f"💰 Block reward sent to: {self.target_address}") + if success: self.send_stratum_response(client, msg_id, True) + if "Block found" in message: + # Get new job after block found + threading.Thread(target=self.update_job_after_block, daemon=True).start() else: - # Accept as share even if not a block - print(f"[{addr}] Share accepted (not a block)") - self.send_stratum_response(client, msg_id, True) + self.send_stratum_response(client, msg_id, False, message) else: - print(f"[{addr}] Invalid share parameters") - self.send_stratum_response(client, msg_id, False, "Invalid parameters") - - except Exception as e: - print(f"[{addr}] Block submission error: {e}") - # Still accept the share for mining statistics - self.send_stratum_response(client, msg_id, True) + self.send_stratum_response(client, msg_id, False, "Stale job") + else: + self.send_stratum_response(client, msg_id, False, "Invalid parameters") else: print(f"[{addr}] Unknown method: {method}") @@ -211,11 +399,51 @@ class RinCoinStratumProxy: print(f"[{addr}] Invalid JSON: {message}") except Exception as e: print(f"[{addr}] Message handling error: {e}") - + + def send_job_to_client(self, client, job): + """Send mining job to specific client""" + try: + # Send proper Stratum job + self.send_stratum_notification(client, "mining.notify", [ + job["job_id"], + job["prevhash"], + "", # coinb1 (empty for now - miner handles coinbase) + "", # coinb2 (empty for now - miner handles coinbase) + [], # merkle_branch (empty for now - we calculate merkle root) + f"{job['version']:08x}", + job["bits"], + job["ntime"], + True # clean_jobs + ]) + except Exception as e: + print(f"Failed to send job: {e}") + + def update_job_after_block(self): + """Update job after a block is found""" + time.sleep(2) # Brief delay to let network propagate + if self.get_block_template(): + self.broadcast_new_job() + + def broadcast_new_job(self): + """Broadcast new job to all connected clients""" + if not self.current_job: + return + + print(f"Broadcasting new job to {len(self.clients)} clients") + + for addr, client_data in list(self.clients.items()): + try: + if 'socket' in client_data: + self.send_job_to_client(client_data['socket'], self.current_job) + except Exception as e: + print(f"Failed to send job to {addr}: {e}") + def handle_client(self, client, addr): """Handle individual client connection""" print(f"[{addr}] Connected") - self.clients[addr] = client + if addr not in self.clients: + self.clients[addr] = {} + self.clients[addr]['socket'] = client try: while self.running: @@ -236,48 +464,41 @@ class RinCoinStratumProxy: if addr in self.clients: del self.clients[addr] print(f"[{addr}] Disconnected") - + def job_updater(self): """Periodically update mining jobs""" while self.running: try: - # Update job every 30 seconds - time.sleep(30) + time.sleep(30) # Update every 30 seconds + + old_height = self.current_job['height'] if self.current_job else 0 if self.get_block_template(): - job = self.current_job - print(f"Broadcasting new job: {job['job_id']}") - - # Send to all connected clients - for addr, client in list(self.clients.items()): - try: - self.send_stratum_notification(client, "mining.notify", [ - job["job_id"], - job["prevhash"], - job["coinb1"], - job["coinb2"], - job["merkle_branch"], - job["version"], - job["nbits"], - job["ntime"], - job["clean_jobs"] - ]) - except Exception as e: - print(f"Failed to send job to {addr}: {e}") - + new_height = self.current_job['height'] + if new_height > old_height: + print(f"New block detected! Broadcasting new job...") + self.broadcast_new_job() + except Exception as e: print(f"Job updater error: {e}") - + def start(self): """Start the Stratum proxy server""" try: # Test RPC connection blockchain_info = self.rpc_call("getblockchaininfo") if not blockchain_info: - print("❌ Failed to connect to RinCoin node!") + print("Failed to connect to RinCoin node!") return - print(f"✅ Connected to RinCoin node (block {blockchain_info.get('blocks', 'unknown')})") + print(f"Connected to RinCoin node") + print(f"Current height: {blockchain_info.get('blocks', 'unknown')}") + print(f"Chain: {blockchain_info.get('chain', 'unknown')}") + + # Get initial block template + if not self.get_block_template(): + print("Failed to get initial block template!") + return # Start job updater thread job_thread = threading.Thread(target=self.job_updater, daemon=True) @@ -289,13 +510,13 @@ class RinCoinStratumProxy: server_socket.bind((self.stratum_host, self.stratum_port)) server_socket.listen(10) - print(f"🚀 Stratum proxy listening on {self.stratum_host}:{self.stratum_port}") - print("Ready for cpuminer-opt-rin connections...") + print(f"REAL Mining Stratum proxy ready!") + print(f"Listening on {self.stratum_host}:{self.stratum_port}") + print(f"Mining to: {self.target_address}") + print(f"Current job: {self.current_job['job_id'] if self.current_job else 'None'}") print("") - print(f"💰 Block rewards will be sent to: {self.target_address}") - print("") - print("Connect your miner with:") - print(f"./cpuminer -a rinhash -o stratum+tcp://{self.stratum_host}:{self.stratum_port} -u user -p pass -t 28") + print("Miner command:") + print(f"./cpuminer -a rinhash -o stratum+tcp://{self.stratum_host}:{self.stratum_port} -u worker1 -p x -t 4") print("") while self.running: @@ -314,19 +535,6 @@ class RinCoinStratumProxy: 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: @@ -334,4 +542,4 @@ class RinCoinStratumProxy: if __name__ == "__main__": proxy = RinCoinStratumProxy() - proxy.start() + proxy.start() \ No newline at end of file