Removed jobs object from jobManager since we only need one job! There's no need to keep the olders in memory.

Refactored, a bit, the emit log event introducing a key for every log message Current keys are:
 - 'client': for all the client related events
 - 'submitblock': dedicated only to events about the block submission!
 - 'system': all log events about the stratum pool
This commit is contained in:
Andrea Baccega 2014-01-14 14:32:30 +01:00
parent a67082131d
commit 61db6d7ea4
5 changed files with 61 additions and 62 deletions

View File

@ -1,7 +1,6 @@
#### TODO #### TODO
* vekexasia: handle socket error from client so that we could clean up stratumServers Client
* vekexasia: fix check of difficulty of the shares. Not sure why a lot of shares are marked as "low-submit-share"
#### TOFIX #### TOFIX
* vekexasia: jobManager.js has implement the expected block hash after submitting it to the daemon. This will let us check if the block was accepted by the daemon. * vekexasia: jobManager.js has implement the expected block hash after submitting it to the daemon. This will let us check if the block was accepted by the daemon.

View File

@ -61,11 +61,6 @@ function DaemonInterface(options){
params: params params: params
}); });
if (method == 'submitblock') {
console.log("SUBMITBLOCK daemon");
console.log(requestJson);
}
var options = { var options = {
hostname: (typeof(_this.options.host) === 'undefined'?'localhost':_this.options.host), hostname: (typeof(_this.options.host) === 'undefined'?'localhost':_this.options.host),
port : _this.options.port, port : _this.options.port,

View File

@ -55,8 +55,6 @@ var JobManager = module.exports = function JobManager(options){
var _this = this; var _this = this;
var jobCounter = new JobCounter(); var jobCounter = new JobCounter();
var jobs = {};
/** /**
* It only checks if the blockTemplate is already in our jobs list. * It only checks if the blockTemplate is already in our jobs list.
@ -64,14 +62,13 @@ var JobManager = module.exports = function JobManager(options){
* used by onNewTemplate * used by onNewTemplate
**/ **/
function CheckNewIfNewBlock(prevBlockHash){ function CheckNewIfNewBlock(prevBlockHash){
if (typeof(_this.currentJob) === 'undefined') {
var newBlock = true; return true;
for(var job in jobs){ } else if (_this.currentJob.rpcData.previousblockhash !== prevBlockHash) {
if (jobs[job].rpcData.previousblockhash === prevBlockHash) { return true;
newBlock = false; } else {
} return false;
} }
return newBlock;
} }
var diffDividend = (function(){ var diffDividend = (function(){
@ -128,9 +125,9 @@ var JobManager = module.exports = function JobManager(options){
//public members //public members
this.extraNonceCounter = new ExtraNonceCounter(); this.extraNonceCounter = new ExtraNonceCounter();
this.extraNoncePlaceholder = new Buffer('f000000ff111111f', 'hex'); this.extraNoncePlaceholder = new Buffer('f000000ff111111f', 'hex');
this.extraNonce2Size = this.extraNoncePlaceholder.length - this.extraNonceCounter.size(); this.extraNonce2Size = this.extraNoncePlaceholder.length - this.extraNonceCounter.size();
this.currentJob; this.currentJob;
@ -138,9 +135,11 @@ var JobManager = module.exports = function JobManager(options){
if (CheckNewIfNewBlock(rpcData.previousblockhash)){ if (CheckNewIfNewBlock(rpcData.previousblockhash)){
var tmpBlockTemplate = new blockTemplate(rpcData, publicKey, _this.extraNoncePlaceholder); var tmpBlockTemplate = new blockTemplate(rpcData, publicKey, _this.extraNoncePlaceholder);
tmpBlockTemplate.setJobId(jobCounter.next()); tmpBlockTemplate.setJobId(jobCounter.next());
jobs[tmpBlockTemplate.jobId] = tmpBlockTemplate;
this.currentJob = jobs[tmpBlockTemplate.jobId]; this.currentJob = tmpBlockTemplate;
_this.emit('newBlock', tmpBlockTemplate); _this.emit('newBlock', tmpBlockTemplate);
} }
}; };
@ -151,8 +150,8 @@ var JobManager = module.exports = function JobManager(options){
if (extraNonce2.length / 2 !== _this.extraNonce2Size) if (extraNonce2.length / 2 !== _this.extraNonce2Size)
return {error: [20, 'incorrect size of extranonce2', null]}; return {error: [20, 'incorrect size of extranonce2', null]};
var job = jobs[jobId]; var job = this.currentJob;
if (!job) { if ( job.jobId != jobId ) {
return {error: [21, 'job not found', null]}; return {error: [21, 'job not found', null]};
} }
@ -191,14 +190,13 @@ var JobManager = module.exports = function JobManager(options){
if (job.target.ge(headerBigNum)){ if (job.target.ge(headerBigNum)){
var blockBuf = job.serializeBlock(headerBuffer, coinbaseBuffer); var blockBuf = job.serializeBlock(headerBuffer, coinbaseBuffer);
console.log("EXPECTED BLOCK HASH: "+blockHashHex(headerBuffer)); // NOT WORKING :(? // console.log("EXPECTED BLOCK HASH: "+blockHashHex(headerBuffer)); // NOT WORKING :(?
_this.emit('blockFound', blockBuf.toString('hex')); _this.emit('blockFound', blockBuf.toString('hex'), blockHashHex(headerBuffer));
} } else {
var targetUser = bignum(diffDividend / difficulty);
// TODO: this seems to not be working properly if (headerBigNum.gt(targetUser)){
var targetUser = bignum(diffDividend / difficulty); return {error: [23, 'low difficulty share', null]};
if (headerBigNum.gt(targetUser)){ }
return {error: [23, 'low difficulty share', null]};
} }
return {result: true, headerHEX: headerBigNum.toString(16)}; return {result: true, headerHEX: headerBigNum.toString(16)};

View File

@ -19,8 +19,9 @@ var pool = module.exports = function pool(options, authorizeFn){
var publicKeyBuffer; var publicKeyBuffer;
var emitLog = function(text){ _this.emit('log', text) }; var emitLog = function(key, text) { _this.emit('log', 'debug' , key, text); };
var emitWarningLog = function(key, text) { _this.emit('log', 'warning', key, text); };
var emitErrorLog = function(key, text) { _this.emit('log', 'error' , key, text); };
(function Init(){ (function Init(){
SetupJobManager(); SetupJobManager();
@ -36,27 +37,24 @@ var pool = module.exports = function pool(options, authorizeFn){
}); });
_this.jobManager.on('newBlock', function(blockTemplate){ _this.jobManager.on('newBlock', function(blockTemplate){
if ( typeof(_this.stratumServer ) === 'undefined') { if ( typeof(_this.stratumServer ) === 'undefined') {
console.warn("Stratum server still not started! cannot broadcast block!"); emitWarningLog("Stratum server still not started! cannot broadcast block!");
} else { } else {
emitLog('system', 'Detected new block');
_this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams()); _this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams());
} }
}).on('blockFound', function(blockHex, headerHex, third){ }).on('blockFound', function(blockHex, headerHex){
if (options.hasSubmitMethod) { if (options.hasSubmitMethod) {
_this.daemon.cmd('submitblock', _this.daemon.cmd('submitblock',
[blockHex], [blockHex],
function(error, result){ function(error, result){
console.log(JSON.stringify(error)); emitLog('submitblock', 'Submitted Block using submitblock :'+headerHex);
console.log(JSON.stringify(result));
console.log("submitblock", JSON.stringify(error), JSON.stringify(result));
} }
); );
} else { } else {
_this.daemon.cmd('getblocktemplate', _this.daemon.cmd('getblocktemplate',
[{'mode': 'submit', 'data': blockHex}], [{'mode': 'submit', 'data': blockHex}],
function(error, result){ function(error, result){
console.log(JSON.stringify(error)); emitLog('submitblock', 'Submitted Block using getblocktemplate: '+headerHex);
console.log(JSON.stringify(result));
console.log("submitblockgetBlockTEmplate", JSON.stringify(error), JSON.stringify(result));
} }
); );
} }
@ -65,7 +63,7 @@ var pool = module.exports = function pool(options, authorizeFn){
function SetupDaemonInterface(){ function SetupDaemonInterface(){
emitLog('Connecting to daemon'); emitLog('system','Connecting to daemon');
_this.daemon = new daemon.interface(options.daemon); _this.daemon = new daemon.interface(options.daemon);
_this.daemon.on('online', function(){ _this.daemon.on('online', function(){
async.parallel({ async.parallel({
@ -74,10 +72,10 @@ var pool = module.exports = function pool(options, authorizeFn){
[options.address], [options.address],
function(error, result){ function(error, result){
if (error){ if (error){
emitLog('validateaddress rpc error'); emitLog('system','validateaddress rpc error');
callback(error); callback(error);
} else if (!result.isvalid) { } else if (!result.isvalid) {
emitLog('address is not valid'); emitLog('system','address is not valid');
callback("address-not-valid"); callback("address-not-valid");
} else { } else {
callback(error, result); callback(error, result);
@ -99,7 +97,7 @@ var pool = module.exports = function pool(options, authorizeFn){
}, function(err, results){ }, function(err, results){
if (err) return; if (err) return;
emitLog('Connected to daemon'); emitLog('system','Connected to daemon');
options.hasSubmitMethod = results.submitMethod; options.hasSubmitMethod = results.submitMethod;
publicKeyBuffer = options.reward === 'POW' ? publicKeyBuffer = options.reward === 'POW' ?
@ -112,19 +110,19 @@ var pool = module.exports = function pool(options, authorizeFn){
}); });
}).on('startFailed', function(){ }).on('startFailed', function(){
emitLog('Failed to start daemon'); emitErrorLog('system','Failed to start daemon');
}); });
} }
function StartStratumServer(){ function StartStratumServer(){
emitLog('Stratum server starting on port ' + options.stratumPort); emitLog('system', 'Stratum server starting on port ' + options.stratumPort);
_this.stratumServer = new stratum.Server({ _this.stratumServer = new stratum.Server({
port: options.stratumPort, port: options.stratumPort,
authorizeFn: authorizeFn authorizeFn: authorizeFn
}); });
_this.stratumServer.on('started', function(){ _this.stratumServer.on('started', function(){
emitLog('Stratum server started on port ' + options.stratumPort); emitLog('system','Stratum server started on port ' + options.stratumPort);
}).on('client.connected', function(client){ }).on('client.connected', function(client){
client.on('subscription', function(params, resultCallback){ client.on('subscription', function(params, resultCallback){
@ -136,7 +134,11 @@ var pool = module.exports = function pool(options, authorizeFn){
); );
this.sendAndSetDifficultyIfNew(options.difficulty); this.sendAndSetDifficultyIfNew(options.difficulty);
this.sendMiningJob(_this.jobManager.currentJob.getJobParams()); if (typeof(_this.jobManager.currentJob) !== 'undefined') {
this.sendMiningJob(_this.jobManager.currentJob.getJobParams());
} else {
emitWarningLog('client', "A miner subscribed but no job to dispatch!");
}
}).on('submit', function(params, resultCallback){ }).on('submit', function(params, resultCallback){
@ -166,7 +168,14 @@ var pool = module.exports = function pool(options, authorizeFn){
nonce : params.nonce nonce : params.nonce
}); });
} }
}).on('malformedMessage', function (message) {
emitWarningLog('client', client.workerName+" has sent us a malformed message: "+message);
}).on('socketError', function() {
emitWarningLog('client', client.workerName+" has somehow had a socket error");
}).on('socketDisconnect', function() {
emitLog('client', "Client '"+client.workerName+"' disconnected!");
}).on('unknownStratumMethod', function(fullMessage) {
emitLog('client', "Client '"+client.workerName+"' has sent us an unknown stratum method: "+fullMessage.method);
}); });
}); });
} }
@ -174,7 +183,7 @@ var pool = module.exports = function pool(options, authorizeFn){
function SetupBlockPolling(){ function SetupBlockPolling(){
if (options.blockRefreshInterval === 0){ if (options.blockRefreshInterval === 0){
emitLog('Block template polling has been disabled'); emitLog('system', 'Block template polling has been disabled');
return; return;
} }
@ -184,13 +193,14 @@ var pool = module.exports = function pool(options, authorizeFn){
setInterval(function () { setInterval(function () {
GetBlockTemplate(function(error, result) { GetBlockTemplate(function(error, result) {
if (error) if (error) {
console.error("Block polling error getting block template for " + options.name); emitErrorLog('system', "Block polling error getting block template for " + options.name)
}
}); });
}, pollingInterval); }, pollingInterval);
emitLog('Block polling setup for every ' + pollingInterval + ' milliseconds'); emitLog('system', 'Block polling setup for every ' + pollingInterval + ' milliseconds');
} }
@ -217,7 +227,7 @@ var pool = module.exports = function pool(options, authorizeFn){
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('Block notify error getting block template for ' + options.name); emitErrorLog('system', 'Block notify error getting block template for ' + options.name);
}) })
} }
} }

View File

@ -54,7 +54,7 @@ var StratumClient = function(options){
}); });
break; break;
default: default:
console.dir('unknown stratum client message: ' + JSON.stringify(message)); _this.emit('unknownStratumMethod', message);
break; break;
} }
} }
@ -155,19 +155,18 @@ var StratumClient = function(options){
var dataBuffer = ''; var dataBuffer = '';
socket.setEncoding('utf8'); socket.setEncoding('utf8');
socket.on('data', function(d){ socket.on('data', function(d){
console.log('request: ' + d);
dataBuffer += d; dataBuffer += d;
if (dataBuffer.slice(-1) === '\n'){ if (dataBuffer.slice(-1) === '\n'){
var messages = dataBuffer.split('\n'); var messages = dataBuffer.split('\n');
messages.forEach(function(message){ messages.forEach(function(message){
if (message.trim() === '') return; if (message.trim() === '') return;
var messageJson; var messageJson;
try{ try {
messageJson = JSON.parse(message); messageJson = JSON.parse(message);
} catch(e) {
_this.emit('malformedMessage', message);
} }
catch(e){
console.log('could not parse stratum client socket message: ' + message);
}
if (messageJson) { if (messageJson) {
handleMessage(messageJson); handleMessage(messageJson);
} }
@ -177,11 +176,9 @@ var StratumClient = function(options){
}); });
socket.on('end', function() { socket.on('end', function() {
_this.emit('socketDisconnect') _this.emit('socketDisconnect')
console.log('stratum client disconnected');
}); });
socket.on('error', function(){ socket.on('error', function(){
_this.emit('socketError'); _this.emit('socketError');
console.log('stratum client socket error');
}); });
} }