diff --git a/cspell.json b/cspell.json index def40448ad5..6073069b028 100644 --- a/cspell.json +++ b/cspell.json @@ -120,6 +120,7 @@ "ierc", "indexeddb", "initialise", + "initialising", "interruptible", "isequal", "ivpk", @@ -154,6 +155,7 @@ "monomorphize", "mplex", "msgpack", + "msgpackr", "muldiv", "multiaddr", "multiaddrs", @@ -163,6 +165,7 @@ "muxers", "nada", "namespacing", + "napi", "Nargo", "nixpkgs", "nodebuffer", diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index a3115f7da67..6aa953cd087 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -38,11 +38,6 @@ export type ArchiverConfig = { */ l1Contracts: L1ContractAddresses; - /** - * Optional dir to store data. If omitted will store in memory. - */ - dataDirectory: string | undefined; - /** The max number of logs that can be obtained in 1 "getUnencryptedLogs" call. */ maxLogs?: number; } & L1ReaderConfig & @@ -57,11 +52,7 @@ export const archiverConfigMappings: ConfigMappingsType = { archiverPollingIntervalMS: { env: 'ARCHIVER_POLLING_INTERVAL_MS', description: 'The polling interval in ms for retrieving new L2 blocks and encrypted logs.', - ...numberConfigHelper(1000), - }, - dataDirectory: { - env: 'DATA_DIRECTORY', - description: 'Optional dir to store data. If omitted will store in memory.', + ...numberConfigHelper(1_000), }, maxLogs: { env: 'ARCHIVER_MAX_LOGS', diff --git a/yarn-project/archiver/src/factory.ts b/yarn-project/archiver/src/factory.ts index ac5b2786757..e439ab370d5 100644 --- a/yarn-project/archiver/src/factory.ts +++ b/yarn-project/archiver/src/factory.ts @@ -2,6 +2,7 @@ import { type ArchiverApi, type Service } from '@aztec/circuit-types'; import { type ContractClassPublic } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { type Maybe } from '@aztec/foundation/types'; +import { type DataStoreConfig } from '@aztec/kv-store/config'; import { createStore } from '@aztec/kv-store/utils'; import { getCanonicalProtocolContract, protocolContractNames } from '@aztec/protocol-contracts'; import { type TelemetryClient } from '@aztec/telemetry-client'; @@ -13,7 +14,7 @@ import { KVArchiverDataStore } from './archiver/index.js'; import { createArchiverClient } from './rpc/index.js'; export async function createArchiver( - config: ArchiverConfig, + config: ArchiverConfig & DataStoreConfig, telemetry: TelemetryClient = new NoopTelemetryClient(), opts: { blockUntilSync: boolean } = { blockUntilSync: true }, ): Promise> { diff --git a/yarn-project/aztec-node/src/aztec-node/config.ts b/yarn-project/aztec-node/src/aztec-node/config.ts index 2bd36b1052e..c083a518315 100644 --- a/yarn-project/aztec-node/src/aztec-node/config.ts +++ b/yarn-project/aztec-node/src/aztec-node/config.ts @@ -1,5 +1,6 @@ import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver'; import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings } from '@aztec/foundation/config'; +import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config'; import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p'; import { type ProverClientConfig, proverClientConfigMappings } from '@aztec/prover-client'; import { type SequencerClientConfig, sequencerClientConfigMappings } from '@aztec/sequencer-client'; @@ -24,7 +25,7 @@ export type AztecNodeConfig = ArchiverConfig & P2PConfig & { /** Whether the validator is disabled for this node */ disableValidator: boolean; - }; + } & DataStoreConfig; export const aztecNodeConfigMappings: ConfigMappingsType = { ...archiverConfigMappings, @@ -33,6 +34,7 @@ export const aztecNodeConfigMappings: ConfigMappingsType = { ...proverClientConfigMappings, ...worldStateConfigMappings, ...p2pConfigMappings, + ...dataConfigMappings, disableValidator: { env: 'VALIDATOR_DISABLED', description: 'Whether the validator is disabled for this node.', diff --git a/yarn-project/aztec/src/cli/aztec_start_options.ts b/yarn-project/aztec/src/cli/aztec_start_options.ts index 9d9c00a7d98..53b0ab01949 100644 --- a/yarn-project/aztec/src/cli/aztec_start_options.ts +++ b/yarn-project/aztec/src/cli/aztec_start_options.ts @@ -218,12 +218,6 @@ export const aztecStartOptions: { [key: string]: AztecStartOption[] } = { defaultValue: undefined, envVar: undefined, }, - { - flag: '--pxe.dataDirectory ', - description: 'Where to store PXE data. If not set, will store in memory', - defaultValue: undefined, - envVar: 'PXE_DATA_DIRECTORY', - }, ...getOptions('pxe', allPxeConfigMappings), ], ARCHIVER: [ diff --git a/yarn-project/aztec/src/cli/cmds/start_archiver.ts b/yarn-project/aztec/src/cli/cmds/start_archiver.ts index cdee55cc214..541ec726db5 100644 --- a/yarn-project/aztec/src/cli/cmds/start_archiver.ts +++ b/yarn-project/aztec/src/cli/cmds/start_archiver.ts @@ -2,6 +2,7 @@ import { Archiver, type ArchiverConfig, KVArchiverDataStore, archiverConfigMappi import { createDebugLogger } from '@aztec/aztec.js'; import { ArchiverApiSchema } from '@aztec/circuit-types'; import { type NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server'; +import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config'; import { createStore } from '@aztec/kv-store/utils'; import { createAndStartTelemetryClient, @@ -16,7 +17,14 @@ export async function startArchiver( signalHandlers: (() => Promise)[], services: NamespacedApiHandlers, ) { - const archiverConfig = extractRelevantOptions(options, archiverConfigMappings, 'archiver'); + const archiverConfig = extractRelevantOptions( + options, + { + ...archiverConfigMappings, + ...dataConfigMappings, + }, + 'archiver', + ); const storeLog = createDebugLogger('aztec:archiver:lmdb'); const store = await createStore('archiver', archiverConfig, storeLog); diff --git a/yarn-project/end-to-end/scripts/e2e_test_config.yml b/yarn-project/end-to-end/scripts/e2e_test_config.yml index 19a2f0003d5..85d30516ee7 100644 --- a/yarn-project/end-to-end/scripts/e2e_test_config.yml +++ b/yarn-project/end-to-end/scripts/e2e_test_config.yml @@ -111,5 +111,6 @@ tests: use_compose: true pxe: use_compose: true - uniswap_trade_on_l1_from_l2: - use_compose: true + # https://github.com/AztecProtocol/aztec-packages/issues/10030 + # uniswap_trade_on_l1_from_l2: + # use_compose: true diff --git a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts index 5aa2b0c33fc..2934f662ff7 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts @@ -5,7 +5,7 @@ import { BBCircuitVerifier } from '@aztec/bb-prover'; import { CompleteAddress, Fq, Fr, GasSettings } from '@aztec/circuits.js'; import { FPCContract, FeeJuiceContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; -import { type PXEService, createPXEService } from '@aztec/pxe'; +import { type PXEService, type PXEServiceConfig, createPXEService } from '@aztec/pxe'; import { jest } from '@jest/globals'; @@ -142,17 +142,18 @@ describe('benchmarks/proving', () => { ctx.logger.info('Starting PXEs configured with real proofs'); provingPxes = []; for (let i = 0; i < 4; i++) { - const pxe = await createPXEService( - ctx.aztecNode, - { - proverEnabled: true, - bbBinaryPath: bbConfig.bbBinaryPath, - bbWorkingDirectory: bbConfig.bbWorkingDirectory, - l2BlockPollingIntervalMS: 1000, - l2StartingBlock: 1, - }, - `proving-pxe-${i}`, - ); + const l1Contracts = await ctx.aztecNode.getL1ContractAddresses(); + const pxeConfig = { + proverEnabled: true, + bbBinaryPath: bbConfig.bbBinaryPath, + bbWorkingDirectory: bbConfig.bbWorkingDirectory, + l2BlockPollingIntervalMS: 1000, + l2StartingBlock: 1, + dataDirectory: undefined, + dataStoreMapSizeKB: 1024 * 1024, + l1Contracts, + } as PXEServiceConfig; + const pxe = await createPXEService(ctx.aztecNode, pxeConfig, `proving-pxe-${i}`); await getSchnorrAccount(pxe, schnorrWalletEncKey, schnorrWalletSigningKey, schnorrWalletSalt).register(); await pxe.registerContract(initialTokenContract); diff --git a/yarn-project/end-to-end/src/benchmarks/utils.ts b/yarn-project/end-to-end/src/benchmarks/utils.ts index 5432a7f6781..4d2a78bdaad 100644 --- a/yarn-project/end-to-end/src/benchmarks/utils.ts +++ b/yarn-project/end-to-end/src/benchmarks/utils.ts @@ -3,7 +3,7 @@ import { type AztecNode, BatchCall, INITIAL_L2_BLOCK_NUM, type SentTx, retryUnti import { times } from '@aztec/foundation/collection'; import { randomInt } from '@aztec/foundation/crypto'; import { BenchmarkingContract } from '@aztec/noir-contracts.js/Benchmarking'; -import { type PXEService, createPXEService } from '@aztec/pxe'; +import { type PXEService, type PXEServiceConfig, createPXEService } from '@aztec/pxe'; import { mkdirpSync } from 'fs-extra'; import { globSync } from 'glob'; @@ -102,10 +102,15 @@ export async function waitNewPXESynced( contract: BenchmarkingContract, startingBlock: number = INITIAL_L2_BLOCK_NUM, ): Promise { - const pxe = await createPXEService(node, { - l2BlockPollingIntervalMS: 100, + const l1Contracts = await node.getL1ContractAddresses(); + const pxeConfig = { l2StartingBlock: startingBlock, - }); + l2BlockPollingIntervalMS: 100, + dataDirectory: undefined, + dataStoreMapSizeKB: 1024 * 1024, + l1Contracts, + } as PXEServiceConfig; + const pxe = await createPXEService(node, pxeConfig); await pxe.registerContract(contract); await retryUntil(() => pxe.isGlobalStateSynchronized(), 'pxe-global-sync'); return pxe; diff --git a/yarn-project/end-to-end/src/prover-coordination/e2e_prover_coordination.test.ts b/yarn-project/end-to-end/src/prover-coordination/e2e_prover_coordination.test.ts index a6ea11a011b..665abe523dc 100644 --- a/yarn-project/end-to-end/src/prover-coordination/e2e_prover_coordination.test.ts +++ b/yarn-project/end-to-end/src/prover-coordination/e2e_prover_coordination.test.ts @@ -359,6 +359,12 @@ describe('e2e_prover_coordination', () => { }); it('Can claim proving rights after a prune', async () => { + await logState(); + + const tips = await ctx.cheatCodes.rollup.getTips(); + + let currentPending = tips.pending; + let currentProven = tips.proven; // Here we are creating a proof quote for epoch 0 const quoteForEpoch0 = await makeEpochProofQuote({ epochToProve: 0n, @@ -373,9 +379,11 @@ describe('e2e_prover_coordination', () => { // Build a block in epoch 1, we should see the quote for epoch 0 submitted earlier published to L1 await contract.methods.create_note(recipient, recipient, 10).send().wait(); + currentPending++; + // Verify that we can claim the current epoch await expectProofClaimOnL1({ ...quoteForEpoch0.payload, proposer: publisherAddress }); - await expectTips({ pending: 3n, proven: 0n }); + await expectTips({ pending: currentPending, proven: currentProven }); // Now go to epoch 1 await advanceToNextEpoch(); @@ -384,19 +392,23 @@ describe('e2e_prover_coordination', () => { const epoch0BlockNumber = await getPendingBlockNumber(); await rollupContract.write.setAssumeProvenThroughBlockNumber([BigInt(epoch0BlockNumber)]); + currentProven = epoch0BlockNumber; + // Go to epoch 2 await advanceToNextEpoch(); // Progress epochs with a block in each until we hit a reorg // Note tips are block numbers, not slots - await expectTips({ pending: 3n, proven: 3n }); + await expectTips({ pending: currentPending, proven: currentProven }); const tx2BeforeReorg = await contract.methods.create_note(recipient, recipient, 10).send().wait(); - await expectTips({ pending: 4n, proven: 3n }); + currentPending++; + await expectTips({ pending: currentPending, proven: currentProven }); // Go to epoch 3 await advanceToNextEpoch(); const tx3BeforeReorg = await contract.methods.create_note(recipient, recipient, 10).send().wait(); - await expectTips({ pending: 5n, proven: 3n }); + currentPending++; + await expectTips({ pending: currentPending, proven: currentProven }); // Go to epoch 4 !!! REORG !!! ay caramba !!! await advanceToNextEpoch(); @@ -430,12 +442,15 @@ describe('e2e_prover_coordination', () => { const newWallet = await createAccount(newPxe); const newWalletAddress = newWallet.getAddress(); - // The chain will prune back to block 3 + // after the re-org the pending chain has moved on by 2 blocks + currentPending = currentProven + 2n; + + // The chain will prune back to the proven block number // then include the txs from the pruned epochs that are still valid - // bringing us back to block 4 (same number, different hash) + // bringing us back to block proven + 1 (same number, different hash) // creating a new account will produce another block - // so we expect 5 blocks in the pending chain here! - await expectTips({ pending: 5n, proven: 3n }); + // so we expect proven + 2 blocks in the pending chain here! + await expectTips({ pending: currentPending, proven: currentProven }); // Submit proof claim for the new epoch const quoteForEpoch4 = await makeEpochProofQuote({ @@ -453,7 +468,8 @@ describe('e2e_prover_coordination', () => { logger.info('Sending new tx on reorged chain'); await contractFromNewPxe.methods.create_note(newWalletAddress, newWalletAddress, 10).send().wait(); - await expectTips({ pending: 6n, proven: 3n }); + currentPending++; + await expectTips({ pending: currentPending, proven: currentProven }); // Expect the proof claim to be accepted for the chain after the reorg await expectProofClaimOnL1({ ...quoteForEpoch4.payload, proposer: publisherAddress }); diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 7b2469bca97..c62e2a03c1d 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -37,6 +37,7 @@ export type EnvVar = | 'BOT_STOP_WHEN_UNHEALTHY' | 'COINBASE' | 'DATA_DIRECTORY' + | 'DATA_STORE_MAP_SIZE_KB' | 'DEBUG' | 'DEPLOY_AZTEC_CONTRACTS_SALT' | 'DEPLOY_AZTEC_CONTRACTS' @@ -112,7 +113,6 @@ export type EnvVar = | 'PROVER_REQUIRED_CONFIRMATIONS' | 'PROVER_TEST_DELAY_MS' | 'PXE_BLOCK_POLLING_INTERVAL_MS' - | 'PXE_DATA_DIRECTORY' | 'PXE_L2_STARTING_BLOCK' | 'PXE_PROVER_ENABLED' | 'QUOTE_PROVIDER_BASIS_POINT_FEE' @@ -152,6 +152,7 @@ export type EnvVar = | 'PROVER_VIEM_POLLING_INTERVAL_MS' | 'SEQ_VIEM_POLLING_INTERVAL_MS' | 'WS_DB_MAP_SIZE_KB' + | 'WS_DATA_DIRECTORY' | 'ETHEREUM_SLOT_DURATION' | 'AZTEC_SLOT_DURATION' | 'AZTEC_EPOCH_DURATION' diff --git a/yarn-project/kv-store/package.json b/yarn-project/kv-store/package.json index ae05345eeaa..870afec3c63 100644 --- a/yarn-project/kv-store/package.json +++ b/yarn-project/kv-store/package.json @@ -5,7 +5,8 @@ "exports": { ".": "./dest/interfaces/index.js", "./lmdb": "./dest/lmdb/index.js", - "./utils": "./dest/utils.js" + "./utils": "./dest/utils.js", + "./config": "./dest/config.js" }, "scripts": { "build": "yarn clean && tsc -b", @@ -55,6 +56,7 @@ ] }, "dependencies": { + "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", "lmdb": "^3.0.6" }, diff --git a/yarn-project/kv-store/src/config.ts b/yarn-project/kv-store/src/config.ts new file mode 100644 index 00000000000..0292bd0b487 --- /dev/null +++ b/yarn-project/kv-store/src/config.ts @@ -0,0 +1,34 @@ +import { l1ContractAddressesMapping } from '@aztec/ethereum'; +import { type ConfigMappingsType, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config'; +import { type EthAddress } from '@aztec/foundation/eth-address'; + +export type DataStoreConfig = { + dataDirectory: string | undefined; + dataStoreMapSizeKB: number; + l1Contracts: { rollupAddress: EthAddress }; +}; + +export const dataConfigMappings: ConfigMappingsType = { + dataDirectory: { + env: 'DATA_DIRECTORY', + description: 'Optional dir to store data. If omitted will store in memory.', + }, + dataStoreMapSizeKB: { + env: 'DATA_STORE_MAP_SIZE_KB', + description: 'DB mapping size to be applied to all key/value stores', + ...numberConfigHelper(128 * 1_024 * 1_024), // Defaulted to 128 GB + }, + l1Contracts: { + description: 'The deployed L1 contract addresses', + defaultValue: l1ContractAddressesMapping, + }, +}; + +/** + * Returns the archiver configuration from the environment variables. + * Note: If an environment variable is not set, the default value is used. + * @returns The archiver configuration. + */ +export function getDataConfigFromEnv(): DataStoreConfig { + return getConfigFromMappings(dataConfigMappings); +} diff --git a/yarn-project/kv-store/src/lmdb/store.test.ts b/yarn-project/kv-store/src/lmdb/store.test.ts index b443b630528..c09953cb55b 100644 --- a/yarn-project/kv-store/src/lmdb/store.test.ts +++ b/yarn-project/kv-store/src/lmdb/store.test.ts @@ -4,6 +4,8 @@ import { join } from 'path'; import { AztecLmdbStore } from './store.js'; +const defaultMapSize = 1024 * 1024 * 1024 * 10; + describe('AztecLmdbStore', () => { const itForks = async (store: AztecLmdbStore) => { const singleton = store.openSingleton('singleton'); @@ -21,17 +23,17 @@ describe('AztecLmdbStore', () => { it('forks a persistent store', async () => { const path = await mkdtemp(join(tmpdir(), 'aztec-store-test-')); - const store = AztecLmdbStore.open(path, false); + const store = AztecLmdbStore.open(path, defaultMapSize, false); await itForks(store); }); it('forks a persistent store with no path', async () => { - const store = AztecLmdbStore.open(undefined, false); + const store = AztecLmdbStore.open(undefined, defaultMapSize, false); await itForks(store); }); it('forks an ephemeral store', async () => { - const store = AztecLmdbStore.open(undefined, true); + const store = AztecLmdbStore.open(undefined, defaultMapSize, true); await itForks(store); }); }); diff --git a/yarn-project/kv-store/src/lmdb/store.ts b/yarn-project/kv-store/src/lmdb/store.ts index 1c5e53f71ff..031cb554c0f 100644 --- a/yarn-project/kv-store/src/lmdb/store.ts +++ b/yarn-project/kv-store/src/lmdb/store.ts @@ -58,14 +58,16 @@ export class AztecLmdbStore implements AztecKVStore { */ static open( path?: string, + mapSizeKb = 1 * 1024 * 1024, // defaults to 1 GB map size ephemeral: boolean = false, log = createDebugLogger('aztec:kv-store:lmdb'), ): AztecLmdbStore { - log.debug(`Opening LMDB database at ${path || 'temporary location'}`); if (path) { mkdirSync(path, { recursive: true }); } - const rootDb = open({ path, noSync: ephemeral }); + const mapSize = 1024 * mapSizeKb; + log.debug(`Opening LMDB database at ${path || 'temporary location'} with map size ${mapSize}`); + const rootDb = open({ path, noSync: ephemeral, mapSize }); return new AztecLmdbStore(rootDb, ephemeral, path); } diff --git a/yarn-project/kv-store/src/utils.ts b/yarn-project/kv-store/src/utils.ts index 640f50932c3..bf388a53d46 100644 --- a/yarn-project/kv-store/src/utils.ts +++ b/yarn-project/kv-store/src/utils.ts @@ -3,11 +3,10 @@ import { type Logger, createDebugLogger } from '@aztec/foundation/log'; import { join } from 'path'; +import { type DataStoreConfig } from './config.js'; import { type AztecKVStore } from './interfaces/store.js'; import { AztecLmdbStore } from './lmdb/store.js'; -export type DataStoreConfig = { dataDirectory: string | undefined; l1Contracts: { rollupAddress: EthAddress } }; - export function createStore(name: string, config: DataStoreConfig, log: Logger = createDebugLogger('aztec:kv-store')) { let { dataDirectory } = config; if (typeof dataDirectory !== 'undefined') { @@ -16,10 +15,14 @@ export function createStore(name: string, config: DataStoreConfig, log: Logger = log.info( dataDirectory - ? `Creating ${name} data store at directory ${dataDirectory}` - : `Creating ${name} ephemeral data store`, + ? `Creating ${name} data store at directory ${dataDirectory} with map size ${config.dataStoreMapSizeKB} KB` + : `Creating ${name} ephemeral data store with map size ${config.dataStoreMapSizeKB} KB`, + ); + return initStoreForRollup( + AztecLmdbStore.open(dataDirectory, config.dataStoreMapSizeKB, false), + config.l1Contracts.rollupAddress, + log, ); - return initStoreForRollup(AztecLmdbStore.open(dataDirectory, false), config.l1Contracts.rollupAddress, log); } /** @@ -60,5 +63,6 @@ async function initStoreForRollup( * @returns A new store */ export function openTmpStore(ephemeral: boolean = false): AztecKVStore { - return AztecLmdbStore.open(undefined, ephemeral); + const mapSize = 1024 * 1024 * 10; // 10 GB map size + return AztecLmdbStore.open(undefined, mapSize, ephemeral); } diff --git a/yarn-project/kv-store/tsconfig.json b/yarn-project/kv-store/tsconfig.json index 63f8ab3e9f7..18fc3bcf3f2 100644 --- a/yarn-project/kv-store/tsconfig.json +++ b/yarn-project/kv-store/tsconfig.json @@ -8,6 +8,9 @@ "references": [ { "path": "../foundation" + }, + { + "path": "../ethereum" } ], "include": ["src"] diff --git a/yarn-project/p2p/src/client/index.ts b/yarn-project/p2p/src/client/index.ts index 2b4c498ca59..1c0dd17bb2d 100644 --- a/yarn-project/p2p/src/client/index.ts +++ b/yarn-project/p2p/src/client/index.ts @@ -1,7 +1,8 @@ import type { ClientProtocolCircuitVerifier, L2BlockSource, WorldStateSynchronizer } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; import { type AztecKVStore } from '@aztec/kv-store'; -import { type DataStoreConfig, createStore } from '@aztec/kv-store/utils'; +import { type DataStoreConfig } from '@aztec/kv-store/config'; +import { createStore } from '@aztec/kv-store/utils'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; diff --git a/yarn-project/p2p/src/config.ts b/yarn-project/p2p/src/config.ts index c98bc9d741a..7cff1711b48 100644 --- a/yarn-project/p2p/src/config.ts +++ b/yarn-project/p2p/src/config.ts @@ -83,11 +83,6 @@ export interface P2PConfig extends P2PReqRespConfig { */ maxPeerCount: number; - /** - * Data directory for peer & tx databases. - */ - dataDirectory?: string; - /** * If announceUdpAddress or announceTcpAddress are not provided, query for the IP address of the machine. Default is false. */ @@ -222,10 +217,6 @@ export const p2pConfigMappings: ConfigMappingsType = { description: 'The maximum number of peers to connect to.', ...numberConfigHelper(100), }, - dataDirectory: { - env: 'DATA_DIRECTORY', - description: 'Data directory for peer & tx databases. Will use temporary location if not set.', - }, queryForIp: { env: 'P2P_QUERY_FOR_IP', description: diff --git a/yarn-project/p2p/src/mocks/index.ts b/yarn-project/p2p/src/mocks/index.ts index 27c37a475fa..8703ba3286b 100644 --- a/yarn-project/p2p/src/mocks/index.ts +++ b/yarn-project/p2p/src/mocks/index.ts @@ -4,7 +4,7 @@ import { type Tx, type WorldStateSynchronizer, } from '@aztec/circuit-types'; -import { type DataStoreConfig } from '@aztec/kv-store/utils'; +import { type DataStoreConfig } from '@aztec/kv-store/config'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; diff --git a/yarn-project/p2p/src/service/data_store.test.ts b/yarn-project/p2p/src/service/data_store.test.ts index 1b3b3da60a8..f46ecf32525 100644 --- a/yarn-project/p2p/src/service/data_store.test.ts +++ b/yarn-project/p2p/src/service/data_store.test.ts @@ -23,19 +23,18 @@ describe('AztecDatastore with AztecLmdbStore', () => { let datastore: AztecDatastore; let aztecStore: AztecLmdbStore; - beforeAll(() => { + beforeEach(() => { aztecStore = AztecLmdbStore.open(); + datastore = new AztecDatastore(aztecStore); }); - beforeEach(async () => { - datastore = new AztecDatastore(aztecStore); - await aztecStore.clear(); + afterEach(async () => { + await aztecStore.delete(); }); it('should store and retrieve an item', async () => { const key = new Key('testKey'); const value = new Uint8Array([1, 2, 3]); - await datastore.put(key, value); const retrieved = datastore.get(key); diff --git a/yarn-project/p2p/src/service/reqresp/reqresp.integration.test.ts b/yarn-project/p2p/src/service/reqresp/reqresp.integration.test.ts index 3a1dc6f502e..3e28c031a0d 100644 --- a/yarn-project/p2p/src/service/reqresp/reqresp.integration.test.ts +++ b/yarn-project/p2p/src/service/reqresp/reqresp.integration.test.ts @@ -4,7 +4,8 @@ import { type ClientProtocolCircuitVerifier, type WorldStateSynchronizer, mockTx import { createDebugLogger } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; import { type AztecKVStore } from '@aztec/kv-store'; -import { type DataStoreConfig, openTmpStore } from '@aztec/kv-store/utils'; +import { type DataStoreConfig } from '@aztec/kv-store/config'; +import { openTmpStore } from '@aztec/kv-store/utils'; import { SignableENR } from '@chainsafe/enr'; import { describe, expect, it, jest } from '@jest/globals'; diff --git a/yarn-project/p2p/src/util.ts b/yarn-project/p2p/src/util.ts index 0550ad5ec92..38654557483 100644 --- a/yarn-project/p2p/src/util.ts +++ b/yarn-project/p2p/src/util.ts @@ -1,4 +1,4 @@ -import { type DataStoreConfig } from '@aztec/kv-store/utils'; +import { type DataStoreConfig } from '@aztec/kv-store/config'; import type { GossipSub } from '@chainsafe/libp2p-gossipsub'; import { resolve } from 'dns/promises'; diff --git a/yarn-project/prover-node/src/config.ts b/yarn-project/prover-node/src/config.ts index ce0f8676065..12894b5cd0d 100644 --- a/yarn-project/prover-node/src/config.ts +++ b/yarn-project/prover-node/src/config.ts @@ -5,6 +5,7 @@ import { getConfigFromMappings, numberConfigHelper, } from '@aztec/foundation/config'; +import { type DataStoreConfig, dataConfigMappings, getDataConfigFromEnv } from '@aztec/kv-store/config'; import { type P2PConfig, getP2PConfigFromEnv, p2pConfigMappings } from '@aztec/p2p'; import { type ProverClientConfig, getProverEnvVars, proverClientConfigMappings } from '@aztec/prover-client'; import { @@ -30,6 +31,7 @@ export type ProverNodeConfig = ArchiverConfig & WorldStateConfig & PublisherConfig & TxSenderConfig & + DataStoreConfig & ProverCoordinationConfig & ProverBondManagerConfig & QuoteProviderConfig & { @@ -77,6 +79,7 @@ const quoteProviderConfigMappings: ConfigMappingsType = { }; export const proverNodeConfigMappings: ConfigMappingsType = { + ...dataConfigMappings, ...archiverConfigMappings, ...proverClientConfigMappings, ...p2pConfigMappings, @@ -91,6 +94,7 @@ export const proverNodeConfigMappings: ConfigMappingsType = { export function getProverNodeConfigFromEnv(): ProverNodeConfig { return { + ...getDataConfigFromEnv(), ...getArchiverConfigFromEnv(), ...getProverEnvVars(), ...getP2PConfigFromEnv(), diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index 3d9cec10579..5632ba0428d 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -3,6 +3,7 @@ import { type ProverCoordination } from '@aztec/circuit-types'; import { createEthereumChain } from '@aztec/ethereum'; import { Buffer32 } from '@aztec/foundation/buffer'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; +import { type DataStoreConfig } from '@aztec/kv-store/config'; import { RollupAbi } from '@aztec/l1-artifacts'; import { createProverClient } from '@aztec/prover-client'; import { L1Publisher } from '@aztec/sequencer-client'; @@ -25,7 +26,7 @@ import { QuoteSigner } from './quote-signer.js'; /** Creates a new prover node given a config. */ export async function createProverNode( - config: ProverNodeConfig, + config: ProverNodeConfig & DataStoreConfig, deps: { telemetry?: TelemetryClient; log?: DebugLogger; diff --git a/yarn-project/prover-node/src/prover-coordination/factory.ts b/yarn-project/prover-node/src/prover-coordination/factory.ts index 1c44d2673dc..a6353294dc2 100644 --- a/yarn-project/prover-node/src/prover-coordination/factory.ts +++ b/yarn-project/prover-node/src/prover-coordination/factory.ts @@ -2,6 +2,7 @@ import { type ArchiveSource, type Archiver } from '@aztec/archiver'; import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; import { type ProverCoordination, type WorldStateSynchronizer, createAztecNodeClient } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; +import { type DataStoreConfig } from '@aztec/kv-store/config'; import { createP2PClient } from '@aztec/p2p'; import { type TelemetryClient } from '@aztec/telemetry-client'; @@ -22,7 +23,7 @@ type ProverCoordinationDeps = { * If an aztec node is provided, it is returned directly. */ export async function createProverCoordination( - config: ProverNodeConfig, + config: ProverNodeConfig & DataStoreConfig, deps: ProverCoordinationDeps, ): Promise { const log = createDebugLogger('aztec:createProverCoordination'); diff --git a/yarn-project/pxe/src/config/index.ts b/yarn-project/pxe/src/config/index.ts index 0873a845414..d97cacbdb92 100644 --- a/yarn-project/pxe/src/config/index.ts +++ b/yarn-project/pxe/src/config/index.ts @@ -5,6 +5,7 @@ import { getConfigFromMappings, numberConfigHelper, } from '@aztec/foundation/config'; +import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config'; import { type Network } from '@aztec/types/network'; import { readFileSync } from 'fs'; @@ -35,11 +36,9 @@ export interface PXEConfig { l2BlockPollingIntervalMS: number; /** L2 block to start scanning from for new accounts */ l2StartingBlock: number; - /** Where to store PXE data. If not set, will store in memory */ - dataDirectory?: string; } -export type PXEServiceConfig = PXEConfig & KernelProverConfig & BBProverConfig; +export type PXEServiceConfig = PXEConfig & KernelProverConfig & BBProverConfig & DataStoreConfig; export type CliPXEOptions = { /** External Aztec network to connect to. e.g. devnet */ @@ -51,6 +50,7 @@ export type CliPXEOptions = { }; export const pxeConfigMappings: ConfigMappingsType = { + ...dataConfigMappings, l2BlockPollingIntervalMS: { env: 'PXE_BLOCK_POLLING_INTERVAL_MS', description: 'The interval to wait between polling for new blocks.', @@ -61,10 +61,6 @@ export const pxeConfigMappings: ConfigMappingsType = { ...numberConfigHelper(INITIAL_L2_BLOCK_NUM), description: 'L2 block to start scanning from for new accounts', }, - dataDirectory: { - env: 'PXE_DATA_DIRECTORY', - description: 'Where to store PXE data. If not set, will store in memory', - }, bbBinaryPath: { env: 'BB_BINARY_PATH', description: 'Path to the BB binary', @@ -111,6 +107,7 @@ export const pxeCliConfigMappings: ConfigMappingsType = { export const allPxeConfigMappings: ConfigMappingsType = { ...pxeConfigMappings, ...pxeCliConfigMappings, + ...dataConfigMappings, proverEnabled: { env: 'PXE_PROVER_ENABLED', parseEnv: (val: string) => ['1', 'true', 'TRUE'].includes(val) || !!process.env.NETWORK, diff --git a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts index bb608b93873..3fa9abe5b1e 100644 --- a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts @@ -31,11 +31,17 @@ export async function createPXEService( typeof useLogSuffix === 'boolean' ? (useLogSuffix ? randomBytes(3).toString('hex') : undefined) : useLogSuffix; const l1Contracts = await aztecNode.getL1ContractAddresses(); - const storeConfig = { dataDirectory: config.dataDirectory, l1Contracts }; + const configWithContracts = { + ...config, + l1Contracts, + } as PXEServiceConfig; + const keyStore = new KeyStore( - await createStore('pxe_key_store', storeConfig, createDebugLogger('aztec:pxe:keystore:lmdb')), + await createStore('pxe_key_store', configWithContracts, createDebugLogger('aztec:pxe:keystore:lmdb')), + ); + const db = new KVPxeDatabase( + await createStore('pxe_data', configWithContracts, createDebugLogger('aztec:pxe:data:lmdb')), ); - const db = new KVPxeDatabase(await createStore('pxe_data', storeConfig, createDebugLogger('aztec:pxe:data:lmdb'))); const prover = proofCreator ?? (await createProver(config, logSuffix)); const server = new PXEService(keyStore, aztecNode, db, prover, config, logSuffix); diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index ca0d00de0db..c4fd6d2a627 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -19,7 +19,13 @@ function createPXEService(): Promise { const keyStore = new KeyStore(kvStore); const node = mock(); const db = new KVPxeDatabase(kvStore); - const config: PXEServiceConfig = { l2BlockPollingIntervalMS: 100, l2StartingBlock: INITIAL_L2_BLOCK_NUM }; + const config: PXEServiceConfig = { + l2BlockPollingIntervalMS: 100, + l2StartingBlock: INITIAL_L2_BLOCK_NUM, + dataDirectory: undefined, + dataStoreMapSizeKB: 1024 * 1024, + l1Contracts: { rollupAddress: EthAddress.random() }, + }; // Setup the relevant mocks node.getBlockNumber.mockResolvedValue(2); @@ -55,7 +61,14 @@ describe('PXEService', () => { keyStore = new KeyStore(kvStore); node = mock(); db = new KVPxeDatabase(kvStore); - config = { l2BlockPollingIntervalMS: 100, l2StartingBlock: INITIAL_L2_BLOCK_NUM, proverEnabled: false }; + config = { + l2BlockPollingIntervalMS: 100, + l2StartingBlock: INITIAL_L2_BLOCK_NUM, + proverEnabled: false, + dataDirectory: undefined, + dataStoreMapSizeKB: 1024 * 1024, + l1Contracts: { rollupAddress: EthAddress.random() }, + }; }); it('throws when submitting a tx with a nullifier of already settled tx', async () => { diff --git a/yarn-project/simulator/src/public/public_tx_simulator.test.ts b/yarn-project/simulator/src/public/public_tx_simulator.test.ts index cf61b574431..48ef94ea6f6 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.test.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.test.ts @@ -24,6 +24,7 @@ import { } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot, siloNullifier } from '@aztec/circuits.js/hash'; import { fr } from '@aztec/circuits.js/testing'; +import { type AztecKVStore } from '@aztec/kv-store'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type AppendOnlyTree, Poseidon, StandardTree, newTree } from '@aztec/merkle-tree'; @@ -56,6 +57,7 @@ describe('public_tx_simulator', () => { let publicDataTree: AppendOnlyTree; let processor: PublicTxSimulator; + let treeStore: AztecKVStore; const mockTxWithPublicCalls = ({ numberOfSetupCalls = 0, @@ -132,9 +134,11 @@ describe('public_tx_simulator', () => { return Promise.resolve(result); }); + treeStore = openTmpStore(); + publicDataTree = await newTree( StandardTree, - openTmpStore(), + treeStore, new Poseidon(), 'PublicData', Fr, @@ -168,6 +172,10 @@ describe('public_tx_simulator', () => { ); }); + afterEach(async () => { + await treeStore.delete(); + }); + it('runs a tx with enqueued public calls in setup phase only', async () => { const tx = mockTxWithPublicCalls({ numberOfSetupCalls: 2, diff --git a/yarn-project/world-state/src/native/native_world_state.ts b/yarn-project/world-state/src/native/native_world_state.ts index 260bfc15a31..8dc112fecfc 100644 --- a/yarn-project/world-state/src/native/native_world_state.ts +++ b/yarn-project/world-state/src/native/native_world_state.ts @@ -59,19 +59,20 @@ export class NativeWorldStateService implements MerkleTreeDatabase { log = createDebugLogger('aztec:world-state:database'), cleanup = () => Promise.resolve(), ): Promise { - const rollupAddressFile = join(dataDir, ROLLUP_ADDRESS_FILE); + const worldStateDirectory = join(dataDir, 'world_state'); + const rollupAddressFile = join(worldStateDirectory, ROLLUP_ADDRESS_FILE); const currentRollupStr = await readFile(rollupAddressFile, 'utf8').catch(() => undefined); const currentRollupAddress = currentRollupStr ? EthAddress.fromString(currentRollupStr.trim()) : undefined; if (currentRollupAddress && !rollupAddress.equals(currentRollupAddress)) { log.warn('Rollup address changed, deleting database'); - await rm(dataDir, { recursive: true, force: true }); + await rm(worldStateDirectory, { recursive: true, force: true }); } - await mkdir(dataDir, { recursive: true }); + await mkdir(worldStateDirectory, { recursive: true }); await writeFile(rollupAddressFile, rollupAddress.toString(), 'utf8'); - const instance = new NativeWorldState(dataDir, dbMapSizeKb); + const instance = new NativeWorldState(worldStateDirectory, dbMapSizeKb); const worldState = new this(instance, log, cleanup); try { await worldState.init(); diff --git a/yarn-project/world-state/src/native/native_world_state_cmp.test.ts b/yarn-project/world-state/src/native/native_world_state_cmp.test.ts index 32e5a77e01e..1e18bc0ca06 100644 --- a/yarn-project/world-state/src/native/native_world_state_cmp.test.ts +++ b/yarn-project/world-state/src/native/native_world_state_cmp.test.ts @@ -8,6 +8,7 @@ import { import { EthAddress, Fr, GENESIS_ARCHIVE_ROOT, NullifierLeaf, PublicDataTreeLeaf } from '@aztec/circuits.js'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { elapsed } from '@aztec/foundation/timer'; +import { type AztecKVStore } from '@aztec/kv-store'; import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -31,6 +32,8 @@ describe('NativeWorldState', () => { let log: DebugLogger; + let legacyStore: AztecKVStore; + const allTrees = Object.values(MerkleTreeId) .filter((x): x is MerkleTreeId => typeof x === 'number') .map(x => [MerkleTreeId[x], x] as const); @@ -43,13 +46,14 @@ describe('NativeWorldState', () => { }); afterAll(async () => { + await legacyStore.delete(); await rm(nativeDataDir, { recursive: true }); - await rm(legacyDataDir, { recursive: true }); }); beforeAll(async () => { + legacyStore = AztecLmdbStore.open(legacyDataDir); nativeWS = await NativeWorldStateService.new(EthAddress.random(), nativeDataDir, 1024 * 1024); - legacyWS = await MerkleTrees.new(AztecLmdbStore.open(legacyDataDir), new NoopTelemetryClient()); + legacyWS = await MerkleTrees.new(legacyStore, new NoopTelemetryClient()); }); it('has to expected genesis archive tree root', async () => { diff --git a/yarn-project/world-state/src/native/native_world_state_instance.ts b/yarn-project/world-state/src/native/native_world_state_instance.ts index 01f6871c0b4..671baaa4fe6 100644 --- a/yarn-project/world-state/src/native/native_world_state_instance.ts +++ b/yarn-project/world-state/src/native/native_world_state_instance.ts @@ -83,6 +83,7 @@ export class NativeWorldState implements NativeWorldStateInstance { /** Creates a new native WorldState instance */ constructor(dataDir: string, dbMapSizeKb: number, private log = createDebugLogger('aztec:world-state:database')) { + log.info(`Creating world state data store at directory ${dataDir} with map size ${dbMapSizeKb} KB`); this.instance = new NATIVE_MODULE[NATIVE_CLASS_NAME]( dataDir, { diff --git a/yarn-project/world-state/src/synchronizer/config.ts b/yarn-project/world-state/src/synchronizer/config.ts index 1308cd801a3..4b90127e952 100644 --- a/yarn-project/world-state/src/synchronizer/config.ts +++ b/yarn-project/world-state/src/synchronizer/config.ts @@ -11,8 +11,11 @@ export interface WorldStateConfig { /** Size of the batch for each get-blocks request from the synchronizer to the archiver. */ worldStateBlockRequestBatchSize?: number; - /** The maximum size of the combined world state db in KB*/ - worldStateDbMapSizeKb: number; + /** The maximum size of the combined world state db in KB, optional, will inherit from the general dataStoreMapSizeKB if not specified*/ + worldStateDbMapSizeKb?: number; + + /** Optional directory for the world state DB, if unspecified will default to the general data directory */ + worldStateDataDirectory?: string; } export const worldStateConfigMappings: ConfigMappingsType = { @@ -35,9 +38,12 @@ export const worldStateConfigMappings: ConfigMappingsType = { worldStateDbMapSizeKb: { env: 'WS_DB_MAP_SIZE_KB', parseEnv: (val: string | undefined) => (val ? +val : undefined), - defaultValue: 1024 * 1024 * 1024, // 1TB description: 'The maximum possible size of the world state DB', }, + worldStateDataDirectory: { + env: 'WS_DATA_DIRECTORY', + description: 'Optional directory for the world state database', + }, }; /** diff --git a/yarn-project/world-state/src/synchronizer/factory.ts b/yarn-project/world-state/src/synchronizer/factory.ts index 7a846652ca4..fa2a7c43ef4 100644 --- a/yarn-project/world-state/src/synchronizer/factory.ts +++ b/yarn-project/world-state/src/synchronizer/factory.ts @@ -1,6 +1,7 @@ import { type L1ToL2MessageSource, type L2BlockSource } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type DataStoreConfig, createStore } from '@aztec/kv-store/utils'; +import { type DataStoreConfig } from '@aztec/kv-store/config'; +import { createStore } from '@aztec/kv-store/utils'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -22,16 +23,20 @@ export async function createWorldState( config: WorldStateConfig & DataStoreConfig, client: TelemetryClient = new NoopTelemetryClient(), ) { + const newConfig = { + dataDirectory: config.worldStateDataDirectory ?? config.dataDirectory, + dataStoreMapSizeKB: config.worldStateDbMapSizeKb ?? config.dataStoreMapSizeKB, + } as DataStoreConfig; const merkleTrees = ['true', '1'].includes(process.env.USE_LEGACY_WORLD_STATE ?? '') ? await MerkleTrees.new( - await createStore('world-state', config, createDebugLogger('aztec:world-state:lmdb')), + await createStore('world-state', newConfig, createDebugLogger('aztec:world-state:lmdb')), client, ) - : config.dataDirectory + : newConfig.dataDirectory ? await NativeWorldStateService.new( config.l1Contracts.rollupAddress, - config.dataDirectory, - config.worldStateDbMapSizeKb, + newConfig.dataDirectory, + newConfig.dataStoreMapSizeKB, ) : await NativeWorldStateService.tmp( config.l1Contracts.rollupAddress, diff --git a/yarn-project/world-state/src/test/integration.test.ts b/yarn-project/world-state/src/test/integration.test.ts index 3a6752f011f..8f839a4d9eb 100644 --- a/yarn-project/world-state/src/test/integration.test.ts +++ b/yarn-project/world-state/src/test/integration.test.ts @@ -3,7 +3,7 @@ import { type L2Block, MerkleTreeId } from '@aztec/circuit-types'; import { EthAddress, type Fr } from '@aztec/circuits.js'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; -import { type DataStoreConfig } from '@aztec/kv-store/utils'; +import { type DataStoreConfig } from '@aztec/kv-store/config'; import { jest } from '@jest/globals'; @@ -38,6 +38,7 @@ describe('world-state integration', () => { beforeEach(async () => { config = { dataDirectory: undefined, + dataStoreMapSizeKB: 1024 * 1024, l1Contracts: { rollupAddress }, worldStateBlockCheckIntervalMS: 20, worldStateProvenBlocksOnly: false, diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 070edc9e94c..196a74d9b03 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -763,6 +763,7 @@ __metadata: version: 0.0.0-use.local resolution: "@aztec/kv-store@workspace:kv-store" dependencies: + "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@jest/globals": ^29.5.0 "@types/jest": ^29.5.0