@aztec/end-to-end 2.0.3 → 2.1.0-rc.2

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.
Files changed (38) hide show
  1. package/dest/e2e_epochs/epochs_test.d.ts +4 -2
  2. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  3. package/dest/e2e_epochs/epochs_test.js +7 -7
  4. package/dest/e2e_multi_validator/utils.d.ts.map +1 -1
  5. package/dest/e2e_multi_validator/utils.js +3 -9
  6. package/dest/e2e_p2p/inactivity_slash_test.d.ts +31 -0
  7. package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -0
  8. package/dest/e2e_p2p/inactivity_slash_test.js +132 -0
  9. package/dest/e2e_p2p/p2p_network.d.ts +6 -4
  10. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  11. package/dest/e2e_p2p/p2p_network.js +4 -5
  12. package/dest/e2e_p2p/shared.d.ts +2 -1
  13. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  14. package/dest/e2e_p2p/shared.js +8 -12
  15. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  16. package/dest/fixtures/e2e_prover_test.js +2 -1
  17. package/dest/fixtures/setup_p2p_test.d.ts +10 -2
  18. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  19. package/dest/fixtures/setup_p2p_test.js +38 -20
  20. package/dest/fixtures/snapshot_manager.d.ts.map +1 -1
  21. package/dest/fixtures/snapshot_manager.js +16 -13
  22. package/dest/fixtures/utils.d.ts +3 -1
  23. package/dest/fixtures/utils.d.ts.map +1 -1
  24. package/dest/fixtures/utils.js +7 -6
  25. package/dest/fixtures/web3signer.d.ts +5 -0
  26. package/dest/fixtures/web3signer.d.ts.map +1 -0
  27. package/dest/fixtures/web3signer.js +42 -0
  28. package/package.json +37 -37
  29. package/src/e2e_epochs/epochs_test.ts +10 -8
  30. package/src/e2e_multi_validator/utils.ts +3 -9
  31. package/src/e2e_p2p/inactivity_slash_test.ts +174 -0
  32. package/src/e2e_p2p/p2p_network.ts +11 -10
  33. package/src/e2e_p2p/shared.ts +13 -7
  34. package/src/fixtures/e2e_prover_test.ts +1 -0
  35. package/src/fixtures/setup_p2p_test.ts +60 -19
  36. package/src/fixtures/snapshot_manager.ts +19 -11
  37. package/src/fixtures/utils.ts +10 -7
  38. package/src/fixtures/web3signer.ts +46 -0
@@ -14,6 +14,7 @@ import {
14
14
  import type { RollupCheatCodes } from '@aztec/aztec/testing';
15
15
  import type { EmpireSlashingProposerContract, RollupContract, TallySlashingProposerContract } from '@aztec/ethereum';
16
16
  import { timesAsync, unique } from '@aztec/foundation/collection';
17
+ import { pluralize } from '@aztec/foundation/string';
17
18
  import type { TestDateProvider } from '@aztec/foundation/timer';
18
19
  import type { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
19
20
  import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.js/Test';
@@ -164,17 +165,20 @@ export async function awaitOffenseDetected({
164
165
  nodeAdmin,
165
166
  slashingRoundSize,
166
167
  epochDuration,
168
+ waitUntilOffenseCount,
167
169
  }: {
168
170
  nodeAdmin: AztecNodeAdmin;
169
171
  logger: Logger;
170
172
  slashingRoundSize: number;
171
173
  epochDuration: number;
174
+ waitUntilOffenseCount?: number;
172
175
  }) {
173
- logger.info(`Waiting for an offense to be detected`);
176
+ const targetOffenseCount = waitUntilOffenseCount ?? 1;
177
+ logger.warn(`Waiting for ${pluralize('offense', targetOffenseCount)} to be detected`);
174
178
  const offenses = await retryUntil(
175
179
  async () => {
176
180
  const offenses = await nodeAdmin.getSlashOffenses('all');
177
- if (offenses.length > 0) {
181
+ if (offenses.length >= targetOffenseCount) {
178
182
  return offenses;
179
183
  }
180
184
  },
@@ -219,8 +223,9 @@ export async function awaitCommitteeKicked({
219
223
 
220
224
  logger.info(`Advancing epochs so we start slashing`);
221
225
  await cheatCodes.debugRollup();
222
- await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
223
- await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
226
+ await cheatCodes.advanceToEpoch((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochs()) + 1n, {
227
+ updateDateProvider: dateProvider,
228
+ });
224
229
 
225
230
  // Await for the slash payload to be created if empire (no payload is created on tally until execution time)
226
231
  if (slashingProposer.type === 'empire') {
@@ -265,10 +270,11 @@ export async function awaitCommitteeKicked({
265
270
  expect(attesterInfo.status).toEqual(2); // Living
266
271
  }
267
272
 
268
- logger.info(`Advancing two epochs to check current committee`);
273
+ logger.info(`Advancing to check current committee`);
269
274
  await cheatCodes.debugRollup();
270
- await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
271
- await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
275
+ await cheatCodes.advanceToEpoch((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochs()) + 1n, {
276
+ updateDateProvider: dateProvider,
277
+ });
272
278
  await cheatCodes.debugRollup();
273
279
 
274
280
  const committeeNextEpoch = await rollup.getCurrentEpochCommittee();
@@ -308,6 +308,7 @@ export class FullProverTest {
308
308
  txGatheringMaxParallelRequestsPerNode: 100,
309
309
  txGatheringTimeoutMs: 24_000,
310
310
  proverNodeFailedEpochStore: undefined,
311
+ proverNodeEpochProvingDelayMs: undefined,
311
312
  };
312
313
  const sponsoredFPCAddress = await getSponsoredFPCAddress();
313
314
  const { prefilledPublicData } = await getGenesisValues(
@@ -39,7 +39,7 @@ export function generatePrivateKeys(startIndex: number, numberOfKeys: number): `
39
39
  }
40
40
 
41
41
  export async function createNodes(
42
- config: AztecNodeConfig,
42
+ config: AztecNodeConfig & { dontStartSequencer?: boolean },
43
43
  dateProvider: DateProvider,
44
44
  bootstrapNodeEnr: string,
45
45
  numNodes: number,
@@ -86,9 +86,9 @@ export async function createNodes(
86
86
  return nodes;
87
87
  }
88
88
 
89
- // creates a P2P enabled instance of Aztec Node Service
89
+ /** Creates a P2P enabled instance of Aztec Node Service with a validator */
90
90
  export async function createNode(
91
- config: AztecNodeConfig,
91
+ config: AztecNodeConfig & { dontStartSequencer?: boolean },
92
92
  dateProvider: DateProvider,
93
93
  tcpPort: number,
94
94
  bootstrapNode: string | undefined,
@@ -101,7 +101,36 @@ export async function createNode(
101
101
  const createNode = async () => {
102
102
  const validatorConfig = await createValidatorConfig(config, bootstrapNode, tcpPort, addressIndex, dataDirectory);
103
103
  const telemetry = getEndToEndTestTelemetryClient(metricsPort);
104
- return await AztecNodeService.createAndSync(validatorConfig, { telemetry, dateProvider }, { prefilledPublicData });
104
+ return await AztecNodeService.createAndSync(
105
+ validatorConfig,
106
+ { telemetry, dateProvider },
107
+ { prefilledPublicData, dontStartSequencer: config.dontStartSequencer },
108
+ );
109
+ };
110
+ return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createNode) : createNode();
111
+ }
112
+
113
+ /** Creates a P2P enabled instance of Aztec Node Service without a validator */
114
+ export async function createNonValidatorNode(
115
+ baseConfig: AztecNodeConfig,
116
+ dateProvider: DateProvider,
117
+ tcpPort: number,
118
+ bootstrapNode: string | undefined,
119
+ prefilledPublicData?: PublicDataTreeLeaf[],
120
+ dataDirectory?: string,
121
+ metricsPort?: number,
122
+ loggerIdStorage?: AsyncLocalStorage<string>,
123
+ ) {
124
+ const createNode = async () => {
125
+ const p2pConfig = await createP2PConfig(baseConfig, bootstrapNode, tcpPort, dataDirectory);
126
+ const config: AztecNodeConfig = {
127
+ ...p2pConfig,
128
+ disableValidator: true,
129
+ validatorPrivateKeys: undefined,
130
+ publisherPrivateKeys: [],
131
+ };
132
+ const telemetry = getEndToEndTestTelemetryClient(metricsPort);
133
+ return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { prefilledPublicData });
105
134
  };
106
135
  return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createNode) : createNode();
107
136
  }
@@ -121,14 +150,13 @@ export async function createProverNode(
121
150
  const proverNodePrivateKey = getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!;
122
151
  const telemetry = getEndToEndTestTelemetryClient(metricsPort);
123
152
 
124
- const proverConfig: Partial<ProverNodeConfig> = {
125
- p2pIp: `127.0.0.1`,
126
- p2pPort: tcpPort ?? (await getPort()),
127
- p2pEnabled: true,
128
- peerCheckIntervalMS: TEST_PEER_CHECK_INTERVAL_MS,
129
- blockCheckIntervalMS: 1000,
130
- bootstrapNodes: bootstrapNode ? [bootstrapNode] : [],
131
- };
153
+ const proverConfig: Partial<ProverNodeConfig> = await createP2PConfig(
154
+ config,
155
+ bootstrapNode,
156
+ tcpPort,
157
+ dataDirectory,
158
+ );
159
+
132
160
  const aztecNodeRpcTxProvider = undefined;
133
161
  return await createAndSyncProverNode(
134
162
  bufferToHex(proverNodePrivateKey),
@@ -142,20 +170,14 @@ export async function createProverNode(
142
170
  return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createProverNode) : createProverNode();
143
171
  }
144
172
 
145
- export async function createValidatorConfig(
173
+ export async function createP2PConfig(
146
174
  config: AztecNodeConfig,
147
175
  bootstrapNodeEnr?: string,
148
176
  port?: number,
149
- addressIndex: number = 1,
150
177
  dataDirectory?: string,
151
178
  ) {
152
179
  port = port ?? (await getPort());
153
180
 
154
- const attesterPrivateKey = bufferToHex(getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!);
155
-
156
- config.validatorPrivateKeys = new SecretValue([attesterPrivateKey]);
157
- config.publisherPrivateKeys = [new SecretValue(attesterPrivateKey)];
158
-
159
181
  const nodeConfig: AztecNodeConfig = {
160
182
  ...config,
161
183
  p2pIp: `127.0.0.1`,
@@ -169,3 +191,22 @@ export async function createValidatorConfig(
169
191
 
170
192
  return nodeConfig;
171
193
  }
194
+
195
+ export async function createValidatorConfig(
196
+ config: AztecNodeConfig,
197
+ bootstrapNodeEnr?: string,
198
+ port?: number,
199
+ addressIndex: number = 1,
200
+ dataDirectory?: string,
201
+ ) {
202
+ const attesterPrivateKey = bufferToHex(getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!);
203
+ const p2pConfig = await createP2PConfig(config, bootstrapNodeEnr, port, dataDirectory);
204
+ const nodeConfig: AztecNodeConfig = {
205
+ ...config,
206
+ ...p2pConfig,
207
+ validatorPrivateKeys: new SecretValue([attesterPrivateKey]),
208
+ publisherPrivateKeys: [new SecretValue(attesterPrivateKey)],
209
+ };
210
+
211
+ return nodeConfig;
212
+ }
@@ -333,14 +333,6 @@ async function setupFromFresh(
333
333
  }
334
334
  aztecNodeConfig.blobSinkUrl = `http://127.0.0.1:${blobSinkPort}`;
335
335
 
336
- // Start anvil. We go via a wrapper script to ensure if the parent dies, anvil dies.
337
- logger.verbose('Starting anvil...');
338
- const res = await startAnvil({ l1BlockTime: opts.ethereumSlotDuration });
339
- const anvil = res.anvil;
340
- aztecNodeConfig.l1RpcUrls = [res.rpcUrl];
341
-
342
- // Deploy our L1 contracts.
343
- logger.verbose('Deploying L1 contracts...');
344
336
  const hdAccount = mnemonicToAccount(MNEMONIC, { addressIndex: 0 });
345
337
  const publisherPrivKeyRaw = hdAccount.getHdKey().privateKey;
346
338
  const publisherPrivKey = publisherPrivKeyRaw === null ? null : Buffer.from(publisherPrivKeyRaw);
@@ -354,8 +346,17 @@ async function setupFromFresh(
354
346
  aztecNodeConfig.validatorPrivateKeys = new SecretValue([`0x${validatorPrivKey!.toString('hex')}`]);
355
347
  aztecNodeConfig.coinbase = opts.coinbase ?? EthAddress.fromString(`${hdAccount.address}`);
356
348
 
349
+ logger.info(`Setting up environment with config`, aztecNodeConfig);
350
+
351
+ // Start anvil. We go via a wrapper script to ensure if the parent dies, anvil dies.
352
+ logger.verbose('Starting anvil...');
353
+ const res = await startAnvil({ l1BlockTime: opts.ethereumSlotDuration });
354
+ const anvil = res.anvil;
355
+ aztecNodeConfig.l1RpcUrls = [res.rpcUrl];
357
356
  const ethCheatCodes = new EthCheatCodesWithState(aztecNodeConfig.l1RpcUrls);
358
357
 
358
+ // Deploy our L1 contracts.
359
+ logger.verbose('Deploying L1 contracts...');
359
360
  if (opts.l1StartTime) {
360
361
  await ethCheatCodes.warp(opts.l1StartTime, { resetBlockInterval: true });
361
362
  }
@@ -379,7 +380,6 @@ async function setupFromFresh(
379
380
  });
380
381
  aztecNodeConfig.l1Contracts = deployL1ContractsValues.l1ContractAddresses;
381
382
  aztecNodeConfig.rollupVersion = deployL1ContractsValues.rollupVersion;
382
- aztecNodeConfig.l1PublishRetryIntervalMS = 100;
383
383
 
384
384
  const dateProvider = new TestDateProvider();
385
385
 
@@ -432,7 +432,11 @@ async function setupFromFresh(
432
432
  proverNode = await createAndSyncProverNode(
433
433
  `0x${proverNodePrivateKey!.toString('hex')}`,
434
434
  aztecNodeConfig,
435
- { dataDirectory: path.join(directoryToCleanup, randomBytes(8).toString('hex')), p2pEnabled: false },
435
+ {
436
+ ...aztecNodeConfig.proverNodeConfig,
437
+ dataDirectory: path.join(directoryToCleanup, randomBytes(8).toString('hex')),
438
+ p2pEnabled: false,
439
+ },
436
440
  aztecNode,
437
441
  prefilledPublicData,
438
442
  );
@@ -558,7 +562,11 @@ async function setupFromState(statePath: string, logger: Logger): Promise<Subsys
558
562
  proverNode = await createAndSyncProverNode(
559
563
  proverNodePrivateKeyHex,
560
564
  aztecNodeConfig,
561
- { dataDirectory: path.join(directoryToCleanup, randomBytes(8).toString('hex')) },
565
+ {
566
+ ...aztecNodeConfig.proverNodeConfig,
567
+ dataDirectory: path.join(directoryToCleanup, randomBytes(8).toString('hex')),
568
+ p2pEnabled: false,
569
+ },
562
570
  aztecNode,
563
571
  prefilledPublicData,
564
572
  );
@@ -576,7 +576,7 @@ export async function setup(
576
576
  await blobSink.start();
577
577
  config.blobSinkUrl = `http://localhost:${blobSinkPort}`;
578
578
 
579
- logger.verbose('Creating and synching an aztec node...');
579
+ logger.verbose('Creating and synching an aztec node', config);
580
580
 
581
581
  const acvmConfig = await getACVMConfig(logger);
582
582
  if (acvmConfig) {
@@ -589,7 +589,6 @@ export async function setup(
589
589
  config.bbBinaryPath = bbConfig.bbBinaryPath;
590
590
  config.bbWorkingDirectory = bbConfig.bbWorkingDirectory;
591
591
  }
592
- config.l1PublishRetryIntervalMS = 100;
593
592
 
594
593
  const blobSinkClient = createBlobSinkClient(config, { logger: createLogger('node:blob-sink:client') });
595
594
 
@@ -666,9 +665,10 @@ export async function setup(
666
665
  (opts.aztecTargetCommitteeSize && opts.aztecTargetCommitteeSize > 0) ||
667
666
  (opts.initialValidators && opts.initialValidators.length > 0)
668
667
  ) {
669
- // We need to advance to epoch 2 such that the committee is set up.
670
- logger.info(`Advancing to epoch 2`);
671
- await cheatCodes.rollup.advanceToEpoch(2n, { updateDateProvider: dateProvider });
668
+ // We need to advance such that the committee is set up.
669
+ await cheatCodes.rollup.advanceToEpoch((await cheatCodes.rollup.getEpoch()) + BigInt(config.lagInEpochs + 1), {
670
+ updateDateProvider: dateProvider,
671
+ });
672
672
  await cheatCodes.rollup.setupEpoch();
673
673
  await cheatCodes.rollup.debugRollup();
674
674
  }
@@ -926,7 +926,7 @@ export async function waitForProvenChain(node: AztecNode, targetBlock?: number,
926
926
  export function createAndSyncProverNode(
927
927
  proverNodePrivateKey: `0x${string}`,
928
928
  aztecNodeConfig: AztecNodeConfig,
929
- proverNodeConfig: Partial<ProverNodeConfig> & Pick<DataStoreConfig, 'dataDirectory'>,
929
+ proverNodeConfig: Partial<ProverNodeConfig> & Pick<DataStoreConfig, 'dataDirectory'> & { dontStart?: boolean },
930
930
  aztecNode: AztecNode | undefined,
931
931
  prefilledPublicData: PublicDataTreeLeaf[] = [],
932
932
  proverNodeDeps: ProverNodeDeps = {},
@@ -962,6 +962,7 @@ export function createAndSyncProverNode(
962
962
  txGatheringTimeoutMs: 24_000,
963
963
  proverNodeFailedEpochStore: undefined,
964
964
  proverId: EthAddress.fromNumber(1),
965
+ proverNodeEpochProvingDelayMs: undefined,
965
966
  ...proverNodeConfig,
966
967
  };
967
968
 
@@ -978,7 +979,9 @@ export function createAndSyncProverNode(
978
979
  { prefilledPublicData },
979
980
  );
980
981
  getLogger().info(`Created and synced prover node`, { publisherAddress: l1TxUtils.client.account!.address });
981
- await proverNode.start();
982
+ if (!proverNodeConfig.dontStart) {
983
+ await proverNode.start();
984
+ }
982
985
  return proverNode;
983
986
  });
984
987
  }
@@ -0,0 +1,46 @@
1
+ import { sleep } from '@aztec/aztec.js';
2
+ import { randomBytes } from '@aztec/foundation/crypto';
3
+
4
+ import { mkdirSync } from 'node:fs';
5
+ import { writeFile } from 'node:fs/promises';
6
+ import { join } from 'node:path';
7
+
8
+ export async function createWeb3SignerKeystore(dir: string, ...privateKeys: string[]) {
9
+ const yaml = privateKeys
10
+ .map(
11
+ pk => `\
12
+ type: file-raw
13
+ keyType: SECP256K1
14
+ privateKey: ${pk}`,
15
+ )
16
+ .join('\n---\n');
17
+
18
+ // NOTE: nodejs stdlib can only create temp directories, not temp files!
19
+ // this write uses wx (write-exclusive) so it'll throw if the file already exists
20
+ const path = join(dir, `keystore-${randomBytes(4).toString('hex')}.yaml`);
21
+ await writeFile(path, yaml, { flag: 'wx' });
22
+ }
23
+
24
+ export async function refreshWeb3Signer(url: string) {
25
+ await fetch(new URL('reload', url), { method: 'POST' });
26
+ // give the service a chance to load up the new files
27
+ // 1s might not be enough if there are a lot of files to scan
28
+ await sleep(1000);
29
+ }
30
+
31
+ export function getWeb3SignerTestKeystoreDir(): string {
32
+ if (process.env.WEB3_SIGNER_TEST_KEYSTORE_DIR) {
33
+ mkdirSync(process.env.WEB3_SIGNER_TEST_KEYSTORE_DIR, { recursive: true });
34
+ return process.env.WEB3_SIGNER_TEST_KEYSTORE_DIR;
35
+ } else {
36
+ throw new Error('Web3signer not running');
37
+ }
38
+ }
39
+
40
+ export function getWeb3SignerUrl(): string {
41
+ if (process.env.WEB3_SIGNER_URL) {
42
+ return process.env.WEB3_SIGNER_URL;
43
+ } else {
44
+ throw new Error('Web3signer not running');
45
+ }
46
+ }