From 1a4343301cf6c9c73b4419b5de1d0dbaad2b9426 Mon Sep 17 00:00:00 2001 From: Bartek Date: Wed, 4 Oct 2023 16:47:04 +0200 Subject: [PATCH] perf: cache l2 block range (#343) --- package.json | 1 + src/lib/message/L2ToL1MessageNitro.ts | 64 ++++++++++++++++++++++++++- yarn.lock | 12 +++++ 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fd578fb86f..7c558b88f1 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@ethersproject/address": "^5.0.8", "@ethersproject/bignumber": "^5.1.1", "@ethersproject/bytes": "^5.0.8", + "async-mutex": "^0.4.0", "ethers": "^5.1.0" }, "devDependencies": { diff --git a/src/lib/message/L2ToL1MessageNitro.ts b/src/lib/message/L2ToL1MessageNitro.ts index 2ef4711d55..a744061ec8 100644 --- a/src/lib/message/L2ToL1MessageNitro.ts +++ b/src/lib/message/L2ToL1MessageNitro.ts @@ -32,6 +32,7 @@ import { NodeInterface__factory } from '../abi/factories/NodeInterface__factory' import { L2ToL1TxEvent } from '../abi/ArbSys' import { ContractTransaction, Overrides } from 'ethers' +import { Mutex } from 'async-mutex' import { EventFetcher, FetchedEvent } from '../utils/eventFetcher' import { ArbSdkError } from '../dataEntities/errors' import { @@ -61,6 +62,64 @@ const ASSERTION_CREATED_PADDING = 50 // expected number of L1 blocks that it takes for a validator to confirm an L1 block after the node deadline is passed const ASSERTION_CONFIRMED_PADDING = 20 +const l2BlockRangeCache: { [key in string]: (number | undefined)[] } = {} +const mutex = new Mutex() + +function getL2BlockRangeCacheKey({ + l2ChainId, + l1BlockNumber, +}: { + l2ChainId: number + l1BlockNumber: number +}) { + return `${l2ChainId}-${l1BlockNumber}` +} + +function setL2BlockRangeCache(key: string, value: (number | undefined)[]) { + l2BlockRangeCache[key] = value +} + +async function getBlockRangesForL1BlockWithCache({ + l1Provider, + l2Provider, + forL1Block, +}: { + l1Provider: JsonRpcProvider + l2Provider: JsonRpcProvider + forL1Block: number +}) { + const l2ChainId = (await l2Provider.getNetwork()).chainId + const key = getL2BlockRangeCacheKey({ + l2ChainId, + l1BlockNumber: forL1Block, + }) + + if (l2BlockRangeCache[key]) { + return l2BlockRangeCache[key] + } + + // implements a lock that only fetches cache once + const release = await mutex.acquire() + + // if cache has been acquired while awaiting the lock + if (l2BlockRangeCache[key]) { + release() + return l2BlockRangeCache[key] + } + + try { + const l2BlockRange = await getBlockRangesForL1Block({ + forL1Block, + provider: l1Provider, + }) + setL2BlockRangeCache(key, l2BlockRange) + } finally { + release() + } + + return l2BlockRangeCache[key] +} + /** * Base functionality for nitro L2->L1 messages */ @@ -212,9 +271,10 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro { // If L1 is Arbitrum, then L2 is an Orbit chain. if (await isArbitrumChain(this.l1Provider)) { try { - const l2BlockRange = await getBlockRangesForL1Block({ + const l2BlockRange = await getBlockRangesForL1BlockWithCache({ + l1Provider: this.l1Provider as JsonRpcProvider, + l2Provider: l2Provider as JsonRpcProvider, forL1Block: createdAtBlock.toNumber(), - provider: this.l1Provider as JsonRpcProvider, }) const startBlock = l2BlockRange[0] const endBlock = l2BlockRange[1] diff --git a/yarn.lock b/yarn.lock index 238f1c19df..dd40c14fe6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1723,6 +1723,13 @@ async-eventemitter@^0.2.4: dependencies: async "^2.4.0" +async-mutex@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.4.0.tgz#ae8048cd4d04ace94347507504b3cf15e631c25f" + integrity sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA== + dependencies: + tslib "^2.4.0" + async@^2.4.0: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" @@ -5192,6 +5199,11 @@ tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.4.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tslint@^6.1.3: version "6.1.3" resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904"