Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion yarn-project/aztec-node/src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createArchiver } from '@aztec/archiver';
import { BBCircuitVerifier, BatchChonkVerifier, QueuedIVCVerifier } from '@aztec/bb-prover';
import { TestCircuitVerifier } from '@aztec/bb-prover/test';
import { createBlobClientWithFileStores } from '@aztec/blob-client/client';
import { Blob } from '@aztec/blob-lib';
import { Blob, getKzg } from '@aztec/blob-lib';
import { EpochCache } from '@aztec/epoch-cache';
import { createEthereumChain } from '@aztec/ethereum/chain';
import { getPublicClient, makeL1HttpTransport } from '@aztec/ethereum/client';
Expand Down Expand Up @@ -94,6 +94,15 @@ export async function createAztecNodeService(
const { BarretenbergSync } = await import('@aztec/bb.js');
await BarretenbergSync.initSingleton();

// Warm the KZG trusted-setup singleton before any subsystem runs. getKzg() synchronously builds
// its precomputation tables on first use (~2s locally, blocking the event loop; 12-15s under
// production CPU limits). If that first use is instead the archiver reconstructing blobs or the
// proposal handler uploading them, the stalled loop overruns the gossipsub mcache window and
// attestation forwarding is skipped. Paying it here keeps it off the gossip path. Idempotent, so
// it is a no-op for sequencers (warmed in Sequencer.init) and for tests that pre-warm via
// warmBlobKzg.
getKzg(log);

const packageVersion = getPackageVersion();
const telemetry = deps.telemetry ?? getTelemetryClient();
const dateProvider = deps.dateProvider ?? new DateProvider();
Expand Down
16 changes: 12 additions & 4 deletions yarn-project/blob-lib/src/kzg_context.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import type { Logger } from '@aztec/foundation/log';
import { elapsedSync } from '@aztec/foundation/timer';

import type { DasContextJs } from '@crate-crypto/node-eth-kzg';
import { createRequire } from 'module';

Expand Down Expand Up @@ -30,12 +33,17 @@ export function getBytesPerCommitment(): number {
let kzgInstance: DasContextJs | undefined;

/**
* Returns the lazily-initialized KZG context.
* The first call takes ~3 seconds to initialize the precomputation tables.
* Returns the lazily-initialized KZG context. The first call synchronously builds the
* precomputation tables (~2s locally, blocking the event loop; longer under constrained CPU), so
* callers on a latency-sensitive path should warm it ahead of time. Pass a logger to record how
* long that first build took.
* @param logger - Optional logger; when provided, the initial table build is timed and logged.
*/
export function getKzg(): DasContextJs {
export function getKzg(logger?: Logger): DasContextJs {
if (!kzgInstance) {
kzgInstance = loadNativeModule().DasContextJs.create({ usePrecomp: true });
const [durationMs, instance] = elapsedSync(() => loadNativeModule().DasContextJs.create({ usePrecomp: true }));
kzgInstance = instance;
logger?.verbose(`Loaded KZG trusted setup`, { durationMs });
}
return kzgInstance;
}
Loading