Better logging for various components, changed example payment intervals from 10 seconds to 60 seconds. Added more coins and example pool configs.

This commit is contained in:
Matt 2014-03-30 17:04:54 -06:00
parent 9b3d5766df
commit b7e7916736
15 changed files with 263 additions and 120 deletions

7
coins/copperbars.json Normal file
View File

@ -0,0 +1,7 @@
{
"name": "Copperbars",
"symbol": "CPR",
"algorithm": "scrypt-jane",
"chainStartTime": 1376184687,
"txMessages": false
}

View File

@ -143,7 +143,7 @@ var spawnPoolWorkers = function(portalConfig, poolConfigs){
i++; i++;
if (i === numForks){ if (i === numForks){
clearInterval(spawnInterval); clearInterval(spawnInterval);
logger.debug('Master', 'PoolSpawner', 'Spawned pools for all ' + numForks + ' configured forks'); logger.debug('Master', 'PoolSpawner', 'Spawned ' + Object.keys(poolConfigs).length + ' pool(s) on ' + numForks + ' thread(s)');
} }
}, 250); }, 250);

View File

@ -9,70 +9,120 @@ module.exports = function(logger){
var poolConfigs = JSON.parse(process.env.pools); var poolConfigs = JSON.parse(process.env.pools);
var enabledPools = [];
Object.keys(poolConfigs).forEach(function(coin) { Object.keys(poolConfigs).forEach(function(coin) {
SetupForPool(logger, poolConfigs[coin]); var poolOptions = poolConfigs[coin];
if (poolOptions.shareProcessing &&
poolOptions.shareProcessing.internal &&
poolOptions.shareProcessing.internal.enabled)
enabledPools.push(coin);
}); });
async.filter(enabledPools, function(coin, callback){
SetupForPool(logger, poolConfigs[coin], function(setupResults){
callback(setupResults);
});
}, function(coins){
coins.forEach(function(coin){
var poolOptions = poolConfigs[coin];
var processingConfig = poolOptions.shareProcessing.internal;
var logSystem = 'Payments';
var logComponent = coin;
logger.debug(logSystem, logComponent, 'Payment processing setup to run every '
+ processingConfig.paymentInterval + ' second(s) with daemon ('
+ processingConfig.daemon.user + '@' + processingConfig.daemon.host + ':' + processingConfig.daemon.port
+ ') and redis (' + processingConfig.redis.host + ':' + processingConfig.redis.port + ')');
});
});
}; };
function SetupForPool(logger, poolOptions){ function SetupForPool(logger, poolOptions, setupFinished){
if (!poolOptions.shareProcessing ||
!poolOptions.shareProcessing.internal ||
!poolOptions.shareProcessing.internal.enabled)
return;
var coin = poolOptions.coin.name; var coin = poolOptions.coin.name;
var processingConfig = poolOptions.shareProcessing.internal; var processingConfig = poolOptions.shareProcessing.internal;
var logSystem = 'Payments'; var logSystem = 'Payments';
var logComponent = coin; var logComponent = coin;
var daemon = new Stratum.daemon.interface([processingConfig.daemon]); var daemon;
daemon.once('online', function(){ var redisClient;
logger.debug(logSystem, logComponent, 'Connected to daemon for payment processing');
async.parallel([
function(callback){
daemon = new Stratum.daemon.interface([processingConfig.daemon]);
daemon.once('online', function(){
daemon.cmd('validateaddress', [poolOptions.address], function(result){ daemon.cmd('validateaddress', [poolOptions.address], function(result){
if (!result[0].response || !result[0].response.ismine){ if (!result[0].response || !result[0].response.ismine){
logger.error(logSystem, logComponent, logger.error(logSystem, logComponent,
'Daemon does not own pool address - payment processing can not be done with this daemon'); 'Daemon does not own pool address - payment processing can not be done with this daemon');
return;
} }
callback()
}); });
}).once('connectionFailed', function(error){ }).once('connectionFailed', function(error){
logger.error(logSystem, logComponent, 'Failed to connect to daemon for payment processing: ' + logger.error(logSystem, logComponent, 'Failed to connect to daemon for payment processing: config ' +
JSON.stringify(processingConfig.daemon) + ', error: ' +
JSON.stringify(error)); JSON.stringify(error));
callback('Error connecting to deamon');
}).on('error', function(error){ }).on('error', function(error){
logger.error(logSystem, logComponent, 'Daemon error ' + JSON.stringify(error)); logger.error(logSystem, logComponent, 'Daemon error ' + JSON.stringify(error));
}).init(); }).init();
},
function(callback){
var redisClient;
var connectToRedis = function(){
var reconnectTimeout;
redisClient = redis.createClient(processingConfig.redis.port, processingConfig.redis.host); redisClient = redis.createClient(processingConfig.redis.port, processingConfig.redis.host);
redisClient.on('ready', function(){ redisClient.on('ready', function(){
clearTimeout(reconnectTimeout); if (callback) {
logger.debug(logSystem, logComponent, 'Successfully connected to redis database'); callback();
})/*).on('error', function(err){ callback = null;
logger.error(logSystem, logComponent, 'Redis client had an error: ' + JSON.stringify(err)) return;
})*/.on('end', function(){ }
logger.debug(logSystem, logComponent, 'Connected to redis at '
+ processingConfig.redis.host + ':' + processingConfig.redis.port + ' for payment processing');
}).on('end', function(){
logger.error(logSystem, logComponent, 'Connection to redis database as been ended'); logger.error(logSystem, logComponent, 'Connection to redis database as been ended');
logger.warning(logSystem, logComponent, 'Trying reconnection to redis in 3 seconds...'); }).once('error', function(){
reconnectTimeout = setTimeout(function(){ if (callback) {
connectToRedis(); logger.error(logSystem, logComponent, 'Failed to connect to redis at '
}, 3000); + processingConfig.redis.host + ':' + processingConfig.redis.port + ' for payment processing');
callback('Error connecting to redis');
callback = null;
}
}); });
};
connectToRedis(); }
], function(err){
if (err){
setupFinished(false);
return;
}
setInterval(function(){
try {
processPayments();
} catch(e){
throw e;
}
}, processingConfig.paymentInterval * 1000);
setTimeout(processPayments, 100);
setupFinished(true);
});
/* Number.toFixed gives us the decimal places we want, but as a string. parseFloat turns it back into number /* Number.toFixed gives us the decimal places we want, but as a string. parseFloat turns it back into number
@ -124,30 +174,6 @@ function SetupForPool(logger, poolOptions){
}); });
}, },
/* First get data from all pending blocks via batch RPC call, we need the coinbase txHash. */
/*(function(rounds, callback){
var batchRPCcommand = rounds.map(function(r){
return ['getblock', [r.solution]];
});
daemon.batchCmd(batchRPCcommand, function(error, blocks) {
if (error || !blocks) {
callback('Check finished - daemon rpc error with batch gettransactions ' +
JSON.stringify(error));
return;
}
blocks.forEach(function (b, i) {
if (b.error || b.result.hash !== rounds[i].solution){
logger.error(logSystem, logComponent, "Did daemon drop a block? " + rounds[i].solution);
return;
}
rounds[i].txHash = b.result.tx[0];
});
callback(null, rounds);
});
},*/
/* Does a batch rpc call to daemon with all the transaction hashes to see if they are confirmed yet. /* Does a batch rpc call to daemon with all the transaction hashes to see if they are confirmed yet.
It also adds the block reward amount to the round object - which the daemon gives also gives us. */ It also adds the block reward amount to the round object - which the daemon gives also gives us. */
function(rounds, callback){ function(rounds, callback){
@ -535,7 +561,7 @@ function SetupForPool(logger, poolOptions){
var paymentProcessTime = Date.now() - startPaymentProcess; var paymentProcessTime = Date.now() - startPaymentProcess;
if (error) if (error)
logger.debug(logSystem, logComponent, '[' + paymentProcessTime + 'ms] ' + error); logger.debug(logSystem, logComponent, '[Took ' + paymentProcessTime + 'ms] ' + error);
else{ else{
logger.debug(logSystem, logComponent, '[' + paymentProcessTime + 'ms] ' + result); logger.debug(logSystem, logComponent, '[' + paymentProcessTime + 'ms] ' + result);
@ -579,14 +605,4 @@ function SetupForPool(logger, poolOptions){
}; };
setInterval(function(){
try {
processPayments();
} catch(e){
throw e;
}
}, processingConfig.paymentInterval * 1000);
setTimeout(processPayments, 100);
}; };

View File

@ -17,7 +17,8 @@ module.exports = function(logger){
var pools = {}; var pools = {};
var proxyStuff = {} 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){
@ -52,7 +53,7 @@ module.exports = function(logger){
var logSystem = 'Pool'; var logSystem = 'Pool';
var logComponent = coin; var logComponent = coin;
var logSubCat = 'Fork ' + forkId; var logSubCat = 'Thread ' + (parseInt(forkId) + 1);
var handlers = { var handlers = {

View File

@ -20,31 +20,23 @@ module.exports = function(logger, poolConfig){
var redisConfig = internalConfig.redis; var redisConfig = internalConfig.redis;
var coin = poolConfig.coin.name; var coin = poolConfig.coin.name;
var logSystem = 'Shares'; var forkId = process.env.forkId;
var logSystem = 'Pool';
var logComponent = coin;
var logSubCat = 'Thread ' + (parseInt(forkId) + 1);
var connection; var connection = redis.createClient(redisConfig.port, redisConfig.host);
function connect(){
var reconnectTimeout;
connection = redis.createClient(redisConfig.port, redisConfig.host);
connection.on('ready', function(){ connection.on('ready', function(){
clearTimeout(reconnectTimeout); logger.debug(logSystem, logComponent, logSubCat, 'Share processing setup with redis (' + redisConfig.host +
logger.debug(logSystem, 'redis', 'Successfully connected to redis database'); ':' + redisConfig.port + ')');
}); });
connection.on('error', function(err){ connection.on('error', function(err){
logger.error(logSystem, 'redis', 'Redis client had an error: ' + JSON.stringify(err)) logger.error(logSystem, logComponent, logSubCat, 'Redis client had an error: ' + JSON.stringify(err))
}); });
connection.on('end', function(){ connection.on('end', function(){
logger.error(logSystem, 'redis', 'Connection to redis database as been ended'); logger.error(logSystem, logComponent, logSubCat, 'Connection to redis database as been ended');
logger.warning(logSystem, 'redis', 'Trying reconnection in 3 seconds...');
reconnectTimeout = setTimeout(function(){
connect();
}, 3000);
}); });
}
connect();
@ -78,9 +70,9 @@ module.exports = function(logger, poolConfig){
connection.multi(redisCommands).exec(function(err, replies){ connection.multi(redisCommands).exec(function(err, replies){
if (err) if (err)
logger.error(logSystem, 'redis', 'Error with share processor multi ' + JSON.stringify(err)); logger.error(logSystem, logComponent, logSubCat, 'Error with share processor multi ' + JSON.stringify(err));
else else
logger.debug(logSystem, 'redis', 'Share data and stats recorded'); logger.debug(logSystem, logComponent, logSubCat, 'Share data and stats recorded');
}); });

View File

@ -140,12 +140,11 @@ module.exports = function(logger, portalConfig, poolConfigs){
}); });
var shareMultiplier = algos[coinStats.algorithm].multiplier || 0; var shareMultiplier = algos[coinStats.algorithm].multiplier || 0;
var hashratePre = shareMultiplier * coinStats.shares / portalConfig.website.hashrateWindow; var hashratePre = shareMultiplier * coinStats.shares / portalConfig.website.hashrateWindow;
console.log([hashratePre, shareMultiplier, coinStats.shares, portalConfig.website.hashrateWindow]);
coinStats.hashrate = hashratePre / 1e3 | 0; coinStats.hashrate = hashratePre / 1e3 | 0;
portalStats.global.hashrate += coinStats.hashrate; portalStats.global.hashrate += coinStats.hashrate;
portalStats.global.workers += Object.keys(coinStats.workers).length; portalStats.global.workers += Object.keys(coinStats.workers).length;
coinStats.hashrates; delete coinStats.hashrates;
coinStats.shares; delete coinStats.shares;
}); });
_this.stats = portalStats; _this.stats = portalStats;

View File

@ -0,0 +1,64 @@
{
"enabled": false,
"coin": "bitcoin.json",
"shareProcessing": {
"internal": {
"enabled": true,
"validateWorkerAddress": true,
"paymentInterval": 60,
"minimumPayment": 100.001,
"minimumReserve": 10,
"feePercent": 0.02,
"feeReceiveAddress": "msjLr1XfpB6aAL1wi8e2CDnDSNhF4WrJ5n",
"feeWithdrawalThreshold": 5,
"daemon": {
"host": "localhost",
"port": 18332,
"user": "testuser",
"password": "testpass"
},
"redis": {
"host": "localhost",
"port": 6379
}
},
"mpos": {
"enabled": false,
"host": "localhost",
"port": 3306,
"user": "me",
"password": "mypass",
"database": "ltc",
"stratumAuth": "password"
}
},
"address": "mtCiLWzBy9EpuxzkLwizPYiPFDy69HTd4b",
"blockRefreshInterval": 1000,
"txRefreshInterval": 20000,
"connectionTimeout": 600,
"banning": {
"enabled": true,
"time": 600,
"invalidPercent": 50,
"checkThreshold": 500,
"purgeInterval": 300
},
"ports": {
"6774": {
"diff": 1
}
},
"daemons": [
{
"host": "localhost",
"port": 18332,
"user": "testuser",
"password": "testpass"
}
]
}

View File

@ -6,7 +6,7 @@
"internal": { "internal": {
"enabled": true, "enabled": true,
"validateWorkerAddress": true, "validateWorkerAddress": true,
"paymentInterval": 10, "paymentInterval": 60,
"minimumPayment": 100.001, "minimumPayment": 100.001,
"minimumReserve": 10, "minimumReserve": 10,
"feePercent": 0.02, "feePercent": 0.02,

View File

@ -11,7 +11,7 @@
"internal": { "internal": {
"enabled": true, "enabled": true,
"validateWorkerAddress": true, "validateWorkerAddress": true,
"paymentInterval": 10, "paymentInterval": 60,
"minimumPayment": 100.001, "minimumPayment": 100.001,
"minimumReserve": 10, "minimumReserve": 10,
"feePercent": 0.02, "feePercent": 0.02,

View File

@ -6,7 +6,7 @@
"internal": { "internal": {
"enabled": true, "enabled": true,
"validateWorkerAddress": true, "validateWorkerAddress": true,
"paymentInterval": 10, "paymentInterval": 60,
"minimumPayment": 70, "minimumPayment": 70,
"minimumReserve": 10, "minimumReserve": 10,
"feePercent": 0.05, "feePercent": 0.05,

View File

@ -6,7 +6,7 @@
"internal": { "internal": {
"enabled": true, "enabled": true,
"validateWorkerAddress": true, "validateWorkerAddress": true,
"paymentInterval": 10, "paymentInterval": 60,
"minimumPayment": 100.001, "minimumPayment": 100.001,
"minimumReserve": 10, "minimumReserve": 10,
"feePercent": 0.02, "feePercent": 0.02,

View File

@ -6,7 +6,7 @@
"internal": { "internal": {
"enabled": false, "enabled": false,
"validateWorkerAddress": true, "validateWorkerAddress": true,
"paymentInterval": 10, "paymentInterval": 60,
"minimumPayment": 100.001, "minimumPayment": 100.001,
"minimumReserve": 10, "minimumReserve": 10,
"feePercent": 0.02, "feePercent": 0.02,

View File

@ -6,7 +6,7 @@
"internal": { "internal": {
"enabled": true, "enabled": true,
"validateWorkerAddress": true, "validateWorkerAddress": true,
"paymentInterval": 10, "paymentInterval": 60,
"minimumPayment": 70, "minimumPayment": 70,
"minimumReserve": 10, "minimumReserve": 10,
"feePercent": 0.05, "feePercent": 0.05,

View File

@ -11,7 +11,7 @@
"internal": { "internal": {
"enabled": true, "enabled": true,
"validateWorkerAddress": true, "validateWorkerAddress": true,
"paymentInterval": 10, "paymentInterval": 60,
"minimumPayment": 100.001, "minimumPayment": 100.001,
"minimumReserve": 10, "minimumReserve": 10,
"feePercent": 0.02, "feePercent": 0.02,

View File

@ -0,0 +1,64 @@
{
"enabled": false,
"coin": "ultracoin.json",
"shareProcessing": {
"internal": {
"enabled": true,
"validateWorkerAddress": true,
"paymentInterval": 60,
"minimumPayment": 100.001,
"minimumReserve": 10,
"feePercent": 0.02,
"feeReceiveAddress": "UZ3cz7EKjC4eRKbhiN9tA6xcaDGSVoESc8",
"feeWithdrawalThreshold": 5,
"daemon": {
"host": "localhost",
"port": 18365,
"user": "testuser",
"password": "testpass"
},
"redis": {
"host": "localhost",
"port": 6379
}
},
"mpos": {
"enabled": false,
"host": "localhost",
"port": 3306,
"user": "me",
"password": "mypass",
"database": "ltc",
"stratumAuth": "password"
}
},
"address": "UhyKVr4m516TPsrLwm91pYL4f99VGrJ1oC",
"blockRefreshInterval": 1000,
"txRefreshInterval": 20000,
"connectionTimeout": 600,
"banning": {
"enabled": true,
"time": 600,
"invalidPercent": 50,
"checkThreshold": 500,
"purgeInterval": 300
},
"ports": {
"6856": {
"diff": 8
}
},
"daemons": [
{
"host": "localhost",
"port": 18365,
"user": "testuser",
"password": "testpass"
}
]
}