From 41b121ab56adf0edfa9b6d5384dc5496a76252d2 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Wed, 26 Mar 2014 15:07:03 -0600 Subject: [PATCH] Fixed bugs that happen when banning is disabled. Attempted to add keccak (maxcoin). --- lib/jobManager.js | 78 ++--------------------------------------- lib/pool.js | 89 ++++++++++++++++++++++++++++++++++++++++++++--- lib/stratum.js | 8 ++--- lib/util.js | 53 ++++++++++++++++------------ package.json | 1 + 5 files changed, 123 insertions(+), 106 deletions(-) diff --git a/lib/jobManager.js b/lib/jobManager.js index 13efcbe..f02cda8 100644 --- a/lib/jobManager.js +++ b/lib/jobManager.js @@ -3,10 +3,7 @@ var crypto = require('crypto'); var bignum = require('bignum'); -var scrypt = require('scrypt256-hash'); -var quark = require('quark-hash'); -var scryptJane = require('scrypt-jane-hash'); -var x11 = require('x11-hash'); + var util = require('./util.js'); var blockTemplate = require('./blockTemplate.js'); @@ -48,7 +45,7 @@ var JobCounter = function(){ * - newBlock(blockTemplate) - When a new block (previously unknown to the JobManager) is added, use this event to broadcast new jobs * - share(shareData, blockHex) - When a worker submits a share. It will have blockHex if a block was found **/ -var JobManager = module.exports = function JobManager(options){ +var JobManager = module.exports = function JobManager(maxDifficulty, hashDigest, options){ //private members @@ -56,77 +53,6 @@ var JobManager = module.exports = function JobManager(options){ var _this = this; var jobCounter = new JobCounter(); - //Which number to use as dividend when converting difficulty to target - var maxDifficulty = bignum((function(){ - switch(options.coin.algorithm){ - case 'sha256': - case 'skein': - return '00000000ffff0000000000000000000000000000000000000000000000000000'; - case 'scrypt': - case 'scrypt-jane': - case 'x11': - return '0000ffff00000000000000000000000000000000000000000000000000000000'; - case 'quark': - return '0000ffff00000000000000000000000000000000000000000000000000000000'; - case 'max': - return 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000' - } - })(), 16); - - - - //On initialization lets figure out which hashing algorithm to use - var hashDigest = (function(){ - switch(options.coin.algorithm){ - case 'sha256': - return function(){ - return util.doublesha.apply(this, arguments); - } - case 'scrypt': - return function(){ - return scrypt.digest.apply(this, arguments); - } - case 'scrypt-jane': - return function(){ - return scryptJane.digest.apply(this, arguments); - } - case 'quark': - return function(){ - return quark.digest.apply(this, arguments); - } - case 'x11': - return function(){ - return x11.digest.apply(this, arguments); - } - case 'skein': - return function(data){ - - /*var dataString = data.slice(0, 80).toString('ascii'); - var skeinHashed = skein(dataString); - - var hash1 = crypto.createHash('sha256'); - hash1.update(new Buffer(skeinHashed, 'hex')); - hash1 = hash1.digest(); - - return hash1;*/ - - //https://github.com/cruzrr/insanehash - //https://github.com/Crypto-Expert/stratum-mining/blob/master/lib/skein.py - } - case 'max': - return function(){ - //Keccak hash - //https://github.com/phusion/node-sha3 - //https://github.com/Prydie/maxcoin-hash-python - //https://github.com/ahmedbodi/stratum-mining-maxcoin/blob/master/lib/template_registry.py - } - default: - return function(){ - console.log('Hashing algorithm ' + options.coin.algorithm + ' not supported'); - } - } - })(); - //public members diff --git a/lib/pool.js b/lib/pool.js index 3676aad..8e4db34 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -1,5 +1,7 @@ var events = require('events'); var async = require('async'); +var bignum = require('bignum'); + var varDiff = require('./varDiff.js'); var daemon = require('./daemon.js'); @@ -8,6 +10,11 @@ var stratum = require('./stratum.js'); var jobManager = require('./jobManager.js'); var util = require('./util.js'); +var scrypt = require('scrypt256-hash'); +var quark = require('quark-hash'); +var scryptJane = require('scrypt-jane-hash'); +var x11 = require('x11-hash'); +var keccak = require('keccak-hash'); /** * Main pool object. It emits the following events: @@ -35,6 +42,74 @@ var pool = module.exports = function pool(options, authorizeFn){ var emitWarningLog = function(text) { _this.emit('log', 'warning', text); }; var emitErrorLog = function(text) { _this.emit('log', 'error' , text); }; + + //Which number to use as dividend when converting difficulty to target + var maxDifficulty = bignum((function(){ + switch(options.coin.algorithm){ + case 'sha256': + case 'skein': + return '00000000ffff0000000000000000000000000000000000000000000000000000'; + case 'scrypt': + case 'scrypt-jane': + case 'x11': + case 'quark': + case 'keccak': + return '0000ffff00000000000000000000000000000000000000000000000000000000'; + } + })(), 16); + + + + //On initialization lets figure out which hashing algorithm to use + var hashDigest = (function(){ + switch(options.coin.algorithm){ + case 'sha256': + return function(){ + return util.doublesha.apply(this, arguments); + } + case 'scrypt': + return function(){ + return scrypt.digest.apply(this, arguments); + } + case 'scrypt-jane': + return function(){ + return scryptJane.digest.apply(this, arguments); + } + case 'quark': + return function(){ + return quark.digest.apply(this, arguments); + } + case 'x11': + return function(){ + return x11.digest.apply(this, arguments); + } + case 'keccak': + return function(){ + return keccak.digest.apply(this, arguments); + } + case 'skein': + return function(data){ + + /*var dataString = data.slice(0, 80).toString('ascii'); + var skeinHashed = skein(dataString); + + var hash1 = crypto.createHash('sha256'); + hash1.update(new Buffer(skeinHashed, 'hex')); + hash1 = hash1.digest(); + + return hash1;*/ + + //https://github.com/cruzrr/insanehash + //https://github.com/Crypto-Expert/stratum-mining/blob/master/lib/skein.py + } + default: + return function(){ + console.log('Hashing algorithm ' + options.coin.algorithm + ' not supported'); + } + } + })(); + + this.start = function(){ emitLog('Starting pool for ' + options.coin.name + ' [' + options.coin.symbol.toUpperCase() + ']'); SetupJobManager(); @@ -115,7 +190,7 @@ var pool = module.exports = function pool(options, authorizeFn){ function SetupJobManager(){ - _this.jobManager = new jobManager(options); + _this.jobManager = new jobManager(maxDifficulty, hashDigest, options); _this.jobManager.on('newBlock', function(blockTemplate){ //Check if stratumServer has been initialized yet @@ -291,9 +366,15 @@ var pool = module.exports = function pool(options, authorizeFn){ return; } - publicKeyBuffer = options.coin.reward === 'POW' ? - util.script_to_address(results.addressInfo.address) : - util.script_to_pubkey(results.addressInfo.pubkey); + publicKeyBuffer = (function(){ + switch(options.coin.reward){ + case 'POS': + return util.pubkeyToScript(results.addressInfo.pubkey); + case 'POW': + if (options.coin.algorithm) + return util.addressToScript(results.addressInfo.address); + } + })(); var networkType = results.info.testnet ? 'testnet' : 'live blockchain'; diff --git a/lib/stratum.js b/lib/stratum.js index 08723ef..ac2edbc 100644 --- a/lib/stratum.js +++ b/lib/stratum.js @@ -36,7 +36,7 @@ var StratumClient = function(options){ this.shares = {valid: 0, invalid: 0}; - var considerBan = !banning.enabled ? function(){} : function(shareValid){ + var considerBan = (!banning || !banning.enabled) ? function(){} : function(shareValid){ if (shareValid === true) _this.shares.valid++; else _this.shares.invalid++; var totalShares = _this.shares.valid + _this.shares.invalid; @@ -292,7 +292,7 @@ var StratumServer = exports.Server = function StratumServer(ports, connectionTim //private members var socketTimeout = connectionTimeout * 1000; - var bannedMS = banning.time * 1000; + var bannedMS = banning ? banning.time * 1000 : null; var _this = this; var stratumClients = {}; @@ -301,7 +301,7 @@ var StratumServer = exports.Server = function StratumServer(ports, connectionTim var bannedIPs = {}; //Interval to look through bannedIPs for old bans and remove them in order to prevent a memory leak - var purgeOldBans = !banning.enabled ? null : setInterval(function(){ + var purgeOldBans = (!banning || !banning.enabled) ? null : setInterval(function(){ for (ip in bannedIPs){ var banTime = bannedIPs[ip]; if (Date.now() - banTime > banning.time) @@ -310,7 +310,7 @@ var StratumServer = exports.Server = function StratumServer(ports, connectionTim }, 1000 * banning.purgeInterval); this.handleNewClient = function (socket) { - if (banning.enabled && socket.remoteAddress in bannedIPs){ + if (banning && banning.enabled && socket.remoteAddress in bannedIPs){ var bannedTime = bannedIPs[socket.remoteAddress]; if ((Date.now() - bannedTime) < bannedMS){ socket.end(); diff --git a/lib/util.js b/lib/util.js index 2edeba4..987168a 100644 --- a/lib/util.js +++ b/lib/util.js @@ -236,34 +236,47 @@ exports.range = function(start, stop, step){ }; -exports.address_to_pubkeyhash = function(addr){ - addr = base58.decode(addr); +exports.getVersionByte = function(addr){ + return base58.decode(addr)[0]; +}; - if (addr.length != 25){ - console.log('invalid address length for ' + addr); - throw 'invalid address length'; +exports.addressToPubkey = function(addr){ + + var decoded = base58.decode(addr); + + if (decoded.length != 25){ + console.error('invalid address length for ' + addr); + throw new Error(); } - if (!addr) - return null; + if (!decoded){ + console.error('base58 decode failed for ' + addr); + throw new Error(); + } - var ver = addr[0]; - var cksumA = addr.slice(-4); - var cksumB = exports.doublesha(addr.slice(0, -4)).slice(0, 4); + /* We already do rpc.validateaddress so we don't need this + var ver = decoded[0]; + var cksumA = decoded.slice(-4); + var cksumB = exports.doublesha(decoded.slice(0, -4)).slice(0, 4); - if (cksumA.toString('hex') != cksumB.toString('hex')) - throw 'checksum did not match'; + if (cksumA.toString('hex') != cksumB.toString('hex')){ + console.error('checksum did not match for ' + addr) + //throw new Error(); + }*/ - return [ver, addr.slice(1,-4)]; + return decoded.slice(1,-4); }; /* For POS coins - used to format wallet address for use in generation transaction's output */ -exports.script_to_pubkey = function(key){ +exports.pubkeyToScript = function(key){ if (key.length === 66) key = new Buffer(key, 'hex'); - if (key.length !== 33) throw 'Invalid address'; + if (key.length !== 33){ + console.error('Invalid pubkey: ' + key); + throw new Error(); + } var pubkey = new Buffer(35); pubkey[0] = 0x21; pubkey[34] = 0xac; @@ -275,12 +288,8 @@ exports.script_to_pubkey = function(key){ /* For POW coins - used to format wallet address for use in generation transaction's output */ -exports.script_to_address = function(addr){ - var d = exports.address_to_pubkeyhash(addr) - if (!d) - throw "invalid address"; - var ver = d[0]; - var pubkeyhash = d[1]; - return Buffer.concat([new Buffer([0x76, 0xa9, 0x14]), pubkeyhash, new Buffer([0x88, 0xac])]); +exports.addressToScript = function(addr){ + var pubkey = exports.addressToPubkey(addr); + return Buffer.concat([new Buffer([0x76, 0xa9, 0x14]), pubkey, new Buffer([0x88, 0xac])]); }; \ No newline at end of file diff --git a/package.json b/package.json index c13c7df..fa4754b 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "scrypt-jane-hash": "https://github.com/zone117x/node-scrypt-jane-hash/archive/master.tar.gz", "quark-hash": "https://github.com/zone117x/node-quark-hash/archive/master.tar.gz", "x11-hash": "https://github.com/zone117x/node-x11-hash/archive/master.tar.gz", + "keccak-hash": "https://github.com/zone117x/node-keccak-hash/archive/master.tar.gz", "bignum": "*", "base58-native": "*", "async": "*"