envio
Version:
A latency and sync speed optimized, developer friendly blockchain data indexer.
183 lines (172 loc) • 6.16 kB
JavaScript
// 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 */