github.com/ethereum-optimism/optimism@v1.7.2/packages/chain-mon/src/fault-mon/helpers.ts (about)

     1  import { Contract } from 'ethers'
     2  import { Logger } from '@eth-optimism/common-ts'
     3  import { BedrockOutputData } from '@eth-optimism/core-utils'
     4  
     5  /**
     6   * Finds the BedrockOutputData that corresponds to a given output index.
     7   *
     8   * @param oracle Output oracle contract
     9   * @param index Output index to search for.
    10   * @returns BedrockOutputData corresponding to the output index.
    11   */
    12  export const findOutputForIndex = async (
    13    oracle: Contract,
    14    index: number,
    15    logger?: Logger
    16  ): Promise<BedrockOutputData> => {
    17    try {
    18      const proposal = await oracle.getL2Output(index)
    19      return {
    20        outputRoot: proposal.outputRoot,
    21        l1Timestamp: proposal.timestamp.toNumber(),
    22        l2BlockNumber: proposal.l2BlockNumber.toNumber(),
    23        l2OutputIndex: index,
    24      }
    25    } catch (err) {
    26      logger?.fatal('error when calling L2OuputOracle.getL2Output', {
    27        errors: err,
    28      })
    29      throw new Error(`unable to find output for index ${index}`)
    30    }
    31  }
    32  
    33  /**
    34   * Finds the first L2 output index that has not yet passed the fault proof window.
    35   *
    36   * @param oracle Output oracle contract.
    37   * @returns Starting L2 output index.
    38   */
    39  export const findFirstUnfinalizedOutputIndex = async (
    40    oracle: Contract,
    41    fpw: number,
    42    logger?: Logger
    43  ): Promise<number> => {
    44    const latestBlock = await oracle.provider.getBlock('latest')
    45    const totalOutputs = (await oracle.nextOutputIndex()).toNumber()
    46  
    47    // Perform a binary search to find the next batch that will pass the challenge period.
    48    let lo = 0
    49    let hi = totalOutputs
    50    while (lo !== hi) {
    51      const mid = Math.floor((lo + hi) / 2)
    52      const outputData = await findOutputForIndex(oracle, mid, logger)
    53  
    54      if (outputData.l1Timestamp + fpw < latestBlock.timestamp) {
    55        lo = mid + 1
    56      } else {
    57        hi = mid
    58      }
    59    }
    60  
    61    // Result will be zero if the chain is less than FPW seconds old. Only returns undefined in the
    62    // case that no batches have been submitted for an entire challenge period.
    63    if (lo === totalOutputs) {
    64      return undefined
    65    } else {
    66      return lo
    67    }
    68  }