├── LICENSE ├── README.md └── miner.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 BastelPichi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # MineCryptoOnWifiRouter 3 | 4 | This is a short guide that shows you how to mine DuinoCoin on a wifi router. DuinoCoin is a crypto that can even be mined on such low power devices. 5 | 6 | 1. Flash the router you want to use with OpenWRT . There many guides for your specific router out there. This will void your Warranty! 7 | 8 | If you want to buy a router in purpose, I would recommend a tplink. You can flash them very easily and they're cheap. 9 | 10 | 2. SSH into your router. Under Linux run: "ssh root@[routerip]. Under Windows use Putty. The default port 22 is fine. 11 | 12 | 3. type: "opkg update", "opkg install python3" and "opkg install coreutils-nohup" to install python and nohup. 13 | 14 | 4. Now edit line 14 to your username. If you want to use LEDs of your router as a indication if there was a accepted or declined share, go to line 16 and change variable 'enableLEDNotification' from ```False``` to ```True``` and set line 17 to the first led and line 18 to the second led. They're coments. You can get the led names by visiting the openwrt webinterface and going to system -> LED-Configuration. Pick 2 that are free.. 15 | 16 | 5. Now use a program like Winscp to get the miner.py script onto your router. Select SCP as protocol. 17 | 18 | 6. Then go back to putty and type "python3 miner.py". 19 | 20 | 7. If everything seems to work, and the router is mining, press Ctrl + c and type "nohup python3 miner.py &". If it doesn't, open an issue. 21 | 22 | 8. That's it! Your router is now mining crypto! Happy Mining! 23 | 24 | 25 | Officially tested Routers: 26 | 27 | Model | Hashrate | Difficulty | Profit 28 | --- | --- | --- | --- 29 | AVM Fritz!Box 4040 | 100kH/s | 2400 | ~10-15 DUCO per day 30 | TP-LINK WR841N | 5kH/s | 5000 31 | 32 | 33 | How can I further develop this? 34 | 1. Create a fork 35 | 2. Change the things you want to change and make sure everything works 36 | 3. Open a pull request 37 | -------------------------------------------------------------------------------- /miner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Duino-Coin Router Miner. Heavely based on the duino-coin Minimal PC Miner by BastelPichi 2022. 3 | # Originally by Revox 4 | 5 | import hashlib 6 | import os 7 | from socket import socket 8 | import sys # Only python3 included libraries 9 | import time 10 | import requests 11 | 12 | 13 | username = "Pichi" # add your username here. 14 | mining_key = "None" # change this to your mining key, or leave as is. 15 | 16 | leds = True # True if led notifications shouzld be enabled, if not, False. 17 | accepted = "fritz4040:amber:info" # Name of the LED that should blink on a accepted share. 18 | rejected = "fritz4040:red:info" # Name of the LED that should blink on a rejected share. 19 | 20 | soc = socket() 21 | 22 | def current_time(): 23 | t = time.localtime() 24 | current_time = time.strftime("%H:%M:%S", t) 25 | return current_time 26 | 27 | def fetch_pools(): 28 | while True: 29 | try: 30 | response = requests.get( 31 | "https://server.duinocoin.com/getPool" 32 | ).json() 33 | NODE_ADDRESS = response["ip"] 34 | NODE_PORT = response["port"] 35 | 36 | return NODE_ADDRESS, NODE_PORT 37 | except Exception as e: 38 | print (f"{current_time()}: Error retrieving mining node, retrying in 15s") 39 | time.sleep(15) 40 | 41 | def led(status): 42 | if leds == True: 43 | f = open(f"/sys/class/leds/{accepted if status else rejected}/brightness", "w") 44 | f.write("1") 45 | f.close() 46 | time.sleep(0.3) 47 | f = open(f"/sys/class/leds/{accepted if status else rejected}/brightness", "w") 48 | f.write("0") 49 | f.close() 50 | else: 51 | pass 52 | 53 | while True: 54 | try: 55 | print(f"{current_time()}: Searching for fastest connection to the server") 56 | try: 57 | NODE_ADDRESS, NODE_PORT = fetch_pools() 58 | except Exception as e: 59 | NODE_ADDRESS = "server.duinocoin.com" 60 | NODE_PORT = 2813 61 | print(f"{current_time()}: Using default server port and address") 62 | soc.connect((str(NODE_ADDRESS), int(NODE_PORT))) 63 | print(f"{current_time()}: Fastest connection found") 64 | server_version = soc.recv(100).decode() 65 | print (f"{current_time()}: Server Version: {server_version}") 66 | # Mining section 67 | while True: 68 | soc.send(bytes( 69 | "JOB," 70 | + str(username) 71 | + ",LOW," 72 | + mining_key, 73 | encoding="utf8")) 74 | 75 | 76 | # Receive work 77 | job = soc.recv(1024).decode().rstrip("\n") 78 | # Split received data to job and difficulty 79 | job = job.split(",") 80 | difficulty = job[2] 81 | 82 | hashingStartTime = time.time() 83 | base_hash = hashlib.sha1(str(job[0]).encode("ascii")) 84 | temp_hash = None 85 | 86 | for result in range(100 * int(difficulty) + 1): 87 | # Calculate hash with difficulty 88 | temp_hash = base_hash.copy() 89 | temp_hash.update(str(result).encode("ascii")) 90 | ducos1 = temp_hash.hexdigest() 91 | 92 | # If hash is even with expected hash result 93 | if job[1] == ducos1: 94 | hashingStopTime = time.time() 95 | timeDifference = hashingStopTime - hashingStartTime 96 | hashrate = result / timeDifference 97 | 98 | # Send numeric result to the server 99 | soc.send(bytes( 100 | str(result) 101 | + "," 102 | + str(hashrate) 103 | + ",Router Miner", 104 | encoding="utf8")) 105 | 106 | # Get feedback about the result 107 | feedback = soc.recv(1024).decode().rstrip("\n") 108 | # If result was good 109 | if feedback == "GOOD": 110 | print(f"{current_time()} : Accepted share", 111 | result, 112 | "Hashrate", 113 | int(hashrate/1000), 114 | "kH/s", 115 | "Difficulty", 116 | difficulty) 117 | led(True) 118 | break 119 | # If result was incorrect 120 | elif feedback == "BAD": 121 | print(f"{current_time()}: Rejected share", 122 | result, 123 | "Hashrate", 124 | int(hashrate/1000), 125 | "kH/s", 126 | "Difficulty", 127 | difficulty) 128 | led(False) 129 | break 130 | 131 | except Exception as e: 132 | print(f"{current_time()}: Error occured: {e}, restarting in 5s.") 133 | time.sleep(5) 134 | os.execl(sys.executable, sys.executable, *sys.argv) 135 | --------------------------------------------------------------------------------