@aztec/cli 2.0.3-rc.2 → 2.0.3-rc.20

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
+ }
@@ -22,11 +22,17 @@ export type L2ChainConfig = L1ContractsConfig & Pick<P2PConfig, 'txPoolDeleteTxs
22
22
  publicIncludeMetrics?: string[];
23
23
  publicMetricsCollectorUrl?: string;
24
24
  publicMetricsCollectFrom?: string[];
25
+ dbMapSizeKb: number;
26
+ archiverStoreMapSizeKb: number;
27
+ noteHashTreeMapSizeKb: number;
28
+ nullifierTreeMapSizeKb: number;
29
+ publicDataTreeMapSizeKb: number;
25
30
  sentinelEnabled: boolean;
26
31
  };
27
32
  export declare const stagingIgnitionL2ChainConfig: L2ChainConfig;
28
33
  export declare const stagingPublicL2ChainConfig: L2ChainConfig;
29
34
  export declare const testnetL2ChainConfig: L2ChainConfig;
35
+ export declare const ignitionL2ChainConfig: L2ChainConfig;
30
36
  export declare function getBootnodes(networkName: NetworkNames, cacheDir?: string): Promise<any>;
31
37
  export declare function getL2ChainConfig(networkName: NetworkNames, cacheDir?: string): Promise<L2ChainConfig | undefined>;
32
38
  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,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAOrE,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAC3C,IAAI,CAAC,SAAS,EAAE,2BAA2B,CAAC,GAC5C,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;AAoCJ,eAAO,MAAM,4BAA4B,EAAE,aA2E1C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,aAgDxC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,aAmDlC,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,iBAyF/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,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAWrE,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAC3C,IAAI,CAAC,SAAS,EAAE,2BAA2B,CAAC,GAC5C,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,aAkF1C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,aAsDxC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,aAyDlC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,aAkFnC,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,16 +1,20 @@
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';
9
+ const defaultDBMapSizeKb = 128 * 1_024 * 1_024; // 128 GB
10
+ const tbMapSizeKb = 1_024 * 1_024 * 1_024; // 1 TB
8
11
  const DefaultSlashConfig = {
9
12
  /** Tally-style slashing */ slasherFlavor: 'tally',
10
13
  /** Allow one round for vetoing */ slashingExecutionDelayInRounds: 1,
11
14
  /** How long for a slash payload to be executed */ slashingLifetimeInRounds: 5,
12
15
  /** Allow 2 rounds to discover faults */ slashingOffsetInRounds: 2,
13
16
  /** No slash vetoer */ slashingVetoer: EthAddress.ZERO,
17
+ /** Use default disable duration */ slashingDisableDuration: DefaultL1ContractsConfig.slashingDisableDuration,
14
18
  /** Use default slash amounts */ slashAmountSmall: DefaultL1ContractsConfig.slashAmountSmall,
15
19
  slashAmountMedium: DefaultL1ContractsConfig.slashAmountMedium,
16
20
  slashAmountLarge: DefaultL1ContractsConfig.slashAmountLarge,
@@ -25,11 +29,19 @@ const DefaultSlashConfig = {
25
29
  slashProposeInvalidAttestationsPenalty: DefaultL1ContractsConfig.slashAmountLarge,
26
30
  slashAttestDescendantOfInvalidPenalty: DefaultL1ContractsConfig.slashAmountLarge,
27
31
  slashUnknownPenalty: DefaultL1ContractsConfig.slashAmountSmall,
28
- slashBroadcastedInvalidBlockPenalty: DefaultL1ContractsConfig.slashAmountMedium,
32
+ slashBroadcastedInvalidBlockPenalty: 0n,
29
33
  slashMaxPayloadSize: 50,
30
34
  slashGracePeriodL2Slots: 32 * 2,
31
35
  slashOffenseExpirationRounds: 8,
32
- sentinelEnabled: true
36
+ sentinelEnabled: true,
37
+ slashExecuteRoundsLookBack: 4
38
+ };
39
+ const DefaultNetworkDBMapSizeConfig = {
40
+ dbMapSizeKb: defaultDBMapSizeKb,
41
+ archiverStoreMapSizeKb: tbMapSizeKb,
42
+ noteHashTreeMapSizeKb: tbMapSizeKb,
43
+ nullifierTreeMapSizeKb: tbMapSizeKb,
44
+ publicDataTreeMapSizeKb: tbMapSizeKb
33
45
  };
34
46
  export const stagingIgnitionL2ChainConfig = {
35
47
  l1ChainId: 11155111,
@@ -37,9 +49,9 @@ export const stagingIgnitionL2ChainConfig = {
37
49
  sponsoredFPC: false,
38
50
  p2pEnabled: true,
39
51
  p2pBootstrapNodes: [],
40
- registryAddress: '0x6c04b1c116ec1ea0f918e3cc91e87b0af3e23b73',
41
- slashFactoryAddress: '',
42
- feeAssetHandlerAddress: '',
52
+ registryAddress: '0x5f85fa0f40bc4b5ccd53c9f34258aa55d25cdde8',
53
+ slashFactoryAddress: '0x257db2ca1471b7f76f414d2997404bfbe916c8c9',
54
+ feeAssetHandlerAddress: '0x67d645b0a3e053605ea861d7e8909be6669812c4',
43
55
  seqMinTxsPerBlock: 0,
44
56
  seqMaxTxsPerBlock: 0,
45
57
  realProofs: true,
@@ -57,11 +69,13 @@ export const stagingIgnitionL2ChainConfig = {
57
69
  /** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */ aztecSlotDuration: 72,
58
70
  /** How many L2 slots an epoch lasts. */ aztecEpochDuration: 32,
59
71
  /** The target validator committee size. */ aztecTargetCommitteeSize: 24,
72
+ /** The number of epochs to lag behind the current epoch for validator selection. */ lagInEpochs: 2,
60
73
  /** The number of epochs after an epoch ends that proofs are still accepted. */ aztecProofSubmissionEpochs: 1,
61
74
  /** How many sequencers must agree with a slash for it to be executed. */ slashingQuorum: 65,
62
75
  slashingRoundSizeInEpochs: 4,
63
76
  slashingLifetimeInRounds: 40,
64
77
  slashingExecutionDelayInRounds: 28,
78
+ slashingDisableDuration: 5 * 24 * 60 * 60,
65
79
  slashAmountSmall: 2_000n * 10n ** 18n,
66
80
  slashAmountMedium: 10_000n * 10n ** 18n,
67
81
  slashAmountLarge: 50_000n * 10n ** 18n,
@@ -73,6 +87,7 @@ export const stagingIgnitionL2ChainConfig = {
73
87
  /** The proving cost per mana */ provingCostPerMana: 0n,
74
88
  ejectionThreshold: 100_000n * 10n ** 18n,
75
89
  activationThreshold: 200_000n * 10n ** 18n,
90
+ localEjectionThreshold: 196_000n * 10n ** 18n,
76
91
  governanceProposerRoundSize: 300,
77
92
  governanceProposerQuorum: 151,
78
93
  // Node slashing config
@@ -87,11 +102,13 @@ export const stagingIgnitionL2ChainConfig = {
87
102
  slashProposeInvalidAttestationsPenalty: 50_000n * 10n ** 18n,
88
103
  slashAttestDescendantOfInvalidPenalty: 50_000n * 10n ** 18n,
89
104
  slashUnknownPenalty: 2_000n * 10n ** 18n,
90
- slashBroadcastedInvalidBlockPenalty: 10_000n * 10n ** 18n,
105
+ slashBroadcastedInvalidBlockPenalty: 0n,
91
106
  slashMaxPayloadSize: 50,
92
107
  slashGracePeriodL2Slots: 32 * 4,
93
108
  slashOffenseExpirationRounds: 8,
94
- sentinelEnabled: true
109
+ sentinelEnabled: true,
110
+ slashExecuteRoundsLookBack: 4,
111
+ ...DefaultNetworkDBMapSizeConfig
95
112
  };
96
113
  export const stagingPublicL2ChainConfig = {
97
114
  l1ChainId: 11155111,
@@ -120,6 +137,8 @@ export const stagingPublicL2ChainConfig = {
120
137
  /** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */ aztecSlotDuration: 36,
121
138
  /** How many L2 slots an epoch lasts. */ aztecEpochDuration: 32,
122
139
  /** The target validator committee size. */ aztecTargetCommitteeSize: 48,
140
+ /** The number of epochs to lag behind the current epoch for validator selection. */ lagInEpochs: DefaultL1ContractsConfig.lagInEpochs,
141
+ /** The local ejection threshold for a validator. Stricter than ejectionThreshold but local to a specific rollup */ localEjectionThreshold: DefaultL1ContractsConfig.localEjectionThreshold,
123
142
  /** The number of epochs after an epoch ends that proofs are still accepted. */ aztecProofSubmissionEpochs: 1,
124
143
  /** The deposit amount for a validator */ activationThreshold: DefaultL1ContractsConfig.activationThreshold,
125
144
  /** The minimum stake for a validator. */ ejectionThreshold: DefaultL1ContractsConfig.ejectionThreshold,
@@ -128,7 +147,8 @@ export const stagingPublicL2ChainConfig = {
128
147
  /** The mana target for the rollup */ manaTarget: DefaultL1ContractsConfig.manaTarget,
129
148
  /** The proving cost per mana */ provingCostPerMana: DefaultL1ContractsConfig.provingCostPerMana,
130
149
  /** Exit delay for stakers */ exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
131
- ...DefaultSlashConfig
150
+ ...DefaultSlashConfig,
151
+ ...DefaultNetworkDBMapSizeConfig
132
152
  };
133
153
  export const testnetL2ChainConfig = {
134
154
  l1ChainId: 11155111,
@@ -157,9 +177,11 @@ export const testnetL2ChainConfig = {
157
177
  /** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */ aztecSlotDuration: 36,
158
178
  /** How many L2 slots an epoch lasts. */ aztecEpochDuration: 32,
159
179
  /** The target validator committee size. */ aztecTargetCommitteeSize: 48,
180
+ /** The number of epochs to lag behind the current epoch for validator selection. */ lagInEpochs: 2,
160
181
  /** The number of epochs after an epoch ends that proofs are still accepted. */ aztecProofSubmissionEpochs: 1,
161
182
  /** The deposit amount for a validator */ activationThreshold: DefaultL1ContractsConfig.activationThreshold,
162
183
  /** The minimum stake for a validator. */ ejectionThreshold: DefaultL1ContractsConfig.ejectionThreshold,
184
+ /** The local ejection threshold for a validator. Stricter than ejectionThreshold but local to a specific rollup */ localEjectionThreshold: DefaultL1ContractsConfig.localEjectionThreshold,
163
185
  /** The slashing round size */ slashingRoundSizeInEpochs: DefaultL1ContractsConfig.slashingRoundSizeInEpochs,
164
186
  /** Governance proposing round size */ governanceProposerRoundSize: DefaultL1ContractsConfig.governanceProposerRoundSize,
165
187
  /** The mana target for the rollup */ manaTarget: DefaultL1ContractsConfig.manaTarget,
@@ -168,38 +190,84 @@ export const testnetL2ChainConfig = {
168
190
  ...DefaultSlashConfig,
169
191
  slashPrunePenalty: 0n,
170
192
  slashDataWithholdingPenalty: 0n,
171
- slashInactivityPenalty: DefaultL1ContractsConfig.slashAmountMedium
193
+ slashInactivityPenalty: DefaultL1ContractsConfig.slashAmountMedium,
194
+ ...DefaultNetworkDBMapSizeConfig
195
+ };
196
+ export const ignitionL2ChainConfig = {
197
+ l1ChainId: 1,
198
+ testAccounts: false,
199
+ sponsoredFPC: false,
200
+ p2pEnabled: true,
201
+ p2pBootstrapNodes: [],
202
+ registryAddress: '',
203
+ slashFactoryAddress: '',
204
+ feeAssetHandlerAddress: '',
205
+ seqMinTxsPerBlock: 0,
206
+ seqMaxTxsPerBlock: 0,
207
+ realProofs: true,
208
+ snapshotsUrl: 'https://storage.googleapis.com/aztec-testnet/snapshots/ignition/',
209
+ autoUpdate: 'notify',
210
+ autoUpdateUrl: 'https://storage.googleapis.com/aztec-testnet/auto-update/ignition.json',
211
+ maxTxPoolSize: 100_000_000,
212
+ publicIncludeMetrics,
213
+ publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
214
+ publicMetricsCollectFrom: [
215
+ 'sequencer'
216
+ ],
217
+ txPoolDeleteTxsAfterReorg: false,
218
+ /** How many seconds an L1 slot lasts. */ ethereumSlotDuration: 12,
219
+ /** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */ aztecSlotDuration: 72,
220
+ /** How many L2 slots an epoch lasts. */ aztecEpochDuration: 32,
221
+ /** The target validator committee size. */ aztecTargetCommitteeSize: 24,
222
+ /** The number of epochs to lag behind the current epoch for validator selection. */ lagInEpochs: 2,
223
+ /** The number of epochs after an epoch ends that proofs are still accepted. */ aztecProofSubmissionEpochs: 1,
224
+ /** How many sequencers must agree with a slash for it to be executed. */ slashingQuorum: 65,
225
+ slashingRoundSizeInEpochs: 4,
226
+ slashingLifetimeInRounds: 40,
227
+ slashingExecutionDelayInRounds: 28,
228
+ slashingDisableDuration: 5 * 24 * 60 * 60,
229
+ slashAmountSmall: 2_000n * 10n ** 18n,
230
+ slashAmountMedium: 10_000n * 10n ** 18n,
231
+ slashAmountLarge: 50_000n * 10n ** 18n,
232
+ slashingOffsetInRounds: 2,
233
+ slasherFlavor: 'tally',
234
+ slashingVetoer: EthAddress.ZERO,
235
+ /** The mana target for the rollup */ manaTarget: 0n,
236
+ exitDelaySeconds: 5 * 24 * 60 * 60,
237
+ /** The proving cost per mana */ provingCostPerMana: 0n,
238
+ ejectionThreshold: 100_000n * 10n ** 18n,
239
+ activationThreshold: 200_000n * 10n ** 18n,
240
+ localEjectionThreshold: 196_000n * 10n ** 18n,
241
+ governanceProposerRoundSize: 300,
242
+ governanceProposerQuorum: 151,
243
+ // Node slashing config
244
+ // TODO TMNT-330
245
+ slashMinPenaltyPercentage: 0.5,
246
+ slashMaxPenaltyPercentage: 2.0,
247
+ slashInactivityTargetPercentage: 0.7,
248
+ slashInactivityConsecutiveEpochThreshold: 2,
249
+ slashInactivityPenalty: 2_000n * 10n ** 18n,
250
+ slashPrunePenalty: 0n,
251
+ slashDataWithholdingPenalty: 0n,
252
+ slashProposeInvalidAttestationsPenalty: 50_000n * 10n ** 18n,
253
+ slashAttestDescendantOfInvalidPenalty: 50_000n * 10n ** 18n,
254
+ slashUnknownPenalty: 2_000n * 10n ** 18n,
255
+ slashBroadcastedInvalidBlockPenalty: 0n,
256
+ slashMaxPayloadSize: 50,
257
+ slashGracePeriodL2Slots: 32 * 4,
258
+ slashOffenseExpirationRounds: 8,
259
+ sentinelEnabled: true,
260
+ slashExecuteRoundsLookBack: 4,
261
+ ...DefaultNetworkDBMapSizeConfig
172
262
  };
173
263
  const BOOTNODE_CACHE_DURATION_MS = 60 * 60 * 1000; // 1 hour;
174
264
  export async function getBootnodes(networkName, cacheDir) {
175
- const cacheFile = cacheDir ? join(cacheDir, networkName, 'bootnodes.json') : undefined;
176
- try {
177
- if (cacheFile) {
178
- const info = await stat(cacheFile);
179
- if (info.mtimeMs + BOOTNODE_CACHE_DURATION_MS > Date.now()) {
180
- return JSON.parse(await readFile(cacheFile, 'utf-8'))['bootnodes'];
181
- }
182
- }
183
- } catch {
184
- // no-op. Get the remote-file
185
- }
186
265
  const url = `http://static.aztec.network/${networkName}/bootnodes.json`;
187
- const response = await fetch(url);
188
- if (!response.ok) {
189
- throw new Error(`Failed to fetch basic contract addresses from ${url}. Check you are using a correct network name.`);
190
- }
191
- const json = await response.json();
192
- try {
193
- if (cacheFile) {
194
- await mkdir(dirname(cacheFile), {
195
- recursive: true
196
- });
197
- await writeFile(cacheFile, JSON.stringify(json), 'utf-8');
198
- }
199
- } catch {
200
- // no-op
201
- }
202
- return json['bootnodes'];
266
+ const data = await cachedFetch(url, {
267
+ cacheDurationMs: BOOTNODE_CACHE_DURATION_MS,
268
+ cacheFile: cacheDir ? join(cacheDir, networkName, 'bootnodes.json') : undefined
269
+ });
270
+ return data?.bootnodes;
203
271
  }
204
272
  export async function getL2ChainConfig(networkName, cacheDir) {
205
273
  let config;
@@ -215,6 +283,10 @@ export async function getL2ChainConfig(networkName, cacheDir) {
215
283
  config = {
216
284
  ...stagingIgnitionL2ChainConfig
217
285
  };
286
+ } else if (networkName === 'ignition') {
287
+ config = {
288
+ ...ignitionL2ChainConfig
289
+ };
218
290
  }
219
291
  if (!config) {
220
292
  return undefined;
@@ -226,21 +298,6 @@ export async function getL2ChainConfig(networkName, cacheDir) {
226
298
  }
227
299
  return config;
228
300
  }
229
- function enrichVar(envVar, value) {
230
- // Don't override
231
- if (process.env[envVar] || value === undefined) {
232
- return;
233
- }
234
- process.env[envVar] = value;
235
- }
236
- function enrichEthAddressVar(envVar, value) {
237
- // EthAddress doesn't like being given empty strings
238
- if (value === '') {
239
- enrichVar(envVar, EthAddress.ZERO.toString());
240
- return;
241
- }
242
- enrichVar(envVar, value);
243
- }
244
301
  function getDefaultDataDir(networkName) {
245
302
  return path.join(process.env.HOME || '~', '.aztec', networkName, 'data');
246
303
  }
@@ -265,6 +322,11 @@ export async function enrichEnvironmentWithChainConfig(networkName) {
265
322
  enrichVar('PXE_PROVER_ENABLED', config.realProofs.toString());
266
323
  enrichVar('SYNC_SNAPSHOTS_URL', config.snapshotsUrl);
267
324
  enrichVar('P2P_MAX_TX_POOL_SIZE', config.maxTxPoolSize.toString());
325
+ enrichVar('DATA_STORE_MAP_SIZE_KB', config.dbMapSizeKb.toString());
326
+ enrichVar('ARCHIVER_STORE_MAP_SIZE_KB', config.archiverStoreMapSizeKb.toString());
327
+ enrichVar('NOTE_HASH_TREE_MAP_SIZE_KB', config.noteHashTreeMapSizeKb.toString());
328
+ enrichVar('NULLIFIER_TREE_MAP_SIZE_KB', config.nullifierTreeMapSizeKb.toString());
329
+ enrichVar('PUBLIC_DATA_TREE_MAP_SIZE_KB', config.publicDataTreeMapSizeKb.toString());
268
330
  if (config.autoUpdate) {
269
331
  enrichVar('AUTO_UPDATE', config.autoUpdate?.toString());
270
332
  }
@@ -291,6 +353,7 @@ export async function enrichEnvironmentWithChainConfig(networkName) {
291
353
  enrichVar('AZTEC_PROOF_SUBMISSION_EPOCHS', config.aztecProofSubmissionEpochs.toString());
292
354
  enrichVar('AZTEC_ACTIVATION_THRESHOLD', config.activationThreshold.toString());
293
355
  enrichVar('AZTEC_EJECTION_THRESHOLD', config.ejectionThreshold.toString());
356
+ enrichVar('AZTEC_LOCAL_EJECTION_THRESHOLD', config.localEjectionThreshold.toString());
294
357
  enrichVar('AZTEC_SLASHING_QUORUM', config.slashingQuorum?.toString());
295
358
  enrichVar('AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS', config.slashingRoundSizeInEpochs.toString());
296
359
  enrichVar('AZTEC_GOVERNANCE_PROPOSER_QUORUM', config.governanceProposerQuorum?.toString());
@@ -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,iBAoBjF"}
@@ -0,0 +1,79 @@
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
+ enrichVar('SYNC_SNAPSHOTS_URL', networkConfig.snapshots.join(','));
75
+ enrichEthAddressVar('REGISTRY_CONTRACT_ADDRESS', networkConfig.registryAddress.toString());
76
+ if (networkConfig.feeAssetHandlerAddress) {
77
+ enrichEthAddressVar('FEE_ASSET_HANDLER_CONTRACT_ADDRESS', networkConfig.feeAssetHandlerAddress.toString());
78
+ }
79
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/cli",
3
- "version": "2.0.3-rc.2",
3
+ "version": "2.0.3-rc.20",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./contracts": "./dest/cmds/contracts/index.js",
@@ -70,17 +70,17 @@
70
70
  ]
71
71
  },
72
72
  "dependencies": {
73
- "@aztec/archiver": "2.0.3-rc.2",
74
- "@aztec/aztec.js": "2.0.3-rc.2",
75
- "@aztec/constants": "2.0.3-rc.2",
76
- "@aztec/entrypoints": "2.0.3-rc.2",
77
- "@aztec/ethereum": "2.0.3-rc.2",
78
- "@aztec/foundation": "2.0.3-rc.2",
79
- "@aztec/l1-artifacts": "2.0.3-rc.2",
80
- "@aztec/node-lib": "2.0.3-rc.2",
81
- "@aztec/p2p": "2.0.3-rc.2",
82
- "@aztec/stdlib": "2.0.3-rc.2",
83
- "@aztec/world-state": "2.0.3-rc.2",
73
+ "@aztec/archiver": "2.0.3-rc.20",
74
+ "@aztec/aztec.js": "2.0.3-rc.20",
75
+ "@aztec/constants": "2.0.3-rc.20",
76
+ "@aztec/entrypoints": "2.0.3-rc.20",
77
+ "@aztec/ethereum": "2.0.3-rc.20",
78
+ "@aztec/foundation": "2.0.3-rc.20",
79
+ "@aztec/l1-artifacts": "2.0.3-rc.20",
80
+ "@aztec/node-lib": "2.0.3-rc.20",
81
+ "@aztec/p2p": "2.0.3-rc.20",
82
+ "@aztec/stdlib": "2.0.3-rc.20",
83
+ "@aztec/world-state": "2.0.3-rc.20",
84
84
  "@iarna/toml": "^2.2.5",
85
85
  "@libp2p/peer-id-factory": "^3.0.4",
86
86
  "commander": "^12.1.0",
@@ -92,8 +92,8 @@
92
92
  "viem": "2.23.7"
93
93
  },
94
94
  "devDependencies": {
95
- "@aztec/accounts": "2.0.3-rc.2",
96
- "@aztec/protocol-contracts": "2.0.3-rc.2",
95
+ "@aztec/accounts": "2.0.3-rc.20",
96
+ "@aztec/protocol-contracts": "2.0.3-rc.20",
97
97
  "@jest/globals": "^30.0.0",
98
98
  "@types/jest": "^30.0.0",
99
99
  "@types/lodash.chunk": "^4.2.9",
@@ -109,15 +109,15 @@
109
109
  "typescript": "^5.3.3"
110
110
  },
111
111
  "peerDependencies": {
112
- "@aztec/accounts": "2.0.3-rc.2",
113
- "@aztec/bb-prover": "2.0.3-rc.2",
114
- "@aztec/ethereum": "2.0.3-rc.2",
115
- "@aztec/l1-artifacts": "2.0.3-rc.2",
116
- "@aztec/noir-contracts.js": "2.0.3-rc.2",
117
- "@aztec/noir-protocol-circuits-types": "2.0.3-rc.2",
118
- "@aztec/noir-test-contracts.js": "2.0.3-rc.2",
119
- "@aztec/protocol-contracts": "2.0.3-rc.2",
120
- "@aztec/stdlib": "2.0.3-rc.2"
112
+ "@aztec/accounts": "2.0.3-rc.20",
113
+ "@aztec/bb-prover": "2.0.3-rc.20",
114
+ "@aztec/ethereum": "2.0.3-rc.20",
115
+ "@aztec/l1-artifacts": "2.0.3-rc.20",
116
+ "@aztec/noir-contracts.js": "2.0.3-rc.20",
117
+ "@aztec/noir-protocol-circuits-types": "2.0.3-rc.20",
118
+ "@aztec/noir-test-contracts.js": "2.0.3-rc.20",
119
+ "@aztec/protocol-contracts": "2.0.3-rc.20",
120
+ "@aztec/stdlib": "2.0.3-rc.20"
121
121
  },
122
122
  "files": [
123
123
  "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
+ }
@@ -5,10 +5,14 @@ import type { SharedNodeConfig } from '@aztec/node-lib/config';
5
5
  import type { P2PConfig } from '@aztec/p2p/config';
6
6
  import type { SlasherConfig } from '@aztec/stdlib/interfaces/server';
7
7
 
8
- import { mkdir, readFile, stat, writeFile } from 'fs/promises';
9
- import path, { dirname, join } from 'path';
8
+ import path, { join } from 'path';
10
9
 
11
10
  import publicIncludeMetrics from '../../public_include_metric_prefixes.json' with { type: 'json' };
11
+ import { cachedFetch } from './cached_fetch.js';
12
+ import { enrichEthAddressVar, enrichVar } from './enrich_env.js';
13
+
14
+ const defaultDBMapSizeKb = 128 * 1_024 * 1_024; // 128 GB
15
+ const tbMapSizeKb = 1_024 * 1_024 * 1_024; // 1 TB
12
16
 
13
17
  export type L2ChainConfig = L1ContractsConfig &
14
18
  Pick<P2PConfig, 'txPoolDeleteTxsAfterReorg'> &
@@ -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
  };
@@ -47,6 +59,8 @@ const DefaultSlashConfig = {
47
59
  slashingOffsetInRounds: 2,
48
60
  /** No slash vetoer */
49
61
  slashingVetoer: EthAddress.ZERO,
62
+ /** Use default disable duration */
63
+ slashingDisableDuration: DefaultL1ContractsConfig.slashingDisableDuration,
50
64
  /** Use default slash amounts */
51
65
  slashAmountSmall: DefaultL1ContractsConfig.slashAmountSmall,
52
66
  slashAmountMedium: DefaultL1ContractsConfig.slashAmountMedium,
@@ -63,11 +77,20 @@ const DefaultSlashConfig = {
63
77
  slashProposeInvalidAttestationsPenalty: DefaultL1ContractsConfig.slashAmountLarge,
64
78
  slashAttestDescendantOfInvalidPenalty: DefaultL1ContractsConfig.slashAmountLarge,
65
79
  slashUnknownPenalty: DefaultL1ContractsConfig.slashAmountSmall,
66
- slashBroadcastedInvalidBlockPenalty: DefaultL1ContractsConfig.slashAmountMedium,
80
+ slashBroadcastedInvalidBlockPenalty: 0n, // DefaultL1ContractsConfig.slashAmountSmall // Disabled until further testing
67
81
  slashMaxPayloadSize: 50,
68
82
  slashGracePeriodL2Slots: 32 * 2, // Two epochs from genesis
69
83
  slashOffenseExpirationRounds: 8,
70
84
  sentinelEnabled: true,
85
+ slashExecuteRoundsLookBack: 4,
86
+ } satisfies Partial<L2ChainConfig>;
87
+
88
+ const DefaultNetworkDBMapSizeConfig = {
89
+ dbMapSizeKb: defaultDBMapSizeKb,
90
+ archiverStoreMapSizeKb: tbMapSizeKb,
91
+ noteHashTreeMapSizeKb: tbMapSizeKb,
92
+ nullifierTreeMapSizeKb: tbMapSizeKb,
93
+ publicDataTreeMapSizeKb: tbMapSizeKb,
71
94
  } satisfies Partial<L2ChainConfig>;
72
95
 
73
96
  export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
@@ -76,9 +99,9 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
76
99
  sponsoredFPC: false,
77
100
  p2pEnabled: true,
78
101
  p2pBootstrapNodes: [],
79
- registryAddress: '0x6c04b1c116ec1ea0f918e3cc91e87b0af3e23b73',
80
- slashFactoryAddress: '',
81
- feeAssetHandlerAddress: '',
102
+ registryAddress: '0x5f85fa0f40bc4b5ccd53c9f34258aa55d25cdde8',
103
+ slashFactoryAddress: '0x257db2ca1471b7f76f414d2997404bfbe916c8c9',
104
+ feeAssetHandlerAddress: '0x67d645b0a3e053605ea861d7e8909be6669812c4',
82
105
  seqMinTxsPerBlock: 0,
83
106
  seqMaxTxsPerBlock: 0,
84
107
  realProofs: true,
@@ -99,6 +122,8 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
99
122
  aztecEpochDuration: 32,
100
123
  /** The target validator committee size. */
101
124
  aztecTargetCommitteeSize: 24,
125
+ /** The number of epochs to lag behind the current epoch for validator selection. */
126
+ lagInEpochs: 2,
102
127
  /** The number of epochs after an epoch ends that proofs are still accepted. */
103
128
  aztecProofSubmissionEpochs: 1,
104
129
  /** How many sequencers must agree with a slash for it to be executed. */
@@ -107,6 +132,7 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
107
132
  slashingRoundSizeInEpochs: 4,
108
133
  slashingLifetimeInRounds: 40,
109
134
  slashingExecutionDelayInRounds: 28,
135
+ slashingDisableDuration: 5 * 24 * 60 * 60, // 5 days in seconds
110
136
  slashAmountSmall: 2_000n * 10n ** 18n,
111
137
  slashAmountMedium: 10_000n * 10n ** 18n,
112
138
  slashAmountLarge: 50_000n * 10n ** 18n,
@@ -124,6 +150,7 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
124
150
 
125
151
  ejectionThreshold: 100_000n * 10n ** 18n,
126
152
  activationThreshold: 200_000n * 10n ** 18n,
153
+ localEjectionThreshold: 196_000n * 10n ** 18n,
127
154
 
128
155
  governanceProposerRoundSize: 300, // TODO TMNT-322
129
156
  governanceProposerQuorum: 151, // TODO TMNT-322
@@ -140,11 +167,14 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
140
167
  slashProposeInvalidAttestationsPenalty: 50_000n * 10n ** 18n,
141
168
  slashAttestDescendantOfInvalidPenalty: 50_000n * 10n ** 18n,
142
169
  slashUnknownPenalty: 2_000n * 10n ** 18n,
143
- slashBroadcastedInvalidBlockPenalty: 10_000n * 10n ** 18n,
170
+ slashBroadcastedInvalidBlockPenalty: 0n, // 10_000n * 10n ** 18n, Disabled for now until further testing
144
171
  slashMaxPayloadSize: 50,
145
172
  slashGracePeriodL2Slots: 32 * 4, // One round from genesis
146
173
  slashOffenseExpirationRounds: 8,
147
174
  sentinelEnabled: true,
175
+ slashExecuteRoundsLookBack: 4,
176
+
177
+ ...DefaultNetworkDBMapSizeConfig,
148
178
  };
149
179
 
150
180
  export const stagingPublicL2ChainConfig: L2ChainConfig = {
@@ -177,6 +207,10 @@ export const stagingPublicL2ChainConfig: L2ChainConfig = {
177
207
  aztecEpochDuration: 32,
178
208
  /** The target validator committee size. */
179
209
  aztecTargetCommitteeSize: 48,
210
+ /** The number of epochs to lag behind the current epoch for validator selection. */
211
+ lagInEpochs: DefaultL1ContractsConfig.lagInEpochs,
212
+ /** The local ejection threshold for a validator. Stricter than ejectionThreshold but local to a specific rollup */
213
+ localEjectionThreshold: DefaultL1ContractsConfig.localEjectionThreshold,
180
214
  /** The number of epochs after an epoch ends that proofs are still accepted. */
181
215
  aztecProofSubmissionEpochs: 1,
182
216
  /** The deposit amount for a validator */
@@ -195,6 +229,8 @@ export const stagingPublicL2ChainConfig: L2ChainConfig = {
195
229
  exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
196
230
 
197
231
  ...DefaultSlashConfig,
232
+
233
+ ...DefaultNetworkDBMapSizeConfig,
198
234
  };
199
235
 
200
236
  export const testnetL2ChainConfig: L2ChainConfig = {
@@ -227,12 +263,16 @@ export const testnetL2ChainConfig: L2ChainConfig = {
227
263
  aztecEpochDuration: 32,
228
264
  /** The target validator committee size. */
229
265
  aztecTargetCommitteeSize: 48,
266
+ /** The number of epochs to lag behind the current epoch for validator selection. */
267
+ lagInEpochs: 2,
230
268
  /** The number of epochs after an epoch ends that proofs are still accepted. */
231
269
  aztecProofSubmissionEpochs: 1,
232
270
  /** The deposit amount for a validator */
233
271
  activationThreshold: DefaultL1ContractsConfig.activationThreshold,
234
272
  /** The minimum stake for a validator. */
235
273
  ejectionThreshold: DefaultL1ContractsConfig.ejectionThreshold,
274
+ /** The local ejection threshold for a validator. Stricter than ejectionThreshold but local to a specific rollup */
275
+ localEjectionThreshold: DefaultL1ContractsConfig.localEjectionThreshold,
236
276
  /** The slashing round size */
237
277
  slashingRoundSizeInEpochs: DefaultL1ContractsConfig.slashingRoundSizeInEpochs,
238
278
  /** Governance proposing round size */
@@ -248,42 +288,104 @@ export const testnetL2ChainConfig: L2ChainConfig = {
248
288
  slashPrunePenalty: 0n,
249
289
  slashDataWithholdingPenalty: 0n,
250
290
  slashInactivityPenalty: DefaultL1ContractsConfig.slashAmountMedium,
291
+
292
+ ...DefaultNetworkDBMapSizeConfig,
293
+ };
294
+
295
+ export const ignitionL2ChainConfig: L2ChainConfig = {
296
+ l1ChainId: 1,
297
+ testAccounts: false,
298
+ sponsoredFPC: false,
299
+ p2pEnabled: true,
300
+ p2pBootstrapNodes: [],
301
+ registryAddress: '',
302
+ slashFactoryAddress: '',
303
+ feeAssetHandlerAddress: '',
304
+ seqMinTxsPerBlock: 0,
305
+ seqMaxTxsPerBlock: 0,
306
+ realProofs: true,
307
+ snapshotsUrl: 'https://storage.googleapis.com/aztec-testnet/snapshots/ignition/',
308
+ autoUpdate: 'notify',
309
+ autoUpdateUrl: 'https://storage.googleapis.com/aztec-testnet/auto-update/ignition.json',
310
+ maxTxPoolSize: 100_000_000, // 100MB
311
+ publicIncludeMetrics,
312
+ publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
313
+ publicMetricsCollectFrom: ['sequencer'],
314
+ txPoolDeleteTxsAfterReorg: false,
315
+
316
+ /** How many seconds an L1 slot lasts. */
317
+ ethereumSlotDuration: 12,
318
+ /** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */
319
+ aztecSlotDuration: 72,
320
+ /** How many L2 slots an epoch lasts. */
321
+ aztecEpochDuration: 32,
322
+ /** The target validator committee size. */
323
+ aztecTargetCommitteeSize: 24,
324
+ /** The number of epochs to lag behind the current epoch for validator selection. */
325
+ lagInEpochs: 2,
326
+ /** The number of epochs after an epoch ends that proofs are still accepted. */
327
+ aztecProofSubmissionEpochs: 1,
328
+ /** How many sequencers must agree with a slash for it to be executed. */
329
+ slashingQuorum: 65,
330
+
331
+ slashingRoundSizeInEpochs: 4,
332
+ slashingLifetimeInRounds: 40,
333
+ slashingExecutionDelayInRounds: 28,
334
+ slashingDisableDuration: 5 * 24 * 60 * 60, // 5 days in seconds
335
+ slashAmountSmall: 2_000n * 10n ** 18n,
336
+ slashAmountMedium: 10_000n * 10n ** 18n,
337
+ slashAmountLarge: 50_000n * 10n ** 18n,
338
+ slashingOffsetInRounds: 2,
339
+ slasherFlavor: 'tally',
340
+ slashingVetoer: EthAddress.ZERO, // TODO TMNT-329
341
+
342
+ /** The mana target for the rollup */
343
+ manaTarget: 0n,
344
+
345
+ exitDelaySeconds: 5 * 24 * 60 * 60,
346
+
347
+ /** The proving cost per mana */
348
+ provingCostPerMana: 0n,
349
+
350
+ ejectionThreshold: 100_000n * 10n ** 18n,
351
+ activationThreshold: 200_000n * 10n ** 18n,
352
+ localEjectionThreshold: 196_000n * 10n ** 18n,
353
+
354
+ governanceProposerRoundSize: 300, // TODO TMNT-322
355
+ governanceProposerQuorum: 151, // TODO TMNT-322
356
+
357
+ // Node slashing config
358
+ // TODO TMNT-330
359
+ slashMinPenaltyPercentage: 0.5,
360
+ slashMaxPenaltyPercentage: 2.0,
361
+ slashInactivityTargetPercentage: 0.7,
362
+ slashInactivityConsecutiveEpochThreshold: 2,
363
+ slashInactivityPenalty: 2_000n * 10n ** 18n,
364
+ slashPrunePenalty: 0n, // 2_000n * 10n ** 18n, We disable slashing for prune offenses right now
365
+ slashDataWithholdingPenalty: 0n, // 2_000n * 10n ** 18n, We disable slashing for data withholding offenses right now
366
+ slashProposeInvalidAttestationsPenalty: 50_000n * 10n ** 18n,
367
+ slashAttestDescendantOfInvalidPenalty: 50_000n * 10n ** 18n,
368
+ slashUnknownPenalty: 2_000n * 10n ** 18n,
369
+ slashBroadcastedInvalidBlockPenalty: 0n, // 10_000n * 10n ** 18n, Disabled for now until further testing
370
+ slashMaxPayloadSize: 50,
371
+ slashGracePeriodL2Slots: 32 * 4, // One round from genesis
372
+ slashOffenseExpirationRounds: 8,
373
+ sentinelEnabled: true,
374
+ slashExecuteRoundsLookBack: 4,
375
+
376
+ ...DefaultNetworkDBMapSizeConfig,
251
377
  };
252
378
 
253
379
  const BOOTNODE_CACHE_DURATION_MS = 60 * 60 * 1000; // 1 hour;
254
380
 
255
381
  export async function getBootnodes(networkName: NetworkNames, cacheDir?: string) {
256
- const cacheFile = cacheDir ? join(cacheDir, networkName, 'bootnodes.json') : undefined;
257
- try {
258
- if (cacheFile) {
259
- const info = await stat(cacheFile);
260
- if (info.mtimeMs + BOOTNODE_CACHE_DURATION_MS > Date.now()) {
261
- return JSON.parse(await readFile(cacheFile, 'utf-8'))['bootnodes'];
262
- }
263
- }
264
- } catch {
265
- // no-op. Get the remote-file
266
- }
267
-
268
382
  const url = `http://static.aztec.network/${networkName}/bootnodes.json`;
269
- const response = await fetch(url);
270
- if (!response.ok) {
271
- throw new Error(
272
- `Failed to fetch basic contract addresses from ${url}. Check you are using a correct network name.`,
273
- );
274
- }
275
- const json = await response.json();
276
-
277
- try {
278
- if (cacheFile) {
279
- await mkdir(dirname(cacheFile), { recursive: true });
280
- await writeFile(cacheFile, JSON.stringify(json), 'utf-8');
281
- }
282
- } catch {
283
- // no-op
284
- }
383
+ const data = await cachedFetch(url, {
384
+ cacheDurationMs: BOOTNODE_CACHE_DURATION_MS,
385
+ cacheFile: cacheDir ? join(cacheDir, networkName, 'bootnodes.json') : undefined,
386
+ });
285
387
 
286
- return json['bootnodes'];
388
+ return data?.bootnodes;
287
389
  }
288
390
 
289
391
  export async function getL2ChainConfig(
@@ -297,6 +399,8 @@ export async function getL2ChainConfig(
297
399
  config = { ...testnetL2ChainConfig };
298
400
  } else if (networkName === 'staging-ignition') {
299
401
  config = { ...stagingIgnitionL2ChainConfig };
402
+ } else if (networkName === 'ignition') {
403
+ config = { ...ignitionL2ChainConfig };
300
404
  }
301
405
  if (!config) {
302
406
  return undefined;
@@ -309,23 +413,6 @@ export async function getL2ChainConfig(
309
413
  return config;
310
414
  }
311
415
 
312
- function enrichVar(envVar: EnvVar, value: string | undefined) {
313
- // Don't override
314
- if (process.env[envVar] || value === undefined) {
315
- return;
316
- }
317
- process.env[envVar] = value;
318
- }
319
-
320
- function enrichEthAddressVar(envVar: EnvVar, value: string) {
321
- // EthAddress doesn't like being given empty strings
322
- if (value === '') {
323
- enrichVar(envVar, EthAddress.ZERO.toString());
324
- return;
325
- }
326
- enrichVar(envVar, value);
327
- }
328
-
329
416
  function getDefaultDataDir(networkName: NetworkNames): string {
330
417
  return path.join(process.env.HOME || '~', '.aztec', networkName, 'data');
331
418
  }
@@ -355,6 +442,12 @@ export async function enrichEnvironmentWithChainConfig(networkName: NetworkNames
355
442
  enrichVar('SYNC_SNAPSHOTS_URL', config.snapshotsUrl);
356
443
  enrichVar('P2P_MAX_TX_POOL_SIZE', config.maxTxPoolSize.toString());
357
444
 
445
+ enrichVar('DATA_STORE_MAP_SIZE_KB', config.dbMapSizeKb.toString());
446
+ enrichVar('ARCHIVER_STORE_MAP_SIZE_KB', config.archiverStoreMapSizeKb.toString());
447
+ enrichVar('NOTE_HASH_TREE_MAP_SIZE_KB', config.noteHashTreeMapSizeKb.toString());
448
+ enrichVar('NULLIFIER_TREE_MAP_SIZE_KB', config.nullifierTreeMapSizeKb.toString());
449
+ enrichVar('PUBLIC_DATA_TREE_MAP_SIZE_KB', config.publicDataTreeMapSizeKb.toString());
450
+
358
451
  if (config.autoUpdate) {
359
452
  enrichVar('AUTO_UPDATE', config.autoUpdate?.toString());
360
453
  }
@@ -387,6 +480,7 @@ export async function enrichEnvironmentWithChainConfig(networkName: NetworkNames
387
480
  enrichVar('AZTEC_PROOF_SUBMISSION_EPOCHS', config.aztecProofSubmissionEpochs.toString());
388
481
  enrichVar('AZTEC_ACTIVATION_THRESHOLD', config.activationThreshold.toString());
389
482
  enrichVar('AZTEC_EJECTION_THRESHOLD', config.ejectionThreshold.toString());
483
+ enrichVar('AZTEC_LOCAL_EJECTION_THRESHOLD', config.localEjectionThreshold.toString());
390
484
  enrichVar('AZTEC_SLASHING_QUORUM', config.slashingQuorum?.toString());
391
485
  enrichVar('AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS', config.slashingRoundSizeInEpochs.toString());
392
486
  enrichVar('AZTEC_GOVERNANCE_PROPOSER_QUORUM', config.governanceProposerQuorum?.toString());
@@ -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,102 @@
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
+ enrichVar('SYNC_SNAPSHOTS_URL', networkConfig.snapshots.join(','));
97
+
98
+ enrichEthAddressVar('REGISTRY_CONTRACT_ADDRESS', networkConfig.registryAddress.toString());
99
+ if (networkConfig.feeAssetHandlerAddress) {
100
+ enrichEthAddressVar('FEE_ASSET_HANDLER_CONTRACT_ADDRESS', networkConfig.feeAssetHandlerAddress.toString());
101
+ }
102
+ }