Added jobRebroadcastTimeout configuration
This commit is contained in:
parent
a6e38a6bb0
commit
a50beb1932
@ -138,6 +138,11 @@ var pool = Stratum.createPool({
|
|||||||
job broadcast. */
|
job broadcast. */
|
||||||
"txRefreshInterval": 20000,
|
"txRefreshInterval": 20000,
|
||||||
|
|
||||||
|
/* Some miner software is bugged and will consider the pool offline if it doesn't receive
|
||||||
|
anything for around a minute, so every time we broadcast jobs, set a timeout to rebroadcast
|
||||||
|
in this many seconds unless we find a new job. Set to zero or remove to disable this. */
|
||||||
|
"jobRebroadcastTimeout": 55,
|
||||||
|
|
||||||
//instanceId: 37, //Recommend not using this because a crypto-random one will be generated
|
//instanceId: 37, //Recommend not using this because a crypto-random one will be generated
|
||||||
|
|
||||||
/* Some attackers will create thousands of workers that use up all available socket connections,
|
/* Some attackers will create thousands of workers that use up all available socket connections,
|
||||||
|
|||||||
@ -10,7 +10,7 @@ var algos = module.exports = global.algos = {
|
|||||||
multiplier: Math.pow(2, 32),
|
multiplier: Math.pow(2, 32),
|
||||||
hash: function(){
|
hash: function(){
|
||||||
return function(){
|
return function(){
|
||||||
return util.doublesha.apply(this, arguments);
|
return util.sha256d.apply(this, arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -99,8 +99,9 @@ var algos = module.exports = global.algos = {
|
|||||||
shift: 24,
|
shift: 24,
|
||||||
multiplier: Math.pow(2, 8),
|
multiplier: Math.pow(2, 8),
|
||||||
hash: function(){
|
hash: function(){
|
||||||
return function(){
|
return function(data, nTime){
|
||||||
return multiHashing.keccak.apply(this, arguments);
|
var f = Buffer.concat([data, new Buffer(nTime.toString(16), 'hex')]);
|
||||||
|
return multiHashing.keccak(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -65,6 +65,8 @@ var JobManager = module.exports = function JobManager(maxDifficulty, hashDigest,
|
|||||||
|
|
||||||
var lastTransactionUpdateCheck = Date.now();
|
var lastTransactionUpdateCheck = Date.now();
|
||||||
|
|
||||||
|
var coinbaseHasher = options.coin.algorithm === 'keccak' ? util.sha256 : util.sha256d;
|
||||||
|
|
||||||
//returns true if processed a new block
|
//returns true if processed a new block
|
||||||
this.processTemplate = function(rpcData, publicKey){
|
this.processTemplate = function(rpcData, publicKey){
|
||||||
|
|
||||||
@ -168,12 +170,12 @@ var JobManager = module.exports = function JobManager(maxDifficulty, hashDigest,
|
|||||||
var extraNonce2Buffer = new Buffer(extraNonce2, 'hex');
|
var extraNonce2Buffer = new Buffer(extraNonce2, 'hex');
|
||||||
|
|
||||||
var coinbaseBuffer = job.serializeCoinbase(extraNonce1Buffer, extraNonce2Buffer);
|
var coinbaseBuffer = job.serializeCoinbase(extraNonce1Buffer, extraNonce2Buffer);
|
||||||
var coinbaseHash = util.doublesha(coinbaseBuffer);
|
var coinbaseHash = coinbaseHasher(coinbaseBuffer);
|
||||||
|
|
||||||
var merkleRoot = util.reverseBuffer(job.merkleTree.withFirst(coinbaseHash)).toString('hex');
|
var merkleRoot = util.reverseBuffer(job.merkleTree.withFirst(coinbaseHash)).toString('hex');
|
||||||
|
|
||||||
var headerBuffer = job.serializeHeader(merkleRoot, nTime, nonce);
|
var headerBuffer = job.serializeHeader(merkleRoot, nTime, nonce);
|
||||||
var headerHash = hashDigest(headerBuffer, nTimeInt);
|
var headerHash = hashDigest(headerBuffer, nTimeInt);
|
||||||
var headerBigNum = bignum.fromBuffer(headerHash, {endian: 'little', size: 32});
|
var headerBigNum = bignum.fromBuffer(headerHash, {endian: 'little', size: 32});
|
||||||
|
|
||||||
var blockHash;
|
var blockHash;
|
||||||
@ -181,14 +183,13 @@ var JobManager = module.exports = function JobManager(maxDifficulty, hashDigest,
|
|||||||
|
|
||||||
|
|
||||||
if (job.target.ge(headerBigNum)){
|
if (job.target.ge(headerBigNum)){
|
||||||
|
|
||||||
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.sha256d(headerBuffer)).toString('hex');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var targetUser = maxDifficulty.div(difficulty);
|
var targetUser = maxDifficulty.div(difficulty);
|
||||||
if (headerBigNum.gt(targetUser)){
|
if (headerBigNum.gt(targetUser)){
|
||||||
var lowPercent = targetUser.div(headerBigNum).mul(100).toNumber().toFixed(10);
|
var lowPercent = headerBigNum.sub(targetUser).div(headerBigNum).mul(100).toNumber().toFixed(10);
|
||||||
return shareError([23, 'low difficulty share, need to be ' + lowPercent + '% higher']);
|
return shareError([23, 'low difficulty share, need to be ' + lowPercent + '% higher']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ var MerkleTree = module.exports = function MerkleTree(data){
|
|||||||
|
|
||||||
function merkleJoin(h1, h2){
|
function merkleJoin(h1, h2){
|
||||||
var joined = Buffer.concat([h1, h2]);
|
var joined = Buffer.concat([h1, h2]);
|
||||||
var dhashed = util.doublesha(joined);
|
var dhashed = util.sha256d(joined);
|
||||||
return dhashed;
|
return dhashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ var MerkleTree = module.exports = function MerkleTree(data){
|
|||||||
MerkleTree.prototype = {
|
MerkleTree.prototype = {
|
||||||
withFirst: function(f){
|
withFirst: function(f){
|
||||||
this.steps.forEach(function(s){
|
this.steps.forEach(function(s){
|
||||||
f = util.doublesha(Buffer.concat([f, s]));
|
f = util.sha256d(Buffer.concat([f, s]));
|
||||||
});
|
});
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,7 +102,7 @@ var Peer = module.exports = function(options){
|
|||||||
var msgLength = header.readUInt32LE(16);
|
var msgLength = header.readUInt32LE(16);
|
||||||
var msgChecksum = header.readUInt32LE(20);
|
var msgChecksum = header.readUInt32LE(20);
|
||||||
readFlowingBytes(client, msgLength, lopped, function(payload, lopped){
|
readFlowingBytes(client, msgLength, lopped, function(payload, lopped){
|
||||||
if (util.doublesha(payload).readUInt32LE(0) !== msgChecksum){
|
if (util.sha256d(payload).readUInt32LE(0) !== msgChecksum){
|
||||||
_this.emit('error', 'bad payload - failed checksum');
|
_this.emit('error', 'bad payload - failed checksum');
|
||||||
beginReadingMessage(null);
|
beginReadingMessage(null);
|
||||||
return;
|
return;
|
||||||
@ -154,7 +154,7 @@ var Peer = module.exports = function(options){
|
|||||||
magic,
|
magic,
|
||||||
command,
|
command,
|
||||||
util.packUInt32LE(payload.length),
|
util.packUInt32LE(payload.length),
|
||||||
util.doublesha(payload).slice(0, 4),
|
util.sha256d(payload).slice(0, 4),
|
||||||
payload
|
payload
|
||||||
]);
|
]);
|
||||||
client.write(message);
|
client.write(message);
|
||||||
|
|||||||
@ -517,7 +517,7 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
|
|
||||||
|
|
||||||
function StartStratumServer(finishedCallback){
|
function StartStratumServer(finishedCallback){
|
||||||
_this.stratumServer = new stratum.Server(options.ports, options.connectionTimeout, options.banning, authorizeFn);
|
_this.stratumServer = new stratum.Server(options.ports, options.connectionTimeout, options.jobRebroadcastTimeout, options.banning, authorizeFn);
|
||||||
|
|
||||||
_this.stratumServer.on('started', function(){
|
_this.stratumServer.on('started', function(){
|
||||||
options.initStats.stratumPorts = Object.keys(options.ports);
|
options.initStats.stratumPorts = Object.keys(options.ports);
|
||||||
|
|||||||
@ -287,18 +287,18 @@ StratumClient.prototype.__proto__ = events.EventEmitter.prototype;
|
|||||||
* - 'client.disconnected'(StratumClientInstance) - when a miner disconnects. Be aware that the socket cannot be used anymore.
|
* - 'client.disconnected'(StratumClientInstance) - when a miner disconnects. Be aware that the socket cannot be used anymore.
|
||||||
* - 'started' - when the server is up and running
|
* - 'started' - when the server is up and running
|
||||||
**/
|
**/
|
||||||
var StratumServer = exports.Server = function StratumServer(ports, connectionTimeout, banning, authorizeFn){
|
var StratumServer = exports.Server = function StratumServer(ports, connectionTimeout, jobRebroadcastTimeout, banning, authorizeFn){
|
||||||
|
|
||||||
//private members
|
//private members
|
||||||
|
|
||||||
var socketTimeout = connectionTimeout * 1000;
|
var socketTimeout = connectionTimeout * 1000;
|
||||||
var bannedMS = banning ? banning.time * 1000 : null;
|
var bannedMS = banning ? banning.time * 1000 : null;
|
||||||
|
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var stratumClients = {};
|
var stratumClients = {};
|
||||||
var subscriptionCounter = SubscriptionCounter();
|
var subscriptionCounter = SubscriptionCounter();
|
||||||
var rebroadcastTimeout;
|
var rebroadcastTimeout;
|
||||||
var bannedIPs = {};
|
var bannedIPs = {};
|
||||||
|
|
||||||
//Interval to look through bannedIPs for old bans and remove them in order to prevent a memory leak
|
//Interval to look through bannedIPs for old bans and remove them in order to prevent a memory leak
|
||||||
var purgeOldBans = (!banning || !banning.enabled) ? null : setInterval(function(){
|
var purgeOldBans = (!banning || !banning.enabled) ? null : setInterval(function(){
|
||||||
@ -376,14 +376,15 @@ var StratumServer = exports.Server = function StratumServer(ports, connectionTim
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some miners will consider the pool dead if it doesn't receive a job at least every 30 seconds.
|
/* Some miners will consider the pool dead if it doesn't receive a job for around a minute.
|
||||||
So every time broadcast jobs, we set a timeout to rebroadcast in 30 seconds unless cleared. */
|
So every time we broadcast jobs, set a timeout to rebroadcast in X seconds unless cleared. */
|
||||||
|
if (isNaN(jobRebroadcastTimeout) || jobRebroadcastTimeout <= 0) return;
|
||||||
clearTimeout(rebroadcastTimeout);
|
clearTimeout(rebroadcastTimeout);
|
||||||
rebroadcastTimeout = setTimeout(function(){
|
rebroadcastTimeout = setTimeout(function(){
|
||||||
var resendParams = jobParams;
|
var resendParams = jobParams;
|
||||||
resendParams[8] = false;
|
resendParams[8] = false;
|
||||||
_this.broadcastMiningJobs(resendParams);
|
_this.broadcastMiningJobs(resendParams);
|
||||||
}, 30000);
|
}, jobRebroadcastTimeout * 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getStratumClients = function () {
|
this.getStratumClients = function () {
|
||||||
|
|||||||
14
lib/util.js
14
lib/util.js
@ -22,16 +22,14 @@ exports.bignumFromBits = function(bitsString){
|
|||||||
return target;
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.doublesha = function(buffer){
|
exports.sha256 = function(buffer){
|
||||||
var hash1 = crypto.createHash('sha256');
|
var hash1 = crypto.createHash('sha256');
|
||||||
hash1.update(buffer);
|
hash1.update(buffer);
|
||||||
hash1 = hash1.digest();
|
return hash1.digest();
|
||||||
|
};
|
||||||
|
|
||||||
var hash2 = crypto.createHash('sha256');
|
exports.sha256d = function(buffer){
|
||||||
hash2.update(hash1);
|
return exports.sha256(exports.sha256(buffer));
|
||||||
hash2 = hash2.digest();
|
|
||||||
|
|
||||||
return hash2;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.reverseBuffer = function(buff){
|
exports.reverseBuffer = function(buff){
|
||||||
@ -257,7 +255,7 @@ exports.addressToPubkey = function(addr){
|
|||||||
/* We already do rpc.validateaddress so we don't need this
|
/* We already do rpc.validateaddress so we don't need this
|
||||||
var ver = decoded[0];
|
var ver = decoded[0];
|
||||||
var cksumA = decoded.slice(-4);
|
var cksumA = decoded.slice(-4);
|
||||||
var cksumB = exports.doublesha(decoded.slice(0, -4)).slice(0, 4);
|
var cksumB = exports.sha256d(decoded.slice(0, -4)).slice(0, 4);
|
||||||
|
|
||||||
if (cksumA.toString('hex') != cksumB.toString('hex')){
|
if (cksumA.toString('hex') != cksumB.toString('hex')){
|
||||||
console.error('checksum did not match for ' + addr)
|
console.error('checksum did not match for ' + addr)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user