Skip to content

Commit

Permalink
Handle merge query correctly with reorgs
Browse files Browse the repository at this point in the history
  • Loading branch information
DZakh committed Dec 27, 2024
1 parent 3c5c859 commit 4f43c5a
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 193 deletions.
56 changes: 32 additions & 24 deletions codegenerator/cli/npm/envio/src/ReorgDetection.res
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ type blockData = {
blockTimestamp: int,
}

type reorgGuard = {
lastBlockScannedData: blockData,
firstBlockParentNumberAndHash: option<blockNumberAndHash>,
}

module LastBlockScannedHashes: {
type t
/**Instantiat t with existing data*/
Expand Down Expand Up @@ -69,7 +74,7 @@ module LastBlockScannedHashes: {

let getAllBlockNumbers: t => Belt.Array.t<int>

let hasReorgOccurred: (t, ~firstBlockParentNumberAndHash: option<blockNumberAndHash>) => bool
let hasReorgOccurred: (t, ~reorgGuard: reorgGuard) => bool

/**
Return a BlockNumbersAndHashes.t rolled back to where blockData is less
Expand Down Expand Up @@ -402,31 +407,34 @@ module LastBlockScannedHashes: {
/**
Checks whether reorg has occured by comparing the parent hash with the last saved block hash.
*/
let rec hasReorgOccurredInternal = (
lastBlockScannedDataList,
~firstBlockParentNumberAndHash: option<blockNumberAndHash>,
) => {
switch (firstBlockParentNumberAndHash, lastBlockScannedDataList) {
| (Some({blockHash: parentHash, blockNumber: parentBlockNumber}), list{head, ...tail}) =>
if parentBlockNumber == head.blockNumber {
parentHash != head.blockHash
} else {
//if block numbers do not match, this is a dynamic contract case and should recurse
//through the list to look for a matching block or nothing to validate
tail->hasReorgOccurredInternal(~firstBlockParentNumberAndHash)
}
| _ => //If parentHash is None, either it's the genesis block (no reorg)
let rec hasReorgOccurredInternal = (lastBlockScannedDataList, ~reorgGuard: reorgGuard) => {
switch lastBlockScannedDataList {
| list{head, ...tail} =>
switch reorgGuard {
| {lastBlockScannedData} if lastBlockScannedData.blockNumber == head.blockNumber =>
lastBlockScannedData.blockHash != head.blockHash
//If parentHash is None, either it's the genesis block (no reorg)
//Or its already confirmed so no Reorg
//If recentLastBlockData is None, we have not yet saved blockData to compare against
false
| {firstBlockParentNumberAndHash: None} => false
| {
firstBlockParentNumberAndHash: Some({
blockHash: parentHash,
blockNumber: parentBlockNumber,
}),
} =>
if parentBlockNumber == head.blockNumber {
parentHash != head.blockHash
} else {
//if block numbers do not match, this is a dynamic contract case and should recurse
//through the list to look for a matching block or nothing to validate
tail->hasReorgOccurredInternal(~reorgGuard)
}
}
//If recentLastBlockData is None, we have not yet saved blockData to compare against
| _ => false
}
}

let hasReorgOccurred = (
lastBlockScannedHashes: t,
~firstBlockParentNumberAndHash: option<blockNumberAndHash>,
) =>
lastBlockScannedHashes.lastBlockScannedDataList->hasReorgOccurredInternal(
~firstBlockParentNumberAndHash,
)
let hasReorgOccurred = (lastBlockScannedHashes: t, ~reorgGuard: reorgGuard) =>
lastBlockScannedHashes.lastBlockScannedDataList->hasReorgOccurredInternal(~reorgGuard)
}
3 changes: 3 additions & 0 deletions codegenerator/cli/npm/envio/src/Utils.res
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ Helper to check if a value exists in an array
})
interleaved
}

@send
external flatten: (array<array<'a>>, @as(json`1`) _) => array<'a> = "flat"
}

module String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,12 @@ type blockRangeFetchStats = {
@as("page fetch time (ms)") pageFetchTime?: int,
}

type reorgGuard = {
lastBlockScannedData: ReorgDetection.blockData,
firstBlockParentNumberAndHash: option<ReorgDetection.blockNumberAndHash>,
}

/**
Thes response returned from a block range fetch
*/
type blockRangeFetchResponse = {
currentBlockHeight: int,
reorgGuard: reorgGuard,
reorgGuard: ReorgDetection.reorgGuard,
parsedQueueItems: array<Internal.eventItem>,
fromBlockQueried: int,
latestFetchedBlockNumber: int,
Expand Down Expand Up @@ -107,3 +102,42 @@ let fetchBlockRange = (
~isPreRegisteringDynamicContracts,
)
}

let fetchBlockRangeUntilToBlock = (
chainWorker,
~fromBlock,
~toBlock,
~contractAddressMapping,
~partitionId,
~chain,
~currentBlockHeight,
~shouldApplyWildcards,
~isPreRegisteringDynamicContracts,
~logger,
) => {
ErrorHandling.ResultPropogateEnv.runAsyncEnv(async () => {
let responses = []
let fromBlock = ref(fromBlock)

while fromBlock.contents <= toBlock {
let response =
(await chainWorker
->fetchBlockRange(
~fromBlock=fromBlock.contents,
~toBlock=Some(toBlock),
~contractAddressMapping,
~partitionId,
~chain,
~currentBlockHeight,
~shouldApplyWildcards,
~isPreRegisteringDynamicContracts,
~logger,
))
->ErrorHandling.ResultPropogateEnv.propogate
fromBlock := response.latestFetchedBlockNumber + 1
responses->Array.push(response)
}

Ok(responses)
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ module Make = (

let lastBlockScannedData = await lastBlockQueriedPromise

let reorgGuard = {
let reorgGuard: ReorgDetection.reorgGuard = {
lastBlockScannedData,
firstBlockParentNumberAndHash: Some({
ReorgDetection.blockHash: lastBlockScannedData.blockHash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ module Make = (

let lastBlockScannedData = await lastBlockQueriedPromise

let reorgGuard = {
let reorgGuard: ReorgDetection.reorgGuard = {
lastBlockScannedData,
firstBlockParentNumberAndHash: pageUnsafe.rollbackGuard->Option.map(v => {
ReorgDetection.blockHash: v.firstParentHash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ module Make = (
let totalTimeElapsed =
startFetchingBatchTimeRef->Hrtime.timeSince->Hrtime.toMillis->Hrtime.intFromMillis

let reorgGuard: reorgGuard = {
let reorgGuard: ReorgDetection.reorgGuard = {
firstBlockParentNumberAndHash: optFirstBlockParent->Option.map(b => {
ReorgDetection.blockNumber: b.number,
blockHash: b.hash,
Expand Down
Loading

0 comments on commit 4f43c5a

Please sign in to comment.