mirror of https://github.com/BTCPrivate/z-nomp.git
Added mpos auth feature
This commit is contained in:
parent
95fe6129b3
commit
943f3d1f32
|
@ -133,7 +133,11 @@ Description of options:
|
|||
"port": 3306,
|
||||
"user": "me",
|
||||
"password": "mypass",
|
||||
"database": "ltc"
|
||||
"database": "ltc",
|
||||
/* For when miner's authenticate: set to "password" for both worker name and password to
|
||||
be checked for in the database, set to "worker" for only work name to be checked, or
|
||||
don't use this option (set to "none") for no auth checks */
|
||||
"stratumAuth": "password"'
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -180,7 +184,7 @@ Description of options:
|
|||
````
|
||||
|
||||
You can create as many of these pool config files as you want (such as one pool per coin you which to operate).
|
||||
If you are creating multiple pools, ensure that they have unique stratum ports with the `pool.stratumPort` field.
|
||||
If you are creating multiple pools, ensure that they have unique stratum ports.
|
||||
|
||||
For more information on these configuration options see the [pool module documentation](https://github.com/zone117x/node-stratum#module-usage)
|
||||
|
||||
|
|
4
init.js
4
init.js
|
@ -110,9 +110,9 @@ if (cluster.isMaster){
|
|||
});
|
||||
listener.on('hash', function(message){
|
||||
|
||||
var serializedMessage = JSON.stringify({'blocknotify': message.hash});
|
||||
var ipcMessage = {type:'blocknotify', coin: message.coin, hash: message.hash};
|
||||
Object.keys(cluster.workers).forEach(function(id) {
|
||||
cluster.workers[id].send(serializedMessage);
|
||||
cluster.workers[id].send(ipcMessage);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -4,6 +4,8 @@ module.exports = function(logger, poolConfigs){
|
|||
|
||||
var dbConnections = (function(){
|
||||
var connections = {};
|
||||
|
||||
|
||||
Object.keys(poolConfigs).forEach(function(coin) {
|
||||
|
||||
var config = poolConfigs[coin];
|
||||
|
@ -23,21 +25,21 @@ module.exports = function(logger, poolConfigs){
|
|||
});
|
||||
connection.connect(function(err){
|
||||
if (err)
|
||||
logger.logError('shareProcessor', 'mysql', config.coin.name +
|
||||
logger.logError('shareProcessor', 'mysql', coin +
|
||||
' - could not connect to mysql database: ' + JSON.stringify(err))
|
||||
else{
|
||||
logger.logDebug('shareProcessor', 'mysql', config.coin.name +
|
||||
logger.logDebug('shareProcessor', 'mysql', coin +
|
||||
' - successful connection to MySQL database');
|
||||
}
|
||||
});
|
||||
connection.on('error', function(err){
|
||||
if(err.code === 'PROTOCOL_CONNECTION_LOST') {
|
||||
logger.logWarning('shareProcessor', 'mysql', config.coin.name +
|
||||
logger.logWarning('shareProcessor', 'mysql', coin +
|
||||
' - lost connection to MySQL database, attempting reconnection...');
|
||||
connect();
|
||||
}
|
||||
else{
|
||||
logger.logError('shareProcessor', 'mysql', config.coin.name +
|
||||
logger.logError('shareProcessor', 'mysql', coin +
|
||||
' - mysql database error: ' + JSON.stringify(err))
|
||||
}
|
||||
});
|
||||
|
@ -45,10 +47,48 @@ module.exports = function(logger, poolConfigs){
|
|||
connect();
|
||||
});
|
||||
return connections;
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
this.handleAuth = function(allowCallback){
|
||||
this.handleAuth = function(data){
|
||||
/*
|
||||
type: 'mposAuth',
|
||||
coin: poolOptions.coin.name,
|
||||
callbackId: callbackId,
|
||||
workerId: cluster.worker.id,
|
||||
workerName: workerName,
|
||||
password: password,
|
||||
authLevel: authLevel
|
||||
*/
|
||||
|
||||
var sendResult = function(authorized){
|
||||
cluster.workers[data.workerId].send({
|
||||
type: 'mposAuth',
|
||||
callbackId: data.callbackId,
|
||||
authorized: authorized
|
||||
});
|
||||
};
|
||||
|
||||
var connection = dbConnections[data.coin];
|
||||
connection.query(
|
||||
'SELECT password FROM pool_worker WHERE username = LOWER(?)',
|
||||
[data.workerName],
|
||||
function(err, result){
|
||||
if (err){
|
||||
logger.logError('shareProcessor', 'mysql', 'MySQL error when authenticating worker: ' +
|
||||
JSON.stringify(err));
|
||||
sendResult(false);
|
||||
}
|
||||
else if (!result[0])
|
||||
sendResult(false);
|
||||
else if (data.authLevel === 'worker')
|
||||
sendResult(true);
|
||||
else if (result[0].password === data.password)
|
||||
sendResult(true)
|
||||
else
|
||||
sendResult(false);
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
var cluster = require('cluster');
|
||||
|
||||
var Stratum = require('stratum-pool');
|
||||
|
||||
module.exports = function(logger){
|
||||
|
@ -13,19 +15,28 @@ module.exports = function(logger){
|
|||
|
||||
var pools = [];
|
||||
|
||||
//Handle blocknotify message from master process sent via IPC
|
||||
//Handle messages from master process sent via IPC
|
||||
process.on('message', function(message) {
|
||||
if (message.blocknotify){
|
||||
for (var i = 0; i < pools.length; i++){
|
||||
if (pools[i].options.coin.name.toLowerCase() === message.coin.toLowerCase()){
|
||||
pools[i].processBlockNotify(message.blockHash)
|
||||
return;
|
||||
switch(message.type){
|
||||
case 'blocknotify':
|
||||
for (var i = 0; i < pools.length; i++){
|
||||
if (pools[i].options.coin.name.toLowerCase() === message.coin.toLowerCase()){
|
||||
pools[i].processBlockNotify(message.hash)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'mposAuth':
|
||||
var callbackId = message.callbackId;
|
||||
if (callbackId in mposAuthCallbacks)
|
||||
mposAuthCallbacks[callbackId](message.authorized);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var mposAuthCallbacks = {};
|
||||
|
||||
Object.keys(poolConfigs).forEach(function(coin) {
|
||||
|
||||
var poolOptions = poolConfigs[coin];
|
||||
|
@ -35,11 +46,49 @@ module.exports = function(logger){
|
|||
var authorizeFN = function (ip, workerName, password, callback) {
|
||||
// Default implementation just returns true
|
||||
logDebug(logIdentify, 'client', "Authorize [" + ip + "] " + workerName + ":" + password);
|
||||
callback({
|
||||
error: null,
|
||||
authorized: true,
|
||||
disconnect: false
|
||||
});
|
||||
|
||||
var mposAuthLevel;
|
||||
if (poolOptions.shareProcessing.mpos.enabled && (
|
||||
(mposAuthLevel = poolOptions.shareProcessing.mpos.stratumAuth) === 'worker' ||
|
||||
mposAuthLevel === 'password'
|
||||
)){
|
||||
var callbackId = coin + workerName + password + Date.now();
|
||||
var authTimeout = setTimeout(function(){
|
||||
if (!(callbackId in mposAuthCallbacks))
|
||||
return;
|
||||
callback({
|
||||
error: null,
|
||||
authorized: false,
|
||||
disconnect: false
|
||||
});
|
||||
delete mposAuthCallbacks[callbackId];
|
||||
}, 30000);
|
||||
mposAuthCallbacks[callbackId] = function(authorized){
|
||||
callback({
|
||||
error: null,
|
||||
authorized: authorized,
|
||||
disconnect: false
|
||||
});
|
||||
delete mposAuthCallbacks[callbackId];
|
||||
clearTimeout(authTimeout);
|
||||
};
|
||||
process.send({
|
||||
type: 'mposAuth',
|
||||
coin: poolOptions.coin.name,
|
||||
callbackId: callbackId,
|
||||
workerId: cluster.worker.id,
|
||||
workerName: workerName,
|
||||
password: password,
|
||||
authLevel: mposAuthLevel
|
||||
});
|
||||
}
|
||||
else{
|
||||
callback({
|
||||
error: null,
|
||||
authorized: true,
|
||||
disconnect: false
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3,39 +3,56 @@ var redis = require('redis');
|
|||
module.exports = function(logger, poolConfigs){
|
||||
|
||||
|
||||
//TODO: need to add redis config to json. probably do one redis client per pool?
|
||||
var dbConnections = (function(){
|
||||
var connections = {};
|
||||
Object.keys(poolConfigs).forEach(function(coin) {
|
||||
|
||||
var client;
|
||||
var config = poolConfigs[coin];
|
||||
|
||||
client = redis.createClient();
|
||||
if (!config.shareProcessing || !config.shareProcessing.internal || !config.shareProcessing.internal.enabled)
|
||||
return;
|
||||
|
||||
var redisConfig = config.shareProcessing.internal.redis;
|
||||
|
||||
function connect(){
|
||||
var connection = connections[coin] = redis.createClient(redisConfig.port, redisConfig.host);
|
||||
connection.on('error', function(err){
|
||||
logger.logError('shareProcessor', 'redis', coin +
|
||||
' - redis client had an error: ' + JSON.stringify(err))
|
||||
});
|
||||
connection.on('end', function(){
|
||||
logger.logWarning('shareProcessor', 'redis', coin +
|
||||
' - connection to redis database as been ended');
|
||||
connect();
|
||||
});
|
||||
}
|
||||
connect();
|
||||
});
|
||||
})();
|
||||
|
||||
client.on("error", function (err) {
|
||||
logger.logError('shareProcessor', 'redis', 'Redis client had an error: ' + err);
|
||||
});
|
||||
|
||||
this.handleDifficultyUpdate = function(data){
|
||||
var coin = data.coin;
|
||||
var poolConfig = poolConfigs[coin];
|
||||
if (poolConfig.shareProcessing.mpos && poolConfig.shareProcessing.mpos.enabled){
|
||||
poolMposHandlers[coin].updateDifficulty(data.workerName, data.diff);
|
||||
}
|
||||
};
|
||||
|
||||
this.handleShare = function(data){
|
||||
|
||||
if ((!data.coin in dbConnections)) return;
|
||||
|
||||
if (!data.isValidShare) return;
|
||||
|
||||
var connection = dbConnections[data.coin];
|
||||
|
||||
var shareData = data.share;
|
||||
var coin = data.coin;
|
||||
var poolConfig = poolConfigs[coin];
|
||||
|
||||
if (poolConfig.shareProcessing.mpos && poolConfig.shareProcessing.mpos.enabled){
|
||||
poolMposHandlers[coin].insertShare(data.isValidShare, data.isValidBlock, shareData);
|
||||
}
|
||||
connection.hincrby([coin + ':' + shareData.height, shareData.worker, shareData.difficulty], function(error, result){
|
||||
if (error)
|
||||
logger.logError('shareProcessor', 'redis', 'could not store worker share')
|
||||
});
|
||||
|
||||
if (poolConfig.shareProcessing.internal && poolConfig.shareProcessing.internal.enable && data.isValidShare){
|
||||
client.hincrby([coin + ':' + shareData.height, shareData.worker, shareData.difficulty], function(error, result){
|
||||
if (error)
|
||||
logger.logError('shareProcessor', 'redis', 'could not store worker share')
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.handleBlock = function(data){
|
||||
|
|
|
@ -36,6 +36,9 @@ var processor = module.exports = function processor(logger, poolConfigs){
|
|||
if (shareProcessing.internal.enabled)
|
||||
shareProcessor.handleBlock(data);
|
||||
break;
|
||||
case 'mposAuth':
|
||||
mposCompat.handleAuth(data);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -22,21 +22,26 @@
|
|||
|
||||
"shareProcessing": {
|
||||
"internal": {
|
||||
"enabled": true,
|
||||
"enabled": false,
|
||||
"daemon": {
|
||||
"host": "localhost",
|
||||
"port": 19332,
|
||||
"user": "litecoinrpc",
|
||||
"password": "testnet"
|
||||
},
|
||||
"redis": {
|
||||
"host": "localhost",
|
||||
"port": 6379
|
||||
}
|
||||
},
|
||||
"mpos": {
|
||||
"enabled": false,
|
||||
"enabled": true,
|
||||
"host": "localhost",
|
||||
"port": 3306,
|
||||
"user": "me",
|
||||
"password": "mypass",
|
||||
"database": "ltc"
|
||||
"database": "ltc",
|
||||
"stratumAuth": "password"
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ var client = net.connect(port, host, function() {
|
|||
client.write(JSON.stringify({
|
||||
password: password,
|
||||
coin: coin,
|
||||
blockHash: blockHash
|
||||
hash: blockHash
|
||||
}) + '\n');
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue