diff --git a/config_examples/monero.json b/config_examples/monero.json index f3b539c..9c745ca 100644 --- a/config_examples/monero.json +++ b/config_examples/monero.json @@ -150,6 +150,42 @@ "trustProxyIP": true }, + "mining": { + "active": "solo", + "backends": { + "solo": { + "enabled": true, + "type": "solo", + "host": "127.0.0.1", + "port": 18081 + }, + "salvium": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "salvium", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "SC1T_PARENT_POOL_ADDRESS_HERE" + }, + "monero": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "monero", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "42_PARENT_POOL_ADDRESS_HERE" + }, + "zephyr": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "zephyr", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "ZEPH_PARENT_POOL_ADDRESS_HERE" + } + } + }, + "miningSource": { "host": "127.0.0.1", "port": 18081 diff --git a/config_examples/peya.json b/config_examples/peya.json index cd5fe9d..02cbca8 100644 --- a/config_examples/peya.json +++ b/config_examples/peya.json @@ -119,6 +119,42 @@ "trustProxyIP": true }, + "mining": { + "active": "solo", + "backends": { + "solo": { + "enabled": true, + "type": "solo", + "host": "127.0.0.1", + "port": 37777 + }, + "salvium": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "salvium", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "SC1T_PARENT_POOL_ADDRESS_HERE" + }, + "monero": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "monero", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "42_PARENT_POOL_ADDRESS_HERE" + }, + "zephyr": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "zephyr", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "ZEPH_PARENT_POOL_ADDRESS_HERE" + } + } + }, + "miningSource": { "host": "127.0.0.1", "port": 37777 diff --git a/config_examples/salvium.json b/config_examples/salvium.json index fc0a667..620e2c9 100644 --- a/config_examples/salvium.json +++ b/config_examples/salvium.json @@ -145,6 +145,42 @@ "trustProxyIP": true }, + "mining": { + "active": "solo", + "backends": { + "solo": { + "enabled": true, + "type": "solo", + "host": "127.0.0.1", + "port": 11812 + }, + "salvium": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "salvium", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "SC1T_PARENT_POOL_ADDRESS_HERE" + }, + "monero": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "monero", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "42_PARENT_POOL_ADDRESS_HERE" + }, + "zephyr": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "zephyr", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "ZEPH_PARENT_POOL_ADDRESS_HERE" + } + } + }, + "miningSource": { "host": "127.0.0.1", "port": 11812 diff --git a/config_examples/zephyr.json b/config_examples/zephyr.json index de760d8..f00e52d 100644 --- a/config_examples/zephyr.json +++ b/config_examples/zephyr.json @@ -111,6 +111,42 @@ "trustProxyIP": true }, + "mining": { + "active": "solo", + "backends": { + "solo": { + "enabled": true, + "type": "solo", + "host": "127.0.0.1", + "port": 17767 + }, + "salvium": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "salvium", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "SC1T_PARENT_POOL_ADDRESS_HERE" + }, + "monero": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "monero", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "42_PARENT_POOL_ADDRESS_HERE" + }, + "zephyr": { + "enabled": false, + "type": "merge-mining", + "parentCoin": "zephyr", + "host": "127.0.0.1", + "port": 37777, + "walletAddress": "ZEPH_PARENT_POOL_ADDRESS_HERE" + } + } + }, + "miningSource": { "host": "127.0.0.1", "port": 17767 diff --git a/lib/miningBackends.js b/lib/miningBackends.js new file mode 100644 index 0000000..7687a5c --- /dev/null +++ b/lib/miningBackends.js @@ -0,0 +1,87 @@ +function getLegacySoloBackend() { + return { + name: 'solo', + type: 'solo', + host: (config.miningSource && config.miningSource.host) || config.daemon.host, + port: (config.miningSource && config.miningSource.port) || config.daemon.port, + alwaysPoll: (config.miningSource && config.miningSource.alwaysPoll) || config.daemon.alwaysPoll || false, + walletAddress: null + }; +} + +function getConfiguredBackends() { + if (!config.mining || !config.mining.backends) { + return null; + } + return config.mining.backends; +} + +function getActiveBackendName(backends) { + if (config.mining && config.mining.active) { + return config.mining.active; + } + + let enabled = Object.keys(backends).filter(function (name) { + return backends[name] && backends[name].enabled; + }); + + if (enabled.length === 0) { + throw new Error('No enabled mining backend configured'); + } + + return enabled[0]; +} + +function normalizeBackend(name, backend) { + return { + name: name, + type: backend.type || (name === 'solo' ? 'solo' : 'merge-mining'), + parentCoin: backend.parentCoin || null, + host: backend.host, + port: backend.port, + alwaysPoll: backend.alwaysPoll || false, + walletAddress: backend.walletAddress || null + }; +} + +function getActiveMiningBackend() { + let backends = getConfiguredBackends(); + if (!backends) { + return getLegacySoloBackend(); + } + + let activeName = getActiveBackendName(backends); + let backend = backends[activeName]; + if (!backend) { + throw new Error('Active mining backend "' + activeName + '" is not defined'); + } + if (!backend.enabled) { + throw new Error('Active mining backend "' + activeName + '" is disabled'); + } + if (!backend.host || !backend.port) { + throw new Error('Active mining backend "' + activeName + '" is missing host/port'); + } + + return normalizeBackend(activeName, backend); +} +exports.getActiveMiningBackend = getActiveMiningBackend; + +function getMiningRpcConfig() { + let backend = getActiveMiningBackend(); + return { + host: backend.host, + port: backend.port + }; +} +exports.getMiningRpcConfig = getMiningRpcConfig; + +function getMiningTemplateAddress(defaultAddress) { + let backend = getActiveMiningBackend(); + return backend.walletAddress || defaultAddress; +} +exports.getMiningTemplateAddress = getMiningTemplateAddress; + +function isSoloMiningBackend() { + return getActiveMiningBackend().type === 'solo'; +} +exports.isSoloMiningBackend = isSoloMiningBackend; diff --git a/lib/miningSource.js b/lib/miningSource.js index 2617c99..7dcbec7 100644 --- a/lib/miningSource.js +++ b/lib/miningSource.js @@ -1,10 +1,10 @@ let utils = require('./utils.js'); let async = require('async'); let apiInterfaces = require('./apiInterfaces.js')(config.daemon, config.wallet, config.api); +let miningBackends = require('./miningBackends.js'); let lastHash; let POOL_NONCE_SIZE = 16 + 1; // +1 for old XMR/new TRTL bugs -let miningConfig = config.miningSource || config.daemon; let logSystem = 'miningSource'; let blockData = JSON.stringify({ @@ -17,6 +17,15 @@ let blockData = JSON.stringify({ require('./exceptionWriter.js')(logSystem); function runInterval () { + let miningConfig; + try { + miningConfig = miningBackends.getActiveMiningBackend(); + } catch (e) { + log('error', logSystem, 'Invalid mining backend configuration: %s', [e.message]); + setTimeout(runInterval, 3000); + return; + } + async.waterfall([ function (callback) { apiInterfaces.jsonHttpRequest(miningConfig.host, miningConfig.port, blockData, function (err, res) { @@ -29,7 +38,7 @@ function runInterval () { let hash = res.result.block_header.hash.toString('hex'); if (!lastHash || lastHash !== hash) { lastHash = hash; - log('info', logSystem, '%s found new hash %s', [config.coin, hash]); + log('info', logSystem, '%s found new hash %s via %s', [config.coin, hash, miningConfig.name]); callback(null, true); return; } else if (miningConfig.alwaysPoll || config.daemon.alwaysPoll || false) { @@ -53,7 +62,7 @@ function runInterval () { method: 'getblocktemplate', params: { reserve_size: POOL_NONCE_SIZE, - wallet_address: utils.getPoolTemplateAddress() + wallet_address: miningBackends.getMiningTemplateAddress(utils.getPoolTemplateAddress()) } }); apiInterfaces.jsonHttpRequest(miningConfig.host, miningConfig.port, templateData, function (err, res) { diff --git a/lib/pool.js b/lib/pool.js index cae1e29..65fde3e 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -14,6 +14,7 @@ let async = require('async'); let apiInterfaces = require('./apiInterfaces.js')(config.daemon, config.wallet, config.api); let notifications = require('./notifications.js'); let utils = require('./utils.js'); +let miningBackends = require('./miningBackends.js'); config.hashingUtil = config.hashingUtil || false; let cnHashing = require('cryptonight-hashing'); @@ -420,7 +421,7 @@ Miner.prototype = { height: blockTemplate.height, submissions: [] }; - if (this.lastBlockHeight === blockTemplate.height && !this.pendingDifficulty && this.cachedJob !== null && !config.daemon.alwaysPoll) { + if (this.lastBlockHeight === blockTemplate.height && !this.pendingDifficulty && this.cachedJob !== null && !miningBackends.getActiveMiningBackend().alwaysPoll) { return this.cachedJob; } let blob = this.proxy ? blockTemplate.nextBlobWithChildNonce() : blockTemplate.nextBlob(); @@ -1048,7 +1049,7 @@ function processShare (miner, job, blockTemplate, params) { ); recordShareData(miner, job, hashDiff.toString(), true, blockFastHash, shareType, blockTemplate); } - }); + }, miningBackends.getMiningRpcConfig()); } else if (hashDiff < jobDifficulty) { log('warn', logSystem, 'Rejected low difficulty share of %s from %s@%s', [hashDiff.toString(), miner.login, miner.ip]); return false;