diff --git a/Example_MergeMining.json b/Example_MergeMining.json deleted file mode 100644 index 74777c4..0000000 --- a/Example_MergeMining.json +++ /dev/null @@ -1,419 +0,0 @@ -{ - "poolHost": "your.pool.host", - "coin": "Arqma", - "symbol": "ARQ", - "coinUnits": 1000000000, - "coinDecimalPlaces": 9, - "coinDifficultyTarget": 120, - "blockchainExplorer": "http://blockexplorer.arqma.com/block/{id}", - "transactionExplorer": "http://blockexplorer.arqma.com/tx/{id}", - "includeHeight": false, - "includeAlgo": null, - "isRandomX": false, - "daemonType": "default", - "cnAlgorithm": "cryptonight_pico", - "cnVariant": 2, - "cnBlobType": 0, - - "logging": { - "files": { - "level": "info", - "directory": "logs", - "flushInterval": 5 - }, - "console": { - "level": "info", - "colors": true - } - }, - "childPools": [{ - "poolAddress": "** Your pool wallet address **", - "pubAddressPrefix": null, - "intAddressPrefix": null, - "subAddressPrefix": null, - "coin": "CyprusCoin", - "childDaemon": { - "host": "1.2.3.4", - "port": 11975 - }, - "pattern": "^XCY", - "blockchainExplorer": "http://explorer.mycypruscoin.com/?hash={id}#blockchain_block", - "transactionExplorer": "http://explorer.mycypruscoin.com/?hash={id}#blockchain_transaction", - "api": "https://your.pool.host/apiMerged1", - "enabled": true - }, - { - "poolAddress": "** Your pool wallet address **", - "pubAddressPrefix": null, - "intAddressPrefix": null, - "subAddressPrefix": null, - "coin": "Turtlecoin", - "childDaemon": { - "host": "1.2.3.4", - "port": 11898 - }, - "pattern": "^TRTL", - "blockchainExplorer": "https://explorer.turtlecoin.lol/block.html?hash={id}", - "transactionExplorer": "https://explorer.turtlecoin.lol/block.html?hash={id}", - "api": "https://your.pool.host/apiMerged2", - "enabled": true - }, - { - "poolAddress": "** Your pool wallet address **", - "pubAddressPrefix": null, - "intAddressPrefix": null, - "subAddressPrefix": null, - "coin": "Plenteum", - "childDaemon": { - "host": "1.2.3.4", - "port": 44016 - }, - "pattern": "^Pl", - "blockchainExplorer": "http://block-explorer.plenteum.com/?hash={id}#blockchain_block", - "transactionExplorer": "http://block-explorer.plenteum.com/?hash={id}#blockchain_transaction", - "api": "https://your.pool.host/apiMerged3", - "enabled": true - }, - { - "poolAddress": "** Your pool wallet address **", - "pubAddressPrefix": null, - "intAddressPrefix": null, - "subAddressPrefix": null, - "coin": "Iridium", - "childDaemon": { - "host": "1.2.3.4", - "port": 13007 - }, - "pattern": "^ir", - "blockchainExplorer": "http://explorer.ird.cash/?hash={id}#block", - "transactionExplorer": "http://explorer.ird.cash/?hash={id}#transaction", - "api": "https://your.pool.host/apiMerged4", - "enabled": true - }, - { - "poolAddress": "** Your pool wallet address **", - "pubAddressPrefix": null, - "intAddressPrefix": null, - "subAddressPrefix": null, - "coin": "Tritanium", - "childDaemon": { - "host": "1.2.3.4", - "port": 16123 - }, - "pattern": "^Tri", - "blockchainExplorer": "http://www.tritaniumcoin.com/?hash={id}#blockchain_block", - "transactionExplorer": "http://www.tritaniumcoin.com/?hash={id}#blockchain_transaction", - "api": "https://your.pool.host/apiMerged5", - "enabled": true - }, - { - "poolAddress": "** Your pool wallet address **", - "pubAddressPrefix": null, - "intAddressPrefix": null, - "subAddressPrefix": null, - "coin": "WrkzCoin", - "childDaemon": { - "host": "1.2.3.4", - "port": 17856 - }, - "pattern": "^Wrkz", - "blockchainExplorer": "http://myexplorer.wrkz.work/?hash={id}#blockchain_block", - "transactionExplorer": "http://myexplorer.wrkz.work/?hash={id}#blockchain_transaction", - "api": "https://your.pool.host/apiMerged6", - "enabled": true - }, - { - "poolAddress": "** Your pool wallet address **", - "pubAddressPrefix": null, - "intAddressPrefix": null, - "subAddressPrefix": null, - "coin": "Elphyrecoin2", - "childDaemon": { - "host": "1.2.3.4", - "port": 45501 - }, - "pattern": "^Phy", - "blockchainExplorer": "http://explorer2.elphyrecoin.xyz/?hash={id}#blockchain_block", - "transactionExplorer": "http://explorer2.elphyrecoin.xyz/?hash={id}#blockchain_transaction", - "api": "https://your.pool.host/apiMerged7", - "enabled": true - } - ], - "poolServer": { - "enabled": true, - "mergedMining": true, - "clusterForks": 5, - "poolAddress": "** Your pool wallet address **", - "pubAddressPrefix": null, - "intAddressPrefix": 1141703, - "subAddressPrefix": null, - "blockRefreshInterval": 1000, - "minerTimeout": 900, - "sslCert": "cert.pem", - "sslKey": "privkey.pem", - "sslCA": "chain.pem", - "ports": [ - { - "port": 1444, - "difficulty": 5000, - "desc": "Low end hardware" - }, - { - "port": 2444, - "difficulty": 50000, - "desc": "Mid range hardware" - }, - { - "port": 3444, - "difficulty": 500000, - "desc": "High end hardware" - } - ], - "varDiff": { - "minDiff": 500, - "maxDiff": 100000000, - "targetTime": 45, - "retargetTime": 40, - "variancePercent": 30, - "maxJump": 60 - }, - "paymentId": { - "addressSeparator": "+" - }, - "fixedDiff": { - "enabled": true, - "addressSeparator": "." - }, - "shareTrust": { - "enabled": true, - "min": 10, - "stepDown": 3, - "threshold": 10, - "penalty": 30 - }, - "banning": { - "enabled": true, - "time": 600, - "invalidPercent": 25, - "checkThreshold": 30 - }, - "slushMining": { - "enabled": false, - "weight": 300, - "blockTime": 60, - "lastBlockCheckRate": 1 - } - }, - - "payments": { - "enabled": true, - "interval": 900, - "maxAddresses": 5, - "mixin": 6, - "priority": 0, - "transferFee": 10000000, - "dynamicTransferFee": true, - "minerPayFee": true, - "minPayment": 1000000000, - "maxPayment": null, - "maxTransactionAmount": 100000000000, - "denomination": 1000000000 - }, - - "blockUnlocker": { - "enabled": true, - "interval": 30, - "depth": 18, - "poolFee": 0.5, - "devDonation": 0, - "networkFee": 0.0 - }, - - "api": { - "enabled": true, - "hashrateWindow": 600, - "updateInterval": 60, - "bindIp": "127.0.0.1", - "port": 8217, - "blocks": 30, - "payments": 30, - "password": "password", - "ssl": false, - "sslPort": 8119, - "sslCert": "cert.pem", - "sslKey": "privkey.pem", - "sslCA": "chain.pem", - "trustProxyIP": true - }, - - "daemon": { - "host": "127.0.0.1", - "port": 19994 - }, - - "wallet": { - "host": "1.2.3.4", - "port": 19996 - }, - - "redis": { - "host": "1.2.3.4", - "port": 6379, - "auth": null, - "db": 10, - "cleanupInterval": 15 - }, - - "notifications": { - "emailTemplate": "email_templates/default.txt", - "emailSubject": { - "emailAdded": "Your email was registered", - "workerConnected": "Worker %WORKER_NAME% connected", - "workerTimeout": "Worker %WORKER_NAME% stopped hashing", - "workerBanned": "Worker %WORKER_NAME% banned", - "blockFound": "Block %HEIGHT% found !", - "blockUnlocked": "Block %HEIGHT% unlocked !", - "blockOrphaned": "Block %HEIGHT% orphaned !", - "payment": "We sent you a payment !" - }, - "emailMessage": { - "emailAdded": "Your email has been registered to receive pool notifications.", - "workerConnected": "Your worker %WORKER_NAME% for address %MINER% is now connected from ip %IP%.", - "workerTimeout": "Your worker %WORKER_NAME% for address %MINER% has stopped submitting hashes on %LAST_HASH%.", - "workerBanned": "Your worker %WORKER_NAME% for address %MINER% has been banned.", - "blockFound": "Block found at height %HEIGHT% by miner %MINER% on %TIME%. Waiting maturity.", - "blockUnlocked": "Block mined at height %HEIGHT% with %REWARD% and %EFFORT% effort on %TIME%.", - "blockOrphaned": "Block orphaned at height %HEIGHT% :(", - "payment": "A payment of %AMOUNT% has been sent to %ADDRESS% wallet." - }, - "telegramMessage": { - "workerConnected": "Your worker _%WORKER_NAME%_ for address _%MINER%_ is now connected from ip _%IP%_.", - "workerTimeout": "Your worker _%WORKER_NAME%_ for address _%MINER%_ has stopped submitting hashes on _%LAST_HASH%_.", - "workerBanned": "Your worker _%WORKER_NAME%_ for address _%MINER%_ has been banned.", - "blockFound": "*Block found at height* _%HEIGHT%_ *by miner* _%MINER%_*! Waiting maturity.*", - "blockUnlocked": "*Block mined at height* _%HEIGHT%_ *with* _%REWARD%_ *and* _%EFFORT%_ *effort on* _%TIME%_*.*", - "blockOrphaned": "*Block orphaned at height* _%HEIGHT%_ *:(*", - "payment": "A payment of _%AMOUNT%_ has been sent." - } - }, - - "email": { - "enabled": false, - "fromAddress": "your@email.com", - "transport": "sendmail", - "sendmail": { - "path": "/usr/sbin/sendmail" - }, - "smtp": { - "host": "smtp.example.com", - "port": 587, - "secure": false, - "auth": { - "user": "username", - "pass": "password" - }, - "tls": { - "rejectUnauthorized": false - } - }, - "mailgun": { - "key": "your-private-key", - "domain": "mg.yourdomain" - } - }, - - "telegram": { - "enabled": false, - "botName": "", - "token": "", - "channel": "", - "channelStats": { - "enabled": false, - "interval": 30 - }, - "botCommands": { - "stats": "/stats", - "report": "/report", - "notify": "/notify", - "blocks": "/blocks" - } - }, - - "monitoring": { - "daemon": { - "checkInterval": 60, - "rpcMethod": "getblockcount" - }, - "wallet": { - "checkInterval": 60, - "rpcMethod": "getbalance" - } - }, - - "prices": { - "source": "tradeogre", - "currency": "USD" - }, - - "charts": { - "pool": { - "hashrate": { - "enabled": true, - "updateInterval": 60, - "stepInterval": 1800, - "maximumPeriod": 86400 - }, - "miners": { - "enabled": true, - "updateInterval": 60, - "stepInterval": 1800, - "maximumPeriod": 86400 - }, - "workers": { - "enabled": true, - "updateInterval": 60, - "stepInterval": 1800, - "maximumPeriod": 86400 - }, - "difficulty": { - "enabled": true, - "updateInterval": 1800, - "stepInterval": 10800, - "maximumPeriod": 604800 - }, - "price": { - "enabled": true, - "updateInterval": 1800, - "stepInterval": 10800, - "maximumPeriod": 604800 - }, - "profit": { - "enabled": true, - "updateInterval": 1800, - "stepInterval": 10800, - "maximumPeriod": 604800 - } - }, - "user": { - "hashrate": { - "enabled": true, - "updateInterval": 180, - "stepInterval": 1800, - "maximumPeriod": 86400 - }, - "worker_hashrate": { - "enabled": true, - "updateInterval": 60, - "stepInterval": 60, - "maximumPeriod": 86400 - }, - "payments": { - "enabled": true - } - }, - "blocks": { - "enabled": true, - "days": 30 - } - } -} diff --git a/README.md b/README.md index 124670c..390cdc6 100644 --- a/README.md +++ b/README.md @@ -31,4 +31,4 @@ Notes: - `Peya` and `Salvium` are treated as current-carrot chains. - `Zephyr` solo validation was done on the local fastfork testnet harness. - `Monero` solo validation was done on local `regtest`. -- merge mining will be built as the next product layer on top of this repo, but the architecture will diverge from the legacy generic pool model. +- merge mining will be built as a separate product layer on top of this repo; legacy child-pool merge-mining code is being removed from this baseline. diff --git a/config_examples/monero.json b/config_examples/monero.json index 52ed6e2..fa8497e 100644 --- a/config_examples/monero.json +++ b/config_examples/monero.json @@ -26,10 +26,8 @@ "colors": true } }, - "childPools": null, "poolServer": { "enabled": true, - "mergedMining": false, "clusterForks": "auto", "poolAddress": "** Your pool wallet address **", "intAddressPrefix": 19, diff --git a/config_examples/peya.json b/config_examples/peya.json index 610da44..8a1e3c8 100644 --- a/config_examples/peya.json +++ b/config_examples/peya.json @@ -39,10 +39,8 @@ } }, - "childPools": null, "poolServer": { "enabled": true, - "mergedMining": false, "clusterForks": "auto", "poolAddress": "PtYa_YOUR_POOL_CARROT_ADDRESS_HERE", "intAddressPrefix": null, diff --git a/config_examples/salvium.json b/config_examples/salvium.json index 81bd9ff..5dae720 100644 --- a/config_examples/salvium.json +++ b/config_examples/salvium.json @@ -55,10 +55,8 @@ "carrotDonationAddress": "SC1_YOUR_DONATION_CARROT_ADDRESS_HERE" }, - "childPools": null, "poolServer": { "enabled": true, - "mergedMining": false, "clusterForks": "auto", "poolAddress": "SaLv_YOUR_POOL_CRYPTONOTE_ADDRESS_HERE", "intAddressPrefix": null, diff --git a/config_examples/zephyr.json b/config_examples/zephyr.json index a396597..8e1be38 100644 --- a/config_examples/zephyr.json +++ b/config_examples/zephyr.json @@ -28,10 +28,8 @@ } }, - "childPools": null, "poolServer": { "enabled": true, - "mergedMining": false, "clusterForks": "auto", "poolAddress": "ZPHT_YOUR_POOL_ADDRESS_HERE", "intAddressPrefix": 19, diff --git a/init.js b/init.js index d04f27e..163f4f0 100644 --- a/init.js +++ b/init.js @@ -39,11 +39,6 @@ auth_pass: config.redis.auth }); - if ((typeof config.poolServer.mergedMining !== 'undefined' && config.poolServer.mergedMining) && typeof config.childPools !== 'undefined') - config.childPools = config.childPools.filter(pool => pool.enabled); - else - config.childPools = []; - // Load pool modules if (cluster.isWorker) { switch (process.env.workerType) { @@ -53,9 +48,6 @@ case 'daemon': require('./lib/daemon.js') break - case 'childDaemon': - require('./lib/childDaemon.js') - break case 'blockUnlocker': require('./lib/blockUnlocker.js'); break; @@ -129,8 +121,6 @@ } else { spawnPoolWorkers(); spawnDaemon(); - if (config.poolServer.mergedMining) - spawnChildDaemons(); spawnBlockUnlocker(); spawnPaymentProcessor(); spawnApi(); @@ -238,65 +228,6 @@ }, 10); } - /** - * Spawn pool workers module - **/ - function spawnChildDaemons () { - if (!config.poolServer || !config.poolServer.enabled || !config.poolServer.ports || config.poolServer.ports.length === 0) return; - - if (config.poolServer.ports.length === 0) { - log('error', logSystem, 'Pool server enabled but no ports specified'); - return; - } - - let numForks = config.childPools.length; - if (numForks === 0) return; - var daemonWorkers = {}; - - var createDaemonWorker = function (poolId) { - var worker = cluster.fork({ - workerType: 'childDaemon', - poolId: poolId - }); - worker.poolId = poolId; - worker.type = 'childDaemon'; - daemonWorkers[poolId] = worker; - worker.on('exit', function (code, signal) { - log('error', logSystem, 'Child Daemon fork %s died, spawning replacement worker...', [poolId]); - setTimeout(function () { - createDaemonWorker(poolId); - }, 2000); - }) - .on('message', function (msg) { - switch (msg.type) { - case 'ChildBlockTemplate': - Object.keys(cluster.workers) - .forEach(function (id) { - if (cluster.workers[id].type === 'pool') { - cluster.workers[id].send({ - type: 'ChildBlockTemplate', - block: msg.block, - poolIndex: msg.poolIndex - }); - } - }); - break; - } - }); - }; - - var i = 0; - var spawnInterval = setInterval(function () { - createDaemonWorker(i.toString()) - i++ - if (i === numForks) { - clearInterval(spawnInterval); - log('info', logSystem, 'Child Daemon spawned on %d thread(s)', [numForks]); - } - }, 10); - } - - /** * Spawn daemon module **/ diff --git a/lib/api.js b/lib/api.js index 7c5d721..1cd0a18 100644 --- a/lib/api.js +++ b/lib/api.js @@ -112,9 +112,6 @@ function handleServerRequest (request, response) { case '/block_explorers': handleBlockExplorers(response) break - case '/get_apis': - handleGetApis(response) - break // Miners/workers hashrate (used for charts) case '/miners_hashrate': if (!authorize(request, response)) { @@ -220,14 +217,6 @@ function collectStats () { healthCommands.push(['hget', `${config.coin}:status:daemon`, 'lastStatus']); healthCommands.push(['hget', `${config.coin}:status:wallet`, 'lastStatus']); healthCommands.push(['hget', `${config.coin}:status:price`, 'lastReponse']); - /* - config.childPools.forEach(pool => { - healthCommands.push(['hmget', `${pool.coin}:status:daemon`, 'lastStatus']); - healthCommands.push(['hmget', `${pool.coin}:status:wallet`, 'lastStatus']); - keys.push(pool.coin); - - }) - */ redisClient.multi(healthCommands).exec(function (error, replies) { if (error) { @@ -644,17 +633,6 @@ function getLastBlockData (callback) { }); } -function handleGetApis (callback) { - let apis = {}; - config.childPools.forEach(pool => { - if (pool.enabled) - apis[pool.coin] = { - api: pool.api - } - }) - callback(apis) -} - /** * Broadcast live statistics **/ @@ -1089,37 +1067,6 @@ function handleGetMarket (urlParts, response) { }); } -function handleGetApis (response) { - async.waterfall([ - function (callback) { - let apis = {}; - config.childPools.forEach(pool => { - if (pool.enabled) - apis[pool.coin] = { - api: pool.api - } - }) - callback(null, apis); - } - ], function (error, data) { - if (error) { - response.end(JSON.stringify({ - error: 'Error collecting Api Information' - })); - return; - } - let reply = JSON.stringify(data); - - response.writeHead("200", { - 'Access-Control-Allow-Origin': '*', - 'Cache-Control': 'no-cache', - 'Content-Type': 'application/json', - 'Content-Length': Buffer.byteLength(reply, 'utf8') - }); - response.end(reply); - }) -} - /** * Return top 10 miners **/ @@ -1131,13 +1078,6 @@ function handleBlockExplorers (response) { "blockchainExplorer": config.blockchainExplorer, "transactionExplorer": config.transactionExplorer } - config.childPools.forEach(pool => { - if (pool.enabled) - blockExplorers[pool.coin] = { - "blockchainExplorer": pool.blockchainExplorer, - "transactionExplorer": pool.transactionExplorer - } - }) callback(null, blockExplorers); } ], function (error, data) { @@ -1895,11 +1835,7 @@ function handleAdminUsers (request, response) { // get workers data function (workerKeys, callback) { - let allCoins = config.childPools.filter(pool => pool.enabled).map(pool => { - return `${pool.coin}` - }) - - allCoins.push(otherCoin); + let allCoins = otherCoin ? [otherCoin] : []; let redisCommands = workerKeys.map(function (k) { return ['hmget', k, 'balance', 'paid', 'lastShare', 'hashes', ...allCoins]; diff --git a/lib/childDaemon.js b/lib/childDaemon.js deleted file mode 100644 index c6c4ad4..0000000 --- a/lib/childDaemon.js +++ /dev/null @@ -1,84 +0,0 @@ -let async = require('async'); -let apiInterfaces = require('./apiInterfaces.js')(config.daemon, config.wallet, config.api); -let lastHash; -let POOL_NONCE_SIZE = 16 + 1; // +1 for old XMR/new TRTL bugs - -let logSystem = 'childDaemon' -require('./exceptionWriter.js')(logSystem); - - -let pool = config.childPools[process.env.poolId]; - -let blockData = JSON.stringify({ - id: "0", - jsonrpc: "2.0", - method: 'getlastblockheader', - params: {} -}) - -let templateData = JSON.stringify({ - id: "0", - jsonrpc: "2.0", - method: 'getblocktemplate', - params: { - reserve_size: POOL_NONCE_SIZE, - wallet_address: pool.poolAddress - } -}) - - -function runInterval () { - async.waterfall([ - function (callback) { - apiInterfaces.jsonHttpRequest(pool.childDaemon.host, pool.childDaemon.port, blockData, function (err, res) { - if (err) { - log('error', logSystem, '%s error from daemon', [pool.coin]); - setTimeout(runInterval, 3000); - return; - } - if (res && res.result && res.result.status === "OK" && res.result.hasOwnProperty('block_header')) { - let hash = res.result.block_header.hash.toString('hex'); - if (!lastHash || lastHash !== hash) { - lastHash = hash - log('info', logSystem, '%s found new hash %s', [pool.coin, hash]); - callback(null, true); - return; - } else if (config.daemon.alwaysPoll || false) { - callback(null, true); - return; - } else { - callback(true); - return; - } - } else { - log('error', logSystem, '%s bad reponse from daemon', [pool.coin]); - setTimeout(runInterval, 3000); - return; - } - }); - }, - function (getbc, callback) { - apiInterfaces.jsonHttpRequest(pool.childDaemon.host, pool.childDaemon.port, templateData, function (err, res) { - if (err) { - log('error', logSystem, '%s Error polling getblocktemplate %j', [pool.coin, err]) - callback(null) - return - } - process.send({ - type: 'ChildBlockTemplate', - block: res.result, - poolIndex: process.env.poolId - }) - callback(null) - }) - } - ], - function (error) { - if (error) {} - setTimeout(function () { - runInterval() - }, config.poolServer.blockRefreshInterval) - }) -} - -runInterval() diff --git a/lib/daemon.js b/lib/daemon.js index 871e976..a93c6e2 100644 --- a/lib/daemon.js +++ b/lib/daemon.js @@ -4,10 +4,6 @@ let apiInterfaces = require('./apiInterfaces.js')(config.daemon, config.wallet, let lastHash; let POOL_NONCE_SIZE = 16 + 1; // +1 for old XMR/new TRTL bugs -let EXTRA_NONCE_TEMPLATE = "02" + POOL_NONCE_SIZE.toString(16) + "00".repeat(POOL_NONCE_SIZE); -let POOL_NONCE_MM_SIZE = POOL_NONCE_SIZE + utils.cnUtil.get_merged_mining_nonce_size(); -let EXTRA_NONCE_NO_CHILD_TEMPLATE = "02" + POOL_NONCE_MM_SIZE.toString(16) + "00".repeat(POOL_NONCE_MM_SIZE); - let logSystem = 'daemon' let blockData = JSON.stringify({ @@ -56,7 +52,7 @@ function runInterval () { jsonrpc: "2.0", method: 'getblocktemplate', params: { - reserve_size: config.poolServer.mergedMining ? POOL_NONCE_MM_SIZE : POOL_NONCE_SIZE, + reserve_size: POOL_NONCE_SIZE, wallet_address: utils.getPoolTemplateAddress() } }); diff --git a/lib/logger.js b/lib/logger.js index 619917b..b815b35 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -75,7 +75,7 @@ global.log = function (severity, system, text, data) { if (logConsole) { if (config.logging.console.colors) - if (system === 'daemon' || system === 'childDaemon') { + if (system === 'daemon') { console.log(severityMap[severity](time) + clc.green.bold(' [' + system + '] ' + formattedMessage)); } else { diff --git a/lib/pool.js b/lib/pool.js index 592307d..cae1e29 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -25,7 +25,6 @@ let noncePattern = new RegExp("^[0-9A-Fa-f]{8}$"); // Set redis database cleanup interval let cleanupInterval = config.redis.cleanupInterval && config.redis.cleanupInterval > 0 ? config.redis.cleanupInterval : 15; -let fallBackCoin = typeof config.poolServer.fallBackCoin !== 'undefined' && config.poolServer.fallBackCoin ? config.poolServer.fallBackCoin : 0 // Initialize log system let logSystem = 'pool'; @@ -54,12 +53,8 @@ let instanceId = utils.instanceId(); // Pool variables let poolStarted = false; let connectedMiners = {}; -// Get merged mining tag reseved space size let POOL_NONCE_SIZE = 16 + 1; // +1 for old XMR/new TRTL bugs let EXTRA_NONCE_TEMPLATE = "02" + POOL_NONCE_SIZE.toString(16) + "00".repeat(POOL_NONCE_SIZE); -let POOL_NONCE_MM_SIZE = POOL_NONCE_SIZE + utils.cnUtil.get_merged_mining_nonce_size(); -let EXTRA_NONCE_NO_CHILD_TEMPLATE = "02" + POOL_NONCE_MM_SIZE.toString(16) + "00".repeat(POOL_NONCE_MM_SIZE); -let mergedMining = config.poolServer.mergedMining && (Array.isArray(config.childPools) && config.childPools.length > 0) function randomIntFromInterval (min, max) { return Math.floor(Math.random() * (max - min + 1) + min); @@ -112,20 +107,11 @@ function Create2DArray (rows) { return arr; } -if (mergedMining) { - config.childPools = config.childPools.filter(pool => pool.enabled); -} - - // Block templates -let validBlockTemplates = mergedMining ? Create2DArray(config.childPools.length) : Create2DArray(1); +let validBlockTemplates = Create2DArray(1); let currentBlockTemplate = []; -// Child Block templates -let currentChildBlockTemplate = new Array(mergedMining ? config.childPools.length : 1); - - // Difficulty buffer const DIFF1 = (1n << 256n) - 1n; @@ -211,13 +197,7 @@ process.on('message', function (message) { try { if (!currentBlockTemplate[0] || new_hash.toString('hex') !== currentBlockTemplate[0].prev_hash.toString('hex') || (currentBlockTemplate[0].num_transactions == 0 && message.block.num_transactions > 0)) { log('info', logSystem, 'New %s block to mine at height %d w/ difficulty of %d (%d transactions)', [config.coin, message.block.height, message.block.difficulty, (message.block.num_transactions || 0)]); - if (mergedMining) { - for (var childPoolIndex = 0; childPoolIndex < config.childPools.length; childPoolIndex++) { - processBlockTemplate(message.block, childPoolIndex); - } - } else { - processBlockTemplate(message.block, 0); - } + processBlockTemplate(message.block); return; } else { return; @@ -225,21 +205,6 @@ process.on('message', function (message) { } catch (e) { log('error', logSystem, `BlockTemplate ${e}`); } - break; - case 'ChildBlockTemplate': - let poolIndex = parseInt(message.poolIndex); - try { - if (!currentChildBlockTemplate[poolIndex] || message.block.height > currentChildBlockTemplate[poolIndex].height || (currentChildBlockTemplate[poolIndex].num_transactions == 0 && message.block.num_transactions > 0)) { - log('info', logSystem, 'New %s child block to mine at height %d w/ difficulty of %d (%d transactions)', [config.childPools[poolIndex].coin, message.block.height, message.block.difficulty, (message.block.num_transactions || 0)]); - processChildBlockTemplate(poolIndex, message.block); - return; - } else { - return; - } - } catch (e) { - log('error', logSystem, `ChildBlockTemplate ${e}`); - } - break; } }); @@ -247,7 +212,7 @@ process.on('message', function (message) { /** * Block template **/ -function BlockTemplate (template, parent, indexOfChildPool) { +function BlockTemplate (template) { this.difficulty = template.difficulty; this.height; try { @@ -259,25 +224,15 @@ function BlockTemplate (template, parent, indexOfChildPool) { this.blocktemplate_blob = template.blocktemplate_blob; let blob = this.blocktemplate_blob; this.buffer = Buffer.from(blob, 'hex'); - let template_hex = EXTRA_NONCE_TEMPLATE; - if (parent && mergedMining) { - if (currentChildBlockTemplate[indexOfChildPool]) { - this.childBlockTemplate = currentChildBlockTemplate[indexOfChildPool]; - this.buffer = utils.cnUtil.construct_mm_parent_block_blob(this.buffer, cnBlobType, this.childBlockTemplate.buffer); - blob = this.buffer.toString('hex'); - } else { - template_hex = EXTRA_NONCE_NO_CHILD_TEMPLATE; - } - } this.isRandomX = config.isRandomX - if (!mergedMining && this.isRandomX) { + if (this.isRandomX) { this.seed_hash = template.seed_hash; this.next_seed_hash = template.next_seed_hash; } - var found_template_at = blob.indexOf(template_hex); + var found_template_at = blob.indexOf(EXTRA_NONCE_TEMPLATE); if (found_template_at !== -1) { this.reserveOffset = offset + (found_template_at >> 1); - if (this.reserveOffset != template.reserved_offset && !mergedMining) { + if (this.reserveOffset != template.reserved_offset) { log('error', logSystem, "INTERNAL ERROR: found reserve offset in unexpected place (found at %d, expected at %d)", [this.reserveOffset, template.reserved_offset]); } @@ -297,11 +252,8 @@ function BlockTemplate (template, parent, indexOfChildPool) { this.buffer.copy(this.prev_hash, 0, previousOffset, 39); } BlockTemplate.prototype = { - nextBlob: function (index) { + nextBlob: function () { this.buffer.writeUInt32BE(++this.extraNonce, this.reserveOffset); - if (mergedMining && this.childBlockTemplate) { - return utils.cnUtil.convert_blob(this.buffer, cnBlobType, this.childBlockTemplate.buffer).toString('hex'); - } return utils.cnUtil.convert_blob(this.buffer, cnBlobType).toString('hex'); }, nextBlobWithChildNonce: function () { @@ -316,43 +268,25 @@ BlockTemplate.prototype = { /** * Process block template **/ -function processBlockTemplate (template, indexOfChildPool) { - let block_template = new BlockTemplate(template, true, indexOfChildPool); +function processBlockTemplate (template) { + let block_template = new BlockTemplate(template); - if (currentBlockTemplate[indexOfChildPool]) { - validBlockTemplates[indexOfChildPool].push(currentBlockTemplate[indexOfChildPool]); + if (currentBlockTemplate[0]) { + validBlockTemplates[0].push(currentBlockTemplate[0]); } - while (validBlockTemplates[indexOfChildPool].length > (mergedMining ? 6 : 3)) { - validBlockTemplates[indexOfChildPool].shift(); + while (validBlockTemplates[0].length > 3) { + validBlockTemplates[0].shift(); } - currentBlockTemplate[indexOfChildPool] = block_template; - notifyConnectedMiners(indexOfChildPool); + currentBlockTemplate[0] = block_template; + notifyConnectedMiners(); } - - -/** - * Process child block template - **/ -function processChildBlockTemplate (indexOfChildPool, template) { - let block_template = new BlockTemplate(template, false); - - currentChildBlockTemplate[indexOfChildPool] = block_template; - - // Update the parent block template to include this new child - if (currentBlockTemplate[indexOfChildPool]) { - processBlockTemplate(currentBlockTemplate[indexOfChildPool], indexOfChildPool); - } -} - -function notifyConnectedMiners (indexOfChildPool) { - let now = Date.now() / 1000 | 0; +function notifyConnectedMiners () { for (let minerId in connectedMiners) { let miner = connectedMiners[minerId]; - if (indexOfChildPool === miner.activeChildPool) - miner.pushMessage('job', miner.getJob()); + miner.pushMessage('job', miner.getJob()); } } @@ -384,15 +318,10 @@ function GetRewardTypeAsKey (rewardType) { /** * Miner **/ -function Miner (rewardType, childRewardType, id, childPoolIndex, login, pass, ip, port, agent, childLogin, startingDiff, noRetarget, pushMessage) { +function Miner (rewardType, id, login, pass, ip, port, agent, startingDiff, noRetarget, pushMessage) { this.rewardType = rewardType; - this.childRewardType = childRewardType; this.rewardTypeAsKey = GetRewardTypeAsKey(rewardType); - this.childRewardTypeAsKey = GetRewardTypeAsKey(childRewardType); - - this.lastChildBlockHeight = 0; this.id = id; - this.activeChildPool = childPoolIndex || 0; this.login = login; this.pass = pass; this.ip = ip; @@ -402,7 +331,6 @@ function Miner (rewardType, childRewardType, id, childPoolIndex, login, pass, ip this.proxy = true; } this.workerName = 'undefined'; - this.childLogin = childLogin; if (pass.lastIndexOf('@') >= 0 && pass.lastIndexOf('@') < pass.length) { passDelimiterPos = pass.lastIndexOf('@') + 1; this.workerName = pass.substr(passDelimiterPos, pass.length) @@ -486,23 +414,14 @@ Miner.prototype = { return hex; }, getJob: function () { - let blockTemplate = currentBlockTemplate[this.activeChildPool]; + let blockTemplate = currentBlockTemplate[0]; let newJob = { id: utils.uid(), height: blockTemplate.height, submissions: [] }; - if (mergedMining) { - if (this.lastBlockHeight === blockTemplate.height && (!currentChildBlockTemplate[this.activeChildPool] || this.lastChildBlockHeight === currentChildBlockTemplate[this.activeChildPool].height) && !this.pendingDifficulty && this.cachedJob !== null && !config.daemon.alwaysPoll) { - return this.cachedJob; - } - this.lastChildBlockHeight = currentChildBlockTemplate ? currentChildBlockTemplate[this.activeChildPool].height : -1; - newJob.activeChildPool = this.activeChildPool; - newJob.childHeight = this.lastChildBlockHeight; - } else { - if (this.lastBlockHeight === blockTemplate.height && !this.pendingDifficulty && this.cachedJob !== null && !config.daemon.alwaysPoll) { - return this.cachedJob; - } + if (this.lastBlockHeight === blockTemplate.height && !this.pendingDifficulty && this.cachedJob !== null && !config.daemon.alwaysPoll) { + return this.cachedJob; } let blob = this.proxy ? blockTemplate.nextBlobWithChildNonce() : blockTemplate.nextBlob(); this.lastBlockHeight = blockTemplate.height; @@ -534,7 +453,6 @@ Miner.prototype = { this.cachedJob.blocktemplate_blob = blob; this.cachedJob.difficulty = blockTemplate.difficulty; this.cachedJob.height = blockTemplate.height; - this.cachedJob.childHeight = this.lastChildBlockHeight; this.cachedJob.reserved_offset = blockTemplate.reserveOffset; this.cachedJob.client_nonce_offset = blockTemplate.clientNonceLocation; this.cachedJob.client_pool_offset = blockTemplate.clientPoolLocation; @@ -647,79 +565,6 @@ function handleMinerMethod (method, params, ip, portData, sendReply, pushMessage let paymentid = null; let port = portData.port; let pass = params.pass; - let childLogin = pass.trim(); - let childPoolIndex = 0; - let childRewardType = rewardType; - if (mergedMining) { - childPoolIndex = -1; - if (!validateMinerPaymentId_difficulty(pass, ip, config.poolServer, 'child ', sendReply)) - { - return - } - - calculated = utils.determineRewardData(pass); - pass = calculated.address; - childRewardType = calculated.rewardType; - - if (pass.indexOf('@') >= 0 && pass.indexOf('@') >= 0) { - passDelimiterPos = pass.lastIndexOf('@'); - childLogin = pass.substr(0, passDelimiterPos).trim(); - } - childLogin = childLogin.replace(/\s/g, ''); - childLogin = utils.cleanupSpecialChars(childLogin); - - - let addr = childLogin.split(config.poolServer.paymentId.addressSeparator); - address = addr[0] || null; - paymentId = addr[1] || null; - - if (!address) { - log('warn', logSystem, 'No address specified for login'); - sendReply('No address specified for login'); - } - - - if (paymentId && config.poolServer.paymentId.validation) { - let valid = false; - config.poolServer.paymentId.validations.forEach(validation => { - if (paymentId.match(`^([a-zA-Z0-9]){${validation}}$`)) { - return valid = true; - } - }) - if (!valid) { - log('warn', logSystem, 'Invalid paymentId specified for login'); - } - if (config.poolServer.paymentId.ban) { - process.send({ - type: 'banIP', - ip: ip - }); - sendReply(`Invalid paymentId specified for login, ${portData.ip} banned for ${config.poolServer.banning.time / 60} minutes`); - } - } - - for (i = 0; i < config.childPools.length; i++) { - if (config.childPools[i].pattern) { - if (new RegExp(config.childPools[i].pattern, 'i').test(address)) { - childPoolIndex = i; - break; - } - } - } - if (childPoolIndex < 0) { - childPoolIndex = fallBackCoin; - address = config.childPools[childPoolIndex].poolAddress; - childLogin = config.childPools[childPoolIndex].poolAddress; - } - if (!utils.validateChildMinerAddress(address, childPoolIndex)) { - let addressPrefix = utils.getAddressPrefix(address); - if (!addressPrefix) addressPrefix = 'N/A'; - - log('warn', logSystem, 'Invalid address used for childLogin (prefix: %s): %s', [addressPrefix, address]); - sendReply('Invalid address used for childLogin'); - return; - } - } let difficulty = portData.difficulty; @@ -775,7 +620,7 @@ function handleMinerMethod (method, params, ip, portData, sendReply, pushMessage } let minerId = utils.uid(); - miner = new Miner(rewardType, childRewardType, minerId, childPoolIndex, login, pass, ip, port, params.agent, childLogin, difficulty, noRetarget, pushMessage); + miner = new Miner(rewardType, minerId, login, pass, ip, port, params.agent, difficulty, noRetarget, pushMessage); connectedMiners[minerId] = miner; sendReply(null, { @@ -875,14 +720,10 @@ function handleMinerMethod (method, params, ip, portData, sendReply, pushMessage } let isJobBlock = function (b) { - return b.height === job.height && job.childHeight === ( - b.childBlockTemplate ? b.childBlockTemplate.height : undefined); + return b.height === job.height; }; - let blockTemplate = currentBlockTemplate[miner.activeChildPool]; - if (job.childHeight) { - blockTemplate = isJobBlock(currentBlockTemplate[miner.activeChildPool]) ? currentBlockTemplate[miner.activeChildPool] : validBlockTemplates[miner.activeChildPool].filter(isJobBlock)[0]; - } + let blockTemplate = isJobBlock(currentBlockTemplate[0]) ? currentBlockTemplate[0] : validBlockTemplates[0].filter(isJobBlock)[0]; if (!blockTemplate) { sendReply('Block expired'); return; @@ -958,28 +799,6 @@ function newConnectedWorker (miner) { }); } }); - if (config.poolServer.mergedMining) { - redisClient.sadd(`${config.childPools[miner.activeChildPool].coin}:workers_ip:${miner.childLogin}`, miner.ip); - redisClient.hincrby(`${config.childPools[miner.activeChildPool].coin}:ports:${miner.port}`, 'users', 1); - - redisClient.hincrby(`${config.childPools[miner.activeChildPool].coin}:active_connections${miner.childRewardTypeAsKey}`, `${miner.childLogin}~${miner.workerName}`, 1, function (error, connectedWorkers) {}); - - - let redisCommands = config.childPools.map(item => { - return ['hdel', `${config.coin}:workers:${miner.login}`, `${item.coin}`, ] - }) - redisClient.multi(redisCommands) - .exec(function (error, replies) { - if (error) { - log('error', logSystem, 'Failed to clear childCoins from parent in redis %j \n %j', [err, redisCommands]); - } - }) - - redisClient.hset(`${config.coin}:workers:${miner.login}`, `${config.childPools[miner.activeChildPool].coin}`, miner.childLogin); - - redisClient.hset(`${config.childPools[miner.activeChildPool].coin}:workers:${miner.childLogin}`, `${config.coin}`, miner.login); - - } } /** @@ -987,10 +806,6 @@ function newConnectedWorker (miner) { **/ function removeConnectedWorker (miner, reason) { redisClient.hincrby(`${config.coin}:ports:${miner.port}`, 'users', '-1'); - if (mergedMining) { - redisClient.hincrby(`${config.childPools[miner.activeChildPool].coin}:ports:${miner.port}`, 'users', '-1'); - redisClient.hincrby(`${config.childPools[miner.activeChildPool].coin}:active_connections${miner.childRewardTypeAsKey}`, `${miner.childLogin}~${miner.workerName}`, 1, function (error, connectedWorkers) {}); - } redisClient.hincrby(`${config.coin}:active_connections${miner.rewardTypeAsKey}`, `${miner.login}~${miner.workerName}`, -1, function (error, connectedWorkers) { if (reason === 'banned') { @@ -1032,14 +847,14 @@ function IsBannedIp (ip) { } } -function recordShareData (miner, job, shareDiff, blockCandidate, hashHex, shareType, blockTemplate, pool) { +function recordShareData (miner, job, shareDiff, blockCandidate, hashHex, shareType, blockTemplate) { let dateNow = Date.now(); let dateNowSeconds = dateNow / 1000 | 0; - let coin = pool !== null ? pool.coin : config.coin; - let login = pool !== null ? miner.childLogin : miner.login; - let job_height = pool !== null ? job.childHeight : job.height; + let coin = config.coin; + let login = miner.login; + let job_height = job.height; let workerName = miner.workerName; - let rewardType = pool !== null ? miner.childRewardType : miner.rewardType; + let rewardType = miner.rewardType; let updateScore; // Weighting older shares lower than newer ones to prevent pool hopping if (slushMiningEnabled) { @@ -1231,60 +1046,14 @@ function processShare (miner, job, blockTemplate, params) { 'Block %s found at height %d by miner %s@%s - submit result: %j', [blockFastHash.substr(0, 6), job.height, miner.login, miner.ip, result] ); - recordShareData(miner, job, hashDiff.toString(), true, blockFastHash, shareType, blockTemplate, null); + recordShareData(miner, job, hashDiff.toString(), true, blockFastHash, shareType, blockTemplate); } }); } else if (hashDiff < jobDifficulty) { log('warn', logSystem, 'Rejected low difficulty share of %s from %s@%s', [hashDiff.toString(), miner.login, miner.ip]); return false; } else { - recordShareData(miner, job, hashDiff.toString(), false, null, shareType, null, null); - } - - if (!job.childHeight) { - return true; - } - - var childBlockTemplate = blockTemplate.childBlockTemplate; - - if (childBlockTemplate) { - if (mergedMining) { - let pool = config.childPools[miner.activeChildPool] - if (hashDiff >= BigInt(childBlockTemplate.difficulty)) { - let mergedBuffer = null - try { - mergedBuffer = utils.cnUtil.construct_mm_child_block_blob(shareBuffer, cnBlobType, childBlockTemplate.buffer); - } catch (e) { - log('error', logSystem, "Failed to construct MM child block: " + e); - } - if (mergedBuffer === null) { - recordShareStatusMerged(miner, 'invalid'); - } else { - - let onChildSuccess = (result) => { - let blockFastHash = utils.cnUtil.get_block_id(mergedBuffer, 2).toString('hex') - log('info', logSystem, - 'Child Block %s found at height %d by miner %s@%s - submit result: %j', - [blockFastHash.substr(0, 6), job.childHeight, miner.workerName, miner.ip, result]); - recordShareData(miner, job, hashDiff.toString(), true, blockFastHash, shareType, childBlockTemplate, pool); - } - - apiInterfaces.rpcDaemon('submitblock', [mergedBuffer.toString('hex')], function (error, result) { - if (error) { - log('error', logSystem, 'Error submitting child block at height %d from %s@%s, share type: "%s" - %j', [job.childHeight, miner.login, miner.ip, shareType, error]); - } else { - onChildSuccess(result) - } - }, pool.childDaemon); - } - } else if (hashDiff < jobDifficulty) { - log('warn', logSystem, 'Rejected low difficulty share of %s from %s@%s', [hashDiff.toString(), miner.workerName, miner.ip]); - return false; - } else { - recordShareData(miner, job, hashDiff.toString(), false, null, shareType, null, pool); - } - } - return true; + recordShareData(miner, job, hashDiff.toString(), false, null, shareType, null); } return true; } diff --git a/lib/utils.js b/lib/utils.js index dc768fa..e8b8ac4 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -73,17 +73,6 @@ function characterCount (string, char) { } exports.characterCount = characterCount; -// Validate miner address -exports.validateChildMinerAddress = (address, index) => { - let childAddressBase58Prefix = parseInt(cnUtil.address_decode(Buffer.from(config.childPools[index].poolAddress)).toString()); - let childIntegratedAddressBase58Prefix = config.poolServer.intChildAddressPrefix ? parseInt(config.childPools[index].intAddressPrefix) : childAddressBase58Prefix + 1; - - let addressPrefix = getAddressPrefix(address); - if (addressPrefix === childAddressBase58Prefix) return true; - else if (addressPrefix === childIntegratedAddressBase58Prefix) return true; - return false; -} - // Return if value is an integrated address exports.isIntegratedAddress = function (address) { let addressPrefix = getAddressPrefix(address); diff --git a/website_example/admin.html b/website_example/admin.html index 39dc397..a086d20 100644 --- a/website_example/admin.html +++ b/website_example/admin.html @@ -79,37 +79,17 @@ mergedStats = {}; let mergedApis = {}; $(function() { - - - let merged_apis = $.ajax({ - url: `${api}/get_apis`, - dataType: 'json', - cache: 'false' - }) - let poolStats = $.ajax({ url: `${api}/stats`, dataType: 'json', cache: 'false' }) - Promise.all([poolStats, merged_apis]) + Promise.all([poolStats]) .then(values => { lastStats = values[0] - mergedApis = values[1] - let subs = []; - Object.keys(mergedApis).some(key => { - let apiUrl = `${mergedApis[key].api}/stats` - subs.push($.ajax({url: apiUrl, dataType: 'json', cache: 'false'})) - }) - Promise.all(subs) - .then(data => { - data.forEach(item => { - mergedStats[item.config.coin] = item - }) - $('#poolVersion').html(lastStats.config.version); - routePage(); - }) + $('#poolVersion').html(lastStats.config.version); + routePage(); }) }); diff --git a/website_example/index.html b/website_example/index.html index 7877ee5..800f972 100644 --- a/website_example/index.html +++ b/website_example/index.html @@ -197,19 +197,6 @@ function loadLiveStats(reload) { }); - Object.keys(mergedApis).some(key => { - let apiUrl = `${mergedApis[key].api}/stats` - // if (xhrLiveStats[key]){ - // xhrLiveStats[key].abort(); - // } - - $.get(apiUrl, function(data){ - updateLiveStats(data, key); - if (!reload){ - routePage(fetchLiveStats(mergedApis[key].api, key)); - } - }); - }) } // Fetch live statistics @@ -239,7 +226,6 @@ function fetchLiveStats(endPoint, key) { // Fetch Block and Transaction Explorer Urls let xhrBlockExplorers; -let xhrMergedApis; function fetchBlockExplorers() { let apiURL = api + '/block_explorers'; @@ -249,17 +235,7 @@ function fetchBlockExplorers() { cache: 'false' }).done(function(data){ blockExplorers = data; - }) - - apiURL = api + '/get_apis'; - - xhrMergedApis = $.ajax({ - url: apiURL, - dataType: 'json', - cache: 'false', - }).done(function(data){ - mergedApis = data; - loadLiveStats() + loadLiveStats(); }) } diff --git a/website_example/pages/faq.html b/website_example/pages/faq.html index 9aaeb57..ff9cb24 100644 --- a/website_example/pages/faq.html +++ b/website_example/pages/faq.html @@ -1,117 +1,91 @@
The hash work of your miner application to the parent coin is also applied to the child coin you specify in the mining software pool password field.
- -You must mine at one parent coin, which in this case is ARQ for ArQmA. -Specify your ArQmA wallet address and static difficulty per the Getting Started page. -Using the pool password field in your miner to specify one of the child coin wallet addresses. See which child coins are listed on the pool's Dashboard page. -You will need at least a wallet address from an exchange or a wallet/paper wallet application to get an coin address for the parent coin and each child coin you wish to merge mine.
- -You can also connect multiple rigs with the same wallet address for the parent coin, and different child coin wallet address to apply hash to that child coin also.
- -Specify your rig_id in your miner software.
-Put your child coin wallet address in the pool password field and put "@rig_id" at the end. - It can be a direct to exchange address also.
-For example in XMR-STAK, the pools.txt config file looks something like this: -"rig_id" : "Johnny5", -An example wallet for Turtle child coin is "TRTL2aedfsr23blahlongaddressfield+paymentIDsomething" -so make it formatted for the pool password as -"pool_password" : "TRTL2aedfsr23blahlongaddressfield+paymentIDsomething@Johnny5"
- -You can also use the configuration generator within the Getting Started section of the pool.
-Also, you can segment your cpu mining on one mining application to be applied to -the parent coin and specify your hash work one of the several child coins. -There is no limit on how many workers you can specify. You can also customize your miner application to mine only with certain gpus to a particular parent/child combination. Probably you can run several mining applications in tandem as long as they use only resources you specify.
- +As soon as the block is found you will get your reward. Please wait a little bit more time. In the case of ArQmA, a block has at least 18 confirmations before the pool starts its payout cycle. Typically every 36 minutes for a completed block plus the time interval set by the pool operator on the pool's Dashboard screeen. Payments can be halted for various reasons within the automated pool software, but highly unlikely. There is usually a minimum payout for each parent coin and child coins. Payments for matured blocks that meet the minimum can also be triggered manually by a pool operator/administrator. Ask nicely in Telegram or Discord support. Please have your information all in order before you ask such as miner application, version number, gpu and cpu information, wallet addresses, and error messages reported. -
The merge mined child coins have a different number of confirmation blocks needed, but at least the pool checks for fully verified blocks set at the interval on the Dashboard page. Not every parent block found generates a child block. -Check the Pool Blocks page on the pool. Or configure your settings to get an email alert if you like on the Settings pool page. -
Solo mining is attempting to find a block by yourself separate from the pool of proportional miners collectively solving the current block.You get almost the entire block reward minus a small fee for the pool. You can specfy your mining software by changing the wallet address with a prefix of "solo:" added to your wallet specification. -However, if the coin network has a high hash in total (see Dashboard), the difficulty is also higher. Typically only very large mining rigs with at least 5-10% of the coin network total is needed to get timely solo blocks. However, you could get a string of blocks on lucky streak, then not find a block solution for a very long time. The more hash rate, the higher the probability(luck). You can generate a solo configuration on the Getting Started page on the pool. Tick the checkbox "solo mining". However, as solo you are also competing against the pool proportional share miners, and evvery single node on the parent coin network also. -
-In the case of solo merged mining specified in the pool password field, you are also competing against the main pool users on proportional shares, and the entire child coin network and the other pools on the parent network that are also merge mining. However the reward is much higher since you might get two coin blocks(or more) for the same effort. -
+Disconnect your miner for five minutes at least. Then try again. Please pay close attention to error messages reported by the pool software to your miner client software. Typical errors are invalid parent wallet address format, or bad child coin wallet address specified in the pool password field. Check your miner logs if you have them turned on. -
-Did you forget to turn off nicehash option?
-For persistent banning, check with the pool operator or Admininstrator to see if there is something else going wrong outside of your control. Links for Telegram and Discord support are on the left side of the pool web page front end.
+