This commit is contained in:
Matt 2014-03-14 16:00:23 -06:00
commit 818fd3385d
7 changed files with 195 additions and 31 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules/ node_modules/
.idea/ .idea/
pool_configs/

View File

@ -2,15 +2,57 @@
"logLevel": "debug", "logLevel": "debug",
"clustering": { "clustering": {
"enabled": true, "enabled": true,
"forks": "auto" "forks": "1"
}, },
"blockNotifyListener": { "blockNotifyListener": {
"enabled": true, "enabled": false,
"port": 8117, "port": 8117,
"password": "test" "password": "test"
}, },
"website": {
"redisBlockNotifyListener": {
"enabled" : false,
"redisPort" : 6379,
"redisHost" : "hostname",
"psubscribeKey" : "newblocks:*"
},
"proxy": {
"enabled": true, "enabled": true,
"ports": {
"80": {
"diff": 32,
"varDiff": {
"minDiff" : 8,
"maxDiff" : 512,
"targetTime" : 15,
"retargetTime" : 90,
"variancePercent" : 30
}
},
"6000": {
"diff": 32,
"varDiff": {
"minDiff" : 8,
"maxDiff" : 512,
"targetTime" : 15,
"retargetTime" : 90,
"variancePercent" : 30
}
},
"8080": {
"diff": 32,
"varDiff": {
"minDiff" : 8,
"maxDiff" : 512,
"targetTime" : 15,
"retargetTime" : 90,
"variancePercent" : 30
}
}
}
},
"website": {
"enabled": false,
"port": 80, "port": 80,
"liveStats": true "liveStats": true
} }

64
init.js
View File

@ -3,19 +3,18 @@ var os = require('os');
var cluster = require('cluster'); var cluster = require('cluster');
var posix = require('posix'); var posix = require('posix');
var PoolLogger = require('./libs/logUtil.js'); var PoolLogger = require('./libs/logUtil.js');
var BlocknotifyListener = require('./libs/blocknotifyListener.js'); var BlocknotifyListener = require('./libs/blocknotifyListener.js');
var WorkerListener = require('./libs/workerListener.js'); var RedisBlocknotifyListener = require('./libs/redisblocknotifyListener.js');
var PoolWorker = require('./libs/poolWorker.js'); var WorkerListener = require('./libs/workerListener.js');
var PaymentProcessor = require('./libs/paymentProcessor.js'); var PoolWorker = require('./libs/poolWorker.js');
var Website = require('./libs/website.js'); var PaymentProcessor = require('./libs/paymentProcessor.js');
var Website = require('./libs/website.js');
JSON.minify = JSON.minify || require("node-json-minify"); JSON.minify = JSON.minify || require("node-json-minify");
var portalConfig = JSON.parse(JSON.minify(fs.readFileSync("config.json", {encoding: 'utf8'}))); var portalConfig = JSON.parse(JSON.minify(fs.readFileSync("config.json", {encoding: 'utf8'})));
var loggerInstance = new PoolLogger({ var loggerInstance = new PoolLogger({
logLevel: portalConfig.logLevel logLevel: portalConfig.logLevel
@ -37,7 +36,7 @@ catch(e){
if (cluster.isWorker){ if (cluster.isWorker){
switch(process.env.workerType){ switch(process.env.workerType){
case 'pool': case 'pool':
new PoolWorker(loggerInstance); new PoolWorker(loggerInstance);
@ -51,7 +50,18 @@ if (cluster.isWorker){
} }
return; return;
} } /* else {
var coinNames = ['alphacoin','frankocoin','emerald','kittehcoin'];
var curIndex = 0;
setInterval(function () {
var newCoinName = coinNames[++curIndex % coinNames.length];
console.log("SWITCHING to "+newCoinName);
var ipcMessage = {type:'switch', coin: newCoinName};
Object.keys(cluster.workers).forEach(function(id) {
cluster.workers[id].send(ipcMessage);
});
}, 20000);
} */
@ -93,9 +103,10 @@ var spawnPoolWorkers = function(portalConfig, poolConfigs){
var createPoolWorker = function(forkId){ var createPoolWorker = function(forkId){
var worker = cluster.fork({ var worker = cluster.fork({
workerType: 'pool', workerType : 'pool',
forkId: forkId, forkId : forkId,
pools: serializedConfigs pools : serializedConfigs,
portalConfig : JSON.stringify(portalConfig),
}); });
worker.on('exit', function(code, signal){ worker.on('exit', function(code, signal){
logError('poolWorker', 'system', 'Fork ' + forkId + ' died, spawning replacement worker...'); logError('poolWorker', 'system', 'Fork ' + forkId + ' died, spawning replacement worker...');
@ -136,6 +147,21 @@ var startBlockListener = function(portalConfig){
listener.start(); listener.start();
}; };
var startRedisBlockListener = function(portalConfig){
//block notify options
//setup block notify here and use IPC to tell appropriate pools
var listener = new RedisBlocknotifyListener(portalConfig.redisBlockNotifyListener);
listener.on('log', function(text){
logDebug('blocknotify', 'system', text);
}).on('hash', function (message) {
var ipcMessage = {type:'blocknotify', coin: message.coin, hash: message.hash};
Object.keys(cluster.workers).forEach(function(id) {
cluster.workers[id].send(ipcMessage);
});
});
listener.start();
};
var startPaymentProcessor = function(poolConfigs){ var startPaymentProcessor = function(poolConfigs){
var worker = cluster.fork({ var worker = cluster.fork({
@ -152,6 +178,8 @@ var startPaymentProcessor = function(poolConfigs){
var startWebsite = function(portalConfig, poolConfigs){ var startWebsite = function(portalConfig, poolConfigs){
console.log(portalConfig.website);
if (!portalConfig.website.enabled) return; if (!portalConfig.website.enabled) return;
var worker = cluster.fork({ var worker = cluster.fork({
@ -168,7 +196,6 @@ var startWebsite = function(portalConfig, poolConfigs){
}; };
(function init(){ (function init(){
var poolConfigs = buildPoolConfigs(); var poolConfigs = buildPoolConfigs();
@ -179,8 +206,11 @@ var startWebsite = function(portalConfig, poolConfigs){
startBlockListener(portalConfig); startBlockListener(portalConfig);
startRedisBlockListener(portalConfig);
startWorkerListener(poolConfigs); startWorkerListener(poolConfigs);
;
startWebsite(portalConfig, poolConfigs); startWebsite(portalConfig, poolConfigs);
})(); })();

View File

@ -53,12 +53,12 @@ var PoolLogger = function (configuration) {
var desc = poolName ? '[' + poolName + '] ' : ''; var desc = poolName ? '[' + poolName + '] ' : '';
console.log( console.log(
'\u001b[' + getSeverityColor(severity) + 'm' + '\u001b['+getSeverityColor(severity)+'m' +
dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss') + dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss') +
" [" + key + "]" + '\u001b[39m: ' + "\t" + " ["+key+"]" + '\u001b[39m: ' + "\t" +
desc + text desc +
); text);
}; }
// public // public

View File

@ -1,4 +1,6 @@
var Stratum = require('stratum-pool'); var Stratum = require('stratum-pool');
var Vardiff = require('stratum-pool/lib/varDiff.js');
var net = require('net');
var MposCompatibility = require('./mposCompatibility.js'); var MposCompatibility = require('./mposCompatibility.js');
var ShareProcessor = require('./shareProcessor.js'); var ShareProcessor = require('./shareProcessor.js');
@ -6,11 +8,15 @@ var ShareProcessor = require('./shareProcessor.js');
module.exports = function(logger){ module.exports = function(logger){
var poolConfigs = JSON.parse(process.env.pools); var poolConfigs = JSON.parse(process.env.pools);
var forkId = process.env.forkId; var portalConfig = JSON.parse(process.env.portalConfig);
var pools = {}; var forkId = process.env.forkId;
var pools = {};
var varDiffsInstances = {}; // contains all the vardiffs for the profit switching pool
var proxyStuff = {}
//Handle messages from master process sent via IPC //Handle messages from master process sent via IPC
process.on('message', function(message) { process.on('message', function(message) {
switch(message.type){ switch(message.type){
@ -18,6 +24,23 @@ module.exports = function(logger){
var pool = pools[message.coin.toLowerCase()] var pool = pools[message.coin.toLowerCase()]
if (pool) pool.processBlockNotify(message.hash) if (pool) pool.processBlockNotify(message.hash)
break; break;
case 'switch':
var newCoinPool = pools[message.coin.toLowerCase()];
if (newCoinPool) {
var oldPool = pools[proxyStuff.curActivePool];
oldPool.relinquishMiners(
function (miner, cback) {
// relinquish miners that are attached to one of the "Auto-switch" ports and leave the others there.
cback(typeof(portalConfig.proxy.ports[miner.client.socket.localPort]) !== 'undefined')
},
function (clients) {
newCoinPool.attachMiners(clients);
proxyStuff.curActivePool = message.coin.toLowerCase();
}
)
}
break;
} }
}); });
@ -131,4 +154,36 @@ module.exports = function(logger){
pool.start(); pool.start();
pools[poolOptions.coin.name.toLowerCase()] = pool; pools[poolOptions.coin.name.toLowerCase()] = pool;
}); });
if (typeof(portalConfig.proxy) !== 'undefined' && portalConfig.proxy.enabled === true) {
proxyStuff.curActivePool = Object.keys(pools)[0];
proxyStuff.proxys = {};
proxyStuff.varDiffs = {};
Object.keys(portalConfig.proxy.ports).forEach(function(port) {
proxyStuff.varDiffs[port] = new Vardiff(port, portalConfig.proxy.ports[port].varDiff);
});
Object.keys(pools).forEach(function (coinName) {
var p = pools[coinName];
Object.keys(proxyStuff.varDiffs).forEach(function(port) {
p.setVarDiff(port, proxyStuff.varDiffs[port]);
});
});
Object.keys(portalConfig.proxy.ports).forEach(function (port) {
proxyStuff.proxys[port] = net
.createServer({allowHalfOpen: true}, function(socket) {
console.log(proxyStuff.curActivePool);
pools[proxyStuff.curActivePool].getStratumServer().handleNewClient(socket);
} )
.listen(parseInt(port), function(){
console.log("Proxy listening on "+port);
});
});
}
}; };

View File

@ -0,0 +1,36 @@
var events = require('events');
var redis = require('redis');
var listener = module.exports = function listener(options){
var _this = this;
var redisConnection;
var emitLog = function(text){
_this.emit('log', text);
};
this.start = function(){
redisConnection = redis.createClient(options.redisPort, options.redisHost);
redisConnection.on("pmessage", function (pattern, channel, message) {
var coinname = channel.split(':')[1];
var blockhash = message;
//emitLog("Redis: Received block for "+coinname+" - hash: "+blockhash);
_this.emit('hash', {
"coin" : coinname,
"hash" : blockhash
});
});
redisConnection.on('connect', function (err, data) {
emitLog("Redis connected");
});
redisConnection.psubscribe(options.psubscribeKey);
emitLog("Connecting to redis!");
}
};
listener.prototype.__proto__ = events.EventEmitter.prototype;

View File

@ -1,5 +1,5 @@
{ {
"disabled": false, "disabled": true,
"coin": "litecoin.json", "coin": "litecoin.json",
"shareProcessing": { "shareProcessing": {