PageRenderTime 25ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/README.md

https://github.com/emanuel/node-open-mining-portal
Markdown | 566 lines | 461 code | 105 blank | 0 comment | 0 complexity | 446bb7af71e5bb75554926e5cbdd35c7 MD5 | raw file
Possible License(s): GPL-2.0
  1. # NOMP ![NOMP Logo](http://zone117x.github.io/node-open-mining-portal/logo.svg "NOMP Logo")
  2. #### Node Open Mining Portal
  3. This portal is an extremely efficient, highly scalable, all-in-one, easy to setup cryptocurrency mining pool written
  4. entirely in Node.js. It contains a stratum poolserver; reward/payment/share processor; and a (*not yet completed*)
  5. responsive user-friendly front-end website featuring mining instructions, in-depth live statistics, and an admin center.
  6. #### Table of Contents
  7. * [Features](#features)
  8. * [Attack Mitigation](##attack-mitigation)
  9. * [Security](#security)
  10. * [Planned Features](#planned-features)
  11. * [Community Support](#community--support)
  12. * [Usage](#usage)
  13. * [Requirements](#requirements)
  14. * [Setting Up Coin Daemon](#0-setting-up-coin-daemon)
  15. * [Downloading & Installing](#1-downloading--installing)
  16. * [Configuration](#2-configuration)
  17. * [Portal Config](#portal-config)
  18. * [Coin Config](#coin-config)
  19. * [Pool Config](#pool-config)
  20. * [Setting Up Blocknotify](#optional-recommended-setting-up-blocknotify)
  21. * [Starting the Portal](#3-start-the-portal)
  22. * [Upgrading NOMP](#upgrading-nomp)
  23. * [Donations](#donations)
  24. * [Credits](#credits)
  25. * [License](#license)
  26. ### Features
  27. * For the pool server it uses the highly efficient [node-stratum-pool](//github.com/zone117x/node-stratum-pool) module which
  28. supports vardiff, POW & POS, transaction messages, anti-DDoS, IP banning, [several hashing algorithms](//github.com/zone117x/node-stratum-pool#hashing-algorithms-supported).
  29. * The portal has an [MPOS](//github.com/MPOS/php-mpos) compatibility mode so that the it can
  30. function as a drop-in-replacement for [python-stratum-mining](//github.com/Crypto-Expert/stratum-mining). This
  31. mode can be enabled in the configuration and will insert shares into a MySQL database in the format which MPOS expects.
  32. For a direct tutorial see the wiki page [Setting up NOMP for MPOS usage](//github.com/zone117x/node-open-mining-portal/wiki/Setting-up-NOMP-for-MPOS-usage).
  33. * Multi-pool ability - this software was built from the ground up to run with multiple coins simultaneously (which can
  34. have different properties and hashing algorithms). It can be used to create a pool for a single coin or for multiple
  35. coins at once. The pools use clustering to load balance across multiple CPU cores.
  36. * For reward/payment processing, shares are inserted into Redis (a fast NoSQL key/value store). The PROP (proportional)
  37. reward system is used with [Redis Transactions](http://redis.io/topics/transactions) for secure and super speedy payouts.
  38. Each and every share will be rewarded - even for rounds resulting in orphaned blocks.
  39. * This portal does not have user accounts/logins/registrations. Instead, miners simply use their coin address for stratum
  40. authentication. A minimalistic HTML5 front-end connects to the portals statistics API to display stats from from each
  41. pool such as connected miners, network/pool difficulty/hash rate, etc.
  42. * Automated switching of connected miners to different pools/coins is also easily done due to the multi-pool architecture
  43. of this software. To use this feature the switching must be controlled by your own script, such as one that calculates
  44. coin profitability via an API such as CoinChoose.com or CoinWarz.com (or calculated locally using daemon-reported network
  45. difficulties and exchange APIs). NOMP's regular payment processing and miner authentication which using coin address as stratum
  46. username will obviously not work with this coin switching feature - so you must control those with your own script as well.
  47. #### Attack Mitigation
  48. * Detects and thwarts socket flooding (garbage data sent over socket in order to consume system resources).
  49. * Detects and thwarts zombie miners (botnet infected computers connecting to your server to use up sockets but not sending any shares).
  50. * Detects and thwarts invalid share attacks:
  51. * NOMP is not vulnerable to the low difficulty share exploits happening to other pool servers. Other pool server
  52. software has hardcoded guesstimated max difficulties for new hashing algorithms while NOMP dynamically generates the
  53. max difficulty for each algorithm based on values founds in coin source code.
  54. * IP banning feature which on a configurable threshold will ban an IP for a configurable amount of time if the miner
  55. submits over a configurable threshold of invalid shares.
  56. * NOMP is written in Node.js which uses a single thread (async) to handle connections rather than the overhead of one
  57. thread per connection, and clustering is also implemented so all CPU cores are taken advantage of.
  58. #### Security
  59. NOMP has some implicit security advantages for pool operators and miners:
  60. * Without a registration/login system, non-security-oriented miners reusing passwords across pools is no longer a concern.
  61. * Automated payouts by default and pool profits are sent to another address so pool wallets aren't plump with coins -
  62. giving hackers little reward and keeping your pool from being a target.
  63. * Miners can notice lack of automated payments as a possible early warning sign that an operator is about to run off with their coins.
  64. #### Planned Features
  65. * NOMP API - Used by the website to display stats and information about the pool(s) on the portal's front-end website,
  66. and by the NOMP Desktop app to retrieve a list of available coins (and version-bytes for local wallet/address generation).
  67. * To reduce variance for pools just starting out which have little to no hashing power a feature is planned which will
  68. allow your own pool to connect upstream to a larger pool server. It will request work from the larger pool then
  69. redistribute the work to our own connected miners.
  70. ### Community / Support
  71. IRC
  72. * Support / general discussion join #nomp: https://webchat.freenode.net/?channels=#nomp
  73. * Development discussion join #nomp-dev: https://webchat.freenode.net/?channels=#nomp-dev
  74. Join our subreddit [/r/nomp](http://reddit.com/r/nomp)!
  75. *Having problems getting the portal running due to some module dependency error?* It's probably because you
  76. didn't follow the instructions in this README. Please __read the usage instructions__ including [requirements](#requirements) and [downloading/installing](#1-downloading--installing). If you've followed the instructions completely and are still having problems then open an issue here on github or join our #nomp IRC channel and explain your problem :).
  77. If your pool uses NOMP let us know and we will list your website here.
  78. ##### Some pools using NOMP or node-stratum-module:
  79. * http://chunkypools.com
  80. * http://clevermining.com
  81. * http://rapidhash.net
  82. * http://suchpool.pw
  83. * http://hashfaster.com
  84. * http://miningpoolhub.com
  85. * http://kryptochaos.com
  86. * http://pool.uberpools.org
  87. Usage
  88. =====
  89. #### Requirements
  90. * Coin daemon(s) (find the coin's repo and build latest version from source)
  91. * [Node.js](http://nodejs.org/) v0.10+ ([follow these installation instructions](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager))
  92. * [Redis](http://redis.io/) key-value store v2.6+ ([follow these instructions](http://redis.io/topics/quickstart))
  93. ##### Seriously
  94. Those are legitimate requirements. If you use old versions of Node.js or Redis that may come with your system package manager then you will have problems. Follow the linked instructions to get the last stable versions.
  95. #### 0) Setting up coin daemon
  96. Follow the build/install instructions for your coin daemon. Your coin.conf file should end up looking something like this:
  97. ```
  98. daemon=1
  99. rpcuser=litecoinrpc
  100. rpcpassword=securepassword
  101. rpcport=19332
  102. ```
  103. For redundancy, its recommended to have at least two daemon instances running in case one drops out-of-sync or offline,
  104. all instances will be polled for block/transaction updates and be used for submitting blocks. Creating a backup daemon
  105. involves spawning a daemon using the `-datadir=/backup` command-line argument which creates a new daemon instance with
  106. it's own config directory and coin.conf file. Learn about the daemon, how to use it and how it works if you want to be
  107. a good pool operator. For starters be sure to read:
  108. * https://en.bitcoin.it/wiki/Running_bitcoind
  109. * https://en.bitcoin.it/wiki/Data_directory
  110. * https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_Calls_list
  111. * https://en.bitcoin.it/wiki/Difficulty
  112. #### 1) Downloading & Installing
  113. Clone the repository and run `npm update` for all the dependencies to be installed:
  114. ```bash
  115. git clone https://github.com/zone117x/node-open-mining-portal.git nomp
  116. cd nomp
  117. npm update
  118. ```
  119. #### 2) Configuration
  120. ##### Portal config
  121. Inside the `config_example.json` file, ensure the default configuration will work for your environment, then copy the file to `config.json`.
  122. Explanation for each field:
  123. ````javascript
  124. {
  125. /* Specifies the level of log output verbosity. Anything more severy than the level specified
  126. will also be logged. */
  127. "logLevel": "debug", //or "warning", "error"
  128. /* By default 'forks' is set to "auto" which will spawn one process/fork/worker for each CPU
  129. core in your system. Each of these workers will run a separate instance of your pool(s),
  130. and the kernel will load balance miners using these forks. Optionally, the 'forks' field
  131. can be a number for how many forks will be spawned. */
  132. "clustering": {
  133. "enabled": true,
  134. "forks": "auto"
  135. },
  136. /* This is the front-end. Its not finished. When it is finished, this comment will say so. */
  137. "website": {
  138. "enabled": true,
  139. "port": 80,
  140. /* Used for displaying stratum connection data on the Getting Started page. */
  141. "stratumHost": "cryppit.com",
  142. "stats": {
  143. /* Gather stats to broadcast to page viewers and store in redis for historical stats
  144. every this many seconds. */
  145. "updateInterval": 15,
  146. /* How many seconds to hold onto historical stats. Currently set to 24 hours. */
  147. "historicalRetention": 43200,
  148. /* How many seconds worth of shares should be gathered to generate hashrate. */
  149. "hashrateWindow": 300
  150. },
  151. /* Not done yet. */
  152. "adminCenter": {
  153. "enabled": true,
  154. "password": "password"
  155. }
  156. },
  157. /* Redis instance of where to store global portal data such as historical stats, proxy states,
  158. ect.. */
  159. "redis": {
  160. "host": "127.0.0.1",
  161. "port": 6379
  162. },
  163. /* With this enabled, the master process listen on the configured port for messages from the
  164. 'scripts/blockNotify.js' script which your coin daemons can be configured to run when a
  165. new block is available. When a blocknotify message is received, the master process uses
  166. IPC (inter-process communication) to notify each thread about the message. Each thread
  167. then sends the message to the appropriate coin pool. See "Setting up blocknotify" below to
  168. set up your daemon to use this feature. */
  169. "blockNotifyListener": {
  170. "enabled": true,
  171. "port": 8117,
  172. "password": "test"
  173. },
  174. /* With this enabled, the master process will listen on the configured port for messages from
  175. the 'scripts/coinSwitch.js' script which will trigger your proxy pools to switch to the
  176. specified coin (non-case-sensitive). This setting is used in conjuction with the proxy
  177. feature below. */
  178. "coinSwitchListener": {
  179. "enabled": false,
  180. "port": 8118,
  181. "password": "test"
  182. },
  183. /* In a proxy configuration, you can setup ports that accept miners for work based on a
  184. specific algorithm instead of a specific coin. Miners that connect to these ports are
  185. automatically switched a coin determined by the server. The default coin is the first
  186. configured pool for each algorithm and coin switching can be triggered using the
  187. coinSwitch.js script in the scripts folder.
  188. Please note miner address authentication must be disabled when using NOMP in a proxy
  189. configuration and that payout processing is left up to the server administrator. */
  190. "proxy": {
  191. "sha256": {
  192. "enabled": false,
  193. "port": "3333",
  194. "diff": 10,
  195. "varDiff": {
  196. "minDiff": 16, //Minimum difficulty
  197. "maxDiff": 512, //Network difficulty will be used if it is lower than this
  198. "targetTime": 15, //Try to get 1 share per this many seconds
  199. "retargetTime": 90, //Check to see if we should retarget every this many seconds
  200. "variancePercent": 30 //Allow time to very this % from target without retargeting
  201. }
  202. },
  203. "scrypt": {
  204. "enabled": false,
  205. "port": "4444",
  206. "diff": 10,
  207. "varDiff": {
  208. "minDiff": 16, //Minimum difficulty
  209. "maxDiff": 512, //Network difficulty will be used if it is lower than this
  210. "targetTime": 15, //Try to get 1 share per this many seconds
  211. "retargetTime": 90, //Check to see if we should retarget every this many seconds
  212. "variancePercent": 30 //Allow time to very this % from target without retargeting
  213. }
  214. },
  215. "scrypt-n": {
  216. "enabled": false,
  217. "port": "5555"
  218. }
  219. }
  220. }
  221. ````
  222. ##### Coin config
  223. Inside the `coins` directory, ensure a json file exists for your coin. If it does not you will have to create it.
  224. Here is an example of the required fields:
  225. ````javascript
  226. {
  227. "name": "Litecoin",
  228. "symbol": "ltc",
  229. "algorithm": "scrypt", //or "sha256", "scrypt-jane", "scrypt-n", "quark", "x11"
  230. "txMessages": false, //or true (not required, defaults to false)
  231. "mposDiffMultiplier": 256, //only for x11 coins in mpos mode, set to 256 (optional)
  232. }
  233. ````
  234. For additional documentation how to configure coins *(especially important for scrypt-n and scrypt-jane coins)*
  235. see [these instructions](//github.com/zone117x/node-stratum-pool#module-usage).
  236. ##### Pool config
  237. Take a look at the example json file inside the `pool_configs` directory. Rename it to `yourcoin.json` and change the
  238. example fields to fit your setup.
  239. Description of options:
  240. ````javascript
  241. {
  242. "enabled": true, //Set this to false and a pool will not be created from this config file
  243. "coin": "litecoin.json", //Reference to coin config file in 'coins' directory
  244. "address": "mi4iBXbBsydtcc5yFmsff2zCFVX4XG7qJc", //Address to where block rewards are given
  245. "blockRefreshInterval": 1000, //How often to poll RPC daemons for new blocks, in milliseconds
  246. /* How many milliseconds should have passed before new block transactions will trigger a new
  247. job broadcast. */
  248. "txRefreshInterval": 20000,
  249. /* Some miner software is bugged and will consider the pool offline if it doesn't receive
  250. anything for around a minute, so every time we broadcast jobs, set a timeout to rebroadcast
  251. in this many seconds unless we find a new job. Set to zero or remove to disable this. */
  252. "jobRebroadcastTimeout": 55,
  253. //instanceId: 37, //Recommend not using this because a crypto-random one will be generated
  254. /* Some attackers will create thousands of workers that use up all available socket connections,
  255. usually the workers are zombies and don't submit shares after connecting. This feature
  256. detects those and disconnects them. */
  257. "connectionTimeout": 600, //Remove workers that haven't been in contact for this many seconds
  258. /* Sometimes you want the block hashes even for shares that aren't block candidates. */
  259. "emitInvalidBlockHashes": false,
  260. /* We use proper maximum algorithm difficulties found in the coin daemon source code. Most
  261. miners/pools that deal with scrypt use a guesstimated one that is about 5.86% off from the
  262. actual one. So here we can set a tolerable threshold for if a share is slightly too low
  263. due to mining apps using incorrect max diffs and this pool using correct max diffs. */
  264. "shareVariancePercent": 10,
  265. /* Enable for client IP addresses to be detected when using a load balancer with TCP proxy
  266. protocol enabled, such as HAProxy with 'send-proxy' param:
  267. http://haproxy.1wt.eu/download/1.5/doc/configuration.txt */
  268. "tcpProxyProtocol": false,
  269. /* This determines what to do with submitted shares (and stratum worker authentication).
  270. You have two options:
  271. 1) Enable internal and disable mpos = this portal to handle all share payments.
  272. 2) Enable mpos and disable internal = shares will be inserted into MySQL database
  273. for MPOS to process. */
  274. "shareProcessing": {
  275. "internal": {
  276. "enabled": true,
  277. /* When workers connect, to receive payments, their address must be used as the worker
  278. name. If this option is true, on worker authentication, their address will be
  279. verified via a validateaddress API call to the daemon. Miners with invalid addresses
  280. will be rejected. */
  281. "validateWorkerAddress": true,
  282. /* Every this many seconds get submitted blocks from redis, use daemon RPC to check
  283. their confirmation status, if confirmed then get shares from redis that contributed
  284. to block and send out payments. */
  285. "paymentInterval": 30,
  286. /* Minimum number of coins that a miner must earn before sending payment. Typically,
  287. a higher minimum means less transactions fees (you profit more) but miners see
  288. payments less frequently (they dislike). Opposite for a lower minimum payment. */
  289. "minimumPayment": 0.001,
  290. /* Minimum number of coins to keep in pool wallet. It is recommended to deposit at
  291. at least this many coins into the pool wallet when first starting the pool. */
  292. "minimumReserve": 10,
  293. /* (2% default) What percent fee your pool takes from the block reward. */
  294. "feePercent": 0.02,
  295. /* Name of the daemon account to use when moving coin profit within daemon wallet. */
  296. "feeCollectAccount": "feesCollected",
  297. /* Your address that receives pool revenue from fees. */
  298. "feeReceiveAddress": "LZz44iyF4zLCXJTU8RxztyyJZBntdS6fvv",
  299. /* How many coins from fee revenue must accumulate on top of the
  300. minimum reserve amount in order to trigger withdrawal to fee address. The higher
  301. this threshold, the less of your profit goes to transactions fees. */
  302. "feeWithdrawalThreshold": 5,
  303. /* This daemon is used to send out payments. It MUST be for the daemon that owns the
  304. configured 'address' that receives the block rewards, otherwise the daemon will not
  305. be able to confirm blocks or send out payments. */
  306. "daemon": {
  307. "host": "127.0.0.1",
  308. "port": 19332,
  309. "user": "litecoinrpc",
  310. "password": "testnet"
  311. },
  312. /* Redis database used for storing share and block submission data. */
  313. "redis": {
  314. "host": "127.0.0.1",
  315. "port": 6379
  316. }
  317. },
  318. /* Enabled mpos and shares will be inserted into share table in a MySQL database. You may
  319. also want to use the "emitInvalidBlockHashes" option below if you require it. */
  320. "mpos": {
  321. "enabled": false,
  322. "host": "127.0.0.1", //MySQL db host
  323. "port": 3306, //MySQL db port
  324. "user": "me", //MySQL db user
  325. "password": "mypass", //MySQL db password
  326. "database": "ltc", //MySQL db database name
  327. /* For when miner's authenticate: set to "password" for both worker name and password to
  328. be checked for in the database, set to "worker" for only work name to be checked, or
  329. don't use this option (set to "none") for no auth checks */
  330. "stratumAuth": "password"
  331. }
  332. },
  333. /* If a worker is submitting a high threshold of invalid shares we can temporarily ban their IP
  334. to reduce system/network load. Also useful to fight against flooding attacks. If running
  335. behind something like HAProxy be sure to enable 'tcpProxyProtocol', otherwise you'll end up
  336. banning your own IP address (and therefore all workers). */
  337. "banning": {
  338. "enabled": true,
  339. "time": 600, //How many seconds to ban worker for
  340. "invalidPercent": 50, //What percent of invalid shares triggers ban
  341. "checkThreshold": 500, //Check invalid percent when this many shares have been submitted
  342. "purgeInterval": 300 //Every this many seconds clear out the list of old bans
  343. },
  344. /* Each pool can have as many ports for your miners to connect to as you wish. Each port can
  345. be configured to use its own pool difficulty and variable difficulty settings. varDiff is
  346. optional and will only be used for the ports you configure it for. */
  347. "ports": {
  348. "3032": { //A port for your miners to connect to
  349. "diff": 32, //the pool difficulty for this port
  350. /* Variable difficulty is a feature that will automatically adjust difficulty for
  351. individual miners based on their hashrate in order to lower networking overhead */
  352. "varDiff": {
  353. "minDiff": 8, //Minimum difficulty
  354. "maxDiff": 512, //Network difficulty will be used if it is lower than this
  355. "targetTime": 15, //Try to get 1 share per this many seconds
  356. "retargetTime": 90, //Check to see if we should retarget every this many seconds
  357. "variancePercent": 30 //Allow time to very this % from target without retargeting
  358. }
  359. },
  360. "3256": { //Another port for your miners to connect to, this port does not use varDiff
  361. "diff": 256 //The pool difficulty
  362. }
  363. },
  364. /* For redundancy, recommended to have at least two daemon instances running in case one
  365. drops out-of-sync or offline. */
  366. "daemons": [
  367. { //Main daemon instance
  368. "host": "127.0.0.1",
  369. "port": 19332,
  370. "user": "litecoinrpc",
  371. "password": "testnet"
  372. },
  373. { //Backup daemon instance
  374. "host": "127.0.0.1",
  375. "port": 19344,
  376. "user": "litecoinrpc",
  377. "password": "testnet"
  378. }
  379. ],
  380. /* This allows the pool to connect to the daemon as a node peer to receive block updates.
  381. It may be the most efficient way to get block updates (faster than polling, less
  382. intensive than blocknotify script). It requires additional setup: the 'magic' field must
  383. be exact (extracted from the coin source code). */
  384. "p2p": {
  385. "enabled": false,
  386. /* Host for daemon */
  387. "host": "127.0.0.1",
  388. /* Port configured for daemon (this is the actual peer port not RPC port) */
  389. "port": 19333,
  390. /* If your coin daemon is new enough (i.e. not a shitcoin) then it will support a p2p
  391. feature that prevents the daemon from spamming our peer node with unnecessary
  392. transaction data. Assume its supported but if you have problems try disabling it. */
  393. "disableTransactions": true,
  394. /* Magic value is different for main/testnet and for each coin. It is found in the daemon
  395. source code as the pchMessageStart variable.
  396. For example, litecoin mainnet magic: http://git.io/Bi8YFw
  397. And for litecoin testnet magic: http://git.io/NXBYJA */
  398. "magic": "fcc1b7dc"
  399. }
  400. }
  401. ````
  402. You can create as many of these pool config files as you want (such as one pool per coin you which to operate).
  403. If you are creating multiple pools, ensure that they have unique stratum ports.
  404. For more information on these configuration options see the [pool module documentation](https://github.com/zone117x/node-stratum-pool#module-usage)
  405. ##### [Optional, recommended] Setting up blocknotify
  406. 1. In `config.json` set the port and password for `blockNotifyListener`
  407. 2. In your daemon conf file set the `blocknotify` command to use:
  408. ```
  409. node [path to scripts/blockNotify.js] [listener host]:[listener port] [listener password] [coin name in config] %s
  410. ```
  411. Example: inside `dogecoin.conf` add the line
  412. ```
  413. blocknotify=node scripts/blockNotify.js 127.0.0.1:8117 mySuperSecurePassword dogecoin %s
  414. ```
  415. Alternatively, you can use a more efficient block notify script written in pure C. Build and usage instructions
  416. are commented in [scripts/blocknotify.c](scripts/blocknotify.c).
  417. #### 3) Start the portal
  418. ```bash
  419. node init.js
  420. ```
  421. ###### Optional enhancements for your awesome new mining pool server setup:
  422. * Use something like [forever](https://github.com/nodejitsu/forever) to keep the node script running
  423. in case the master process crashes.
  424. * Use something like [redis-commander](https://github.com/joeferner/redis-commander) to have a nice GUI
  425. for exploring your redis database.
  426. * Use something like [logrotator](http://www.thegeekstuff.com/2010/07/logrotate-examples/) to rotate log
  427. output from NOMP.
  428. * Use [New Relic](http://newrelic.com/) to monitor your NOMP instance and server performance.
  429. #### Upgrading NOMP
  430. When updating NOMP to the latest code its important to not only `git pull` the latest from this repo, but to also update the `node-statum-pool` module and any config files that may have been changed.
  431. * Inside your NOMP directory (where the init.js script is) do `git pull` to get the latest NOMP code.
  432. * Remove the dependenices by deleting the `node_modules` directory with `rm -r node_modules`.
  433. * Run `npm update` to force updating/reinstalling of the dependencies.
  434. * Compare your `config.json` and `pool_configs/coin.json` configurations to the latest example ones in this repo or the ones in the setup instructions where each config field is explained. You may need to modify or add any new changes.
  435. Donations
  436. ---------
  437. To support development of this project feel free to donate :)
  438. * BTC: `1KRotMnQpxu3sePQnsVLRy3EraRFYfJQFR`
  439. * LTC: `LKfavSDJmwiFdcgaP1bbu46hhyiWw5oFhE`
  440. * VTC: `VgW4uFTZcimMSvcnE4cwS3bjJ6P8bcTykN`
  441. * MAX: `mWexUXRCX5PWBmfh34p11wzS5WX2VWvTRT`
  442. * QRK: `QehPDAhzVQWPwDPQvmn7iT3PoFUGT7o8bC`
  443. * DRK: `XcQmhp8ANR7okWAuArcNFZ2bHSB81jpapQ`
  444. * DOGE: `DBGGVtwAAit1NPZpRm5Nz9VUFErcvVvHYW`
  445. * Cryptsy Trade Key: `254ca13444be14937b36c44ba29160bd8f02ff76`
  446. Credits
  447. -------
  448. * [Jerry Brady / mintyfresh68](https://github.com/bluecircle) - got coin-switching fully working and developed proxy-per-algo feature
  449. * [Tony Dobbs](http://anthonydobbs.com) - designs for front-end and created the NOMP logo
  450. * [LucasJones(//github.com/LucasJones) - getting p2p block notify script working
  451. * [vekexasia](//github.com/vekexasia) - co-developer & great tester
  452. * [TheSeven](//github.com/TheSeven) - answering an absurd amount of my questions and being a very helpful gentleman
  453. * [UdjinM6](//github.com/UdjinM6) - helped implement fee withdrawal in payment processing
  454. * [Alex Petrov / sysmanalex](https://github.com/sysmanalex) - contributed the pure C block notify script
  455. * [svirusxxx](//github.com/svirusxxx) - sponsored development of MPOS mode
  456. * [icecube45](//github.com/icecube45) - helping out with the repo wiki
  457. * Those that contributed to [node-stratum-pool](//github.com/zone117x/node-stratum-pool#credits)
  458. License
  459. -------
  460. Released under the GNU General Public License v2
  461. http://www.gnu.org/licenses/gpl-2.0.html