@aztec/end-to-end 0.0.1-commit.b2a5d0dd1 → 0.0.1-commit.b3d3157a

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 (130) hide show
  1. package/dest/bench/client_flows/benchmark.d.ts +15 -1
  2. package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
  3. package/dest/bench/client_flows/benchmark.js +17 -0
  4. package/dest/bench/client_flows/client_flows_benchmark.d.ts +2 -2
  5. package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
  6. package/dest/bench/client_flows/client_flows_benchmark.js +13 -9
  7. package/dest/bench/utils.d.ts +1 -1
  8. package/dest/bench/utils.d.ts.map +1 -1
  9. package/dest/bench/utils.js +2 -0
  10. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +3 -3
  11. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  12. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +13 -4
  13. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +15 -4
  14. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
  15. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +39 -7
  16. package/dest/e2e_deploy_contract/deploy_test.d.ts +3 -3
  17. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
  18. package/dest/e2e_deploy_contract/deploy_test.js +2 -1
  19. package/dest/e2e_epochs/epochs_test.d.ts +8 -2
  20. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  21. package/dest/e2e_epochs/epochs_test.js +30 -7
  22. package/dest/e2e_fees/fees_test.d.ts +5 -2
  23. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  24. package/dest/e2e_fees/fees_test.js +29 -3
  25. package/dest/e2e_nested_contract/nested_contract_test.d.ts +3 -3
  26. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  27. package/dest/e2e_nested_contract/nested_contract_test.js +2 -1
  28. package/dest/e2e_p2p/inactivity_slash_test.d.ts +1 -1
  29. package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -1
  30. package/dest/e2e_p2p/inactivity_slash_test.js +1 -0
  31. package/dest/e2e_p2p/reqresp/utils.d.ts +1 -1
  32. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  33. package/dest/e2e_p2p/reqresp/utils.js +28 -12
  34. package/dest/e2e_p2p/shared.d.ts +19 -8
  35. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  36. package/dest/e2e_p2p/shared.js +33 -13
  37. package/dest/e2e_token_contract/token_contract_test.d.ts +3 -3
  38. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  39. package/dest/e2e_token_contract/token_contract_test.js +4 -2
  40. package/dest/fixtures/e2e_prover_test.d.ts +3 -3
  41. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  42. package/dest/fixtures/e2e_prover_test.js +2 -1
  43. package/dest/fixtures/fixtures.d.ts +59 -1
  44. package/dest/fixtures/fixtures.d.ts.map +1 -1
  45. package/dest/fixtures/fixtures.js +55 -0
  46. package/dest/fixtures/schnorr_hardcoded_account_contract.js +2 -4
  47. package/dest/fixtures/setup.d.ts +30 -4
  48. package/dest/fixtures/setup.d.ts.map +1 -1
  49. package/dest/fixtures/setup.js +117 -7
  50. package/dest/fixtures/setup_p2p_test.d.ts +5 -1
  51. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  52. package/dest/fixtures/utils.d.ts +2 -2
  53. package/dest/fixtures/utils.d.ts.map +1 -1
  54. package/dest/fixtures/utils.js +1 -1
  55. package/dest/install_legacy_contracts.d.cts +10 -0
  56. package/dest/install_legacy_contracts.d.cts.map +1 -0
  57. package/dest/legacy-jest-resolver.d.cts +1 -1
  58. package/dest/legacy-jest-resolver.d.cts.map +1 -1
  59. package/dest/shared/cross_chain_test_harness.d.ts +4 -2
  60. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  61. package/dest/shared/cross_chain_test_harness.js +9 -5
  62. package/dest/shared/gas_portal_test_harness.d.ts +8 -5
  63. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
  64. package/dest/shared/gas_portal_test_harness.js +16 -7
  65. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  66. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  67. package/dest/shared/uniswap_l1_l2.js +50 -28
  68. package/dest/shared/wait_for_l1_to_l2_message.d.ts +13 -0
  69. package/dest/shared/wait_for_l1_to_l2_message.d.ts.map +1 -0
  70. package/dest/shared/wait_for_l1_to_l2_message.js +10 -0
  71. package/dest/simulators/lending_simulator.d.ts +10 -3
  72. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  73. package/dest/simulators/lending_simulator.js +23 -11
  74. package/dest/spartan/setup_test_wallets.d.ts +1 -1
  75. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  76. package/dest/spartan/setup_test_wallets.js +9 -3
  77. package/dest/spartan/tx_metrics.d.ts +18 -4
  78. package/dest/spartan/tx_metrics.d.ts.map +1 -1
  79. package/dest/spartan/tx_metrics.js +73 -20
  80. package/dest/spartan/utils/config.d.ts +9 -35
  81. package/dest/spartan/utils/config.d.ts.map +1 -1
  82. package/dest/spartan/utils/nodes.js +2 -2
  83. package/dest/test-wallet/test_wallet.d.ts +3 -2
  84. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  85. package/dest/test-wallet/test_wallet.js +49 -27
  86. package/dest/test-wallet/utils.d.ts +3 -3
  87. package/dest/test-wallet/utils.d.ts.map +1 -1
  88. package/dest/test-wallet/utils.js +2 -7
  89. package/dest/test-wallet/wallet_worker_script.js +7 -2
  90. package/dest/test-wallet/worker_wallet.d.ts +2 -1
  91. package/dest/test-wallet/worker_wallet.d.ts.map +1 -1
  92. package/dest/test-wallet/worker_wallet.js +6 -2
  93. package/dest/test-wallet/worker_wallet_schema.d.ts +110 -229
  94. package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -1
  95. package/dest/test-wallet/worker_wallet_schema.js +14 -2
  96. package/package.json +45 -41
  97. package/src/bench/client_flows/benchmark.ts +19 -0
  98. package/src/bench/client_flows/client_flows_benchmark.ts +32 -30
  99. package/src/bench/utils.ts +2 -1
  100. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +21 -4
  101. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +49 -11
  102. package/src/e2e_deploy_contract/deploy_test.ts +3 -2
  103. package/src/e2e_epochs/epochs_test.ts +32 -5
  104. package/src/e2e_fees/fees_test.ts +33 -2
  105. package/src/e2e_nested_contract/nested_contract_test.ts +3 -1
  106. package/src/e2e_p2p/inactivity_slash_test.ts +1 -0
  107. package/src/e2e_p2p/reqresp/utils.ts +29 -11
  108. package/src/e2e_p2p/shared.ts +31 -12
  109. package/src/e2e_token_contract/token_contract_test.ts +12 -2
  110. package/src/fixtures/e2e_prover_test.ts +3 -1
  111. package/src/fixtures/fixtures.ts +61 -0
  112. package/src/fixtures/schnorr_hardcoded_account_contract.ts +2 -2
  113. package/src/fixtures/setup.ts +134 -10
  114. package/src/fixtures/setup_p2p_test.ts +4 -0
  115. package/src/fixtures/utils.ts +2 -0
  116. package/src/install_legacy_contracts.cjs +75 -0
  117. package/src/legacy-jest-resolver.cjs +25 -48
  118. package/src/shared/cross_chain_test_harness.ts +14 -4
  119. package/src/shared/gas_portal_test_harness.ts +20 -9
  120. package/src/shared/uniswap_l1_l2.ts +84 -36
  121. package/src/shared/wait_for_l1_to_l2_message.ts +23 -0
  122. package/src/simulators/lending_simulator.ts +27 -13
  123. package/src/spartan/setup_test_wallets.ts +6 -4
  124. package/src/spartan/tx_metrics.ts +81 -23
  125. package/src/spartan/utils/nodes.ts +2 -2
  126. package/src/test-wallet/test_wallet.ts +46 -23
  127. package/src/test-wallet/utils.ts +3 -7
  128. package/src/test-wallet/wallet_worker_script.ts +5 -2
  129. package/src/test-wallet/worker_wallet.ts +7 -3
  130. package/src/test-wallet/worker_wallet_schema.ts +2 -2
@@ -28,7 +28,7 @@ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
28
28
  import { GasSettings } from '@aztec/stdlib/gas';
29
29
  import { deriveSigningKey } from '@aztec/stdlib/keys';
30
30
 
31
- import { MNEMONIC, getPaddedMaxFeesPerGas } from '../../fixtures/fixtures.js';
31
+ import { AUTOMINE_E2E_OPTS, MNEMONIC, getPaddedMaxFeesPerGas } from '../../fixtures/fixtures.js';
32
32
  import { type EndToEndContext, type SetupOptions, deployAccounts, setup, teardown } from '../../fixtures/setup.js';
33
33
  import { mintTokensToPrivate } from '../../fixtures/token_utils.js';
34
34
  import { setupSponsoredFPC } from '../../fixtures/utils.js';
@@ -88,33 +88,35 @@ export class ClientFlowsBenchmark {
88
88
 
89
89
  public realProofs = ['true', '1'].includes(process.env.REAL_PROOFS ?? '');
90
90
 
91
- public paymentMethods: Record<BenchmarkingFeePaymentMethod, { forWallet: FeePaymentMethodGetter; circuits: number }> =
92
- {
93
- // eslint-disable-next-line camelcase
94
- bridged_fee_juice: {
95
- forWallet: this.getBridgedFeeJuicePaymentMethodForWallet.bind(this),
96
- circuits: 2, // FeeJuice claim + kernel inner
97
- },
98
- // eslint-disable-next-line camelcase
99
- private_fpc: {
100
- forWallet: this.getPrivateFPCPaymentMethodForWallet.bind(this),
101
- circuits:
102
- 2 + // FPC entrypoint + kernel inner
103
- 2 + // BananaCoin transfer_to_public + kernel inner
104
- 2 + // Account verify_private_authwit + kernel inner
105
- 2, // BananaCoin prepare_private_balance_increase + kernel inner
106
- },
107
- // eslint-disable-next-line camelcase
108
- sponsored_fpc: {
109
- forWallet: this.getSponsoredFPCPaymentMethodForWallet.bind(this),
110
- circuits: 2, // Sponsored FPC sponsor_unconditionally + kernel inner
111
- },
112
- // eslint-disable-next-line camelcase
113
- fee_juice: {
114
- forWallet: () => Promise.resolve(undefined),
115
- circuits: 0,
116
- },
117
- };
91
+ // `apps` is the number of private function calls contributed by this payment method.
92
+ // Each app produces one execution step at proving time; the orchestrator additionally produces
93
+ // one kernel step per batch of N apps (see `expectedExecutionSteps` in `benchmark.ts`).
94
+ public paymentMethods: Record<BenchmarkingFeePaymentMethod, { forWallet: FeePaymentMethodGetter; apps: number }> = {
95
+ // eslint-disable-next-line camelcase
96
+ bridged_fee_juice: {
97
+ forWallet: this.getBridgedFeeJuicePaymentMethodForWallet.bind(this),
98
+ apps: 1, // FeeJuice claim
99
+ },
100
+ // eslint-disable-next-line camelcase
101
+ private_fpc: {
102
+ forWallet: this.getPrivateFPCPaymentMethodForWallet.bind(this),
103
+ apps:
104
+ 1 + // FPC entrypoint
105
+ 1 + // BananaCoin transfer_to_public
106
+ 1 + // Account verify_private_authwit
107
+ 1, // BananaCoin prepare_private_balance_increase
108
+ },
109
+ // eslint-disable-next-line camelcase
110
+ sponsored_fpc: {
111
+ forWallet: this.getSponsoredFPCPaymentMethodForWallet.bind(this),
112
+ apps: 1, // Sponsored FPC sponsor_unconditionally
113
+ },
114
+ // eslint-disable-next-line camelcase
115
+ fee_juice: {
116
+ forWallet: () => Promise.resolve(undefined),
117
+ apps: 0,
118
+ },
119
+ };
118
120
 
119
121
  public config: ClientFlowsConfig;
120
122
 
@@ -123,7 +125,7 @@ export class ClientFlowsBenchmark {
123
125
 
124
126
  constructor(testName?: string, setupOptions: Partial<SetupOptions & DeployAztecL1ContractsArgs> = {}) {
125
127
  this.logger = createLogger(`bench:client_flows${testName ? `:${testName}` : ''}`);
126
- this.setupOptions = { startProverNode: true, ...setupOptions };
128
+ this.setupOptions = { ...AUTOMINE_E2E_OPTS, startProverNode: true, ...setupOptions };
127
129
  this.config = BENCHMARK_CONFIG === 'key_flows' ? KEY_FLOWS_CONFIG : FULL_FLOWS_CONFIG;
128
130
  ProxyLogger.create();
129
131
  this.proxyLogger = ProxyLogger.getInstance();
@@ -347,7 +349,7 @@ export class ClientFlowsBenchmark {
347
349
  // Register benchy on the user's Wallet, where we're going to be interacting from
348
350
  const accountManager = await this.userWallet.createAccount({
349
351
  secret: benchysAccount.getSecretKey(),
350
- salt: new Fr(benchysAccount.salt),
352
+ salt: new Fr(benchysAccountManager.getInstance().salt),
351
353
  contract: benchysAccountManager.getAccountContract(),
352
354
  });
353
355
  return accountManager.address;
@@ -11,6 +11,7 @@ import type { BenchmarkDataPoint, BenchmarkMetricsType, BenchmarkTelemetryClient
11
11
  import { mkdirSync, writeFileSync } from 'fs';
12
12
  import path from 'path';
13
13
 
14
+ import { PIPELINING_SETUP_OPTS } from '../fixtures/fixtures.js';
14
15
  import { type EndToEndContext, type SetupOptions, setup } from '../fixtures/utils.js';
15
16
 
16
17
  /**
@@ -23,7 +24,7 @@ export async function benchmarkSetup(
23
24
  benchOutput?: string;
24
25
  },
25
26
  ) {
26
- const context = await setup(1, { ...opts, telemetryConfig: { benchmark: true } });
27
+ const context = await setup(1, { ...PIPELINING_SETUP_OPTS, ...opts, telemetryConfig: { benchmark: true } });
27
28
  const defaultAccountAddress = context.accounts[0];
28
29
  const { contract } = await BenchmarkingContract.deploy(context.wallet).send({ from: defaultAccountAddress });
29
30
  context.logger.info(`Deployed benchmarking contract at ${contract.address}`);
@@ -14,7 +14,15 @@ import type { AztecNodeDebug } from '@aztec/stdlib/interfaces/client';
14
14
 
15
15
  import { jest } from '@jest/globals';
16
16
 
17
- import { type EndToEndContext, deployAccounts, publicDeployAccounts, setup, teardown } from '../fixtures/setup.js';
17
+ import {
18
+ type EndToEndContext,
19
+ type SetupOptions,
20
+ deployAccounts,
21
+ ensureAuthRegistryPublished,
22
+ publicDeployAccounts,
23
+ setup,
24
+ teardown,
25
+ } from '../fixtures/setup.js';
18
26
  import { TokenSimulator } from '../simulators/token_simulator.js';
19
27
  import type { TestWallet } from '../test-wallet/test_wallet.js';
20
28
 
@@ -69,6 +77,12 @@ export class BlacklistTokenContractTest {
69
77
  }
70
78
 
71
79
  async crossTimestampOfChange() {
80
+ // Under AUTOMINE_E2E_OPTS, the 86400s warp crosses many epochs without any proofs being
81
+ // submitted. Mark current pending checkpoints as proven first so the rollup contract's
82
+ // pruning window doesn't reset the chain tip to genesis (which would make the warp's
83
+ // own empty-checkpoint propose fail with Rollup__InvalidArchive). See the AutomineSequencer
84
+ // README "Epoch proving caveat" and the equivalent pattern in lending_simulator.progressSlots.
85
+ await this.cheatCodes.rollup.markAsProven();
72
86
  await this.cheatCodes.warpL2TimeAtLeastBy(this.aztecNode, BlacklistTokenContractTest.CHANGE_ROLES_DELAY);
73
87
  }
74
88
 
@@ -78,8 +92,9 @@ export class BlacklistTokenContractTest {
78
92
  * 2. Publicly deploy accounts, deploy token contract and a "bad account".
79
93
  */
80
94
  async applyBaseSetup() {
81
- // Adding a timeout of 2 minutes in here such that it is propagated to the underlying tests
82
- jest.setTimeout(120_000);
95
+ // Bumped from 2 min: pipelined cadence (~24s/dependent-tx) makes the 3-account deploy plus token/bad-account/
96
+ // proxy deploys exceed the original window.
97
+ jest.setTimeout(600_000);
83
98
 
84
99
  this.logger.info('Deploying 3 accounts');
85
100
  const { deployedAccounts } = await deployAccounts(
@@ -99,6 +114,7 @@ export class BlacklistTokenContractTest {
99
114
  this.blacklistedAddress = deployedAccounts[2].address;
100
115
 
101
116
  this.logger.info('Setting up blacklist token contract');
117
+ await ensureAuthRegistryPublished(this.wallet, this.adminAddress);
102
118
  // Create the token contract state.
103
119
  this.logger.verbose(`Public deploy accounts...`);
104
120
  await publicDeployAccounts(this.wallet, [this.adminAddress, this.otherAddress, this.blacklistedAddress]);
@@ -139,9 +155,10 @@ export class BlacklistTokenContractTest {
139
155
  ).toEqual(new Role().withAdmin().toNoirStruct());
140
156
  }
141
157
 
142
- async setup() {
158
+ async setup(opts: Partial<SetupOptions> = {}) {
143
159
  this.logger.info('Setting up fresh context');
144
160
  this.context = await setup(0, {
161
+ ...opts,
145
162
  fundSponsoredFPC: true,
146
163
  skipAccountDeployment: true,
147
164
  });
@@ -4,7 +4,7 @@ import { waitForProven } from '@aztec/aztec.js/contracts';
4
4
  import { type Logger, createLogger } from '@aztec/aztec.js/log';
5
5
  import type { AztecNode } from '@aztec/aztec.js/node';
6
6
  import type { TxReceipt } from '@aztec/aztec.js/tx';
7
- import { CheatCodes } from '@aztec/aztec/testing';
7
+ import { CheatCodes, EpochTestSettler } from '@aztec/aztec/testing';
8
8
  import { createExtendedL1Client } from '@aztec/ethereum/client';
9
9
  import { InboxContract, OutboxContract, RollupContract } from '@aztec/ethereum/contracts';
10
10
  import type {
@@ -12,12 +12,14 @@ import type {
12
12
  DeployAztecL1ContractsReturnType,
13
13
  } from '@aztec/ethereum/deploy-aztec-l1-contracts';
14
14
  import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
15
+ import { pickL1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
15
16
  import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
16
17
  import { EpochNumber } from '@aztec/foundation/branded-types';
17
18
  import { sleep } from '@aztec/foundation/sleep';
18
19
  import { TestERC20Abi, TestERC20Bytecode } from '@aztec/l1-artifacts';
19
20
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
20
21
  import { TokenBridgeContract } from '@aztec/noir-contracts.js/TokenBridge';
22
+ import type { PXEConfig } from '@aztec/pxe/server';
21
23
  import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
22
24
 
23
25
  import { MNEMONIC } from '../fixtures/fixtures.js';
@@ -25,6 +27,7 @@ import {
25
27
  type EndToEndContext,
26
28
  type SetupOptions,
27
29
  deployAccounts,
30
+ ensureAuthRegistryPublished,
28
31
  publicDeployAccounts,
29
32
  setup,
30
33
  teardown,
@@ -36,6 +39,7 @@ export class CrossChainMessagingTest {
36
39
  private requireEpochProven: boolean;
37
40
  private setupOptions: SetupOptions;
38
41
  private deployL1ContractsArgs: Partial<DeployAztecL1ContractsArgs>;
42
+ private pxeOpts: Partial<PXEConfig>;
39
43
  logger: Logger;
40
44
  context!: EndToEndContext;
41
45
  aztecNode!: AztecNode;
@@ -58,12 +62,23 @@ export class CrossChainMessagingTest {
58
62
  outbox!: OutboxContract;
59
63
  cheatCodes!: CheatCodes;
60
64
 
65
+ /**
66
+ * Background loop that marks each completed epoch as proven on L1. Started in `applyBaseSetup`
67
+ * when the test runs without a real prover node, because the e2e fixture uses L1 interval mining
68
+ * and the AnvilTestWatcher's auto-prove loop only runs under L1 automine. Without this, L1's
69
+ * `aztecProofSubmissionEpochs` window expires mid-test and triggers a chain prune that drops
70
+ * in-flight wallet txs. Tests that intentionally pause proving (e.g. inbox drift tests) can
71
+ * stop it via `await t.epochTestSettler?.stop()`.
72
+ */
73
+ epochTestSettler?: EpochTestSettler;
74
+
61
75
  deployL1ContractsValues!: DeployAztecL1ContractsReturnType;
62
76
 
63
77
  constructor(
64
78
  testName: string,
65
79
  opts: SetupOptions = {},
66
80
  deployL1ContractsArgs: Partial<DeployAztecL1ContractsArgs> = {},
81
+ pxeOpts: Partial<PXEConfig> = {},
67
82
  ) {
68
83
  this.logger = createLogger(`e2e:e2e_cross_chain_messaging:${testName}`);
69
84
  this.setupOptions = opts;
@@ -71,17 +86,25 @@ export class CrossChainMessagingTest {
71
86
  initialValidators: [],
72
87
  ...deployL1ContractsArgs,
73
88
  };
89
+ this.pxeOpts = pxeOpts;
74
90
  this.requireEpochProven = opts.startProverNode ?? false;
75
91
  }
76
92
 
77
- async setup() {
93
+ async setup(opts: Partial<SetupOptions> = {}, pxeOpts: Partial<PXEConfig> = {}) {
78
94
  this.logger.info('Setting up cross chain messaging test');
79
- this.context = await setup(0, {
80
- ...this.setupOptions,
81
- fundSponsoredFPC: true,
82
- skipAccountDeployment: true,
83
- l1ContractsArgs: this.deployL1ContractsArgs,
84
- });
95
+ // Recompute requireEpochProven from the merged options so per-call startProverNode is honored.
96
+ this.requireEpochProven = opts.startProverNode ?? this.setupOptions.startProverNode ?? false;
97
+ this.context = await setup(
98
+ 0,
99
+ {
100
+ ...this.setupOptions,
101
+ ...opts,
102
+ fundSponsoredFPC: true,
103
+ skipAccountDeployment: true,
104
+ l1ContractsArgs: { ...this.deployL1ContractsArgs, ...opts.l1ContractsArgs },
105
+ },
106
+ { ...this.pxeOpts, ...pxeOpts },
107
+ );
85
108
  await this.applyBaseSetup();
86
109
  }
87
110
 
@@ -98,12 +121,13 @@ export class CrossChainMessagingTest {
98
121
 
99
122
  async catchUpProvenChain() {
100
123
  const bn = await this.aztecNode.getBlockNumber();
101
- while ((await this.aztecNode.getProvenBlockNumber()) < bn) {
124
+ while ((await this.aztecNode.getBlockNumber('proven')) < bn) {
102
125
  await sleep(1000);
103
126
  }
104
127
  }
105
128
 
106
129
  async teardown() {
130
+ await this.epochTestSettler?.stop();
107
131
  await teardown(this.context);
108
132
  }
109
133
 
@@ -119,6 +143,19 @@ export class CrossChainMessagingTest {
119
143
  if (this.requireEpochProven) {
120
144
  // Turn off the watcher to prevent it from keep marking blocks as proven.
121
145
  this.context.watcher.setIsMarkingAsProven(false);
146
+ } else {
147
+ // When no real prover is running, the L1 proof window (aztecProofSubmissionEpochs) would
148
+ // otherwise expire mid-test and trigger a chain prune. The AnvilTestWatcher's auto-prove
149
+ // loop is dormant under L1 interval mining (it gates on `isAutoMining`), so start an
150
+ // EpochTestSettler to mark each completed epoch as proven on L1.
151
+ this.epochTestSettler = new EpochTestSettler(
152
+ this.context.ethCheatCodes,
153
+ this.context.deployL1ContractsValues.l1ContractAddresses.rollupAddress,
154
+ this.context.aztecNodeService.getBlockSource(),
155
+ this.logger.createChild('epoch-settler'),
156
+ { pollingIntervalMs: 500 },
157
+ );
158
+ await this.epochTestSettler.start();
122
159
  }
123
160
 
124
161
  // Deploy 3 accounts
@@ -135,6 +172,7 @@ export class CrossChainMessagingTest {
135
172
  // Set up cross chain messaging
136
173
  this.logger.info('Applying e2e_cross_chain_messaging setup');
137
174
 
175
+ await ensureAuthRegistryPublished(this.wallet, this.ownerAddress);
138
176
  // Create the token contract state.
139
177
  this.logger.verbose(`Public deploy accounts...`);
140
178
  await publicDeployAccounts(this.wallet, [this.ownerAddress, this.user1Address, this.user2Address]);
@@ -171,7 +209,7 @@ export class CrossChainMessagingTest {
171
209
  const l1Client = createExtendedL1Client(this.aztecNodeConfig.l1RpcUrls, MNEMONIC);
172
210
  this.l1Client = l1Client;
173
211
 
174
- const l1Contracts = this.aztecNodeConfig.l1Contracts;
212
+ const l1Contracts = pickL1ContractAddresses(this.aztecNodeConfig);
175
213
  this.rollup = new RollupContract(l1Client, l1Contracts.rollupAddress.toString());
176
214
  this.inbox = new InboxContract(l1Client, l1Contracts.inboxAddress.toString());
177
215
  this.outbox = new OutboxContract(l1Client, l1Contracts.outboxAddress.toString());
@@ -185,7 +223,7 @@ export class CrossChainMessagingTest {
185
223
  tokenPortalAddress,
186
224
  crossChainContext.underlying,
187
225
  l1Client,
188
- this.aztecNodeConfig.l1Contracts,
226
+ pickL1ContractAddresses(this.aztecNodeConfig),
189
227
  this.wallet,
190
228
  this.ownerAddress,
191
229
  );
@@ -9,7 +9,7 @@ import type { Wallet } from '@aztec/aztec.js/wallet';
9
9
  import type { StatefulTestContract } from '@aztec/noir-test-contracts.js/StatefulTest';
10
10
  import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
11
11
 
12
- import { type EndToEndContext, deployAccounts, setup, teardown } from '../fixtures/setup.js';
12
+ import { type EndToEndContext, type SetupOptions, deployAccounts, setup, teardown } from '../fixtures/setup.js';
13
13
  import type { TestWallet } from '../test-wallet/test_wallet.js';
14
14
 
15
15
  export class DeployTest {
@@ -24,9 +24,10 @@ export class DeployTest {
24
24
  this.logger = createLogger(`e2e:e2e_deploy_contract:${testName}`);
25
25
  }
26
26
 
27
- async setup() {
27
+ async setup(opts: Partial<SetupOptions> = {}) {
28
28
  this.logger.info('Setting up test environment');
29
29
  this.context = await setup(0, {
30
+ ...opts,
30
31
  fundSponsoredFPC: true,
31
32
  skipAccountDeployment: true,
32
33
  });
@@ -60,6 +60,11 @@ export type EpochsTestOpts = Partial<SetupOptions> & {
60
60
  aztecSlotDurationInL1Slots?: number;
61
61
  /** Skip creating/registering the hardcoded account during setup (for tests that handle accounts themselves). */
62
62
  skipHardcodedAccount?: boolean;
63
+ /**
64
+ * Force the hardcoded-account fast-path even when an initial sequencer is running. Useful for
65
+ * tests with tight per-block gas budgets that can't fit a full account-deploy tx.
66
+ */
67
+ useHardcodedAccount?: boolean;
63
68
  };
64
69
 
65
70
  export type TrackedSequencerEvent = {
@@ -130,9 +135,11 @@ export class EpochsTestContext {
130
135
  this.L1_BLOCK_TIME_IN_S = ethereumSlotDuration;
131
136
  this.L2_SLOT_DURATION_IN_S = aztecSlotDuration;
132
137
 
133
- // When skipInitialSequencer is set, auto-create a hardcoded account funded via genesis.
134
- // This avoids needing to deploy accounts on-chain (which would require a running sequencer).
135
- const useHardcodedAccount = opts.skipInitialSequencer && !opts.skipHardcodedAccount;
138
+ // Auto-create a hardcoded account funded via genesis when:
139
+ // - skipInitialSequencer is set (no sequencer to deploy on-chain), or
140
+ // - useHardcodedAccount is explicitly requested (e.g. tight per-block gas budgets that
141
+ // can't fit a full account-deploy tx).
142
+ const useHardcodedAccount = (opts.skipInitialSequencer || opts.useHardcodedAccount) && !opts.skipHardcodedAccount;
136
143
  let hardcodedAccountData: InitialAccountData | undefined;
137
144
  if (useHardcodedAccount) {
138
145
  hardcodedAccountData = await EpochsTestContext.getHardcodedAccountData(Fr.random(), Fr.random());
@@ -398,7 +405,7 @@ export class EpochsTestContext {
398
405
  await sleep(waitTime);
399
406
  const [syncState, tips] = await Promise.all([
400
407
  this.context.aztecNode.getWorldStateSyncStatus(),
401
- await this.context.aztecNode.getL2Tips(),
408
+ await this.context.aztecNode.getChainTips(),
402
409
  ]);
403
410
  this.logger.info(`Wait for node synch ${blockNumber} ${type}`, { blockNumber, type, syncState, tips });
404
411
  if (type === 'proven') {
@@ -465,7 +472,7 @@ export class EpochsTestContext {
465
472
  /** Verifies at least one checkpoint has the target number of blocks (for MBPS validation). */
466
473
  public async assertMultipleBlocksPerSlot(targetBlockCount: number) {
467
474
  const archiver = (this.context.aztecNode as AztecNodeService).getBlockSource() as Archiver;
468
- const checkpoints = await archiver.getCheckpoints(CheckpointNumber(1), 50);
475
+ const checkpoints = await archiver.getCheckpoints({ from: CheckpointNumber(1), limit: 50 });
469
476
 
470
477
  this.logger.warn(`Retrieved ${checkpoints.length} checkpoints from archiver`, {
471
478
  checkpoints: checkpoints.map(pc => pc.checkpoint.getStats()),
@@ -497,6 +504,7 @@ export class EpochsTestContext {
497
504
  public watchSequencerEvents(
498
505
  sequencers: SequencerClient[],
499
506
  getMetadata: (i: number) => Record<string, any> = () => ({}),
507
+ additionalFailEventKeys: (keyof SequencerEvents)[] = [],
500
508
  ) {
501
509
  const stateChanges: TrackedSequencerEvent[] = [];
502
510
  const failEvents: TrackedSequencerEvent[] = [];
@@ -507,6 +515,11 @@ export class EpochsTestContext {
507
515
  'block-build-failed',
508
516
  'checkpoint-publish-failed',
509
517
  'proposer-rollup-check-failed',
518
+ 'checkpoint-error',
519
+ 'checkpoint-publish-failed',
520
+ 'header-validation-failed',
521
+ 'pipelined-checkpoint-discarded',
522
+ ...additionalFailEventKeys,
510
523
  ];
511
524
 
512
525
  const makeEvent = (
@@ -536,6 +549,13 @@ export class EpochsTestContext {
536
549
  });
537
550
  failEventsKeys.forEach(eventName => {
538
551
  sequencer.getSequencer().on(eventName, (args: Parameters<SequencerEvents[typeof eventName]>[0]) => {
552
+ // Skip benign block-build-failed events where the builder rejected the block because it
553
+ // could not collect enough valid txs. This is the same "not enough txs" case as
554
+ // block-tx-count-check-failed (which is already excluded above), just detected after we
555
+ // started processing txs rather than before.
556
+ if (eventName === 'block-build-failed' && (args as { reason?: string }).reason === 'Insufficient valid txs') {
557
+ return;
558
+ }
539
559
  const evt = makeEvent(i, eventName, args);
540
560
  failEvents.push(evt);
541
561
  this.logger.error(`Failed event ${eventName} from sequencer ${sequencerIndex}`, undefined, evt);
@@ -545,4 +565,11 @@ export class EpochsTestContext {
545
565
 
546
566
  return { failEvents, stateChanges };
547
567
  }
568
+
569
+ public assertNoFailuresFromSequencers(failEvents: TrackedSequencerEvent[]) {
570
+ if (failEvents.length > 0) {
571
+ this.logger.error(`Failed events from sequencers`, failEvents);
572
+ }
573
+ expect(failEvents).toEqual([]);
574
+ }
548
575
  }
@@ -28,6 +28,7 @@ import {
28
28
  type EndToEndContext,
29
29
  type SetupOptions,
30
30
  deployAccounts,
31
+ ensureAuthRegistryPublished,
31
32
  publicDeployAccounts,
32
33
  setup,
33
34
  teardown,
@@ -84,6 +85,8 @@ export class FeesTest {
84
85
  public getBananaPublicBalanceFn!: BalancesFn;
85
86
  public getBananaPrivateBalanceFn!: BalancesFn;
86
87
  public getProverFee!: (blockNumber: BlockNumber) => Promise<bigint>;
88
+ public getCommittedProverFee!: (blockNumber: BlockNumber) => Promise<bigint>;
89
+ public getCommittedBurn!: (blockNumber: BlockNumber) => Promise<bigint>;
87
90
 
88
91
  public readonly ALICE_INITIAL_BANANAS = BigInt(1e22);
89
92
  public readonly SUBSCRIPTION_AMOUNT = BigInt(1e19);
@@ -102,13 +105,14 @@ export class FeesTest {
102
105
  this.logger = createLogger(`e2e:e2e_fees:${testName}`);
103
106
  }
104
107
 
105
- async setup() {
108
+ async setup(opts: Partial<SetupOptions> = {}) {
106
109
  this.logger.verbose('Setting up fresh context...');
107
110
  // Token allowlist entries are test-only: FPC-based fee payment with custom tokens won't work on mainnet alpha.
108
111
  const tokenAllowList = await getTokenAllowedSetupFunctions();
109
112
  this.context = await setup(0, {
110
113
  startProverNode: true,
111
114
  ...this.setupOptions,
115
+ ...opts,
112
116
  fundSponsoredFPC: true,
113
117
  skipAccountDeployment: true,
114
118
  l1ContractsArgs: { ...this.setupOptions },
@@ -134,7 +138,7 @@ export class FeesTest {
134
138
 
135
139
  async catchUpProvenChain() {
136
140
  const bn = await this.aztecNode.getBlockNumber();
137
- while ((await this.aztecNode.getProvenBlockNumber()) < bn) {
141
+ while ((await this.aztecNode.getBlockNumber('proven')) < bn) {
138
142
  await sleep(1000);
139
143
  }
140
144
  }
@@ -174,11 +178,17 @@ export class FeesTest {
174
178
 
175
179
  public async applyBaseSetup() {
176
180
  await this.applyInitialAccounts();
181
+ await this.applyEnsureAuthRegistryPublished();
177
182
  await this.applyPublicDeployAccounts();
178
183
  await this.applySetupFeeJuice();
179
184
  await this.applyDeployBananaToken();
180
185
  }
181
186
 
187
+ async applyEnsureAuthRegistryPublished() {
188
+ this.logger.info('Ensuring AuthRegistry published');
189
+ await ensureAuthRegistryPublished(this.wallet, this.aliceAddress);
190
+ }
191
+
182
192
  async applyInitialAccounts() {
183
193
  this.logger.info('Applying initial accounts setup');
184
194
 
@@ -302,6 +312,27 @@ export class FeesTest {
302
312
  const mana = block!.header.totalManaUsed.toBigInt();
303
313
  return mulDiv(mana * proverCost, 10n ** 12n, price);
304
314
  };
315
+
316
+ /**
317
+ * Reads the prover fee that the rollup actually committed for the block's checkpoint, which is what
318
+ * RewardLib uses to pay prover rewards. Unlike `getProverFee`, this does not re-derive the value
319
+ * from current L1 fees or current eth-per-fee-asset price, so it is robust to pipelined fee-asset-price
320
+ * drift between propose-time and reward-payout-time.
321
+ */
322
+ this.getCommittedProverFee = async (blockNumber: BlockNumber) => {
323
+ const block = await this.aztecNode.getBlock(blockNumber);
324
+ const feeHeader = await this.rollupContract.getFeeHeader(BigInt(block!.checkpointNumber));
325
+ return feeHeader.manaUsed * feeHeader.proverCost;
326
+ };
327
+
328
+ // RewardLib computes sequencerFee = checkpointFee - burn - proverFee where burn = manaUsed * congestionCost.
329
+ // The fixture's typical case keeps congestionCost at zero, but reading it explicitly avoids latent bugs
330
+ // when test load changes excess mana.
331
+ this.getCommittedBurn = async (blockNumber: BlockNumber) => {
332
+ const block = await this.aztecNode.getBlock(blockNumber);
333
+ const feeHeader = await this.rollupContract.getFeeHeader(BigInt(block!.checkpointNumber));
334
+ return feeHeader.manaUsed * feeHeader.congestionCost;
335
+ };
305
336
  }
306
337
 
307
338
  public async applySponsoredFPCSetup() {
@@ -7,6 +7,7 @@ import { ParentContract } from '@aztec/noir-test-contracts.js/Parent';
7
7
 
8
8
  import {
9
9
  type EndToEndContext,
10
+ type SetupOptions,
10
11
  deployAccounts,
11
12
  publicDeployAccounts,
12
13
  setup,
@@ -50,9 +51,10 @@ export class NestedContractTest {
50
51
  await publicDeployAccounts(this.wallet, [this.defaultAccountAddress]);
51
52
  }
52
53
 
53
- async setup() {
54
+ async setup(opts: Partial<SetupOptions> = {}) {
54
55
  this.logger.info('Setting up fresh subsystems');
55
56
  this.context = await setup(0, {
57
+ ...opts,
56
58
  fundSponsoredFPC: true,
57
59
  skipAccountDeployment: true,
58
60
  });
@@ -58,6 +58,7 @@ export class P2PInactivityTest {
58
58
  basePort: BOOT_NODE_UDP_PORT,
59
59
  startProverNode: true,
60
60
  initialConfig: {
61
+ inboxLag: 2,
61
62
  anvilSlotsInAnEpoch: 4,
62
63
  proverNodeConfig: { proverNodeEpochProvingDelayMs: AZTEC_SLOT_DURATION * 1000 },
63
64
  aztecTargetCommitteeSize: COMMITTEE_SIZE,
@@ -2,6 +2,7 @@ import type { AztecNodeService } from '@aztec/aztec-node';
2
2
  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
+ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '@aztec/epoch-cache';
5
6
  import { RollupContract } from '@aztec/ethereum/contracts';
6
7
  import { CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
7
8
  import { timesAsync } from '@aztec/foundation/collection';
@@ -14,7 +15,7 @@ import path from 'path';
14
15
 
15
16
  import { getBootNodeUdpPort, shouldCollectMetrics } from '../../fixtures/fixtures.js';
16
17
  import { createNodes } from '../../fixtures/setup_p2p_test.js';
17
- import { P2PNetworkTest, WAIT_FOR_TX_TIMEOUT } from '../p2p_network.js';
18
+ import { P2PNetworkTest } from '../p2p_network.js';
18
19
  import { prepareTransactions } from '../shared.js';
19
20
 
20
21
  // Don't set this to a higher value than 9 because each node will use a different L1 publisher account and anvil seeds
@@ -49,6 +50,9 @@ export async function createReqrespTest(options: ReqrespOptions = {}): Promise<P
49
50
  ...(disableStatusHandshake ? { p2pDisableStatusHandshake: true } : {}),
50
51
  listenAddress: '127.0.0.1',
51
52
  aztecEpochDuration: 64, // stable committee
53
+ // Pipelining: target-slot is one ahead of build-slot; inboxLag sources L1->L2
54
+ // messages from the previous checkpoint to avoid L1ToL2MessagesNotReadyError.
55
+ inboxLag: 2,
52
56
  },
53
57
  });
54
58
  await t.setup();
@@ -125,7 +129,15 @@ export async function runReqrespTxTest(params: {
125
129
  t.ctx.dateProvider.setTime(Number(timestamp) * 1000);
126
130
  const startSlotTimestamp = BigInt(timestamp);
127
131
 
128
- const { proposerIndexes, nodesToTurnOffTxGossip } = await getProposerIndexes(t, startSlotTimestamp);
132
+ // Under pipelining the active builder during wallclock slot S targets slot S+1, so
133
+ // we must address the proposer of S+1 (not S) for batch 0. Shift the proposer lookup
134
+ // window by the pipelining offset so we always send to the currently-building proposer.
135
+ const proposerSlotOffset = PROPOSER_PIPELINING_SLOT_OFFSET;
136
+ const { proposerIndexes, nodesToTurnOffTxGossip } = await getProposerIndexes(
137
+ t,
138
+ startSlotTimestamp,
139
+ proposerSlotOffset,
140
+ );
129
141
  t.logger.info(`Turning off tx gossip for nodes: ${nodesToTurnOffTxGossip.map(getNodePort)}`);
130
142
  t.logger.info(`Sending txs to proposer nodes: ${proposerIndexes.map(getNodePort)}`);
131
143
 
@@ -176,12 +188,17 @@ export async function runReqrespTxTest(params: {
176
188
  t.logger.info(`Node ${getNodePort(i)} pool has ${count} pending txs`);
177
189
  }
178
190
 
191
+ // Use the test's own aztecSlotDuration (not the env default that p2p_network's
192
+ // WAIT_FOR_TX_TIMEOUT is derived from) so the timeout scales with this test's 36s slot.
193
+ // Under pipelining the round-trip is roughly build-slot + target-slot + L1 publish, so
194
+ // budget for >= 3 slots.
195
+ const waitForTxTimeout = t.ctx.aztecNodeConfig.aztecSlotDuration * 4.5;
179
196
  t.logger.info('Waiting for all transactions to be mined');
180
197
  await Promise.all(
181
198
  submittedTxs.flatMap((batch, batchIndex) =>
182
199
  batch.map(async (submittedTx, txIndex) => {
183
200
  t.logger.info(`Waiting for tx ${batchIndex}-${txIndex} ${submittedTx.txHash.toString()} to be mined`);
184
- await waitForTx(submittedTx.node, submittedTx.txHash, { timeout: WAIT_FOR_TX_TIMEOUT * 1.5 });
201
+ await waitForTx(submittedTx.node, submittedTx.txHash, { timeout: waitForTxTimeout });
185
202
  t.logger.info(`Tx ${batchIndex}-${txIndex} ${submittedTx.txHash.toString()} has been mined`);
186
203
  }),
187
204
  ),
@@ -194,8 +211,8 @@ export async function runReqrespTxTest(params: {
194
211
  // Wait for L1 checkpoint sync, which may lag behind P2P block propagation.
195
212
  const checkpoints = await retryUntil(
196
213
  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;
214
+ const cps = await nodes[0].getCheckpoints(CheckpointNumber(1), 50, { includeBlocks: true });
215
+ return cps.length > 0 && cps.some(cp => (cp.blocks?.length ?? 0) >= 2) ? cps : undefined;
199
216
  },
200
217
  'waiting for multi-block checkpoint to sync from L1',
201
218
  30,
@@ -203,16 +220,17 @@ export async function runReqrespTxTest(params: {
203
220
  );
204
221
 
205
222
  let mbpsFound = false;
206
- let expectedBlockNumber = checkpoints[0].checkpoint.blocks[0].number;
223
+ let expectedBlockNumber = checkpoints[0].blocks![0].number;
207
224
 
208
225
  for (const published of checkpoints) {
209
- const blockCount = published.checkpoint.blocks.length;
226
+ const blocks = published.blocks!;
227
+ const blockCount = blocks.length;
210
228
  mbpsFound = mbpsFound || blockCount >= 2;
211
229
 
212
230
  for (let i = 0; i < blockCount; i++) {
213
- const block = published.checkpoint.blocks[i];
231
+ const block = blocks[i];
214
232
  expect(block.indexWithinCheckpoint).toBe(i);
215
- expect(block.checkpointNumber).toBe(published.checkpoint.number);
233
+ expect(block.checkpointNumber).toBe(published.number);
216
234
  expect(block.number).toBe(expectedBlockNumber);
217
235
  expectedBlockNumber++;
218
236
  }
@@ -222,7 +240,7 @@ export async function runReqrespTxTest(params: {
222
240
  return nodes;
223
241
  }
224
242
 
225
- async function getProposerIndexes(t: P2PNetworkTest, startSlotTimestamp: bigint) {
243
+ async function getProposerIndexes(t: P2PNetworkTest, startSlotTimestamp: bigint, slotOffset = 0) {
226
244
  // Get the nodes for the next set of slots
227
245
  const rollupContract = new RollupContract(
228
246
  t.ctx.deployL1ContractsValues.l1Client,
@@ -234,7 +252,7 @@ async function getProposerIndexes(t: P2PNetworkTest, startSlotTimestamp: bigint)
234
252
 
235
253
  const proposers = await Promise.all(
236
254
  Array.from({ length: 3 }, async (_, i) => {
237
- const slot = SlotNumber(startSlot + i);
255
+ const slot = SlotNumber(startSlot + slotOffset + i);
238
256
  const slotTimestamp = await rollupContract.getTimestampForSlot(slot);
239
257
  return await rollupContract.getProposerAt(slotTimestamp);
240
258
  }),