Skip to content

Commit

Permalink
fix: Handle proofs for blocks submitted out of range (#8357)
Browse files Browse the repository at this point in the history
`prover-stats` was throwing an error when querying with a start-block
that was not the start of the chain, since it'd look up for the
submission time of the L2 block for a proof, but would not find it
because it was out of range.
  • Loading branch information
spalladino authored Sep 3, 2024
1 parent 0c116b5 commit 9934adb
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 19 deletions.
44 changes: 29 additions & 15 deletions yarn-project/cli/src/cmds/l1/prover_stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getL2BlockProcessedLogs, retrieveL2ProofVerifiedEvents } from '@aztec/a
import { createAztecNodeClient } from '@aztec/circuit-types';
import { EthAddress } from '@aztec/circuits.js';
import { createEthereumChain } from '@aztec/ethereum';
import { unique } from '@aztec/foundation/collection';
import { compactArray, mapValues, unique } from '@aztec/foundation/collection';
import { type LogFn, type Logger, createDebugLogger } from '@aztec/foundation/log';

import chunk from 'lodash.chunk';
Expand Down Expand Up @@ -65,6 +65,9 @@ export async function proverStats(opts: {

// But if we do, fetch the events for each block submitted, so we can look up their timestamp
const blockEvents = await getL2BlockEvents(startBlock, lastBlockNum, batchSize, debugLog, publicClient, rollup);
debugLog.verbose(
`First L2 block within range is ${blockEvents[0]?.args.blockNumber} at L1 block ${blockEvents[0]?.blockNumber}`,
);

// Get the timestamps for every block on every log, both for proof and block submissions
const l1BlockNumbers = unique([...events.map(e => e.l1BlockNumber), ...blockEvents.map(e => e.blockNumber)]);
Expand All @@ -86,24 +89,35 @@ export async function proverStats(opts: {
}

// Now calculate stats
const stats = groupBy(events, 'proverId');
const stats = mapValues(groupBy(events, 'proverId'), (blocks, proverId) =>
compactArray(
blocks.map(e => {
const provenTimestamp = l1BlockTimestamps[e.l1BlockNumber.toString()];
const uploadedBlockNumber = l2BlockSubmissions[e.l2BlockNumber.toString()];
if (!uploadedBlockNumber) {
debugLog.verbose(
`Skipping ${proverId}'s proof for L2 block ${e.l2BlockNumber} as it was before the start block`,
);
return undefined;
}
const uploadedTimestamp = l1BlockTimestamps[uploadedBlockNumber.toString()];
const provingTime = provenTimestamp - uploadedTimestamp;
debugLog.debug(
`prover=${e.proverId} blockNumber=${e.l2BlockNumber} uploaded=${uploadedTimestamp} proven=${provenTimestamp} time=${provingTime}`,
);
return { provenTimestamp, uploadedTimestamp, provingTime, ...e };
}),
),
);

log(`prover_id, blocks_proven_within_timeout, total_blocks_proven, avg_proving_time`);
for (const proverId in stats) {
const blocks = stats[proverId].map(e => {
const provenTimestamp = l1BlockTimestamps[e.l1BlockNumber.toString()];
const uploadedBlockNumber = l2BlockSubmissions[e.l2BlockNumber.toString()];
const uploadedTimestamp = l1BlockTimestamps[uploadedBlockNumber.toString()];
const provingTime = provenTimestamp - uploadedTimestamp;
debugLog.debug(
`prover=${e.proverId} blockNumber=${e.l2BlockNumber} uploaded=${uploadedTimestamp} proven=${provenTimestamp} time=${provingTime}`,
);
return { provenTimestamp, uploadedTimestamp, provingTime, ...e };
});

const blocks = stats[proverId];
const withinTimeout = blocks.filter(b => b.provingTime <= provingTimeout);
const uniqueBlocksWithinTimeout = new Set(withinTimeout.map(e => e.l2BlockNumber));
const uniqueBlocks = new Set(stats[proverId].map(e => e.l2BlockNumber));
const avgProvingTime = Math.ceil(Number(blocks.reduce((acc, b) => acc + b.provingTime, 0n)) / blocks.length);
const uniqueBlocks = new Set(blocks.map(e => e.l2BlockNumber));
const avgProvingTime =
blocks.length === 0 ? 0 : Math.ceil(Number(blocks.reduce((acc, b) => acc + b.provingTime, 0n)) / blocks.length);

log(`${proverId}, ${uniqueBlocksWithinTimeout.size}, ${uniqueBlocks.size}, ${avgProvingTime}`);
}
Expand Down
8 changes: 4 additions & 4 deletions yarn-project/foundation/src/collection/object.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
/** Returns a new object with the same keys and where each value has been passed through the mapping function. */
export function mapValues<K extends string | number | symbol, T, U>(
obj: Record<K, T>,
fn: (value: T) => U,
fn: (value: T, key: K) => U,
): Record<K, U>;
export function mapValues<K extends string | number | symbol, T, U>(
obj: Partial<Record<K, T>>,
fn: (value: T) => U,
fn: (value: T, key: K) => U,
): Partial<Record<K, U>>;
export function mapValues<K extends string | number | symbol, T, U>(
obj: Record<K, T>,
fn: (value: T) => U,
fn: (value: T, key: K) => U,
): Record<K, U> {
const result: Record<K, U> = {} as Record<K, U>;
for (const key in obj) {
result[key] = fn(obj[key]);
result[key] = fn(obj[key], key);
}
return result;
}
Expand Down

0 comments on commit 9934adb

Please sign in to comment.