Changed all references to localhost to 127.0.0.1 for better system compatibility. Implemented thread-wide IP banning via IPC. Added redis config for portal-wide related db interactions (stats and proxy)

This commit is contained in:
Matt 2014-04-15 16:38:51 -06:00
parent 790cffb0c4
commit 4888aaffba
10 changed files with 101 additions and 72 deletions

View File

@ -2,10 +2,34 @@
#### Node Open Mining Portal
This portal is an extremely efficient, highly scalable, all-in-one, easy to setup cryptocurrency mining pool written
entirely in Node.js. It contains a stratum poolserver, reward/payment/share processor, and a (*not yet completed*)
front-end website.
entirely in Node.js. It contains a stratum poolserver; reward/payment/share processor; and a (*not yet completed*)
responsive user-friendly front-end website featuring mining instructions, in-depth live statistics, and an admin center.
#### Features
#### Table of Contents
* [Features](#features)
* [Attack Mitigation](##attack-mitigation)
* [Security](#security)
* [Planned Features](#planned-features)
* [Community Support](#community--support)
* [Usage](#usage)
* [Requirements](#requirements)
* [Setting Up Coin Daemon](#0-setting-up-coin-daemon)
* [Downloading & Installing](#1-downloading--installing)
* [Configuration](#2-configuration)
* [Portal Config](#portal-config)
* [Coin Config](#coin-config)
* [Pool Config](#pool-config)
* [Setting Up Blocknotify](#optional-recommended-setting-up-blocknotify)
* [Starting the Portal](#3-start-the-portal)
* [Upgrading NOMP](#upgrading-nomp)
* [Donations](#donations)
* [Credits](#credits)
* [License](#license)
### Features
* For the pool server it uses the highly efficient [node-stratum-pool](//github.com/zone117x/node-stratum-pool) module which
supports vardiff, POW & POS, transaction messages, anti-DDoS, IP banning, [several hashing algorithms](//github.com/zone117x/node-stratum-pool#hashing-algorithms-supported).
@ -64,7 +88,7 @@ allow your own pool to connect upstream to a larger pool server. It will request
redistribute the work to our own connected miners.
#### Community / Support
### Community / Support
IRC
* Support / general discussion join #nomp: https://webchat.freenode.net/?channels=#nomp
* Development discussion join #nomp-dev: https://webchat.freenode.net/?channels=#nomp-dev
@ -80,8 +104,11 @@ If your pool uses NOMP let us know and we will list your website here.
* http://chunkypools.com
* http://clevermining.com
* http://rapidhash.net
* http://suchpool.pw
* http://hashfaster.com
* http://miningpoolhub.com
* http://kryptochaos.com
* http://pool.uberpools.org
Usage
@ -156,12 +183,7 @@ Explanation for each field:
/* How many seconds to hold onto historical stats. Currently set to 24 hours. */
"historicalRetention": 43200,
/* How many seconds worth of shares should be gathered to generate hashrate. */
"hashrateWindow": 300,
/* Redis instance of where to store historical stats. */
"redis": {
"host": "localhost",
"port": 6379
}
"hashrateWindow": 300
},
/* Not done yet. */
"adminCenter": {
@ -170,6 +192,13 @@ Explanation for each field:
}
},
/* Redis instance of where to store global portal data such as historical stats, proxy states,
ect.. */
"redis": {
"host": "127.0.0.1",
"port": 6379
},
/* With this enabled, the master process listen on the configured port for messages from the
'scripts/blockNotify.js' script which your coin daemons can be configured to run when a
new block is available. When a blocknotify message is received, the master process uses
@ -290,6 +319,12 @@ Description of options:
due to mining apps using incorrect max diffs and this pool using correct max diffs. */
"shareVariancePercent": 10,
/* Enable for client IP addresses to be detected when using a load balancer with TCP proxy
protocol enabled, such as HAProxy with 'send-proxy' param:
http://haproxy.1wt.eu/download/1.5/doc/configuration.txt */
"tcpProxyProtocol": false,
/* This determines what to do with submitted shares (and stratum worker authentication).
You have two options:
1) Enable internal and disable mpos = this portal to handle all share payments.
@ -338,7 +373,7 @@ Description of options:
configured 'address' that receives the block rewards, otherwise the daemon will not
be able to confirm blocks or send out payments. */
"daemon": {
"host": "localhost",
"host": "127.0.0.1",
"port": 19332,
"user": "litecoinrpc",
"password": "testnet"
@ -346,7 +381,7 @@ Description of options:
/* Redis database used for storing share and block submission data. */
"redis": {
"host": "localhost",
"host": "127.0.0.1",
"port": 6379
}
},
@ -355,7 +390,7 @@ Description of options:
also want to use the "emitInvalidBlockHashes" option below if you require it. */
"mpos": {
"enabled": false,
"host": "localhost", //MySQL db host
"host": "127.0.0.1", //MySQL db host
"port": 3306, //MySQL db port
"user": "me", //MySQL db user
"password": "mypass", //MySQL db password
@ -368,8 +403,10 @@ Description of options:
}
},
/* If a worker is submitting a high threshold of invalid shares we can temporarily ban them
to reduce system/network load. Also useful to fight against flooding attacks. */
/* If a worker is submitting a high threshold of invalid shares we can temporarily ban their IP
to reduce system/network load. Also useful to fight against flooding attacks. The worker's
If running behind something like HAProxy be sure to enable the TCP Proxy Protocol config,
otherwise you'll end up banning your own IP address (and therefore all workers). */
"banning": {
"enabled": true,
"time": 600, //How many seconds to ban worker for
@ -404,13 +441,13 @@ Description of options:
drops out-of-sync or offline. */
"daemons": [
{ //Main daemon instance
"host": "localhost",
"host": "127.0.0.1",
"port": 19332,
"user": "litecoinrpc",
"password": "testnet"
},
{ //Backup daemon instance
"host": "localhost",
"host": "127.0.0.1",
"port": 19344,
"user": "litecoinrpc",
"password": "testnet"
@ -423,7 +460,7 @@ Description of options:
intensive than blocknotify script). However its still under development (not yet working). */
"p2p": {
"enabled": false,
"host": "localhost",
"host": "127.0.0.1",
"port": 19333,
/* Magic value is different for main/testnet and for each coin. It is found in the daemon
@ -455,7 +492,7 @@ node [path to scripts/blockNotify.js] [listener host]:[listener port] [listener
```
Example: inside `dogecoin.conf` add the line
```
blocknotify="node scripts/blockNotify.js localhost:8117 mySuperSecurePassword dogecoin %s"
blocknotify="node scripts/blockNotify.js 127.0.0.1:8117 mySuperSecurePassword dogecoin %s"
```
Alternatively, you can use a more efficient block notify script written in pure C. Build and usage instructions
@ -506,7 +543,8 @@ Credits
* [TheSeven](//github.com/TheSeven) - answering an absurd amount of my questions and being a very helpful gentleman
* [UdjinM6](//github.com/UdjinM6) - helped implement fee withdrawal in payment processing
* [Alex Petrov / sysmanalex](https://github.com/sysmanalex) - contributed the pure C block notify script
* Those that contributed to [node-stratum-pool](//github.com/zone117x/node-stratum-pool)
* [svirusxxx](//github.com/svirusxxx) - sponsored development of MPOS mode
* Those that contributed to [node-stratum-pool](//github.com/zone117x/node-stratum-pool#credits)
License

View File

@ -13,11 +13,7 @@
"stats": {
"updateInterval": 60,
"historicalRetention": 43200,
"hashrateWindow": 300,
"redis": {
"host": "localhost",
"port": 6379
}
"hashrateWindow": 300
},
"adminCenter": {
"enabled": true,
@ -25,6 +21,11 @@
}
},
"redis": {
"host": "127.0.0.1",
"port": 6379
},
"blockNotifyListener": {
"enabled": false,
"port": 8117,

23
init.js
View File

@ -8,7 +8,6 @@ var PoolLogger = require('./libs/logUtil.js');
var BlocknotifyListener = require('./libs/blocknotifyListener.js');
var CoinswitchListener = require('./libs/coinswitchListener.js');
var RedisBlocknotifyListener = require('./libs/redisblocknotifyListener.js');
var WorkerListener = require('./libs/workerListener.js');
var PoolWorker = require('./libs/poolWorker.js');
var PaymentProcessor = require('./libs/paymentProcessor.js');
var Website = require('./libs/website.js');
@ -139,6 +138,7 @@ var spawnPoolWorkers = function(portalConfig, poolConfigs){
return portalConfig.clustering.forks;
})();
var poolWorkers = {};
var createPoolWorker = function(forkId){
var worker = cluster.fork({
@ -147,11 +147,24 @@ var spawnPoolWorkers = function(portalConfig, poolConfigs){
pools: serializedConfigs,
portalConfig: JSON.stringify(portalConfig)
});
worker.forkId = forkId;
worker.type = 'pool';
poolWorkers[forkId] = worker;
worker.on('exit', function(code, signal){
logger.error('Master', 'PoolSpanwer', 'Fork ' + forkId + ' died, spawning replacement worker...');
setTimeout(function(){
createPoolWorker(forkId);
}, 2000);
}).on('message', function(msg){
switch(msg.type){
case 'banIP':
Object.keys(cluster.workers).forEach(function(id) {
if (cluster.workers[id].type === 'pool'){
cluster.workers[id].send({type: 'banIP', ip: msg.ip});
}
});
break;
}
});
};
@ -168,12 +181,6 @@ var spawnPoolWorkers = function(portalConfig, poolConfigs){
};
var startWorkerListener = function(poolConfigs){
var workerListener = new WorkerListener(logger, poolConfigs);
workerListener.init();
};
var startBlockListener = function(portalConfig){
//block notify options
//setup block notify here and use IPC to tell appropriate pools
@ -301,8 +308,6 @@ var startWebsite = function(portalConfig, poolConfigs){
startRedisBlockListener(portalConfig);
startWorkerListener(poolConfigs);
startWebsite(portalConfig, poolConfigs);
})();

View File

@ -41,7 +41,7 @@ module.exports = function(logger, poolConfig){
connection.query(
'SELECT password FROM pool_worker WHERE username = LOWER(?)',
[workerName],
[workerName.toLowerCase()],
function(err, result){
if (err){
logger.error(logIdentify, logComponent, 'Database error when authenticating worker: ' +

View File

@ -22,6 +22,13 @@ module.exports = function(logger){
process.on('message', function(message) {
switch(message.type){
case 'banIP':
for (var p in pools){
if (pools[p].stratumServer)
pools[p].stratumServer.addBannedIP(message.ip);
}
break;
case 'blocknotify':
var messageCoin = message.coin.toLowerCase();
@ -75,7 +82,7 @@ module.exports = function(logger){
);
proxySwitch[algo].currentPool = newCoin;
var redisClient = redis.createClient(6379, "localhost")
var redisClient = redis.createClient(portalConfig.redis.port, portalConfig.redis.host)
redisClient.on('ready', function(){
redisClient.hset('proxyState', algo, newCoin, function(error, obj) {
if (error) {
@ -186,6 +193,8 @@ module.exports = function(logger){
handlers.diff(workerName, diff);
}).on('log', function(severity, text) {
logger[severity](logSystem, logComponent, logSubCat, text);
}).on('banIP', function(ip, worker){
process.send({type: 'banIP', ip: ip});
});
pool.start();
@ -206,7 +215,7 @@ module.exports = function(logger){
// on the last pool it was using when reloaded or restarted
//
logger.debug(logSystem, logComponent, logSubCat, 'Loading last proxy state from redis');
var redisClient = redis.createClient(6379, "localhost")
var redisClient = redis.createClient(portalConfig.redis.port, portalConfig.redis.host)
redisClient.on('ready', function(){
redisClient.hgetall("proxyState", function(error, obj) {
if (error || obj == null) {

View File

@ -59,7 +59,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
function setupStatsRedis(){
redisStats = redis.createClient(portalConfig.website.stats.redis.port, portalConfig.website.stats.redis.host);
redisStats = redis.createClient(portalConfig.redis.port, portalConfig.redis.host);
redisStats.on('error', function(err){
logger.error(logSystem, 'Historics', 'Redis for stats had an error ' + JSON.stringify(err));
});

View File

@ -1,26 +0,0 @@
var events = require('events');
var cluster = require('cluster');
var MposCompatibility = require('./mposCompatibility.js');
var ShareProcessor = require('./shareProcessor.js');
var processor = module.exports = function processor(logger, poolConfigs){
var _this = this;
this.init = function(){
Object.keys(cluster.workers).forEach(function(id) {
cluster.workers[id].on('message', function(data){
switch(data.type){
}
});
});
}
};
processor.prototype.__proto__ = events.EventEmitter.prototype;

View File

@ -10,6 +10,8 @@
"emitInvalidBlockHashes": false,
"shareVariancePercent": 15,
"tcpProxyProtocol": false,
"shareProcessing": {
"internal": {
"enabled": true,
@ -22,19 +24,19 @@
"feeReceiveAddress": "mppaGeNaSbG1Q7S6V3gL5uJztMhucgL9Vh",
"feeWithdrawalThreshold": 5,
"daemon": {
"host": "localhost",
"host": "127.0.0.1",
"port": 19332,
"user": "litecoinrpc",
"password": "testnet"
},
"redis": {
"host": "localhost",
"host": "127.0.0.1",
"port": 6379
}
},
"mpos": {
"enabled": false,
"host": "localhost",
"host": "127.0.0.1",
"port": 3306,
"user": "me",
"password": "mypass",
@ -72,13 +74,13 @@
"daemons": [
{
"host": "localhost",
"host": "127.0.0.1",
"port": 19332,
"user": "litecoinrpc",
"password": "testnet"
},
{
"host": "localhost",
"host": "127.0.0.1",
"port": 19344,
"user": "litecoinrpc",
"password": "testnet"
@ -87,7 +89,7 @@
"p2p": {
"enabled": false,
"host": "localhost",
"host": "127.0.0.1",
"port": 19333,
"protocolVersion": 70002,
"magic": "fcc1b7dc"

View File

@ -1,6 +1,6 @@
/*
This script should be hooked to the coin daemon as follow:
litecoind -blocknotify="node /path/to/this/script/blockNotify.js localhost:8117 password litecoin %s"
litecoind -blocknotify="node /path/to/this/script/blockNotify.js 127.0.0.1:8117 password litecoin %s"
The above will send tell litecoin to launch this script with those parameters every time a block is found.
This script will then send the blockhash along with other information to a listening tcp socket
*/

View File

@ -2,7 +2,7 @@
This script demonstrates sending a coin switch request and can be invoked from the command line
with:
"node coinSwitch.js localhost:8118 password %s"
"node coinSwitch.js 127.0.0.1:8118 password %s"
where <%s> is the name of the coin proxy miners will be switched onto.