UNPKG

envio

Version:

A latency and sync speed optimized, developer friendly blockchain data indexer.

183 lines (172 loc) 6.16 kB
// Generated by ReScript, PLEASE EDIT WITH CARE import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js"; function reorgDetectedToLogParams(reorgDetected, shouldRollbackOnReorg) { let scannedBlock = reorgDetected.scannedBlock; return { msg: `Blockchain reorg detected. ` + ( shouldRollbackOnReorg ? "Initiating indexer rollback" : "NOT initiating indexer rollback due to configuration" ) + `.`, blockNumber: scannedBlock.blockNumber, indexedBlockHash: scannedBlock.blockHash, receivedBlockHash: reorgDetected.receivedBlock.blockHash }; } function make(chainReorgCheckpoints, maxReorgDepth, shouldRollbackOnReorg) { let dataByBlockNumber = {}; chainReorgCheckpoints.forEach(block => { dataByBlockNumber[block.block_number] = { blockHash: block.block_hash, blockNumber: block.block_number }; }); return { shouldRollbackOnReorg: shouldRollbackOnReorg, maxReorgDepth: maxReorgDepth, dataByBlockNumber: dataByBlockNumber }; } function getDataByBlockNumberCopyInThreshold(param, knownHeight) { let dataByBlockNumber = param.dataByBlockNumber; let ascBlockNumberKeys = Object.keys(dataByBlockNumber); let thresholdBlockNumber = knownHeight - param.maxReorgDepth | 0; let copy = {}; for (let idx = 0, idx_finish = ascBlockNumberKeys.length; idx < idx_finish; ++idx) { let blockNumberKey = ascBlockNumberKeys[idx]; let scannedBlock = dataByBlockNumber[blockNumberKey]; let isInReorgThreshold = scannedBlock.blockNumber >= thresholdBlockNumber; if (isInReorgThreshold) { copy[blockNumberKey] = scannedBlock; } } return copy; } function registerReorgGuard(self, blockHashes, knownHeight) { let maxReorgDepth = self.maxReorgDepth; let shouldRollbackOnReorg = self.shouldRollbackOnReorg; let dataByBlockNumberCopyInThreshold = getDataByBlockNumberCopyInThreshold(self, knownHeight); let thresholdBlockNumber = knownHeight - maxReorgDepth | 0; let maybeReorgDetected; let idx = 0; while (maybeReorgDetected === undefined && idx < blockHashes.length) { let receivedBlock = blockHashes[idx]; if (receivedBlock.blockNumber >= thresholdBlockNumber) { let key = receivedBlock.blockNumber.toString(); let scannedBlock = dataByBlockNumberCopyInThreshold[key]; if (scannedBlock !== undefined && scannedBlock.blockHash !== receivedBlock.blockHash) { maybeReorgDetected = { scannedBlock: scannedBlock, receivedBlock: receivedBlock }; } else { dataByBlockNumberCopyInThreshold[key] = receivedBlock; } } idx = idx + 1 | 0; }; let reorgDetected = maybeReorgDetected; if (reorgDetected !== undefined) { return [ shouldRollbackOnReorg ? self : make([], maxReorgDepth, shouldRollbackOnReorg), { TAG: "ReorgDetected", _0: reorgDetected } ]; } else { return [ { shouldRollbackOnReorg: shouldRollbackOnReorg, maxReorgDepth: maxReorgDepth, dataByBlockNumber: dataByBlockNumberCopyInThreshold }, "NoReorg" ]; } } function getLatestValidScannedBlock(reorgDetection, blockNumbersAndHashes) { let verifiedDataByBlockNumber = {}; for (let idx = 0, idx_finish = blockNumbersAndHashes.length; idx < idx_finish; ++idx) { let blockData = blockNumbersAndHashes[idx]; verifiedDataByBlockNumber[blockData.blockNumber.toString()] = blockData; } let ascBlockNumberKeys = Object.keys(verifiedDataByBlockNumber); let getPrevScannedBlockNumber = idx => Stdlib_Option.map(ascBlockNumberKeys[idx - 1 | 0], key => verifiedDataByBlockNumber[key].blockNumber); let _idx = 0; while (true) { let idx$1 = _idx; let blockNumberKey = ascBlockNumberKeys[idx$1]; if (blockNumberKey === undefined) { return getPrevScannedBlockNumber(idx$1); } let scannedBlock = reorgDetection.dataByBlockNumber[blockNumberKey]; if (scannedBlock === undefined) { return getPrevScannedBlockNumber(idx$1); } if (verifiedDataByBlockNumber[blockNumberKey].blockHash !== scannedBlock.blockHash) { return getPrevScannedBlockNumber(idx$1); } _idx = idx$1 + 1 | 0; continue; }; } function rollbackToValidBlockNumber(param, blockNumber) { let dataByBlockNumber = param.dataByBlockNumber; let ascBlockNumberKeys = Object.keys(dataByBlockNumber); let newDataByBlockNumber = {}; let loop = _idx => { while (true) { let idx = _idx; let blockNumberKey = ascBlockNumberKeys[idx]; if (blockNumberKey === undefined) { return; } let scannedBlock = dataByBlockNumber[blockNumberKey]; let shouldKeep = scannedBlock.blockNumber <= blockNumber; if (!shouldKeep) { return; } newDataByBlockNumber[blockNumberKey] = scannedBlock; _idx = idx + 1 | 0; continue; }; }; loop(0); return { shouldRollbackOnReorg: param.shouldRollbackOnReorg, maxReorgDepth: param.maxReorgDepth, dataByBlockNumber: newDataByBlockNumber }; } function getThresholdBlockNumbersBelowBlock(self, blockNumber, knownHeight) { let arr = []; let ascBlockNumberKeys = Object.keys(self.dataByBlockNumber); let thresholdBlockNumber = knownHeight - self.maxReorgDepth | 0; for (let idx = 0, idx_finish = ascBlockNumberKeys.length; idx < idx_finish; ++idx) { let blockNumberKey = ascBlockNumberKeys[idx]; let scannedBlock = self.dataByBlockNumber[blockNumberKey]; let isInReorgThreshold = scannedBlock.blockNumber >= thresholdBlockNumber; if (isInReorgThreshold && scannedBlock.blockNumber < blockNumber) { arr.push(scannedBlock.blockNumber); } } return arr; } function getHashByBlockNumber(reorgDetection, blockNumber) { let v = reorgDetection.dataByBlockNumber[blockNumber]; if (v !== undefined) { return v.blockHash; } else { return null; } } export { reorgDetectedToLogParams, make, getDataByBlockNumberCopyInThreshold, registerReorgGuard, getLatestValidScannedBlock, rollbackToValidBlockNumber, getThresholdBlockNumbersBelowBlock, getHashByBlockNumber, } /* No side effect */