diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 305a89874f0d..e79d48becd46 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -1,3 +1,4 @@ +import { type BlobSinkClientInterface } from '@aztec/blob-sink/client'; import { InboxLeaf, type L1RollupConstants, L2Block } from '@aztec/circuit-types'; import { GENESIS_ARCHIVE_ROOT, PrivateLog } from '@aztec/circuits.js'; import { DefaultL1ContractsConfig } from '@aztec/ethereum'; @@ -53,6 +54,7 @@ describe('Archiver', () => { let publicClient: MockProxy>; let instrumentation: MockProxy; + let blobSinkClient: MockProxy; let archiverStore: ArchiverDataStore; let now: number; let l1Constants: L1RollupConstants; @@ -92,6 +94,7 @@ describe('Archiver', () => { ); }) as any, }); + blobSinkClient = mock(); const tracer = new NoopTelemetryClient().getTracer(); instrumentation = mock({ isEnabled: () => true, tracer }); @@ -109,6 +112,7 @@ describe('Archiver', () => { { rollupAddress, inboxAddress, registryAddress }, archiverStore, { pollingIntervalMs: 1000, batchSize: 1000 }, + blobSinkClient, instrumentation, l1Constants, ); diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 049e87733226..7cdab4b031d3 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -1,3 +1,4 @@ +import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client'; import { type GetUnencryptedLogsResponse, type InBlock, @@ -51,6 +52,7 @@ import { } from '@aztec/protocol-contracts/class-registerer'; import { ContractInstanceDeployedEvent } from '@aztec/protocol-contracts/instance-deployer'; import { Attributes, type TelemetryClient, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import groupBy from 'lodash.groupby'; import { @@ -115,6 +117,7 @@ export class Archiver implements ArchiveSource, Traceable { private readonly l1Addresses: { rollupAddress: EthAddress; inboxAddress: EthAddress; registryAddress: EthAddress }, readonly dataStore: ArchiverDataStore, private readonly config: { pollingIntervalMs: number; batchSize: number }, + private readonly _blobSinkClient: BlobSinkClientInterface, private readonly instrumentation: ArchiverInstrumentation, private readonly l1constants: L1RollupConstants, private readonly log: Logger = createLogger('archiver'), @@ -145,7 +148,7 @@ export class Archiver implements ArchiveSource, Traceable { public static async createAndSync( config: ArchiverConfig, archiverStore: ArchiverDataStore, - telemetry: TelemetryClient, + deps: { telemetry: TelemetryClient; blobSinkClient: BlobSinkClientInterface }, blockUntilSynced = true, ): Promise { const chain = createEthereumChain(config.l1RpcUrl, config.l1ChainId); @@ -176,7 +179,8 @@ export class Archiver implements ArchiveSource, Traceable { pollingIntervalMs: config.archiverPollingIntervalMS ?? 10_000, batchSize: config.archiverBatchSize ?? 100, }, - await ArchiverInstrumentation.new(telemetry, () => archiverStore.estimateSize()), + deps.blobSinkClient, + await ArchiverInstrumentation.new(deps.telemetry, () => archiverStore.estimateSize()), { l1StartBlock, l1GenesisTime, epochDuration, slotDuration, ethereumSlotDuration }, ); await archiver.start(blockUntilSynced); diff --git a/yarn-project/archiver/src/factory.ts b/yarn-project/archiver/src/factory.ts index 018cbec57f98..0c47a192e482 100644 --- a/yarn-project/archiver/src/factory.ts +++ b/yarn-project/archiver/src/factory.ts @@ -1,3 +1,4 @@ +import { type BlobSinkClientInterface } from '@aztec/blob-sink/client'; import { type ArchiverApi, type Service } from '@aztec/circuit-types'; import { type ContractClassPublic, @@ -23,6 +24,7 @@ import { createArchiverClient } from './rpc/index.js'; export async function createArchiver( config: ArchiverConfig & DataStoreConfig, + blobSinkClient: BlobSinkClientInterface, telemetry: TelemetryClient = new NoopTelemetryClient(), opts: { blockUntilSync: boolean } = { blockUntilSync: true }, ): Promise> { @@ -31,7 +33,7 @@ export async function createArchiver( const archiverStore = new KVArchiverDataStore(store, config.maxLogs); await registerProtocolContracts(archiverStore); await registerCommonContracts(archiverStore); - return Archiver.createAndSync(config, archiverStore, telemetry, opts.blockUntilSync); + return Archiver.createAndSync(config, archiverStore, { telemetry, blobSinkClient }, opts.blockUntilSync); } else { return createArchiverClient(config.archiverUrl); } diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index a801fbabf285..04857555bb7f 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -1,5 +1,6 @@ import { createArchiver } from '@aztec/archiver'; import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; +import { BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client'; import { type AztecNode, type ClientProtocolCircuitVerifier, @@ -140,11 +141,13 @@ export class AztecNodeService implements AztecNode, Traceable { logger?: Logger; publisher?: L1Publisher; dateProvider?: DateProvider; + blobSinkClient?: BlobSinkClientInterface; } = {}, ): Promise { const telemetry = deps.telemetry ?? new NoopTelemetryClient(); const log = deps.logger ?? createLogger('node'); const dateProvider = deps.dateProvider ?? new DateProvider(); + const blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config.blobSinkUrl); const ethereumChain = createEthereumChain(config.l1RpcUrl, config.l1ChainId); //validate that the actual chain id matches that specified in configuration if (config.l1ChainId !== ethereumChain.chainInfo.id) { @@ -153,7 +156,7 @@ export class AztecNodeService implements AztecNode, Traceable { ); } - const archiver = await createArchiver(config, telemetry, { blockUntilSync: true }); + const archiver = await createArchiver(config, blobSinkClient, telemetry, { blockUntilSync: true }); // we identify the P2P transaction protocol by using the rollup contract address. // this may well change in future @@ -189,6 +192,7 @@ export class AztecNodeService implements AztecNode, Traceable { const sequencer = config.disableValidator ? undefined : await SequencerClient.new(config, { + ...deps, validatorClient, p2pClient, worldStateSynchronizer, @@ -197,7 +201,7 @@ export class AztecNodeService implements AztecNode, Traceable { l1ToL2MessageSource: archiver, telemetry, dateProvider, - ...deps, + blobSinkClient, }); return new AztecNodeService( diff --git a/yarn-project/aztec/src/cli/cmds/start_archiver.ts b/yarn-project/aztec/src/cli/cmds/start_archiver.ts index 05851de847bb..05d7c0197f5b 100644 --- a/yarn-project/aztec/src/cli/cmds/start_archiver.ts +++ b/yarn-project/aztec/src/cli/cmds/start_archiver.ts @@ -1,5 +1,6 @@ import { Archiver, type ArchiverConfig, KVArchiverDataStore, archiverConfigMappings } from '@aztec/archiver'; import { createLogger } from '@aztec/aztec.js'; +import { createBlobSinkClient } from '@aztec/blob-sink/client'; import { ArchiverApiSchema } from '@aztec/circuit-types'; import { type NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server'; import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config'; @@ -31,7 +32,9 @@ export async function startArchiver( const archiverStore = new KVArchiverDataStore(store, archiverConfig.maxLogs); const telemetry = await createAndStartTelemetryClient(getTelemetryClientConfig()); - const archiver = await Archiver.createAndSync(archiverConfig, archiverStore, telemetry, true); + // TODO(ISSUE): place CL url in config here + const blobSinkClient = createBlobSinkClient(); + const archiver = await Archiver.createAndSync(archiverConfig, archiverStore, { telemetry, blobSinkClient }, true); services.archiver = [archiver, ArchiverApiSchema]; signalHandlers.push(archiver.stop); return services; diff --git a/yarn-project/aztec/src/cli/cmds/start_node.ts b/yarn-project/aztec/src/cli/cmds/start_node.ts index 1758ea35a387..1d93fd1e4ad1 100644 --- a/yarn-project/aztec/src/cli/cmds/start_node.ts +++ b/yarn-project/aztec/src/cli/cmds/start_node.ts @@ -91,7 +91,7 @@ export async function startNode( const telemetry = await createAndStartTelemetryClient(telemetryConfig); // Create and start Aztec Node - const node = await createAztecNode(nodeConfig, telemetry); + const node = await createAztecNode(nodeConfig, { telemetry }); // Add node and p2p to services list services.node = [node, AztecNodeApiSchema]; diff --git a/yarn-project/aztec/src/sandbox.ts b/yarn-project/aztec/src/sandbox.ts index a271f11d05fe..19f0f9b16535 100644 --- a/yarn-project/aztec/src/sandbox.ts +++ b/yarn-project/aztec/src/sandbox.ts @@ -2,6 +2,7 @@ import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node'; import { AnvilTestWatcher, EthCheatCodes, SignerlessWallet, retryUntil } from '@aztec/aztec.js'; import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint'; +import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client'; import { type AztecNode } from '@aztec/circuit-types'; import { setupCanonicalL2FeeJuice } from '@aztec/cli/setup-contracts'; import { @@ -143,8 +144,10 @@ export async function createSandbox(config: Partial = {}) { await watcher.start(); } - const client = await createAndStartTelemetryClient(getTelemetryClientConfig()); - const node = await createAztecNode(aztecNodeConfig, client); + const telemetry = await createAndStartTelemetryClient(getTelemetryClientConfig()); + // Create a local blob sink client inside the sandbox, no http connectivity + const blobSinkClient = createBlobSinkClient(); + const node = await createAztecNode(aztecNodeConfig, { telemetry, blobSinkClient }); const pxe = await createAztecPXE(node); if (config.enableGas) { @@ -168,9 +171,12 @@ export async function createSandbox(config: Partial = {}) { * Create and start a new Aztec RPC HTTP Server * @param config - Optional Aztec node settings. */ -export async function createAztecNode(config: Partial = {}, telemetryClient?: TelemetryClient) { +export async function createAztecNode( + config: Partial = {}, + deps: { telemetry?: TelemetryClient; blobSinkClient?: BlobSinkClientInterface } = {}, +) { const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config }; - const node = await AztecNodeService.createAndSync(aztecNodeConfig, { telemetry: telemetryClient }); + const node = await AztecNodeService.createAndSync(aztecNodeConfig, deps); return node; } diff --git a/yarn-project/blob-sink/src/client/http.test.ts b/yarn-project/blob-sink/src/client/http.test.ts index 767f73c015f9..128853d7692d 100644 --- a/yarn-project/blob-sink/src/client/http.test.ts +++ b/yarn-project/blob-sink/src/client/http.test.ts @@ -13,7 +13,6 @@ describe('HttpBlobSinkClient', () => { await server.start(); const client = new HttpBlobSinkClient(`http://localhost:${server.port}`); - console.log(`HttpBlobSinkClient listening on port ${server.port}`); return { client, diff --git a/yarn-project/blob-sink/src/client/http.ts b/yarn-project/blob-sink/src/client/http.ts index 0ed2612e984d..3822a7903cd3 100644 --- a/yarn-project/blob-sink/src/client/http.ts +++ b/yarn-project/blob-sink/src/client/http.ts @@ -65,7 +65,6 @@ export class HttpBlobSinkClient implements BlobSinkClientInterface { this.log.error('Failed to get blob sidecar', res.status); return []; } catch (err) { - console.log('err', err); this.log.error(`Error getting blob sidecar`, err); return []; } diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index de355e1fae62..17ca49f88bc4 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -187,7 +187,7 @@ describe('L1Publisher integration', () => { ethereumSlotDuration: config.ethereumSlotDuration, blobSinkUrl: BLOB_SINK_URL, }, - new NoopTelemetryClient(), + { telemetry: new NoopTelemetryClient() }, ); coinbase = config.coinbase || EthAddress.random(); diff --git a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts index aac3af2db0ad..1926ee52eb23 100644 --- a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts +++ b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts @@ -20,6 +20,8 @@ import { TestCircuitVerifier, type UltraKeccakHonkProtocolArtifact, } from '@aztec/bb-prover'; +import { createBlobSinkClient } from '@aztec/blob-sink/client'; +import { type BlobSinkServer } from '@aztec/blob-sink/server'; import { compileContract } from '@aztec/ethereum'; import { Buffer32 } from '@aztec/foundation/buffer'; import { RollupAbi, TestERC20Abi } from '@aztec/l1-artifacts'; @@ -76,6 +78,7 @@ export class FullProverTest { aztecNode!: AztecNode; pxe!: PXEService; cheatCodes!: CheatCodes; + blobSink!: BlobSinkServer; private provenComponents: ProvenSetup[] = []; private bbConfigCleanup?: () => Promise; private acvmConfigCleanup?: () => Promise; @@ -163,8 +166,11 @@ export class FullProverTest { aztecNode: this.aztecNode, deployL1ContractsValues: this.l1Contracts, cheatCodes: this.cheatCodes, + blobSink: this.blobSink, } = this.context); + const blobSinkClient = createBlobSinkClient(`http://localhost:${this.blobSink.port}`); + // Configure a full prover PXE let acvmConfig: Awaited> | undefined; let bbConfig: Awaited> | undefined; @@ -247,6 +253,7 @@ export class FullProverTest { this.logger.verbose('Starting archiver for new prover node'); const archiver = await createArchiver( { ...this.context.aztecNodeConfig, dataDirectory: undefined }, + blobSinkClient, new NoopTelemetryClient(), { blockUntilSync: true }, ); @@ -279,6 +286,7 @@ export class FullProverTest { this.proverNode = await createProverNode(proverConfig, { aztecNodeTxProvider: this.aztecNode, archiver: archiver as Archiver, + blobSinkClient, }); await this.proverNode.start(); diff --git a/yarn-project/end-to-end/src/e2e_synching.test.ts b/yarn-project/end-to-end/src/e2e_synching.test.ts index a618bc6ec2e5..24aeb10de9a3 100644 --- a/yarn-project/end-to-end/src/e2e_synching.test.ts +++ b/yarn-project/end-to-end/src/e2e_synching.test.ts @@ -45,6 +45,7 @@ import { createLogger, sleep, } from '@aztec/aztec.js'; +import { createBlobSinkClient } from '@aztec/blob-sink/client'; // eslint-disable-next-line no-restricted-imports import { L2Block, tryStop } from '@aztec/circuit-types'; import { type AztecAddress } from '@aztec/circuits.js'; @@ -382,6 +383,8 @@ describe('e2e_synching', () => { await (sequencer as any).stop(); await watcher?.stop(); + const blobSinkClient = createBlobSinkClient(`http://localhost:${blobSink?.port ?? 5052}`); + const sequencerPK: `0x${string}` = `0x${getPrivateKeyFromIndex(0)!.toString('hex')}`; const publisher = new L1Publisher( { @@ -395,7 +398,7 @@ describe('e2e_synching', () => { ethereumSlotDuration: ETHEREUM_SLOT_DURATION, blobSinkUrl: `http://localhost:${blobSink?.port ?? 5052}`, }, - new NoopTelemetryClient(), + { telemetry: new NoopTelemetryClient(), blobSinkClient }, ); const blocks = variant.loadBlocks(); @@ -498,7 +501,10 @@ describe('e2e_synching', () => { await aztecNode.stop(); } - const archiver = await createArchiver(opts.config!); + const blobSinkClient = createBlobSinkClient(`http://localhost:${opts.blobSink?.port ?? 5052}`); + const archiver = await createArchiver(opts.config!, blobSinkClient, new NoopTelemetryClient(), { + blockUntilSync: true, + }); const pendingBlockNumber = await rollup.read.getPendingBlockNumber(); const worldState = await createWorldStateSynchronizer(opts.config!, archiver, new NoopTelemetryClient()); diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index 836eb8c3c5b9..173eb21ce986 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -14,7 +14,7 @@ import { type Wallet, } from '@aztec/aztec.js'; import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment'; -import { type BlobSinkServer, createBlobSinkServer } from '@aztec/blob-sink'; +import { type BlobSinkServer, createBlobSinkServer } from '@aztec/blob-sink/server'; import { type DeployL1ContractsArgs, createL1Clients, getL1ContractsConfigEnvVars, l1Artifacts } from '@aztec/ethereum'; import { EthCheatCodesWithState, startAnvil } from '@aztec/ethereum/test'; import { asyncMap } from '@aztec/foundation/async-map'; diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 23cf19b22bf0..b09375e9532b 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -27,7 +27,8 @@ import { import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment'; import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint'; import { type BBNativePrivateKernelProver } from '@aztec/bb-prover'; -import { type BlobSinkServer, createBlobSinkServer } from '@aztec/blob-sink'; +import { createBlobSinkClient } from '@aztec/blob-sink/client'; +import { type BlobSinkServer, createBlobSinkServer } from '@aztec/blob-sink/server'; import { type EthAddress, FEE_JUICE_INITIAL_MINT, Fr, Gas, getContractClassFromArtifact } from '@aztec/circuits.js'; import { type DeployL1ContractsArgs, @@ -453,8 +454,15 @@ export async function setup( config.l1PublishRetryIntervalMS = 100; const telemetry = await telemetryPromise; - const publisher = new TestL1Publisher(config, telemetry); - const aztecNode = await AztecNodeService.createAndSync(config, { telemetry, publisher, dateProvider }); + + const blobSinkClient = createBlobSinkClient(config.blobSinkUrl); + const publisher = new TestL1Publisher(config, { telemetry, blobSinkClient }); + const aztecNode = await AztecNodeService.createAndSync(config, { + telemetry, + publisher, + dateProvider, + blobSinkClient, + }); const sequencer = aztecNode.getSequencer(); let proverNode: ProverNode | undefined = undefined; @@ -724,9 +732,13 @@ export async function createAndSyncProverNode( stop: () => Promise.resolve(), }; + const blobSinkClient = createBlobSinkClient(); // Creating temp store and archiver for simulated prover node const archiverConfig = { ...aztecNodeConfig, dataDirectory }; - const archiver = await createArchiver(archiverConfig, new NoopTelemetryClient(), { blockUntilSync: true }); + const telemetry = new NoopTelemetryClient(); + const archiver = await createArchiver(archiverConfig, blobSinkClient, telemetry, { + blockUntilSync: true, + }); // Prover node config is for simulated proofs const proverConfig: ProverNodeConfig = { @@ -747,7 +759,7 @@ export async function createAndSyncProverNode( }; // Use testing l1 publisher - const publisher = new TestL1Publisher(proverConfig, new NoopTelemetryClient()); + const publisher = new TestL1Publisher(proverConfig, { telemetry, blobSinkClient }); const proverNode = await createProverNode(proverConfig, { aztecNodeTxProvider: aztecNodeWithoutStop, diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index f7f777626fb5..6054c366e404 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -1,4 +1,5 @@ import { type Archiver, createArchiver } from '@aztec/archiver'; +import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client'; import { type ProverCoordination, type ProvingJobBroker } from '@aztec/circuit-types'; import { EpochCache } from '@aztec/epoch-cache'; import { createEthereumChain } from '@aztec/ethereum'; @@ -34,12 +35,14 @@ export async function createProverNode( aztecNodeTxProvider?: ProverCoordination; archiver?: Archiver; publisher?: L1Publisher; + blobSinkClient?: BlobSinkClientInterface; broker?: ProvingJobBroker; } = {}, ) { const telemetry = deps.telemetry ?? new NoopTelemetryClient(); + const blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config.blobSinkUrl); const log = deps.log ?? createLogger('prover-node'); - const archiver = deps.archiver ?? (await createArchiver(config, telemetry, { blockUntilSync: true })); + const archiver = deps.archiver ?? (await createArchiver(config, blobSinkClient, telemetry, { blockUntilSync: true })); log.verbose(`Created archiver and synced to block ${await archiver.getBlockNumber()}`); const worldStateConfig = { ...config, worldStateProvenBlocksOnly: false }; @@ -50,7 +53,7 @@ export async function createProverNode( const prover = await createProverClient(config, worldStateSynchronizer, broker, telemetry); // REFACTOR: Move publisher out of sequencer package and into an L1-related package - const publisher = deps.publisher ?? new L1Publisher(config, telemetry); + const publisher = deps.publisher ?? new L1Publisher(config, { telemetry, blobSinkClient }); const epochCache = await EpochCache.create(config.l1Contracts.rollupAddress, config); diff --git a/yarn-project/sequencer-client/src/client/sequencer-client.ts b/yarn-project/sequencer-client/src/client/sequencer-client.ts index 81bf69ad10fd..28f6c39a82fd 100644 --- a/yarn-project/sequencer-client/src/client/sequencer-client.ts +++ b/yarn-project/sequencer-client/src/client/sequencer-client.ts @@ -1,3 +1,4 @@ +import { BlobSinkClientInterface } from '@aztec/blob-sink/client'; import { type L1ToL2MessageSource, type L2BlockSource, type WorldStateSynchronizer } from '@aztec/circuit-types'; import { type ContractDataSource } from '@aztec/circuits.js'; import { isAnvilTestChain } from '@aztec/ethereum'; @@ -45,6 +46,7 @@ export class SequencerClient { l1ToL2MessageSource: L1ToL2MessageSource; telemetry: TelemetryClient; publisher?: L1Publisher; + blobSinkClient?: BlobSinkClientInterface; dateProvider: DateProvider; }, ) { @@ -57,7 +59,8 @@ export class SequencerClient { l1ToL2MessageSource, telemetry: telemetryClient, } = deps; - const publisher = deps.publisher ?? new L1Publisher(config, telemetryClient); + const publisher = + deps.publisher ?? new L1Publisher(config, { telemetry: telemetryClient, blobSinkClient: deps.blobSinkClient }); const globalsBuilder = new GlobalVariableBuilder(config); const publicProcessorFactory = new PublicProcessorFactory(contractDataSource, deps.dateProvider, telemetryClient); diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts index 689c03c71d16..a000d6f80f59 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts @@ -1,3 +1,4 @@ +import { HttpBlobSinkClient } from '@aztec/blob-sink/client'; import { L2Block } from '@aztec/circuit-types'; import { EthAddress } from '@aztec/circuits.js'; import { @@ -91,6 +92,7 @@ describe('L1Publisher', () => { let blockHash: Buffer; let body: Buffer; + let blobSinkClient: HttpBlobSinkClient; let mockBlobSinkServer: Server | undefined = undefined; // An l1 publisher with some private methods exposed @@ -100,6 +102,7 @@ describe('L1Publisher', () => { beforeEach(() => { mockBlobSinkServer = undefined; + blobSinkClient = new HttpBlobSinkClient(BLOB_SINK_URL); l2Block = L2Block.random(42); @@ -136,7 +139,7 @@ describe('L1Publisher', () => { Pick & L1TxUtilsConfig; - publisher = new L1Publisher(config, new NoopTelemetryClient()); + publisher = new L1Publisher(config, { telemetry: new NoopTelemetryClient(), blobSinkClient }); (publisher as any)['rollupContract'] = rollupContract; (publisher as any)['publicClient'] = publicClient; diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 1128cbba4670..9e74df456e4d 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -1,3 +1,4 @@ +import { BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client'; import { ConsensusPayload, type EpochProofClaim, @@ -35,6 +36,7 @@ import { InterruptibleSleep } from '@aztec/foundation/sleep'; import { Timer } from '@aztec/foundation/timer'; import { ExtRollupLibAbi, GovernanceProposerAbi, LeonidasLibAbi, RollupAbi } from '@aztec/l1-artifacts'; import { type TelemetryClient } from '@aztec/telemetry-client'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import pick from 'lodash.pick'; import { @@ -171,8 +173,7 @@ export class L1Publisher { protected account: PrivateKeyAccount; protected ethereumSlotDuration: bigint; - private blobSinkUrl: string | undefined; - + private blobSinkClient: BlobSinkClientInterface; // @note - with blobs, the below estimate seems too large. // Total used for full block from int_l1_pub e2e test: 1m (of which 86k is 1x blob) // Total used for emptier block from above test: 429k (of which 84k is 1x blob) @@ -183,12 +184,17 @@ export class L1Publisher { constructor( config: TxSenderConfig & PublisherConfig & Pick & L1TxUtilsConfig, - client: TelemetryClient, + deps: { telemetry?: TelemetryClient; blobSinkClient?: BlobSinkClientInterface } = {}, ) { this.sleepTimeMs = config?.l1PublishRetryIntervalMS ?? 60_000; this.ethereumSlotDuration = BigInt(config.ethereumSlotDuration); - this.blobSinkUrl = config.blobSinkUrl; - this.metrics = new L1PublisherMetrics(client, 'L1Publisher'); + + // TODO: This client will need to be injected at a higher level for the + // archiver to be able to interface with it + const telemetry = deps.telemetry ?? new NoopTelemetryClient(); + this.blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config.blobSinkUrl); + + this.metrics = new L1PublisherMetrics(telemetry, 'L1Publisher'); const { l1RpcUrl: rpcUrl, l1ChainId: chainId, publisherPrivateKey, l1Contracts } = config; const chain = createEthereumChain(rpcUrl, chainId); @@ -1117,38 +1123,8 @@ export class L1Publisher { * In the future this will move to be the beacon block id - which takes a bit more work * to calculate and will need to be mocked in e2e tests */ - protected async sendBlobsToBlobSink(blockHash: string, blobs: Blob[]): Promise { - // TODO(md): for now we are assuming the indexes of the blobs will be 0, 1, 2 - // When in reality they will not, but for testing purposes this is fine - if (!this.blobSinkUrl) { - this.log.verbose('No blob sink url configured'); - return false; - } - - this.log.verbose(`Sending ${blobs.length} blobs to blob sink`); - try { - const res = await fetch(`${this.blobSinkUrl}/blob_sidecar`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - // eslint-disable-next-line camelcase - block_id: blockHash, - blobs: blobs.map((b, i) => ({ blob: b.toBuffer(), index: i })), - }), - }); - - if (res.ok) { - return true; - } - - this.log.error('Failed to send blobs to blob sink', res.status); - return false; - } catch (err) { - this.log.error(`Error sending blobs to blob sink`, err); - return false; - } + protected sendBlobsToBlobSink(blockHash: string, blobs: Blob[]): Promise { + return this.blobSinkClient.sendBlobsToBlobSink(blockHash, blobs); } }