mirror of https://github.com/BTCPrivate/z-nomp.git
Replaced various listeners (coinswitch and blocknotify) with united NOMP CLI (command-line interface)
This commit is contained in:
parent
35772fd780
commit
952c7105cc
35
README.md
35
README.md
|
@ -113,7 +113,8 @@ If your pool uses NOMP let us know and we will list your website here.
|
|||
* http://kryptochaos.com
|
||||
* http://pool.uberpools.org
|
||||
* http://onebtcplace.com
|
||||
* https://minr.es
|
||||
* http://minr.es
|
||||
* http://mining.theminingpools.com
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
@ -167,6 +168,11 @@ Explanation for each field:
|
|||
will also be logged. */
|
||||
"logLevel": "debug", //or "warning", "error"
|
||||
|
||||
|
||||
/* The NOMP CLI (command-line interface) will listen for commands on this port. For example,
|
||||
blocknotify messages are sent to NOMP through this. */
|
||||
"cliPort": 17117,
|
||||
|
||||
/* By default 'forks' is set to "auto" which will spawn one process/fork/worker for each CPU
|
||||
core in your system. Each of these workers will run a separate instance of your pool(s),
|
||||
and the kernel will load balance miners using these forks. Optionally, the 'forks' field
|
||||
|
@ -205,33 +211,12 @@ Explanation for each field:
|
|||
"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
|
||||
IPC (inter-process communication) to notify each thread about the message. Each thread
|
||||
then sends the message to the appropriate coin pool. See "Setting up blocknotify" below to
|
||||
set up your daemon to use this feature. */
|
||||
"blockNotifyListener": {
|
||||
"enabled": true,
|
||||
"port": 8117,
|
||||
"password": "test"
|
||||
},
|
||||
|
||||
/* With this enabled, the master process will listen on the configured port for messages from
|
||||
the 'scripts/coinSwitch.js' script which will trigger your proxy pools to switch to the
|
||||
specified coin (non-case-sensitive). This setting is used in conjuction with the proxy
|
||||
feature below. */
|
||||
"coinSwitchListener": {
|
||||
"enabled": false,
|
||||
"port": 8118,
|
||||
"password": "test"
|
||||
},
|
||||
|
||||
/* In a proxy configuration, you can setup ports that accept miners for work based on a
|
||||
specific algorithm instead of a specific coin. Miners that connect to these ports are
|
||||
automatically switched a coin determined by the server. The default coin is the first
|
||||
configured pool for each algorithm and coin switching can be triggered using the
|
||||
coinSwitch.js script in the scripts folder.
|
||||
cli.js script in the scripts folder.
|
||||
|
||||
Please note miner address authentication must be disabled when using NOMP in a proxy
|
||||
configuration and that payout processing is left up to the server administrator. */
|
||||
|
@ -505,11 +490,11 @@ For more information on these configuration options see the [pool module documen
|
|||
1. In `config.json` set the port and password for `blockNotifyListener`
|
||||
2. In your daemon conf file set the `blocknotify` command to use:
|
||||
```
|
||||
node [path to scripts/blockNotify.js] [listener host]:[listener port] [listener password] [coin name in config] %s
|
||||
node [path to cli.js] [coin name in config] [block hash symbol]
|
||||
```
|
||||
Example: inside `dogecoin.conf` add the line
|
||||
```
|
||||
blocknotify=node scripts/blockNotify.js 127.0.0.1:8117 mySuperSecurePassword dogecoin %s
|
||||
blocknotify=node /home/nomp/scripts/cli.js blocknotify dogecoin %s
|
||||
```
|
||||
|
||||
Alternatively, you can use a more efficient block notify script written in pure C. Build and usage instructions
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"name": "Ecoin",
|
||||
"symbol": "ECN",
|
||||
"algorithm": "keccak",
|
||||
"normalHashing": true,
|
||||
"diffShift": 32
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"logLevel": "debug",
|
||||
|
||||
"cliPort": 17117,
|
||||
|
||||
"clustering": {
|
||||
"enabled": true,
|
||||
"forks": "auto"
|
||||
|
@ -26,23 +28,12 @@
|
|||
"port": 6379
|
||||
},
|
||||
|
||||
"blockNotifyListener": {
|
||||
"switching": {
|
||||
"switch1": {
|
||||
"enabled": false,
|
||||
"port": 8117,
|
||||
"password": "test"
|
||||
},
|
||||
|
||||
"coinSwitchListener": {
|
||||
"enabled": false,
|
||||
"host": "127.0.0.1",
|
||||
"port": 8118,
|
||||
"password": "test"
|
||||
},
|
||||
|
||||
"proxy": {
|
||||
"sha256": {
|
||||
"enabled": false,
|
||||
"port": "3333",
|
||||
"algorithm": "sha256",
|
||||
"ports": {
|
||||
"3333": {
|
||||
"diff": 10,
|
||||
"varDiff": {
|
||||
"minDiff": 16,
|
||||
|
@ -51,10 +42,14 @@
|
|||
"retargetTime": 90,
|
||||
"variancePercent": 30
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrypt": {
|
||||
"switch2": {
|
||||
"enabled": false,
|
||||
"port": "4444",
|
||||
"algorithm": "scrypt",
|
||||
"ports": {
|
||||
"4444": {
|
||||
"diff": 10,
|
||||
"varDiff": {
|
||||
"minDiff": 16,
|
||||
|
@ -63,10 +58,17 @@
|
|||
"retargetTime": 90,
|
||||
"variancePercent": 30
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrypt-n": {
|
||||
"switch3": {
|
||||
"enabled": false,
|
||||
"port": "5555"
|
||||
"algorithm": "x11",
|
||||
"ports": {
|
||||
"5555": {
|
||||
"diff": 0.001
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
103
init.js
103
init.js
|
@ -5,8 +5,7 @@ var cluster = require('cluster');
|
|||
|
||||
var async = require('async');
|
||||
var PoolLogger = require('./libs/logUtil.js');
|
||||
var BlocknotifyListener = require('./libs/blocknotifyListener.js');
|
||||
var CoinswitchListener = require('./libs/coinswitchListener.js');
|
||||
var CliListener = require('./libs/cliListener.js');
|
||||
var RedisBlocknotifyListener = require('./libs/redisblocknotifyListener.js');
|
||||
var PoolWorker = require('./libs/poolWorker.js');
|
||||
var PaymentProcessor = require('./libs/paymentProcessor.js');
|
||||
|
@ -82,18 +81,68 @@ if (cluster.isWorker){
|
|||
var buildPoolConfigs = function(){
|
||||
var configs = {};
|
||||
var configDir = 'pool_configs/';
|
||||
|
||||
var poolConfigFiles = [];
|
||||
|
||||
|
||||
/* Get filenames of pool config json files that are enabled */
|
||||
fs.readdirSync(configDir).forEach(function(file){
|
||||
if (!fs.existsSync(configDir + file) || path.extname(configDir + file) !== '.json') return;
|
||||
var poolOptions = JSON.parse(JSON.minify(fs.readFileSync(configDir + file, {encoding: 'utf8'})));
|
||||
if (!poolOptions.enabled) return;
|
||||
var coinFilePath = 'coins/' + poolOptions.coin;
|
||||
poolOptions.fileName = file;
|
||||
poolConfigFiles.push(poolOptions);
|
||||
});
|
||||
|
||||
|
||||
/* Ensure no pool uses any of the same ports as another pool */
|
||||
for (var i = 0; i < poolConfigFiles.length; i++){
|
||||
var ports = Object.keys(poolConfigFiles[i].ports);
|
||||
for (var f = 0; f < poolConfigFiles.length; f++){
|
||||
if (f === i) continue;
|
||||
var portsF = Object.keys(poolConfigFiles[f].ports);
|
||||
for (var g = 0; g < portsF.length; g++){
|
||||
if (ports.indexOf(portsF[g]) !== -1){
|
||||
logger.error('Master', poolConfigFiles[f].fileName, 'Has same configured port of ' + portsF[g] + ' as ' + poolConfigFiles[i].fileName);
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (poolConfigFiles[f].coin === poolConfigFiles[i].coin){
|
||||
logger.error('Master', poolConfigFiles[f].fileName, 'Pool has same configured coin file coins/' + poolConfigFiles[f].coin + ' as ' + poolConfigFiles[i].fileName + ' pool');
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
poolConfigFiles.forEach(function(poolOptions){
|
||||
|
||||
poolOptions.coinFileName = poolOptions.coin;
|
||||
|
||||
var coinFilePath = 'coins/' + poolOptions.coinFileName;
|
||||
if (!fs.existsSync(coinFilePath)){
|
||||
logger.error('Master', poolOptions.coin, 'could not find file: ' + coinFilePath);
|
||||
logger.error('Master', poolOptions.coinFileName, 'could not find file: ' + coinFilePath);
|
||||
return;
|
||||
}
|
||||
|
||||
var coinProfile = JSON.parse(JSON.minify(fs.readFileSync(coinFilePath, {encoding: 'utf8'})));
|
||||
poolOptions.coin = coinProfile;
|
||||
|
||||
if (poolOptions.coin.name in configs){
|
||||
|
||||
logger.error('Master', poolOptions.fileName, 'coins/' + poolOptions.coinFileName
|
||||
+ ' has same configured coin name ' + poolOptions.coin.name + ' as coins/'
|
||||
+ configs[poolOptions.coin.name].coinFileName + ' used by pool config '
|
||||
+ configs[poolOptions.coin.name].fileName);
|
||||
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
configs[poolOptions.coin.name] = poolOptions;
|
||||
|
||||
if (!(coinProfile.algorithm in algos)){
|
||||
|
@ -130,6 +179,10 @@ var spawnPoolWorkers = function(portalConfig, poolConfigs){
|
|||
return;
|
||||
}
|
||||
|
||||
for (var p in poolConfigs){
|
||||
|
||||
}
|
||||
|
||||
var serializedConfigs = JSON.stringify(poolConfigs);
|
||||
|
||||
var numForks = (function(){
|
||||
|
@ -185,25 +238,34 @@ var spawnPoolWorkers = function(portalConfig, poolConfigs){
|
|||
};
|
||||
|
||||
|
||||
var startBlockListener = function(portalConfig){
|
||||
//block notify options
|
||||
//setup block notify here and use IPC to tell appropriate pools
|
||||
var listener = new BlocknotifyListener(portalConfig.blockNotifyListener);
|
||||
var startCliListener = function(cliPort){
|
||||
var listener = new CliListener(cliPort);
|
||||
listener.on('log', function(text){
|
||||
logger.debug('Master', 'Blocknotify', text);
|
||||
});
|
||||
listener.on('hash', function(message){
|
||||
logger.debug('Master', 'CLI', text);
|
||||
}).on('command', function(command, params, options){
|
||||
|
||||
var ipcMessage = {type:'blocknotify', coin: message.coin, hash: message.hash};
|
||||
switch(command){
|
||||
case 'blocknotify':
|
||||
Object.keys(cluster.workers).forEach(function(id) {
|
||||
cluster.workers[id].send(ipcMessage);
|
||||
cluster.workers[id].send({type: 'blocknotify', coin: params[0], hash: params[1]});
|
||||
});
|
||||
break;
|
||||
case 'coinswitch':
|
||||
Object.keys(cluster.workers).forEach(function(id) {
|
||||
cluster.workers[id].send({type: 'coinswitch', switchName: params[0], coin: params[1] });
|
||||
});
|
||||
break;
|
||||
case 'restartpool':
|
||||
Object.keys(cluster.workers).forEach(function(id) {
|
||||
cluster.workers[id].send({type: 'restartpool', coin: params[0] });
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
listener.start();
|
||||
console.log('command: ' + JSON.stringify([command, params, options]));
|
||||
}).start();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
//
|
||||
// Receives authenticated events from coin switch listener and triggers proxy
|
||||
// to swtich to a new coin.
|
||||
|
@ -219,7 +281,7 @@ var startCoinswitchListener = function(portalConfig){
|
|||
cluster.workers[id].send(ipcMessage);
|
||||
});
|
||||
var ipcMessage = {
|
||||
type:'switch',
|
||||
type:'coinswitch',
|
||||
coin: message.coin
|
||||
};
|
||||
Object.keys(cluster.workers).forEach(function(id) {
|
||||
|
@ -228,6 +290,7 @@ var startCoinswitchListener = function(portalConfig){
|
|||
});
|
||||
listener.start();
|
||||
};
|
||||
*/
|
||||
|
||||
var startRedisBlockListener = function(portalConfig){
|
||||
//block notify options
|
||||
|
@ -324,14 +387,12 @@ var startProfitSwitch = function(portalConfig, poolConfigs){
|
|||
|
||||
startPaymentProcessor(poolConfigs);
|
||||
|
||||
startBlockListener(portalConfig);
|
||||
|
||||
startCoinswitchListener(portalConfig);
|
||||
|
||||
startRedisBlockListener(portalConfig);
|
||||
|
||||
startWebsite(portalConfig, poolConfigs);
|
||||
|
||||
startProfitSwitch(portalConfig, poolConfigs);
|
||||
|
||||
startCliListener(portalConfig.cliPort);
|
||||
|
||||
})();
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
var events = require('events');
|
||||
var net = require('net');
|
||||
|
||||
var listener = module.exports = function listener(options){
|
||||
|
||||
var _this = this;
|
||||
|
||||
var emitLog = function(text){
|
||||
_this.emit('log', text);
|
||||
};
|
||||
|
||||
|
||||
this.start = function(){
|
||||
if (!options || !options.enabled){
|
||||
emitLog('Blocknotify listener disabled');
|
||||
return;
|
||||
}
|
||||
|
||||
var blockNotifyServer = net.createServer(function(c) {
|
||||
|
||||
emitLog('Block listener has incoming connection');
|
||||
var data = '';
|
||||
try {
|
||||
c.on('data', function (d) {
|
||||
emitLog('Block listener received blocknotify data');
|
||||
data += d;
|
||||
if (data.slice(-1) === '\n') {
|
||||
c.end();
|
||||
}
|
||||
});
|
||||
c.on('end', function () {
|
||||
|
||||
emitLog('Block listener connection ended');
|
||||
|
||||
var message;
|
||||
|
||||
try{
|
||||
message = JSON.parse(data);
|
||||
}
|
||||
catch(e){
|
||||
emitLog('Block listener failed to parse message ' + data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.password === options.password) {
|
||||
_this.emit('hash', message);
|
||||
}
|
||||
else
|
||||
emitLog('Block listener received notification with incorrect password');
|
||||
|
||||
});
|
||||
}
|
||||
catch(e){
|
||||
emitLog('Block listener had an error: ' + e);
|
||||
}
|
||||
|
||||
});
|
||||
blockNotifyServer.listen(options.port, function() {
|
||||
emitLog('Block notify listener server started on port ' + options.port)
|
||||
});
|
||||
|
||||
emitLog("Block listener is enabled, starting server on port " + options.port);
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
listener.prototype.__proto__ = events.EventEmitter.prototype;
|
|
@ -0,0 +1,40 @@
|
|||
var events = require('events');
|
||||
var net = require('net');
|
||||
|
||||
var listener = module.exports = function listener(port){
|
||||
|
||||
var _this = this;
|
||||
|
||||
var emitLog = function(text){
|
||||
_this.emit('log', text);
|
||||
};
|
||||
|
||||
|
||||
this.start = function(){
|
||||
net.createServer(function(c) {
|
||||
|
||||
var data = '';
|
||||
try {
|
||||
c.on('data', function (d) {
|
||||
data += d;
|
||||
if (data.slice(-1) === '\n') {
|
||||
c.end();
|
||||
}
|
||||
});
|
||||
c.on('end', function () {
|
||||
var message = JSON.parse(data);
|
||||
_this.emit('command', message.command, message.params, message.options);
|
||||
});
|
||||
}
|
||||
catch(e){
|
||||
emitLog('CLI listener failed to parse message ' + data);
|
||||
}
|
||||
|
||||
}).listen(port, '127.0.0.1', function() {
|
||||
emitLog('CLI listening on port ' + port)
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
listener.prototype.__proto__ = events.EventEmitter.prototype;
|
|
@ -1,56 +0,0 @@
|
|||
var events = require('events');
|
||||
var net = require('net');
|
||||
|
||||
var listener = module.exports = function listener(options){
|
||||
|
||||
var _this = this;
|
||||
|
||||
var emitLog = function(text){
|
||||
_this.emit('log', text);
|
||||
};
|
||||
|
||||
|
||||
this.start = function(){
|
||||
if (!options || !options.enabled){
|
||||
emitLog('Coinswitch listener disabled');
|
||||
return;
|
||||
}
|
||||
|
||||
var coinswitchServer = net.createServer(function(c) {
|
||||
|
||||
emitLog('Coinswitch listener has incoming connection');
|
||||
var data = '';
|
||||
try {
|
||||
c.on('data', function (d) {
|
||||
emitLog('Coinswitch listener received switch request');
|
||||
data += d;
|
||||
if (data.slice(-1) === '\n') {
|
||||
c.end();
|
||||
}
|
||||
});
|
||||
c.on('end', function () {
|
||||
|
||||
var message = JSON.parse(data);
|
||||
if (message.password === options.password) {
|
||||
_this.emit('switchcoin', message);
|
||||
}
|
||||
else
|
||||
emitLog('Coinswitch listener received notification with incorrect password');
|
||||
|
||||
});
|
||||
}
|
||||
catch(e){
|
||||
emitLog('Coinswitch listener failed to parse message ' + data);
|
||||
}
|
||||
|
||||
});
|
||||
coinswitchServer.listen(options.port, function() {
|
||||
emitLog('Coinswitch notify listener server started on port ' + options.port)
|
||||
});
|
||||
|
||||
emitLog("Coinswitch listener is enabled, starting server on port " + options.port);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
listener.prototype.__proto__ = events.EventEmitter.prototype;
|
|
@ -18,6 +18,8 @@ module.exports = function(logger){
|
|||
|
||||
var proxySwitch = {};
|
||||
|
||||
var redisClient = redis.createClient(portalConfig.redis.port, portalConfig.redis.host);
|
||||
|
||||
//Handle messages from master process sent via IPC
|
||||
process.on('message', function(message) {
|
||||
switch(message.type){
|
||||
|
@ -42,26 +44,39 @@ module.exports = function(logger){
|
|||
break;
|
||||
|
||||
// IPC message for pool switching
|
||||
case 'switch':
|
||||
case 'coinswitch':
|
||||
var logSystem = 'Proxy';
|
||||
var logComponent = 'Switch';
|
||||
var logSubCat = 'Thread ' + (parseInt(forkId) + 1);
|
||||
|
||||
var switchName = message.switchName;
|
||||
if (!portalConfig.switching[switchName]) {
|
||||
logger.error(logSystem, logComponent, logSubCat, 'Switching key not recognized: ' + switchName);
|
||||
}
|
||||
|
||||
var messageCoin = message.coin.toLowerCase();
|
||||
var newCoin = Object.keys(pools).filter(function(p){
|
||||
return p.toLowerCase() === messageCoin;
|
||||
})[0];
|
||||
|
||||
if (!newCoin){
|
||||
logger.debug(logSystem, logComponent, logSubCat, 'Switch message to coin that is not recognized: ' + messageCoin);
|
||||
logger.error(logSystem, logComponent, logSubCat, 'Switch message to coin that is not recognized: ' + messageCoin);
|
||||
break;
|
||||
}
|
||||
|
||||
var algo = poolConfigs[newCoin].coin.algorithm;
|
||||
|
||||
if (algo !== proxySwitch[switchName].algorithm){
|
||||
logger.error(logSystem, logComponent, logSubCat, 'Cannot switch a '
|
||||
+ proxySwitch[switchName].algorithm
|
||||
+ ' algo pool to coin ' + newCoin + ' with ' + algo + ' algo');
|
||||
break;
|
||||
}
|
||||
|
||||
var newPool = pools[newCoin];
|
||||
var oldCoin = proxySwitch[algo].currentPool;
|
||||
var oldCoin = proxySwitch[switchName].currentPool;
|
||||
var oldPool = pools[oldCoin];
|
||||
var proxyPort = proxySwitch[algo].port;
|
||||
var proxyPorts = Object.keys(proxySwitch[switchName].ports);
|
||||
|
||||
if (newCoin == oldCoin) {
|
||||
logger.debug(logSystem, logComponent, logSubCat, 'Switch message would have no effect - ignoring ' + newCoin);
|
||||
|
@ -74,16 +89,14 @@ module.exports = function(logger){
|
|||
oldPool.relinquishMiners(
|
||||
function (miner, cback) {
|
||||
// relinquish miners that are attached to one of the "Auto-switch" ports and leave the others there.
|
||||
cback(miner.client.socket.localPort == proxyPort)
|
||||
cback(proxyPorts.indexOf(miner.client.socket.localPort.toString()) !== -1)
|
||||
},
|
||||
function (clients) {
|
||||
newPool.attachMiners(clients);
|
||||
}
|
||||
);
|
||||
proxySwitch[algo].currentPool = newCoin;
|
||||
proxySwitch[switchName].currentPool = newCoin;
|
||||
|
||||
var redisClient = redis.createClient(portalConfig.redis.port, portalConfig.redis.host)
|
||||
redisClient.on('ready', function(){
|
||||
redisClient.hset('proxyState', algo, newCoin, function(error, obj) {
|
||||
if (error) {
|
||||
logger.error(logSystem, logComponent, logSubCat, 'Redis error writing proxy config: ' + JSON.stringify(err))
|
||||
|
@ -92,7 +105,7 @@ module.exports = function(logger){
|
|||
logger.debug(logSystem, logComponent, logSubCat, 'Last proxy state saved to redis for ' + algo);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -119,7 +132,7 @@ module.exports = function(logger){
|
|||
if (shareProcessing && shareProcessing.mpos && shareProcessing.mpos.enabled){
|
||||
var mposCompat = new MposCompatibility(logger, poolOptions);
|
||||
|
||||
handlers.auth = function(workerName, password, authCallback){
|
||||
handlers.auth = function(port, workerName, password, authCallback){
|
||||
mposCompat.handleAuth(workerName, password, authCallback);
|
||||
};
|
||||
|
||||
|
@ -137,10 +150,30 @@ module.exports = function(logger){
|
|||
|
||||
var shareProcessor = new ShareProcessor(logger, poolOptions);
|
||||
|
||||
handlers.auth = function(workerName, password, authCallback){
|
||||
handlers.auth = function(port, workerName, password, authCallback){
|
||||
if (shareProcessing.internal.validateWorkerAddress !== true)
|
||||
authCallback(true);
|
||||
else {
|
||||
port = port.toString();
|
||||
if (portalConfig.switching) {
|
||||
for (var switchName in portalConfig.switching) {
|
||||
if (portalConfig.switching[switchName].enabled && Object.keys(portalConfig.switching[switchName].ports).indexOf(port) !== -1) {
|
||||
if (workerName.length === 40) {
|
||||
try {
|
||||
new Buffer(workerName, 'hex');
|
||||
authCallback(true);
|
||||
}
|
||||
catch (e) {
|
||||
authCallback(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
authCallback(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pool.daemon.cmd('validateaddress', [workerName], function(results){
|
||||
var isValid = results.filter(function(r){return r.response.isvalid}).length > 0;
|
||||
authCallback(isValid);
|
||||
|
@ -153,8 +186,8 @@ module.exports = function(logger){
|
|||
};
|
||||
}
|
||||
|
||||
var authorizeFN = function (ip, workerName, password, callback) {
|
||||
handlers.auth(workerName, password, function(authorized){
|
||||
var authorizeFN = function (ip, port, workerName, password, callback) {
|
||||
handlers.auth(port, workerName, password, function(authorized){
|
||||
|
||||
var authString = authorized ? 'Authorized' : 'Unauthorized ';
|
||||
|
||||
|
@ -202,9 +235,9 @@ module.exports = function(logger){
|
|||
});
|
||||
|
||||
|
||||
if (typeof(portalConfig.proxy) !== 'undefined') {
|
||||
if (portalConfig.switching) {
|
||||
|
||||
var logSystem = 'Proxy';
|
||||
var logSystem = 'Switching';
|
||||
var logComponent = 'Setup';
|
||||
var logSubCat = 'Thread ' + (parseInt(forkId) + 1);
|
||||
|
||||
|
@ -215,8 +248,13 @@ 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(portalConfig.redis.port, portalConfig.redis.host);
|
||||
redisClient.on('ready', function(){
|
||||
|
||||
|
||||
|
||||
/*redisClient.on('error', function(err){
|
||||
logger.debug(logSystem, logComponent, logSubCat, 'Pool configuration failed: ' + err);
|
||||
});*/
|
||||
|
||||
redisClient.hgetall("proxyState", function(error, obj) {
|
||||
if (error || obj == null) {
|
||||
//logger.debug(logSystem, logComponent, logSubCat, 'No last proxy state found in redis');
|
||||
|
@ -234,14 +272,17 @@ module.exports = function(logger){
|
|||
// In addition, the proxy config also takes diff and varDiff parmeters the override the
|
||||
// defaults for the standard config of the coin.
|
||||
//
|
||||
Object.keys(portalConfig.proxy).forEach(function(algorithm) {
|
||||
Object.keys(portalConfig.switching).forEach(function(switchName) {
|
||||
|
||||
if (portalConfig.proxy[algorithm].enabled === true) {
|
||||
var algorithm = portalConfig.switching[switchName].algorithm;
|
||||
|
||||
if (portalConfig.switching[switchName].enabled === true) {
|
||||
var initalPool = proxyState.hasOwnProperty(algorithm) ? proxyState[algorithm] : _this.getFirstPoolForAlgorithm(algorithm);
|
||||
proxySwitch[algorithm] = {
|
||||
port: portalConfig.proxy[algorithm].port,
|
||||
proxySwitch[switchName] = {
|
||||
algorithm: algorithm,
|
||||
ports: portalConfig.switching[switchName].ports,
|
||||
currentPool: initalPool,
|
||||
proxy: {}
|
||||
servers: []
|
||||
};
|
||||
|
||||
|
||||
|
@ -250,39 +291,51 @@ module.exports = function(logger){
|
|||
// Note: This seems a bit wonky and brittle - better if proxy just used the diff config of the port it was
|
||||
// routed into instead.
|
||||
//
|
||||
if (portalConfig.proxy[algorithm].hasOwnProperty('varDiff')) {
|
||||
/*if (portalConfig.proxy[algorithm].hasOwnProperty('varDiff')) {
|
||||
proxySwitch[algorithm].varDiff = new Stratum.varDiff(proxySwitch[algorithm].port, portalConfig.proxy[algorithm].varDiff);
|
||||
proxySwitch[algorithm].diff = portalConfig.proxy[algorithm].diff;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
Object.keys(pools).forEach(function (coinName) {
|
||||
var a = poolConfigs[coinName].coin.algorithm;
|
||||
var p = pools[coinName];
|
||||
if (a === algorithm) {
|
||||
p.setVarDiff(proxySwitch[algorithm].port, proxySwitch[algorithm].varDiff);
|
||||
if (poolConfigs[coinName].coin.algorithm === algorithm) {
|
||||
for (var port in portalConfig.switching[switchName].ports) {
|
||||
if (portalConfig.switching[switchName].ports[port].vardiff)
|
||||
p.setVarDiff(port, portalConfig.switching[switchName].ports[port].vardiff);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
proxySwitch[algorithm].proxy = net.createServer(function(socket) {
|
||||
var currentPool = proxySwitch[algorithm].currentPool;
|
||||
var logSubCat = 'Thread ' + (parseInt(forkId) + 1);
|
||||
|
||||
logger.debug(logSystem, 'Connect', logSubCat, 'Proxy connect from ' + socket.remoteAddress + ' on ' + proxySwitch[algorithm].port
|
||||
+ ' routing to ' + currentPool);
|
||||
Object.keys(proxySwitch[switchName].ports).forEach(function(port){
|
||||
var f = net.createServer(function(socket) {
|
||||
var currentPool = proxySwitch[switchName].currentPool;
|
||||
|
||||
logger.debug(logSystem, 'Connect', logSubCat, 'Connection to '
|
||||
+ switchName + ' from '
|
||||
+ socket.remoteAddress + ' on '
|
||||
+ port + ' routing to ' + currentPool);
|
||||
|
||||
pools[currentPool].getStratumServer().handleNewClient(socket);
|
||||
|
||||
}).listen(parseInt(proxySwitch[algorithm].port), function() {
|
||||
logger.debug(logSystem, logComponent, logSubCat, 'Proxy listening for ' + algorithm + ' on port ' + proxySwitch[algorithm].port
|
||||
+ ' into ' + proxySwitch[algorithm].currentPool);
|
||||
}).listen(parseInt(port), function() {
|
||||
logger.debug(logSystem, logComponent, logSubCat, 'Switching "' + switchName
|
||||
+ '" listening for ' + algorithm
|
||||
+ ' on port ' + port
|
||||
+ ' into ' + proxySwitch[switchName].currentPool);
|
||||
});
|
||||
proxySwitch[switchName].servers.push(f);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
//logger.debug(logSystem, logComponent, logSubCat, 'Proxy pool for ' + algorithm + ' disabled.');
|
||||
}
|
||||
});
|
||||
});
|
||||
}).on('error', function(err){
|
||||
logger.debug(logSystem, logComponent, logSubCat, 'Pool configuration failed: ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
this.getFirstPoolForAlgorithm = function(algorithm) {
|
||||
|
|
|
@ -148,7 +148,11 @@ module.exports = function(logger, portalConfig, poolConfigs){
|
|||
symbol: poolConfigs[coinName].coin.symbol.toUpperCase(),
|
||||
algorithm: poolConfigs[coinName].coin.algorithm,
|
||||
hashrates: replies[i + 1],
|
||||
poolStats: replies[i + 2] != null ? replies[i + 2] : { validShares: 0, validBlocks: 0, invalidShares: 0 },
|
||||
poolStats: {
|
||||
validShares: replies[i + 2] ? (replies[i + 2].validShares || 0) : 0,
|
||||
validBlocks: replies[i + 2] ? (replies[i + 2].validBlocks || 0) : 0,
|
||||
invalidShares: replies[i + 2] ? (replies[i + 2].invalidShares || 0) : 0
|
||||
},
|
||||
blocks: {
|
||||
pending: replies[i + 3],
|
||||
confirmed: replies[i + 4],
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
This script should be hooked to the coin daemon as follow:
|
||||
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
|
||||
*/
|
||||
|
||||
var net = require('net');
|
||||
var config = process.argv[2];
|
||||
var parts = config.split(':');
|
||||
var host = parts[0];
|
||||
var port = parts[1];
|
||||
var password = process.argv[3];
|
||||
var coin = process.argv[4];
|
||||
var blockHash = process.argv[5];
|
||||
|
||||
var client = net.connect(port, host, function () {
|
||||
console.log('client connected');
|
||||
client.write(JSON.stringify({
|
||||
password: password,
|
||||
coin: coin,
|
||||
hash: blockHash
|
||||
}) + '\n');
|
||||
});
|
||||
|
||||
client.on('data', function (data) {
|
||||
console.log(data.toString());
|
||||
//client.end();
|
||||
});
|
||||
|
||||
client.on('end', function () {
|
||||
console.log('client disconnected');
|
||||
//process.exit();
|
||||
});
|
|
@ -16,75 +16,68 @@ Simple lightweight & fast - a more efficient block notify script in pure C.
|
|||
|
||||
(may also work as coin switch)
|
||||
|
||||
Platforms : Linux,BSD,Solaris (mostly OS independent)
|
||||
Platforms : Linux, BSD, Solaris (mostly OS independent)
|
||||
|
||||
Build with:
|
||||
gcc blocknotify.c -o blocknotify
|
||||
|
||||
|
||||
Usage in daemon coin.conf
|
||||
blocknotify="/bin/blocknotify 127.0.0.1:8117 mySuperSecurePassword dogecoin %s"
|
||||
Example usage in daemon coin.conf using default NOMP CLI port of 17117
|
||||
blocknotify="/bin/blocknotify 127.0.0.1:17117 dogecoin %s"
|
||||
|
||||
*NOTE* If you use "localhost" as hostname you may get a "13" error (socket / connect / send may consider "localhost" as a broadcast address)
|
||||
|
||||
// {"password":"notepas","coin":"Xcoin","hash":"d2191a8b644c9cd903439edf1d89ee060e196b3e116e0d48a3f11e5e3987a03b"}
|
||||
// simplest connect + send json string to server
|
||||
|
||||
# $Id: blocknotify.c,v 0.1 2014/04/07 22:38:09 sysman Exp $
|
||||
*/
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int sockfd,n;
|
||||
struct sockaddr_in servaddr,cliaddr;
|
||||
struct sockaddr_in servaddr, cliaddr;
|
||||
char sendline[1000];
|
||||
char recvline[1000];
|
||||
char host[200];
|
||||
char *p,*arg,*errptr;
|
||||
char *p, *arg, *errptr;
|
||||
int port;
|
||||
|
||||
if (argc < 4)
|
||||
if (argc < 3)
|
||||
{
|
||||
// print help
|
||||
printf("NOMP pool block notify\n usage: <host:port> <password> <coin> <block>\n");
|
||||
printf("NOMP pool block notify\n usage: <host:port> <coin> <block>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strncpy(host,argv[1],(sizeof(host)-1));
|
||||
p=host;
|
||||
strncpy(host, argv[1], (sizeof(host)-1));
|
||||
p = host;
|
||||
|
||||
if ( (arg=strchr(p,':')) )
|
||||
if ( (arg = strchr(p,':')) )
|
||||
{
|
||||
*arg='\0';
|
||||
*arg = '\0';
|
||||
|
||||
errno=0; // reset errno
|
||||
port=strtol(++arg,&errptr,10);
|
||||
errno = 0; // reset errno
|
||||
port = strtol(++arg, &errptr, 10);
|
||||
|
||||
if ( (errno != 0) || (errptr == arg) ) { fprintf(stderr, "port number fail [%s]\n",errptr); }
|
||||
// if(strlen(arg) > (errptr-arg) ) also fail, but we ignore it for now
|
||||
// printf("host %s:%d\n",host,port);
|
||||
if ( (errno != 0) || (errptr == arg) )
|
||||
{
|
||||
fprintf(stderr, "port number fail [%s]\n", errptr);
|
||||
}
|
||||
|
||||
// printf("pass: %s coin: %s block:[%s]\n",argv[2],argv[3],argv[4]);
|
||||
snprintf(sendline,sizeof(sendline)-1,
|
||||
"{\"password\":\"%s\",\"coin\":\"%s\",\"hash\":\"%s\"}\n",
|
||||
argv[2], argv[3], argv[4]);
|
||||
}
|
||||
|
||||
// printf("sendline:[%s]",sendline);
|
||||
snprintf(sendline, sizeof(sendline) - 1, "{\"command\":\"blocknotify\",\"params\":[\"%s\",\"%s\"]}\n", argv[2], argv[3]);
|
||||
|
||||
sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
|
||||
bzero(&servaddr,sizeof(servaddr));
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
bzero(&servaddr, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr=inet_addr(host);
|
||||
servaddr.sin_port=htons(port);
|
||||
servaddr.sin_addr.s_addr = inet_addr(host);
|
||||
servaddr.sin_port = htons(port);
|
||||
connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
|
||||
|
||||
int result = send(sockfd,sendline,strlen(sendline),0);
|
||||
int result = send(sockfd, sendline, strlen(sendline), 0);
|
||||
close(sockfd);
|
||||
|
||||
if(result == -1) {
|
||||
printf("Error sending: %i\n",errno);
|
||||
printf("Error sending: %i\n", errno);
|
||||
exit(-1);
|
||||
}
|
||||
exit(0);
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
var net = require('net');
|
||||
|
||||
var defaultPort = 17117;
|
||||
var defaultHost = '127.0.0.1';
|
||||
|
||||
var args = process.argv.slice(2);
|
||||
var params = [];
|
||||
var options = {};
|
||||
|
||||
for(var i = 0; i < args.length; i++){
|
||||
if (args[i].indexOf('-') === 0 && args[i].indexOf('=') !== -1){
|
||||
var s = args[i].substr(1).split('=');
|
||||
options[s[0]] = s[1];
|
||||
}
|
||||
else
|
||||
params.push(args[i]);
|
||||
}
|
||||
|
||||
var command = params.shift();
|
||||
|
||||
|
||||
|
||||
var client = net.connect(options.port || defaultPort, options.host || defaultHost, function () {
|
||||
client.write(JSON.stringify({
|
||||
command: command,
|
||||
params: params,
|
||||
options: options
|
||||
}) + '\n');
|
||||
}).on('error', function(error){
|
||||
if (error.code === 'ECONNREFUSED')
|
||||
console.log('Could not connect to NOMP instance at ' + defaultHost + ':' + defaultPort);
|
||||
else
|
||||
console.log('Socket error ' + JSON.stringify(error));
|
||||
}).on('data', function(data) {
|
||||
console.log(data.toString());
|
||||
}).on('close', function () {
|
||||
|
||||
});
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
This script demonstrates sending a coin switch request and can be invoked from the command line
|
||||
with:
|
||||
|
||||
"node coinSwitch.js 127.0.0.1:8118 password %s"
|
||||
|
||||
where <%s> is the name of the coin proxy miners will be switched onto.
|
||||
|
||||
If the coin name is not configured, disabled or matches the existing proxy setting, no action
|
||||
will be taken by NOMP on receipt of the message.
|
||||
*/
|
||||
|
||||
var net = require('net');
|
||||
var config = process.argv[2];
|
||||
var parts = config.split(':');
|
||||
var host = parts[0];
|
||||
var port = parts[1];
|
||||
var password = process.argv[3];
|
||||
var coin = process.argv[4];
|
||||
|
||||
var client = net.connect(port, host, function () {
|
||||
console.log('client connected');
|
||||
client.write(JSON.stringify({
|
||||
password: password,
|
||||
coin: coin
|
||||
}) + '\n');
|
||||
});
|
||||
|
||||
client.on('data', function (data) {
|
||||
console.log(data.toString());
|
||||
//client.end();
|
||||
});
|
||||
|
||||
client.on('end', function () {
|
||||
console.log('client disconnected');
|
||||
//process.exit();
|
||||
});
|
|
@ -1,34 +1,38 @@
|
|||
<style>
|
||||
|
||||
#topCharts{
|
||||
#topCharts {
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
#topCharts > div > div > svg{
|
||||
#topCharts > div > div > svg {
|
||||
display: block;
|
||||
height: 280px;
|
||||
}
|
||||
|
||||
.chartWrapper{
|
||||
.chartWrapper {
|
||||
border: solid 1px #c7c7c7;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.chartLabel{
|
||||
.chartLabel {
|
||||
font-size: 1.2em;
|
||||
text-align: center;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.chartHolder{
|
||||
.chartHolder {
|
||||
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="footer" style="background-color:#2d2d2d;clear:both;text-align:center;">
|
||||
<table class="pure-table">
|
||||
|
||||
<table class="pure-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Pool</th>
|
||||
|
@ -52,5 +56,4 @@
|
|||
<td>{{=it.stats.pools[pool].hashrateString}}</td>
|
||||
</tr>
|
||||
{{ } }}
|
||||
</table>
|
||||
</div>
|
||||
</table>
|
||||
|
|
Loading…
Reference in New Issue