refactored block polling and pool setup

This commit is contained in:
Matthew Little 2014-01-13 16:23:41 -05:00
parent 677bc176a4
commit f8efd80488
4 changed files with 136 additions and 132 deletions

View File

@ -3,15 +3,15 @@
"symbol": "doge", "symbol": "doge",
"algorithm": "scrypt", "algorithm": "scrypt",
"reward": "POW", "reward": "POW",
"address": "mkLyYQ5U8aFQ8aDAF1GS9zXStTzi3m29Tg", "address": "DDt79i6P3Wro3SD3HSnkRLpMgUGUGdiNhS",
"stratumPort": 3334, "stratumPort": 3334,
"difficulty": 8, "difficulty": 8,
"templateRefreshInterval": 60, "blockRefreshInterval": 60,
"merkleRefreshInterval": 60, "merkleRefreshInterval": 60,
"daemon": { "daemon": {
"host": "localhost", "host": "localhost",
"port": 19334, "port": 8332,
"user": "testnet", "user": "test",
"password": "AHhQYqfSZqzQvkSXAtHtDAbKaZaoPih3wfmJfgCtjRx9" "password": "test"
} }
} }

23
init.js
View File

@ -39,23 +39,6 @@ fs.readdir(confFolder, function(err, files){
coin.shareManager = new ShareManager(coin.pool); coin.shareManager = new ShareManager(coin.pool);
coins.push(coin); 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){ 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) { var blockNotifyServer = net.createServer(function(c) {
console.log('server connected'); console.log('server connected');
var data = ''; var data = '';
@ -90,5 +73,7 @@ if (config.blockNotifyListener.enabled){
console.log('server disconnected'); 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)
});
} }

View File

@ -59,7 +59,7 @@ var JobManager = module.exports = function JobManager(options){
* @returns true if it's a new block, false otherwise. * @returns true if it's a new block, false otherwise.
* used by onNewTemplate * used by onNewTemplate
**/ **/
function CheckNewIfNewBlock(blockTemplate){ function CheckNewIfNewBlock(prevBlockHash){
var newBlock = true; var newBlock = true;
for(var job in jobs){ for(var job in jobs){
if (jobs[job].rpcData.previousblockhash === blockTemplate.rpcData.previousblockhash) { 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.extraNonce2Size = this.extraNoncePlaceholder.length - this.extraNonceCounter.size();
this.currentJob; this.currentJob;
this.newTemplate = function(rpcData, publicKey){
var tmpBlockTemplate = new blockTemplate(rpcData, publicKey, _this.extraNoncePlaceholder); this.processTemplate = function(rpcData, publicKey){
if ( CheckNewIfNewBlock(tmpBlockTemplate) ) { if (CheckNewIfNewBlock(rpcData.previousblockhash)){
var tmpBlockTemplate = new blockTemplate(rpcData, publicKey, _this.extraNoncePlaceholder);
tmpBlockTemplate.setJobId(jobCounter.next()); tmpBlockTemplate.setJobId(jobCounter.next());
jobs[tmpBlockTemplate.jobId] = tmpBlockTemplate; jobs[tmpBlockTemplate.jobId] = tmpBlockTemplate;
this.currentJob = jobs[tmpBlockTemplate.jobId]; this.currentJob = jobs[tmpBlockTemplate.jobId];
_this.emit('newBlock', tmpBlockTemplate); _this.emit('newBlock', tmpBlockTemplate);
} }
}; };
this.processShare = function(jobId, difficulty, extraNonce1, extraNonce2, nTime, nonce){ this.processShare = function(jobId, difficulty, extraNonce1, extraNonce2, nTime, nonce){
var submitTime = Date.now() / 1000 | 0; var submitTime = Date.now() / 1000 | 0;

216
pool.js
View File

@ -14,107 +14,109 @@ var pool = module.exports = function pool(coin){
var _this = this; var _this = this;
var publicKeyBuffer; var publicKeyBuffer;
this.shareManager = undefined; // just for us to know that the variable should be this one. (function Init(){
this.jobManager = new jobManager({ SetupJobManager();
algorithm: coin.options.algorithm, SetupDaemonInterface();
address: coin.options.address SetupShareManager();
}); })();
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));
}
);
}
});
console.log('Connecting to daemon for ' + coin.options.name); function SetupJobManager(){
this.daemon = new daemon.interface(coin.options.daemon); this.jobManager = new jobManager({
this.daemon.on('online', function(){ algorithm: coin.options.algorithm,
async.parallel({ address: coin.options.address
rpcTemplate: GetBlockTemplate, });
addressInfo: function(callback){ this.jobManager.on('newBlock', function(blockTemplate){
_this.daemon.cmd('validateaddress', if ( typeof(_this.stratumServer ) === 'undefined') {
[coin.options.address], 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){ function(error, result){
if (error){ console.log(JSON.stringify(error));
console.log('validateaddress rpc error for ' + coin.options.name); console.log(JSON.stringify(result));
callback(error); console.log("submitblock", JSON.stringify(error), JSON.stringify(result));
}
else if (!result.isvalid){
console.log('address is not valid for ' + coin.options.name);
callback(error);
}
else
callback(error, result);
} }
); );
}, } else {
submitMethod: function(callback){ _this.daemon.cmd('getblocktemplate',
_this.daemon.cmd('submitblock', [{'mode': 'submit', 'data': blockHex}],
[],
function(error, result){ function(error, result){
if (error && error.message === 'Method not found') console.log(JSON.stringify(error));
callback(null, false); console.log(JSON.stringify(result));
else console.log("submitblockgetBlockTEmplate", JSON.stringify(error), JSON.stringify(result));
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);
_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(){ function StartStratumServer(){
console.log('Stratum server starting on port ' + coin.options.stratumPort + ' for ' + coin.options.name); console.log('Stratum server starting on port ' + coin.options.stratumPort + ' for ' + coin.options.name);
_this.stratumServer = new stratum.Server({ _this.stratumServer = new stratum.Server({
port: coin.options.stratumPort port: coin.options.stratumPort
}); });
_this.stratumServer.on('started', function(){ _this.stratumServer.on('started', function(){
<<<<<<< HEAD
=======
_this.emit('started');
>>>>>>> a301c49943980d0209fb42114999099eeeb44ded
console.log('Stratum server started on port ' + coin.options.stratumPort + ' for ' + coin.options.name); console.log('Stratum server started on port ' + coin.options.stratumPort + ' for ' + coin.options.name);
}).on('client', function(client){ }).on('client', function(client){
client.on('subscription', function(params, resultCallback){ client.on('subscription', function(params, resultCallback){
@ -165,6 +167,36 @@ var pool = module.exports = function pool(coin){
}); });
} }
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){ function GetBlockTemplate(callback){
_this.daemon.cmd('getblocktemplate', _this.daemon.cmd('getblocktemplate',
[{"capabilities": [ "coinbasetxn", "workid", "coinbase/append" ]}], [{"capabilities": [ "coinbasetxn", "workid", "coinbase/append" ]}],
@ -172,24 +204,13 @@ var pool = module.exports = function pool(coin){
if (error) { if (error) {
callback(error); callback(error);
} else { } else {
_this.jobManager.processTemplate(result, publicKeyBuffer);
callback(null, result); 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 * 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){ this.processBlockNotify = function(blockHash){
if (blockHash !== _this.jobManager.currentJob.rpcData.previousblockhash){ if (blockHash !== _this.jobManager.currentJob.rpcData.previousblockhash){
GetBlockTemplate(function(error, result){ GetBlockTemplate(function(error, result){
if (error){ if (error)
console.error('[processBlockNotify] Error getting block template for ' + coin.options.name); console.error('Block notify error getting block template for ' + coin.options.name);
return;
}
_this.jobManager.newTemplate(result, publicKeyBuffer);
}) })
} }
} }