@aztec/end-to-end 0.0.1-commit.f504929 → 0.0.1-commit.f650c0a5c

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 (86) 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_epochs/epochs_test.d.ts +3 -1
  6. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  7. package/dest/e2e_epochs/epochs_test.js +8 -5
  8. package/dest/e2e_fees/fees_test.d.ts +1 -1
  9. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  10. package/dest/e2e_fees/fees_test.js +9 -2
  11. package/dest/e2e_p2p/inactivity_slash_test.js +3 -3
  12. package/dest/e2e_p2p/p2p_network.d.ts +6 -8
  13. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  14. package/dest/e2e_p2p/p2p_network.js +9 -13
  15. package/dest/e2e_p2p/reqresp/utils.d.ts +1 -1
  16. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  17. package/dest/e2e_p2p/reqresp/utils.js +16 -3
  18. package/dest/e2e_p2p/shared.d.ts +16 -12
  19. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  20. package/dest/e2e_p2p/shared.js +33 -51
  21. package/dest/fixtures/authwit_proxy.d.ts +1 -1
  22. package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
  23. package/dest/fixtures/authwit_proxy.js +4 -0
  24. package/dest/fixtures/e2e_prover_test.d.ts +4 -3
  25. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  26. package/dest/fixtures/e2e_prover_test.js +7 -12
  27. package/dest/fixtures/get_bb_config.d.ts +1 -1
  28. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  29. package/dest/fixtures/get_bb_config.js +5 -5
  30. package/dest/fixtures/setup.d.ts +10 -4
  31. package/dest/fixtures/setup.d.ts.map +1 -1
  32. package/dest/fixtures/setup.js +20 -15
  33. package/dest/fixtures/setup_p2p_test.d.ts +6 -6
  34. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  35. package/dest/fixtures/setup_p2p_test.js +8 -8
  36. package/dest/fixtures/token_utils.d.ts +1 -1
  37. package/dest/fixtures/token_utils.d.ts.map +1 -1
  38. package/dest/fixtures/token_utils.js +2 -5
  39. package/dest/legacy-jest-resolver.d.cts +3 -0
  40. package/dest/legacy-jest-resolver.d.cts.map +1 -0
  41. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  42. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  43. package/dest/shared/uniswap_l1_l2.js +9 -12
  44. package/dest/simulators/lending_simulator.d.ts +1 -1
  45. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  46. package/dest/simulators/lending_simulator.js +2 -2
  47. package/dest/simulators/token_simulator.js +1 -1
  48. package/dest/spartan/setup_test_wallets.d.ts +4 -2
  49. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  50. package/dest/spartan/setup_test_wallets.js +70 -40
  51. package/dest/spartan/utils/config.d.ts +4 -1
  52. package/dest/spartan/utils/config.d.ts.map +1 -1
  53. package/dest/spartan/utils/config.js +1 -0
  54. package/dest/spartan/utils/index.d.ts +2 -1
  55. package/dest/spartan/utils/index.d.ts.map +1 -1
  56. package/dest/spartan/utils/index.js +2 -0
  57. package/dest/spartan/utils/pod_logs.d.ts +25 -0
  58. package/dest/spartan/utils/pod_logs.d.ts.map +1 -0
  59. package/dest/spartan/utils/pod_logs.js +74 -0
  60. package/dest/test-wallet/test_wallet.d.ts +15 -23
  61. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  62. package/dest/test-wallet/test_wallet.js +72 -64
  63. package/dest/test-wallet/worker_wallet_schema.d.ts +2 -2
  64. package/package.json +40 -40
  65. package/src/bench/client_flows/client_flows_benchmark.ts +35 -23
  66. package/src/e2e_epochs/epochs_test.ts +17 -5
  67. package/src/e2e_fees/fees_test.ts +5 -2
  68. package/src/e2e_p2p/inactivity_slash_test.ts +3 -3
  69. package/src/e2e_p2p/p2p_network.ts +17 -24
  70. package/src/e2e_p2p/reqresp/utils.ts +24 -3
  71. package/src/e2e_p2p/shared.ts +36 -67
  72. package/src/fixtures/authwit_proxy.ts +4 -0
  73. package/src/fixtures/e2e_prover_test.ts +12 -17
  74. package/src/fixtures/get_bb_config.ts +7 -6
  75. package/src/fixtures/setup.ts +29 -21
  76. package/src/fixtures/setup_p2p_test.ts +9 -9
  77. package/src/fixtures/token_utils.ts +1 -4
  78. package/src/legacy-jest-resolver.cjs +135 -0
  79. package/src/shared/uniswap_l1_l2.ts +29 -24
  80. package/src/simulators/lending_simulator.ts +4 -2
  81. package/src/simulators/token_simulator.ts +1 -1
  82. package/src/spartan/setup_test_wallets.ts +97 -35
  83. package/src/spartan/utils/config.ts +1 -0
  84. package/src/spartan/utils/index.ts +3 -0
  85. package/src/spartan/utils/pod_logs.ts +99 -0
  86. package/src/test-wallet/test_wallet.ts +99 -79
@@ -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,8 @@ 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 type { GenesisData } from '@aztec/stdlib/world-state';
30
24
  import { ZkPassportProofParams } from '@aztec/stdlib/zkpassport';
31
25
  import { getGenesisValues } from '@aztec/world-state/testing';
32
26
 
@@ -59,7 +53,7 @@ export const WAIT_FOR_TX_TIMEOUT = l1ContractsConfig.aztecSlotDuration * 3;
59
53
  export const SHORTENED_BLOCK_TIME_CONFIG_NO_PRUNES = {
60
54
  aztecSlotDuration: 12,
61
55
  ethereumSlotDuration: 4,
62
- aztecProofSubmissionWindow: 640,
56
+ aztecProofSubmissionEpochs: 640,
63
57
  };
64
58
 
65
59
  export class P2PNetworkTest {
@@ -77,7 +71,7 @@ export class P2PNetworkTest {
77
71
  public validators: Operator[] = [];
78
72
 
79
73
  public deployedAccounts: InitialAccountData[] = [];
80
- public prefilledPublicData: PublicDataTreeLeaf[] = [];
74
+ public genesis: GenesisData | undefined;
81
75
 
82
76
  // The re-execution test needs a wallet and a spam contract
83
77
  public wallet?: TestWallet;
@@ -124,7 +118,7 @@ export class P2PNetworkTest {
124
118
  initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs,
125
119
  slashingRoundSizeInEpochs:
126
120
  initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
127
- slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally',
121
+ slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
128
122
  aztecTargetCommitteeSize: numberOfValidators,
129
123
  metricsPort: metricsPort,
130
124
  numberOfInitialFundedAccounts: 2,
@@ -137,7 +131,7 @@ export class P2PNetworkTest {
137
131
  aztecEpochDuration: initialValidatorConfig.aztecEpochDuration ?? l1ContractsConfig.aztecEpochDuration,
138
132
  slashingRoundSizeInEpochs:
139
133
  initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
140
- slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally',
134
+ slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
141
135
 
142
136
  ethereumSlotDuration: initialValidatorConfig.ethereumSlotDuration ?? l1ContractsConfig.ethereumSlotDuration,
143
137
  aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration,
@@ -360,7 +354,7 @@ export class P2PNetworkTest {
360
354
  ...this.setupOptions,
361
355
  fundSponsoredFPC: true,
362
356
  skipAccountDeployment: true,
363
- slasherFlavor: this.setupOptions.slasherFlavor ?? this.deployL1ContractsArgs.slasherFlavor ?? 'none',
357
+ slasherEnabled: this.setupOptions.slasherEnabled ?? this.deployL1ContractsArgs.slasherEnabled ?? false,
364
358
  aztecTargetCommitteeSize: 0,
365
359
  l1ContractsArgs: this.deployL1ContractsArgs,
366
360
  },
@@ -372,8 +366,13 @@ export class P2PNetworkTest {
372
366
  const sponsoredFPCAddress = await getSponsoredFPCAddress();
373
367
  const initialFundedAccounts = [...this.context.initialFundedAccounts.map(a => a.address), sponsoredFPCAddress];
374
368
 
375
- const { prefilledPublicData } = await getGenesisValues(initialFundedAccounts);
376
- this.prefilledPublicData = prefilledPublicData;
369
+ const { genesis } = await getGenesisValues(
370
+ initialFundedAccounts,
371
+ undefined,
372
+ undefined,
373
+ this.context.genesis!.genesisTimestamp,
374
+ );
375
+ this.genesis = genesis;
377
376
 
378
377
  const rollupContract = RollupContract.getFromL1ContractsValues(this.context.deployL1ContractsValues);
379
378
  this.monitor = new ChainMonitor(rollupContract, this.context.dateProvider).start();
@@ -468,8 +467,7 @@ export class P2PNetworkTest {
468
467
  async getContracts(): Promise<{
469
468
  rollup: RollupContract;
470
469
  slasherContract: GetContractReturnType<typeof SlasherAbi, ViemClient>;
471
- slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
472
- slashFactory: SlashFactoryContract;
470
+ slashingProposer: SlashingProposerContract | undefined;
473
471
  }> {
474
472
  if (!this.ctx.deployL1ContractsValues) {
475
473
  throw new Error('DeployAztecL1ContractsValues not set');
@@ -486,14 +484,9 @@ export class P2PNetworkTest {
486
484
  client: this.ctx.deployL1ContractsValues.l1Client,
487
485
  });
488
486
 
489
- // Get the actual slashing proposer from rollup (which handles both empire and tally)
487
+ // Get the actual slashing proposer from rollup
490
488
  const slashingProposer = await rollup.getSlashingProposer();
491
489
 
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 };
490
+ return { rollup, slasherContract, slashingProposer };
498
491
  }
499
492
  }
@@ -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);
@@ -17,6 +17,10 @@ async function buildProxyCall(proxy: GenericProxyContract, action: ContractFunct
17
17
  return proxy.methods.forward_private_3(call.to, call.selector, call.args);
18
18
  } else if (argCount === 4) {
19
19
  return proxy.methods.forward_private_4(call.to, call.selector, call.args);
20
+ } else if (argCount === 5) {
21
+ return proxy.methods.forward_private_5(call.to, call.selector, call.args);
22
+ } else if (argCount === 6) {
23
+ return proxy.methods.forward_private_6(call.to, call.selector, call.args);
20
24
  }
21
25
  throw new Error(`No forward_private_${argCount} method on proxy`);
22
26
  }
@@ -4,12 +4,7 @@ import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
4
4
  import { type Logger, createLogger } from '@aztec/aztec.js/log';
5
5
  import type { AztecNode } from '@aztec/aztec.js/node';
6
6
  import { CheatCodes } from '@aztec/aztec/testing';
7
- import {
8
- BBCircuitVerifier,
9
- type ClientProtocolCircuitVerifier,
10
- QueuedIVCVerifier,
11
- TestCircuitVerifier,
12
- } from '@aztec/bb-prover';
7
+ import type { ClientProtocolCircuitVerifier } from '@aztec/bb-prover';
13
8
  import { BackendType, Barretenberg } from '@aztec/bb.js';
14
9
  import type { DeployAztecL1ContractsReturnType } from '@aztec/ethereum/deploy-aztec-l1-contracts';
15
10
  import { Buffer32 } from '@aztec/foundation/buffer';
@@ -68,7 +63,10 @@ export class FullProverTest {
68
63
  private provenComponents: ProvenSetup[] = [];
69
64
  private bbConfigCleanup?: () => Promise<void>;
70
65
  private acvmConfigCleanup?: () => Promise<void>;
71
- circuitProofVerifier?: ClientProtocolCircuitVerifier;
66
+ /** Returns the proof verifier from the prover node (for test assertions). */
67
+ get circuitProofVerifier(): ClientProtocolCircuitVerifier | undefined {
68
+ return this.proverAztecNode?.getProofVerifier();
69
+ }
72
70
  provenAsset!: TokenContract;
73
71
  context!: EndToEndContext;
74
72
  private proverAztecNode!: AztecNodeService;
@@ -106,15 +104,13 @@ export class FullProverTest {
106
104
  await publicDeployAccounts(this.wallet, this.accounts.slice(0, 2));
107
105
 
108
106
  this.logger.info('Applying base setup: deploying token contract');
109
- const {
110
- receipt: { contract: asset, instance },
111
- } = await TokenContract.deploy(
107
+ const { contract: asset, instance } = await TokenContract.deploy(
112
108
  this.wallet,
113
109
  this.accounts[0],
114
110
  FullProverTest.TOKEN_NAME,
115
111
  FullProverTest.TOKEN_SYMBOL,
116
112
  FullProverTest.TOKEN_DECIMALS,
117
- ).send({ from: this.accounts[0], wait: { returnReceipt: true } });
113
+ ).send({ from: this.accounts[0] });
118
114
  this.logger.verbose(`Token deployed to ${asset.address}`);
119
115
 
120
116
  this.fakeProofsAsset = asset;
@@ -170,9 +166,6 @@ export class FullProverTest {
170
166
 
171
167
  await Barretenberg.initSingleton({ backend: BackendType.NativeUnixSocket });
172
168
 
173
- const verifier = await BBCircuitVerifier.new(bbConfig);
174
- this.circuitProofVerifier = new QueuedIVCVerifier(bbConfig, verifier);
175
-
176
169
  this.logger.debug(`Configuring the node for real proofs...`);
177
170
  await this.aztecNodeAdmin.setConfig({
178
171
  realProofs: true,
@@ -180,7 +173,6 @@ export class FullProverTest {
180
173
  });
181
174
  } else {
182
175
  this.logger.debug(`Configuring the node min txs per block ${this.minNumberOfTxsPerBlock}...`);
183
- this.circuitProofVerifier = new TestCircuitVerifier();
184
176
  await this.aztecNodeAdmin.setConfig({
185
177
  minTxsPerBlock: this.minNumberOfTxsPerBlock,
186
178
  });
@@ -231,8 +223,11 @@ export class FullProverTest {
231
223
 
232
224
  this.logger.verbose('Starting prover node');
233
225
  const sponsoredFPCAddress = await getSponsoredFPCAddress();
234
- const { prefilledPublicData } = await getGenesisValues(
226
+ const { genesis } = await getGenesisValues(
235
227
  this.context.initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress),
228
+ undefined,
229
+ undefined,
230
+ this.context.genesis!.genesisTimestamp,
236
231
  );
237
232
 
238
233
  const proverNodeConfig: Parameters<typeof AztecNodeService.createAndSync>[0] = {
@@ -260,7 +255,7 @@ export class FullProverTest {
260
255
  this.proverAztecNode = await AztecNodeService.createAndSync(
261
256
  proverNodeConfig,
262
257
  { dateProvider: this.context.dateProvider, p2pClientDeps: { rpcTxProviders: [this.aztecNode] } },
263
- { prefilledPublicData },
258
+ { genesis },
264
259
  );
265
260
  this.logger.warn(`Proofs are now enabled`, { realProofs: this.realProofs });
266
261
  return this;
@@ -13,8 +13,10 @@ const {
13
13
  BB_SKIP_CLEANUP = '',
14
14
  TEMP_DIR = tmpdir(),
15
15
  BB_WORKING_DIRECTORY = '',
16
- BB_NUM_IVC_VERIFIERS = '1',
16
+ BB_NUM_IVC_VERIFIERS = '8',
17
17
  BB_IVC_CONCURRENCY = '1',
18
+ BB_CHONK_VERIFY_MAX_BATCH = '16',
19
+ BB_CHONK_VERIFY_BATCH_CONCURRENCY = '6',
18
20
  } = process.env;
19
21
 
20
22
  export const getBBConfig = async (
@@ -41,16 +43,15 @@ export const getBBConfig = async (
41
43
  const bbSkipCleanup = ['1', 'true'].includes(BB_SKIP_CLEANUP);
42
44
  const cleanup = bbSkipCleanup ? () => Promise.resolve() : () => tryRmDir(directoryToCleanup);
43
45
 
44
- const numIvcVerifiers = Number(BB_NUM_IVC_VERIFIERS);
45
- const ivcConcurrency = Number(BB_IVC_CONCURRENCY);
46
-
47
46
  return {
48
47
  bbSkipCleanup,
49
48
  bbBinaryPath,
50
49
  bbWorkingDirectory,
51
50
  cleanup,
52
- numConcurrentIVCVerifiers: numIvcVerifiers,
53
- bbIVCConcurrency: ivcConcurrency,
51
+ numConcurrentIVCVerifiers: Number(BB_NUM_IVC_VERIFIERS),
52
+ bbIVCConcurrency: Number(BB_IVC_CONCURRENCY),
53
+ bbChonkVerifyMaxBatch: Number(BB_CHONK_VERIFY_MAX_BATCH),
54
+ bbChonkVerifyConcurrency: Number(BB_CHONK_VERIFY_BATCH_CONCURRENCY),
54
55
  };
55
56
  } catch (err) {
56
57
  logger.error(`Native BB not available, error: ${err}`);
@@ -1,6 +1,7 @@
1
1
  import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr';
2
2
  import { type InitialAccountData, generateSchnorrAccounts } from '@aztec/accounts/testing';
3
3
  import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node';
4
+ import { NO_FROM } from '@aztec/aztec.js/account';
4
5
  import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
5
6
  import {
6
7
  BatchCall,
@@ -51,6 +52,7 @@ import { type ContractInstanceWithAddress, getContractInstanceFromInstantiationP
51
52
  import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
52
53
  import { tryStop } from '@aztec/stdlib/interfaces/server';
53
54
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
55
+ import type { GenesisData } from '@aztec/stdlib/world-state';
54
56
  import {
55
57
  type TelemetryClient,
56
58
  type TelemetryClientConfig,
@@ -185,6 +187,11 @@ export type SetupOptions = {
185
187
  anvilAccounts?: number;
186
188
  /** Port to start anvil (defaults to 8545) */
187
189
  anvilPort?: number;
190
+ /**
191
+ * Number of slots per epoch for Anvil's finality simulation.
192
+ * Anvil reports `finalized = latest - slotsInAnEpoch * 2`.
193
+ */
194
+ anvilSlotsInAnEpoch?: number;
188
195
  /** Key to use for publishing L1 contracts */
189
196
  l1PublisherKey?: SecretValue<`0x${string}`>;
190
197
  /** ZkPassport configuration (domain, scope, mock verifier) */
@@ -243,8 +250,8 @@ export type EndToEndContext = {
243
250
  sequencerDelayer: Delayer | undefined;
244
251
  /** Delayer for prover node L1 txs (only when enableDelayer and startProverNode are true). */
245
252
  proverDelayer: Delayer | undefined;
246
- /** Prefilled public data used for setting up nodes. */
247
- prefilledPublicData: PublicDataTreeLeaf[] | undefined;
253
+ /** Genesis data used for setting up nodes. */
254
+ genesis: GenesisData | undefined;
248
255
  /** ACVM config (only set if running locally). */
249
256
  acvmConfig: Awaited<ReturnType<typeof getACVMConfig>>;
250
257
  /** BB config (only set if running locally). */
@@ -270,7 +277,7 @@ export async function setup(
270
277
  let anvil: Anvil | undefined;
271
278
  try {
272
279
  opts.aztecTargetCommitteeSize ??= 0;
273
- opts.slasherFlavor ??= 'none';
280
+ opts.slasherEnabled ??= false;
274
281
 
275
282
  const config: AztecNodeConfig & SetupOptions = { ...getConfigEnvVars(), ...opts };
276
283
  // use initialValidators for the node config
@@ -297,6 +304,8 @@ export async function setup(
297
304
  config.dataDirectory = directoryToCleanup;
298
305
  }
299
306
 
307
+ const dateProvider = new TestDateProvider();
308
+
300
309
  if (!config.l1RpcUrls?.length) {
301
310
  if (!isAnvilTestChain(chain.id)) {
302
311
  throw new Error(`No ETHEREUM_HOSTS set but non anvil chain requested`);
@@ -305,6 +314,8 @@ export async function setup(
305
314
  l1BlockTime: opts.ethereumSlotDuration,
306
315
  accounts: opts.anvilAccounts,
307
316
  port: opts.anvilPort ?? (process.env.ANVIL_PORT ? parseInt(process.env.ANVIL_PORT) : undefined),
317
+ slotsInAnEpoch: opts.anvilSlotsInAnEpoch,
318
+ dateProvider,
308
319
  });
309
320
  anvil = res.anvil;
310
321
  config.l1RpcUrls = [res.rpcUrl];
@@ -316,8 +327,6 @@ export async function setup(
316
327
  logger.info(`Logging metrics to ${filename}`);
317
328
  setupMetricsLogger(filename);
318
329
  }
319
-
320
- const dateProvider = new TestDateProvider();
321
330
  const ethCheatCodes = new EthCheatCodesWithState(config.l1RpcUrls, dateProvider);
322
331
 
323
332
  if (opts.stateLoad) {
@@ -367,10 +376,12 @@ export async function setup(
367
376
  addressesToFund.push(sponsoredFPCAddress);
368
377
  }
369
378
 
370
- const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(
379
+ const genesisTimestamp = BigInt(Math.floor(Date.now() / 1000));
380
+ const { genesisArchiveRoot, genesis, fundingNeeded } = await getGenesisValues(
371
381
  addressesToFund,
372
382
  opts.initialAccountFeeJuice,
373
383
  opts.genesisPublicData,
384
+ genesisTimestamp,
374
385
  );
375
386
 
376
387
  const wasAutomining = await ethCheatCodes.isAutoMining();
@@ -413,11 +424,12 @@ export async function setup(
413
424
  await ethCheatCodes.setIntervalMining(config.ethereumSlotDuration);
414
425
  }
415
426
 
416
- // Always sync dateProvider to L1 time after deploying L1 contracts, regardless of mining mode.
417
- // In compose mode, L1 time may have drifted ahead of system time due to the local-network watcher
418
- // warping time forward on each filled slot. Without this sync, the sequencer computes the wrong
419
- // slot from its dateProvider and cannot propose blocks.
420
- dateProvider.setTime((await ethCheatCodes.timestamp()) * 1000);
427
+ // In compose mode (no local anvil), sync dateProvider to L1 time since it may have drifted
428
+ // ahead of system time due to the local-network watcher warping time forward on each filled slot.
429
+ // When running with a local anvil, the dateProvider is kept in sync via the stdout listener.
430
+ if (!anvil) {
431
+ dateProvider.setTime((await ethCheatCodes.lastBlockTimestamp()) * 1000);
432
+ }
421
433
 
422
434
  if (opts.l2StartTime) {
423
435
  await ethCheatCodes.warp(opts.l2StartTime, { resetBlockInterval: true });
@@ -487,11 +499,7 @@ export async function setup(
487
499
  }
488
500
 
489
501
  const aztecNodeService = await withLoggerBindings({ actor: 'node-0' }, () =>
490
- AztecNodeService.createAndSync(
491
- config,
492
- { dateProvider, telemetry: telemetryClient, p2pClientDeps },
493
- { prefilledPublicData },
494
- ),
502
+ AztecNodeService.createAndSync(config, { dateProvider, telemetry: telemetryClient, p2pClientDeps }, { genesis }),
495
503
  );
496
504
  const sequencerClient = aztecNodeService.getSequencer();
497
505
 
@@ -515,7 +523,7 @@ export async function setup(
515
523
  dataDirectory: proverNodeDataDirectory,
516
524
  },
517
525
  { dateProvider, p2pClientDeps, telemetry: telemetryClient },
518
- { prefilledPublicData },
526
+ { genesis },
519
527
  ));
520
528
  }
521
529
 
@@ -620,7 +628,7 @@ export async function setup(
620
628
  initialFundedAccounts,
621
629
  logger,
622
630
  mockGossipSubNetwork,
623
- prefilledPublicData,
631
+ genesis,
624
632
  proverNode,
625
633
  sequencerDelayer,
626
634
  proverDelayer,
@@ -720,7 +728,7 @@ export function createAndSyncProverNode(
720
728
  dateProvider: DateProvider;
721
729
  p2pClientDeps?: P2PClientDeps;
722
730
  },
723
- options: { prefilledPublicData: PublicDataTreeLeaf[]; dontStart?: boolean },
731
+ options: { genesis?: GenesisData; dontStart?: boolean },
724
732
  ): Promise<{ proverNode: AztecNodeService }> {
725
733
  return withLoggerBindings({ actor: 'prover-0' }, async () => {
726
734
  const proverNode = await AztecNodeService.createAndSync(
@@ -733,7 +741,7 @@ export function createAndSyncProverNode(
733
741
  proverPublisherPrivateKeys: [new SecretValue(proverNodePrivateKey)],
734
742
  },
735
743
  deps,
736
- { ...options, dontStartProverNode: options.dontStart },
744
+ { genesis: options.genesis, dontStartProverNode: options.dontStart },
737
745
  );
738
746
 
739
747
  if (!proverNode.getProverNode()) {
@@ -841,7 +849,7 @@ export const deployAccounts =
841
849
  );
842
850
  const deployMethod = await accountManager.getDeployMethod();
843
851
  await deployMethod.send({
844
- from: AztecAddress.ZERO,
852
+ from: NO_FROM,
845
853
  skipClassPublication: i !== 0, // Publish the contract class at most once.
846
854
  });
847
855
  }