"use strict"; import {DataFinder} from "./DataFinder"; import {DBBlock} from "duniter/app/lib/db/DBBlock"; const co = require('co'); const constants = require(__dirname + '/constants') /** * updateCache * */ module.exports = async (req:any, res:any, next:any) => { var { duniterServer, cache } = req.app.locals const dataFinder = new DataFinder(duniterServer) try { // Définition des constantes const conf = duniterServer.conf; // Définition des variables let upgradeCache = false; // Cacluler s'il faut mettre à jour le cache ou pas upgradeCache = (Math.floor(Date.now() / 1000) > (cache.lastUptime + constants.MIN_CACHE_UPDATE_FREQ)); // Si le cache membersCount est dévérouillé, le vérouiller, sinon ne pas réinitialiser le cache if (upgradeCache && !cache.lockMembersCount) { cache.lockMembersCount = true; } else if(cache.lockMembersCount) { upgradeCache = false; } // If fork, unstack cache let reinitBdd = false; if (cache.endBlock != null) { let checkBlock = [await dataFinder.getBlock(cache.blockchain[cache.blockchain.length-1].number) as DBBlock]; if (cache.blockchain.length > 0 && cache.blockchain[cache.blockchain.length-1].hash != checkBlock[0].hash && upgradeCache) { // reinitialize cache cache.lastUptime = 0; cache.lockMembersCount = false; cache.beginBlock = null; cache.currentBlockNumber = 0; cache.currentBlockTime = 0; cache.currentSentries = 0; cache.endBlock = null; cache.step = null; cache.stepUnit = null; cache.stepTime = null; cache.onlyDate = null; cache.Yn = 0; cache.pubkeys = new Array(); cache.pub_index = new Array(); cache.blockchain = new Array(); // reinitialize bdd reinitBdd = true; } } // define step cache.step = 1; if (typeof(req.query.step) != 'undefined' && parseInt(req.query.step) > 0) { cache.step = req.query.step; } // calculate unitTime and onlyDate let unitTime = 0; if (typeof(req.query.stepUnit) != 'undefined') { switch (req.query.stepUnit) { case "blocks": unitTime = 300; cache.onlyDate = false; cache.stepUnit = "blocks"; break; case "hours": unitTime = 3600; cache.onlyDate = false; cache.stepUnit = "hours"; break; case "days": unitTime = 86400; cache.onlyDate = true; cache.stepUnit = "days"; break; case "weeks": unitTime = 604800; cache.onlyDate = true; cache.stepUnit = "weeks"; break; case "months": unitTime = 18144000; cache.onlyDate = true; cache.stepUnit = "months"; break; case "years": unitTime = 31557600; cache.onlyDate = true; cache.stepUnit = "years"; break; } } // Default values else { unitTime = 86400; cache.onlyDate = true; cache.stepUnit = "days"; } // get endBlock if ( typeof(req.query.end) == 'undefined' || req.query.end <= 0) { cache.endBlock = [await dataFinder.getCurrentBlockOrNull()]; } else { cache.endBlock = [await dataFinder.getBlock(req.query.end)]; // Si end >= currentBlock, get currentBlock if ( typeof(cache.endBlock[0]) == 'undefined' ) { cache.endBlock = [await dataFinder.getCurrentBlockOrNull()]; } } // fix begin value if ( typeof(req.query.begin) == 'undefined' || req.query.begin < 0 ) { cache.beginBlock = [await dataFinder.getBlock(0)]; } else if (req.query.begin > cache.endBlock[0].number) { let beginTime = cache.endBlock[0].medianTime-(parseInt(cache.step)*unitTime*constants.STEP_COUNT_MIN); cache.beginBlock = [await dataFinder.getBlockWhereMedianTimeGte(beginTime)]; } else { cache.beginBlock = [await dataFinder.getBlock(req.query.begin)]; } // Define nbMaxPoints and adaptMaxPoints if ( typeof(req.query.nbMaxPoints) != 'undefined' && req.query.nbMaxPoints > 0 ) { cache.nbMaxPoints = req.query.nbMaxPoints; } else { cache.nbMaxPoints = constants.STEP_COUNT_MAX; } if ( typeof(req.query.adaptMaxPoints) != 'undefined' && (req.query.adaptMaxPoints == "step" || req.query.adaptMaxPoints == "end")) { cache.adaptMaxPoints = req.query.adaptMaxPoints; } else { cache.adaptMaxPoints = "begin"; } // Apply nbMaxPoints and adaptMaxPoints if (cache.adaptMaxPoints == "begin") { if ( Math.ceil((cache.endBlock[0].medianTime-cache.beginBlock[0].medianTime)/(cache.step*unitTime)) > cache.nbMaxPoints ) { let newBeginTime = cache.endBlock[0].medianTime-cache.step*cache.nbMaxPoints*unitTime; cache.beginBlock = [await dataFinder.getBlockWhereMedianTimeGte(newBeginTime)]; } } else if (cache.adaptMaxPoints == "step") { cache.step = Math.ceil((cache.endBlock[0].medianTime-cache.beginBlock[0].medianTime)/(constants.STEP_COUNT_MAX*unitTime)); } else { let newEndTime = cache.beginBlock[0].medianTime+cache.step*cache.nbMaxPoints*unitTime; cache.endBlock = [await dataFinder.getBlockWhereMedianTimeLte(newEndTime)]; } // Calculate stepTime cache.stepTime = parseInt(cache.step)*unitTime; // if new blocks and MIN_CACHE_UPDATE_FREQ pass, update cache if ( parseInt(cache.endBlock[0].number) >= cache.currentBlockNumber && Math.floor(Date.now() / 1000) > (cache.lastUptime + constants.MIN_CACHE_UPDATE_FREQ)) { // let previousCacheTime = (cache.blockchain.length > 0) ? cache.blockchain[cache.blockchain.length-1].medianTime:0; var newBlocks = await dataFinder.getBlockWhereMedianTimeLteAndGtNoLimit(cache.currentBlockTime, cache.endBlock[0].medianTime); // Initialise newJoiners let newJoiners = new Array(); // Initialise delIdtys let delIdtys = new Array(); for (let b=0;b '+cache.currentBlockTime+' AND `medianTime` < '+(parseInt(newBlocks[b].medianTime)-sigValidity)+' ORDER BY `medianTime` DESC LIMIT 1'); if (tmpExpireCertsBlock.length > 0) { expireCertsNumber = parseInt(tmpExpireCertsBlock[0].number); } // Suppr expires certs if (expireCertsNumber >= 0) { for (let m=0;m cache.Yn && cache.Yn > 0) { for (let m=0;m= cache.Yn && cache.pubkeys[m].receivedCerts.length >= minReceivedCerts && (cache.pubkeys[m].writtenCerts.length < newYn || cache.pubkeys[m].receivedCerts.length < newYn)) { newSentries -= 1; } } minReceivedCerts = (newYn= minReceivedCerts) { newSentries++; } // Calculate if the receiver of cert become sentry if (cache.pubkeys[cache.pub_index[certifications[c][1]]].writtenCerts.length >= cache.Yn && cache.pubkeys[cache.pub_index[certifications[c][1]]].receivedCerts.length == minReceivedCerts) { newSentries++; } } if (newSentries != 0) { cache.blockchain.push({ number: newBlocks[b].number, hash: newBlocks[b].hash, medianTime: newBlocks[b].medianTime, newSentries: newSentries, sentries: (cache.blockchain.length > 0) ? cache.blockchain[cache.blockchain.length-1].sentries+newSentries:newSentries }); } } // end of newBlocks loop // update cache.currentBlockNumber and cache.currentBlockTime cache.currentBlockNumber = cache.endBlock[0].number; cache.currentBlockTime = cache.endBlock[0].medianTime; // Upgrade lastUptime cache.lastUptime = Math.floor(Date.now() / 1000); } // Unlock Members count cache if (upgradeCache) { cache.lockMembersCount = false; } next() } catch (e) { console.error(e.stack || e) // En cas d'exception, afficher le message res.status(500).send(`
${e.stack || e.message}
`) } }