stratum-pool-sugarchain
Version:
High performance Sugarchain Stratum poolserver in Node.js
127 lines (99 loc) • 3.38 kB
JavaScript
var events = require('events');
/*
Vardiff ported from stratum-mining share-limiter
https://github.com/ahmedbodi/stratum-mining/blob/master/mining/basic_share_limiter.py
*/
function RingBuffer(maxSize){
var data = [];
var cursor = 0;
var isFull = false;
this.append = function(x){
if (isFull){
data[cursor] = x;
cursor = (cursor + 1) % maxSize;
}
else{
data.push(x);
cursor++;
if (data.length === maxSize){
cursor = 0;
isFull = true;
}
}
};
this.avg = function(){
var sum = data.reduce(function(a, b){ return a + b });
return sum / (isFull ? maxSize : cursor);
};
this.size = function(){
return isFull ? maxSize : cursor;
};
this.clear = function(){
data = [];
cursor = 0;
isFull = false;
};
}
// Truncate a number to a fixed amount of decimal places
function toFixed(num, len) {
return parseFloat(num.toFixed(len));
}
var varDiff = module.exports = function varDiff(port, varDiffOptions){
var _this = this;
var bufferSize, tMin, tMax;
//if (!varDiffOptions) return;
var variance = varDiffOptions.targetTime * (varDiffOptions.variancePercent / 100);
bufferSize = varDiffOptions.retargetTime / varDiffOptions.targetTime * 4;
tMin = varDiffOptions.targetTime - variance;
tMax = varDiffOptions.targetTime + variance;
this.manageClient = function(client){
var stratumPort = client.socket.localPort;
if (stratumPort != port) {
console.error("Handling a client which is not of this vardiff?");
}
var options = varDiffOptions;
var lastTs;
var lastRtc;
var timeBuffer;
client.on('submit', function(){
var ts = (Date.now() / 1000) | 0;
if (!lastRtc){
lastRtc = ts - options.retargetTime / 2;
lastTs = ts;
timeBuffer = new RingBuffer(bufferSize);
return;
}
var sinceLast = ts - lastTs;
timeBuffer.append(sinceLast);
lastTs = ts;
if ((ts - lastRtc) < options.retargetTime && timeBuffer.size() > 0)
return;
lastRtc = ts;
var avg = timeBuffer.avg();
var ddiff = options.targetTime / avg;
if (avg > tMax && client.difficulty > options.minDiff) {
if (options.x2mode) {
ddiff = 0.5;
}
if (ddiff * client.difficulty < options.minDiff) {
ddiff = options.minDiff / client.difficulty;
}
} else if (avg < tMin) {
if (options.x2mode) {
ddiff = 2;
}
var diffMax = options.maxDiff;
if (ddiff * client.difficulty > diffMax) {
ddiff = diffMax / client.difficulty;
}
}
else{
return;
}
var newDiff = toFixed(client.difficulty * ddiff, 8);
timeBuffer.clear();
_this.emit('newDifficulty', client, newDiff);
});
};
};
varDiff.prototype.__proto__ = events.EventEmitter.prototype;