Add check for if submitblock was successful and refined the data emitted by onShare
This commit is contained in:
parent
cbcaa1cf98
commit
cb5d7c7bdc
@ -78,8 +78,15 @@ function DaemonInterface(options){
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', function(){
|
||||
var dataJson = JSON.parse(data);
|
||||
callback(dataJson.error, dataJson.result);
|
||||
var dataJson;
|
||||
try{
|
||||
dataJson = JSON.parse(data);
|
||||
}
|
||||
catch(e){
|
||||
_this.emit('error', 'daemon interface could not parse rpc data from method: ' + method + ' ' + options.hostname);
|
||||
}
|
||||
if (typeof(dataJson) !== 'undefined')
|
||||
callback(dataJson.error, dataJson.result);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -126,33 +126,45 @@ var JobManager = module.exports = function JobManager(options){
|
||||
}
|
||||
};
|
||||
|
||||
this.processShare = function(jobId, difficulty, extraNonce1, extraNonce2, nTime, nonce){
|
||||
this.processShare = function(jobId, difficulty, extraNonce1, extraNonce2, nTime, nonce, ipAddress, workerName){
|
||||
|
||||
|
||||
var shareError = function(error){
|
||||
_this.emit('share', {
|
||||
job: jobId,
|
||||
ip: ipAddress,
|
||||
worker: workerName,
|
||||
difficulty: difficulty,
|
||||
error: error.error[1]
|
||||
});
|
||||
return error;
|
||||
};
|
||||
|
||||
var submitTime = Date.now() / 1000 | 0;
|
||||
|
||||
if (extraNonce2.length / 2 !== _this.extraNonce2Size)
|
||||
return {error: [20, 'incorrect size of extranonce2', null]};
|
||||
return shareError({error: [20, 'incorrect size of extranonce2']});
|
||||
|
||||
var job = this.currentJob;
|
||||
if ( job.jobId != jobId ) {
|
||||
return {error: [21, 'job not found', null]};
|
||||
return shareError({error: [21, 'job not found']});
|
||||
}
|
||||
|
||||
if (nTime.length !== 8) {
|
||||
return {error: [20, 'incorrect size of ntime']};
|
||||
return shareError({error: [20, 'incorrect size of ntime']});
|
||||
}
|
||||
|
||||
var nTimeInt = parseInt(nTime, 16);
|
||||
if (nTimeInt < job.rpcData.curtime || nTime > submitTime + 7200) {
|
||||
return {error: [20, 'ntime out of range', null]};
|
||||
return shareError({error: [20, 'ntime out of range']});
|
||||
}
|
||||
|
||||
if (nonce.length !== 8) {
|
||||
return {error: [20, 'incorrect size of nonce']};
|
||||
return shareError({error: [20, 'incorrect size of nonce']});
|
||||
}
|
||||
|
||||
if (!job.registerSubmit(extraNonce1, extraNonce2, nTime, nonce)) {
|
||||
return {error: [22, 'duplicate share', null]};
|
||||
return shareError({error: [22, 'duplicate share']});
|
||||
}
|
||||
|
||||
|
||||
@ -169,19 +181,27 @@ var JobManager = module.exports = function JobManager(options){
|
||||
var headerBigNum = bignum.fromBuffer(headerHash, {endian: 'little', size: 32});
|
||||
|
||||
var blockHash;
|
||||
var blockHex;
|
||||
|
||||
if (job.target.ge(headerBigNum)){
|
||||
var blockHex = job.serializeBlock(headerBuffer, coinbaseBuffer).toString('hex');
|
||||
blockHex = job.serializeBlock(headerBuffer, coinbaseBuffer).toString('hex');
|
||||
blockHash = util.reverseBuffer(util.doublesha(headerBuffer)).toString('hex');
|
||||
_this.emit('blockFound', blockHex, blockHash);
|
||||
}
|
||||
else {
|
||||
var targetUser = bignum(diffDividend / difficulty);
|
||||
if (headerBigNum.gt(targetUser)){
|
||||
return {error: [23, 'low difficulty share', null]};
|
||||
return shareError({error: [23, 'low difficulty share']});
|
||||
}
|
||||
}
|
||||
|
||||
_this.emit('share', {
|
||||
job: jobId,
|
||||
ip: ipAddress,
|
||||
worker: workerName,
|
||||
difficulty: difficulty,
|
||||
solution: blockHash
|
||||
}, blockHex);
|
||||
|
||||
return {result: true, error: null, solution: blockHash};
|
||||
};
|
||||
};
|
||||
|
||||
100
lib/pool.js
100
lib/pool.js
@ -29,6 +29,32 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||
})();
|
||||
|
||||
|
||||
function SubmitBlock(blockHex, callback){
|
||||
if (options.hasSubmitMethod) {
|
||||
_this.daemon.cmd('submitblock',
|
||||
[blockHex],
|
||||
function(error, result){
|
||||
if (error)
|
||||
emitErrorLog('submitblock', 'rpc error when submitting block with submitblock')
|
||||
else
|
||||
emitLog('submitblock', 'Submitted Block using submitblock');
|
||||
callback();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
_this.daemon.cmd('getblocktemplate',
|
||||
[{'mode': 'submit', 'data': blockHex}],
|
||||
function(error, result){
|
||||
if (error)
|
||||
emitErrorLog('submitblock', 'rpc error when submitting block with getblocktemplate')
|
||||
else
|
||||
emitLog('submitblock', 'Submitted Block using getblocktemplate');
|
||||
callback()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function SetupJobManager(){
|
||||
_this.jobManager = new jobManager({
|
||||
@ -42,21 +68,27 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||
emitLog('system', 'Detected new block');
|
||||
_this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams());
|
||||
}
|
||||
}).on('blockFound', function(blockHex, blockHash){
|
||||
if (options.hasSubmitMethod) {
|
||||
_this.daemon.cmd('submitblock',
|
||||
[blockHex],
|
||||
function(error, result){
|
||||
emitLog('submitblock', 'Submitted Block using submitblock :'+blockHash);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
_this.daemon.cmd('getblocktemplate',
|
||||
[{'mode': 'submit', 'data': blockHex}],
|
||||
function(error, result){
|
||||
emitLog('submitblock', 'Submitted Block using getblocktemplate: '+blockHash);
|
||||
}
|
||||
);
|
||||
}).on('share', function(shareData, blockHex){
|
||||
var isValidShare = !shareData.error;
|
||||
var isValidBlock = !!blockHex;
|
||||
var emitShare = function(){
|
||||
_this.emit('share', isValidShare, isValidBlock, shareData);
|
||||
};
|
||||
|
||||
/*
|
||||
If we calculated that the block solution was found,
|
||||
before we emit the share, lets submit the block,
|
||||
then check if it was accepted using RPC getblock
|
||||
*/
|
||||
if (!isValidBlock)
|
||||
emitShare();
|
||||
else{
|
||||
SubmitBlock(blockHex, function(){
|
||||
CheckBlockAccepted(shareData.solution, function(isAccepted){
|
||||
isValidBlock = isAccepted;
|
||||
emitShare();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -72,10 +104,10 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||
[options.address],
|
||||
function(error, result){
|
||||
if (error){
|
||||
emitLog('system','validateaddress rpc error');
|
||||
emitErrorLog('system','validateaddress rpc error');
|
||||
callback(error);
|
||||
} else if (!result.isvalid) {
|
||||
emitLog('system','address is not valid');
|
||||
emitErrorLog('system','address is not valid');
|
||||
callback("address-not-valid");
|
||||
} else {
|
||||
callback(error, result);
|
||||
@ -111,6 +143,8 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||
|
||||
}).on('startFailed', function(){
|
||||
emitErrorLog('system','Failed to start daemon');
|
||||
}).on('error', function(message){
|
||||
emitErrorLog('system', message);
|
||||
});
|
||||
}
|
||||
|
||||
@ -148,25 +182,13 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||
client.extraNonce1,
|
||||
params.extraNonce2,
|
||||
params.nTime,
|
||||
params.nonce
|
||||
params.nonce,
|
||||
client.socket.remoteAddress,
|
||||
params.name
|
||||
);
|
||||
|
||||
resultCallback(result.error, result.result ? true : null);
|
||||
|
||||
_this.emit('share', !result.error, {
|
||||
job: params.jobId,
|
||||
ip: client.socket.remoteAddress,
|
||||
worker: params.name,
|
||||
solution: result.solution,
|
||||
error: result.error ? result.error[1] : undefined,
|
||||
difficulty: client.difficulty,
|
||||
timestamp: Date.now() / 1000 | 0,
|
||||
accepted: !!result.result,
|
||||
extraNonce2: params.extraNonce2,
|
||||
nTime: params.nTime,
|
||||
nonce: params.nonce
|
||||
});
|
||||
|
||||
}).on('malformedMessage', function (message) {
|
||||
emitWarningLog('client', client.workerName+" has sent us a malformed message: "+message);
|
||||
}).on('socketError', function() {
|
||||
@ -202,7 +224,6 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||
emitLog('system', 'Block polling setup for every ' + pollingInterval + ' milliseconds');
|
||||
}
|
||||
|
||||
|
||||
function GetBlockTemplate(callback){
|
||||
_this.daemon.cmd('getblocktemplate',
|
||||
[{"capabilities": [ "coinbasetxn", "workid", "coinbase/append" ]}],
|
||||
@ -217,6 +238,19 @@ var pool = module.exports = function pool(options, authorizeFn){
|
||||
);
|
||||
}
|
||||
|
||||
function CheckBlockAccepted(blockHash, callback){
|
||||
_this.daemon.cmd('getblock',
|
||||
[blockHash],
|
||||
function(error, result){
|
||||
if (error)
|
||||
callback(false);
|
||||
else if (result.hash === blockHash)
|
||||
callback(true);
|
||||
else
|
||||
callback(false);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is being called from the blockNotify so that when a new block is discovered by the daemon
|
||||
|
||||
@ -239,7 +239,8 @@ var StratumServer = exports.Server = function StratumServer(options){
|
||||
var subscriptionCounter = SubscriptionCounter();
|
||||
|
||||
(function init(){
|
||||
_socketServer = socketServer = net.createServer(function(c){
|
||||
_socketServer = socketServer = net.createServer({allowHalfOpen: true}, function(c){
|
||||
c.setKeepAlive(true);
|
||||
var subscriptionId = subscriptionCounter.next();
|
||||
var client = new StratumClient(
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user