@aztec/end-to-end 0.0.1-commit.7cf39cb55 → 0.0.1-commit.7ffbba4

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 (142) hide show
  1. package/dest/bench/client_flows/client_flows_benchmark.d.ts +1 -1
  2. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  3. package/dest/bench/client_flows/client_flows_benchmark.js +16 -8
  4. package/dest/bench/utils.d.ts +1 -1
  5. package/dest/bench/utils.d.ts.map +1 -1
  6. package/dest/bench/utils.js +6 -3
  7. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +2 -2
  8. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  9. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +16 -16
  10. package/dest/e2e_epochs/epochs_test.d.ts +9 -7
  11. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  12. package/dest/e2e_epochs/epochs_test.js +53 -34
  13. package/dest/e2e_fees/fees_test.d.ts +1 -1
  14. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  15. package/dest/e2e_fees/fees_test.js +13 -6
  16. package/dest/e2e_nested_contract/nested_contract_test.d.ts +1 -1
  17. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  18. package/dest/e2e_nested_contract/nested_contract_test.js +4 -6
  19. package/dest/e2e_p2p/p2p_network.d.ts +4 -3
  20. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  21. package/dest/e2e_p2p/p2p_network.js +24 -7
  22. package/dest/e2e_p2p/reqresp/utils.d.ts +3 -3
  23. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  24. package/dest/e2e_p2p/reqresp/utils.js +32 -8
  25. package/dest/e2e_p2p/shared.d.ts +15 -1
  26. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  27. package/dest/e2e_p2p/shared.js +25 -2
  28. package/dest/e2e_token_contract/token_contract_test.d.ts +2 -2
  29. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  30. package/dest/e2e_token_contract/token_contract_test.js +13 -13
  31. package/dest/fixtures/authwit_proxy.d.ts +15 -0
  32. package/dest/fixtures/authwit_proxy.d.ts.map +1 -0
  33. package/dest/fixtures/authwit_proxy.js +30 -0
  34. package/dest/fixtures/e2e_prover_test.d.ts +3 -3
  35. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  36. package/dest/fixtures/e2e_prover_test.js +33 -40
  37. package/dest/fixtures/elu_monitor.d.ts +21 -0
  38. package/dest/fixtures/elu_monitor.d.ts.map +1 -0
  39. package/dest/fixtures/elu_monitor.js +102 -0
  40. package/dest/fixtures/fixtures.d.ts +5 -1
  41. package/dest/fixtures/fixtures.d.ts.map +1 -1
  42. package/dest/fixtures/fixtures.js +6 -0
  43. package/dest/fixtures/setup.d.ts +25 -9
  44. package/dest/fixtures/setup.d.ts.map +1 -1
  45. package/dest/fixtures/setup.js +49 -80
  46. package/dest/fixtures/setup_p2p_test.d.ts +6 -3
  47. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  48. package/dest/fixtures/setup_p2p_test.js +12 -9
  49. package/dest/fixtures/token_utils.d.ts +2 -2
  50. package/dest/fixtures/token_utils.d.ts.map +1 -1
  51. package/dest/fixtures/token_utils.js +5 -4
  52. package/dest/shared/cross_chain_test_harness.d.ts +1 -1
  53. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  54. package/dest/shared/cross_chain_test_harness.js +13 -13
  55. package/dest/shared/gas_portal_test_harness.js +2 -2
  56. package/dest/shared/index.d.ts +2 -1
  57. package/dest/shared/index.d.ts.map +1 -1
  58. package/dest/shared/index.js +1 -0
  59. package/dest/shared/jest_setup.js +41 -1
  60. package/dest/shared/mock_state_view.d.ts +86 -0
  61. package/dest/shared/mock_state_view.d.ts.map +1 -0
  62. package/dest/shared/mock_state_view.js +186 -0
  63. package/dest/shared/submit-transactions.js +1 -1
  64. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  65. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  66. package/dest/shared/uniswap_l1_l2.js +5 -5
  67. package/dest/simulators/lending_simulator.d.ts +1 -1
  68. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  69. package/dest/simulators/lending_simulator.js +2 -2
  70. package/dest/simulators/token_simulator.d.ts +1 -1
  71. package/dest/simulators/token_simulator.d.ts.map +1 -1
  72. package/dest/simulators/token_simulator.js +2 -2
  73. package/dest/spartan/setup_test_wallets.d.ts +8 -1
  74. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  75. package/dest/spartan/setup_test_wallets.js +32 -3
  76. package/dest/spartan/tx_metrics.js +1 -1
  77. package/dest/spartan/utils/bot.d.ts +3 -2
  78. package/dest/spartan/utils/bot.d.ts.map +1 -1
  79. package/dest/spartan/utils/bot.js +2 -1
  80. package/dest/spartan/utils/config.d.ts +4 -1
  81. package/dest/spartan/utils/config.d.ts.map +1 -1
  82. package/dest/spartan/utils/config.js +2 -1
  83. package/dest/spartan/utils/index.d.ts +3 -2
  84. package/dest/spartan/utils/index.d.ts.map +1 -1
  85. package/dest/spartan/utils/index.js +3 -1
  86. package/dest/spartan/utils/k8s.d.ts +3 -1
  87. package/dest/spartan/utils/k8s.d.ts.map +1 -1
  88. package/dest/spartan/utils/k8s.js +6 -0
  89. package/dest/spartan/utils/nodes.d.ts +4 -5
  90. package/dest/spartan/utils/nodes.d.ts.map +1 -1
  91. package/dest/spartan/utils/nodes.js +9 -9
  92. package/dest/test-wallet/test_wallet.d.ts +4 -3
  93. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  94. package/dest/test-wallet/test_wallet.js +3 -3
  95. package/dest/test-wallet/wallet_worker_script.d.ts +2 -0
  96. package/dest/test-wallet/wallet_worker_script.d.ts.map +1 -0
  97. package/dest/test-wallet/wallet_worker_script.js +48 -0
  98. package/dest/test-wallet/worker_wallet.d.ts +52 -0
  99. package/dest/test-wallet/worker_wallet.d.ts.map +1 -0
  100. package/dest/test-wallet/worker_wallet.js +151 -0
  101. package/dest/test-wallet/worker_wallet_schema.d.ts +274 -0
  102. package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -0
  103. package/dest/test-wallet/worker_wallet_schema.js +10 -0
  104. package/package.json +43 -44
  105. package/src/bench/client_flows/client_flows_benchmark.ts +38 -30
  106. package/src/bench/utils.ts +7 -2
  107. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +20 -16
  108. package/src/e2e_epochs/epochs_test.ts +66 -66
  109. package/src/e2e_fees/fees_test.ts +13 -6
  110. package/src/e2e_nested_contract/nested_contract_test.ts +6 -4
  111. package/src/e2e_p2p/p2p_network.ts +31 -5
  112. package/src/e2e_p2p/reqresp/utils.ts +36 -8
  113. package/src/e2e_p2p/shared.ts +45 -2
  114. package/src/e2e_token_contract/token_contract_test.ts +18 -10
  115. package/src/fixtures/authwit_proxy.ts +50 -0
  116. package/src/fixtures/dumps/epoch_proof_result.json +1 -1
  117. package/src/fixtures/e2e_prover_test.ts +36 -40
  118. package/src/fixtures/elu_monitor.ts +126 -0
  119. package/src/fixtures/fixtures.ts +10 -0
  120. package/src/fixtures/setup.ts +68 -110
  121. package/src/fixtures/setup_p2p_test.ts +9 -17
  122. package/src/fixtures/token_utils.ts +6 -3
  123. package/src/shared/cross_chain_test_harness.ts +13 -9
  124. package/src/shared/gas_portal_test_harness.ts +1 -1
  125. package/src/shared/index.ts +1 -0
  126. package/src/shared/jest_setup.ts +51 -1
  127. package/src/shared/mock_state_view.ts +188 -0
  128. package/src/shared/submit-transactions.ts +1 -1
  129. package/src/shared/uniswap_l1_l2.ts +6 -4
  130. package/src/simulators/lending_simulator.ts +4 -2
  131. package/src/simulators/token_simulator.ts +6 -2
  132. package/src/spartan/setup_test_wallets.ts +56 -11
  133. package/src/spartan/tx_metrics.ts +1 -1
  134. package/src/spartan/utils/bot.ts +3 -0
  135. package/src/spartan/utils/config.ts +1 -0
  136. package/src/spartan/utils/index.ts +4 -0
  137. package/src/spartan/utils/k8s.ts +8 -0
  138. package/src/spartan/utils/nodes.ts +15 -10
  139. package/src/test-wallet/test_wallet.ts +5 -4
  140. package/src/test-wallet/wallet_worker_script.ts +60 -0
  141. package/src/test-wallet/worker_wallet.ts +213 -0
  142. package/src/test-wallet/worker_wallet_schema.ts +13 -0
@@ -54,7 +54,7 @@ export class BlacklistTokenContractTest {
54
54
  asset!: TokenBlacklistContract;
55
55
  tokenSim!: TokenSimulator;
56
56
  badAccount!: InvalidAccountContract;
57
- proxy!: GenericProxyContract;
57
+ authwitProxy!: GenericProxyContract;
58
58
  cheatCodes!: CheatCodes;
59
59
  sequencer!: SequencerClient;
60
60
  aztecNode!: AztecNode;
@@ -107,21 +107,25 @@ export class BlacklistTokenContractTest {
107
107
  await publicDeployAccounts(this.wallet, [this.adminAddress, this.otherAddress, this.blacklistedAddress]);
108
108
 
109
109
  this.logger.verbose(`Deploying TokenContract...`);
110
- this.asset = await TokenBlacklistContract.deploy(this.wallet, this.adminAddress).send({
110
+ ({ contract: this.asset } = await TokenBlacklistContract.deploy(this.wallet, this.adminAddress).send({
111
111
  from: this.adminAddress,
112
- });
112
+ }));
113
113
  this.logger.verbose(`Token deployed to ${this.asset.address}`);
114
114
 
115
115
  this.logger.verbose(`Deploying bad account...`);
116
- this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress });
116
+ ({ contract: this.badAccount } = await InvalidAccountContract.deploy(this.wallet).send({
117
+ from: this.adminAddress,
118
+ }));
117
119
  this.logger.verbose(`Deployed to ${this.badAccount.address}.`);
118
120
 
119
121
  // Deploy a proxy contract for "on behalf of other" tests. The note owner must be the tx sender
120
122
  // (so their notes are in scope), but msg_sender in the target must differ from the note owner
121
123
  // to trigger authwit validation. The proxy forwards calls so that msg_sender != tx sender.
122
124
  this.logger.verbose(`Deploying generic proxy...`);
123
- this.proxy = await GenericProxyContract.deploy(this.wallet).send({ from: this.adminAddress });
124
- this.logger.verbose(`Deployed to ${this.proxy.address}.`);
125
+ ({ contract: this.authwitProxy } = await GenericProxyContract.deploy(this.wallet).send({
126
+ from: this.adminAddress,
127
+ }));
128
+ this.logger.verbose(`Deployed to ${this.authwitProxy.address}.`);
125
129
 
126
130
  await this.crossTimestampOfChange();
127
131
 
@@ -133,9 +137,9 @@ export class BlacklistTokenContractTest {
133
137
  [this.adminAddress, this.otherAddress, this.blacklistedAddress],
134
138
  );
135
139
 
136
- expect(await this.asset.methods.get_roles(this.adminAddress).simulate({ from: this.adminAddress })).toEqual(
137
- new Role().withAdmin().toNoirStruct(),
138
- );
140
+ expect(
141
+ (await this.asset.methods.get_roles(this.adminAddress).simulate({ from: this.adminAddress })).result,
142
+ ).toEqual(new Role().withAdmin().toNoirStruct());
139
143
  }
140
144
 
141
145
  async setup() {
@@ -189,9 +193,9 @@ export class BlacklistTokenContractTest {
189
193
 
190
194
  await this.crossTimestampOfChange();
191
195
 
192
- expect(await this.asset.methods.get_roles(this.adminAddress).simulate({ from: this.adminAddress })).toEqual(
193
- adminMinterRole.toNoirStruct(),
194
- );
196
+ expect(
197
+ (await this.asset.methods.get_roles(this.adminAddress).simulate({ from: this.adminAddress })).result,
198
+ ).toEqual(adminMinterRole.toNoirStruct());
195
199
 
196
200
  this.logger.verbose(`Minting ${amount} publicly...`);
197
201
  await asset.methods.mint_public(this.adminAddress, amount).send({ from: this.adminAddress });
@@ -199,7 +203,7 @@ export class BlacklistTokenContractTest {
199
203
  this.logger.verbose(`Minting ${amount} privately...`);
200
204
  const secret = Fr.random();
201
205
  const secretHash = await computeSecretHash(secret);
202
- const receipt = await asset.methods.mint_private(amount, secretHash).send({ from: this.adminAddress });
206
+ const { receipt } = await asset.methods.mint_private(amount, secretHash).send({ from: this.adminAddress });
203
207
 
204
208
  await this.addPendingShieldNoteToPXE(asset, this.adminAddress, amount, secretHash, receipt.txHash);
205
209
  await asset.methods.redeem_shield(this.adminAddress, amount, secret).send({ from: this.adminAddress });
@@ -207,20 +211,20 @@ export class BlacklistTokenContractTest {
207
211
 
208
212
  tokenSim.mintPublic(this.adminAddress, amount);
209
213
 
210
- const publicBalance = await asset.methods
214
+ const { result: publicBalance } = await asset.methods
211
215
  .balance_of_public(this.adminAddress)
212
216
  .simulate({ from: this.adminAddress });
213
217
  this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`);
214
218
  expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(this.adminAddress));
215
219
 
216
220
  tokenSim.mintPrivate(this.adminAddress, amount);
217
- const privateBalance = await asset.methods
221
+ const { result: privateBalance } = await asset.methods
218
222
  .balance_of_private(this.adminAddress)
219
223
  .simulate({ from: this.adminAddress });
220
224
  this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
221
225
  expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(this.adminAddress));
222
226
 
223
- const totalSupply = await asset.methods.total_supply().simulate({ from: this.adminAddress });
227
+ const { result: totalSupply } = await asset.methods.total_supply().simulate({ from: this.adminAddress });
224
228
  this.logger.verbose(`Total supply: ${totalSupply}`);
225
229
  expect(totalSupply).toEqual(tokenSim.totalSupply);
226
230
  }
@@ -1,3 +1,4 @@
1
+ import type { Archiver } from '@aztec/archiver';
1
2
  import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
2
3
  import { getTimestampRangeForEpoch } from '@aztec/aztec.js/block';
3
4
  import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
@@ -9,7 +10,8 @@ import { EpochCache } from '@aztec/epoch-cache';
9
10
  import { createExtendedL1Client } from '@aztec/ethereum/client';
10
11
  import { DefaultL1ContractsConfig } from '@aztec/ethereum/config';
11
12
  import { RollupContract } from '@aztec/ethereum/contracts';
12
- import { ChainMonitor, DelayedTxUtils, type Delayer, waitUntilL1Timestamp, withDelayer } from '@aztec/ethereum/test';
13
+ import { Delayer, createDelayer, waitUntilL1Timestamp, wrapClientWithDelayer } from '@aztec/ethereum/l1-tx-utils';
14
+ import { ChainMonitor } from '@aztec/ethereum/test';
13
15
  import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
14
16
  import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
15
17
  import { SecretValue } from '@aztec/foundation/config';
@@ -20,16 +22,9 @@ import { sleep } from '@aztec/foundation/sleep';
20
22
  import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
21
23
  import { TestContract } from '@aztec/noir-test-contracts.js/Test';
22
24
  import { getMockPubSubP2PServiceFactory } from '@aztec/p2p/test-helpers';
23
- import { ProverNode, type ProverNodeConfig, ProverNodePublisher } from '@aztec/prover-node';
24
- import type { TestProverNode } from '@aztec/prover-node/test';
25
+ import type { ProverNodeConfig } from '@aztec/prover-node';
25
26
  import type { PXEConfig } from '@aztec/pxe/config';
26
- import {
27
- type SequencerClient,
28
- type SequencerEvents,
29
- type SequencerPublisher,
30
- SequencerState,
31
- } from '@aztec/sequencer-client';
32
- import type { TestSequencerClient } from '@aztec/sequencer-client/test';
27
+ import { type SequencerClient, type SequencerEvents, SequencerState } from '@aztec/sequencer-client';
33
28
  import { type BlockParameter, EthAddress } from '@aztec/stdlib/block';
34
29
  import { type L1RollupConstants, getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
35
30
  import { tryStop } from '@aztec/stdlib/interfaces/server';
@@ -46,7 +41,7 @@ import {
46
41
  setup,
47
42
  } from '../fixtures/utils.js';
48
43
 
49
- export const WORLD_STATE_BLOCK_HISTORY = 2;
44
+ export const WORLD_STATE_CHECKPOINT_HISTORY = 2;
50
45
  export const WORLD_STATE_BLOCK_CHECK_INTERVAL = 50;
51
46
  export const ARCHIVER_POLL_INTERVAL = 50;
52
47
  export const DEFAULT_L1_BLOCK_TIME = process.env.CI ? 12 : 8;
@@ -81,7 +76,7 @@ export class EpochsTestContext {
81
76
  public proverDelayer!: Delayer;
82
77
  public sequencerDelayer!: Delayer;
83
78
 
84
- public proverNodes: ProverNode[] = [];
79
+ public proverNodes: AztecNodeService[] = [];
85
80
  public nodes: AztecNodeService[] = [];
86
81
 
87
82
  public epochDuration!: number;
@@ -147,7 +142,7 @@ export class EpochsTestContext {
147
142
  // using the prover's eth address if the proverId is used for something in the rollup contract
148
143
  // Use numeric EthAddress for deterministic prover id
149
144
  proverId: EthAddress.fromNumber(1),
150
- worldStateBlockHistory: WORLD_STATE_BLOCK_HISTORY,
145
+ worldStateCheckpointHistory: WORLD_STATE_CHECKPOINT_HISTORY,
151
146
  exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
152
147
  slasherFlavor: 'none',
153
148
  l1PublishingTime,
@@ -169,17 +164,8 @@ export class EpochsTestContext {
169
164
  // Loop that tracks L1 and L2 block numbers and logs whenever there's a new one.
170
165
  this.monitor = new ChainMonitor(this.rollup, context.dateProvider, this.logger).start();
171
166
 
172
- // This is hideous.
173
- // We ought to have a definite reference to the l1TxUtils that we're using in both places, provided by the test context.
174
- this.proverDelayer = context.proverNode
175
- ? (((context.proverNode as TestProverNode).publisher as ProverNodePublisher).l1TxUtils as DelayedTxUtils).delayer!
176
- : undefined!;
177
- this.sequencerDelayer = context.sequencer
178
- ? (
179
- ((context.sequencer as TestSequencerClient).sequencer.publisher as SequencerPublisher)
180
- .l1TxUtils as DelayedTxUtils
181
- ).delayer!
182
- : undefined!;
167
+ this.proverDelayer = context.proverDelayer!;
168
+ this.sequencerDelayer = context.sequencerDelayer!;
183
169
 
184
170
  if ((context.proverNode && !this.proverDelayer) || (context.sequencer && !this.sequencerDelayer)) {
185
171
  throw new Error(`Could not find prover or sequencer delayer`);
@@ -214,26 +200,29 @@ export class EpochsTestContext {
214
200
  const proverNodePrivateKey = this.getNextPrivateKey();
215
201
  const proverIndex = this.proverNodes.length + 1;
216
202
  const { mockGossipSubNetwork } = this.context;
217
- const proverNode = await withLoggerBindings({ actor: `prover-${proverIndex}` }, () =>
203
+ const { proverNode } = await withLoggerBindings({ actor: `prover-${proverIndex}` }, () =>
218
204
  createAndSyncProverNode(
219
205
  proverNodePrivateKey,
220
206
  {
221
207
  ...this.context.config,
222
208
  p2pEnabled: this.context.config.p2pEnabled || mockGossipSubNetwork !== undefined,
223
- },
224
- {
225
- dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
226
209
  proverId: EthAddress.fromNumber(proverIndex),
227
210
  dontStart: opts.dontStart,
228
211
  ...opts,
229
212
  },
230
- this.context.aztecNode,
231
- this.context.prefilledPublicData ?? [],
213
+ {
214
+ dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
215
+ },
232
216
  {
233
217
  dateProvider: this.context.dateProvider,
234
- p2pClientDeps: mockGossipSubNetwork
235
- ? { p2pServiceFactory: getMockPubSubP2PServiceFactory(mockGossipSubNetwork) }
236
- : undefined,
218
+ p2pClientDeps: {
219
+ p2pServiceFactory: mockGossipSubNetwork ? getMockPubSubP2PServiceFactory(mockGossipSubNetwork) : undefined,
220
+ rpcTxProviders: [this.context.aztecNode],
221
+ },
222
+ },
223
+ {
224
+ prefilledPublicData: this.context.prefilledPublicData ?? [],
225
+ dontStart: opts.dontStart,
237
226
  },
238
227
  ),
239
228
  );
@@ -248,15 +237,13 @@ export class EpochsTestContext {
248
237
 
249
238
  public createValidatorNode(
250
239
  privateKeys: `0x${string}`[],
251
- opts: Partial<AztecNodeConfig> & { txDelayerMaxInclusionTimeIntoSlot?: number; dontStartSequencer?: boolean } = {},
240
+ opts: Partial<AztecNodeConfig> & { dontStartSequencer?: boolean } = {},
252
241
  ) {
253
242
  this.logger.warn('Creating and syncing a validator node...');
254
243
  return this.createNode({ ...opts, disableValidator: false, validatorPrivateKeys: new SecretValue(privateKeys) });
255
244
  }
256
245
 
257
- private async createNode(
258
- opts: Partial<AztecNodeConfig> & { txDelayerMaxInclusionTimeIntoSlot?: number; dontStartSequencer?: boolean } = {},
259
- ) {
246
+ private async createNode(opts: Partial<AztecNodeConfig> & { dontStartSequencer?: boolean } = {}) {
260
247
  const nodeIndex = this.nodes.length + 1;
261
248
  const actorPrefix = opts.disableValidator ? 'node' : 'validator';
262
249
  const { mockGossipSubNetwork } = this.context;
@@ -285,26 +272,6 @@ export class EpochsTestContext {
285
272
  ),
286
273
  );
287
274
 
288
- // REFACTOR: We're getting too much into the internals of the sequencer here.
289
- // We should have a single method for constructing an aztec node that returns a TestAztecNodeService
290
- // which directly exposes the delayer and sets any test config.
291
- if (opts.txDelayerMaxInclusionTimeIntoSlot !== undefined) {
292
- this.logger.info(
293
- `Setting tx delayer max inclusion time into slot to ${opts.txDelayerMaxInclusionTimeIntoSlot} seconds`,
294
- );
295
- // Here we reach into the sequencer and hook in a tx delayer. The problem is that the sequencer's l1 utils only uses a public client, not a wallet.
296
- // The delayer needs a wallet (a client that can sign), so we have to create one here.
297
- const l1Client = createExtendedL1Client(
298
- resolvedConfig.l1RpcUrls!,
299
- resolvedConfig.publisherPrivateKeys![0]!.getValue(),
300
- );
301
- const sequencer = node.getSequencer() as TestSequencerClient;
302
- const publisher = sequencer.sequencer.publisher;
303
- const delayed = DelayedTxUtils.fromL1TxUtils(publisher.l1TxUtils, this.L1_BLOCK_TIME_IN_S, l1Client);
304
- delayed.delayer!.setMaxInclusionTimeIntoSlot(opts.txDelayerMaxInclusionTimeIntoSlot);
305
- publisher.l1TxUtils = delayed;
306
- }
307
-
308
275
  this.nodes.push(node);
309
276
  return node;
310
277
  }
@@ -356,7 +323,10 @@ export class EpochsTestContext {
356
323
  this.logger.info(`Waiting until last slot of submission window for epoch ${epochNumber} at ${date}`, {
357
324
  oneSlotBefore,
358
325
  });
359
- await waitUntilL1Timestamp(this.l1Client, oneSlotBefore);
326
+ // Use a timeout that accounts for the full proof submission window
327
+ const proofSubmissionWindowDuration =
328
+ this.constants.proofSubmissionEpochs * this.epochDuration * this.L2_SLOT_DURATION_IN_S;
329
+ await waitUntilL1Timestamp(this.l1Client, oneSlotBefore, undefined, proofSubmissionWindowDuration * 2);
360
330
  }
361
331
 
362
332
  /** Waits for the aztec node to sync to the target block number. */
@@ -408,15 +378,13 @@ export class EpochsTestContext {
408
378
 
409
379
  /** Creates an L1 client using a fresh account with funds from anvil, with a tx delayer already set up. */
410
380
  public async createL1Client() {
411
- const { client, delayer } = withDelayer(
412
- createExtendedL1Client(
413
- [...this.l1Client.chain.rpcUrls.default.http],
414
- privateKeyToAccount(this.getNextPrivateKey()),
415
- this.l1Client.chain,
416
- ),
417
- this.context.dateProvider,
418
- { ethereumSlotDuration: this.L1_BLOCK_TIME_IN_S },
381
+ const rawClient = createExtendedL1Client(
382
+ [...this.l1Client.chain.rpcUrls.default.http],
383
+ privateKeyToAccount(this.getNextPrivateKey()),
384
+ this.l1Client.chain,
419
385
  );
386
+ const delayer = createDelayer(this.context.dateProvider, { ethereumSlotDuration: this.L1_BLOCK_TIME_IN_S }, {});
387
+ const client = wrapClientWithDelayer(rawClient, delayer);
420
388
  expect(await client.getBalance({ address: client.account.address })).toBeGreaterThan(0n);
421
389
  return { client, delayer };
422
390
  }
@@ -433,6 +401,38 @@ export class EpochsTestContext {
433
401
  expect(result).toBe(expectedSuccess);
434
402
  }
435
403
 
404
+ /** Verifies at least one checkpoint has the target number of blocks (for MBPS validation). */
405
+ public async assertMultipleBlocksPerSlot(targetBlockCount: number) {
406
+ const archiver = (this.context.aztecNode as AztecNodeService).getBlockSource() as Archiver;
407
+ const checkpoints = await archiver.getCheckpoints(CheckpointNumber(1), 50);
408
+
409
+ this.logger.warn(`Retrieved ${checkpoints.length} checkpoints from archiver`, {
410
+ checkpoints: checkpoints.map(pc => pc.checkpoint.getStats()),
411
+ });
412
+
413
+ let expectedBlockNumber = checkpoints[0].checkpoint.blocks[0].number;
414
+ let targetFound = false;
415
+
416
+ for (const checkpoint of checkpoints) {
417
+ const blockCount = checkpoint.checkpoint.blocks.length;
418
+ targetFound = targetFound || blockCount >= targetBlockCount;
419
+
420
+ this.logger.verbose(`Checkpoint ${checkpoint.checkpoint.number} has ${blockCount} blocks`, {
421
+ checkpoint: checkpoint.checkpoint.getStats(),
422
+ });
423
+
424
+ for (let i = 0; i < blockCount; i++) {
425
+ const block = checkpoint.checkpoint.blocks[i];
426
+ expect(block.indexWithinCheckpoint).toBe(i);
427
+ expect(block.checkpointNumber).toBe(checkpoint.checkpoint.number);
428
+ expect(block.number).toBe(expectedBlockNumber);
429
+ expectedBlockNumber++;
430
+ }
431
+ }
432
+
433
+ expect(targetFound).toBe(true);
434
+ }
435
+
436
436
  public watchSequencerEvents(
437
437
  sequencers: SequencerClient[],
438
438
  getMetadata: (i: number) => Record<string, any> = () => ({}),
@@ -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);
@@ -157,11 +160,15 @@ export class FeesTest {
157
160
 
158
161
  /** Alice mints bananaCoin tokens privately to the target address and redeems them. */
159
162
  async mintPrivateBananas(amount: bigint, address: AztecAddress) {
160
- const balanceBefore = await this.bananaCoin.methods.balance_of_private(address).simulate({ from: address });
163
+ const { result: balanceBefore } = await this.bananaCoin.methods
164
+ .balance_of_private(address)
165
+ .simulate({ from: address });
161
166
 
162
167
  await mintTokensToPrivate(this.bananaCoin, this.aliceAddress, address, amount);
163
168
 
164
- const balanceAfter = await this.bananaCoin.methods.balance_of_private(address).simulate({ from: address });
169
+ const { result: balanceAfter } = await this.bananaCoin.methods
170
+ .balance_of_private(address)
171
+ .simulate({ from: address });
165
172
  expect(balanceAfter).toEqual(balanceBefore + amount);
166
173
  }
167
174
 
@@ -223,7 +230,7 @@ export class FeesTest {
223
230
  async applyDeployBananaToken() {
224
231
  this.logger.info('Applying deploy banana token setup');
225
232
 
226
- const bananaCoin = await BananaCoin.deploy(this.wallet, this.aliceAddress, 'BC', 'BC', 18n).send({
233
+ const { contract: bananaCoin } = await BananaCoin.deploy(this.wallet, this.aliceAddress, 'BC', 'BC', 18n).send({
227
234
  from: this.aliceAddress,
228
235
  });
229
236
  this.logger.info(`BananaCoin deployed at ${bananaCoin.address}`);
@@ -244,7 +251,7 @@ export class FeesTest {
244
251
  expect((await this.wallet.getContractMetadata(feeJuiceContract.address)).isContractPublished).toBe(true);
245
252
 
246
253
  const bananaCoin = this.bananaCoin;
247
- const bananaFPC = await FPCContract.deploy(this.wallet, bananaCoin.address, this.fpcAdmin).send({
254
+ const { contract: bananaFPC } = await FPCContract.deploy(this.wallet, bananaCoin.address, this.fpcAdmin).send({
248
255
  from: this.aliceAddress,
249
256
  });
250
257
 
@@ -275,7 +282,7 @@ export class FeesTest {
275
282
 
276
283
  // @todo @lherskind As we deal with #13601
277
284
  // Right now the value is from `FeeLib.sol`
278
- const L1_GAS_PER_EPOCH_VERIFIED = 1000000n;
285
+ const L1_GAS_PER_EPOCH_VERIFIED = 3600000n;
279
286
 
280
287
  // We round up
281
288
  const mulDiv = (a: bigint, b: bigint, c: bigint) => (a * b) / c + ((a * b) % c > 0n ? 1n : 0n);
@@ -65,9 +65,11 @@ export class NestedContractTest {
65
65
 
66
66
  async applyManual() {
67
67
  this.logger.info('Deploying parent and child contracts');
68
- const parentContract = await ParentContract.deploy(this.wallet).send({ from: this.defaultAccountAddress });
69
- const childContract = await ChildContract.deploy(this.wallet).send({ from: this.defaultAccountAddress });
70
- this.parentContract = parentContract;
71
- this.childContract = childContract;
68
+ ({ contract: this.parentContract } = await ParentContract.deploy(this.wallet).send({
69
+ from: this.defaultAccountAddress,
70
+ }));
71
+ ({ contract: this.childContract } = await ChildContract.deploy(this.wallet).send({
72
+ from: this.defaultAccountAddress,
73
+ }));
72
74
  }
73
75
  }
@@ -12,7 +12,7 @@ import {
12
12
  import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts';
13
13
  import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
14
14
  import { MultiAdderArtifact } from '@aztec/ethereum/l1-artifacts';
15
- import { createL1TxUtilsFromViemWallet } from '@aztec/ethereum/l1-tx-utils';
15
+ import { createL1TxUtils } from '@aztec/ethereum/l1-tx-utils';
16
16
  import { ChainMonitor } from '@aztec/ethereum/test';
17
17
  import type { ExtendedViemWalletClient, ViemClient } from '@aztec/ethereum/types';
18
18
  import { EpochNumber } from '@aztec/foundation/branded-types';
@@ -25,6 +25,7 @@ import type { BootstrapNode } from '@aztec/p2p/bootstrap';
25
25
  import { createBootstrapNodeFromPrivateKey, getBootstrapNodeEnr } from '@aztec/p2p/test-helpers';
26
26
  import { tryStop } from '@aztec/stdlib/interfaces/server';
27
27
  import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
28
+ import { TopicType } from '@aztec/stdlib/p2p';
28
29
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
29
30
  import { ZkPassportProofParams } from '@aztec/stdlib/zkpassport';
30
31
  import { getGenesisValues } from '@aztec/world-state/testing';
@@ -58,7 +59,7 @@ export const WAIT_FOR_TX_TIMEOUT = l1ContractsConfig.aztecSlotDuration * 3;
58
59
  export const SHORTENED_BLOCK_TIME_CONFIG_NO_PRUNES = {
59
60
  aztecSlotDuration: 12,
60
61
  ethereumSlotDuration: 4,
61
- aztecProofSubmissionWindow: 640,
62
+ aztecProofSubmissionEpochs: 640,
62
63
  };
63
64
 
64
65
  export class P2PNetworkTest {
@@ -322,8 +323,9 @@ export class P2PNetworkTest {
322
323
  throw new Error('Call setupAccount before deploying spam contract');
323
324
  }
324
325
 
325
- const spamContract = await SpamContract.deploy(this.wallet).send({ from: this.defaultAccountAddress! });
326
- this.spamContract = spamContract;
326
+ ({ contract: this.spamContract } = await SpamContract.deploy(this.wallet).send({
327
+ from: this.defaultAccountAddress!,
328
+ }));
327
329
  }
328
330
 
329
331
  async removeInitialNode() {
@@ -343,7 +345,7 @@ export class P2PNetworkTest {
343
345
  }
344
346
 
345
347
  private async _sendDummyTx(l1Client: ExtendedViemWalletClient) {
346
- const l1TxUtils = createL1TxUtilsFromViemWallet(l1Client);
348
+ const l1TxUtils = createL1TxUtils(l1Client);
347
349
  return await l1TxUtils.sendAndMonitorTransaction({
348
350
  to: l1Client.account!.address,
349
351
  value: 1n,
@@ -406,6 +408,7 @@ export class P2PNetworkTest {
406
408
  expectedNodeCount?: number,
407
409
  timeoutSeconds = 30,
408
410
  checkIntervalSeconds = 0.1,
411
+ topics: TopicType[] = [TopicType.tx],
409
412
  ) {
410
413
  const nodeCount = expectedNodeCount ?? nodes.length;
411
414
  const minPeerCount = nodeCount - 1;
@@ -431,6 +434,29 @@ export class P2PNetworkTest {
431
434
  );
432
435
 
433
436
  this.logger.warn('All nodes connected to P2P mesh');
437
+
438
+ // Wait for GossipSub mesh to form for all specified topics.
439
+ // We only require at least 1 mesh peer per node because GossipSub
440
+ // stops grafting once it reaches Dlo peers and won't fill the mesh to all available peers.
441
+ for (const topic of topics) {
442
+ this.logger.warn(`Waiting for GossipSub mesh to form for ${topic} topic...`);
443
+ await Promise.all(
444
+ nodes.map(async (node, index) => {
445
+ const p2p = node.getP2P();
446
+ await retryUntil(
447
+ async () => {
448
+ const meshPeers = await p2p.getGossipMeshPeerCount(topic);
449
+ this.logger.debug(`Node ${index} has ${meshPeers} gossip mesh peers for ${topic} topic`);
450
+ return meshPeers >= 1 ? true : undefined;
451
+ },
452
+ `Node ${index} to have gossip mesh peers for ${topic} topic`,
453
+ timeoutSeconds,
454
+ checkIntervalSeconds,
455
+ );
456
+ }),
457
+ );
458
+ this.logger.warn(`All nodes have gossip mesh peers for ${topic} topic`);
459
+ }
434
460
  }
435
461
 
436
462
  async teardown() {
@@ -3,24 +3,24 @@ import { createLogger } from '@aztec/aztec.js/log';
3
3
  import { waitForTx } from '@aztec/aztec.js/node';
4
4
  import { Tx } from '@aztec/aztec.js/tx';
5
5
  import { RollupContract } from '@aztec/ethereum/contracts';
6
- import { SlotNumber } from '@aztec/foundation/branded-types';
6
+ import { CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
7
7
  import { timesAsync } from '@aztec/foundation/collection';
8
8
  import { retryUntil } from '@aztec/foundation/retry';
9
9
 
10
- import { jest } from '@jest/globals';
10
+ import { expect, jest } from '@jest/globals';
11
11
  import fs from 'fs';
12
12
  import os from 'os';
13
13
  import path from 'path';
14
14
 
15
- import { shouldCollectMetrics } from '../../fixtures/fixtures.js';
15
+ import { getBootNodeUdpPort, shouldCollectMetrics } from '../../fixtures/fixtures.js';
16
16
  import { createNodes } from '../../fixtures/setup_p2p_test.js';
17
- import { P2PNetworkTest, SHORTENED_BLOCK_TIME_CONFIG_NO_PRUNES, WAIT_FOR_TX_TIMEOUT } from '../p2p_network.js';
17
+ import { P2PNetworkTest, WAIT_FOR_TX_TIMEOUT } from '../p2p_network.js';
18
18
  import { prepareTransactions } from '../shared.js';
19
19
 
20
20
  // Don't set this to a higher value than 9 because each node will use a different L1 publisher account and anvil seeds
21
21
  export const NUM_VALIDATORS = 6;
22
- export const NUM_TXS_PER_NODE = 2;
23
- export const BOOT_NODE_UDP_PORT = 4500;
22
+ export const NUM_TXS_PER_NODE = 4;
23
+ export const BOOT_NODE_UDP_PORT = getBootNodeUdpPort();
24
24
 
25
25
  export const createReqrespDataDir = () => fs.mkdtempSync(path.join(os.tmpdir(), 'reqresp-'));
26
26
 
@@ -38,8 +38,14 @@ export async function createReqrespTest(options: ReqrespOptions = {}): Promise<P
38
38
  // To collect metrics - run in aztec-packages `docker compose --profile metrics up`
39
39
  metricsPort: shouldCollectMetrics(),
40
40
  initialConfig: {
41
- ...SHORTENED_BLOCK_TIME_CONFIG_NO_PRUNES,
42
- aztecSlotDuration: 24,
41
+ ethereumSlotDuration: 8,
42
+ aztecSlotDuration: 36,
43
+ blockDurationMs: 6000,
44
+ l1PublishingTime: 8,
45
+ minTxsPerBlock: 1,
46
+ maxTxsPerBlock: 2,
47
+ enforceTimeTable: true,
48
+ aztecProofSubmissionEpochs: 1024, // effectively do not reorg
43
49
  ...(disableStatusHandshake ? { p2pDisableStatusHandshake: true } : {}),
44
50
  listenAddress: '127.0.0.1',
45
51
  aztecEpochDuration: 64, // stable committee
@@ -170,6 +176,28 @@ export async function runReqrespTxTest(params: {
170
176
 
171
177
  t.logger.info('All transactions mined');
172
178
 
179
+ // Assert that multiple blocks were built for at least one slot
180
+ 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);
183
+
184
+ let mbpsFound = false;
185
+ let expectedBlockNumber = checkpoints[0].checkpoint.blocks[0].number;
186
+
187
+ for (const published of checkpoints) {
188
+ const blockCount = published.checkpoint.blocks.length;
189
+ mbpsFound = mbpsFound || blockCount >= 2;
190
+
191
+ for (let i = 0; i < blockCount; i++) {
192
+ const block = published.checkpoint.blocks[i];
193
+ expect(block.indexWithinCheckpoint).toBe(i);
194
+ expect(block.checkpointNumber).toBe(published.checkpoint.number);
195
+ expect(block.number).toBe(expectedBlockNumber);
196
+ expectedBlockNumber++;
197
+ }
198
+ }
199
+
200
+ expect(mbpsFound).toBe(true);
173
201
  return nodes;
174
202
  }
175
203
 
@@ -6,12 +6,13 @@ import { Fr } from '@aztec/aztec.js/fields';
6
6
  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
+ import type { EpochCacheInterface } from '@aztec/epoch-cache';
9
10
  import type {
10
11
  EmpireSlashingProposerContract,
11
12
  RollupContract,
12
13
  TallySlashingProposerContract,
13
14
  } from '@aztec/ethereum/contracts';
14
- import { EpochNumber } from '@aztec/foundation/branded-types';
15
+ import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
15
16
  import { timesAsync, unique } from '@aztec/foundation/collection';
16
17
  import { EthAddress } from '@aztec/foundation/eth-address';
17
18
  import { retryUntil } from '@aztec/foundation/retry';
@@ -41,7 +42,7 @@ export const submitComplexTxsTo = async (
41
42
  const spamCount = 15;
42
43
  for (let i = 0; i < numTxs; i++) {
43
44
  const method = spamContract.methods.spam(seed + BigInt(i * spamCount), spamCount, !!opts.callPublic);
44
- const txHash = await method.send({ from, wait: NO_WAIT });
45
+ const { txHash } = await method.send({ from, wait: NO_WAIT });
45
46
  logger.info(`Tx sent with hash ${txHash.toString()}`);
46
47
  txs.push(txHash);
47
48
  }
@@ -150,6 +151,48 @@ export async function awaitCommitteeExists({
150
151
  return committee!.map(c => c.toString() as `0x${string}`);
151
152
  }
152
153
 
154
+ /**
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.
158
+ */
159
+ export async function awaitEpochWithProposer({
160
+ epochCache,
161
+ cheatCodes,
162
+ targetProposer,
163
+ logger,
164
+ maxAttempts = 20,
165
+ }: {
166
+ epochCache: EpochCacheInterface;
167
+ cheatCodes: RollupCheatCodes;
168
+ targetProposer: EthAddress;
169
+ logger: Logger;
170
+ maxAttempts?: number;
171
+ }): Promise<void> {
172
+ const { epochDuration } = await cheatCodes.getConfig();
173
+
174
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
175
+ const currentEpoch = await cheatCodes.getEpoch();
176
+ const startSlot = Number(currentEpoch) * Number(epochDuration);
177
+ const endSlot = startSlot + Number(epochDuration);
178
+
179
+ logger.info(`Checking epoch ${currentEpoch} (slots ${startSlot}-${endSlot - 1}) for proposer ${targetProposer}`);
180
+
181
+ for (let s = startSlot; s < endSlot; s++) {
182
+ const proposer = await epochCache.getProposerAttesterAddressInSlot(SlotNumber(s));
183
+ if (proposer && proposer.equals(targetProposer)) {
184
+ logger.warn(`Found target proposer ${targetProposer} in slot ${s} of epoch ${currentEpoch}`);
185
+ return;
186
+ }
187
+ }
188
+
189
+ logger.info(`Target proposer not found in epoch ${currentEpoch}, advancing to next epoch`);
190
+ await cheatCodes.advanceToNextEpoch();
191
+ }
192
+
193
+ throw new Error(`Target proposer ${targetProposer} not found in any slot after ${maxAttempts} epoch attempts`);
194
+ }
195
+
153
196
  export async function awaitOffenseDetected({
154
197
  logger,
155
198
  nodeAdmin,