From 1f41b67e3b2a6f8f7ce465cf935b7207ffe47649 Mon Sep 17 00:00:00 2001 From: Ken Ellis Date: Thu, 1 Oct 2020 09:33:06 -0400 Subject: [PATCH] add internal caching for slp.tokenUtxoDetails to reduce duplicate calls --- src/slp/utils.js | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/slp/utils.js b/src/slp/utils.js index 70c7c8a..369b413 100644 --- a/src/slp/utils.js +++ b/src/slp/utils.js @@ -662,6 +662,9 @@ class Utils { * Similar to decodeOpReturn(), except decodeOpReturn2() uses the slp-parser * library maintained by JT Freeman. Outputs have slightly different format. * + * If optional associative array parameter cache is used, will cache and + * reuse responses for the same input. + * * Throws an error if given a non-SLP txid. * * In a future version of bch-js, this method will replace the origonal @@ -694,7 +697,13 @@ class Utils { * } */ // Reimplementation of decodeOpReturn() using slp-parser. - async decodeOpReturn(txid) { + async decodeOpReturn(txid, cache = null) { + if (cache) { + if (!(cache instanceof Object)) + throw new Error(`decodeOpReturn cache parameter must be Object`) + const cachedVal = cache[txid] + if (cachedVal) return cachedVal + } try { // Validate the txid input. if (!txid || txid === "" || typeof txid !== "string") @@ -745,7 +754,7 @@ class Utils { } } // console.log(`tokenData: ${JSON.stringify(tokenData, null, 2)}`) - + if (cache) cache[txid] = tokenData return tokenData } catch (error) { // console.log('decodeOpReturn error: ', error) @@ -813,6 +822,10 @@ class Utils { // CT 5/31/20: Refactored to use slp-parse library. async tokenUtxoDetails(utxos) { try { + // utxo list may have duplicate tx_hash, varying tx_pos + // only need to call decodeOpReturn once for those + const decodeOpReturnCache = {} + const cachedTxValidation = {} // Throw error if input is not an array. if (!Array.isArray(utxos)) throw new Error(`Input must be an array.`) @@ -870,7 +883,7 @@ class Utils { // If there is no OP_RETURN, mark the UTXO as false. let slpData = false try { - slpData = await this.decodeOpReturn(utxo.txid) + slpData = await this.decodeOpReturn(utxo.txid, decodeOpReturnCache) // console.log(`slpData: ${JSON.stringify(slpData, null, 2)}`) } catch (err) { // console.log(`error from decodeOpReturn(${utxo.txid}): `, err) @@ -955,7 +968,7 @@ class Utils { // If UTXO passes validation, then return formatted token data. else { - const genesisData = await this.decodeOpReturn(slpData.tokenId) + const genesisData = await this.decodeOpReturn(slpData.tokenId, decodeOpReturnCache) // console.log(`genesisData: ${JSON.stringify(genesisData, null, 2)}`) // Minting Baton @@ -1003,7 +1016,7 @@ class Utils { // If UTXO passes validation, then return formatted token data. else { - const genesisData = await this.decodeOpReturn(slpData.tokenId) + const genesisData = await this.decodeOpReturn(slpData.tokenId, decodeOpReturnCache) // console.log(`genesisData: ${JSON.stringify(genesisData, null, 2)}`) // console.log(`utxo: ${JSON.stringify(utxo, null, 2)}`) @@ -1030,7 +1043,11 @@ class Utils { // Finally, validate the SLP txid with SLPDB. if (outAry[i].tokenType) { - const isValid = await this.validateTxid(utxo.txid) + var isValid = cachedTxValidation[utxo.txid] + if (isValid == null) { + isValid = await this.validateTxid(utxo.txid) + cachedTxValidation[utxo.txid] = isValid + } // console.log(`isValid: ${JSON.stringify(isValid, null, 2)}`) outAry[i].isValid = isValid[0].valid