From f8efd80488e831c1b2c4014a9e0b0e5de767bbb5 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Mon, 13 Jan 2014 16:23:41 -0500 Subject: [PATCH] refactored block polling and pool setup --- coins/dogecoin.json | 12 +-- init.js | 23 +---- jobManager.js | 11 ++- pool.js | 222 ++++++++++++++++++++++++-------------------- 4 files changed, 136 insertions(+), 132 deletions(-) diff --git a/coins/dogecoin.json b/coins/dogecoin.json index 395991e..d108652 100644 --- a/coins/dogecoin.json +++ b/coins/dogecoin.json @@ -3,15 +3,15 @@ "symbol": "doge", "algorithm": "scrypt", "reward": "POW", - "address": "mkLyYQ5U8aFQ8aDAF1GS9zXStTzi3m29Tg", + "address": "DDt79i6P3Wro3SD3HSnkRLpMgUGUGdiNhS", "stratumPort": 3334, "difficulty": 8, - "templateRefreshInterval": 60, + "blockRefreshInterval": 60, "merkleRefreshInterval": 60, "daemon": { "host": "localhost", - "port": 19334, - "user": "testnet", - "password": "AHhQYqfSZqzQvkSXAtHtDAbKaZaoPih3wfmJfgCtjRx9" + "port": 8332, + "user": "test", + "password": "test" } -} +} \ No newline at end of file diff --git a/init.js b/init.js index 7a7f9b7..74763c0 100644 --- a/init.js +++ b/init.js @@ -39,23 +39,6 @@ fs.readdir(confFolder, function(err, files){ coin.shareManager = new ShareManager(coin.pool); coins.push(coin); - - // If the block notify listener is not enabled lets set up the polling. - if ( ! config.blockNotifyListener.enabled ) { - // as soon as the pool is started we start polling - var pollingTime = typeof(config.blockPollingTime) === 'undefined' ? 5000 : parseInt(config.blockPollingTime, 10); - coin.pool.on('started', function() { - var curPool = this; - setInterval( - function() { - curPool.processBlockPolling(); - }, - pollingTime - ); - }); - - - } }); }); @@ -63,7 +46,7 @@ fs.readdir(confFolder, function(err, files){ if (config.blockNotifyListener.enabled){ - console.log("ENABLED"); + console.log("Block listener is enabled, starting server on port " + config.blockNotifyListener.port); var blockNotifyServer = net.createServer(function(c) { console.log('server connected'); var data = ''; @@ -90,5 +73,7 @@ if (config.blockNotifyListener.enabled){ console.log('server disconnected'); }); }); - blockNotifyServer.listen(config.blockNotifyListener.port, function() {}); + blockNotifyServer.listen(config.blockNotifyListener.port, function() { + console.log('Block notify listener server started on port ' + config.blockNotifyListener.port) + }); } \ No newline at end of file diff --git a/jobManager.js b/jobManager.js index 697c2c5..098b9ea 100644 --- a/jobManager.js +++ b/jobManager.js @@ -59,7 +59,7 @@ var JobManager = module.exports = function JobManager(options){ * @returns true if it's a new block, false otherwise. * used by onNewTemplate **/ - function CheckNewIfNewBlock(blockTemplate){ + function CheckNewIfNewBlock(prevBlockHash){ var newBlock = true; for(var job in jobs){ if (jobs[job].rpcData.previousblockhash === blockTemplate.rpcData.previousblockhash) { @@ -109,16 +109,17 @@ var JobManager = module.exports = function JobManager(options){ this.extraNonce2Size = this.extraNoncePlaceholder.length - this.extraNonceCounter.size(); this.currentJob; - this.newTemplate = function(rpcData, publicKey){ - var tmpBlockTemplate = new blockTemplate(rpcData, publicKey, _this.extraNoncePlaceholder); - if ( CheckNewIfNewBlock(tmpBlockTemplate) ) { + + this.processTemplate = function(rpcData, publicKey){ + if (CheckNewIfNewBlock(rpcData.previousblockhash)){ + var tmpBlockTemplate = new blockTemplate(rpcData, publicKey, _this.extraNoncePlaceholder); tmpBlockTemplate.setJobId(jobCounter.next()); jobs[tmpBlockTemplate.jobId] = tmpBlockTemplate; this.currentJob = jobs[tmpBlockTemplate.jobId]; _this.emit('newBlock', tmpBlockTemplate); } - }; + this.processShare = function(jobId, difficulty, extraNonce1, extraNonce2, nTime, nonce){ var submitTime = Date.now() / 1000 | 0; diff --git a/pool.js b/pool.js index 3c5803a..4e48541 100644 --- a/pool.js +++ b/pool.js @@ -14,107 +14,109 @@ var pool = module.exports = function pool(coin){ var _this = this; var publicKeyBuffer; - this.shareManager = undefined; // just for us to know that the variable should be this one. - this.jobManager = new jobManager({ - algorithm: coin.options.algorithm, - address: coin.options.address - }); - this.jobManager.on('newBlock', function(blockTemplate){ - if ( typeof(_this.stratumServer ) === 'undefined') { - console.warn("Stratum server still not started! cannot broadcast block!"); - } else { - _this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams()); - } - - }).on('blockFound', function(blockHex, headerHex, third){ - console.log("BLOCK "+blockHex); - console.log("HEADER "+headerHex); - console.log("THIRD "+third); - if (coin.options.hasSubmitMethod) { - _this.daemon.cmd('submitblock', - [blockHex], - function(error, result){ - console.log(JSON.stringify(error)); - console.log(JSON.stringify(result)); - console.log("submitblock", JSON.stringify(error), JSON.stringify(result)); - } - ); - } else { - _this.daemon.cmd('getblocktemplate', - [{'mode': 'submit', 'data': blockHex}], - function(error, result){ - console.log(JSON.stringify(error)); - console.log(JSON.stringify(result)); - console.log("submitblockgetBlockTEmplate", JSON.stringify(error), JSON.stringify(result)); - } - ); - } - }); + (function Init(){ + SetupJobManager(); + SetupDaemonInterface(); + SetupShareManager(); + })(); - console.log('Connecting to daemon for ' + coin.options.name); - this.daemon = new daemon.interface(coin.options.daemon); - this.daemon.on('online', function(){ - async.parallel({ - rpcTemplate: GetBlockTemplate, - addressInfo: function(callback){ - _this.daemon.cmd('validateaddress', - [coin.options.address], + + function SetupJobManager(){ + this.jobManager = new jobManager({ + algorithm: coin.options.algorithm, + address: coin.options.address + }); + this.jobManager.on('newBlock', function(blockTemplate){ + if ( typeof(_this.stratumServer ) === 'undefined') { + console.warn("Stratum server still not started! cannot broadcast block!"); + } else { + _this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams()); + } + + }).on('blockFound', function(blockHex, headerHex, third){ + if (coin.options.hasSubmitMethod) { + _this.daemon.cmd('submitblock', + [blockHex], function(error, result){ - if (error){ - console.log('validateaddress rpc error for ' + coin.options.name); - callback(error); - } - else if (!result.isvalid){ - console.log('address is not valid for ' + coin.options.name); - callback(error); - } - else - callback(error, result); + console.log(JSON.stringify(error)); + console.log(JSON.stringify(result)); + console.log("submitblock", JSON.stringify(error), JSON.stringify(result)); } ); - }, - submitMethod: function(callback){ - _this.daemon.cmd('submitblock', - [], + } else { + _this.daemon.cmd('getblocktemplate', + [{'mode': 'submit', 'data': blockHex}], function(error, result){ - if (error && error.message === 'Method not found') - callback(null, false); - else - callback(null, true); + console.log(JSON.stringify(error)); + console.log(JSON.stringify(result)); + console.log("submitblockgetBlockTEmplate", JSON.stringify(error), JSON.stringify(result)); } ); } - }, function(err, results){ - if (err) return; - console.log('Connected to daemon for ' + coin.options.name); - coin.options.hasSubmitMethod = results.submitMethod; - - publicKeyBuffer = coin.options.reward === 'POW' ? - util.script_to_address(results.addressInfo.address) : - util.script_to_pubkey(results.addressInfo.pubkey); - - _this.jobManager.newTemplate(results.rpcTemplate, publicKeyBuffer); - - StartStratumServer(); - }); + } - }).on('startFailed', function(){ - console.log('Failed to start daemon for ' + coin.name); - }); + + function SetupDaemonInterface(){ + console.log('Connecting to daemon for ' + coin.options.name); + this.daemon = new daemon.interface(coin.options.daemon); + this.daemon.on('online', function(){ + async.parallel({ + addressInfo: function(callback){ + _this.daemon.cmd('validateaddress', + [coin.options.address], + function(error, result){ + if (error){ + console.log('validateaddress rpc error for ' + coin.options.name); + callback(error); + } + else if (!result.isvalid){ + console.log('address is not valid for ' + coin.options.name); + callback(error); + } + else + callback(error, result); + } + ); + }, + submitMethod: function(callback){ + _this.daemon.cmd('submitblock', + [], + function(error, result){ + if (error && error.message === 'Method not found') + callback(null, false); + else + callback(null, true); + } + ); + } + }, function(err, results){ + if (err) return; + console.log('Connected to daemon for ' + coin.options.name); + coin.options.hasSubmitMethod = results.submitMethod; + + publicKeyBuffer = coin.options.reward === 'POW' ? + util.script_to_address(results.addressInfo.address) : + util.script_to_pubkey(results.addressInfo.pubkey); + + StartStratumServer(); + GetBlockTemplate(); + SetupBlockPolling(); + + }); + + }).on('startFailed', function(){ + console.log('Failed to start daemon for ' + coin.name); + }); + } function StartStratumServer(){ - console.log('Stratum server starting on port ' + coin.options.stratumPort + ' for ' + coin.options.name); _this.stratumServer = new stratum.Server({ port: coin.options.stratumPort }); _this.stratumServer.on('started', function(){ -<<<<<<< HEAD -======= - _this.emit('started'); ->>>>>>> a301c49943980d0209fb42114999099eeeb44ded console.log('Stratum server started on port ' + coin.options.stratumPort + ' for ' + coin.options.name); }).on('client', function(client){ client.on('subscription', function(params, resultCallback){ @@ -157,14 +159,44 @@ var pool = module.exports = function pool(coin){ extraNonce1 : client.extraNonce1, extraNonce2 : params.extraNonce2, nTime : params.nTime, - nonce : params.nonce + nonce : params.nonce }); } - + }); }); } + + function SetupShareManager(){ + this.shareManager = undefined; // just for us to know that the variable should be this one. + } + + + function SetupBlockPolling(){ + + if (coin.options.blockRefreshInterval === 0){ + console.log('Block template polling has been disabled for ' + coin.options.name); + return; + } + + var pollingInterval = coin.options.blockRefreshInterval * 1000; + var pollTimeout; + var setPoll; + + setPoll = function(){ + pollTimeout = setTimeout(function(){ + GetBlockTemplate(function(error, result) { + if (error) + console.error("Block polling error getting block template for " + coin.options.name); + setPoll(); + }); + }, pollingInterval); + }; + console.log('Block polling setup for every ' + pollingInterval + ' milliseconds for ' + coin.options.name); + } + + function GetBlockTemplate(callback){ _this.daemon.cmd('getblocktemplate', [{"capabilities": [ "coinbasetxn", "workid", "coinbase/append" ]}], @@ -172,24 +204,13 @@ var pool = module.exports = function pool(coin){ if (error) { callback(error); } else { + _this.jobManager.processTemplate(result, publicKeyBuffer); callback(null, result); } } ); } - /** - * This method needs to be called to perform a block polling to the daemon so that we can notify our miners - * about new blocks - **/ - this.processBlockPolling = function() { - GetBlockTemplate(function(error, result) { - if (error) { - console.error("[processBlockPolling] Error getting block template for " + coin.options.name); - } - _this.jobManager.newTemplate(result, publicKeyBuffer); - }); - } /** * This method is being called from the blockNotify so that when a new block is discovered by the daemon @@ -198,11 +219,8 @@ var pool = module.exports = function pool(coin){ this.processBlockNotify = function(blockHash){ if (blockHash !== _this.jobManager.currentJob.rpcData.previousblockhash){ GetBlockTemplate(function(error, result){ - if (error){ - console.error('[processBlockNotify] Error getting block template for ' + coin.options.name); - return; - } - _this.jobManager.newTemplate(result, publicKeyBuffer); + if (error) + console.error('Block notify error getting block template for ' + coin.options.name); }) } }