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;
|
data += chunk;
|
||||||
});
|
});
|
||||||
res.on('end', function(){
|
res.on('end', function(){
|
||||||
var dataJson = JSON.parse(data);
|
var dataJson;
|
||||||
callback(dataJson.error, dataJson.result);
|
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;
|
var submitTime = Date.now() / 1000 | 0;
|
||||||
|
|
||||||
if (extraNonce2.length / 2 !== _this.extraNonce2Size)
|
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;
|
var job = this.currentJob;
|
||||||
if ( job.jobId != jobId ) {
|
if ( job.jobId != jobId ) {
|
||||||
return {error: [21, 'job not found', null]};
|
return shareError({error: [21, 'job not found']});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nTime.length !== 8) {
|
if (nTime.length !== 8) {
|
||||||
return {error: [20, 'incorrect size of ntime']};
|
return shareError({error: [20, 'incorrect size of ntime']});
|
||||||
}
|
}
|
||||||
|
|
||||||
var nTimeInt = parseInt(nTime, 16);
|
var nTimeInt = parseInt(nTime, 16);
|
||||||
if (nTimeInt < job.rpcData.curtime || nTime > submitTime + 7200) {
|
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) {
|
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)) {
|
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 headerBigNum = bignum.fromBuffer(headerHash, {endian: 'little', size: 32});
|
||||||
|
|
||||||
var blockHash;
|
var blockHash;
|
||||||
|
var blockHex;
|
||||||
|
|
||||||
if (job.target.ge(headerBigNum)){
|
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');
|
blockHash = util.reverseBuffer(util.doublesha(headerBuffer)).toString('hex');
|
||||||
_this.emit('blockFound', blockHex, blockHash);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var targetUser = bignum(diffDividend / difficulty);
|
var targetUser = bignum(diffDividend / difficulty);
|
||||||
if (headerBigNum.gt(targetUser)){
|
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};
|
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(){
|
function SetupJobManager(){
|
||||||
_this.jobManager = new jobManager({
|
_this.jobManager = new jobManager({
|
||||||
@ -42,21 +68,27 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
emitLog('system', 'Detected new block');
|
emitLog('system', 'Detected new block');
|
||||||
_this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams());
|
_this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams());
|
||||||
}
|
}
|
||||||
}).on('blockFound', function(blockHex, blockHash){
|
}).on('share', function(shareData, blockHex){
|
||||||
if (options.hasSubmitMethod) {
|
var isValidShare = !shareData.error;
|
||||||
_this.daemon.cmd('submitblock',
|
var isValidBlock = !!blockHex;
|
||||||
[blockHex],
|
var emitShare = function(){
|
||||||
function(error, result){
|
_this.emit('share', isValidShare, isValidBlock, shareData);
|
||||||
emitLog('submitblock', 'Submitted Block using submitblock :'+blockHash);
|
};
|
||||||
}
|
|
||||||
);
|
/*
|
||||||
} else {
|
If we calculated that the block solution was found,
|
||||||
_this.daemon.cmd('getblocktemplate',
|
before we emit the share, lets submit the block,
|
||||||
[{'mode': 'submit', 'data': blockHex}],
|
then check if it was accepted using RPC getblock
|
||||||
function(error, result){
|
*/
|
||||||
emitLog('submitblock', 'Submitted Block using getblocktemplate: '+blockHash);
|
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],
|
[options.address],
|
||||||
function(error, result){
|
function(error, result){
|
||||||
if (error){
|
if (error){
|
||||||
emitLog('system','validateaddress rpc error');
|
emitErrorLog('system','validateaddress rpc error');
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if (!result.isvalid) {
|
} else if (!result.isvalid) {
|
||||||
emitLog('system','address is not valid');
|
emitErrorLog('system','address is not valid');
|
||||||
callback("address-not-valid");
|
callback("address-not-valid");
|
||||||
} else {
|
} else {
|
||||||
callback(error, result);
|
callback(error, result);
|
||||||
@ -111,6 +143,8 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
|
|
||||||
}).on('startFailed', function(){
|
}).on('startFailed', function(){
|
||||||
emitErrorLog('system','Failed to start daemon');
|
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,
|
client.extraNonce1,
|
||||||
params.extraNonce2,
|
params.extraNonce2,
|
||||||
params.nTime,
|
params.nTime,
|
||||||
params.nonce
|
params.nonce,
|
||||||
|
client.socket.remoteAddress,
|
||||||
|
params.name
|
||||||
);
|
);
|
||||||
|
|
||||||
resultCallback(result.error, result.result ? true : null);
|
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) {
|
}).on('malformedMessage', function (message) {
|
||||||
emitWarningLog('client', client.workerName+" has sent us a malformed message: "+message);
|
emitWarningLog('client', client.workerName+" has sent us a malformed message: "+message);
|
||||||
}).on('socketError', function() {
|
}).on('socketError', function() {
|
||||||
@ -202,7 +224,6 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
emitLog('system', 'Block polling setup for every ' + pollingInterval + ' milliseconds');
|
emitLog('system', 'Block polling setup for every ' + pollingInterval + ' milliseconds');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function GetBlockTemplate(callback){
|
function GetBlockTemplate(callback){
|
||||||
_this.daemon.cmd('getblocktemplate',
|
_this.daemon.cmd('getblocktemplate',
|
||||||
[{"capabilities": [ "coinbasetxn", "workid", "coinbase/append" ]}],
|
[{"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
|
* 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();
|
var subscriptionCounter = SubscriptionCounter();
|
||||||
|
|
||||||
(function init(){
|
(function init(){
|
||||||
_socketServer = socketServer = net.createServer(function(c){
|
_socketServer = socketServer = net.createServer({allowHalfOpen: true}, function(c){
|
||||||
|
c.setKeepAlive(true);
|
||||||
var subscriptionId = subscriptionCounter.next();
|
var subscriptionId = subscriptionCounter.next();
|
||||||
var client = new StratumClient(
|
var client = new StratumClient(
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user