diff --git a/routes/willMembers2.ts b/routes/willMembers2.ts index 2076a0ca8391357291b5b4bd233198c05e14e437..b659f723e6449ca78195b9315d8bcc9c8077fc9a 100755 --- a/routes/willMembers2.ts +++ b/routes/willMembers2.ts @@ -30,10 +30,9 @@ module.exports = async (req: any, res: any, next: any) => { try { // get blockchain timestamp let resultQueryCurrentBlock = await dataFinder.getCurrentBlockOrNull(); - const currentBlockchainTimestamp = resultQueryCurrentBlock[0].medianTime; - const currentMembersCount = resultQueryCurrentBlock[0].membersCount; - const currentBlockNumber = resultQueryCurrentBlock[0].number; - const currentBlockHash = resultQueryCurrentBlock[0].hash; + const currentBlockchainTimestamp = resultQueryCurrentBlock.medianTime; + const currentMembersCount = resultQueryCurrentBlock.membersCount; + const currentBlockNumber = resultQueryCurrentBlock.number; // Initaliser les constantes const conf = duniterServer.conf; @@ -42,8 +41,6 @@ module.exports = async (req: any, res: any, next: any) => { // Initaliser les variables let errors = ""; let idtysListOrdered: WillMemberIdentityWithPendingCerts[] = [] - let sumPercentSentriesReached = 0; - let sumPercentMembersReached = 0; // Récupérer les paramètres let days = req.query.d || 65 // Valeur par défaut @@ -73,6 +70,7 @@ module.exports = async (req: any, res: any, next: any) => { if (reinitCache) { // Réinitialiser le cache + dataFinder.invalidateCache() identitiesList = []; idtysPendingCertifsList = []; nbMaxCertifs = 0; @@ -97,7 +95,7 @@ module.exports = async (req: any, res: any, next: any) => { let idtyBlockNumber = idtyBlockStamp[0]; // récupérer le medianTime et le hash du bloc d'émission de l'identité - let idtyEmittedBlock = await dataFinder.getBlockMedianTimeAndHash(idtyBlockNumber); + let idtyEmittedBlock = await dataFinder.getBlockMedianTimeAndHash(parseInt(idtyBlockNumber)); // Récupérer l'identifiant wotex de l'identité (en cas d'identité multiple) let idties = await dataFinder.getWotexInfos(resultQueryIdtys[i].uid); @@ -114,7 +112,7 @@ module.exports = async (req: any, res: any, next: any) => { // vérifier la validité du blockstamp de l'identité let validIdtyBlockStamp = false; - if (typeof(idtyEmittedBlock[0]) == 'undefined' || idtyEmittedBlock[0].hash == idtyBlockStamp[1]) + if (typeof(idtyEmittedBlock) == 'undefined' || idtyEmittedBlock.hash == idtyBlockStamp[1]) { validIdtyBlockStamp = true; } // vérifier si l'identité a été révoquée ou non @@ -127,7 +125,7 @@ module.exports = async (req: any, res: any, next: any) => { // Stocker les informations de l'identité identitiesList.push({ BlockNumber: parseInt(idtyBlockNumber), - creationTimestamp: (typeof(idtyEmittedBlock[0]) == 'undefined' ) ? currentBlockchainTimestamp:idtyEmittedBlock[0].medianTime, + creationTimestamp: (typeof(idtyEmittedBlock) == 'undefined' ) ? currentBlockchainTimestamp:idtyEmittedBlock.medianTime, pubkey: resultQueryIdtys[i].pubkey, uid: resultQueryIdtys[i].uid, hash: resultQueryIdtys[i].hash, @@ -149,11 +147,11 @@ module.exports = async (req: any, res: any, next: any) => { for (let j=0;j<tmpQueryPendingCertifsList.length;j++) { // Récupérer le medianTime et le hash du bloc d'émission de la certification - let emittedBlock = await dataFinder.getBlockMedianTimeAndHash2(tmpQueryPendingCertifsList[j].block_number) + let emittedBlock = await dataFinder.getBlockMedianTimeAndHash(tmpQueryPendingCertifsList[j].block_number) // Vérifier que l'émetteur de la certification correspond à une identité inscrite en blockchain - let tmpQueryGetUidIssuerPendingCert = await dataFinder.getUidByFrom(tmpQueryPendingCertifsList[j].from) - if ( tmpQueryGetUidIssuerPendingCert.length > 0 ) + let tmpQueryGetUidIssuerPendingCert = await dataFinder.getUidOfPub(tmpQueryPendingCertifsList[j].from) + if (emittedBlock && tmpQueryGetUidIssuerPendingCert.length > 0) { // Récupérer la pubkey de l'émetteur let issuerPubkey = tmpQueryPendingCertifsList[j].from; @@ -186,7 +184,7 @@ module.exports = async (req: any, res: any, next: any) => { // Vérifier si le blockstamp est correct var validBlockStamp = false; - if (typeof(emittedBlock[0]) != 'undefined' && emittedBlock[0].hash == tmpQueryPendingCertifsList[j].block_hash) + if (emittedBlock.hash == tmpQueryPendingCertifsList[j].block_hash) { validBlockStamp = true; } // récupérer le timestamp d'enchainement de la dernière certification écrite par l'émetteur @@ -216,7 +214,7 @@ module.exports = async (req: any, res: any, next: any) => { wotb_id: wotb_id, issuerIsSentry: issuerIsSentry, blockNumber: tmpQueryPendingCertifsList[j].block_number, - creationTimestamp: emittedBlock[0].medianTime, + creationTimestamp: emittedBlock.medianTime, timestampExpire: tmpQueryPendingCertifsList[j].expires_on, timestampWritable: certTimestampWritable, validBlockStamp: validBlockStamp @@ -564,20 +562,21 @@ interface WillMemberIdentityWithPendingCerts extends WillMemberIdentity { class DataFinder { + private memBlocks: { [k: number]: any } = {} + private memCertsToTarget: { [k: number]: any } = {} + private memUidFromPub: { [k: number]: any } = {} + private memWotbIdFromPub: { [k: number]: any } = {} + constructor(protected duniterServer: Server) { } findPendingMembers() { - return this.duniterServer.dal.peerDAL.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on`,`revocation_sig` FROM identities_pending WHERE `member`=0') + return this.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on`,`revocation_sig` FROM identities_pending WHERE `member`=0') } findPendingCertsToTarget(toPubkey: string, hash: string) { - return this.duniterServer.dal.peerDAL.query( - 'SELECT `from`,`block_number`,`block_hash`,`expires_on` FROM certifications_pending WHERE `to`=\''+toPubkey+'\' AND `target`=\''+hash+'\' ORDER BY `expires_on` DESC') - } - - getBlockMedianTimeAndHash(idtyBlockNumber: string) { - return this.duniterServer.dal.peerDAL.query('SELECT `medianTime`,`hash` FROM block WHERE `number`=\''+idtyBlockNumber+'\' AND fork=0 LIMIT 1') + return DataFinder.getFromCacheOrDB(this.memCertsToTarget, [toPubkey, hash].join('-'), () => this.query( + 'SELECT `from`,`block_number`,`block_hash`,`expires_on` FROM certifications_pending WHERE `to`=\''+toPubkey+'\' AND `target`=\''+hash+'\' ORDER BY `expires_on` DESC')) } getWotexInfos(uid: string) { @@ -586,23 +585,41 @@ class DataFinder { 'UNION ALL ' + 'SELECT hash, uid, pubkey as pub, (SELECT NULL) AS wotb_id FROM idty WHERE uid = ?', [uid, uid]) } - getBlockMedianTimeAndHash2(block_number: number) { - return this.duniterServer.dal.peerDAL.query('SELECT `hash`,`medianTime` FROM block WHERE `number`=\''+block_number+'\' AND `fork`=0 LIMIT 1') + async getBlockMedianTimeAndHash(block_number: number): Promise<{ hash: string, medianTime: number }|undefined> { + return (await DataFinder.getFromCacheOrDB(this.memBlocks, String(block_number),() => this.duniterServer.dal.getBlock(block_number))) || undefined } - getUidByFrom(from: string) { - return this.duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+from+'\' LIMIT 1') + getUidOfPub(pub: string): Promise<{ uid: string }[]> { + return DataFinder.getFromCacheOrDB(this.memUidFromPub, pub, () => this.query('SELECT `uid` FROM i_index WHERE `pub`=\''+pub+'\' LIMIT 1')) } async getWotbIdByIssuerPubkey(issuerPubkey: string) { - return (await this.duniterServer.dal.iindexDAL.query('SELECT wotb_id FROM i_index WHERE pub = ? AND wotb_id IS NOT NULL', [issuerPubkey]))[0].wotb_id + return DataFinder.getFromCacheOrDB(this.memWotbIdFromPub, issuerPubkey, async () => (await this.duniterServer.dal.iindexDAL.query('SELECT wotb_id FROM i_index WHERE pub = ? AND wotb_id IS NOT NULL', [issuerPubkey]))[0].wotb_id) } getChainableOnByIssuerPubkey(issuerPubkey: string) { - return this.duniterServer.dal.peerDAL.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+issuerPubkey+'\' ORDER BY `chainable_on` DESC LIMIT 1') + return this.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+issuerPubkey+'\' ORDER BY `chainable_on` DESC LIMIT 1') } getCurrentBlockOrNull() { - return this.duniterServer.dal.peerDAL.query('SELECT `medianTime`,`number`,`hash`,`membersCount` FROM block ORDER BY `medianTime` DESC LIMIT 1 ') + return this.duniterServer.dal.getCurrentBlockOrNull() + } + + query(sql: string, params?: any[]) { + return this.duniterServer.dal.peerDAL.query(sql, params || []) + } + + static async getFromCacheOrDB<T>(cache: { [k: string]: any }, key: string, fetcher: () => Promise<T>) { + if (cache[key]) { + return cache[key] + } + return cache[key] = await fetcher() + } + + invalidateCache() { + this.memBlocks = {} + this.memCertsToTarget = {} + this.memUidFromPub = {} + this.memWotbIdFromPub = {} } }