diff --git a/README.md b/README.md index 533a445..47ae0bb 100644 --- a/README.md +++ b/README.md @@ -280,14 +280,16 @@ var pool = Stratum.createPool({ Listen to pool events ```javascript /* + 'data' object contains: job: 4, //stratum work job ID ip: '71.33.19.37', //ip address of client worker: 'matt.worker1', //stratum worker name - difficulty: 64, //stratum client difficulty - reward: 5000000000, //the number of satoshis received as payment for solving this block height: 443795, //block height - networkDifficulty: 3349 //network difficulty for this block + reward: 5000000000, //the number of satoshis received as payment for solving this block + difficulty: 64, //stratum worker difficulty + shareDiff: 78, //actual difficulty of the share + blockDiff: 3349 //difficulty for this block //AAK the block solution - set if block was found blockHash: '110c0447171ad819dd181216d5d80f41e9218e25d833a2789cb8ba289a52eee4', diff --git a/lib/algoProperties.js b/lib/algoProperties.js index d7094c3..e93ea9c 100644 --- a/lib/algoProperties.js +++ b/lib/algoProperties.js @@ -2,12 +2,12 @@ var bignum = require('bignum'); var multiHashing = require('multi-hashing'); var util = require('./util.js'); +var diff1 = global.diff1 = bignum('00000000ffff0000000000000000000000000000000000000000000000000000', 16); var algos = module.exports = global.algos = { sha256: { //Uncomment diff if you want to use hardcoded truncated diff - //diff: new Buffer('00000000ffff0000000000000000000000000000000000000000000000000000', 'hex'), - shift: 32, + //diff: '00000000ffff0000000000000000000000000000000000000000000000000000', multiplier: Math.pow(2, 32), hash: function(){ return function(){ @@ -17,8 +17,7 @@ var algos = module.exports = global.algos = { }, scrypt: { //Uncomment diff if you want to use hardcoded truncated diff - //diff: new Buffer('0000ffff00000000000000000000000000000000000000000000000000000000', 'hex'), - shift: 20, + //diff: '0000ffff00000000000000000000000000000000000000000000000000000000', multiplier: Math.pow(2, 16), hash: function(){ return function(){ @@ -27,7 +26,6 @@ var algos = module.exports = global.algos = { } }, 'scrypt-jane': { - shift: 20, multiplier: Math.pow(2, 16), hash: function(coinConfig){ var nTimestamp = coinConfig.chainStartTime || 1367991200; @@ -39,7 +37,6 @@ var algos = module.exports = global.algos = { } }, 'scrypt-n': { - shift: 20, multiplier: Math.pow(2, 16), hash: function(coinConfig){ @@ -63,8 +60,7 @@ var algos = module.exports = global.algos = { } }, x11: { - shift: 20, - multiplier: Math.pow(2, 32.3), + multiplier: Math.pow(2, 32), hash: function(){ return function(){ return multiHashing.x11.apply(this, arguments); @@ -72,32 +68,14 @@ var algos = module.exports = global.algos = { } }, quark: { - shift: 20, - multipler: Math.pow(2, 16), + multiplier: Math.pow(2, 16), hash: function(){ return function(){ return multiHashing.quark.apply(this, arguments); } } }, - skein: { - shift: 20, - hash: function(){ - return function(){ - return multiHashing.skein.apply(this, arguments); - } - } - }, - bcrypt: { - shift: 11, - hash: function(){ - return function(){ - return multiHashing.bcrypt.apply(this, arguments); - } - } - }, keccak: { - shift: 24, multiplier: Math.pow(2, 24), hash: function(coinConfig){ if (coinConfig.normalHashing === true) { @@ -112,6 +90,22 @@ var algos = module.exports = global.algos = { } } }, + skein: { + multiplier: Math.pow(2, 16), + hash: function(){ + return function(){ + return multiHashing.skein.apply(this, arguments); + } + } + }, + bcrypt: { + shift: 11, + hash: function(){ + return function(){ + return multiHashing.bcrypt.apply(this, arguments); + } + } + }, blake: { shift: 24, hash: function(){ @@ -148,9 +142,18 @@ var algos = module.exports = global.algos = { for (var algo in algos){ - if (!algos[algo].diff) { + if (algos[algo].diff){ + algos[algo].maxDiff = bignum(algos[algo].diff, 16); + } + else if (algos[algo].shift){ algos[algo].nonTruncatedDiff = util.shiftMax256Right(algos[algo].shift); algos[algo].bits = util.bufferToCompactBits(algos[algo].nonTruncatedDiff); - algos[algo].diff = util.convertBitsToBuff(algos[algo].bits); + algos[algo].maxDiff = bignum.fromBuffer(util.convertBitsToBuff(algos[algo].bits)); } -} + else if (algos[algo].multiplier){ + algos[algo].maxDiff = diff1.mul(Math.pow(2, 32) / algos[algo].multiplier); + } + else{ + algos[algo].maxDiff = diff1; + } +} \ No newline at end of file diff --git a/lib/blockTemplate.js b/lib/blockTemplate.js index 307de33..1fe4501 100644 --- a/lib/blockTemplate.js +++ b/lib/blockTemplate.js @@ -5,7 +5,6 @@ var transactions = require('./transactions.js'); var util = require('./util.js'); - /** * The BlockTemplate class holds a single job. * and provides several methods to validate and submit it to the daemon coin @@ -36,14 +35,17 @@ var BlockTemplate = module.exports = function BlockTemplate(maxDifficulty, jobId this.jobId = jobId; - /* - Use the 'target' field if available, but some daemons only return the 'bits' field - */ - this.target = rpcData.target ? - bignum.fromBuffer(new Buffer(rpcData.target, 'hex')) : - util.bignumFromBits(rpcData.bits); - this.difficulty = maxDifficulty.div(this.target); + //Use the 'target' field if available, but some daemons only return the 'bits' field + /*this.target = rpcData.target ? + bignum.fromBuffer(new Buffer(rpcData.target, 'hex')) : + util.bignumFromBits(rpcData.bits);*/ + + this.target = rpcData.target ? + bignum(rpcData.target, 16) : + util.bignumFromBitsHex(rpcData.bits); + + this.difficulty = parseFloat((diff1.toNumber() / this.target.toNumber()).toFixed(9)); this.prevHashReversed = util.reverseByteOrder(new Buffer(rpcData.previousblockhash, 'hex')).toString('hex'); this.transactionData = Buffer.concat(rpcData.transactions.map(function(tx){ diff --git a/lib/jobManager.js b/lib/jobManager.js index f74965c..15c4b00 100644 --- a/lib/jobManager.js +++ b/lib/jobManager.js @@ -208,7 +208,9 @@ var JobManager = module.exports = function JobManager(maxDifficulty, options){ var blockHash; var blockHex; - var shareDiff = maxDifficulty.div(headerBigNum); + var shareDiff = difficulty < 1 ? + maxDifficulty.toNumber() / headerBigNum.toNumber() : + maxDifficulty.div(headerBigNum).toNumber(); //Check if share is a block candidate (matched network difficulty) if (job.target.ge(headerBigNum)){ @@ -219,22 +221,20 @@ var JobManager = module.exports = function JobManager(maxDifficulty, options){ if (options.emitInvalidBlockHashes) blockHashInvalid = util.reverseBuffer(util.sha256d(headerBuffer)).toString('hex'); - //Difficulty the miner is set to - var targetUser = maxDifficulty.div(difficulty); //Check if share didn't reached the miner's difficulty) - if (headerBigNum.gt(targetUser)){ + if (shareDiff < difficulty){ //Check if share matched a previous difficulty from before a vardiff retarget - if (previousDifficulty && !headerBigNum.gt(maxDifficulty.div(previousDifficulty))){ + if (previousDifficulty && shareDiff >= previousDifficulty){ difficulty = previousDifficulty; } else{ - var offPercent = 100 - (shareDiff.toNumber() / difficulty) * 100; + var offPercent = 100 - (shareDiff / difficulty) * 100; //Check to see if low diff share is within acceptable configured range if (offPercent > (options.shareVariancePercent || 0)){ - return shareError([23, 'low difficulty share of ' + shareDiff.toString()]); + return shareError([23, 'low difficulty share of ' + shareDiff]); } else{ _this.emit('log', 'warning', 'Share accepted a low diff ' + shareDiff + ' off by ' + offPercent.toFixed(2) + '%'); @@ -249,14 +249,13 @@ var JobManager = module.exports = function JobManager(maxDifficulty, options){ job: jobId, ip: ipAddress, worker: workerName, - difficulty: difficulty, - shareDiff: shareDiff, height: job.rpcData.height, reward: job.rpcData.coinbasevalue, - networkDifficulty : job.difficulty.toString(), + difficulty: difficulty, + shareDiff: shareDiff, + blockDiff : job.difficulty, blockHash: blockHash, blockHashInvalid: blockHashInvalid - }, blockHex); return {result: true, error: null, blockHash: blockHash}; diff --git a/lib/pool.js b/lib/pool.js index f6327ae..ea061d3 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -44,12 +44,15 @@ var pool = module.exports = function pool(options, authorizeFn){ throw new Error(); } - var diff1 = options.coin.diffShift ? - util.getTruncatedDiff(options.coin.diffShift) : - algos[options.coin.algorithm].diff; + //var diff1 = options.coin.diffShift ? + // util.getTruncatedDiff(options.coin.diffShift) : + // algos[options.coin.algorithm].diff; + //Which number to use as dividend when converting difficulty to target - var maxDifficulty = bignum.fromBuffer(diff1); + var maxDifficulty = algos[options.coin.algorithm].maxDiff; + console.log(options.coin.name + ' ' + maxDifficulty.toString(16)); + this.start = function(){ @@ -86,14 +89,13 @@ var pool = module.exports = function pool(options, authorizeFn){ Object.keys(options.ports).forEach(function(port){ var portDiff = options.ports[port].diff; - if (_this.jobManager.currentJob.difficulty.le(portDiff)) - portWarnings.push('port ' + port + ' w/ difficulty ' + portDiff); - + if (options.initStats.difficulty < portDiff) + portWarnings.push('port ' + port + ' w/ diff ' + portDiff); }); //Only let the first fork show synced status or the log wil look flooded with it if (portWarnings.length > 0 && (!process.env.forkId || process.env.forkId === '0')) { - var warnMessage = 'Network difficulty of ' + _this.jobManager.currentJob.difficulty.toString() + ' is lower than ' + var warnMessage = 'Network diff of ' + options.initStats.difficulty + ' is lower than ' + portWarnings.join(' and '); emitWarningLog(warnMessage); } @@ -117,15 +119,14 @@ var pool = module.exports = function pool(options, authorizeFn){ 'Detected Reward Type:\t' + options.coin.reward, 'Current Block Height:\t' + _this.jobManager.currentJob.rpcData.height, 'Current Connect Peers:\t' + options.initStats.connections, + 'Current Block Diff:\t' + _this.jobManager.currentJob.difficulty, + 'Network Difficulty:\t' + options.initStats.difficulty, 'Network Hash Rate:\t' + util.getReadableHashRateString(options.initStats.networkHashRate), - 'Network Difficulty:\t' + _this.jobManager.currentJob.difficulty.toString(), - 'Listening Port(s):\t' + _this.options.initStats.stratumPorts.join(', ') + 'Stratum Port(s):\t' + _this.options.initStats.stratumPorts.join(', ') ]; - - if (typeof options.blockRefreshInterval === "number" && options.blockRefreshInterval > 0) - infoLines.push('Block polling every:\t' + options.blockRefreshInterval + ' ms') + infoLines.push('Block polling every:\t' + options.blockRefreshInterval + ' ms'); emitSpecialLog(infoLines.join('\n\t\t\t\t\t\t')); diff --git a/lib/util.js b/lib/util.js index 6cf17af..c834a99 100644 --- a/lib/util.js +++ b/lib/util.js @@ -4,23 +4,6 @@ var base58 = require('base58-native'); var bignum = require('bignum'); -/* -Used to convert getblocktemplate bits field into target if target is not included. -More info: https://en.bitcoin.it/wiki/Target - */ -exports.bignumFromBits = function(bitsString){ - var bitsBuff = new Buffer(bitsString, 'hex'); - var numBytes = bitsBuff.readUInt8(0); - var bigBits = bignum.fromBuffer(bitsBuff.slice(1)); - var target = bigBits.mul( - bignum(2).pow( - bignum(8).mul( - numBytes - 3 - ) - ) - ); - return target; -}; exports.sha256 = function(buffer){ var hash1 = crypto.createHash('sha256'); @@ -336,8 +319,12 @@ exports.bufferToCompactBits = function(startingBuff){ return compact; }; +/* + Used to convert getblocktemplate bits field into target if target is not included. + More info: https://en.bitcoin.it/wiki/Target + */ -exports.convertBitsToBuff = function(bitsBuff){ +exports.bignumFromBitsBuffer = function(bitsBuff){ var numBytes = bitsBuff.readUInt8(0); var bigBits = bignum.fromBuffer(bitsBuff.slice(1)); var target = bigBits.mul( @@ -347,12 +334,20 @@ exports.convertBitsToBuff = function(bitsBuff){ ) ) ); + return target; +}; +exports.bignumFromBitsHex = function(bitsString){ + var bitsBuff = new Buffer(bitsString, 'hex'); + return exports.bignumFromBitsBuffer(bitsBuff); +}; + +exports.convertBitsToBuff = function(bitsBuff){ + var target = exports.bignumFromBitsBuffer(bitsBuff); var resultBuff = target.toBuffer(); var buff256 = new Buffer(32); buff256.fill(0); resultBuff.copy(buff256, buff256.length - resultBuff.length); - return buff256; };