mirror of
https://github.com/jwinterm/nodejs-pool.git
synced 2026-10-17 05:21:27 +02:00
Backport an update from parent repo
My push overwrote a recent update from the parent NodeJS-Pool repo. This puts it back.
This commit is contained in:
+95
-34
@@ -517,38 +517,111 @@ function Database(){
|
||||
txn.commit();
|
||||
};
|
||||
|
||||
this.getOldestLockedBlock = function(){
|
||||
/*
|
||||
6-29-2017 - Snipa -
|
||||
This function returns a decompressed block proto for the first locked block in the system as part of the
|
||||
share depth functions. DO NOT BLINDLY REPLACE getLastBlock WITH THIS FUNCTION.
|
||||
*/
|
||||
this.refreshEnv();
|
||||
debug("Getting the oldest locked block in the system");
|
||||
let txn = this.env.beginTxn({readOnly: true});
|
||||
let cursor = new this.lmdb.Cursor(txn, this.blockDB);
|
||||
let highestBlock = null;
|
||||
for (let found = cursor.goToFirst(); found; found = cursor.goToNext()) {
|
||||
if (highestBlock !== null){
|
||||
break;
|
||||
}
|
||||
cursor.getCurrentBinary(function(key, data){ // jshint ignore:line
|
||||
let blockData = global.protos.Block.decode(data);
|
||||
if (blockData.unlocked === false){
|
||||
highestBlock = blockData;
|
||||
}
|
||||
});
|
||||
}
|
||||
cursor.close();
|
||||
txn.commit();
|
||||
if (highestBlock !== null) {
|
||||
debug("Got the oldest locked block in the system at height: " + JSON.stringify(highestBlock));
|
||||
} else {
|
||||
debug("There are no unlocked blocks in the system. Woohoo!");
|
||||
}
|
||||
return highestBlock;
|
||||
};
|
||||
|
||||
this.cleanShareDB = function() {
|
||||
/*
|
||||
This function takes the difficulty of the current block, and the last PPS block. If it's 0, save everything,
|
||||
UNLESS global.config.pps.enable is FALSE, then feel free to trash it.
|
||||
Due to LMDB under current config, we must delete entire keys, due to this, we save diff * shareMultiLog * 1.5
|
||||
global.config.pplns.shareMultiLog should be at least 1.5x your shareMulti, in case of diff spikiing
|
||||
This function takes the difficulty of the current block, and the last PPS block. If it's 0, save everything,
|
||||
UNLESS global.config.pps.enable is FALSE, then feel free to trash it.
|
||||
Due to LMDB under current config, we must delete entire keys, due to this, we save diff * shareMulti * 1.3
|
||||
6/29/2017 - Fixed bug with the way the system got blocks. getLastBlock gets the most recent block.
|
||||
getOldestLockedBlock gets the oldest block in the system that's locked. This ensures that shares for that block
|
||||
can't be destroyed, and that there's enough depth past that point to ensure the system will have the ability
|
||||
to make payouts based on the shareMultiLog. Thanks suhz for finding this. Sorry it hit your aeon pool hard.
|
||||
:( -- Snipa
|
||||
If current_height - global.payout.blocksRequired > lastLockedBlock, then set the scan start to
|
||||
current_height - global.payout.blocksRequired - 1 so that we have the full block in case of PPS.
|
||||
Otherwise, use the lastPPLNSBlock as the scan start. There we go. Stupid logic!
|
||||
Math check!
|
||||
cur_height = 100, blocksRequired=20, lastPPLNSLockedBlock.height=90
|
||||
In this case, the functional depth required for SOLO is 80 - 1, giving us 79 as our start
|
||||
cur_height = 100, blocksRequired=20, lastPPLNSLockedBlock.height=70
|
||||
In this case, the PPLNS locked block is older than the current height - the required amount, so start is 70.
|
||||
PPS height no longer matters! Yay!
|
||||
Solo really doesn't matter, as block finder gets everything.
|
||||
If there is no valid locked block to start from, aka all blocks are unlocked, then scan from the current height
|
||||
of the chain, as there's no way for the system to have older blocks. We only need to save extra in the case
|
||||
where there's unlocked blocks. A find on the current block will have enough depth as long as the saves are
|
||||
correct. This will cause the system to clean up shares massively when there are no unlocked blocks.
|
||||
*/
|
||||
let lastPPSBlock = this.getLastBlock();
|
||||
if (global.config.pps.enable){
|
||||
lastPPSBlock = this.getLastBlock(global.protos.POOLTYPE.PPS);
|
||||
if (lastPPSBlock === 0){
|
||||
return;
|
||||
}
|
||||
}
|
||||
let lastPPLNSBlock = this.getLastBlock(global.protos.POOLTYPE.PPLNS);
|
||||
debug("Last PPS block: "+lastPPSBlock);
|
||||
// Hopping into async, we need the current block height to know where to start our indexing...
|
||||
let oldestLockedBlock = this.getOldestLockedBlock();
|
||||
async.waterfall([
|
||||
function(callback){
|
||||
global.coinFuncs.getBlockHeaderByHash(oldestLockedBlock.hash, (err, result) => {
|
||||
oldestLockedBlock.height = result.height;
|
||||
console.log(`Got the oldest block`);
|
||||
callback(null, oldestLockedBlock);
|
||||
});
|
||||
},
|
||||
function(oldestLockedBlock, callback){
|
||||
global.coinFuncs.getLastBlockHeader(function(err, body){
|
||||
if (err) {
|
||||
return callback(true, body);
|
||||
if (oldestLockedBlock === null){
|
||||
/*
|
||||
If there's no locked blocks, then allow the system to scan from the PPS depth downwards if PPS
|
||||
is enabled.
|
||||
Save enough shares so that the diff * share multi * 30% for buffer.
|
||||
*/
|
||||
if (global.config.pps.enable){
|
||||
// If PPS is enabled, we scan for new blocks at cur height - blocksRequired/2.
|
||||
// We need to save shares back that far at the least.
|
||||
callback(null, body.height - Math.floor(global.config.payout.blocksRequired/2), Math.floor(body.difficulty * global.config.pplns.shareMulti * 1.3));
|
||||
} else {
|
||||
// Otherwise, we can just start from the current height. Woo!
|
||||
callback(null, body.height, Math.floor(body.difficulty * global.config.pplns.shareMulti * 1.3));
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
Otherwise, start the scan from the oldest locked block downwards.
|
||||
This protects against the blockManager being messed up and not unlocking blocks.
|
||||
This will ensure that enough shares are in place to unlock all blocks.
|
||||
If the block is Solo, PPLNS or PPS, it doesn't matter.
|
||||
*/
|
||||
if (global.config.pps.enable && oldestLockedBlock.height > body.height - Math.floor(global.config.payout.blocksRequired/2)) {
|
||||
// If PPS is enabled, and the oldestLockedBlock.height > the PPS minimum, start from the PPS minimum.
|
||||
callback(null, body.height - Math.floor(global.config.payout.blocksRequired/2), Math.floor(body.difficulty * global.config.pplns.shareMulti * 1.3));
|
||||
} else {
|
||||
// If PPS isn't enabled, or the oldestLockedBlock.height < the PPS minimum, then start from there.
|
||||
callback(null, oldestLockedBlock.height, Math.floor(oldestLockedBlock.difficulty * global.config.pplns.shareMulti * 1.3));
|
||||
}
|
||||
}
|
||||
return callback(null, body.height, Math.floor(body.difficulty * 1.5 * global.config.pplns.shareMultiLog));
|
||||
});
|
||||
},
|
||||
function (lastBlock, difficulty, callback) {
|
||||
let shareCount = 0;
|
||||
let ppsFound = false;
|
||||
let pplnsFound = false;
|
||||
let blockList = [];
|
||||
debug("Scanning from: "+lastBlock + " for more than: " + difficulty + " shares");
|
||||
console.log("Scanning from: "+lastBlock + " for more than: " + difficulty + " shares");
|
||||
range.range(0, lastBlock+1).forEach(function (blockID) {
|
||||
blockID = (blockID - lastBlock+1) * -1;
|
||||
if (blockID < 0){
|
||||
@@ -558,7 +631,7 @@ function Database(){
|
||||
let txn = global.database.env.beginTxn({readOnly: true});
|
||||
let cursor = new global.database.lmdb.Cursor(txn, global.database.shareDB);
|
||||
for (let found = (cursor.goToRange(blockID) === blockID); found; found = cursor.goToNextDup()) {
|
||||
if (ppsFound && pplnsFound){
|
||||
if (pplnsFound){
|
||||
cursor.getCurrentBinary(function(key, data) { // jshint ignore:line
|
||||
if (blockList.indexOf(key) === -1){
|
||||
blockList.push(key);
|
||||
@@ -566,9 +639,6 @@ function Database(){
|
||||
});
|
||||
} else {
|
||||
cursor.getCurrentBinary(function(key, data) { // jshint ignore:line
|
||||
if (key < lastPPSBlock){
|
||||
ppsFound = true;
|
||||
}
|
||||
try{
|
||||
let shareData = global.protos.Share.decode(data);
|
||||
if (shareData.poolType === global.protos.POOLTYPE.PPLNS){
|
||||
@@ -589,19 +659,11 @@ function Database(){
|
||||
callback(null, blockList);
|
||||
}
|
||||
], function(err, data){
|
||||
if (err === null && global.config.general.blockCleaner === true){
|
||||
if (global.config.general.blockCleaner === true){
|
||||
if(data.length > 0){
|
||||
global.database.refreshEnv();
|
||||
let blockList = global.database.getBlockList();
|
||||
debug("Got the block list");
|
||||
let totalDeleted = 0;
|
||||
data.forEach(function(block){
|
||||
if ((blockList.indexOf(block) !== -1 && !blockList.unlocked) || block > lastPPLNSBlock){
|
||||
// Don't delete locked blocks. ffs.
|
||||
// Don't delete blocks that could contain shares. Even if it's unlikely as all getout.
|
||||
debug("Skipped deleting block: " + block);
|
||||
return;
|
||||
}
|
||||
totalDeleted += 1;
|
||||
let txn = global.database.env.beginTxn();
|
||||
txn.del(global.database.shareDB, block);
|
||||
@@ -613,12 +675,11 @@ function Database(){
|
||||
global.database.env.sync(function(){
|
||||
});
|
||||
} else {
|
||||
console.log("Block cleaning disabled. Would of removed: " + JSON.stringify(data));
|
||||
console.log("Block cleaning disabled. Would have removed: " + JSON.stringify(data));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
this.refreshEnv = function(){};
|
||||
|
||||
setInterval(function(){
|
||||
|
||||
Reference in New Issue
Block a user