diff --git a/yarn-project/archiver/src/modules/l1_synchronizer.ts b/yarn-project/archiver/src/modules/l1_synchronizer.ts index 092df4b083f8..33afde395721 100644 --- a/yarn-project/archiver/src/modules/l1_synchronizer.ts +++ b/yarn-project/archiver/src/modules/l1_synchronizer.ts @@ -3,6 +3,7 @@ import { EpochCache } from '@aztec/epoch-cache'; import { InboxContract, RollupContract } from '@aztec/ethereum/contracts'; import type { L1BlockId } from '@aztec/ethereum/l1-types'; import type { ViemPublicClient, ViemPublicDebugClient } from '@aztec/ethereum/types'; +import { asyncPool } from '@aztec/foundation/async-pool'; import { maxBigint } from '@aztec/foundation/bigint'; import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types'; import { Buffer32 } from '@aztec/foundation/buffer'; @@ -333,17 +334,20 @@ export class ArchiverL1Synchronizer implements Traceable { const checkpointsToUnwind = localPendingCheckpointNumber - provenCheckpointNumber; - const checkpointPromises = Array.from({ length: checkpointsToUnwind }) - .fill(0) - .map((_, i) => this.store.getCheckpointData(CheckpointNumber(i + pruneFrom))); - const checkpoints = await Promise.all(checkpointPromises); - - const blockPromises = await Promise.all( - checkpoints - .filter(isDefined) - .map(cp => this.store.getBlocksForCheckpoint(CheckpointNumber(cp.checkpointNumber))), + // Fetch checkpoints and blocks in bounded batches to avoid unbounded concurrent + // promises when the gap between local pending and proven checkpoint numbers is large. + const BATCH_SIZE = 10; + const indices = Array.from({ length: checkpointsToUnwind }, (_, i) => CheckpointNumber(i + pruneFrom)); + const checkpoints = (await asyncPool(BATCH_SIZE, indices, idx => this.store.getCheckpointData(idx))).filter( + isDefined, ); - const newBlocks = blockPromises.filter(isDefined).flat(); + const newBlocks = ( + await asyncPool(BATCH_SIZE, checkpoints, cp => + this.store.getBlocksForCheckpoint(CheckpointNumber(cp.checkpointNumber)), + ) + ) + .filter(isDefined) + .flat(); // Emit an event for listening services to react to the chain prune this.events.emit(L2BlockSourceEvents.L2PruneUnproven, {