From 8eae3ea6ee920b2fb465c4456a7d0457d27b40b0 Mon Sep 17 00:00:00 2001 From: hackyminer Date: Mon, 21 May 2018 20:43:41 +0900 Subject: [PATCH 1/9] add hdac coin --- coins/hdac.json | 11 ++++ config-hdac.json | 121 ++++++++++++++++++++++++++++++++++++++++ pool_configs/h-dac.json | 78 ++++++++++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 coins/hdac.json create mode 100644 config-hdac.json create mode 100644 pool_configs/h-dac.json diff --git a/coins/hdac.json b/coins/hdac.json new file mode 100644 index 000000000..079ca1a37 --- /dev/null +++ b/coins/hdac.json @@ -0,0 +1,11 @@ +{ + "name": "HDAC", + "symbol": "DAC", + "algorithm": "lyra2rev2", + /** + * @Hdac + * Add the 'reward' key value for ePoW, a unique consensus algorithm of Hdac. + * This annotation should be removed when reflecting on the server due to the JSON formatting convention. + */ + "reward": "ePoW" +} \ No newline at end of file diff --git a/config-hdac.json b/config-hdac.json new file mode 100644 index 000000000..207cacc7f --- /dev/null +++ b/config-hdac.json @@ -0,0 +1,121 @@ +{ + "logLevel": "debug", + "logColors": true, + + "cliHost": "127.0.0.1", + "cliPort": 17117, + + "clustering": { + "enabled": true, + "forks": "auto" + }, + + /** + * @Hdac + * Add the 'blockWindowSizeRefreshInterval' key value. + * This is used to set the schedule period associated with ePOW application. + * This annotation should be removed when reflecting on the server due to the JSON formatting convention. + */ + "defaultPoolConfigs": { + "blockRefreshInterval": 1000, + "blockWindowSizeRefreshInterval": 50000, + "jobRebroadcastTimeout": 55, + "connectionTimeout": 600, + "emitInvalidBlockHashes": false, + "validateWorkerUsername": true, + "tcpProxyProtocol": false, + "banning": { + "enabled": false, + "time": 600, + "invalidPercent": 50, + "checkThreshold": 500, + "purgeInterval": 300 + }, + "redis": { + "host": "127.0.0.1", + "port": 6379 + } + }, + + "website": { + "enabled": true, + "host": "0.0.0.0", + "port": 8088, + "stratumHost": "0.0.0.0", + "stats": { + "updateInterval": 60, + "historicalRetention": 43200, + "hashrateWindow": 300 + }, + "adminCenter": { + "enabled": true, + "password": "password" + } + }, + + "redis": { + "host": "127.0.0.1", + "port": 6379 + }, + + "switching": { + "switch1": { + "enabled": false, + "algorithm": "sha256", + "ports": { + "3333": { + "diff": 10, + "varDiff": { + "minDiff": 16, + "maxDiff": 512, + "targetTime": 15, + "retargetTime": 90, + "variancePercent": 30 + } + } + } + }, + "switch2": { + "enabled": false, + "algorithm": "scrypt", + "ports": { + "4444": { + "diff": 10, + "varDiff": { + "minDiff": 16, + "maxDiff": 512, + "targetTime": 15, + "retargetTime": 90, + "variancePercent": 30 + } + } + } + }, + "switch3": { + "enabled": false, + "algorithm": "x11", + "ports": { + "5555": { + "diff": 0.001, + "varDiff": { + "minDiff": 0.001, + "maxDiff": 1, + "targetTime": 15, + "retargetTime": 60, + "variancePercent": 30 + } + } + } + } + }, + + "profitSwitch": { + "enabled": false, + "updateInterval": 600, + "depth": 0.90, + "usePoloniex": true, + "useCryptsy": true, + "useMintpal": true, + "useBittrex": true + } +} diff --git a/pool_configs/h-dac.json b/pool_configs/h-dac.json new file mode 100644 index 000000000..59c00dfe8 --- /dev/null +++ b/pool_configs/h-dac.json @@ -0,0 +1,78 @@ +{ + "enabled": true, + "coin": "hdac.json", + + "address": "HBblahblahblahblahblahblahblahblah", + + "rewardRecipients": { + "HBblahblahblahblahblahblahblahblah": 1 + }, + + "paymentProcessing": { + "enabled": true, + "paymentInterval": 20, + "minimumPayment": 70, + "daemon": { + "host": "127.0.0.1", + "port": "8822", + "user": "rpcuser", + "password": "rpcpass" + } + }, + + "ports": { + "3008": { + "diff": 32.00000 + }, + "3333": { + "diff": 64.00000, + "varDiff": { + "minDiff": 64.00000, + "maxDiff": 256, + "targetTime": 15, + "retargetTime": 90, + "variancePercent": 30 + } + }, + "3256": { + "diff": 128 + } + }, + + "daemons": [ + { + "host": "127.0.0.1", + "port": "8822", + "user": "rpcuser", + "password": "rpcpass" + } + ], + + "p2p": { + "enabled": false, + "host": "127.0.0.1", + "port": 8822, + "disableTransactions": true + }, + + "mposMode": { + "enabled": false, + "host": "set your mysql host", + "port": 3306, + "user": "set your mysql user id", + "password": "set your mysql password", + "database": "mpos", + "checkPassword": true, + "autoCreateWorker": false + }, + + "mongoMode": { + "enabled": false, + "host": "127.0.0.1", + "user": "", + "pass": "", + "database": "hdac", + "authMechanism": "DEFAULT" + } + +} From a836c1cb0fb1fcd9f997fe320b46ac0578ca2641 Mon Sep 17 00:00:00 2001 From: hackyminer Date: Mon, 21 May 2018 22:15:36 +0900 Subject: [PATCH 2/9] use Hdactech/stratum-pool --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 597f6f26e..702af0b56 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "nonce": "^1.0.4", "redis": "^2.7.1", "request": "^2.83.0", - "stratum-pool": "git://github.com/foxer666/node-stratum-pool.git" + "stratum-pool": "git://github.com/Hdactech/stratum-pool.git" }, "engines": { "node": ">=8.1.4" From 423eaa6d2b3dd51ea8667d50d34711f60cebf428 Mon Sep 17 00:00:00 2001 From: hackyminer Date: Wed, 23 May 2018 00:18:11 +0900 Subject: [PATCH 3/9] check tx.result validity first --- libs/paymentProcessor.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index cedd542c5..e9090a57c 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -234,16 +234,16 @@ function SetupForPool(logger, poolOptions, setupFinished) { round.category = 'kicked'; return; } - else if (!tx.result.details || (tx.result.details && tx.result.details.length === 0)) { - logger.warning(logSystem, logComponent, 'Daemon reports no details for transaction: ' + round.txHash); - round.category = 'kicked'; - return; - } else if (tx.error || !tx.result) { logger.error(logSystem, logComponent, 'Odd error with gettransaction ' + round.txHash + ' ' + JSON.stringify(tx)); return; } + else if (!tx.result.details || (tx.result.details && tx.result.details.length === 0)) { + logger.warning(logSystem, logComponent, 'Daemon reports no details for transaction: ' + round.txHash); + round.category = 'kicked'; + return; + } var generationTx = tx.result.details.filter(function (tx) { return tx.address === poolOptions.address; From 587ed1ab9b6ce1b45876e0b22bee15115ce4ccb9 Mon Sep 17 00:00:00 2001 From: hackyminer Date: Wed, 23 May 2018 00:41:21 +0900 Subject: [PATCH 4/9] add payment only runner --- pay.js | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 pay.js diff --git a/pay.js b/pay.js new file mode 100644 index 000000000..c1eabc9ab --- /dev/null +++ b/pay.js @@ -0,0 +1,216 @@ +var fs = require('fs'); +var path = require('path'); +var os = require('os'); +var cluster = require('cluster'); + +var async = require('async'); + +var PoolLogger = require('./libs/logUtil.js'); +var PaymentProcessor = require('./libs/paymentProcessor.js'); + +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'}))); +var poolConfigs; + + +var logger = new PoolLogger({ + logLevel: portalConfig.logLevel, + logColors: portalConfig.logColors +}); + + + + +try { + require('newrelic'); + if (cluster.isMaster) + logger.debug('NewRelic', 'Monitor', 'New Relic initiated'); +} catch(e) {} + + +//Try to give process ability to handle 100k concurrent connections +try{ + 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'); + } + finally { + // Find out which user used sudo through the environment variable + var uid = parseInt(process.env.SUDO_UID); + // Set our server's uid to that user + if (uid) { + process.setuid(uid); + logger.debug('POSIX', 'Connection Limit', 'Raised to 100K concurrent connections, now running as non-root user: ' + process.getuid()); + } + } +} +catch(e){ + if (cluster.isMaster) + logger.debug('POSIX', 'Connection Limit', '(Safe to ignore) POSIX module not installed and resource (connection) limit was not raised'); +} + + +if (cluster.isWorker){ + + switch(process.env.workerType){ + case 'pool': + new PoolWorker(logger); + break; + case 'paymentProcessor': + new PaymentProcessor(logger); + break; + case 'website': + new Website(logger); + break; + case 'profitSwitch': + new ProfitSwitch(logger); + break; + } + + return; +} + + +//Read all pool configs from pool_configs and join them with their coin profile +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; + 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.coinFileName, 'could not find file: ' + coinFilePath); + return; + } + + var coinProfile = JSON.parse(JSON.minify(fs.readFileSync(coinFilePath, {encoding: 'utf8'}))); + poolOptions.coin = coinProfile; + poolOptions.coin.name = poolOptions.coin.name.toLowerCase(); + + 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; + } + + for (var option in portalConfig.defaultPoolConfigs){ + if (!(option in poolOptions)){ + var toCloneOption = portalConfig.defaultPoolConfigs[option]; + var clonedOption = {}; + if (toCloneOption.constructor === Object) { + Object.assign(clonedOption, toCloneOption); + } else { + clonedOption = toCloneOption; + } + poolOptions[option] = clonedOption; + } + } + + + configs[poolOptions.coin.name] = poolOptions; + + if (!(coinProfile.algorithm in algos)){ + logger.error('Master', coinProfile.name, 'Cannot run a pool for unsupported algorithm "' + coinProfile.algorithm + '"'); + delete configs[poolOptions.coin.name]; + } + + }); + return configs; +}; + + + +var startPaymentProcessor = function(){ + + var enabledForAny = false; + for (var pool in poolConfigs){ + var p = poolConfigs[pool]; + var enabled = p.enabled && p.paymentProcessing && p.paymentProcessing.enabled; + if (enabled){ + enabledForAny = true; + break; + } + } + + console.log(poolConfigs); + + if (!enabledForAny) + return; + + var worker = cluster.fork({ + workerType: 'paymentProcessor', + pools: JSON.stringify(poolConfigs) + }); + worker.on('exit', function(code, signal){ + logger.error('Master', 'Payment Processor', 'Payment processor died, spawning replacement...'); + setTimeout(function(){ + startPaymentProcessor(poolConfigs); + }, 2000); + }); +}; + + +(function init(){ + + poolConfigs = buildPoolConfigs(); + + startPaymentProcessor(); + +})(); From ab3b1bb161e9135ede4d78e14ca7851e39f9db3d Mon Sep 17 00:00:00 2001 From: hackyminer Date: Wed, 23 May 2018 08:15:42 +0900 Subject: [PATCH 5/9] DO NOT MERGE temorary change repo for stratum-pool --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 702af0b56..e76157fef 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "nonce": "^1.0.4", "redis": "^2.7.1", "request": "^2.83.0", - "stratum-pool": "git://github.com/Hdactech/stratum-pool.git" + "stratum-pool": "git://github.com/OpenCommunityCoin/node-stratum-pool.git" }, "engines": { "node": ">=8.1.4" From 12897c8d12cf374e5263007e02b8422ab6610c8e Mon Sep 17 00:00:00 2001 From: hackyminer Date: Wed, 23 May 2018 08:21:11 +0900 Subject: [PATCH 6/9] use payment_configs/ as configDir for the pay.js --- pay.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pay.js b/pay.js index c1eabc9ab..fb5ac0052 100644 --- a/pay.js +++ b/pay.js @@ -86,7 +86,7 @@ if (cluster.isWorker){ //Read all pool configs from pool_configs and join them with their coin profile var buildPoolConfigs = function(){ var configs = {}; - var configDir = 'pool_configs/'; + var configDir = 'payment_configs/'; var poolConfigFiles = []; From 17f487cc401626d588a7f6844910f876649bc2d6 Mon Sep 17 00:00:00 2001 From: hackyminer Date: Wed, 23 May 2018 10:05:16 +0900 Subject: [PATCH 7/9] fixed possible crash bug. --- libs/poolWorker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/poolWorker.js b/libs/poolWorker.js index 67df9043a..f06708271 100644 --- a/libs/poolWorker.js +++ b/libs/poolWorker.js @@ -151,7 +151,7 @@ module.exports = function(logger){ else { pool.daemon.cmd('validateaddress', [workerName], function (results) { var isValid = results.filter(function (r) { - return r.response.isvalid + return r.response && r.response.isvalid; }).length > 0; authCallback(isValid); }); From 16033aa0d31a350405667b05356ad244c7d9264f Mon Sep 17 00:00:00 2001 From: globaltoken Date: Fri, 2 Mar 2018 07:41:06 +0100 Subject: [PATCH 8/9] Updated to new Core 0.16 Format (getaddressinfo) Since the new Wallet release of Bitcoin Core, they introduced a new Validation format for addresses. Validateaddress is not longer working. --- libs/paymentProcessor.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index e9090a57c..f1aa183b2 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -74,6 +74,17 @@ function SetupForPool(logger, poolOptions, setupFinished) { callback(true); } else if (!result.response || !result.response.ismine) { + daemon.cmd('getaddressinfo', [poolOptions.address], function(result) { + if (result.error){ + logger.error(logSystem, logComponent, 'Error with payment processing daemon ' + JSON.stringify(result.error)); + callback(true); + } + else if (!result.response || !result.response.ismine) { + logger.error(logSystem, logComponent, + 'Daemon does not own pool address - payment processing can not be done with this daemon, ' + + JSON.stringify(result.response)); + callback(true); + } logger.error(logSystem, logComponent, 'Daemon does not own pool address - payment processing can not be done with this daemon, ' + JSON.stringify(result.response)); From d4f8ab50d7899dcc50bb590ec81a9b2afcb1a3f9 Mon Sep 17 00:00:00 2001 From: globaltoken Date: Fri, 2 Mar 2018 07:58:27 +0100 Subject: [PATCH 9/9] Update paymentProcessor.js --- libs/paymentProcessor.js | 29 ++++++++++++++++------------- pool_configs/h-dac.json | 16 ++++++++-------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index f1aa183b2..315f886f7 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -74,21 +74,24 @@ function SetupForPool(logger, poolOptions, setupFinished) { callback(true); } else if (!result.response || !result.response.ismine) { - daemon.cmd('getaddressinfo', [poolOptions.address], function(result) { - if (result.error){ - logger.error(logSystem, logComponent, 'Error with payment processing daemon ' + JSON.stringify(result.error)); - callback(true); - } - else if (!result.response || !result.response.ismine) { - logger.error(logSystem, logComponent, - 'Daemon does not own pool address - payment processing can not be done with this daemon, ' - + JSON.stringify(result.response)); - callback(true); - } logger.error(logSystem, logComponent, - 'Daemon does not own pool address - payment processing can not be done with this daemon, ' + 'Validateaddress failed, trying for newer getaddressinfo Command ..., ' + JSON.stringify(result.response)); - callback(true); + daemon.cmd('getaddressinfo', [poolOptions.address], function(result) { + if (result.error){ + logger.error(logSystem, logComponent, 'Error with payment processing daemon, getaddressinfo failed ... ' + JSON.stringify(result.error)); + callback(true); + } + else if (!result.response || !result.response.ismine) { + logger.error(logSystem, logComponent, + 'Daemon does not own pool address - payment processing can not be done with this daemon, ' + + JSON.stringify(result.response)); + callback(true); + } + else{ + callback() + } + }, true); } else { callback() diff --git a/pool_configs/h-dac.json b/pool_configs/h-dac.json index 59c00dfe8..317f1ee7c 100644 --- a/pool_configs/h-dac.json +++ b/pool_configs/h-dac.json @@ -2,21 +2,21 @@ "enabled": true, "coin": "hdac.json", - "address": "HBblahblahblahblahblahblahblahblah", + "address": "HBSREYHSZUoLELycQcpGTFnwYPcbvfeywx", "rewardRecipients": { - "HBblahblahblahblahblahblahblahblah": 1 + "HBSREYHSZUoLELycQcpGTFnwYPcbvfeywx": 1 }, "paymentProcessing": { - "enabled": true, + "enabled": false, "paymentInterval": 20, "minimumPayment": 70, "daemon": { "host": "127.0.0.1", "port": "8822", - "user": "rpcuser", - "password": "rpcpass" + "user": "bab", + "password": "foobar123" } }, @@ -43,15 +43,15 @@ { "host": "127.0.0.1", "port": "8822", - "user": "rpcuser", - "password": "rpcpass" + "user": "bab", + "password": "foobar123" } ], "p2p": { "enabled": false, "host": "127.0.0.1", - "port": 8822, + "port": 19333, "disableTransactions": true },