diff --git a/.gitignore b/.gitignore index d35bbf7..88d9a09 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ -.idea/ \ No newline at end of file +.idea/ +config.json \ No newline at end of file diff --git a/README.md b/README.md index 66f9f49..75c9990 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ npm update #### 2) Configuration ##### Portal config -Inside the `config.json` file, ensure the default configuration will work for your environment. +Inside the `config_example.json` file, ensure the default configuration will work for your environment, then copy the file to `config.json`. Explanation for each field: ````javascript @@ -232,7 +232,9 @@ Description of options: } }, - "mpos": { //Enabled this and shares will be inserted into share table in a MySQL database + /* Enabled mpos and shares will be inserted into share table in a MySQL database. You may + also want to use the "emitInvalidBlockHashes" option below if you require it. */ + "mpos": { "enabled": false, "host": "localhost", //MySQL db host "port": 3306, //MySQL db port @@ -267,6 +269,9 @@ Description of options: detects those and disconnects them. */ "connectionTimeout": 600, //Remove workers that haven't been in contact for this many seconds + /* Sometimes you want the block hashes even for shares that aren't block candidates. */ + "emitInvalidBlockHashes": false, + /* If a worker is submitting a high threshold of invalid shares we can temporarily ban them to reduce system/network load. Also useful to fight against flooding attacks. */ "banning": { diff --git a/coins/365coin.json b/coins/365coin.json new file mode 100644 index 0000000..c208e44 --- /dev/null +++ b/coins/365coin.json @@ -0,0 +1,5 @@ +{ + "name": "365coin", + "symbol": "365", + "algorithm": "keccak" +} \ No newline at end of file diff --git a/coins/helixcoin.json b/coins/helixcoin.json index 9fc6f85..65302ec 100644 --- a/coins/helixcoin.json +++ b/coins/helixcoin.json @@ -1,5 +1,5 @@ { "name": "Helixcoin", "symbol": "HXC", - "algorithm": "max" + "algorithm": "keccak" } \ No newline at end of file diff --git a/config.json b/config_example.json similarity index 100% rename from config.json rename to config_example.json diff --git a/init.js b/init.js index 982b358..decf2cb 100644 --- a/init.js +++ b/init.js @@ -3,15 +3,18 @@ var path = require('path'); 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 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'); -var WorkerListener = require('./libs/workerListener.js'); -var PoolWorker = require('./libs/poolWorker.js'); -var PaymentProcessor = require('./libs/paymentProcessor.js'); -var Website = require('./libs/website.js'); +var WorkerListener = require('./libs/workerListener.js'); +var PoolWorker = require('./libs/poolWorker.js'); +var PaymentProcessor = require('./libs/paymentProcessor.js'); +var Website = require('./libs/website.js'); + +var algos = require('stratum-pool/lib/algoProperties.js'); + JSON.minify = JSON.minify || require("node-json-minify"); var portalConfig = JSON.parse(JSON.minify(fs.readFileSync("config.json", {encoding: 'utf8'}))); @@ -88,6 +91,12 @@ var buildPoolConfigs = function(){ var coinProfile = JSON.parse(JSON.minify(fs.readFileSync(coinFilePath, {encoding: 'utf8'}))); poolOptions.coin = coinProfile; 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; }; diff --git a/libs/mposCompatibility.js b/libs/mposCompatibility.js index 4b75adb..26b30a2 100644 --- a/libs/mposCompatibility.js +++ b/libs/mposCompatibility.js @@ -70,7 +70,7 @@ module.exports = function(logger, poolConfig){ isValidBlock ? 'Y' : 'N', shareData.difficulty, typeof(shareData.error) === 'undefined' ? null : shareData.error, - typeof(shareData.solution) === 'undefined' ? '' : shareData.solution + shareData.blockHash ? shareData.blockHash : (shareData.blockHashInvalid ? shareData.blockHashInvalid : '') ]; connection.query( 'INSERT INTO `shares` SET time = NOW(), rem_host = ?, username = ?, our_result = ?, upstream_result = ?, difficulty = ?, reason = ?, solution = ?', diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index af67f6a..3f1f2cb 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -160,7 +160,7 @@ function SetupForPool(logger, poolOptions, setupFinished){ var details = r.split(':'); return { category: details[0].category, - solution: details[0], + blockHash: details[0], txHash: details[1], height: details[2], reward: details[3], @@ -191,20 +191,20 @@ function SetupForPool(logger, poolOptions, setupFinished){ txDetails.forEach(function(tx, i){ var round = rounds[i]; - if (tx.error && tx.error.code === -5 || round.solution !== tx.result.blockhash){ + if (tx.error && tx.error.code === -5 || round.blockHash !== tx.result.blockhash){ /* Block was dropped from coin daemon even after it happily accepted it earlier. */ //If we find another block at the same height then this block was drop-kicked orphaned var dropKicked = rounds.filter(function(r){ - return r.height === round.height && r.solution !== round.solution && r.category !== 'dropkicked'; + return r.height === round.height && r.blockHash !== round.blockHash && r.category !== 'dropkicked'; }).length > 0; if (dropKicked){ logger.warning(logSystem, logComponent, 'A block was drop-kicked orphaned' - + ' - we found a better block at the same height, solution ' - + round.solution + " round " + round.height); + + ' - we found a better block at the same height, blockHash ' + + round.blockHash + " round " + round.height); round.category = 'dropkicked'; } else{ @@ -298,7 +298,7 @@ function SetupForPool(logger, poolOptions, setupFinished){ if (!workerShares){ logger.error(logSystem, logComponent, 'No worker shares for round: ' - + round.height + ' solution: ' + round.solution); + + round.height + ' blockHash: ' + round.blockHash); return; } @@ -486,6 +486,7 @@ function SetupForPool(logger, poolOptions, setupFinished){ if (toBePaid !== 0) finalRedisCommands.push(['hincrbyfloat', coin + '_stats', 'totalPaid', (toBePaid / magnitude).toFixed(coinPrecision)]); + finalRedisCommands.push(['bgsave']); callback(null, magnitude, workerPayments, finalRedisCommands); diff --git a/libs/poolWorker.js b/libs/poolWorker.js index fdcde2f..453ea08 100644 --- a/libs/poolWorker.js +++ b/libs/poolWorker.js @@ -118,11 +118,11 @@ module.exports = function(logger){ var shareData = JSON.stringify(data); - if (data.solution && !isValidBlock) - logger.debug(logSystem, logComponent, logSubCat, 'We thought a block solution was found but it was rejected by the daemon, share data: ' + shareData); + if (data.blockHash && !isValidBlock) + logger.debug(logSystem, logComponent, logSubCat, 'We thought a block was found but it was rejected by the daemon, share data: ' + shareData); else if (isValidBlock) - logger.debug(logSystem, logComponent, logSubCat, 'Block solution found: ' + data.solution); + logger.debug(logSystem, logComponent, logSubCat, 'Block found: ' + data.blockHash); if (isValidShare) diff --git a/libs/shareProcessor.js b/libs/shareProcessor.js index 938bd48..57df98e 100644 --- a/libs/shareProcessor.js +++ b/libs/shareProcessor.js @@ -61,10 +61,10 @@ module.exports = function(logger, poolConfig){ if (isValidBlock){ redisCommands.push(['rename', coin + '_shares:roundCurrent', coin + '_shares:round' + shareData.height]); - redisCommands.push(['sadd', coin + '_blocksPending', [shareData.solution, shareData.tx, shareData.height, shareData.reward].join(':')]); + redisCommands.push(['sadd', coin + '_blocksPending', [shareData.blockHash, shareData.txHash, shareData.height, shareData.reward].join(':')]); redisCommands.push(['hincrby', coin + '_stats', 'validBlocks', 1]); } - else if (shareData.solution){ + else if (shareData.blockHash){ redisCommands.push(['hincrby', coin + '_stats', 'invalidBlocks', 1]); }