Added jobRebroadcastTimeout configuration

This commit is contained in:
Matt 2014-04-01 10:10:50 -06:00
parent a6e38a6bb0
commit a50beb1932
8 changed files with 36 additions and 30 deletions

View File

@ -138,6 +138,11 @@ var pool = Stratum.createPool({
job broadcast. */
"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
/* Some attackers will create thousands of workers that use up all available socket connections,

View File

@ -10,7 +10,7 @@ var algos = module.exports = global.algos = {
multiplier: Math.pow(2, 32),
hash: 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,
multiplier: Math.pow(2, 8),
hash: function(){
return function(){
return multiHashing.keccak.apply(this, arguments);
return function(data, nTime){
var f = Buffer.concat([data, new Buffer(nTime.toString(16), 'hex')]);
return multiHashing.keccak(f);
}
}
},

View File

@ -65,6 +65,8 @@ var JobManager = module.exports = function JobManager(maxDifficulty, hashDigest,
var lastTransactionUpdateCheck = Date.now();
var coinbaseHasher = options.coin.algorithm === 'keccak' ? util.sha256 : util.sha256d;
//returns true if processed a new block
this.processTemplate = function(rpcData, publicKey){
@ -168,12 +170,12 @@ var JobManager = module.exports = function JobManager(maxDifficulty, hashDigest,
var extraNonce2Buffer = new Buffer(extraNonce2, 'hex');
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 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 blockHash;
@ -181,14 +183,13 @@ var JobManager = module.exports = function JobManager(maxDifficulty, hashDigest,
if (job.target.ge(headerBigNum)){
blockHex = job.serializeBlock(headerBuffer, coinbaseBuffer).toString('hex');
blockHash = util.reverseBuffer(util.doublesha(headerBuffer)).toString('hex');
blockHash = util.reverseBuffer(util.sha256d(headerBuffer)).toString('hex');
}
else {
var targetUser = maxDifficulty.div(difficulty);
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']);
}
}

View File

@ -10,7 +10,7 @@ var MerkleTree = module.exports = function MerkleTree(data){
function merkleJoin(h1, h2){
var joined = Buffer.concat([h1, h2]);
var dhashed = util.doublesha(joined);
var dhashed = util.sha256d(joined);
return dhashed;
}
@ -51,7 +51,7 @@ var MerkleTree = module.exports = function MerkleTree(data){
MerkleTree.prototype = {
withFirst: function(f){
this.steps.forEach(function(s){
f = util.doublesha(Buffer.concat([f, s]));
f = util.sha256d(Buffer.concat([f, s]));
});
return f;
}

View File

@ -102,7 +102,7 @@ var Peer = module.exports = function(options){
var msgLength = header.readUInt32LE(16);
var msgChecksum = header.readUInt32LE(20);
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');
beginReadingMessage(null);
return;
@ -154,7 +154,7 @@ var Peer = module.exports = function(options){
magic,
command,
util.packUInt32LE(payload.length),
util.doublesha(payload).slice(0, 4),
util.sha256d(payload).slice(0, 4),
payload
]);
client.write(message);

View File

@ -517,7 +517,7 @@ var pool = module.exports = function pool(options, authorizeFn){
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(){
options.initStats.stratumPorts = Object.keys(options.ports);

View File

@ -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.
* - '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
var socketTimeout = connectionTimeout * 1000;
var bannedMS = banning ? banning.time * 1000 : null;
var socketTimeout = connectionTimeout * 1000;
var bannedMS = banning ? banning.time * 1000 : null;
var _this = this;
var stratumClients = {};
var _this = this;
var stratumClients = {};
var subscriptionCounter = SubscriptionCounter();
var rebroadcastTimeout;
var bannedIPs = {};
var bannedIPs = {};
//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(){
@ -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.
So every time broadcast jobs, we set a timeout to rebroadcast in 30 seconds unless cleared. */
/* Some miners will consider the pool dead if it doesn't receive a job for around a minute.
So every time we broadcast jobs, set a timeout to rebroadcast in X seconds unless cleared. */
if (isNaN(jobRebroadcastTimeout) || jobRebroadcastTimeout <= 0) return;
clearTimeout(rebroadcastTimeout);
rebroadcastTimeout = setTimeout(function(){
var resendParams = jobParams;
resendParams[8] = false;
_this.broadcastMiningJobs(resendParams);
}, 30000);
}, jobRebroadcastTimeout * 1000);
};
this.getStratumClients = function () {

View File

@ -22,16 +22,14 @@ exports.bignumFromBits = function(bitsString){
return target;
};
exports.doublesha = function(buffer){
exports.sha256 = function(buffer){
var hash1 = crypto.createHash('sha256');
hash1.update(buffer);
hash1 = hash1.digest();
return hash1.digest();
};
var hash2 = crypto.createHash('sha256');
hash2.update(hash1);
hash2 = hash2.digest();
return hash2;
exports.sha256d = function(buffer){
return exports.sha256(exports.sha256(buffer));
};
exports.reverseBuffer = function(buff){
@ -257,7 +255,7 @@ exports.addressToPubkey = function(addr){
/* We already do rpc.validateaddress so we don't need this
var ver = decoded[0];
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')){
console.error('checksum did not match for ' + addr)