@aztec/end-to-end 0.0.1-commit.db765a8 → 0.0.1-commit.ddcf04837

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 (94) hide show
  1. package/README.md +27 -0
  2. package/dest/bench/client_flows/client_flows_benchmark.d.ts +1 -1
  3. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  4. package/dest/bench/client_flows/client_flows_benchmark.js +21 -29
  5. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +3 -2
  6. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  7. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +1 -1
  8. package/dest/e2e_epochs/epochs_test.d.ts +3 -1
  9. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  10. package/dest/e2e_epochs/epochs_test.js +8 -5
  11. package/dest/e2e_fees/fees_test.d.ts +1 -1
  12. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  13. package/dest/e2e_fees/fees_test.js +9 -2
  14. package/dest/e2e_p2p/inactivity_slash_test.js +3 -3
  15. package/dest/e2e_p2p/p2p_network.d.ts +6 -8
  16. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  17. package/dest/e2e_p2p/p2p_network.js +15 -14
  18. package/dest/e2e_p2p/reqresp/utils.d.ts +1 -1
  19. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  20. package/dest/e2e_p2p/reqresp/utils.js +16 -3
  21. package/dest/e2e_p2p/shared.d.ts +16 -12
  22. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  23. package/dest/e2e_p2p/shared.js +33 -51
  24. package/dest/fixtures/authwit_proxy.d.ts +1 -1
  25. package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
  26. package/dest/fixtures/authwit_proxy.js +4 -0
  27. package/dest/fixtures/e2e_prover_test.d.ts +4 -3
  28. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  29. package/dest/fixtures/e2e_prover_test.js +7 -12
  30. package/dest/fixtures/get_bb_config.d.ts +1 -1
  31. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  32. package/dest/fixtures/get_bb_config.js +5 -5
  33. package/dest/fixtures/setup.d.ts +16 -8
  34. package/dest/fixtures/setup.d.ts.map +1 -1
  35. package/dest/fixtures/setup.js +24 -18
  36. package/dest/fixtures/setup_p2p_test.d.ts +6 -6
  37. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  38. package/dest/fixtures/setup_p2p_test.js +8 -8
  39. package/dest/fixtures/token_utils.d.ts +1 -1
  40. package/dest/fixtures/token_utils.d.ts.map +1 -1
  41. package/dest/fixtures/token_utils.js +2 -5
  42. package/dest/legacy-jest-resolver.d.cts +3 -0
  43. package/dest/legacy-jest-resolver.d.cts.map +1 -0
  44. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  45. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  46. package/dest/shared/uniswap_l1_l2.js +9 -12
  47. package/dest/simulators/lending_simulator.d.ts +1 -1
  48. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  49. package/dest/simulators/lending_simulator.js +2 -2
  50. package/dest/simulators/token_simulator.js +1 -1
  51. package/dest/spartan/setup_test_wallets.d.ts +4 -2
  52. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  53. package/dest/spartan/setup_test_wallets.js +70 -40
  54. package/dest/spartan/utils/config.d.ts +4 -1
  55. package/dest/spartan/utils/config.d.ts.map +1 -1
  56. package/dest/spartan/utils/config.js +1 -0
  57. package/dest/spartan/utils/index.d.ts +2 -1
  58. package/dest/spartan/utils/index.d.ts.map +1 -1
  59. package/dest/spartan/utils/index.js +2 -0
  60. package/dest/spartan/utils/pod_logs.d.ts +25 -0
  61. package/dest/spartan/utils/pod_logs.d.ts.map +1 -0
  62. package/dest/spartan/utils/pod_logs.js +74 -0
  63. package/dest/test-wallet/test_wallet.d.ts +24 -23
  64. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  65. package/dest/test-wallet/test_wallet.js +115 -80
  66. package/dest/test-wallet/worker_wallet.d.ts +4 -4
  67. package/dest/test-wallet/worker_wallet.d.ts.map +1 -1
  68. package/dest/test-wallet/worker_wallet_schema.d.ts +9 -4
  69. package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -1
  70. package/package.json +40 -40
  71. package/src/bench/client_flows/client_flows_benchmark.ts +35 -23
  72. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +3 -6
  73. package/src/e2e_epochs/epochs_test.ts +17 -5
  74. package/src/e2e_fees/fees_test.ts +5 -2
  75. package/src/e2e_p2p/inactivity_slash_test.ts +3 -3
  76. package/src/e2e_p2p/p2p_network.ts +23 -28
  77. package/src/e2e_p2p/reqresp/utils.ts +24 -3
  78. package/src/e2e_p2p/shared.ts +36 -67
  79. package/src/fixtures/authwit_proxy.ts +4 -0
  80. package/src/fixtures/e2e_prover_test.ts +12 -17
  81. package/src/fixtures/get_bb_config.ts +7 -6
  82. package/src/fixtures/setup.ts +38 -25
  83. package/src/fixtures/setup_p2p_test.ts +9 -9
  84. package/src/fixtures/token_utils.ts +1 -4
  85. package/src/legacy-jest-resolver.cjs +135 -0
  86. package/src/shared/uniswap_l1_l2.ts +29 -24
  87. package/src/simulators/lending_simulator.ts +4 -2
  88. package/src/simulators/token_simulator.ts +1 -1
  89. package/src/spartan/setup_test_wallets.ts +97 -35
  90. package/src/spartan/utils/config.ts +1 -0
  91. package/src/spartan/utils/index.ts +3 -0
  92. package/src/spartan/utils/pod_logs.ts +99 -0
  93. package/src/test-wallet/test_wallet.ts +144 -99
  94. package/src/test-wallet/worker_wallet.ts +3 -2
@@ -1,10 +1,11 @@
1
+ import { NO_FROM } from '@aztec/aztec.js/account';
1
2
  import { AztecAddress } from '@aztec/aztec.js/addresses';
2
3
  import { FeeJuicePaymentMethodWithClaim } from '@aztec/aztec.js/fee';
3
4
  import { type FeePaymentMethod, PrivateFeePaymentMethod, SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee';
4
5
  import { type Logger, createLogger } from '@aztec/aztec.js/log';
5
6
  import type { AztecNode } from '@aztec/aztec.js/node';
6
7
  import type { Wallet } from '@aztec/aztec.js/wallet';
7
- import { CheatCodes } from '@aztec/aztec/testing';
8
+ import { CheatCodes, getTokenAllowedSetupFunctions } from '@aztec/aztec/testing';
8
9
  import { createExtendedL1Client } from '@aztec/ethereum/client';
9
10
  import { RollupContract } from '@aztec/ethereum/contracts';
10
11
  import type { DeployAztecL1ContractsArgs } from '@aztec/ethereum/deploy-aztec-l1-contracts';
@@ -130,11 +131,14 @@ export class ClientFlowsBenchmark {
130
131
 
131
132
  async setup() {
132
133
  this.logger.info('Setting up subsystems from fresh');
134
+ // Token allowlist entries are test-only: FPC-based fee payment with custom tokens won't work on mainnet alpha.
135
+ const tokenAllowList = await getTokenAllowedSetupFunctions();
133
136
  this.context = await setup(0, {
134
137
  ...this.setupOptions,
135
138
  fundSponsoredFPC: true,
136
139
  skipAccountDeployment: true,
137
140
  l1ContractsArgs: this.setupOptions,
141
+ txPublicSetupAllowListExtend: [...(this.setupOptions.txPublicSetupAllowListExtend ?? []), ...tokenAllowList],
138
142
  });
139
143
  await this.applyBaseSetup();
140
144
 
@@ -246,11 +250,14 @@ export class ClientFlowsBenchmark {
246
250
 
247
251
  async applyDeployBananaToken() {
248
252
  this.logger.info('Applying banana token deployment');
249
- const {
250
- receipt: { contract: bananaCoin, instance: bananaCoinInstance },
251
- } = await BananaCoin.deploy(this.adminWallet, this.adminAddress, 'BC', 'BC', 18n).send({
253
+ const { contract: bananaCoin, instance: bananaCoinInstance } = await BananaCoin.deploy(
254
+ this.adminWallet,
255
+ this.adminAddress,
256
+ 'BC',
257
+ 'BC',
258
+ 18n,
259
+ ).send({
252
260
  from: this.adminAddress,
253
- wait: { returnReceipt: true },
254
261
  });
255
262
  this.logger.info(`BananaCoin deployed at ${bananaCoin.address}`);
256
263
  this.bananaCoin = bananaCoin;
@@ -259,11 +266,14 @@ export class ClientFlowsBenchmark {
259
266
 
260
267
  async applyDeployCandyBarToken() {
261
268
  this.logger.info('Applying candy bar token deployment');
262
- const {
263
- receipt: { contract: candyBarCoin, instance: candyBarCoinInstance },
264
- } = await TokenContract.deploy(this.adminWallet, this.adminAddress, 'CBC', 'CBC', 18n).send({
269
+ const { contract: candyBarCoin, instance: candyBarCoinInstance } = await TokenContract.deploy(
270
+ this.adminWallet,
271
+ this.adminAddress,
272
+ 'CBC',
273
+ 'CBC',
274
+ 18n,
275
+ ).send({
265
276
  from: this.adminAddress,
266
- wait: { returnReceipt: true },
267
277
  });
268
278
  this.logger.info(`CandyBarCoin deployed at ${candyBarCoin.address}`);
269
279
  this.candyBarCoin = candyBarCoin;
@@ -276,11 +286,12 @@ export class ClientFlowsBenchmark {
276
286
  expect((await this.context.wallet.getContractMetadata(feeJuiceContract.address)).isContractPublished).toBe(true);
277
287
 
278
288
  const bananaCoin = this.bananaCoin;
279
- const {
280
- receipt: { contract: bananaFPC, instance: bananaFPCInstance },
281
- } = await FPCContract.deploy(this.adminWallet, bananaCoin.address, this.adminAddress).send({
289
+ const { contract: bananaFPC, instance: bananaFPCInstance } = await FPCContract.deploy(
290
+ this.adminWallet,
291
+ bananaCoin.address,
292
+ this.adminAddress,
293
+ ).send({
282
294
  from: this.adminAddress,
283
- wait: { returnReceipt: true },
284
295
  });
285
296
 
286
297
  this.logger.info(`BananaPay deployed at ${bananaFPC.address}`);
@@ -330,7 +341,7 @@ export class ClientFlowsBenchmark {
330
341
  const claim = await this.feeJuiceBridgeTestHarness.prepareTokensOnL1(benchysAddress);
331
342
  const behchysDeployMethod = await benchysAccountManager.getDeployMethod();
332
343
  await behchysDeployMethod.send({
333
- from: AztecAddress.ZERO,
344
+ from: NO_FROM,
334
345
  fee: { paymentMethod: new FeeJuicePaymentMethodWithClaim(benchysAddress, claim) },
335
346
  });
336
347
  // Register benchy on the user's Wallet, where we're going to be interacting from
@@ -344,20 +355,21 @@ export class ClientFlowsBenchmark {
344
355
 
345
356
  public async applyDeployAmm() {
346
357
  this.logger.info('Applying AMM deployment');
347
- const {
348
- receipt: { contract: liquidityToken, instance: liquidityTokenInstance },
349
- } = await TokenContract.deploy(this.adminWallet, this.adminAddress, 'LPT', 'LPT', 18n).send({
358
+ const { contract: liquidityToken, instance: liquidityTokenInstance } = await TokenContract.deploy(
359
+ this.adminWallet,
360
+ this.adminAddress,
361
+ 'LPT',
362
+ 'LPT',
363
+ 18n,
364
+ ).send({
350
365
  from: this.adminAddress,
351
- wait: { returnReceipt: true },
352
366
  });
353
- const {
354
- receipt: { contract: amm, instance: ammInstance },
355
- } = await AMMContract.deploy(
367
+ const { contract: amm, instance: ammInstance } = await AMMContract.deploy(
356
368
  this.adminWallet,
357
369
  this.bananaCoin.address,
358
370
  this.candyBarCoin.address,
359
371
  liquidityToken.address,
360
- ).send({ from: this.adminAddress, wait: { returnReceipt: true } });
372
+ ).send({ from: this.adminAddress });
361
373
  this.logger.info(`AMM deployed at ${amm.address}`);
362
374
  await liquidityToken.methods.set_minter(amm.address, true).send({ from: this.adminAddress });
363
375
  this.liquidityToken = liquidityToken;
@@ -375,7 +387,7 @@ export class ClientFlowsBenchmark {
375
387
  // The private fee paying method assembled on the app side requires knowledge of the maximum
376
388
  // fee the user is willing to pay
377
389
  const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1.5);
378
- const gasSettings = GasSettings.default({ maxFeesPerGas });
390
+ const gasSettings = GasSettings.fallback({ maxFeesPerGas });
379
391
  return new PrivateFeePaymentMethod(this.bananaFPC.address, sender, wallet, gasSettings);
380
392
  }
381
393
 
@@ -10,6 +10,7 @@ import { TokenBlacklistContract } from '@aztec/noir-contracts.js/TokenBlacklist'
10
10
  import { GenericProxyContract } from '@aztec/noir-test-contracts.js/GenericProxy';
11
11
  import { InvalidAccountContract } from '@aztec/noir-test-contracts.js/InvalidAccount';
12
12
  import type { SequencerClient } from '@aztec/sequencer-client';
13
+ import type { AztecNodeDebug } from '@aztec/stdlib/interfaces/client';
13
14
 
14
15
  import { jest } from '@jest/globals';
15
16
 
@@ -57,7 +58,7 @@ export class BlacklistTokenContractTest {
57
58
  authwitProxy!: GenericProxyContract;
58
59
  cheatCodes!: CheatCodes;
59
60
  sequencer!: SequencerClient;
60
- aztecNode!: AztecNode;
61
+ aztecNode!: AztecNode & AztecNodeDebug;
61
62
 
62
63
  adminAddress!: AztecAddress;
63
64
  otherAddress!: AztecAddress;
@@ -68,11 +69,7 @@ export class BlacklistTokenContractTest {
68
69
  }
69
70
 
70
71
  async crossTimestampOfChange() {
71
- await this.cheatCodes.warpL2TimeAtLeastBy(
72
- this.sequencer,
73
- this.aztecNode,
74
- BlacklistTokenContractTest.CHANGE_ROLES_DELAY,
75
- );
72
+ await this.cheatCodes.warpL2TimeAtLeastBy(this.aztecNode, BlacklistTokenContractTest.CHANGE_ROLES_DELAY);
76
73
  }
77
74
 
78
75
  /**
@@ -28,6 +28,7 @@ import { type SequencerClient, type SequencerEvents, SequencerState } from '@azt
28
28
  import { type BlockParameter, EthAddress } from '@aztec/stdlib/block';
29
29
  import { type L1RollupConstants, getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
30
30
  import { tryStop } from '@aztec/stdlib/interfaces/server';
31
+ import type { SlashingProtectionDatabase } from '@aztec/validator-ha-signer/types';
31
32
 
32
33
  import { join } from 'path';
33
34
  import type { Hex } from 'viem';
@@ -144,7 +145,7 @@ export class EpochsTestContext {
144
145
  proverId: EthAddress.fromNumber(1),
145
146
  worldStateCheckpointHistory: WORLD_STATE_CHECKPOINT_HISTORY,
146
147
  exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
147
- slasherFlavor: 'none',
148
+ slasherEnabled: false,
148
149
  l1PublishingTime,
149
150
  ...opts,
150
151
  },
@@ -181,6 +182,7 @@ export class EpochsTestContext {
181
182
  ethereumSlotDuration,
182
183
  proofSubmissionEpochs: Number(await this.rollup.getProofSubmissionEpochs()),
183
184
  targetCommitteeSize: await this.rollup.getTargetCommitteeSize(),
185
+ rollupManaLimit: Number(await this.rollup.getManaLimit()),
184
186
  };
185
187
 
186
188
  this.logger.info(
@@ -221,7 +223,7 @@ export class EpochsTestContext {
221
223
  },
222
224
  },
223
225
  {
224
- prefilledPublicData: this.context.prefilledPublicData ?? [],
226
+ genesis: this.context.genesis,
225
227
  dontStart: opts.dontStart,
226
228
  },
227
229
  ),
@@ -237,13 +239,21 @@ export class EpochsTestContext {
237
239
 
238
240
  public createValidatorNode(
239
241
  privateKeys: `0x${string}`[],
240
- opts: Partial<AztecNodeConfig> & { dontStartSequencer?: boolean } = {},
242
+ opts: Partial<AztecNodeConfig> & {
243
+ dontStartSequencer?: boolean;
244
+ slashingProtectionDb?: SlashingProtectionDatabase;
245
+ } = {},
241
246
  ) {
242
247
  this.logger.warn('Creating and syncing a validator node...');
243
248
  return this.createNode({ ...opts, disableValidator: false, validatorPrivateKeys: new SecretValue(privateKeys) });
244
249
  }
245
250
 
246
- private async createNode(opts: Partial<AztecNodeConfig> & { dontStartSequencer?: boolean } = {}) {
251
+ private async createNode(
252
+ opts: Partial<AztecNodeConfig> & {
253
+ dontStartSequencer?: boolean;
254
+ slashingProtectionDb?: SlashingProtectionDatabase;
255
+ } = {},
256
+ ) {
247
257
  const nodeIndex = this.nodes.length + 1;
248
258
  const actorPrefix = opts.disableValidator ? 'node' : 'validator';
249
259
  const { mockGossipSubNetwork } = this.context;
@@ -256,6 +266,7 @@ export class EpochsTestContext {
256
266
  ...resolvedConfig,
257
267
  dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
258
268
  validatorPrivateKeys: opts.validatorPrivateKeys ?? new SecretValue([]),
269
+ nodeId: resolvedConfig.nodeId || `${actorPrefix}-${nodeIndex}`,
259
270
  p2pEnabled,
260
271
  p2pIp,
261
272
  },
@@ -264,9 +275,10 @@ export class EpochsTestContext {
264
275
  p2pClientDeps: {
265
276
  p2pServiceFactory: mockGossipSubNetwork ? getMockPubSubP2PServiceFactory(mockGossipSubNetwork) : undefined,
266
277
  },
278
+ slashingProtectionDb: opts.slashingProtectionDb,
267
279
  },
268
280
  {
269
- prefilledPublicData: this.context.prefilledPublicData,
281
+ genesis: this.context.genesis,
270
282
  ...opts,
271
283
  },
272
284
  ),
@@ -1,7 +1,7 @@
1
1
  import type { AztecAddress } from '@aztec/aztec.js/addresses';
2
2
  import { type Logger, createLogger } from '@aztec/aztec.js/log';
3
3
  import type { AztecNode } from '@aztec/aztec.js/node';
4
- import { CheatCodes } from '@aztec/aztec/testing';
4
+ import { CheatCodes, getTokenAllowedSetupFunctions } from '@aztec/aztec/testing';
5
5
  import { createExtendedL1Client } from '@aztec/ethereum/client';
6
6
  import { RollupContract } from '@aztec/ethereum/contracts';
7
7
  import type { DeployAztecL1ContractsArgs } from '@aztec/ethereum/deploy-aztec-l1-contracts';
@@ -104,12 +104,15 @@ export class FeesTest {
104
104
 
105
105
  async setup() {
106
106
  this.logger.verbose('Setting up fresh context...');
107
+ // Token allowlist entries are test-only: FPC-based fee payment with custom tokens won't work on mainnet alpha.
108
+ const tokenAllowList = await getTokenAllowedSetupFunctions();
107
109
  this.context = await setup(0, {
108
110
  startProverNode: true,
109
111
  ...this.setupOptions,
110
112
  fundSponsoredFPC: true,
111
113
  skipAccountDeployment: true,
112
114
  l1ContractsArgs: { ...this.setupOptions },
115
+ txPublicSetupAllowListExtend: [...(this.setupOptions.txPublicSetupAllowListExtend ?? []), ...tokenAllowList],
113
116
  });
114
117
 
115
118
  this.rollupContract = RollupContract.getFromConfig(this.context.config);
@@ -190,7 +193,7 @@ export class FeesTest {
190
193
  this.wallet = this.context.wallet;
191
194
  this.aztecNode = this.context.aztecNodeService;
192
195
  this.aztecNodeAdmin = this.context.aztecNodeService;
193
- this.gasSettings = GasSettings.default({ maxFeesPerGas: (await this.aztecNode.getCurrentMinFees()).mul(2) });
196
+ this.gasSettings = GasSettings.fallback({ maxFeesPerGas: (await this.aztecNode.getCurrentMinFees()).mul(2) });
194
197
  this.cheatCodes = this.context.cheatCodes;
195
198
  this.accounts = deployedAccounts.map(a => a.address);
196
199
  this.accounts.forEach((a, i) => this.logger.verbose(`Account ${i} address: ${a}`));
@@ -58,6 +58,7 @@ export class P2PInactivityTest {
58
58
  basePort: BOOT_NODE_UDP_PORT,
59
59
  startProverNode: true,
60
60
  initialConfig: {
61
+ anvilSlotsInAnEpoch: 4,
61
62
  proverNodeConfig: { proverNodeEpochProvingDelayMs: AZTEC_SLOT_DURATION * 1000 },
62
63
  aztecTargetCommitteeSize: COMMITTEE_SIZE,
63
64
  aztecSlotDuration: AZTEC_SLOT_DURATION,
@@ -66,7 +67,6 @@ export class P2PInactivityTest {
66
67
  listenAddress: '127.0.0.1',
67
68
  minTxsPerBlock: 0,
68
69
  aztecEpochDuration: EPOCH_DURATION,
69
- validatorReexecute: false,
70
70
  sentinelEnabled: true,
71
71
  slashingQuorum: SLASHING_QUORUM,
72
72
  slashingRoundSizeInEpochs: SLASHING_ROUND_SIZE_IN_EPOCHS,
@@ -108,7 +108,7 @@ export class P2PInactivityTest {
108
108
  this.test.bootstrapNodeEnr,
109
109
  NUM_NODES - this.inactiveNodeCount - Number(this.keepInitialNode),
110
110
  BOOT_NODE_UDP_PORT,
111
- this.test.prefilledPublicData,
111
+ this.test.genesis,
112
112
  this.dataDir,
113
113
  undefined,
114
114
  Number(this.keepInitialNode),
@@ -122,7 +122,7 @@ export class P2PInactivityTest {
122
122
  this.test.bootstrapNodeEnr,
123
123
  this.inactiveNodeCount,
124
124
  BOOT_NODE_UDP_PORT,
125
- this.test.prefilledPublicData,
125
+ this.test.genesis,
126
126
  this.dataDir,
127
127
  undefined,
128
128
  NUM_NODES - this.inactiveNodeCount,
@@ -3,12 +3,7 @@ import type { AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
3
3
  import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
4
4
  import { Fr } from '@aztec/aztec.js/fields';
5
5
  import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
6
- import {
7
- type EmpireSlashingProposerContract,
8
- GSEContract,
9
- RollupContract,
10
- type TallySlashingProposerContract,
11
- } from '@aztec/ethereum/contracts';
6
+ import { GSEContract, RollupContract, type SlashingProposerContract } from '@aztec/ethereum/contracts';
12
7
  import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts';
13
8
  import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
14
9
  import { MultiAdderArtifact } from '@aztec/ethereum/l1-artifacts';
@@ -24,9 +19,9 @@ import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
24
19
  import type { BootstrapNode } from '@aztec/p2p/bootstrap';
25
20
  import { createBootstrapNodeFromPrivateKey, getBootstrapNodeEnr } from '@aztec/p2p/test-helpers';
26
21
  import { tryStop } from '@aztec/stdlib/interfaces/server';
27
- import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
28
22
  import { TopicType } from '@aztec/stdlib/p2p';
29
- import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
23
+ import { TxStatus } from '@aztec/stdlib/tx';
24
+ import type { GenesisData } from '@aztec/stdlib/world-state';
30
25
  import { ZkPassportProofParams } from '@aztec/stdlib/zkpassport';
31
26
  import { getGenesisValues } from '@aztec/world-state/testing';
32
27
 
@@ -59,7 +54,7 @@ export const WAIT_FOR_TX_TIMEOUT = l1ContractsConfig.aztecSlotDuration * 3;
59
54
  export const SHORTENED_BLOCK_TIME_CONFIG_NO_PRUNES = {
60
55
  aztecSlotDuration: 12,
61
56
  ethereumSlotDuration: 4,
62
- aztecProofSubmissionWindow: 640,
57
+ aztecProofSubmissionEpochs: 640,
63
58
  };
64
59
 
65
60
  export class P2PNetworkTest {
@@ -77,7 +72,7 @@ export class P2PNetworkTest {
77
72
  public validators: Operator[] = [];
78
73
 
79
74
  public deployedAccounts: InitialAccountData[] = [];
80
- public prefilledPublicData: PublicDataTreeLeaf[] = [];
75
+ public genesis: GenesisData | undefined;
81
76
 
82
77
  // The re-execution test needs a wallet and a spam contract
83
78
  public wallet?: TestWallet;
@@ -124,7 +119,7 @@ export class P2PNetworkTest {
124
119
  initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs,
125
120
  slashingRoundSizeInEpochs:
126
121
  initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
127
- slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally',
122
+ slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
128
123
  aztecTargetCommitteeSize: numberOfValidators,
129
124
  metricsPort: metricsPort,
130
125
  numberOfInitialFundedAccounts: 2,
@@ -137,7 +132,7 @@ export class P2PNetworkTest {
137
132
  aztecEpochDuration: initialValidatorConfig.aztecEpochDuration ?? l1ContractsConfig.aztecEpochDuration,
138
133
  slashingRoundSizeInEpochs:
139
134
  initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
140
- slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally',
135
+ slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
141
136
 
142
137
  ethereumSlotDuration: initialValidatorConfig.ethereumSlotDuration ?? l1ContractsConfig.ethereumSlotDuration,
143
138
  aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration,
@@ -305,10 +300,11 @@ export class P2PNetworkTest {
305
300
 
306
301
  async setupAccount() {
307
302
  this.logger.info('Setting up account');
308
- const { deployedAccounts } = await deployAccounts(
309
- 1,
310
- this.logger,
311
- )({
303
+ const { deployedAccounts } = await deployAccounts(1, this.logger, {
304
+ wait: {
305
+ waitForStatus: TxStatus.CHECKPOINTED,
306
+ },
307
+ })({
312
308
  wallet: this.context.wallet,
313
309
  initialFundedAccounts: this.context.initialFundedAccounts,
314
310
  });
@@ -360,7 +356,7 @@ export class P2PNetworkTest {
360
356
  ...this.setupOptions,
361
357
  fundSponsoredFPC: true,
362
358
  skipAccountDeployment: true,
363
- slasherFlavor: this.setupOptions.slasherFlavor ?? this.deployL1ContractsArgs.slasherFlavor ?? 'none',
359
+ slasherEnabled: this.setupOptions.slasherEnabled ?? this.deployL1ContractsArgs.slasherEnabled ?? false,
364
360
  aztecTargetCommitteeSize: 0,
365
361
  l1ContractsArgs: this.deployL1ContractsArgs,
366
362
  },
@@ -372,8 +368,13 @@ export class P2PNetworkTest {
372
368
  const sponsoredFPCAddress = await getSponsoredFPCAddress();
373
369
  const initialFundedAccounts = [...this.context.initialFundedAccounts.map(a => a.address), sponsoredFPCAddress];
374
370
 
375
- const { prefilledPublicData } = await getGenesisValues(initialFundedAccounts);
376
- this.prefilledPublicData = prefilledPublicData;
371
+ const { genesis } = await getGenesisValues(
372
+ initialFundedAccounts,
373
+ undefined,
374
+ undefined,
375
+ this.context.genesis!.genesisTimestamp,
376
+ );
377
+ this.genesis = genesis;
377
378
 
378
379
  const rollupContract = RollupContract.getFromL1ContractsValues(this.context.deployL1ContractsValues);
379
380
  this.monitor = new ChainMonitor(rollupContract, this.context.dateProvider).start();
@@ -468,8 +469,7 @@ export class P2PNetworkTest {
468
469
  async getContracts(): Promise<{
469
470
  rollup: RollupContract;
470
471
  slasherContract: GetContractReturnType<typeof SlasherAbi, ViemClient>;
471
- slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
472
- slashFactory: SlashFactoryContract;
472
+ slashingProposer: SlashingProposerContract | undefined;
473
473
  }> {
474
474
  if (!this.ctx.deployL1ContractsValues) {
475
475
  throw new Error('DeployAztecL1ContractsValues not set');
@@ -486,14 +486,9 @@ export class P2PNetworkTest {
486
486
  client: this.ctx.deployL1ContractsValues.l1Client,
487
487
  });
488
488
 
489
- // Get the actual slashing proposer from rollup (which handles both empire and tally)
489
+ // Get the actual slashing proposer from rollup
490
490
  const slashingProposer = await rollup.getSlashingProposer();
491
491
 
492
- const slashFactory = new SlashFactoryContract(
493
- this.ctx.deployL1ContractsValues.l1Client,
494
- getAddress(this.ctx.deployL1ContractsValues.l1ContractAddresses.slashFactoryAddress!.toString()),
495
- );
496
-
497
- return { rollup, slasherContract, slashingProposer, slashFactory };
492
+ return { rollup, slasherContract, slashingProposer };
498
493
  }
499
494
  }
@@ -91,7 +91,7 @@ export async function runReqrespTxTest(params: {
91
91
  t.bootstrapNodeEnr,
92
92
  NUM_VALIDATORS,
93
93
  BOOT_NODE_UDP_PORT,
94
- t.prefilledPublicData,
94
+ t.genesis,
95
95
  dataDir,
96
96
  shouldCollectMetrics(),
97
97
  );
@@ -149,6 +149,13 @@ export async function runReqrespTxTest(params: {
149
149
  const submittedTxs = await Promise.all(
150
150
  txBatches.map(async (batch, batchIndex) => {
151
151
  const proposerNode = nodes[proposerIndexes[batchIndex]];
152
+ for (const tx of batch) {
153
+ t.logger.info(`Tx ${tx.getTxHash().toString()} base64: ${tx.toBuffer().toString('base64')}`);
154
+ }
155
+ const txHashes = batch.map(tx => tx.getTxHash().toString());
156
+ t.logger.info(
157
+ `Sending batch ${batchIndex} to proposer ${getNodePort(proposerIndexes[batchIndex])}: ${txHashes.join(', ')}`,
158
+ );
152
159
  await Promise.all(
153
160
  batch.map(async tx => {
154
161
  try {
@@ -163,6 +170,12 @@ export async function runReqrespTxTest(params: {
163
170
  }),
164
171
  );
165
172
 
173
+ // Log pool state per node after sending
174
+ for (let i = 0; i < NUM_VALIDATORS; i++) {
175
+ const count = await nodes[i].getPendingTxCount();
176
+ t.logger.info(`Node ${getNodePort(i)} pool has ${count} pending txs`);
177
+ }
178
+
166
179
  t.logger.info('Waiting for all transactions to be mined');
167
180
  await Promise.all(
168
181
  submittedTxs.flatMap((batch, batchIndex) =>
@@ -178,8 +191,16 @@ export async function runReqrespTxTest(params: {
178
191
 
179
192
  // Assert that multiple blocks were built for at least one slot
180
193
  t.logger.info('Verifying multiple blocks for at least one checkpoint');
181
- const checkpoints = await nodes[0].getCheckpoints(CheckpointNumber(1), 50);
182
- expect(checkpoints.length).toBeGreaterThan(0);
194
+ // Wait for L1 checkpoint sync, which may lag behind P2P block propagation.
195
+ const checkpoints = await retryUntil(
196
+ async () => {
197
+ const cps = await nodes[0].getCheckpoints(CheckpointNumber(1), 50);
198
+ return cps.length > 0 && cps.some(cp => cp.checkpoint.blocks.length >= 2) ? cps : undefined;
199
+ },
200
+ 'waiting for multi-block checkpoint to sync from L1',
201
+ 30,
202
+ 1,
203
+ );
183
204
 
184
205
  let mbpsFound = false;
185
206
  let expectedBlockNumber = checkpoints[0].checkpoint.blocks[0].number;
@@ -7,11 +7,7 @@ import type { Logger } from '@aztec/aztec.js/log';
7
7
  import { TxHash } from '@aztec/aztec.js/tx';
8
8
  import type { RollupCheatCodes } from '@aztec/aztec/testing';
9
9
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
10
- import type {
11
- EmpireSlashingProposerContract,
12
- RollupContract,
13
- TallySlashingProposerContract,
14
- } from '@aztec/ethereum/contracts';
10
+ import type { RollupContract, SlashingProposerContract } from '@aztec/ethereum/contracts';
15
11
  import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
16
12
  import { timesAsync, unique } from '@aztec/foundation/collection';
17
13
  import { EthAddress } from '@aztec/foundation/eth-address';
@@ -22,7 +18,6 @@ import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.j
22
18
  import { getPXEConfig, getPXEConfig as getRpcConfig } from '@aztec/pxe/server';
23
19
  import { getRoundForOffense } from '@aztec/slasher';
24
20
  import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
25
- import type { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
26
21
 
27
22
  import { submitTxsTo } from '../shared/submit-transactions.js';
28
23
  import { TestWallet } from '../test-wallet/test_wallet.js';
@@ -99,7 +94,7 @@ export async function prepareTransactions(
99
94
  }
100
95
 
101
96
  export function awaitProposalExecution(
102
- slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract,
97
+ slashingProposer: SlashingProposerContract,
103
98
  timeoutSeconds: number,
104
99
  logger: Logger,
105
100
  ): Promise<bigint> {
@@ -109,24 +104,12 @@ export function awaitProposalExecution(
109
104
  reject(new Error(`Timeout waiting for proposal execution after ${timeoutSeconds}s`));
110
105
  }, timeoutSeconds * 1000);
111
106
 
112
- if (slashingProposer.type === 'empire') {
113
- const unwatch = slashingProposer.listenToPayloadSubmitted(args => {
114
- logger.warn(`Proposal ${args.payload} from round ${args.round} executed`);
115
- clearTimeout(timeout);
116
- unwatch();
117
- resolve(args.round);
118
- });
119
- } else if (slashingProposer.type === 'tally') {
120
- const unwatch = slashingProposer.listenToRoundExecuted(args => {
121
- logger.warn(`Slash from round ${args.round} executed`);
122
- clearTimeout(timeout);
123
- unwatch();
124
- resolve(args.round);
125
- });
126
- } else {
107
+ const unwatch = slashingProposer.listenToRoundExecuted(args => {
108
+ logger.warn(`Slash from round ${args.round} executed`);
127
109
  clearTimeout(timeout);
128
- reject(new Error(`Unknown slashing proposer type: ${(slashingProposer as any).type}`));
129
- }
110
+ unwatch();
111
+ resolve(args.round);
112
+ });
130
113
  });
131
114
  }
132
115
 
@@ -152,11 +135,14 @@ export async function awaitCommitteeExists({
152
135
  }
153
136
 
154
137
  /**
155
- * Advance epochs until we find one where the target proposer is selected for at least one slot.
156
- * With N validators and M slots per epoch, a specific proposer may not be selected in any given epoch.
157
- * For example, with 4 validators and 2 slots/epoch, there is about a 44% chance per epoch.
138
+ * Advance epochs until we find one where the target proposer is selected for at least one slot,
139
+ * then stop one epoch before it. This leaves time for the caller to start sequencers before
140
+ * warping to the target epoch, avoiding the race where the target epoch passes before sequencers
141
+ * are ready.
142
+ *
143
+ * Returns the target epoch number so the caller can warp to it after starting sequencers.
158
144
  */
159
- export async function awaitEpochWithProposer({
145
+ export async function advanceToEpochBeforeProposer({
160
146
  epochCache,
161
147
  cheatCodes,
162
148
  targetProposer,
@@ -168,25 +154,32 @@ export async function awaitEpochWithProposer({
168
154
  targetProposer: EthAddress;
169
155
  logger: Logger;
170
156
  maxAttempts?: number;
171
- }): Promise<void> {
157
+ }): Promise<{ targetEpoch: EpochNumber }> {
172
158
  const { epochDuration } = await cheatCodes.getConfig();
173
159
 
174
160
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
175
161
  const currentEpoch = await cheatCodes.getEpoch();
176
- const startSlot = Number(currentEpoch) * Number(epochDuration);
162
+ // Check the NEXT epoch's slots so we stay one epoch before the target,
163
+ // giving the caller time to start sequencers before the target epoch arrives.
164
+ const nextEpoch = Number(currentEpoch) + 1;
165
+ const startSlot = nextEpoch * Number(epochDuration);
177
166
  const endSlot = startSlot + Number(epochDuration);
178
167
 
179
- logger.info(`Checking epoch ${currentEpoch} (slots ${startSlot}-${endSlot - 1}) for proposer ${targetProposer}`);
168
+ logger.info(
169
+ `Checking next epoch ${nextEpoch} (slots ${startSlot}-${endSlot - 1}) for proposer ${targetProposer} (current epoch: ${currentEpoch})`,
170
+ );
180
171
 
181
172
  for (let s = startSlot; s < endSlot; s++) {
182
173
  const proposer = await epochCache.getProposerAttesterAddressInSlot(SlotNumber(s));
183
174
  if (proposer && proposer.equals(targetProposer)) {
184
- logger.warn(`Found target proposer ${targetProposer} in slot ${s} of epoch ${currentEpoch}`);
185
- return;
175
+ logger.warn(
176
+ `Found target proposer ${targetProposer} in slot ${s} of epoch ${nextEpoch}. Staying at epoch ${currentEpoch} to allow sequencer startup.`,
177
+ );
178
+ return { targetEpoch: EpochNumber(nextEpoch) };
186
179
  }
187
180
  }
188
181
 
189
- logger.info(`Target proposer not found in epoch ${currentEpoch}, advancing to next epoch`);
182
+ logger.info(`Target proposer not found in epoch ${nextEpoch}, advancing to next epoch`);
190
183
  await cheatCodes.advanceToNextEpoch();
191
184
  }
192
185
 
@@ -235,7 +228,6 @@ export async function awaitCommitteeKicked({
235
228
  rollup,
236
229
  cheatCodes,
237
230
  committee,
238
- slashFactory,
239
231
  slashingProposer,
240
232
  slashingRoundSize,
241
233
  aztecSlotDuration,
@@ -246,8 +238,7 @@ export async function awaitCommitteeKicked({
246
238
  rollup: RollupContract;
247
239
  cheatCodes: RollupCheatCodes;
248
240
  committee: readonly `0x${string}`[];
249
- slashFactory: SlashFactoryContract;
250
- slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
241
+ slashingProposer: SlashingProposerContract | undefined;
251
242
  slashingRoundSize: number;
252
243
  aztecSlotDuration: number;
253
244
  aztecEpochDuration: number;
@@ -260,36 +251,14 @@ export async function awaitCommitteeKicked({
260
251
 
261
252
  await cheatCodes.debugRollup();
262
253
 
263
- if (slashingProposer.type === 'empire') {
264
- // Await for the slash payload to be created if empire (no payload is created on tally until execution time)
265
- const targetEpoch = EpochNumber((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochsForValidatorSet()) + 1);
266
- logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
267
- await cheatCodes.advanceToEpoch(targetEpoch);
268
-
269
- const slashPayloadEvents = await retryUntil(
270
- async () => {
271
- const events = await slashFactory.getSlashPayloadCreatedEvents();
272
- return events.length > 0 ? events : undefined;
273
- },
274
- 'slash payload created',
275
- 120,
276
- 1,
277
- );
278
- expect(slashPayloadEvents.length).toBe(1);
279
- // The uniqueness check is needed since a validator may be slashed more than once on the same round (eg because they let two epochs be pruned)
280
- expect(unique(slashPayloadEvents[0].slashes.map(slash => slash.validator.toString()))).toHaveLength(
281
- committee.length,
282
- );
283
- } else {
284
- // Use the slash offset to ensure we are in the right epoch for tally
285
- const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
286
- const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
287
- const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
288
- const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
289
- const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
290
- logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
291
- await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
292
- }
254
+ // Use the slash offset to ensure we are in the right epoch for tally
255
+ const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
256
+ const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
257
+ const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
258
+ const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
259
+ const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
260
+ logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
261
+ await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
293
262
 
294
263
  const attestersPre = await rollup.getAttesters();
295
264
  expect(attestersPre.length).toBe(committee.length);