@aztec/end-to-end 0.0.1-commit.934299a21 → 0.0.1-commit.949a33fd8

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 (149) 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 -28
  5. package/dest/bench/utils.d.ts +1 -1
  6. package/dest/bench/utils.d.ts.map +1 -1
  7. package/dest/bench/utils.js +6 -3
  8. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +3 -2
  9. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  10. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +15 -15
  11. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +1 -1
  12. package/dest/e2e_epochs/epochs_test.d.ts +18 -1
  13. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  14. package/dest/e2e_epochs/epochs_test.js +61 -10
  15. package/dest/e2e_fees/fees_test.d.ts +1 -1
  16. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  17. package/dest/e2e_fees/fees_test.js +16 -9
  18. package/dest/e2e_nested_contract/nested_contract_test.d.ts +1 -1
  19. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
  20. package/dest/e2e_nested_contract/nested_contract_test.js +4 -6
  21. package/dest/e2e_p2p/inactivity_slash_test.js +3 -3
  22. package/dest/e2e_p2p/p2p_network.d.ts +13 -11
  23. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  24. package/dest/e2e_p2p/p2p_network.js +65 -43
  25. package/dest/e2e_p2p/reqresp/utils.d.ts +1 -1
  26. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  27. package/dest/e2e_p2p/reqresp/utils.js +23 -7
  28. package/dest/e2e_p2p/shared.d.ts +25 -7
  29. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  30. package/dest/e2e_p2p/shared.js +69 -49
  31. package/dest/e2e_token_contract/token_contract_test.d.ts +1 -1
  32. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
  33. package/dest/e2e_token_contract/token_contract_test.js +11 -11
  34. package/dest/fixtures/authwit_proxy.d.ts +3 -3
  35. package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
  36. package/dest/fixtures/authwit_proxy.js +4 -0
  37. package/dest/fixtures/e2e_prover_test.d.ts +4 -3
  38. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  39. package/dest/fixtures/e2e_prover_test.js +11 -16
  40. package/dest/fixtures/fixtures.d.ts +12 -1
  41. package/dest/fixtures/fixtures.d.ts.map +1 -1
  42. package/dest/fixtures/fixtures.js +10 -0
  43. package/dest/fixtures/get_bb_config.d.ts +1 -1
  44. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  45. package/dest/fixtures/get_bb_config.js +5 -5
  46. package/dest/fixtures/ha_setup.d.ts +2 -2
  47. package/dest/fixtures/ha_setup.d.ts.map +1 -1
  48. package/dest/fixtures/ha_setup.js +1 -1
  49. package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts +25 -0
  50. package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts.map +1 -0
  51. package/dest/fixtures/schnorr_hardcoded_account_contract.js +39 -0
  52. package/dest/fixtures/setup.d.ts +24 -13
  53. package/dest/fixtures/setup.d.ts.map +1 -1
  54. package/dest/fixtures/setup.js +45 -25
  55. package/dest/fixtures/setup_p2p_test.d.ts +6 -6
  56. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  57. package/dest/fixtures/setup_p2p_test.js +8 -8
  58. package/dest/fixtures/token_utils.d.ts +1 -1
  59. package/dest/fixtures/token_utils.d.ts.map +1 -1
  60. package/dest/fixtures/token_utils.js +2 -5
  61. package/dest/forward-compatibility/wallet_rpc_client.d.ts +7 -0
  62. package/dest/forward-compatibility/wallet_rpc_client.d.ts.map +1 -0
  63. package/dest/forward-compatibility/wallet_rpc_client.js +15 -0
  64. package/dest/forward-compatibility/wallet_service.d.ts +3 -0
  65. package/dest/forward-compatibility/wallet_service.d.ts.map +1 -0
  66. package/dest/forward-compatibility/wallet_service.js +109 -0
  67. package/dest/legacy-jest-resolver.d.cts +3 -0
  68. package/dest/legacy-jest-resolver.d.cts.map +1 -0
  69. package/dest/shared/cross_chain_test_harness.d.ts +1 -1
  70. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
  71. package/dest/shared/cross_chain_test_harness.js +13 -13
  72. package/dest/shared/gas_portal_test_harness.js +3 -3
  73. package/dest/shared/jest_setup.js +32 -1
  74. package/dest/shared/submit-transactions.d.ts +1 -1
  75. package/dest/shared/submit-transactions.d.ts.map +1 -1
  76. package/dest/shared/submit-transactions.js +1 -1
  77. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  78. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  79. package/dest/shared/uniswap_l1_l2.js +14 -21
  80. package/dest/simulators/lending_simulator.d.ts +1 -1
  81. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  82. package/dest/simulators/lending_simulator.js +4 -4
  83. package/dest/simulators/token_simulator.d.ts +1 -1
  84. package/dest/simulators/token_simulator.d.ts.map +1 -1
  85. package/dest/simulators/token_simulator.js +2 -2
  86. package/dest/spartan/setup_test_wallets.d.ts +4 -2
  87. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  88. package/dest/spartan/setup_test_wallets.js +69 -38
  89. package/dest/spartan/tx_metrics.d.ts +1 -1
  90. package/dest/spartan/tx_metrics.d.ts.map +1 -1
  91. package/dest/spartan/tx_metrics.js +19 -3
  92. package/dest/spartan/utils/config.d.ts +7 -1
  93. package/dest/spartan/utils/config.d.ts.map +1 -1
  94. package/dest/spartan/utils/config.js +3 -1
  95. package/dest/spartan/utils/index.d.ts +3 -1
  96. package/dest/spartan/utils/index.d.ts.map +1 -1
  97. package/dest/spartan/utils/index.js +4 -0
  98. package/dest/spartan/utils/nodes.js +1 -1
  99. package/dest/spartan/utils/pod_logs.d.ts +25 -0
  100. package/dest/spartan/utils/pod_logs.d.ts.map +1 -0
  101. package/dest/spartan/utils/pod_logs.js +74 -0
  102. package/dest/test-wallet/test_wallet.d.ts +24 -23
  103. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  104. package/dest/test-wallet/test_wallet.js +124 -83
  105. package/dest/test-wallet/worker_wallet.d.ts +4 -4
  106. package/dest/test-wallet/worker_wallet.d.ts.map +1 -1
  107. package/dest/test-wallet/worker_wallet_schema.d.ts +10 -5
  108. package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -1
  109. package/package.json +43 -44
  110. package/src/bench/client_flows/client_flows_benchmark.ts +29 -12
  111. package/src/bench/utils.ts +7 -2
  112. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +21 -20
  113. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +1 -1
  114. package/src/e2e_epochs/epochs_test.ts +70 -9
  115. package/src/e2e_fees/fees_test.ts +17 -8
  116. package/src/e2e_nested_contract/nested_contract_test.ts +6 -4
  117. package/src/e2e_p2p/inactivity_slash_test.ts +3 -3
  118. package/src/e2e_p2p/p2p_network.ts +82 -60
  119. package/src/e2e_p2p/reqresp/utils.ts +29 -7
  120. package/src/e2e_p2p/shared.ts +88 -63
  121. package/src/e2e_token_contract/token_contract_test.ts +16 -8
  122. package/src/fixtures/authwit_proxy.ts +4 -0
  123. package/src/fixtures/e2e_prover_test.ts +19 -18
  124. package/src/fixtures/fixtures.ts +22 -0
  125. package/src/fixtures/get_bb_config.ts +7 -6
  126. package/src/fixtures/ha_setup.ts +4 -2
  127. package/src/fixtures/schnorr_hardcoded_account_contract.ts +49 -0
  128. package/src/fixtures/setup.ts +69 -33
  129. package/src/fixtures/setup_p2p_test.ts +9 -9
  130. package/src/fixtures/token_utils.ts +1 -2
  131. package/src/forward-compatibility/wallet_rpc_client.ts +14 -0
  132. package/src/forward-compatibility/wallet_service.ts +104 -0
  133. package/src/guides/up_quick_start.sh +0 -2
  134. package/src/legacy-jest-resolver.cjs +135 -0
  135. package/src/shared/cross_chain_test_harness.ts +13 -9
  136. package/src/shared/gas_portal_test_harness.ts +1 -2
  137. package/src/shared/jest_setup.ts +36 -1
  138. package/src/shared/submit-transactions.ts +1 -4
  139. package/src/shared/uniswap_l1_l2.ts +35 -32
  140. package/src/simulators/lending_simulator.ts +8 -4
  141. package/src/simulators/token_simulator.ts +6 -2
  142. package/src/spartan/setup_test_wallets.ts +90 -35
  143. package/src/spartan/tx_metrics.ts +17 -5
  144. package/src/spartan/utils/config.ts +2 -0
  145. package/src/spartan/utils/index.ts +6 -0
  146. package/src/spartan/utils/nodes.ts +1 -1
  147. package/src/spartan/utils/pod_logs.ts +99 -0
  148. package/src/test-wallet/test_wallet.ts +152 -101
  149. package/src/test-wallet/worker_wallet.ts +3 -2
@@ -6,12 +6,9 @@ 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 {
10
- EmpireSlashingProposerContract,
11
- RollupContract,
12
- TallySlashingProposerContract,
13
- } from '@aztec/ethereum/contracts';
14
- import { EpochNumber } from '@aztec/foundation/branded-types';
9
+ import type { EpochCacheInterface } from '@aztec/epoch-cache';
10
+ import type { RollupContract, SlashingProposerContract } from '@aztec/ethereum/contracts';
11
+ import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
15
12
  import { timesAsync, unique } from '@aztec/foundation/collection';
16
13
  import { EthAddress } from '@aztec/foundation/eth-address';
17
14
  import { retryUntil } from '@aztec/foundation/retry';
@@ -21,8 +18,8 @@ import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.j
21
18
  import { getPXEConfig, getPXEConfig as getRpcConfig } from '@aztec/pxe/server';
22
19
  import { getRoundForOffense } from '@aztec/slasher';
23
20
  import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
24
- import type { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
25
21
 
22
+ import { SchnorrHardcodedKeyAccountContract } from '../fixtures/schnorr_hardcoded_account_contract.js';
26
23
  import { submitTxsTo } from '../shared/submit-transactions.js';
27
24
  import { TestWallet } from '../test-wallet/test_wallet.js';
28
25
  import { type ProvenTx, proveInteraction } from '../test-wallet/utils.js';
@@ -41,7 +38,7 @@ export const submitComplexTxsTo = async (
41
38
  const spamCount = 15;
42
39
  for (let i = 0; i < numTxs; i++) {
43
40
  const method = spamContract.methods.spam(seed + BigInt(i * spamCount), spamCount, !!opts.callPublic);
44
- const txHash = await method.send({ from, wait: NO_WAIT });
41
+ const { txHash } = await method.send({ from, wait: NO_WAIT });
45
42
  logger.info(`Tx sent with hash ${txHash.toString()}`);
46
43
  txs.push(txHash);
47
44
  }
@@ -59,10 +56,17 @@ export const submitTransactions = async (
59
56
  rpcConfig.proverEnabled = false;
60
57
  const wallet = await TestWallet.create(
61
58
  node,
62
- { ...getPXEConfig(), proverEnabled: false },
59
+ // Use checkpointed chain tip to avoid anchoring on provisional blocks that the archiver can prune
60
+ // when their slot ends without a checkpoint landing on L1.
61
+ { ...getPXEConfig(), proverEnabled: false, syncChainTip: 'checkpointed' },
63
62
  { loggerActorLabel: 'pxe-tx' },
64
63
  );
65
- const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
64
+ const contract = new SchnorrHardcodedKeyAccountContract();
65
+ const fundedAccountManager = await wallet.createAccount({
66
+ secret: fundedAccount.secret,
67
+ salt: fundedAccount.salt,
68
+ contract,
69
+ });
66
70
  return submitTxsTo(wallet, fundedAccountManager.address, numTxs, logger);
67
71
  };
68
72
 
@@ -77,10 +81,15 @@ export async function prepareTransactions(
77
81
 
78
82
  const wallet = await TestWallet.create(
79
83
  node,
80
- { ...getPXEConfig(), proverEnabled: false },
84
+ { ...getPXEConfig(), proverEnabled: false, syncChainTip: 'checkpointed' },
81
85
  { loggerActorLabel: 'pxe-tx' },
82
86
  );
83
- const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
87
+ const accountContract = new SchnorrHardcodedKeyAccountContract();
88
+ const fundedAccountManager = await wallet.createAccount({
89
+ secret: fundedAccount.secret,
90
+ salt: fundedAccount.salt,
91
+ contract: accountContract,
92
+ });
84
93
 
85
94
  const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {
86
95
  salt: Fr.random(),
@@ -98,7 +107,7 @@ export async function prepareTransactions(
98
107
  }
99
108
 
100
109
  export function awaitProposalExecution(
101
- slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract,
110
+ slashingProposer: SlashingProposerContract,
102
111
  timeoutSeconds: number,
103
112
  logger: Logger,
104
113
  ): Promise<bigint> {
@@ -108,24 +117,12 @@ export function awaitProposalExecution(
108
117
  reject(new Error(`Timeout waiting for proposal execution after ${timeoutSeconds}s`));
109
118
  }, timeoutSeconds * 1000);
110
119
 
111
- if (slashingProposer.type === 'empire') {
112
- const unwatch = slashingProposer.listenToPayloadSubmitted(args => {
113
- logger.warn(`Proposal ${args.payload} from round ${args.round} executed`);
114
- clearTimeout(timeout);
115
- unwatch();
116
- resolve(args.round);
117
- });
118
- } else if (slashingProposer.type === 'tally') {
119
- const unwatch = slashingProposer.listenToRoundExecuted(args => {
120
- logger.warn(`Slash from round ${args.round} executed`);
121
- clearTimeout(timeout);
122
- unwatch();
123
- resolve(args.round);
124
- });
125
- } else {
120
+ const unwatch = slashingProposer.listenToRoundExecuted(args => {
121
+ logger.warn(`Slash from round ${args.round} executed`);
126
122
  clearTimeout(timeout);
127
- reject(new Error(`Unknown slashing proposer type: ${(slashingProposer as any).type}`));
128
- }
123
+ unwatch();
124
+ resolve(args.round);
125
+ });
129
126
  });
130
127
  }
131
128
 
@@ -150,6 +147,58 @@ export async function awaitCommitteeExists({
150
147
  return committee!.map(c => c.toString() as `0x${string}`);
151
148
  }
152
149
 
150
+ /**
151
+ * Advance epochs until we find one where the target proposer is selected for at least one slot,
152
+ * then stop one epoch before it. This leaves time for the caller to start sequencers before
153
+ * warping to the target epoch, avoiding the race where the target epoch passes before sequencers
154
+ * are ready.
155
+ *
156
+ * Returns the target epoch number so the caller can warp to it after starting sequencers.
157
+ */
158
+ export async function advanceToEpochBeforeProposer({
159
+ epochCache,
160
+ cheatCodes,
161
+ targetProposer,
162
+ logger,
163
+ maxAttempts = 20,
164
+ }: {
165
+ epochCache: EpochCacheInterface;
166
+ cheatCodes: RollupCheatCodes;
167
+ targetProposer: EthAddress;
168
+ logger: Logger;
169
+ maxAttempts?: number;
170
+ }): Promise<{ targetEpoch: EpochNumber }> {
171
+ const { epochDuration } = await cheatCodes.getConfig();
172
+
173
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
174
+ const currentEpoch = await cheatCodes.getEpoch();
175
+ // Check the NEXT epoch's slots so we stay one epoch before the target,
176
+ // giving the caller time to start sequencers before the target epoch arrives.
177
+ const nextEpoch = Number(currentEpoch) + 1;
178
+ const startSlot = nextEpoch * Number(epochDuration);
179
+ const endSlot = startSlot + Number(epochDuration);
180
+
181
+ logger.info(
182
+ `Checking next epoch ${nextEpoch} (slots ${startSlot}-${endSlot - 1}) for proposer ${targetProposer} (current epoch: ${currentEpoch})`,
183
+ );
184
+
185
+ for (let s = startSlot; s < endSlot; s++) {
186
+ const proposer = await epochCache.getProposerAttesterAddressInSlot(SlotNumber(s));
187
+ if (proposer && proposer.equals(targetProposer)) {
188
+ logger.warn(
189
+ `Found target proposer ${targetProposer} in slot ${s} of epoch ${nextEpoch}. Staying at epoch ${currentEpoch} to allow sequencer startup.`,
190
+ );
191
+ return { targetEpoch: EpochNumber(nextEpoch) };
192
+ }
193
+ }
194
+
195
+ logger.info(`Target proposer not found in epoch ${nextEpoch}, advancing to next epoch`);
196
+ await cheatCodes.advanceToNextEpoch();
197
+ }
198
+
199
+ throw new Error(`Target proposer ${targetProposer} not found in any slot after ${maxAttempts} epoch attempts`);
200
+ }
201
+
153
202
  export async function awaitOffenseDetected({
154
203
  logger,
155
204
  nodeAdmin,
@@ -192,7 +241,6 @@ export async function awaitCommitteeKicked({
192
241
  rollup,
193
242
  cheatCodes,
194
243
  committee,
195
- slashFactory,
196
244
  slashingProposer,
197
245
  slashingRoundSize,
198
246
  aztecSlotDuration,
@@ -203,8 +251,7 @@ export async function awaitCommitteeKicked({
203
251
  rollup: RollupContract;
204
252
  cheatCodes: RollupCheatCodes;
205
253
  committee: readonly `0x${string}`[];
206
- slashFactory: SlashFactoryContract;
207
- slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
254
+ slashingProposer: SlashingProposerContract | undefined;
208
255
  slashingRoundSize: number;
209
256
  aztecSlotDuration: number;
210
257
  aztecEpochDuration: number;
@@ -217,36 +264,14 @@ export async function awaitCommitteeKicked({
217
264
 
218
265
  await cheatCodes.debugRollup();
219
266
 
220
- if (slashingProposer.type === 'empire') {
221
- // Await for the slash payload to be created if empire (no payload is created on tally until execution time)
222
- const targetEpoch = EpochNumber((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochsForValidatorSet()) + 1);
223
- logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
224
- await cheatCodes.advanceToEpoch(targetEpoch);
225
-
226
- const slashPayloadEvents = await retryUntil(
227
- async () => {
228
- const events = await slashFactory.getSlashPayloadCreatedEvents();
229
- return events.length > 0 ? events : undefined;
230
- },
231
- 'slash payload created',
232
- 120,
233
- 1,
234
- );
235
- expect(slashPayloadEvents.length).toBe(1);
236
- // 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)
237
- expect(unique(slashPayloadEvents[0].slashes.map(slash => slash.validator.toString()))).toHaveLength(
238
- committee.length,
239
- );
240
- } else {
241
- // Use the slash offset to ensure we are in the right epoch for tally
242
- const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
243
- const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
244
- const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
245
- const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
246
- const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
247
- logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
248
- await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
249
- }
267
+ // Use the slash offset to ensure we are in the right epoch for tally
268
+ const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
269
+ const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
270
+ const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
271
+ const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
272
+ const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
273
+ logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
274
+ await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
250
275
 
251
276
  const attestersPre = await rollup.getAttesters();
252
277
  expect(attestersPre.length).toBe(committee.length);
@@ -81,24 +81,28 @@ export class TokenContractTest {
81
81
  await publicDeployAccounts(this.wallet, [this.adminAddress, this.account1Address]);
82
82
 
83
83
  this.logger.verbose(`Deploying TokenContract...`);
84
- this.asset = await TokenContract.deploy(
84
+ ({ contract: this.asset } = await TokenContract.deploy(
85
85
  this.wallet,
86
86
  this.adminAddress,
87
87
  TokenContractTest.TOKEN_NAME,
88
88
  TokenContractTest.TOKEN_SYMBOL,
89
89
  TokenContractTest.TOKEN_DECIMALS,
90
- ).send({ from: this.adminAddress });
90
+ ).send({ from: this.adminAddress }));
91
91
  this.logger.verbose(`Token deployed to ${this.asset.address}`);
92
92
 
93
93
  this.logger.verbose(`Deploying bad account...`);
94
- this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress });
94
+ ({ contract: this.badAccount } = await InvalidAccountContract.deploy(this.wallet).send({
95
+ from: this.adminAddress,
96
+ }));
95
97
  this.logger.verbose(`Deployed to ${this.badAccount.address}.`);
96
98
 
97
99
  // Deploy a proxy contract for "on behalf of other" tests. The note owner must be the tx sender
98
100
  // (so their notes are in scope), but msg_sender in the target must differ from the note owner
99
101
  // to trigger authwit validation. The proxy forwards calls so that msg_sender != tx sender.
100
102
  this.logger.verbose(`Deploying generic proxy...`);
101
- this.authwitProxy = await GenericProxyContract.deploy(this.wallet).send({ from: this.adminAddress });
103
+ ({ contract: this.authwitProxy } = await GenericProxyContract.deploy(this.wallet).send({
104
+ from: this.adminAddress,
105
+ }));
102
106
  this.logger.verbose(`Deployed to ${this.authwitProxy.address}.`);
103
107
 
104
108
  this.tokenSim = new TokenSimulator(this.asset, this.wallet, this.adminAddress, this.logger, [
@@ -106,7 +110,7 @@ export class TokenContractTest {
106
110
  this.account1Address,
107
111
  ]);
108
112
 
109
- expect(await this.asset.methods.get_admin().simulate({ from: this.adminAddress })).toBe(
113
+ expect((await this.asset.methods.get_admin().simulate({ from: this.adminAddress })).result).toBe(
110
114
  this.adminAddress.toBigInt(),
111
115
  );
112
116
  }
@@ -140,7 +144,9 @@ export class TokenContractTest {
140
144
  await asset.methods.mint_to_public(adminAddress, amount).send({ from: adminAddress });
141
145
  tokenSim.mintPublic(adminAddress, amount);
142
146
 
143
- const publicBalance = await asset.methods.balance_of_public(adminAddress).simulate({ from: adminAddress });
147
+ const { result: publicBalance } = await asset.methods
148
+ .balance_of_public(adminAddress)
149
+ .simulate({ from: adminAddress });
144
150
  this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`);
145
151
  expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(adminAddress));
146
152
 
@@ -148,11 +154,13 @@ export class TokenContractTest {
148
154
  await mintTokensToPrivate(asset, adminAddress, adminAddress, amount);
149
155
  tokenSim.mintPrivate(adminAddress, amount);
150
156
 
151
- const privateBalance = await asset.methods.balance_of_private(adminAddress).simulate({ from: adminAddress });
157
+ const { result: privateBalance } = await asset.methods
158
+ .balance_of_private(adminAddress)
159
+ .simulate({ from: adminAddress });
152
160
  this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
153
161
  expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(adminAddress));
154
162
 
155
- const totalSupply = await asset.methods.total_supply().simulate({ from: adminAddress });
163
+ const { result: totalSupply } = await asset.methods.total_supply().simulate({ from: adminAddress });
156
164
  this.logger.verbose(`Total supply: ${totalSupply}`);
157
165
  expect(totalSupply).toEqual(tokenSim.totalSupply);
158
166
 
@@ -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;
@@ -112,7 +110,7 @@ export class FullProverTest {
112
110
  FullProverTest.TOKEN_NAME,
113
111
  FullProverTest.TOKEN_SYMBOL,
114
112
  FullProverTest.TOKEN_DECIMALS,
115
- ).send({ from: this.accounts[0], wait: { returnReceipt: true } });
113
+ ).send({ from: this.accounts[0] });
116
114
  this.logger.verbose(`Token deployed to ${asset.address}`);
117
115
 
118
116
  this.fakeProofsAsset = asset;
@@ -121,7 +119,7 @@ export class FullProverTest {
121
119
 
122
120
  this.tokenSim = new TokenSimulator(this.fakeProofsAsset, this.wallet, this.accounts[0], this.logger, this.accounts);
123
121
 
124
- expect(await this.fakeProofsAsset.methods.get_admin().simulate({ from: this.accounts[0] })).toBe(
122
+ expect((await this.fakeProofsAsset.methods.get_admin().simulate({ from: this.accounts[0] })).result).toBe(
125
123
  this.accounts[0].toBigInt(),
126
124
  );
127
125
  }
@@ -168,9 +166,6 @@ export class FullProverTest {
168
166
 
169
167
  await Barretenberg.initSingleton({ backend: BackendType.NativeUnixSocket });
170
168
 
171
- const verifier = await BBCircuitVerifier.new(bbConfig);
172
- this.circuitProofVerifier = new QueuedIVCVerifier(bbConfig, verifier);
173
-
174
169
  this.logger.debug(`Configuring the node for real proofs...`);
175
170
  await this.aztecNodeAdmin.setConfig({
176
171
  realProofs: true,
@@ -178,7 +173,6 @@ export class FullProverTest {
178
173
  });
179
174
  } else {
180
175
  this.logger.debug(`Configuring the node min txs per block ${this.minNumberOfTxsPerBlock}...`);
181
- this.circuitProofVerifier = new TestCircuitVerifier();
182
176
  await this.aztecNodeAdmin.setConfig({
183
177
  minTxsPerBlock: this.minNumberOfTxsPerBlock,
184
178
  });
@@ -229,8 +223,11 @@ export class FullProverTest {
229
223
 
230
224
  this.logger.verbose('Starting prover node');
231
225
  const sponsoredFPCAddress = await getSponsoredFPCAddress();
232
- const { prefilledPublicData } = await getGenesisValues(
226
+ const { genesis } = await getGenesisValues(
233
227
  this.context.initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress),
228
+ undefined,
229
+ undefined,
230
+ this.context.genesis!.genesisTimestamp,
234
231
  );
235
232
 
236
233
  const proverNodeConfig: Parameters<typeof AztecNodeService.createAndSync>[0] = {
@@ -258,7 +255,7 @@ export class FullProverTest {
258
255
  this.proverAztecNode = await AztecNodeService.createAndSync(
259
256
  proverNodeConfig,
260
257
  { dateProvider: this.context.dateProvider, p2pClientDeps: { rpcTxProviders: [this.aztecNode] } },
261
- { prefilledPublicData },
258
+ { genesis },
262
259
  );
263
260
  this.logger.warn(`Proofs are now enabled`, { realProofs: this.realProofs });
264
261
  return this;
@@ -310,16 +307,20 @@ export class FullProverTest {
310
307
  } = this;
311
308
  tokenSim.mintPublic(address, publicAmount);
312
309
 
313
- const publicBalance = await fakeProofsAsset.methods.balance_of_public(address).simulate({ from: address });
310
+ const { result: publicBalance } = await fakeProofsAsset.methods
311
+ .balance_of_public(address)
312
+ .simulate({ from: address });
314
313
  this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`);
315
314
  expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(address));
316
315
 
317
316
  tokenSim.mintPrivate(address, publicAmount);
318
- const privateBalance = await fakeProofsAsset.methods.balance_of_private(address).simulate({ from: address });
317
+ const { result: privateBalance } = await fakeProofsAsset.methods
318
+ .balance_of_private(address)
319
+ .simulate({ from: address });
319
320
  this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
320
321
  expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(address));
321
322
 
322
- const totalSupply = await fakeProofsAsset.methods.total_supply().simulate({ from: address });
323
+ const { result: totalSupply } = await fakeProofsAsset.methods.total_supply().simulate({ from: address });
323
324
  this.logger.verbose(`Total supply: ${totalSupply}`);
324
325
  expect(totalSupply).toEqual(tokenSim.totalSupply);
325
326
  }
@@ -1,5 +1,27 @@
1
+ import type { AztecNode } from '@aztec/aztec.js/node';
2
+ import type { GasFees } from '@aztec/stdlib/gas';
3
+
1
4
  export const METRICS_PORT = 4318;
2
5
 
6
+ /** Default fee padding applied to predicted min fees in e2e tests. */
7
+ export const DEFAULT_MIN_FEE_PADDING = 5;
8
+
9
+ /**
10
+ * Large fee padding for txs that may be mined significantly later than when they were created,
11
+ * such as cloned txs in throughput/capacity benchmarks, where fees may spike between creation and mining.
12
+ */
13
+ export const LARGE_MIN_FEE_PADDING = 15;
14
+
15
+ /** Returns worst-case predicted min fees with padding applied, mirroring the BaseWallet pattern. */
16
+ export async function getPaddedMaxFeesPerGas(node: AztecNode, padding = DEFAULT_MIN_FEE_PADDING): Promise<GasFees> {
17
+ const predicted = await node.getPredictedMinFees();
18
+ const worstCase =
19
+ predicted.length > 0
20
+ ? predicted.reduce((worst, fees) => (fees.feePerL2Gas > worst.feePerL2Gas ? fees : worst))
21
+ : await node.getCurrentMinFees();
22
+ return worstCase.mul(1 + padding);
23
+ }
24
+
3
25
  export const shouldCollectMetrics = () => {
4
26
  if (process.env.COLLECT_METRICS) {
5
27
  return METRICS_PORT;
@@ -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}`);
@@ -11,7 +11,7 @@ import { privateKeyToAccount } from 'viem/accounts';
11
11
  */
12
12
  export interface HADatabaseConfig {
13
13
  /** PostgreSQL connection URL */
14
- databaseUrl: string;
14
+ databaseUrl: SecretValue<string>;
15
15
  /** Node ID for HA coordination */
16
16
  nodeId: string;
17
17
  /** Enable HA signing */
@@ -28,7 +28,9 @@ export interface HADatabaseConfig {
28
28
  * Get database configuration from environment variables
29
29
  */
30
30
  export function createHADatabaseConfig(nodeId: string): HADatabaseConfig {
31
- const databaseUrl = process.env.DATABASE_URL || 'postgresql://aztec:aztec@localhost:5432/aztec_ha_test';
31
+ const databaseUrl = new SecretValue(
32
+ process.env.DATABASE_URL || 'postgresql://aztec:aztec@localhost:5432/aztec_ha_test',
33
+ );
32
34
 
33
35
  return {
34
36
  databaseUrl,
@@ -0,0 +1,49 @@
1
+ import { DefaultAccountContract } from '@aztec/accounts/defaults';
2
+ import type { ContractArtifact } from '@aztec/aztec.js/abi';
3
+ import type { AuthWitnessProvider } from '@aztec/aztec.js/account';
4
+ import type { CompleteAddress } from '@aztec/aztec.js/addresses';
5
+ import { AuthWitness } from '@aztec/aztec.js/authorization';
6
+ import type { Fr } from '@aztec/aztec.js/fields';
7
+ import { Schnorr } from '@aztec/foundation/crypto/schnorr';
8
+ import { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
9
+ import { SchnorrHardcodedAccountContractArtifact } from '@aztec/noir-contracts.js/SchnorrHardcodedAccount';
10
+
11
+ /**
12
+ * The private key that matches the hardcoded public key in the SchnorrHardcodedAccountContract.
13
+ * The corresponding public key is baked into the Noir contract as a global constant.
14
+ */
15
+ export const SCHNORR_HARDCODED_PRIVATE_KEY = GrumpkinScalar.fromHexString(
16
+ '0xd35d743ac0dfe3d6dbe6be8c877cb524a00ab1e3d52d7bada095dfc8894ccfa',
17
+ );
18
+
19
+ /**
20
+ * Account contract backed by the SchnorrHardcodedAccount Noir contract.
21
+ * This contract verifies Schnorr signatures against a public key that is hardcoded
22
+ * in the contract artifact (not stored in a note), so it does not require on-chain
23
+ * deployment or initialization. Useful for tests that need a working account without
24
+ * mining any blocks.
25
+ */
26
+ export class SchnorrHardcodedKeyAccountContract extends DefaultAccountContract {
27
+ constructor(private privateKey: GrumpkinScalar = SCHNORR_HARDCODED_PRIVATE_KEY) {
28
+ super();
29
+ }
30
+
31
+ override getContractArtifact(): Promise<ContractArtifact> {
32
+ return Promise.resolve(SchnorrHardcodedAccountContractArtifact);
33
+ }
34
+
35
+ getInitializationFunctionAndArgs() {
36
+ return Promise.resolve(undefined);
37
+ }
38
+
39
+ getAuthWitnessProvider(_address: CompleteAddress): AuthWitnessProvider {
40
+ const privateKey = this.privateKey;
41
+ return {
42
+ async createAuthWit(messageHash: Fr): Promise<AuthWitness> {
43
+ const signer = new Schnorr();
44
+ const signature = await signer.constructSignature(messageHash.toBuffer(), privateKey);
45
+ return new AuthWitness(messageHash, [...signature.toBuffer()]);
46
+ },
47
+ };
48
+ }
49
+ }