From 916019f418b2b20832d2a5fd559b14ed2016c349 Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Mon, 3 Jul 2017 06:43:52 -0700 Subject: [PATCH 01/11] Setting the new sizes, holders, and test states to see if this thing works. --- lib/coins/xmr.js | 38 ++++++++++++++++++++-- lib/pool.js | 82 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 96 insertions(+), 24 deletions(-) diff --git a/lib/coins/xmr.js b/lib/coins/xmr.js index a493a43..977759f 100644 --- a/lib/coins/xmr.js +++ b/lib/coins/xmr.js @@ -69,7 +69,7 @@ function Coin(data){ this.getBlockTemplate = function(walletAddress, callback){ global.support.rpcDaemon('getblocktemplate', { - reserve_size: 8, + reserve_size: 16, wallet_address: walletAddress }, function(body){ return callback(body); @@ -102,22 +102,56 @@ function Coin(data){ }; this.BlockTemplate = function(template) { + /* + Generating a block template is a simple thing. Ask for a boatload of information, and go from there. + Important things to consider. + The reserved space is 13 bytes long now in the following format: + |minerNonce/extraNonce - 4 bytes|instanceId - 4 bytes|clientNonce - 4 bytes|clientPoolNonce - 4 bytes| + This is designed to allow a single block template to be used on up to 4 billion poolSlaves (clientPoolNonce) + Each with 4 billion clients. (clientNonce) + While being unique to this particular pool thread (instanceId) + With up to 4 billion clients (minerNonce/extraNonce) + Overkill? Sure. But that's what we do here. Overkill. + */ + + // Set this.blob equal to the BT blob that we get from upstream. this.blob = template.blocktemplate_blob; + // Set this.diff equal to the known diff for this block. this.difficulty = template.difficulty; + // Set this.height equal to the known height for this block. this.height = template.height; + // Set this.reserveOffset to the byte location of the reserved offset. this.reserveOffset = template.reserved_offset; + // Set this.buffer to the binary decoded version of the BT blob. this.buffer = new Buffer(this.blob, 'hex'); + // Copy the Instance ID to the reserve offset + 4 bytes deeper. Copy in 4 bytes. instanceId.copy(this.buffer, this.reserveOffset + 4, 0, 3); + // Generate a clean, shiny new buffer. this.previous_hash = new Buffer(32); + // Copy in bytes 7 through 39 to this.previous_hash from the current BT. this.buffer.copy(this.previous_hash, 0, 7, 39); + // Reset the Nonce. - This is the per-miner/pool nonce this.extraNonce = 0; + // The clientNonceLocation is the location at which the client pools should set the nonces for each of their clients. + this.clientNonceLocation = this.reserveOffset + 8; + // The clientPoolLocation is for multi-thread/multi-server pools to handle the nonce for each of their tiers. + this.clientPoolLocation = this.reserveOffset + 12; this.nextBlob = function () { + // Write a 32 bit integer, big-endian style to the 0 byte of the reserve offset. this.buffer.writeUInt32BE(++this.extraNonce, this.reserveOffset); + // Convert the blob into something hashable. return global.coinFuncs.convertBlob(this.buffer).toString('hex'); }; + // Make it so you can get the raw block blob out. + this.nextBlobWithChildNonce = function () { + // Write a 32 bit integer, big-endian style to the 0 byte of the reserve offset. + this.buffer.writeUInt32BE(++this.extraNonce, this.reserveOffset); + // Don't convert the blob to something hashable. You bad. + return this.buffer.toString('hex'); + }; }; - this.cryptoNight = multiHashing['cryptonight']; + this.cryptoNight = multiHashing.cryptoNight; } diff --git a/lib/pool.js b/lib/pool.js index 4715633..d0e556c 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -215,9 +215,13 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer let pass_split = pass.split(":"); this.error = ""; this.identifier = pass_split[0]; + this.proxy = false; if (agent && agent.includes('MinerGate')){ this.identifier = "MinerGate"; } + if (agent && agent.includes('xmr-node-proxy')){ + this.proxy = true; + } this.paymentID = null; this.valid_miner = true; this.port = port; @@ -463,27 +467,52 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer return this.cachedJob; } - let blob = activeBlockTemplate.nextBlob(); - let target = this.getTargetHex(); - this.lastBlockHeight = activeBlockTemplate.height; + if (!this.proxy){ + let blob = activeBlockTemplate.nextBlob(); + let target = this.getTargetHex(); + this.lastBlockHeight = activeBlockTemplate.height; - let newJob = { - id: crypto.pseudoRandomBytes(21).toString('base64'), - extraNonce: activeBlockTemplate.extraNonce, - height: activeBlockTemplate.height, - difficulty: this.difficulty, - diffHex: this.diffHex, - submissions: [] - }; + let newJob = { + id: crypto.pseudoRandomBytes(21).toString('base64'), + extraNonce: activeBlockTemplate.extraNonce, + height: activeBlockTemplate.height, + difficulty: this.difficulty, + diffHex: this.diffHex, + submissions: [] + }; - this.validJobs.enq(newJob); - this.cachedJob = { - blob: blob, - job_id: newJob.id, - target: target, - id: this.id - }; + this.validJobs.enq(newJob); + this.cachedJob = { + blob: blob, + job_id: newJob.id, + target: target, + id: this.id + }; + } else { + let blob = activeBlockTemplate.nextBlobWithChildNonce(); + this.lastBlockHeight = activeBlockTemplate.height; + + let newJob = { + id: crypto.pseudoRandomBytes(21).toString('base64'), + extraNonce: activeBlockTemplate.extraNonce, + height: activeBlockTemplate.height, + difficulty: this.difficulty, + diffHex: this.diffHex, + submissions: [] + }; + this.validJobs.enq(newJob); + this.cachedJob = { + blocktemplate_blob: blob, + difficulty: activeBlockTemplate.difficulty, + height: activeBlockTemplate.height, + reserved_offset: activeBlockTemplate.reserveOffset, + client_nonce_offset: activeBlockTemplate.clientNonceLocation, + client_pool_offset: activeBlockTemplate.clientPoolLocation, + job_id: newJob.id, + id: this.id + }; + } return this.cachedJob; }; } @@ -526,10 +555,19 @@ function recordShareData(miner, job, shareDiff, blockCandidate, hashHex, shareTy } -function processShare(miner, job, blockTemplate, nonce, resultHash) { +function processShare(miner, job, blockTemplate, params) { + let nonce = params.nonce; + let resultHash = params.result; let template = new Buffer(blockTemplate.buffer.length); - blockTemplate.buffer.copy(template); - template.writeUInt32BE(job.extraNonce, blockTemplate.reserveOffset); + if (!miner.proxy){ + blockTemplate.buffer.copy(template); + template.writeUInt32BE(job.extraNonce, blockTemplate.reserveOffset); + } else { + blockTemplate.buffer.copy(template); + template.writeUInt32BE(job.extraNonce, blockTemplate.reserveOffset); + template.writeUInt32BE(params.workerNonce, blockTemplate.clientNonceLocation); + template.writeUInt32BE(params.poolNonce, blockTemplate.clientPoolLocation); + } let shareBuffer = global.coinFuncs.constructNewBlob(template, new Buffer(nonce, 'hex')); let convertedBlob; @@ -691,7 +729,7 @@ function handleMinerData(method, params, ip, portData, sendReply, pushMessage) { return; } - let shareAccepted = processShare(miner, job, blockTemplate, params.nonce, params.result); + let shareAccepted = processShare(miner, job, blockTemplate, params); miner.checkBan(shareAccepted); if (global.config.pool.trustedMiners) { From 778dd7d1b890c0a97c27de2b29269b80d2985c7f Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Mon, 3 Jul 2017 06:49:32 -0700 Subject: [PATCH 02/11] Helps if I hit the right frunction. --- lib/coins/xmr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/coins/xmr.js b/lib/coins/xmr.js index 977759f..fe8fa26 100644 --- a/lib/coins/xmr.js +++ b/lib/coins/xmr.js @@ -151,7 +151,7 @@ function Coin(data){ }; }; - this.cryptoNight = multiHashing.cryptoNight; + this.cryptoNight = multiHashing.cryptonight; } From f77ceae79bb4795b8c0fbed850ba86c5e22027cf Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Mon, 3 Jul 2017 07:47:37 -0700 Subject: [PATCH 03/11] Fixes to send more diff information down the wire. --- lib/blockManager.js | 4 ++-- lib/pool.js | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/blockManager.js b/lib/blockManager.js index 81262fd..02a286a 100644 --- a/lib/blockManager.js +++ b/lib/blockManager.js @@ -271,12 +271,12 @@ function calculatePPLNSPayments(blockHeader) { paymentData[userIdentifier].amount = paymentData[userIdentifier].amount + amountToPay; let donations = 0; if(global.config.payout.devDonation > 0){ - let devDonation = (feesToPay * (global.config.payout.devDonation / 100)); + let devDonation = Math.floor(feesToPay * (global.config.payout.devDonation / 100)); donations += devDonation; paymentData[global.coinFuncs.coinDevAddress].amount = paymentData[global.coinFuncs.coinDevAddress].amount + devDonation ; } if(global.config.payout.poolDevDonation > 0){ - let poolDevDonation = (feesToPay * (global.config.payout.poolDevDonation / 100)); + let poolDevDonation = Math.floor(feesToPay * (global.config.payout.poolDevDonation / 100)); donations += poolDevDonation; paymentData[global.coinFuncs.poolDevAddress].amount = paymentData[global.coinFuncs.poolDevAddress].amount + poolDevDonation; } diff --git a/lib/pool.js b/lib/pool.js index d0e556c..b9746e8 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -509,6 +509,8 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer reserved_offset: activeBlockTemplate.reserveOffset, client_nonce_offset: activeBlockTemplate.clientNonceLocation, client_pool_offset: activeBlockTemplate.clientPoolLocation, + target_diff: this.difficulty, + target_diff_hex: this.diffHex, job_id: newJob.id, id: this.id }; From 9f62144d04033aec98a013c38289b296bd55e511 Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Tue, 4 Jul 2017 09:34:54 -0700 Subject: [PATCH 04/11] Update to reverse the pool nonce vs the client nonce. --- lib/coins/xmr.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/coins/xmr.js b/lib/coins/xmr.js index fe8fa26..7199983 100644 --- a/lib/coins/xmr.js +++ b/lib/coins/xmr.js @@ -133,9 +133,9 @@ function Coin(data){ // Reset the Nonce. - This is the per-miner/pool nonce this.extraNonce = 0; // The clientNonceLocation is the location at which the client pools should set the nonces for each of their clients. - this.clientNonceLocation = this.reserveOffset + 8; + this.clientNonceLocation = this.reserveOffset + 12; // The clientPoolLocation is for multi-thread/multi-server pools to handle the nonce for each of their tiers. - this.clientPoolLocation = this.reserveOffset + 12; + this.clientPoolLocation = this.reserveOffset + 8; this.nextBlob = function () { // Write a 32 bit integer, big-endian style to the 0 byte of the reserve offset. this.buffer.writeUInt32BE(++this.extraNonce, this.reserveOffset); From a875391b0c6b3bd3917b73df6af206c25f20adc8 Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Tue, 4 Jul 2017 10:04:17 -0700 Subject: [PATCH 05/11] Expand reserve_size so there is a NUL byte at the end, this allows the end-pools to use a UInt32BE call at the end. --- lib/coins/xmr.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/coins/xmr.js b/lib/coins/xmr.js index 7199983..40ba728 100644 --- a/lib/coins/xmr.js +++ b/lib/coins/xmr.js @@ -69,7 +69,7 @@ function Coin(data){ this.getBlockTemplate = function(walletAddress, callback){ global.support.rpcDaemon('getblocktemplate', { - reserve_size: 16, + reserve_size: 17, wallet_address: walletAddress }, function(body){ return callback(body); @@ -106,7 +106,9 @@ function Coin(data){ Generating a block template is a simple thing. Ask for a boatload of information, and go from there. Important things to consider. The reserved space is 13 bytes long now in the following format: - |minerNonce/extraNonce - 4 bytes|instanceId - 4 bytes|clientNonce - 4 bytes|clientPoolNonce - 4 bytes| + Assuming that the extraNonce starts at byte 130: + |130-133|134-137|138-141|142-145| + |minerNonce/extraNonce - 4 bytes|instanceId - 4 bytes|clientPoolNonce - 4 bytes|clientNonce - 4 bytes| This is designed to allow a single block template to be used on up to 4 billion poolSlaves (clientPoolNonce) Each with 4 billion clients. (clientNonce) While being unique to this particular pool thread (instanceId) From e0d39be6940128c8c0a2c6ace65e060488f74e31 Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Tue, 4 Jul 2017 12:05:55 -0700 Subject: [PATCH 06/11] Update for the pool nonce save location. --- lib/pool.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/pool.js b/lib/pool.js index b9746e8..2675616 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -479,6 +479,8 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer height: activeBlockTemplate.height, difficulty: this.difficulty, diffHex: this.diffHex, + clientPoolLocation: activeBlockTemplate.clientPoolLocation, + clientNonceLocation: activeBlockTemplate.clientNonceLocation, submissions: [] }; @@ -567,8 +569,8 @@ function processShare(miner, job, blockTemplate, params) { } else { blockTemplate.buffer.copy(template); template.writeUInt32BE(job.extraNonce, blockTemplate.reserveOffset); - template.writeUInt32BE(params.workerNonce, blockTemplate.clientNonceLocation); - template.writeUInt32BE(params.poolNonce, blockTemplate.clientPoolLocation); + template.writeUInt32BE(params.poolNonce, job.clientPoolLocation); + template.writeUInt32BE(params.workerNonce, job.clientNonceLocation); } let shareBuffer = global.coinFuncs.constructNewBlob(template, new Buffer(nonce, 'hex')); From e23658c21f76efbba8ea25a3a3ca317edd3aabad Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Tue, 4 Jul 2017 12:13:10 -0700 Subject: [PATCH 07/11] Only the proxied versions need that data. Really. Why doesn't node blow up if I do that... --- lib/pool.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pool.js b/lib/pool.js index 2675616..3792ce4 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -479,8 +479,6 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer height: activeBlockTemplate.height, difficulty: this.difficulty, diffHex: this.diffHex, - clientPoolLocation: activeBlockTemplate.clientPoolLocation, - clientNonceLocation: activeBlockTemplate.clientNonceLocation, submissions: [] }; @@ -501,6 +499,8 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer height: activeBlockTemplate.height, difficulty: this.difficulty, diffHex: this.diffHex, + clientPoolLocation: activeBlockTemplate.clientPoolLocation, + clientNonceLocation: activeBlockTemplate.clientNonceLocation, submissions: [] }; this.validJobs.enq(newJob); From 93f64201a9aab8515ba389611c37b9b602e1491b Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Tue, 4 Jul 2017 13:10:40 -0700 Subject: [PATCH 08/11] Update for diff cycling. --- lib/pool.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pool.js b/lib/pool.js index 3792ce4..2602a5d 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -491,6 +491,10 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer }; } else { let blob = activeBlockTemplate.nextBlobWithChildNonce(); + if (this.newDiff) { + this.difficulty = this.newDiff; + this.newDiff = null; + } this.lastBlockHeight = activeBlockTemplate.height; let newJob = { From 687decc04d7c3433b5e529cc393a6e7b0aee3646 Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Tue, 4 Jul 2017 13:35:33 -0700 Subject: [PATCH 09/11] Perma-adding Atrides fix + setting the target for the proxied clients to 1/10th of normal. --- lib/pool.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/pool.js b/lib/pool.js index 2602a5d..6002a2b 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -394,7 +394,13 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer this.updateDifficulty = function(){ if (this.hashes > 0) { - this.setNewDiff(Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000))) * global.config.pool.targetTime); + let newDiff = 0; + if (this.proxy){ + newDiff = Math.floor(Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000))) * global.config.pool.targetTime/10); + } else { + newDiff = Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000))) * global.config.pool.targetTime; + } + this.setNewDiff(newDiff); } else { this.updateDifficultyOld(); } @@ -403,7 +409,7 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer this.setNewDiff = function (difficulty) { this.newDiff = Math.round(difficulty); debug(threadName + "Difficulty: " + this.newDiff + " For: " + this.logString + " Time Average: " + this.shareTimeBuffer.average(this.lastShareTime) + " Entries: " + this.shareTimeBuffer.size() + " Sum: " + this.shareTimeBuffer.sum()); - if (this.newDiff > global.config.pool.maxDifficulty) { + if (this.newDiff > global.config.pool.maxDifficulty && !this.proxy) { this.newDiff = global.config.pool.maxDifficulty; } if (this.difficulty === this.newDiff) { @@ -876,7 +882,7 @@ if (cluster.isMaster) { socket.on('data', function (d) { dataBuffer += d; - if (Buffer.byteLength(dataBuffer, 'utf8') > 10240) { //10KB + if (Buffer.byteLength(dataBuffer, 'utf8') > 102400) { //10KB dataBuffer = null; console.warn(threadName + 'Excessive packet size from: ' + socket.remoteAddress); socket.destroy(); From 3c3f347c889abbc11c1ebc77994a8e18fa30adef Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Tue, 4 Jul 2017 13:55:24 -0700 Subject: [PATCH 10/11] Update to make it so proxies aim for 1 second share times, rather than 3. --- lib/pool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pool.js b/lib/pool.js index 6002a2b..212bbdf 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -396,7 +396,7 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer if (this.hashes > 0) { let newDiff = 0; if (this.proxy){ - newDiff = Math.floor(Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000))) * global.config.pool.targetTime/10); + newDiff = Math.floor(Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000)))); } else { newDiff = Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000))) * global.config.pool.targetTime; } From 9c1dd12d311dccf40eb34a10aadb92d3cebb9c64 Mon Sep 17 00:00:00 2001 From: Alexander Blair Date: Mon, 10 Jul 2017 18:49:54 -0700 Subject: [PATCH 11/11] Update to patch the number of Valid Jobs and to lock in the new code to properly support the proxy. --- lib/pool.js | 86 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/lib/pool.js b/lib/pool.js index 212bbdf..bb1789a 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -23,7 +23,7 @@ let threadName; let minerCount = []; let BlockTemplate = global.coinFuncs.BlockTemplate; let hexMatch = new RegExp("^[0-9a-f]+$"); -let totalShares=0, trustedShares=0, normalShares=0, invalidShares=0; +let totalShares = 0, trustedShares = 0, normalShares = 0, invalidShares = 0; Buffer.prototype.toByteArray = function () { @@ -33,12 +33,12 @@ Buffer.prototype.toByteArray = function () { if (cluster.isMaster) { threadName = "(Master) "; - setInterval(function(){ + setInterval(function () { console.log(`Processed ${trustedShares}/${normalShares}/${invalidShares}/${totalShares} Trusted/Validated/Invalid/Total shares in the last 30 seconds`); - totalShares=0; - trustedShares=0; - normalShares=0; - invalidShares=0; + totalShares = 0; + trustedShares = 0; + normalShares = 0; + invalidShares = 0; }, 30000); } else { threadName = "(Worker " + cluster.worker.id + " - " + process.pid + ") "; @@ -59,7 +59,7 @@ function registerPool() { [global.config.pool_id, global.config.bind_ip, true, global.config.hostname, true]); global.mysql.query("DELETE FROM ports WHERE pool_id = ?", [global.config.pool_id]).then(function () { global.config.ports.forEach(function (port) { - if ('ssl' in port && port['ssl'] === true) { + if ('ssl' in port && port.ssl === true) { global.mysql.query("INSERT INTO ports (pool_id, network_port, starting_diff, port_type, description, hidden, ip_address, ssl_port) values (?, ?, ?, ?, ?, ?, ?, 1)", [global.config.pool_id, port.port, port.difficulty, port.portType, port.desc, port.hidden, global.config.bind_ip]); } else { @@ -171,7 +171,7 @@ function templateUpdate(repeating) { newBlockTemplate(rpcResponse); } } - if (repeating !== false){ + if (repeating !== false) { setTimeout(templateUpdate, 300); } } @@ -216,10 +216,10 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer this.error = ""; this.identifier = pass_split[0]; this.proxy = false; - if (agent && agent.includes('MinerGate')){ + if (agent && agent.includes('MinerGate')) { this.identifier = "MinerGate"; } - if (agent && agent.includes('xmr-node-proxy')){ + if (agent && agent.includes('xmr-node-proxy')) { this.proxy = true; } this.paymentID = null; @@ -248,7 +248,7 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer this.fixed_diff = false; this.difficulty = startingDiff; this.connectTime = Date.now(); - if (agent && agent.includes('NiceHash')){ + if (agent && agent.includes('NiceHash')) { this.fixed_diff = true; this.difficulty = global.coinFuncs.niceHashDiff; } @@ -316,7 +316,7 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer this.error = "Exchange addresses need payment IDs"; this.valid_miner = false; } - if (!activeBlockTemplate){ + if (!activeBlockTemplate) { this.error = "No active block template"; this.valid_miner = false; } @@ -347,7 +347,7 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer }; } - this.validJobs = global.support.circularBuffer(10); + this.validJobs = global.support.circularBuffer(4); this.cachedJob = null; @@ -392,10 +392,10 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer } }; - this.updateDifficulty = function(){ + this.updateDifficulty = function () { if (this.hashes > 0) { let newDiff = 0; - if (this.proxy){ + if (this.proxy) { newDiff = Math.floor(Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000)))); } else { newDiff = Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000))) * global.config.pool.targetTime; @@ -419,10 +419,10 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer this.newDiff = global.config.pool.minDifficulty; } debug(threadName + "Difficulty change to: " + this.newDiff + " For: " + this.logString); - if (this.hashes > 0){ - debug(threadName + "Hashes: " + this.hashes + " in: " + Math.floor((Date.now() - this.connectTime)/1000) + " seconds gives: " + - Math.floor(this.hashes/(Math.floor((Date.now() - this.connectTime)/1000))) + " hashes/second or: " + - Math.floor(this.hashes/(Math.floor((Date.now() - this.connectTime)/1000))) * global.config.pool.targetTime + " difficulty versus: " + this.newDiff); + if (this.hashes > 0) { + debug(threadName + "Hashes: " + this.hashes + " in: " + Math.floor((Date.now() - this.connectTime) / 1000) + " seconds gives: " + + Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000))) + " hashes/second or: " + + Math.floor(this.hashes / (Math.floor((Date.now() - this.connectTime) / 1000))) * global.config.pool.targetTime + " difficulty versus: " + this.newDiff); } this.messageSender('job', this.getJob()); }; @@ -468,12 +468,12 @@ function Miner(id, login, pass, ipAddress, startingDiff, messageSender, protoVer return buffReversed.toString('hex'); }; this.getJob = function () { - + if (this.lastBlockHeight === activeBlockTemplate.height && !this.newDiff && this.cachedJob !== null) { return this.cachedJob; } - if (!this.proxy){ + if (!this.proxy) { let blob = activeBlockTemplate.nextBlob(); let target = this.getTargetHex(); this.lastBlockHeight = activeBlockTemplate.height; @@ -573,7 +573,7 @@ function processShare(miner, job, blockTemplate, params) { let nonce = params.nonce; let resultHash = params.result; let template = new Buffer(blockTemplate.buffer.length); - if (!miner.proxy){ + if (!miner.proxy) { blockTemplate.buffer.copy(template); template.writeUInt32BE(job.extraNonce, blockTemplate.reserveOffset); } else { @@ -601,7 +601,7 @@ function processShare(miner, job, blockTemplate, params) { if (hash.toString('hex') !== resultHash) { console.error(threadName + "Bad share from miner " + miner.logString); process.send({type: 'invalidShare'}); - if (miner.incremented === false){ + if (miner.incremented === false) { miner.newDiff = miner.difficulty + 1; miner.incremented = true; } else { @@ -713,24 +713,34 @@ function handleMinerData(method, params, ip, portData, sendReply, pushMessage) { global.database.storeInvalidShare(miner.invalidShareProto); return; } - - if (job.submissions.indexOf(params.nonce) !== -1) { - console.warn(threadName + 'Duplicate share: ' + JSON.stringify(params) + ' from ' + miner.logString); - miner.checkBan(false); - sendReply('Duplicate share'); - global.database.storeInvalidShare(miner.invalidShareProto); - return; + if (!miner.proxy) { + if (job.submissions.indexOf(params.nonce) !== -1) { + console.warn(threadName + 'Duplicate share: ' + JSON.stringify(params) + ' from ' + miner.logString); + miner.checkBan(false); + sendReply('Duplicate share'); + global.database.storeInvalidShare(miner.invalidShareProto); + return; + } + job.submissions.push(params.nonce); + } else { + let nonce_test = `${params.nonce}_${params.poolNonce}_${params.workerNonce}`; + if (job.submissions.indexOf(nonce_test) !== -1) { + console.warn(threadName + 'Duplicate share: ' + JSON.stringify(params) + ' from ' + miner.logString); + miner.checkBan(false); + sendReply('Duplicate share'); + global.database.storeInvalidShare(miner.invalidShareProto); + return; + } + job.submissions.push(nonce_test); } - job.submissions.push(params.nonce); - let blockTemplate = activeBlockTemplate.height === job.height ? activeBlockTemplate : pastBlockTemplates.toarray().filter(function (t) { - return t.height === job.height; - })[0]; + return t.height === job.height; + })[0]; if (!blockTemplate) { console.warn(threadName + 'Block expired, Height: ' + job.height + ' from ' + miner.logString); - if (miner.incremented === false){ + if (miner.incremented === false) { miner.newDiff = miner.difficulty + 1; miner.incremented = true; } else { @@ -820,7 +830,7 @@ if (cluster.isMaster) { workerList.push(worker); }); templateUpdate(); - global.support.sendEmail(global.config.general.adminEmail, "Pool server "+global.config.hostname+" online", "The pool server: "+global.config.hostname+" with IP: "+global.config.bind_ip+" is online"); + global.support.sendEmail(global.config.general.adminEmail, "Pool server " + global.config.hostname + " online", "The pool server: " + global.config.hostname + " with IP: " + global.config.bind_ip + " is online"); } else { setInterval(checkAliveMiners, 30000); setInterval(retargetMiners, global.config.pool.retargetTime * 1000); @@ -830,7 +840,7 @@ if (cluster.isMaster) { templateUpdate(false); }, 60000); async.each(global.config.ports, function (portData) { - if (global.config[portData.portType].enable !== true){ + if (global.config[portData.portType].enable !== true) { return; } let handleMessage = function (socket, jsonData, pushMessage) { @@ -931,7 +941,7 @@ if (cluster.isMaster) { }); } - if ('ssl' in portData && portData['ssl'] === true) { + if ('ssl' in portData && portData.ssl === true) { tls.createServer({ key: fs.readFileSync('cert.key'), cert: fs.readFileSync('cert.pem')