|
| 1 | +# go-ethereum-pool |
| 2 | +## High Performance Ethereum Mining Pool |
| 3 | + |
| 4 | + |
| 5 | + |
| 6 | +### Features |
| 7 | + |
| 8 | +* Highly available mining endpoint module |
| 9 | +* Payouts and block unlocking (maturity) module |
| 10 | +* Configurable payouts period and balance threshold |
| 11 | +* PROP payouts (miners are simply paid out when a block is found) |
| 12 | +* Detailed block stats with luck percentage and full reward |
| 13 | +* Failover geth instances: geth high availability built in |
| 14 | +* Strict policy module (banning strategies using ipset/iptables) |
| 15 | +* Designed for 100% distributed setup of all modules |
| 16 | +* Modern beautiful Ember.js frontend |
| 17 | +* Separate stats for workers: can highlight timed-out workers so miners can perform maintenance of rigs |
| 18 | +* JSON-API for stats, miners can use for rigs maintenance automation (rig rebooting for example ) |
| 19 | +Also it's compatible with my *ether-proxy* solo/pool proxy solution. |
| 20 | + |
| 21 | +*Written in Go it's a rocket highly concurrent and low RAM consuming piece of code* |
| 22 | + |
| 23 | +### Building on Linux |
| 24 | + |
| 25 | +Dependencies: |
| 26 | + |
| 27 | + * go >= 1.4 |
| 28 | + * geth |
| 29 | + * redis-server |
| 30 | + * nodejs |
| 31 | + * nginx |
| 32 | + |
| 33 | +**I highly recommend to use Ubuntu 14.04 LTS.** |
| 34 | + |
| 35 | +First of all you must install [go-ethereum](https://github.com/ethereum/go-ethereum/wiki/Installation-Instructions-for-Ubuntu). |
| 36 | + |
| 37 | +Export GOPATH: |
| 38 | + |
| 39 | + export GOPATH=$HOME/go |
| 40 | + |
| 41 | +Install required packages: |
| 42 | + |
| 43 | + go get github.com/ethereum/ethash |
| 44 | + go get github.com/ethereum/go-ethereum/common |
| 45 | + go get github.com/gorilla/mux |
| 46 | + go get github.com/yvasiyarov/gorelic |
| 47 | + |
| 48 | +Compile: |
| 49 | + |
| 50 | + go build -o ether-pool main.go |
| 51 | + |
| 52 | +Install redis-server and all software you need too. |
| 53 | +Install nodejs, I suggest to use >= 4.x LTS version from https://github.com/nodesource/distributions or from your Linux distribution. |
| 54 | + |
| 55 | +### Building on Windows |
| 56 | + |
| 57 | +It's a little bit crazy to run production pool on this platform, but you can follow |
| 58 | +[geth building instructions](https://github.com/ethereum/go-ethereum/wiki/Installation-instructions-for-Windows) and compile pool this way. |
| 59 | +Use some cloud Redis provider or give a try to https://github.com/MSOpenTech/redis/releases. |
| 60 | + |
| 61 | +### Building Frontend |
| 62 | + |
| 63 | +Frontend is a single-page Ember.js application. It polls API of the pool |
| 64 | +to render pool stats to miners. |
| 65 | + |
| 66 | + cd www |
| 67 | + |
| 68 | +Change <code>ApiUrl: '//example.net/'</code> to match your domain name. |
| 69 | + |
| 70 | + |
| 71 | + npm install -g bower |
| 72 | + npm install |
| 73 | + bower install |
| 74 | + ./build.sh |
| 75 | + |
| 76 | +Configure nginx to serve API on <code>/api</code> subdirectory. |
| 77 | +Configure your nginx instance to serve <code>www/dist</code> as static website. |
| 78 | + |
| 79 | +#### Serving API using nginx |
| 80 | + |
| 81 | +Create an upstream for API: |
| 82 | + |
| 83 | + upstream api { |
| 84 | + server 127.0.0.1:8080; |
| 85 | + } |
| 86 | + |
| 87 | +and add this setting after <code>location /</code>: |
| 88 | + |
| 89 | + location /api { |
| 90 | + proxy_pass http://api; |
| 91 | + } |
| 92 | + |
| 93 | +You can customize layout and other stuff using built-in web server with live reload: |
| 94 | + |
| 95 | + ember server --port 8082 --environment development |
| 96 | + |
| 97 | +#### Customization |
| 98 | + |
| 99 | +Check out <code>www/app/templates</code> directory and edit these templates |
| 100 | +in order to add your own branding and contacts. |
| 101 | + |
| 102 | +### Configuration |
| 103 | + |
| 104 | +Configuration is actually simple, just read it twice and think twice before changing defaults. |
| 105 | + |
| 106 | +**Don't copy config directly from this manual, use example config from package, |
| 107 | +Otherwise you will get errors on start because JSON can't contain comments actually.** |
| 108 | + |
| 109 | +```javascript |
| 110 | +{ |
| 111 | + // Set to a number of CPU threads of your server |
| 112 | + "threads": 2, |
| 113 | + // Prefix for keys in redis store |
| 114 | + "coin": "eth", |
| 115 | + // Give unique name to each instance |
| 116 | + "name": "main", |
| 117 | + |
| 118 | + "proxy": { |
| 119 | + "enabled": true, |
| 120 | + |
| 121 | + // Bind mining endpoint to this IP:PORT |
| 122 | + "listen": "0.0.0.0:8546", |
| 123 | + |
| 124 | + // Allow only this header and body size of HTTP request from miners |
| 125 | + "limitHeadersSize": 1024, |
| 126 | + "limitBodySize": 256, |
| 127 | + |
| 128 | + /* Use it if you are behind CloudFlare (bad idea) or behind http-reverse |
| 129 | + proxy to enable IP detection from X-Forwarded-For header. |
| 130 | + Advanced users only. It's tricky to make it right and secure. |
| 131 | + */ |
| 132 | + "behindReverseProxy": false, |
| 133 | + |
| 134 | + // Try to get new job from geth in this interval |
| 135 | + "blockRefreshInterval": "120ms", |
| 136 | + "stateUpdateInterval": "3s", |
| 137 | + // Require this share difficulty from miners |
| 138 | + "difficulty": 2000000000, |
| 139 | + |
| 140 | + "hashrateExpiration": "30m", |
| 141 | + |
| 142 | + /* Reply error to miner instead of job if redis is unavailable. |
| 143 | + Should save electricity to miners if pool is sick and they didn't set up failovers. |
| 144 | + */ |
| 145 | + "healthCheck": true, |
| 146 | + // Mark pool sick after this number of redis failures. |
| 147 | + "maxFails": 100, |
| 148 | + |
| 149 | + "policy": { |
| 150 | + "workers": 8, |
| 151 | + "resetInterval": "60m", |
| 152 | + "refreshInterval": "1m", |
| 153 | + |
| 154 | + "banning": { |
| 155 | + "enabled": false, |
| 156 | + /* Name of ipset for banning. |
| 157 | + Check http://ipset.netfilter.org/ documentation. |
| 158 | + */ |
| 159 | + "ipset": "blacklist", |
| 160 | + // Remove ban after this amount of time |
| 161 | + "timeout": 1800, |
| 162 | + // Percent of invalid shares from all shares to ban miner |
| 163 | + "invalidPercent": 30, |
| 164 | + // Check after after miner submitted this number of shares |
| 165 | + "checkThreshold": 30, |
| 166 | + // Bad miner after this number of malformed requests |
| 167 | + "malformedLimit": 5 |
| 168 | + } |
| 169 | + } |
| 170 | + }, |
| 171 | + |
| 172 | + // Provides JSON data for frontend which is static website |
| 173 | + "api": { |
| 174 | + "enabled": true, |
| 175 | + |
| 176 | + /* If you are running API node in a distributed environment where this module |
| 177 | + is reading data from redis writeable slave, enable this option. |
| 178 | + Only redis writeable slave will work properly if you are distributing using redis slaves. |
| 179 | + Don't distribute! |
| 180 | + */ |
| 181 | + "purgeOnly": false, |
| 182 | + "listen": "0.0.0.0:8080", |
| 183 | + // Collect miners stats (hashrate, ...) in this interval |
| 184 | + "statsCollectInterval": "5s", |
| 185 | + |
| 186 | + // Fast hashrate estimation window for each miner from it's shares |
| 187 | + "hashrateWindow": "30m", |
| 188 | + // Long and precise hashrate from shares, 3h is cool, keep it |
| 189 | + "hashrateLargeWindow": "3h", |
| 190 | + // Max number of payments to display in frontend |
| 191 | + "payments": 50, |
| 192 | + // Max numbers of blocks to display in frontend |
| 193 | + "blocks": 50 |
| 194 | + }, |
| 195 | + |
| 196 | + // Check health of each geth node in this interval |
| 197 | + "upstreamCheckInterval": "5s", |
| 198 | + |
| 199 | + /* List of geth nodes to poll for new jobs. Pool will try to get work from |
| 200 | + first alive one and check in background for failed to back up. |
| 201 | + Current block template of the pool is always cached in RAM indeed. |
| 202 | + */ |
| 203 | + "upstream": [ |
| 204 | + { |
| 205 | + "name": "main", |
| 206 | + "url": "http://127.0.0.1:8545", |
| 207 | + "timeout": "10s" |
| 208 | + }, |
| 209 | + { |
| 210 | + "name": "backup", |
| 211 | + "url": "http://127.0.0.2:8545", |
| 212 | + "timeout": "10s" |
| 213 | + } |
| 214 | + ], |
| 215 | + |
| 216 | + // This is standard redis connection options |
| 217 | + "redis": { |
| 218 | + // Where your redis instance is listening for commands |
| 219 | + "endpoint": "127.0.0.1:6379", |
| 220 | + "poolSize": 8, |
| 221 | + "database": 0, |
| 222 | + /* Generate and specify very strong password for in redis |
| 223 | + configuration file and specify it here. |
| 224 | + This is done using the requirepass directive in the configuration file. |
| 225 | + */ |
| 226 | + "password": "secret" |
| 227 | + }, |
| 228 | + |
| 229 | + // This module periodically credits coins to miners |
| 230 | + "unlocker": { |
| 231 | + "enabled": false, |
| 232 | + // Pool fee percentage |
| 233 | + "poolFee": 1.0, |
| 234 | + // Unlock only if this number of blocks mined back |
| 235 | + "depth": 120, |
| 236 | + // Simply don't touch this option |
| 237 | + "immatureDepth": 20, |
| 238 | + // Run unlocker in this interval |
| 239 | + "interval": "10m", |
| 240 | + // Geth instance node rpc endpoint for unlocking blocks |
| 241 | + "daemon": "http://127.0.0.1:8545", |
| 242 | + // Rise error if can't reach geth in this amount of time |
| 243 | + "timeout": "10s" |
| 244 | + }, |
| 245 | + |
| 246 | + // Paying out miners using this module |
| 247 | + "payouts": { |
| 248 | + "enabled": false, |
| 249 | + // Run payouts in this interval |
| 250 | + "interval": "12h", |
| 251 | + // Geth instance node rpc endpoint for payouts processing |
| 252 | + "daemon": "http://127.0.0.1:8545", |
| 253 | + // Rise error if can't reach geth in this amount of time |
| 254 | + "timeout": "10s", |
| 255 | + // Address with pool balance |
| 256 | + "address": "0x0", |
| 257 | + // Gas amount and price for payout tx |
| 258 | + "gas": "21000", |
| 259 | + "gasPrice": "50000000000", |
| 260 | + // Seend payment only if miner's balance is >= 0.5 Ether |
| 261 | + "threshold": 500000000 |
| 262 | + }, |
| 263 | +} |
| 264 | +``` |
| 265 | + |
| 266 | +If you are distributing your pool deployment to several servers or processes, |
| 267 | +create several configs and disable unneeded modules on each server. |
| 268 | +This is very advanced, better don't distribute to several servers until you really need it. |
| 269 | + |
| 270 | +I recommend this deployment strategy: |
| 271 | + |
| 272 | +* Mining instance - 1x (it depends, you can run one node for EU, one for US, one for Asia) |
| 273 | +* Unlocker and payouts instance - 1x each (strict!) |
| 274 | +* API instance - 1x |
| 275 | + |
| 276 | +### Notes |
| 277 | + |
| 278 | +Unlocking and payouts are sequential, 1st tx go, 2nd waiting for 1st to confirm and so on. |
| 279 | +You can disable that in code. Also, keep in mind that unlocking and payouts will be stopped in case of any backend or geth failure. |
| 280 | +You must restart module if you see such errors with *suspended* word, so I recommend to run unlocker and payouts in a separate processes. |
| 281 | +Don't run payouts and unlocker as part of mining node. |
| 282 | + |
| 283 | +### Credits |
| 284 | + |
| 285 | +Made by sammy007. |
| 286 | + |
| 287 | +### Donations |
| 288 | + |
| 289 | +* **ETH**: [0xb85150eb365e7df0941f0cf08235f987ba91506a](https://etherchain.org/account/0xb85150eb365e7df0941f0cf08235f987ba91506a) |
| 290 | + |
| 291 | +* **BTC**: [1PYqZATFuYAKS65dbzrGhkrvoN9au7WBj8](https://blockchain.info/address/1PYqZATFuYAKS65dbzrGhkrvoN9au7WBj8) |
0 commit comments