envio
Version:
A latency and sync speed optimized, developer friendly blockchain data indexer.
224 lines (211 loc) • 8.23 kB
JavaScript
// Generated by ReScript, PLEASE EDIT WITH CARE
;
var Js_exn = require("rescript/lib/js/js_exn.js");
var Js_dict = require("rescript/lib/js/js_dict.js");
var Belt_Array = require("rescript/lib/js/belt_Array.js");
var Belt_Option = require("rescript/lib/js/belt_Option.js");
function reorgDetectedToLogParams(reorgDetected, shouldRollbackOnReorg) {
var 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 makeWithData(blocks, confirmedBlockThreshold, detectedReorgBlock) {
var dataByBlockNumber = {};
Belt_Array.forEach(blocks, (function (block) {
dataByBlockNumber[block.blockNumber.toString()] = block;
}));
return {
confirmedBlockThreshold: confirmedBlockThreshold,
dataByBlockNumber: dataByBlockNumber,
detectedReorgBlock: detectedReorgBlock
};
}
function empty(confirmedBlockThreshold) {
return {
confirmedBlockThreshold: confirmedBlockThreshold,
dataByBlockNumber: {},
detectedReorgBlock: undefined
};
}
function getDataByBlockNumberCopyInThreshold(param, currentBlockHeight) {
var dataByBlockNumber = param.dataByBlockNumber;
var ascBlockNumberKeys = Object.keys(dataByBlockNumber);
var thresholdBlockNumber = currentBlockHeight - param.confirmedBlockThreshold | 0;
var copy = {};
for(var idx = 0 ,idx_finish = ascBlockNumberKeys.length; idx < idx_finish; ++idx){
var blockNumberKey = ascBlockNumberKeys[idx];
var scannedBlock = dataByBlockNumber[blockNumberKey];
var isInReorgThreshold = scannedBlock.blockNumber >= thresholdBlockNumber;
if (isInReorgThreshold) {
copy[blockNumberKey] = scannedBlock;
}
}
return copy;
}
function registerReorgGuard(self, reorgGuard, currentBlockHeight, shouldRollbackOnReorg) {
var confirmedBlockThreshold = self.confirmedBlockThreshold;
var dataByBlockNumberCopyInThreshold = getDataByBlockNumberCopyInThreshold(self, currentBlockHeight);
var prevRangeLastBlock = reorgGuard.prevRangeLastBlock;
var rangeLastBlock = reorgGuard.rangeLastBlock;
var scannedBlock = dataByBlockNumberCopyInThreshold[String(rangeLastBlock.blockNumber)];
var maybeReorgDetected;
var exit = 0;
if (scannedBlock !== undefined && scannedBlock.blockHash !== rangeLastBlock.blockHash) {
maybeReorgDetected = {
scannedBlock: scannedBlock,
receivedBlock: rangeLastBlock
};
} else {
exit = 1;
}
if (exit === 1) {
if (prevRangeLastBlock !== undefined) {
var scannedBlock$1 = dataByBlockNumberCopyInThreshold[String(prevRangeLastBlock.blockNumber)];
maybeReorgDetected = scannedBlock$1 !== undefined && scannedBlock$1.blockHash !== prevRangeLastBlock.blockHash ? ({
scannedBlock: scannedBlock$1,
receivedBlock: prevRangeLastBlock
}) : undefined;
} else {
maybeReorgDetected = undefined;
}
}
if (maybeReorgDetected !== undefined) {
return [
shouldRollbackOnReorg ? ({
confirmedBlockThreshold: self.confirmedBlockThreshold,
dataByBlockNumber: self.dataByBlockNumber,
detectedReorgBlock: maybeReorgDetected.scannedBlock
}) : empty(confirmedBlockThreshold),
{
TAG: "ReorgDetected",
_0: maybeReorgDetected
}
];
} else {
dataByBlockNumberCopyInThreshold[String(rangeLastBlock.blockNumber)] = rangeLastBlock;
if (prevRangeLastBlock !== undefined) {
dataByBlockNumberCopyInThreshold[String(prevRangeLastBlock.blockNumber)] = prevRangeLastBlock;
}
return [
{
confirmedBlockThreshold: confirmedBlockThreshold,
dataByBlockNumber: dataByBlockNumberCopyInThreshold,
detectedReorgBlock: undefined
},
"NoReorg"
];
}
}
function getLatestValidScannedBlock(self, blockNumbersAndHashes, currentBlockHeight, skipReorgDuplicationCheckOpt) {
var skipReorgDuplicationCheck = skipReorgDuplicationCheckOpt !== undefined ? skipReorgDuplicationCheckOpt : false;
var verifiedDataByBlockNumber = {};
for(var idx = 0 ,idx_finish = blockNumbersAndHashes.length; idx < idx_finish; ++idx){
var blockData = blockNumbersAndHashes[idx];
verifiedDataByBlockNumber[String(blockData.blockNumber)] = blockData;
}
var isAlreadyReorgedResponse;
if (skipReorgDuplicationCheck) {
isAlreadyReorgedResponse = false;
} else {
var detectedReorgBlock = self.detectedReorgBlock;
if (detectedReorgBlock !== undefined) {
var verifiedBlockData = verifiedDataByBlockNumber[String(detectedReorgBlock.blockNumber)];
isAlreadyReorgedResponse = verifiedBlockData !== undefined ? verifiedBlockData.blockHash === detectedReorgBlock.blockHash : false;
} else {
isAlreadyReorgedResponse = false;
}
}
if (isAlreadyReorgedResponse) {
return {
TAG: "Error",
_0: "AlreadyReorgedHashes"
};
}
var dataByBlockNumber = getDataByBlockNumberCopyInThreshold(self, currentBlockHeight);
var ascBlockNumberKeys = Object.keys(dataByBlockNumber);
var getPrevScannedBlock = function (idx) {
var data = Belt_Option.flatMap(Belt_Array.get(ascBlockNumberKeys, idx - 1 | 0), (function (key) {
return verifiedDataByBlockNumber[key];
}));
if (data !== undefined) {
return {
TAG: "Ok",
_0: data
};
} else {
return {
TAG: "Error",
_0: "NotFound"
};
}
};
var _idx = 0;
while(true) {
var idx$1 = _idx;
var blockNumberKey = Belt_Array.get(ascBlockNumberKeys, idx$1);
if (blockNumberKey === undefined) {
return getPrevScannedBlock(idx$1);
}
var scannedBlock = dataByBlockNumber[blockNumberKey];
var verifiedBlockData$1 = verifiedDataByBlockNumber[blockNumberKey];
if (verifiedBlockData$1 === undefined) {
return Js_exn.raiseError("Unexpected case. Couldn't find verified hash for block number " + blockNumberKey);
}
if (verifiedBlockData$1.blockHash !== scannedBlock.blockHash) {
return getPrevScannedBlock(idx$1);
}
_idx = idx$1 + 1 | 0;
continue ;
};
}
function rollbackToValidBlockNumber(param, blockNumber) {
var dataByBlockNumber = param.dataByBlockNumber;
var ascBlockNumberKeys = Object.keys(dataByBlockNumber);
var newDataByBlockNumber = {};
var loop = function (_idx) {
while(true) {
var idx = _idx;
var blockNumberKey = Belt_Array.get(ascBlockNumberKeys, idx);
if (blockNumberKey === undefined) {
return ;
}
var scannedBlock = dataByBlockNumber[blockNumberKey];
var shouldKeep = scannedBlock.blockNumber <= blockNumber;
if (!shouldKeep) {
return ;
}
newDataByBlockNumber[blockNumberKey] = scannedBlock;
_idx = idx + 1 | 0;
continue ;
};
};
loop(0);
return {
confirmedBlockThreshold: param.confirmedBlockThreshold,
dataByBlockNumber: newDataByBlockNumber,
detectedReorgBlock: undefined
};
}
function getThresholdBlockNumbers(self, currentBlockHeight) {
var dataByBlockNumberCopyInThreshold = getDataByBlockNumberCopyInThreshold(self, currentBlockHeight);
return Js_dict.values(dataByBlockNumberCopyInThreshold).map(function (v) {
return v.blockNumber;
});
}
var LastBlockScannedHashes = {
makeWithData: makeWithData,
empty: empty,
registerReorgGuard: registerReorgGuard,
getLatestValidScannedBlock: getLatestValidScannedBlock,
getThresholdBlockNumbers: getThresholdBlockNumbers,
rollbackToValidBlockNumber: rollbackToValidBlockNumber
};
exports.reorgDetectedToLogParams = reorgDetectedToLogParams;
exports.LastBlockScannedHashes = LastBlockScannedHashes;
/* No side effect */