@aztec/cli 3.0.0-nightly.20250929 → 3.0.0-nightly.20251001

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ export interface CachedFetchOptions {
2
+ /** Cache duration in milliseconds */
3
+ cacheDurationMs: number;
4
+ /** The cache file */
5
+ cacheFile?: string;
6
+ }
7
+ /**
8
+ * Fetches data from a URL with file-based caching support.
9
+ * This utility can be used by both remote config and bootnodes fetching.
10
+ *
11
+ * @param url - The URL to fetch from
12
+ * @param networkName - Network name for cache directory structure
13
+ * @param options - Caching and error handling options
14
+ * @param cacheDir - Optional cache directory (defaults to no caching)
15
+ * @returns The fetched and parsed JSON data, or undefined if fetch fails and throwOnError is false
16
+ */
17
+ export declare function cachedFetch<T = any>(url: string, options: CachedFetchOptions, fetch?: typeof globalThis.fetch, log?: import("@aztec/aztec.js").Logger): Promise<T | undefined>;
18
+ //# sourceMappingURL=cached_fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cached_fetch.d.ts","sourceRoot":"","sources":["../../src/config/cached_fetch.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,CAAC,GAAG,GAAG,EACvC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,kBAAkB,EAC3B,KAAK,0BAAmB,EACxB,GAAG,mCAA+B,GACjC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAuCxB"}
@@ -0,0 +1,54 @@
1
+ import { createLogger } from '@aztec/aztec.js';
2
+ import { mkdir, readFile, stat, writeFile } from 'fs/promises';
3
+ import { dirname } from 'path';
4
+ /**
5
+ * Fetches data from a URL with file-based caching support.
6
+ * This utility can be used by both remote config and bootnodes fetching.
7
+ *
8
+ * @param url - The URL to fetch from
9
+ * @param networkName - Network name for cache directory structure
10
+ * @param options - Caching and error handling options
11
+ * @param cacheDir - Optional cache directory (defaults to no caching)
12
+ * @returns The fetched and parsed JSON data, or undefined if fetch fails and throwOnError is false
13
+ */ export async function cachedFetch(url, options, fetch = globalThis.fetch, log = createLogger('cached_fetch')) {
14
+ const { cacheDurationMs, cacheFile } = options;
15
+ // Try to read from cache first
16
+ try {
17
+ if (cacheFile) {
18
+ const info = await stat(cacheFile);
19
+ if (info.mtimeMs + cacheDurationMs > Date.now()) {
20
+ const cachedData = JSON.parse(await readFile(cacheFile, 'utf-8'));
21
+ return cachedData;
22
+ }
23
+ }
24
+ } catch {
25
+ log.trace('Failed to read data from cache');
26
+ }
27
+ try {
28
+ const response = await fetch(url);
29
+ if (!response.ok) {
30
+ log.warn(`Failed to fetch from ${url}: ${response.status} ${response.statusText}`);
31
+ return undefined;
32
+ }
33
+ const data = await response.json();
34
+ try {
35
+ if (cacheFile) {
36
+ await mkdir(dirname(cacheFile), {
37
+ recursive: true
38
+ });
39
+ await writeFile(cacheFile, JSON.stringify(data), 'utf-8');
40
+ }
41
+ } catch (err) {
42
+ log.warn('Failed to cache data on disk: ' + cacheFile, {
43
+ cacheFile,
44
+ err
45
+ });
46
+ }
47
+ return data;
48
+ } catch (err) {
49
+ log.warn(`Failed to fetch from ${url}`, {
50
+ err
51
+ });
52
+ return undefined;
53
+ }
54
+ }
@@ -21,11 +21,17 @@ export type L2ChainConfig = L1ContractsConfig & Omit<SlasherConfig, 'slashValida
21
21
  publicIncludeMetrics?: string[];
22
22
  publicMetricsCollectorUrl?: string;
23
23
  publicMetricsCollectFrom?: string[];
24
+ dbMapSizeKb: number;
25
+ archiverStoreMapSizeKb: number;
26
+ noteHashTreeMapSizeKb: number;
27
+ nullifierTreeMapSizeKb: number;
28
+ publicDataTreeMapSizeKb: number;
24
29
  sentinelEnabled: boolean;
25
30
  };
26
31
  export declare const stagingIgnitionL2ChainConfig: L2ChainConfig;
27
32
  export declare const stagingPublicL2ChainConfig: L2ChainConfig;
28
33
  export declare const testnetL2ChainConfig: L2ChainConfig;
34
+ export declare const ignitionL2ChainConfig: L2ChainConfig;
29
35
  export declare function getBootnodes(networkName: NetworkNames, cacheDir?: string): Promise<any>;
30
36
  export declare function getL2ChainConfig(networkName: NetworkNames, cacheDir?: string): Promise<L2ChainConfig | undefined>;
31
37
  export declare function enrichEnvironmentWithChainConfig(networkName: NetworkNames): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"chain_l2_config.d.ts","sourceRoot":"","sources":["../../src/config/chain_l2_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AASrE,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAC3C,IAAI,CAAC,aAAa,EAAE,sBAAsB,GAAG,uBAAuB,CAAC,GAAG;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;IAGpC,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAuCJ,eAAO,MAAM,4BAA4B,EAAE,aA+E1C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,aAmDxC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,aAqDlC,CAAC;AAIF,wBAAsB,YAAY,CAAC,WAAW,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,gBAgC9E;AAED,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,YAAY,EACzB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAkBpC;AAuBD,wBAAsB,gCAAgC,CAAC,WAAW,EAAE,YAAY,iBA0F/E"}
1
+ {"version":3,"file":"chain_l2_config.d.ts","sourceRoot":"","sources":["../../src/config/chain_l2_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAarE,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAC3C,IAAI,CAAC,aAAa,EAAE,sBAAsB,GAAG,uBAAuB,CAAC,GAAG;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;IAIpC,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,uBAAuB,EAAE,MAAM,CAAC;IAGhC,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AA+CJ,eAAO,MAAM,4BAA4B,EAAE,aAiF1C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,aAqDxC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,aAuDlC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,aAmFnC,CAAC;AAIF,wBAAsB,YAAY,CAAC,WAAW,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,gBAQ9E;AAED,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,YAAY,EACzB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAoBpC;AAMD,wBAAsB,gCAAgC,CAAC,WAAW,EAAE,YAAY,iBAgG/E"}
@@ -1,11 +1,14 @@
1
1
  import { DefaultL1ContractsConfig } from '@aztec/ethereum';
2
2
  import { EthAddress } from '@aztec/foundation/eth-address';
3
- import { mkdir, readFile, stat, writeFile } from 'fs/promises';
4
- import path, { dirname, join } from 'path';
3
+ import path, { join } from 'path';
5
4
  import publicIncludeMetrics from '../../public_include_metric_prefixes.json' with {
6
5
  type: 'json'
7
6
  };
7
+ import { cachedFetch } from './cached_fetch.js';
8
+ import { enrichEthAddressVar, enrichVar } from './enrich_env.js';
8
9
  const SNAPSHOT_URL = 'https://pub-f4a8c34d4bb7441ebf8f48d904512180.r2.dev/snapshots';
10
+ const defaultDBMapSizeKb = 128 * 1_024 * 1_024; // 128 GB
11
+ const tbMapSizeKb = 1_024 * 1_024 * 1_024; // 1 TB
9
12
  const DefaultSlashConfig = {
10
13
  /** Tally-style slashing */ slasherFlavor: 'tally',
11
14
  /** Allow one round for vetoing */ slashingExecutionDelayInRounds: 1,
@@ -34,15 +37,22 @@ const DefaultSlashConfig = {
34
37
  sentinelEnabled: true,
35
38
  slashExecuteRoundsLookBack: 4
36
39
  };
40
+ const DefaultNetworkDBMapSizeConfig = {
41
+ dbMapSizeKb: defaultDBMapSizeKb,
42
+ archiverStoreMapSizeKb: tbMapSizeKb,
43
+ noteHashTreeMapSizeKb: tbMapSizeKb,
44
+ nullifierTreeMapSizeKb: tbMapSizeKb,
45
+ publicDataTreeMapSizeKb: tbMapSizeKb
46
+ };
37
47
  export const stagingIgnitionL2ChainConfig = {
38
48
  l1ChainId: 11155111,
39
49
  testAccounts: false,
40
50
  sponsoredFPC: false,
41
51
  p2pEnabled: true,
42
52
  p2pBootstrapNodes: [],
43
- registryAddress: '0x5f85fa0f40bc4b5ccd53c9f34258aa55d25cdde8',
44
- slashFactoryAddress: '0x257db2ca1471b7f76f414d2997404bfbe916c8c9',
45
- feeAssetHandlerAddress: '0x67d645b0a3e053605ea861d7e8909be6669812c4',
53
+ registryAddress: '0x53e2c2148da04fd0e8dd282f016f627a187c292c',
54
+ slashFactoryAddress: '0x56448efb139ef440438dfa445333734ea5ed60a0',
55
+ feeAssetHandlerAddress: '0x3613b834544030c166a4d47eca14b910f4816f57',
46
56
  seqMinTxsPerBlock: 0,
47
57
  seqMaxTxsPerBlock: 0,
48
58
  realProofs: true,
@@ -97,7 +107,8 @@ export const stagingIgnitionL2ChainConfig = {
97
107
  slashOffenseExpirationRounds: 8,
98
108
  sentinelEnabled: true,
99
109
  slashingDisableDuration: 5 * 24 * 60 * 60,
100
- slashExecuteRoundsLookBack: 4
110
+ slashExecuteRoundsLookBack: 4,
111
+ ...DefaultNetworkDBMapSizeConfig
101
112
  };
102
113
  export const stagingPublicL2ChainConfig = {
103
114
  l1ChainId: 11155111,
@@ -105,9 +116,9 @@ export const stagingPublicL2ChainConfig = {
105
116
  sponsoredFPC: true,
106
117
  p2pEnabled: true,
107
118
  p2pBootstrapNodes: [],
108
- registryAddress: '0x2e48addca360da61e4d6c21ff2b1961af56eb83b',
109
- slashFactoryAddress: '0xe19410632fd00695bc5a08dd82044b7b26317742',
110
- feeAssetHandlerAddress: '0xb46dc3d91f849999330b6dd93473fa29fc45b076',
119
+ registryAddress: '0xe83067689f3cf837ccbf8a3966f0e0fe985dcb3e',
120
+ slashFactoryAddress: '0x8b87a1812162d4890f01bb40f410047f37d3ceb8',
121
+ feeAssetHandlerAddress: '0xa8159159a9e2a57c6e8c59fd5b3dd94c6dbddfe3',
111
122
  seqMinTxsPerBlock: 0,
112
123
  seqMaxTxsPerBlock: 20,
113
124
  realProofs: true,
@@ -135,7 +146,8 @@ export const stagingPublicL2ChainConfig = {
135
146
  /** The mana target for the rollup */ manaTarget: DefaultL1ContractsConfig.manaTarget,
136
147
  /** The proving cost per mana */ provingCostPerMana: DefaultL1ContractsConfig.provingCostPerMana,
137
148
  /** Exit delay for stakers */ exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
138
- ...DefaultSlashConfig
149
+ ...DefaultSlashConfig,
150
+ ...DefaultNetworkDBMapSizeConfig
139
151
  };
140
152
  export const testnetL2ChainConfig = {
141
153
  l1ChainId: 11155111,
@@ -175,38 +187,83 @@ export const testnetL2ChainConfig = {
175
187
  /** Exit delay for stakers */ exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
176
188
  ...DefaultSlashConfig,
177
189
  slashPrunePenalty: 0n,
178
- slashDataWithholdingPenalty: 0n
190
+ slashDataWithholdingPenalty: 0n,
191
+ ...DefaultNetworkDBMapSizeConfig
192
+ };
193
+ export const ignitionL2ChainConfig = {
194
+ l1ChainId: 1,
195
+ testAccounts: false,
196
+ sponsoredFPC: false,
197
+ p2pEnabled: true,
198
+ p2pBootstrapNodes: [],
199
+ registryAddress: '',
200
+ slashFactoryAddress: '',
201
+ feeAssetHandlerAddress: '',
202
+ seqMinTxsPerBlock: 0,
203
+ seqMaxTxsPerBlock: 0,
204
+ realProofs: true,
205
+ snapshotsUrl: 'https://storage.googleapis.com/aztec-testnet/snapshots/ignition/',
206
+ autoUpdate: 'notify',
207
+ autoUpdateUrl: 'https://storage.googleapis.com/aztec-testnet/auto-update/ignition.json',
208
+ maxTxPoolSize: 100_000_000,
209
+ publicIncludeMetrics,
210
+ publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
211
+ publicMetricsCollectFrom: [
212
+ 'sequencer'
213
+ ],
214
+ /** How many seconds an L1 slot lasts. */ ethereumSlotDuration: 12,
215
+ /** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */ aztecSlotDuration: 72,
216
+ /** How many L2 slots an epoch lasts. */ aztecEpochDuration: 32,
217
+ /** The target validator committee size. */ aztecTargetCommitteeSize: 24,
218
+ /** The number of epochs after an epoch ends that proofs are still accepted. */ aztecProofSubmissionEpochs: 1,
219
+ /** How many sequencers must agree with a slash for it to be executed. */ slashingQuorum: 65,
220
+ /** The number of epochs to lag behind the current epoch for validator selection. */ lagInEpochs: 2,
221
+ localEjectionThreshold: 196_000n * 10n ** 18n,
222
+ slashingDisableDuration: 5 * 24 * 60 * 60,
223
+ slashingRoundSizeInEpochs: 4,
224
+ slashingLifetimeInRounds: 40,
225
+ slashingExecutionDelayInRounds: 28,
226
+ slashAmountSmall: 2_000n * 10n ** 18n,
227
+ slashAmountMedium: 10_000n * 10n ** 18n,
228
+ slashAmountLarge: 50_000n * 10n ** 18n,
229
+ slashingOffsetInRounds: 2,
230
+ slasherFlavor: 'tally',
231
+ slashingVetoer: EthAddress.ZERO,
232
+ /** The mana target for the rollup */ manaTarget: 0n,
233
+ exitDelaySeconds: 5 * 24 * 60 * 60,
234
+ /** The proving cost per mana */ provingCostPerMana: 0n,
235
+ ejectionThreshold: 100_000n * 10n ** 18n,
236
+ activationThreshold: 200_000n * 10n ** 18n,
237
+ governanceProposerRoundSize: 300,
238
+ governanceProposerQuorum: 151,
239
+ // Node slashing config
240
+ // TODO TMNT-330
241
+ slashMinPenaltyPercentage: 0.5,
242
+ slashMaxPenaltyPercentage: 2.0,
243
+ slashInactivityTargetPercentage: 0.7,
244
+ slashInactivityConsecutiveEpochThreshold: 2,
245
+ slashInactivityPenalty: 2_000n * 10n ** 18n,
246
+ slashPrunePenalty: 0n,
247
+ slashDataWithholdingPenalty: 0n,
248
+ slashProposeInvalidAttestationsPenalty: 50_000n * 10n ** 18n,
249
+ slashAttestDescendantOfInvalidPenalty: 50_000n * 10n ** 18n,
250
+ slashUnknownPenalty: 2_000n * 10n ** 18n,
251
+ slashBroadcastedInvalidBlockPenalty: 0n,
252
+ slashMaxPayloadSize: 50,
253
+ slashGracePeriodL2Slots: 32 * 4,
254
+ slashOffenseExpirationRounds: 8,
255
+ sentinelEnabled: true,
256
+ slashExecuteRoundsLookBack: 4,
257
+ ...DefaultNetworkDBMapSizeConfig
179
258
  };
180
259
  const BOOTNODE_CACHE_DURATION_MS = 60 * 60 * 1000; // 1 hour;
181
260
  export async function getBootnodes(networkName, cacheDir) {
182
- const cacheFile = cacheDir ? join(cacheDir, networkName, 'bootnodes.json') : undefined;
183
- try {
184
- if (cacheFile) {
185
- const info = await stat(cacheFile);
186
- if (info.mtimeMs + BOOTNODE_CACHE_DURATION_MS > Date.now()) {
187
- return JSON.parse(await readFile(cacheFile, 'utf-8'))['bootnodes'];
188
- }
189
- }
190
- } catch {
191
- // no-op. Get the remote-file
192
- }
193
261
  const url = `http://static.aztec.network/${networkName}/bootnodes.json`;
194
- const response = await fetch(url);
195
- if (!response.ok) {
196
- throw new Error(`Failed to fetch basic contract addresses from ${url}. Check you are using a correct network name.`);
197
- }
198
- const json = await response.json();
199
- try {
200
- if (cacheFile) {
201
- await mkdir(dirname(cacheFile), {
202
- recursive: true
203
- });
204
- await writeFile(cacheFile, JSON.stringify(json), 'utf-8');
205
- }
206
- } catch {
207
- // no-op
208
- }
209
- return json['bootnodes'];
262
+ const data = await cachedFetch(url, {
263
+ cacheDurationMs: BOOTNODE_CACHE_DURATION_MS,
264
+ cacheFile: cacheDir ? join(cacheDir, networkName, 'bootnodes.json') : undefined
265
+ });
266
+ return data?.bootnodes;
210
267
  }
211
268
  export async function getL2ChainConfig(networkName, cacheDir) {
212
269
  let config;
@@ -222,6 +279,10 @@ export async function getL2ChainConfig(networkName, cacheDir) {
222
279
  config = {
223
280
  ...stagingIgnitionL2ChainConfig
224
281
  };
282
+ } else if (networkName === 'ignition') {
283
+ config = {
284
+ ...ignitionL2ChainConfig
285
+ };
225
286
  }
226
287
  if (!config) {
227
288
  return undefined;
@@ -233,21 +294,6 @@ export async function getL2ChainConfig(networkName, cacheDir) {
233
294
  }
234
295
  return config;
235
296
  }
236
- function enrichVar(envVar, value) {
237
- // Don't override
238
- if (process.env[envVar] || value === undefined) {
239
- return;
240
- }
241
- process.env[envVar] = value;
242
- }
243
- function enrichEthAddressVar(envVar, value) {
244
- // EthAddress doesn't like being given empty strings
245
- if (value === '') {
246
- enrichVar(envVar, EthAddress.ZERO.toString());
247
- return;
248
- }
249
- enrichVar(envVar, value);
250
- }
251
297
  function getDefaultDataDir(networkName) {
252
298
  return path.join(process.env.HOME || '~', '.aztec', networkName, 'data');
253
299
  }
@@ -272,6 +318,11 @@ export async function enrichEnvironmentWithChainConfig(networkName) {
272
318
  enrichVar('PXE_PROVER_ENABLED', config.realProofs.toString());
273
319
  enrichVar('SYNC_SNAPSHOTS_URL', config.snapshotsUrl);
274
320
  enrichVar('P2P_MAX_TX_POOL_SIZE', config.maxTxPoolSize.toString());
321
+ enrichVar('DATA_STORE_MAP_SIZE_KB', config.dbMapSizeKb.toString());
322
+ enrichVar('ARCHIVER_STORE_MAP_SIZE_KB', config.archiverStoreMapSizeKb.toString());
323
+ enrichVar('NOTE_HASH_TREE_MAP_SIZE_KB', config.noteHashTreeMapSizeKb.toString());
324
+ enrichVar('NULLIFIER_TREE_MAP_SIZE_KB', config.nullifierTreeMapSizeKb.toString());
325
+ enrichVar('PUBLIC_DATA_TREE_MAP_SIZE_KB', config.publicDataTreeMapSizeKb.toString());
275
326
  if (config.autoUpdate) {
276
327
  enrichVar('AUTO_UPDATE', config.autoUpdate?.toString());
277
328
  }
@@ -0,0 +1,4 @@
1
+ import type { EnvVar } from '@aztec/foundation/config';
2
+ export declare function enrichVar(envVar: EnvVar, value: string | undefined): void;
3
+ export declare function enrichEthAddressVar(envVar: EnvVar, value: string): void;
4
+ //# sourceMappingURL=enrich_env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrich_env.d.ts","sourceRoot":"","sources":["../../src/config/enrich_env.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,QAMlE;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAGhE"}
@@ -0,0 +1,12 @@
1
+ import { EthAddress } from '@aztec/aztec.js';
2
+ export function enrichVar(envVar, value) {
3
+ // Don't override
4
+ if (process.env[envVar] || value === undefined) {
5
+ return;
6
+ }
7
+ process.env[envVar] = value;
8
+ }
9
+ export function enrichEthAddressVar(envVar, value) {
10
+ // EthAddress doesn't like being given empty strings
11
+ enrichVar(envVar, value || EthAddress.ZERO.toString());
12
+ }
@@ -1,3 +1,5 @@
1
+ export * from './cached_fetch.js';
1
2
  export * from './chain_l2_config.js';
2
3
  export * from './get_l1_config.js';
4
+ export * from './network_config.js';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC"}
@@ -1,2 +1,4 @@
1
+ export * from './cached_fetch.js';
1
2
  export * from './chain_l2_config.js';
2
3
  export * from './get_l1_config.js';
4
+ export * from './network_config.js';
@@ -0,0 +1,19 @@
1
+ import { type NetworkConfig, type NetworkNames } from '@aztec/foundation/config';
2
+ /**
3
+ * Fetches remote network configuration from GitHub with caching support.
4
+ * Uses the reusable cachedFetch utility.
5
+ *
6
+ * @param networkName - The network name to fetch config for
7
+ * @param cacheDir - Optional cache directory for storing fetched config
8
+ * @returns Remote configuration for the specified network, or undefined if not found/error
9
+ */
10
+ export declare function getNetworkConfig(networkName: NetworkNames, cacheDir?: string): Promise<NetworkConfig | undefined>;
11
+ /**
12
+ * Enriches environment variables with remote network configuration.
13
+ * This function is called before node config initialization to set env vars
14
+ * from the remote config, following the same pattern as enrichEnvironmentWithChainConfig().
15
+ *
16
+ * @param networkName - The network name to fetch remote config for
17
+ */
18
+ export declare function enrichEnvironmentWithNetworkConfig(networkName: NetworkNames): Promise<void>;
19
+ //# sourceMappingURL=network_config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network_config.d.ts","sourceRoot":"","sources":["../../src/config/network_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAA0B,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAYzG;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,YAAY,EACzB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAiDpC;AAED;;;;;;GAMG;AACH,wBAAsB,kCAAkC,CAAC,WAAW,EAAE,YAAY,iBA0BjF"}
@@ -0,0 +1,84 @@
1
+ import { NetworkConfigMapSchema } from '@aztec/foundation/config';
2
+ import { readFile } from 'fs/promises';
3
+ import { join } from 'path';
4
+ import { cachedFetch } from './cached_fetch.js';
5
+ import { enrichEthAddressVar, enrichVar } from './enrich_env.js';
6
+ const DEFAULT_CONFIG_URL = 'https://raw.githubusercontent.com/AztecProtocol/networks/refs/heads/main/network_config.json';
7
+ const NETWORK_CONFIG_CACHE_DURATION_MS = 60 * 60 * 1000; // 1 hour
8
+ /**
9
+ * Fetches remote network configuration from GitHub with caching support.
10
+ * Uses the reusable cachedFetch utility.
11
+ *
12
+ * @param networkName - The network name to fetch config for
13
+ * @param cacheDir - Optional cache directory for storing fetched config
14
+ * @returns Remote configuration for the specified network, or undefined if not found/error
15
+ */ export async function getNetworkConfig(networkName, cacheDir) {
16
+ let url;
17
+ const configLocation = process.env.NETWORK_CONFIG_LOCATION || DEFAULT_CONFIG_URL;
18
+ if (!configLocation) {
19
+ return undefined;
20
+ }
21
+ try {
22
+ if (configLocation.includes('://')) {
23
+ url = new URL(configLocation);
24
+ } else {
25
+ url = new URL(`file://${configLocation}`);
26
+ }
27
+ } catch {
28
+ /* no-op */ }
29
+ if (!url) {
30
+ return undefined;
31
+ }
32
+ try {
33
+ let rawConfig;
34
+ if (url.protocol === 'http:' || url.protocol === 'https:') {
35
+ rawConfig = await cachedFetch(url.href, {
36
+ cacheDurationMs: NETWORK_CONFIG_CACHE_DURATION_MS,
37
+ cacheFile: cacheDir ? join(cacheDir, networkName, 'network_config.json') : undefined
38
+ });
39
+ } else if (url.protocol === 'file:') {
40
+ rawConfig = JSON.parse(await readFile(url.pathname, 'utf-8'));
41
+ } else {
42
+ throw new Error('Unsupported Aztec network config protocol: ' + url.href);
43
+ }
44
+ if (!rawConfig) {
45
+ return undefined;
46
+ }
47
+ const networkConfigMap = NetworkConfigMapSchema.parse(rawConfig);
48
+ if (networkName in networkConfigMap) {
49
+ return networkConfigMap[networkName];
50
+ } else {
51
+ return undefined;
52
+ }
53
+ } catch {
54
+ return undefined;
55
+ }
56
+ }
57
+ /**
58
+ * Enriches environment variables with remote network configuration.
59
+ * This function is called before node config initialization to set env vars
60
+ * from the remote config, following the same pattern as enrichEnvironmentWithChainConfig().
61
+ *
62
+ * @param networkName - The network name to fetch remote config for
63
+ */ export async function enrichEnvironmentWithNetworkConfig(networkName) {
64
+ if (networkName === 'local') {
65
+ return; // No remote config for local development
66
+ }
67
+ const cacheDir = process.env.DATA_DIRECTORY ? join(process.env.DATA_DIRECTORY, 'cache') : undefined;
68
+ const networkConfig = await getNetworkConfig(networkName, cacheDir);
69
+ if (!networkConfig) {
70
+ return;
71
+ }
72
+ enrichVar('BOOTSTRAP_NODES', networkConfig.bootnodes.join(','));
73
+ enrichVar('L1_CHAIN_ID', String(networkConfig.l1ChainId));
74
+ // Snapshot synch only supports a single source. Take the first
75
+ // See A-101 for more details
76
+ const firstSource = networkConfig[0];
77
+ if (firstSource) {
78
+ enrichVar('SYNC_SNAPSHOTS_URL', networkConfig.snapshots.join(','));
79
+ }
80
+ enrichEthAddressVar('REGISTRY_CONTRACT_ADDRESS', networkConfig.registryAddress.toString());
81
+ if (networkConfig.feeAssetHandlerAddress) {
82
+ enrichEthAddressVar('FEE_ASSET_HANDLER_CONTRACT_ADDRESS', networkConfig.feeAssetHandlerAddress.toString());
83
+ }
84
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/cli",
3
- "version": "3.0.0-nightly.20250929",
3
+ "version": "3.0.0-nightly.20251001",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./contracts": "./dest/cmds/contracts/index.js",
@@ -70,20 +70,20 @@
70
70
  ]
71
71
  },
72
72
  "dependencies": {
73
- "@aztec/accounts": "3.0.0-nightly.20250929",
74
- "@aztec/archiver": "3.0.0-nightly.20250929",
75
- "@aztec/aztec.js": "3.0.0-nightly.20250929",
76
- "@aztec/constants": "3.0.0-nightly.20250929",
77
- "@aztec/entrypoints": "3.0.0-nightly.20250929",
78
- "@aztec/ethereum": "3.0.0-nightly.20250929",
79
- "@aztec/foundation": "3.0.0-nightly.20250929",
80
- "@aztec/l1-artifacts": "3.0.0-nightly.20250929",
81
- "@aztec/node-lib": "3.0.0-nightly.20250929",
82
- "@aztec/p2p": "3.0.0-nightly.20250929",
83
- "@aztec/protocol-contracts": "3.0.0-nightly.20250929",
84
- "@aztec/stdlib": "3.0.0-nightly.20250929",
85
- "@aztec/test-wallet": "3.0.0-nightly.20250929",
86
- "@aztec/world-state": "3.0.0-nightly.20250929",
73
+ "@aztec/accounts": "3.0.0-nightly.20251001",
74
+ "@aztec/archiver": "3.0.0-nightly.20251001",
75
+ "@aztec/aztec.js": "3.0.0-nightly.20251001",
76
+ "@aztec/constants": "3.0.0-nightly.20251001",
77
+ "@aztec/entrypoints": "3.0.0-nightly.20251001",
78
+ "@aztec/ethereum": "3.0.0-nightly.20251001",
79
+ "@aztec/foundation": "3.0.0-nightly.20251001",
80
+ "@aztec/l1-artifacts": "3.0.0-nightly.20251001",
81
+ "@aztec/node-lib": "3.0.0-nightly.20251001",
82
+ "@aztec/p2p": "3.0.0-nightly.20251001",
83
+ "@aztec/protocol-contracts": "3.0.0-nightly.20251001",
84
+ "@aztec/stdlib": "3.0.0-nightly.20251001",
85
+ "@aztec/test-wallet": "3.0.0-nightly.20251001",
86
+ "@aztec/world-state": "3.0.0-nightly.20251001",
87
87
  "@iarna/toml": "^2.2.5",
88
88
  "@libp2p/peer-id-factory": "^3.0.4",
89
89
  "commander": "^12.1.0",
@@ -110,15 +110,15 @@
110
110
  "typescript": "^5.3.3"
111
111
  },
112
112
  "peerDependencies": {
113
- "@aztec/accounts": "3.0.0-nightly.20250929",
114
- "@aztec/bb-prover": "3.0.0-nightly.20250929",
115
- "@aztec/ethereum": "3.0.0-nightly.20250929",
116
- "@aztec/l1-artifacts": "3.0.0-nightly.20250929",
117
- "@aztec/noir-contracts.js": "3.0.0-nightly.20250929",
118
- "@aztec/noir-protocol-circuits-types": "3.0.0-nightly.20250929",
119
- "@aztec/noir-test-contracts.js": "3.0.0-nightly.20250929",
120
- "@aztec/protocol-contracts": "3.0.0-nightly.20250929",
121
- "@aztec/stdlib": "3.0.0-nightly.20250929"
113
+ "@aztec/accounts": "3.0.0-nightly.20251001",
114
+ "@aztec/bb-prover": "3.0.0-nightly.20251001",
115
+ "@aztec/ethereum": "3.0.0-nightly.20251001",
116
+ "@aztec/l1-artifacts": "3.0.0-nightly.20251001",
117
+ "@aztec/noir-contracts.js": "3.0.0-nightly.20251001",
118
+ "@aztec/noir-protocol-circuits-types": "3.0.0-nightly.20251001",
119
+ "@aztec/noir-test-contracts.js": "3.0.0-nightly.20251001",
120
+ "@aztec/protocol-contracts": "3.0.0-nightly.20251001",
121
+ "@aztec/stdlib": "3.0.0-nightly.20251001"
122
122
  },
123
123
  "files": [
124
124
  "dest",
@@ -0,0 +1,67 @@
1
+ import { createLogger } from '@aztec/aztec.js';
2
+
3
+ import { mkdir, readFile, stat, writeFile } from 'fs/promises';
4
+ import { dirname } from 'path';
5
+
6
+ export interface CachedFetchOptions {
7
+ /** Cache duration in milliseconds */
8
+ cacheDurationMs: number;
9
+ /** The cache file */
10
+ cacheFile?: string;
11
+ }
12
+
13
+ /**
14
+ * Fetches data from a URL with file-based caching support.
15
+ * This utility can be used by both remote config and bootnodes fetching.
16
+ *
17
+ * @param url - The URL to fetch from
18
+ * @param networkName - Network name for cache directory structure
19
+ * @param options - Caching and error handling options
20
+ * @param cacheDir - Optional cache directory (defaults to no caching)
21
+ * @returns The fetched and parsed JSON data, or undefined if fetch fails and throwOnError is false
22
+ */
23
+ export async function cachedFetch<T = any>(
24
+ url: string,
25
+ options: CachedFetchOptions,
26
+ fetch = globalThis.fetch,
27
+ log = createLogger('cached_fetch'),
28
+ ): Promise<T | undefined> {
29
+ const { cacheDurationMs, cacheFile } = options;
30
+
31
+ // Try to read from cache first
32
+ try {
33
+ if (cacheFile) {
34
+ const info = await stat(cacheFile);
35
+ if (info.mtimeMs + cacheDurationMs > Date.now()) {
36
+ const cachedData = JSON.parse(await readFile(cacheFile, 'utf-8'));
37
+ return cachedData;
38
+ }
39
+ }
40
+ } catch {
41
+ log.trace('Failed to read data from cache');
42
+ }
43
+
44
+ try {
45
+ const response = await fetch(url);
46
+ if (!response.ok) {
47
+ log.warn(`Failed to fetch from ${url}: ${response.status} ${response.statusText}`);
48
+ return undefined;
49
+ }
50
+
51
+ const data = await response.json();
52
+
53
+ try {
54
+ if (cacheFile) {
55
+ await mkdir(dirname(cacheFile), { recursive: true });
56
+ await writeFile(cacheFile, JSON.stringify(data), 'utf-8');
57
+ }
58
+ } catch (err) {
59
+ log.warn('Failed to cache data on disk: ' + cacheFile, { cacheFile, err });
60
+ }
61
+
62
+ return data;
63
+ } catch (err) {
64
+ log.warn(`Failed to fetch from ${url}`, { err });
65
+ return undefined;
66
+ }
67
+ }
@@ -4,13 +4,17 @@ import { EthAddress } from '@aztec/foundation/eth-address';
4
4
  import type { SharedNodeConfig } from '@aztec/node-lib/config';
5
5
  import type { SlasherConfig } from '@aztec/stdlib/interfaces/server';
6
6
 
7
- import { mkdir, readFile, stat, writeFile } from 'fs/promises';
8
- import path, { dirname, join } from 'path';
7
+ import path, { join } from 'path';
9
8
 
10
9
  import publicIncludeMetrics from '../../public_include_metric_prefixes.json' with { type: 'json' };
10
+ import { cachedFetch } from './cached_fetch.js';
11
+ import { enrichEthAddressVar, enrichVar } from './enrich_env.js';
11
12
 
12
13
  const SNAPSHOT_URL = 'https://pub-f4a8c34d4bb7441ebf8f48d904512180.r2.dev/snapshots';
13
14
 
15
+ const defaultDBMapSizeKb = 128 * 1_024 * 1_024; // 128 GB
16
+ const tbMapSizeKb = 1_024 * 1_024 * 1_024; // 1 TB
17
+
14
18
  export type L2ChainConfig = L1ContractsConfig &
15
19
  Omit<SlasherConfig, 'slashValidatorsNever' | 'slashValidatorsAlways'> & {
16
20
  l1ChainId: number;
@@ -32,6 +36,14 @@ export type L2ChainConfig = L1ContractsConfig &
32
36
  publicMetricsCollectorUrl?: string;
33
37
  publicMetricsCollectFrom?: string[];
34
38
 
39
+ // Setting the dbMapSize provides the default for every DB in the node.
40
+ // Then we explicitly override the sizes for the archiver and the larger trees.
41
+ dbMapSizeKb: number;
42
+ archiverStoreMapSizeKb: number;
43
+ noteHashTreeMapSizeKb: number;
44
+ nullifierTreeMapSizeKb: number;
45
+ publicDataTreeMapSizeKb: number;
46
+
35
47
  // Control whether sentinel is enabled or not. Needed for slashing
36
48
  sentinelEnabled: boolean;
37
49
  };
@@ -73,15 +85,23 @@ const DefaultSlashConfig = {
73
85
  slashExecuteRoundsLookBack: 4,
74
86
  } satisfies Partial<L2ChainConfig>;
75
87
 
88
+ const DefaultNetworkDBMapSizeConfig = {
89
+ dbMapSizeKb: defaultDBMapSizeKb,
90
+ archiverStoreMapSizeKb: tbMapSizeKb,
91
+ noteHashTreeMapSizeKb: tbMapSizeKb,
92
+ nullifierTreeMapSizeKb: tbMapSizeKb,
93
+ publicDataTreeMapSizeKb: tbMapSizeKb,
94
+ } satisfies Partial<L2ChainConfig>;
95
+
76
96
  export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
77
97
  l1ChainId: 11155111,
78
98
  testAccounts: false,
79
99
  sponsoredFPC: false,
80
100
  p2pEnabled: true,
81
101
  p2pBootstrapNodes: [],
82
- registryAddress: '0x5f85fa0f40bc4b5ccd53c9f34258aa55d25cdde8',
83
- slashFactoryAddress: '0x257db2ca1471b7f76f414d2997404bfbe916c8c9',
84
- feeAssetHandlerAddress: '0x67d645b0a3e053605ea861d7e8909be6669812c4',
102
+ registryAddress: '0x53e2c2148da04fd0e8dd282f016f627a187c292c',
103
+ slashFactoryAddress: '0x56448efb139ef440438dfa445333734ea5ed60a0',
104
+ feeAssetHandlerAddress: '0x3613b834544030c166a4d47eca14b910f4816f57',
85
105
  seqMinTxsPerBlock: 0,
86
106
  seqMaxTxsPerBlock: 0,
87
107
  realProofs: true,
@@ -152,6 +172,8 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
152
172
  sentinelEnabled: true,
153
173
  slashingDisableDuration: 5 * 24 * 60 * 60,
154
174
  slashExecuteRoundsLookBack: 4,
175
+
176
+ ...DefaultNetworkDBMapSizeConfig,
155
177
  };
156
178
 
157
179
  export const stagingPublicL2ChainConfig: L2ChainConfig = {
@@ -160,9 +182,9 @@ export const stagingPublicL2ChainConfig: L2ChainConfig = {
160
182
  sponsoredFPC: true,
161
183
  p2pEnabled: true,
162
184
  p2pBootstrapNodes: [],
163
- registryAddress: '0x2e48addca360da61e4d6c21ff2b1961af56eb83b',
164
- slashFactoryAddress: '0xe19410632fd00695bc5a08dd82044b7b26317742',
165
- feeAssetHandlerAddress: '0xb46dc3d91f849999330b6dd93473fa29fc45b076',
185
+ registryAddress: '0xe83067689f3cf837ccbf8a3966f0e0fe985dcb3e',
186
+ slashFactoryAddress: '0x8b87a1812162d4890f01bb40f410047f37d3ceb8',
187
+ feeAssetHandlerAddress: '0xa8159159a9e2a57c6e8c59fd5b3dd94c6dbddfe3',
166
188
  seqMinTxsPerBlock: 0,
167
189
  seqMaxTxsPerBlock: 20,
168
190
  realProofs: true,
@@ -205,6 +227,8 @@ export const stagingPublicL2ChainConfig: L2ChainConfig = {
205
227
  exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
206
228
 
207
229
  ...DefaultSlashConfig,
230
+
231
+ ...DefaultNetworkDBMapSizeConfig,
208
232
  };
209
233
 
210
234
  export const testnetL2ChainConfig: L2ChainConfig = {
@@ -260,42 +284,105 @@ export const testnetL2ChainConfig: L2ChainConfig = {
260
284
  ...DefaultSlashConfig,
261
285
  slashPrunePenalty: 0n,
262
286
  slashDataWithholdingPenalty: 0n,
287
+
288
+ ...DefaultNetworkDBMapSizeConfig,
289
+ };
290
+
291
+ export const ignitionL2ChainConfig: L2ChainConfig = {
292
+ l1ChainId: 1,
293
+ testAccounts: false,
294
+ sponsoredFPC: false,
295
+ p2pEnabled: true,
296
+ p2pBootstrapNodes: [],
297
+ registryAddress: '',
298
+ slashFactoryAddress: '',
299
+ feeAssetHandlerAddress: '',
300
+ seqMinTxsPerBlock: 0,
301
+ seqMaxTxsPerBlock: 0,
302
+ realProofs: true,
303
+ snapshotsUrl: 'https://storage.googleapis.com/aztec-testnet/snapshots/ignition/',
304
+ autoUpdate: 'notify',
305
+ autoUpdateUrl: 'https://storage.googleapis.com/aztec-testnet/auto-update/ignition.json',
306
+ maxTxPoolSize: 100_000_000, // 100MB
307
+ publicIncludeMetrics,
308
+ publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
309
+ publicMetricsCollectFrom: ['sequencer'],
310
+
311
+ /** How many seconds an L1 slot lasts. */
312
+ ethereumSlotDuration: 12,
313
+ /** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */
314
+ aztecSlotDuration: 72,
315
+ /** How many L2 slots an epoch lasts. */
316
+ aztecEpochDuration: 32,
317
+ /** The target validator committee size. */
318
+ aztecTargetCommitteeSize: 24,
319
+ /** The number of epochs after an epoch ends that proofs are still accepted. */
320
+ aztecProofSubmissionEpochs: 1,
321
+ /** How many sequencers must agree with a slash for it to be executed. */
322
+ slashingQuorum: 65,
323
+
324
+ /** The number of epochs to lag behind the current epoch for validator selection. */
325
+ lagInEpochs: 2,
326
+
327
+ localEjectionThreshold: 196_000n * 10n ** 18n,
328
+ slashingDisableDuration: 5 * 24 * 60 * 60,
329
+
330
+ slashingRoundSizeInEpochs: 4,
331
+ slashingLifetimeInRounds: 40,
332
+ slashingExecutionDelayInRounds: 28,
333
+ slashAmountSmall: 2_000n * 10n ** 18n,
334
+ slashAmountMedium: 10_000n * 10n ** 18n,
335
+ slashAmountLarge: 50_000n * 10n ** 18n,
336
+ slashingOffsetInRounds: 2,
337
+ slasherFlavor: 'tally',
338
+ slashingVetoer: EthAddress.ZERO, // TODO TMNT-329
339
+
340
+ /** The mana target for the rollup */
341
+ manaTarget: 0n,
342
+
343
+ exitDelaySeconds: 5 * 24 * 60 * 60,
344
+
345
+ /** The proving cost per mana */
346
+ provingCostPerMana: 0n,
347
+
348
+ ejectionThreshold: 100_000n * 10n ** 18n,
349
+ activationThreshold: 200_000n * 10n ** 18n,
350
+
351
+ governanceProposerRoundSize: 300, // TODO TMNT-322
352
+ governanceProposerQuorum: 151, // TODO TMNT-322
353
+
354
+ // Node slashing config
355
+ // TODO TMNT-330
356
+ slashMinPenaltyPercentage: 0.5,
357
+ slashMaxPenaltyPercentage: 2.0,
358
+ slashInactivityTargetPercentage: 0.7,
359
+ slashInactivityConsecutiveEpochThreshold: 2,
360
+ slashInactivityPenalty: 2_000n * 10n ** 18n,
361
+ slashPrunePenalty: 0n, // 2_000n * 10n ** 18n, We disable slashing for prune offenses right now
362
+ slashDataWithholdingPenalty: 0n, // 2_000n * 10n ** 18n, We disable slashing for data withholding offenses right now
363
+ slashProposeInvalidAttestationsPenalty: 50_000n * 10n ** 18n,
364
+ slashAttestDescendantOfInvalidPenalty: 50_000n * 10n ** 18n,
365
+ slashUnknownPenalty: 2_000n * 10n ** 18n,
366
+ slashBroadcastedInvalidBlockPenalty: 0n, // 10_000n * 10n ** 18n, Disabled for now until further testing
367
+ slashMaxPayloadSize: 50,
368
+ slashGracePeriodL2Slots: 32 * 4, // One round from genesis
369
+ slashOffenseExpirationRounds: 8,
370
+ sentinelEnabled: true,
371
+ slashExecuteRoundsLookBack: 4,
372
+
373
+ ...DefaultNetworkDBMapSizeConfig,
263
374
  };
264
375
 
265
376
  const BOOTNODE_CACHE_DURATION_MS = 60 * 60 * 1000; // 1 hour;
266
377
 
267
378
  export async function getBootnodes(networkName: NetworkNames, cacheDir?: string) {
268
- const cacheFile = cacheDir ? join(cacheDir, networkName, 'bootnodes.json') : undefined;
269
- try {
270
- if (cacheFile) {
271
- const info = await stat(cacheFile);
272
- if (info.mtimeMs + BOOTNODE_CACHE_DURATION_MS > Date.now()) {
273
- return JSON.parse(await readFile(cacheFile, 'utf-8'))['bootnodes'];
274
- }
275
- }
276
- } catch {
277
- // no-op. Get the remote-file
278
- }
279
-
280
379
  const url = `http://static.aztec.network/${networkName}/bootnodes.json`;
281
- const response = await fetch(url);
282
- if (!response.ok) {
283
- throw new Error(
284
- `Failed to fetch basic contract addresses from ${url}. Check you are using a correct network name.`,
285
- );
286
- }
287
- const json = await response.json();
288
-
289
- try {
290
- if (cacheFile) {
291
- await mkdir(dirname(cacheFile), { recursive: true });
292
- await writeFile(cacheFile, JSON.stringify(json), 'utf-8');
293
- }
294
- } catch {
295
- // no-op
296
- }
380
+ const data = await cachedFetch(url, {
381
+ cacheDurationMs: BOOTNODE_CACHE_DURATION_MS,
382
+ cacheFile: cacheDir ? join(cacheDir, networkName, 'bootnodes.json') : undefined,
383
+ });
297
384
 
298
- return json['bootnodes'];
385
+ return data?.bootnodes;
299
386
  }
300
387
 
301
388
  export async function getL2ChainConfig(
@@ -309,6 +396,8 @@ export async function getL2ChainConfig(
309
396
  config = { ...testnetL2ChainConfig };
310
397
  } else if (networkName === 'staging-ignition') {
311
398
  config = { ...stagingIgnitionL2ChainConfig };
399
+ } else if (networkName === 'ignition') {
400
+ config = { ...ignitionL2ChainConfig };
312
401
  }
313
402
  if (!config) {
314
403
  return undefined;
@@ -321,23 +410,6 @@ export async function getL2ChainConfig(
321
410
  return config;
322
411
  }
323
412
 
324
- function enrichVar(envVar: EnvVar, value: string | undefined) {
325
- // Don't override
326
- if (process.env[envVar] || value === undefined) {
327
- return;
328
- }
329
- process.env[envVar] = value;
330
- }
331
-
332
- function enrichEthAddressVar(envVar: EnvVar, value: string) {
333
- // EthAddress doesn't like being given empty strings
334
- if (value === '') {
335
- enrichVar(envVar, EthAddress.ZERO.toString());
336
- return;
337
- }
338
- enrichVar(envVar, value);
339
- }
340
-
341
413
  function getDefaultDataDir(networkName: NetworkNames): string {
342
414
  return path.join(process.env.HOME || '~', '.aztec', networkName, 'data');
343
415
  }
@@ -367,6 +439,12 @@ export async function enrichEnvironmentWithChainConfig(networkName: NetworkNames
367
439
  enrichVar('SYNC_SNAPSHOTS_URL', config.snapshotsUrl);
368
440
  enrichVar('P2P_MAX_TX_POOL_SIZE', config.maxTxPoolSize.toString());
369
441
 
442
+ enrichVar('DATA_STORE_MAP_SIZE_KB', config.dbMapSizeKb.toString());
443
+ enrichVar('ARCHIVER_STORE_MAP_SIZE_KB', config.archiverStoreMapSizeKb.toString());
444
+ enrichVar('NOTE_HASH_TREE_MAP_SIZE_KB', config.noteHashTreeMapSizeKb.toString());
445
+ enrichVar('NULLIFIER_TREE_MAP_SIZE_KB', config.nullifierTreeMapSizeKb.toString());
446
+ enrichVar('PUBLIC_DATA_TREE_MAP_SIZE_KB', config.publicDataTreeMapSizeKb.toString());
447
+
370
448
  if (config.autoUpdate) {
371
449
  enrichVar('AUTO_UPDATE', config.autoUpdate?.toString());
372
450
  }
@@ -0,0 +1,15 @@
1
+ import { EthAddress } from '@aztec/aztec.js';
2
+ import type { EnvVar } from '@aztec/foundation/config';
3
+
4
+ export function enrichVar(envVar: EnvVar, value: string | undefined) {
5
+ // Don't override
6
+ if (process.env[envVar] || value === undefined) {
7
+ return;
8
+ }
9
+ process.env[envVar] = value;
10
+ }
11
+
12
+ export function enrichEthAddressVar(envVar: EnvVar, value: string) {
13
+ // EthAddress doesn't like being given empty strings
14
+ enrichVar(envVar, value || EthAddress.ZERO.toString());
15
+ }
@@ -1,2 +1,4 @@
1
+ export * from './cached_fetch.js';
1
2
  export * from './chain_l2_config.js';
2
3
  export * from './get_l1_config.js';
4
+ export * from './network_config.js';
@@ -0,0 +1,108 @@
1
+ import { type NetworkConfig, NetworkConfigMapSchema, type NetworkNames } from '@aztec/foundation/config';
2
+
3
+ import { readFile } from 'fs/promises';
4
+ import { join } from 'path';
5
+
6
+ import { cachedFetch } from './cached_fetch.js';
7
+ import { enrichEthAddressVar, enrichVar } from './enrich_env.js';
8
+
9
+ const DEFAULT_CONFIG_URL =
10
+ 'https://raw.githubusercontent.com/AztecProtocol/networks/refs/heads/main/network_config.json';
11
+ const NETWORK_CONFIG_CACHE_DURATION_MS = 60 * 60 * 1000; // 1 hour
12
+
13
+ /**
14
+ * Fetches remote network configuration from GitHub with caching support.
15
+ * Uses the reusable cachedFetch utility.
16
+ *
17
+ * @param networkName - The network name to fetch config for
18
+ * @param cacheDir - Optional cache directory for storing fetched config
19
+ * @returns Remote configuration for the specified network, or undefined if not found/error
20
+ */
21
+ export async function getNetworkConfig(
22
+ networkName: NetworkNames,
23
+ cacheDir?: string,
24
+ ): Promise<NetworkConfig | undefined> {
25
+ let url: URL | undefined;
26
+ const configLocation = process.env.NETWORK_CONFIG_LOCATION || DEFAULT_CONFIG_URL;
27
+
28
+ if (!configLocation) {
29
+ return undefined;
30
+ }
31
+
32
+ try {
33
+ if (configLocation.includes('://')) {
34
+ url = new URL(configLocation);
35
+ } else {
36
+ url = new URL(`file://${configLocation}`);
37
+ }
38
+ } catch {
39
+ /* no-op */
40
+ }
41
+
42
+ if (!url) {
43
+ return undefined;
44
+ }
45
+
46
+ try {
47
+ let rawConfig: any;
48
+
49
+ if (url.protocol === 'http:' || url.protocol === 'https:') {
50
+ rawConfig = await cachedFetch(url.href, {
51
+ cacheDurationMs: NETWORK_CONFIG_CACHE_DURATION_MS,
52
+ cacheFile: cacheDir ? join(cacheDir, networkName, 'network_config.json') : undefined,
53
+ });
54
+ } else if (url.protocol === 'file:') {
55
+ rawConfig = JSON.parse(await readFile(url.pathname, 'utf-8'));
56
+ } else {
57
+ throw new Error('Unsupported Aztec network config protocol: ' + url.href);
58
+ }
59
+
60
+ if (!rawConfig) {
61
+ return undefined;
62
+ }
63
+
64
+ const networkConfigMap = NetworkConfigMapSchema.parse(rawConfig);
65
+ if (networkName in networkConfigMap) {
66
+ return networkConfigMap[networkName];
67
+ } else {
68
+ return undefined;
69
+ }
70
+ } catch {
71
+ return undefined;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Enriches environment variables with remote network configuration.
77
+ * This function is called before node config initialization to set env vars
78
+ * from the remote config, following the same pattern as enrichEnvironmentWithChainConfig().
79
+ *
80
+ * @param networkName - The network name to fetch remote config for
81
+ */
82
+ export async function enrichEnvironmentWithNetworkConfig(networkName: NetworkNames) {
83
+ if (networkName === 'local') {
84
+ return; // No remote config for local development
85
+ }
86
+
87
+ const cacheDir = process.env.DATA_DIRECTORY ? join(process.env.DATA_DIRECTORY, 'cache') : undefined;
88
+ const networkConfig = await getNetworkConfig(networkName, cacheDir);
89
+
90
+ if (!networkConfig) {
91
+ return;
92
+ }
93
+
94
+ enrichVar('BOOTSTRAP_NODES', networkConfig.bootnodes.join(','));
95
+ enrichVar('L1_CHAIN_ID', String(networkConfig.l1ChainId));
96
+
97
+ // Snapshot synch only supports a single source. Take the first
98
+ // See A-101 for more details
99
+ const firstSource = networkConfig[0];
100
+ if (firstSource) {
101
+ enrichVar('SYNC_SNAPSHOTS_URL', networkConfig.snapshots.join(','));
102
+ }
103
+
104
+ enrichEthAddressVar('REGISTRY_CONTRACT_ADDRESS', networkConfig.registryAddress.toString());
105
+ if (networkConfig.feeAssetHandlerAddress) {
106
+ enrichEthAddressVar('FEE_ASSET_HANDLER_CONTRACT_ADDRESS', networkConfig.feeAssetHandlerAddress.toString());
107
+ }
108
+ }