From 7fe215679a6d7f774c73919776ca0985a3b32a9d Mon Sep 17 00:00:00 2001 From: "Eugene@ubuntu" Date: Wed, 2 Apr 2014 14:56:13 +0400 Subject: [PATCH 1/7] fix payment redis final cleanout issue - possible double spending - optimized --- libs/paymentProcessor.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index a9edd14..af67f6a 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -493,6 +493,33 @@ function SetupForPool(logger, poolOptions, setupFinished){ }); }, + /* Call redis to check if previous sendmany and/or redis cleanout commands completed successfully. + If sendmany worked fine but redis commands failed you HAVE TO run redis commands again + (manually) to prevent double payments. If sendmany failed too you can safely delete + coin + '_finalRedisCommands' string from redis to let pool calculate payments again. */ + function(magnitude, workerPayments, finalRedisCommands, callback) { + redisClient.get(coin + '_finalRedisCommands', function(error, reply) { + if (error){ + callback('Check finished - error with redis getting finalRedisCommands' + JSON.stringify(error)); + return; + } + if (reply) { + callback('Check finished - previous sendmany and/or redis cleanout commands failed - ' + reply); + return; + } else { + /* There was no error in previous sendmany and/or redis cleanout commands + so we can safely continue */ + redisClient.set(coin + '_finalRedisCommands', JSON.stringify(finalRedisCommands), function(error, reply) { + if (error){ + callback('Check finished - error with saving finalRedisCommands' + JSON.stringify(error)); + return; + } + callback(null, magnitude, workerPayments, finalRedisCommands); + }); + } + }); + }, + function(magnitude, workerPayments, finalRedisCommands, callback){ //This does the final all-or-nothing atom transaction if block deamon sent payments From a9132319cc1c573882c819c31e5749d71ae7b0c4 Mon Sep 17 00:00:00 2001 From: "Eugene@ubuntu" Date: Thu, 3 Apr 2014 00:43:58 +0400 Subject: [PATCH 2/7] fix payment redis final cleanout issue - possible double spending - optimized - fixed --- libs/paymentProcessor.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index 3f1f2cb..91bfeb4 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -470,27 +470,24 @@ function SetupForPool(logger, poolOptions, setupFinished){ if (orphanMergeCommands.length > 0) finalRedisCommands = finalRedisCommands.concat(orphanMergeCommands); - if (balanceUpdateCommands.length > 0) finalRedisCommands = finalRedisCommands.concat(balanceUpdateCommands); - if (workerPayoutsCommand.length > 0) finalRedisCommands = finalRedisCommands.concat(workerPayoutsCommand); - if (roundsToDelete.length > 0) finalRedisCommands.push(['del'].concat(roundsToDelete)); - if (toBePaid !== 0) finalRedisCommands.push(['hincrbyfloat', coin + '_stats', 'totalPaid', (toBePaid / magnitude).toFixed(coinPrecision)]); + finalRedisCommands.push(['del', coin + '_finalRedisCommands']); + finalRedisCommands.push(['bgsave']); callback(null, magnitude, workerPayments, finalRedisCommands); - }); }, From 086ace75d738d037779f2c5d4eed69cfef76aabf Mon Sep 17 00:00:00 2001 From: "Eugene@ubuntu" Date: Sat, 5 Apr 2014 05:02:52 +0400 Subject: [PATCH 3/7] fix payment redis final cleanout issue - possible double spending - optimized.v2 --- libs/paymentProcessor.js | 68 ++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index 91bfeb4..3d3482a 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -52,6 +52,7 @@ function SetupForPool(logger, poolOptions, setupFinished){ var logSystem = 'Payments'; var logComponent = coin; + var processingPayments = true; var daemon; var redisClient; @@ -119,8 +120,28 @@ function SetupForPool(logger, poolOptions, setupFinished){ }); - - + /* Call redis to check if previous sendmany and/or redis cleanout commands completed successfully. + If sendmany worked fine but redis commands failed you HAVE TO run redis commands again + (manually) to prevent double payments. If sendmany failed too you can safely delete + coin + '_finalRedisCommands' string from redis to let pool calculate payments again. */ + function checkPreviousPaymentsStatus(callback) { + redisClient.get(coin + '_finalRedisCommands', function(error, reply) { + if (error){ + callback('Could not get finalRedisCommands - ' + JSON.stringify(error)); + return; + } + if (reply) { + callback('Payments stopped because of the critical error - failed commands saved in ' + + coin + '_finalRedisCommands redis set:\n' + reply); + return; + } else { + /* There was no error in previous sendmany and/or redis cleanout commands + so we can safely continue */ + processingPayments = false; + callback(); + } + }); + } /* Number.toFixed gives us the decimal places we want, but as a string. parseFloat turns it back into number @@ -140,6 +161,21 @@ function SetupForPool(logger, poolOptions, setupFinished){ async.waterfall([ + function(callback) { + if (processingPayments) { + checkPreviousPaymentsStatus(function(error){ + if (error) { + logger.error(logSystem, logComponent, error); + callback('Check finished - previous payments processing error'); + return; + } + callback(); + }); + return; + } + callback(); + }, + /* Call redis to get an array of rounds - which are coinbase transactions and block heights from submitted blocks. */ function(callback){ @@ -147,7 +183,7 @@ function SetupForPool(logger, poolOptions, setupFinished){ redisClient.smembers(coin + '_blocksPending', function(error, results){ if (error){ - logger.error(logSystem, logComponent, 'Could get blocks from redis ' + JSON.stringify(error)); + logger.error(logSystem, logComponent, 'Could not get blocks from redis ' + JSON.stringify(error)); callback('Check finished - redis error for getting blocks'); return; } @@ -491,30 +527,14 @@ function SetupForPool(logger, poolOptions, setupFinished){ }); }, - /* Call redis to check if previous sendmany and/or redis cleanout commands completed successfully. - If sendmany worked fine but redis commands failed you HAVE TO run redis commands again - (manually) to prevent double payments. If sendmany failed too you can safely delete - coin + '_finalRedisCommands' string from redis to let pool calculate payments again. */ function(magnitude, workerPayments, finalRedisCommands, callback) { - redisClient.get(coin + '_finalRedisCommands', function(error, reply) { + /* Save final redis cleanout commands in case something goes wrong during payments */ + redisClient.set(coin + '_finalRedisCommands', JSON.stringify(finalRedisCommands), function(error, reply) { if (error){ - callback('Check finished - error with redis getting finalRedisCommands' + JSON.stringify(error)); + callback('Check finished - error with saving finalRedisCommands' + JSON.stringify(error)); return; } - if (reply) { - callback('Check finished - previous sendmany and/or redis cleanout commands failed - ' + reply); - return; - } else { - /* There was no error in previous sendmany and/or redis cleanout commands - so we can safely continue */ - redisClient.set(coin + '_finalRedisCommands', JSON.stringify(finalRedisCommands), function(error, reply) { - if (error){ - callback('Check finished - error with saving finalRedisCommands' + JSON.stringify(error)); - return; - } - callback(null, magnitude, workerPayments, finalRedisCommands); - }); - } + callback(null, magnitude, workerPayments, finalRedisCommands); }); }, @@ -527,6 +547,7 @@ function SetupForPool(logger, poolOptions, setupFinished){ callback('Error with final redis commands for cleaning up ' + JSON.stringify(error)); return; } + processingPayments = false; logger.debug(logSystem, logComponent, 'Payments processing performed an interval'); }); }; @@ -548,6 +569,7 @@ function SetupForPool(logger, poolOptions, setupFinished){ logger.debug(logSystem, logComponent, 'Payments to be sent to: ' + JSON.stringify(addressAmounts)); + processingPayments = true; daemon.cmd('sendmany', ['', addressAmounts], function(results){ if (results[0].error){ From d9269f483ce70ba7cb2a77039c9c2fc324606929 Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 5 Apr 2014 14:19:02 -0600 Subject: [PATCH 4/7] Changed npm dependency to use git uri --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ebd0ec..a6abc57 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "url": "https://github.com/zone117x/node-open-mining-portal.git" }, "dependencies": { - "stratum-pool": "https://github.com/zone117x/node-stratum-pool/archive/master.tar.gz", + "stratum-pool": "git://github.com/zone117x/node-stratum-pool.git", "dateformat": "*", "node-json-minify": "*", "posix": "*", From 27289ba37faffa34d6177394051e05f4890910d5 Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 5 Apr 2014 14:27:05 -0600 Subject: [PATCH 5/7] Added check for config.json file existence --- init.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/init.js b/init.js index decf2cb..1a7a51b 100644 --- a/init.js +++ b/init.js @@ -17,6 +17,11 @@ var algos = require('stratum-pool/lib/algoProperties.js'); JSON.minify = JSON.minify || require("node-json-minify"); +if (!fs.existsSync('config.json')){ + console.log('config.json file does not exist. Read the installation/setup instructions.'); + return; +} + var portalConfig = JSON.parse(JSON.minify(fs.readFileSync("config.json", {encoding: 'utf8'}))); From 323c8b669df2427108c120438447eadc613ba031 Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 5 Apr 2014 15:47:00 -0600 Subject: [PATCH 6/7] Removed posix module from being installed by default --- init.js | 13 ++++++++++--- package.json | 1 - 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/init.js b/init.js index 1a7a51b..9cd58b2 100644 --- a/init.js +++ b/init.js @@ -4,7 +4,6 @@ var os = require('os'); var cluster = require('cluster'); var async = require('async'); -var posix = require('posix'); var PoolLogger = require('./libs/logUtil.js'); var BlocknotifyListener = require('./libs/blocknotifyListener.js'); var RedisBlocknotifyListener = require('./libs/redisblocknotifyListener.js'); @@ -41,10 +40,18 @@ try { //Try to give process ability to handle 100k concurrent connections try{ - posix.setrlimit('nofile', { soft: 100000, hard: 100000 }); + var posix = require('posix'); + try { + posix.setrlimit('nofile', { soft: 100000, hard: 100000 }); + } + catch(e){ + if (cluster.isMaster) + logger.warning('POSIX', 'Connection Limit', '(Safe to ignore) Must be ran as root to increase resource limits'); + } } catch(e){ - logger.warning('POSIX', 'Connection Limit', '(Safe to ignore) Must be ran as root to increase resource limits'); + if (cluster.isMaster) + logger.debug('POSIX', 'Connection Limit', '(Safe to ignore) POSIX module not installed and resource (connection) limit was not raised'); } diff --git a/package.json b/package.json index a6abc57..24e73b1 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "stratum-pool": "git://github.com/zone117x/node-stratum-pool.git", "dateformat": "*", "node-json-minify": "*", - "posix": "*", "redis": "*", "mysql": "*", "async": "*", From 575158f8586bc538703056ec29d11ff0ebb47dcd Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 5 Apr 2014 16:29:24 -0600 Subject: [PATCH 7/7] More error handling for blocknotify --- libs/blocknotifyListener.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libs/blocknotifyListener.js b/libs/blocknotifyListener.js index 921e1f4..4691c13 100644 --- a/libs/blocknotifyListener.js +++ b/libs/blocknotifyListener.js @@ -32,7 +32,16 @@ var listener = module.exports = function listener(options){ emitLog('Block listener connection ended'); - var message = JSON.parse(data); + 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); } @@ -42,7 +51,7 @@ var listener = module.exports = function listener(options){ }); } catch(e){ - emitLog('Block listener failed to parse message ' + data); + emitLog('Block listener had an error: ' + e); } });