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 }