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:
parent
a67082131d
commit
61db6d7ea4
@ -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.
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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)};
|
||||||
|
|||||||
58
lib/pool.js
58
lib/pool.js
@ -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);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user