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

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 (103) 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 +15 -30
  5. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +3 -2
  6. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
  7. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +1 -1
  8. package/dest/e2e_epochs/epochs_test.d.ts +18 -1
  9. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  10. package/dest/e2e_epochs/epochs_test.js +59 -9
  11. package/dest/e2e_fees/fees_test.d.ts +1 -1
  12. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  13. package/dest/e2e_fees/fees_test.js +3 -3
  14. package/dest/e2e_p2p/inactivity_slash_test.js +3 -3
  15. package/dest/e2e_p2p/p2p_network.d.ts +10 -9
  16. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  17. package/dest/e2e_p2p/p2p_network.js +46 -27
  18. package/dest/e2e_p2p/reqresp/utils.js +1 -1
  19. package/dest/e2e_p2p/shared.d.ts +5 -7
  20. package/dest/e2e_p2p/shared.d.ts.map +1 -1
  21. package/dest/e2e_p2p/shared.js +29 -44
  22. package/dest/fixtures/authwit_proxy.d.ts +1 -1
  23. package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
  24. package/dest/fixtures/authwit_proxy.js +4 -0
  25. package/dest/fixtures/e2e_prover_test.d.ts +4 -3
  26. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  27. package/dest/fixtures/e2e_prover_test.js +7 -12
  28. package/dest/fixtures/fixtures.d.ts +12 -1
  29. package/dest/fixtures/fixtures.d.ts.map +1 -1
  30. package/dest/fixtures/fixtures.js +10 -0
  31. package/dest/fixtures/get_bb_config.d.ts +1 -1
  32. package/dest/fixtures/get_bb_config.d.ts.map +1 -1
  33. package/dest/fixtures/get_bb_config.js +5 -5
  34. package/dest/fixtures/ha_setup.d.ts +2 -2
  35. package/dest/fixtures/ha_setup.d.ts.map +1 -1
  36. package/dest/fixtures/ha_setup.js +1 -1
  37. package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts +25 -0
  38. package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts.map +1 -0
  39. package/dest/fixtures/schnorr_hardcoded_account_contract.js +39 -0
  40. package/dest/fixtures/setup.d.ts +17 -10
  41. package/dest/fixtures/setup.d.ts.map +1 -1
  42. package/dest/fixtures/setup.js +40 -21
  43. package/dest/fixtures/setup_p2p_test.d.ts +6 -6
  44. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  45. package/dest/fixtures/setup_p2p_test.js +8 -8
  46. package/dest/fixtures/token_utils.d.ts +1 -1
  47. package/dest/fixtures/token_utils.d.ts.map +1 -1
  48. package/dest/fixtures/token_utils.js +2 -5
  49. package/dest/forward-compatibility/wallet_rpc_client.d.ts +7 -0
  50. package/dest/forward-compatibility/wallet_rpc_client.d.ts.map +1 -0
  51. package/dest/forward-compatibility/wallet_rpc_client.js +15 -0
  52. package/dest/forward-compatibility/wallet_service.d.ts +3 -0
  53. package/dest/forward-compatibility/wallet_service.d.ts.map +1 -0
  54. package/dest/forward-compatibility/wallet_service.js +109 -0
  55. package/dest/legacy-jest-resolver.d.cts +3 -0
  56. package/dest/legacy-jest-resolver.d.cts.map +1 -0
  57. package/dest/shared/gas_portal_test_harness.js +1 -1
  58. package/dest/shared/uniswap_l1_l2.d.ts +1 -1
  59. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
  60. package/dest/shared/uniswap_l1_l2.js +9 -16
  61. package/dest/simulators/lending_simulator.d.ts +1 -1
  62. package/dest/simulators/lending_simulator.d.ts.map +1 -1
  63. package/dest/simulators/lending_simulator.js +2 -2
  64. package/dest/simulators/token_simulator.js +1 -1
  65. package/dest/spartan/setup_test_wallets.d.ts +1 -1
  66. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  67. package/dest/spartan/setup_test_wallets.js +63 -45
  68. package/dest/test-wallet/test_wallet.d.ts +24 -23
  69. package/dest/test-wallet/test_wallet.d.ts.map +1 -1
  70. package/dest/test-wallet/test_wallet.js +118 -81
  71. package/dest/test-wallet/worker_wallet.d.ts +4 -4
  72. package/dest/test-wallet/worker_wallet.d.ts.map +1 -1
  73. package/dest/test-wallet/worker_wallet_schema.d.ts +9 -4
  74. package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -1
  75. package/package.json +40 -40
  76. package/src/bench/client_flows/client_flows_benchmark.ts +33 -24
  77. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +3 -6
  78. package/src/e2e_epochs/epochs_test.ts +69 -9
  79. package/src/e2e_fees/fees_test.ts +4 -2
  80. package/src/e2e_p2p/inactivity_slash_test.ts +3 -3
  81. package/src/e2e_p2p/p2p_network.ts +57 -39
  82. package/src/e2e_p2p/reqresp/utils.ts +1 -1
  83. package/src/e2e_p2p/shared.ts +29 -59
  84. package/src/fixtures/authwit_proxy.ts +4 -0
  85. package/src/fixtures/e2e_prover_test.ts +12 -17
  86. package/src/fixtures/fixtures.ts +22 -0
  87. package/src/fixtures/get_bb_config.ts +7 -6
  88. package/src/fixtures/ha_setup.ts +4 -2
  89. package/src/fixtures/schnorr_hardcoded_account_contract.ts +49 -0
  90. package/src/fixtures/setup.ts +54 -25
  91. package/src/fixtures/setup_p2p_test.ts +9 -9
  92. package/src/fixtures/token_utils.ts +1 -4
  93. package/src/forward-compatibility/wallet_rpc_client.ts +14 -0
  94. package/src/forward-compatibility/wallet_service.ts +104 -0
  95. package/src/guides/up_quick_start.sh +0 -2
  96. package/src/legacy-jest-resolver.cjs +135 -0
  97. package/src/shared/gas_portal_test_harness.ts +0 -1
  98. package/src/shared/uniswap_l1_l2.ts +29 -28
  99. package/src/simulators/lending_simulator.ts +4 -2
  100. package/src/simulators/token_simulator.ts +1 -1
  101. package/src/spartan/setup_test_wallets.ts +63 -39
  102. package/src/test-wallet/test_wallet.ts +147 -100
  103. package/src/test-wallet/worker_wallet.ts +3 -2
@@ -7,11 +7,7 @@ import type { Logger } from '@aztec/aztec.js/log';
7
7
  import { TxHash } from '@aztec/aztec.js/tx';
8
8
  import type { RollupCheatCodes } from '@aztec/aztec/testing';
9
9
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
10
- import type {
11
- EmpireSlashingProposerContract,
12
- RollupContract,
13
- TallySlashingProposerContract,
14
- } from '@aztec/ethereum/contracts';
10
+ import type { RollupContract, SlashingProposerContract } from '@aztec/ethereum/contracts';
15
11
  import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
16
12
  import { timesAsync, unique } from '@aztec/foundation/collection';
17
13
  import { EthAddress } from '@aztec/foundation/eth-address';
@@ -22,8 +18,8 @@ import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.j
22
18
  import { getPXEConfig, getPXEConfig as getRpcConfig } from '@aztec/pxe/server';
23
19
  import { getRoundForOffense } from '@aztec/slasher';
24
20
  import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
25
- import type { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
26
21
 
22
+ import { SchnorrHardcodedKeyAccountContract } from '../fixtures/schnorr_hardcoded_account_contract.js';
27
23
  import { submitTxsTo } from '../shared/submit-transactions.js';
28
24
  import { TestWallet } from '../test-wallet/test_wallet.js';
29
25
  import { type ProvenTx, proveInteraction } from '../test-wallet/utils.js';
@@ -63,7 +59,12 @@ export const submitTransactions = async (
63
59
  { ...getPXEConfig(), proverEnabled: false },
64
60
  { loggerActorLabel: 'pxe-tx' },
65
61
  );
66
- const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
62
+ const contract = new SchnorrHardcodedKeyAccountContract();
63
+ const fundedAccountManager = await wallet.createAccount({
64
+ secret: fundedAccount.secret,
65
+ salt: fundedAccount.salt,
66
+ contract,
67
+ });
67
68
  return submitTxsTo(wallet, fundedAccountManager.address, numTxs, logger);
68
69
  };
69
70
 
@@ -81,7 +82,12 @@ export async function prepareTransactions(
81
82
  { ...getPXEConfig(), proverEnabled: false },
82
83
  { loggerActorLabel: 'pxe-tx' },
83
84
  );
84
- const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
85
+ const accountContract = new SchnorrHardcodedKeyAccountContract();
86
+ const fundedAccountManager = await wallet.createAccount({
87
+ secret: fundedAccount.secret,
88
+ salt: fundedAccount.salt,
89
+ contract: accountContract,
90
+ });
85
91
 
86
92
  const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {
87
93
  salt: Fr.random(),
@@ -99,7 +105,7 @@ export async function prepareTransactions(
99
105
  }
100
106
 
101
107
  export function awaitProposalExecution(
102
- slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract,
108
+ slashingProposer: SlashingProposerContract,
103
109
  timeoutSeconds: number,
104
110
  logger: Logger,
105
111
  ): Promise<bigint> {
@@ -109,24 +115,12 @@ export function awaitProposalExecution(
109
115
  reject(new Error(`Timeout waiting for proposal execution after ${timeoutSeconds}s`));
110
116
  }, timeoutSeconds * 1000);
111
117
 
112
- if (slashingProposer.type === 'empire') {
113
- const unwatch = slashingProposer.listenToPayloadSubmitted(args => {
114
- logger.warn(`Proposal ${args.payload} from round ${args.round} executed`);
115
- clearTimeout(timeout);
116
- unwatch();
117
- resolve(args.round);
118
- });
119
- } else if (slashingProposer.type === 'tally') {
120
- const unwatch = slashingProposer.listenToRoundExecuted(args => {
121
- logger.warn(`Slash from round ${args.round} executed`);
122
- clearTimeout(timeout);
123
- unwatch();
124
- resolve(args.round);
125
- });
126
- } else {
118
+ const unwatch = slashingProposer.listenToRoundExecuted(args => {
119
+ logger.warn(`Slash from round ${args.round} executed`);
127
120
  clearTimeout(timeout);
128
- reject(new Error(`Unknown slashing proposer type: ${(slashingProposer as any).type}`));
129
- }
121
+ unwatch();
122
+ resolve(args.round);
123
+ });
130
124
  });
131
125
  }
132
126
 
@@ -245,7 +239,6 @@ export async function awaitCommitteeKicked({
245
239
  rollup,
246
240
  cheatCodes,
247
241
  committee,
248
- slashFactory,
249
242
  slashingProposer,
250
243
  slashingRoundSize,
251
244
  aztecSlotDuration,
@@ -256,8 +249,7 @@ export async function awaitCommitteeKicked({
256
249
  rollup: RollupContract;
257
250
  cheatCodes: RollupCheatCodes;
258
251
  committee: readonly `0x${string}`[];
259
- slashFactory: SlashFactoryContract;
260
- slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
252
+ slashingProposer: SlashingProposerContract | undefined;
261
253
  slashingRoundSize: number;
262
254
  aztecSlotDuration: number;
263
255
  aztecEpochDuration: number;
@@ -270,36 +262,14 @@ export async function awaitCommitteeKicked({
270
262
 
271
263
  await cheatCodes.debugRollup();
272
264
 
273
- if (slashingProposer.type === 'empire') {
274
- // Await for the slash payload to be created if empire (no payload is created on tally until execution time)
275
- const targetEpoch = EpochNumber((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochsForValidatorSet()) + 1);
276
- logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
277
- await cheatCodes.advanceToEpoch(targetEpoch);
278
-
279
- const slashPayloadEvents = await retryUntil(
280
- async () => {
281
- const events = await slashFactory.getSlashPayloadCreatedEvents();
282
- return events.length > 0 ? events : undefined;
283
- },
284
- 'slash payload created',
285
- 120,
286
- 1,
287
- );
288
- expect(slashPayloadEvents.length).toBe(1);
289
- // 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)
290
- expect(unique(slashPayloadEvents[0].slashes.map(slash => slash.validator.toString()))).toHaveLength(
291
- committee.length,
292
- );
293
- } else {
294
- // Use the slash offset to ensure we are in the right epoch for tally
295
- const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
296
- const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
297
- const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
298
- const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
299
- const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
300
- logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
301
- await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
302
- }
265
+ // Use the slash offset to ensure we are in the right epoch for tally
266
+ const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
267
+ const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
268
+ const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
269
+ const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
270
+ const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
271
+ logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
272
+ await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
303
273
 
304
274
  const attestersPre = await rollup.getAttesters();
305
275
  expect(attestersPre.length).toBe(committee.length);
@@ -17,6 +17,10 @@ async function buildProxyCall(proxy: GenericProxyContract, action: ContractFunct
17
17
  return proxy.methods.forward_private_3(call.to, call.selector, call.args);
18
18
  } else if (argCount === 4) {
19
19
  return proxy.methods.forward_private_4(call.to, call.selector, call.args);
20
+ } else if (argCount === 5) {
21
+ return proxy.methods.forward_private_5(call.to, call.selector, call.args);
22
+ } else if (argCount === 6) {
23
+ return proxy.methods.forward_private_6(call.to, call.selector, call.args);
20
24
  }
21
25
  throw new Error(`No forward_private_${argCount} method on proxy`);
22
26
  }
@@ -4,12 +4,7 @@ import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
4
4
  import { type Logger, createLogger } from '@aztec/aztec.js/log';
5
5
  import type { AztecNode } from '@aztec/aztec.js/node';
6
6
  import { CheatCodes } from '@aztec/aztec/testing';
7
- import {
8
- BBCircuitVerifier,
9
- type ClientProtocolCircuitVerifier,
10
- QueuedIVCVerifier,
11
- TestCircuitVerifier,
12
- } from '@aztec/bb-prover';
7
+ import type { ClientProtocolCircuitVerifier } from '@aztec/bb-prover';
13
8
  import { BackendType, Barretenberg } from '@aztec/bb.js';
14
9
  import type { DeployAztecL1ContractsReturnType } from '@aztec/ethereum/deploy-aztec-l1-contracts';
15
10
  import { Buffer32 } from '@aztec/foundation/buffer';
@@ -68,7 +63,10 @@ export class FullProverTest {
68
63
  private provenComponents: ProvenSetup[] = [];
69
64
  private bbConfigCleanup?: () => Promise<void>;
70
65
  private acvmConfigCleanup?: () => Promise<void>;
71
- circuitProofVerifier?: ClientProtocolCircuitVerifier;
66
+ /** Returns the proof verifier from the prover node (for test assertions). */
67
+ get circuitProofVerifier(): ClientProtocolCircuitVerifier | undefined {
68
+ return this.proverAztecNode?.getProofVerifier();
69
+ }
72
70
  provenAsset!: TokenContract;
73
71
  context!: EndToEndContext;
74
72
  private proverAztecNode!: AztecNodeService;
@@ -106,15 +104,13 @@ export class FullProverTest {
106
104
  await publicDeployAccounts(this.wallet, this.accounts.slice(0, 2));
107
105
 
108
106
  this.logger.info('Applying base setup: deploying token contract');
109
- const {
110
- receipt: { contract: asset, instance },
111
- } = await TokenContract.deploy(
107
+ const { contract: asset, instance } = await TokenContract.deploy(
112
108
  this.wallet,
113
109
  this.accounts[0],
114
110
  FullProverTest.TOKEN_NAME,
115
111
  FullProverTest.TOKEN_SYMBOL,
116
112
  FullProverTest.TOKEN_DECIMALS,
117
- ).send({ from: this.accounts[0], wait: { returnReceipt: true } });
113
+ ).send({ from: this.accounts[0] });
118
114
  this.logger.verbose(`Token deployed to ${asset.address}`);
119
115
 
120
116
  this.fakeProofsAsset = asset;
@@ -170,9 +166,6 @@ export class FullProverTest {
170
166
 
171
167
  await Barretenberg.initSingleton({ backend: BackendType.NativeUnixSocket });
172
168
 
173
- const verifier = await BBCircuitVerifier.new(bbConfig);
174
- this.circuitProofVerifier = new QueuedIVCVerifier(bbConfig, verifier);
175
-
176
169
  this.logger.debug(`Configuring the node for real proofs...`);
177
170
  await this.aztecNodeAdmin.setConfig({
178
171
  realProofs: true,
@@ -180,7 +173,6 @@ export class FullProverTest {
180
173
  });
181
174
  } else {
182
175
  this.logger.debug(`Configuring the node min txs per block ${this.minNumberOfTxsPerBlock}...`);
183
- this.circuitProofVerifier = new TestCircuitVerifier();
184
176
  await this.aztecNodeAdmin.setConfig({
185
177
  minTxsPerBlock: this.minNumberOfTxsPerBlock,
186
178
  });
@@ -231,8 +223,11 @@ export class FullProverTest {
231
223
 
232
224
  this.logger.verbose('Starting prover node');
233
225
  const sponsoredFPCAddress = await getSponsoredFPCAddress();
234
- const { prefilledPublicData } = await getGenesisValues(
226
+ const { genesis } = await getGenesisValues(
235
227
  this.context.initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress),
228
+ undefined,
229
+ undefined,
230
+ this.context.genesis!.genesisTimestamp,
236
231
  );
237
232
 
238
233
  const proverNodeConfig: Parameters<typeof AztecNodeService.createAndSync>[0] = {
@@ -260,7 +255,7 @@ export class FullProverTest {
260
255
  this.proverAztecNode = await AztecNodeService.createAndSync(
261
256
  proverNodeConfig,
262
257
  { dateProvider: this.context.dateProvider, p2pClientDeps: { rpcTxProviders: [this.aztecNode] } },
263
- { prefilledPublicData },
258
+ { genesis },
264
259
  );
265
260
  this.logger.warn(`Proofs are now enabled`, { realProofs: this.realProofs });
266
261
  return this;
@@ -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
+ }
@@ -1,11 +1,14 @@
1
1
  import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr';
2
2
  import { type InitialAccountData, generateSchnorrAccounts } from '@aztec/accounts/testing';
3
3
  import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node';
4
+ import { NO_FROM } from '@aztec/aztec.js/account';
4
5
  import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
5
6
  import {
6
7
  BatchCall,
7
8
  type ContractFunctionInteraction,
8
9
  type ContractMethod,
10
+ type DeployInteractionWaitOptions,
11
+ type DeployOptions,
9
12
  getContractClassFromArtifact,
10
13
  waitForProven,
11
14
  } from '@aztec/aztec.js/contracts';
@@ -14,7 +17,7 @@ import { Fr } from '@aztec/aztec.js/fields';
14
17
  import { type Logger, createLogger } from '@aztec/aztec.js/log';
15
18
  import type { AztecNode } from '@aztec/aztec.js/node';
16
19
  import type { Wallet } from '@aztec/aztec.js/wallet';
17
- import { AnvilTestWatcher, CheatCodes } from '@aztec/aztec/testing';
20
+ import { AnvilTestWatcher, type AnvilTestWatcherOpts, CheatCodes } from '@aztec/aztec/testing';
18
21
  import { SPONSORED_FPC_SALT } from '@aztec/constants';
19
22
  import { isAnvilTestChain } from '@aztec/ethereum/chain';
20
23
  import { createExtendedL1Client } from '@aztec/ethereum/client';
@@ -48,9 +51,10 @@ import type { ProverNodeConfig } from '@aztec/prover-node';
48
51
  import { type PXEConfig, getPXEConfig } from '@aztec/pxe/server';
49
52
  import type { SequencerClient } from '@aztec/sequencer-client';
50
53
  import { type ContractInstanceWithAddress, getContractInstanceFromInstantiationParams } from '@aztec/stdlib/contract';
51
- import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
54
+ import type { AztecNodeAdmin, AztecNodeDebug } from '@aztec/stdlib/interfaces/client';
52
55
  import { tryStop } from '@aztec/stdlib/interfaces/server';
53
56
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
57
+ import type { GenesisData } from '@aztec/stdlib/world-state';
54
58
  import {
55
59
  type TelemetryClient,
56
60
  type TelemetryClientConfig,
@@ -177,8 +181,11 @@ export type SetupOptions = {
177
181
  proverNodeConfig?: Partial<ProverNodeConfig>;
178
182
  /** Whether to use a mock gossip sub network for p2p clients. */
179
183
  mockGossipSubNetwork?: boolean;
184
+ /** Whether to add simulated latency to the mock gossipsub network (in ms) */
185
+ mockGossipSubNetworkLatency?: number;
180
186
  /** Whether to disable the anvil test watcher (can still be manually started) */
181
187
  disableAnvilTestWatcher?: boolean;
188
+ anvilTestWatcherOpts?: AnvilTestWatcherOpts;
182
189
  /** Whether to enable anvil automine during deployment of L1 contracts (consider defaulting this to true). */
183
190
  automineL1Setup?: boolean;
184
191
  /** How many accounts to seed and unlock in anvil. */
@@ -200,8 +207,11 @@ export type SetupOptions = {
200
207
  skipAccountDeployment?: boolean;
201
208
  /** L1 contracts deployment arguments. */
202
209
  l1ContractsArgs?: Partial<DeployAztecL1ContractsArgs>;
203
- /** Wallet minimum fee padding multiplier (defaults to 0.5, which is 50% padding). */
210
+ /** Wallet minimum fee padding multiplier */
204
211
  walletMinFeePadding?: number;
212
+ /** Whether the initial node should be a lightweight RPC-only node (no sequencer, no validator).
213
+ * Use for tests that create their own validator nodes and don't need the initial sequencer. */
214
+ skipInitialSequencer?: boolean;
205
215
  } & Partial<AztecNodeConfig>;
206
216
 
207
217
  /** Context for an end-to-end test as returned by the `setup` function */
@@ -209,7 +219,7 @@ export type EndToEndContext = {
209
219
  /** The Anvil instance (only set if anvil was started locally). */
210
220
  anvil: Anvil | undefined;
211
221
  /** The Aztec Node service or client a connected to it. */
212
- aztecNode: AztecNode;
222
+ aztecNode: AztecNode & AztecNodeDebug;
213
223
  /** The Aztec Node as a service. */
214
224
  aztecNodeService: AztecNodeService;
215
225
  /** Client to the Aztec Node admin interface. */
@@ -248,8 +258,8 @@ export type EndToEndContext = {
248
258
  sequencerDelayer: Delayer | undefined;
249
259
  /** Delayer for prover node L1 txs (only when enableDelayer and startProverNode are true). */
250
260
  proverDelayer: Delayer | undefined;
251
- /** Prefilled public data used for setting up nodes. */
252
- prefilledPublicData: PublicDataTreeLeaf[] | undefined;
261
+ /** Genesis data used for setting up nodes. */
262
+ genesis: GenesisData | undefined;
253
263
  /** ACVM config (only set if running locally). */
254
264
  acvmConfig: Awaited<ReturnType<typeof getACVMConfig>>;
255
265
  /** BB config (only set if running locally). */
@@ -275,7 +285,7 @@ export async function setup(
275
285
  let anvil: Anvil | undefined;
276
286
  try {
277
287
  opts.aztecTargetCommitteeSize ??= 0;
278
- opts.slasherFlavor ??= 'none';
288
+ opts.slasherEnabled ??= false;
279
289
 
280
290
  const config: AztecNodeConfig & SetupOptions = { ...getConfigEnvVars(), ...opts };
281
291
  // use initialValidators for the node config
@@ -302,6 +312,8 @@ export async function setup(
302
312
  config.dataDirectory = directoryToCleanup;
303
313
  }
304
314
 
315
+ const dateProvider = new TestDateProvider();
316
+
305
317
  if (!config.l1RpcUrls?.length) {
306
318
  if (!isAnvilTestChain(chain.id)) {
307
319
  throw new Error(`No ETHEREUM_HOSTS set but non anvil chain requested`);
@@ -311,6 +323,7 @@ export async function setup(
311
323
  accounts: opts.anvilAccounts,
312
324
  port: opts.anvilPort ?? (process.env.ANVIL_PORT ? parseInt(process.env.ANVIL_PORT) : undefined),
313
325
  slotsInAnEpoch: opts.anvilSlotsInAnEpoch,
326
+ dateProvider,
314
327
  });
315
328
  anvil = res.anvil;
316
329
  config.l1RpcUrls = [res.rpcUrl];
@@ -322,8 +335,6 @@ export async function setup(
322
335
  logger.info(`Logging metrics to ${filename}`);
323
336
  setupMetricsLogger(filename);
324
337
  }
325
-
326
- const dateProvider = new TestDateProvider();
327
338
  const ethCheatCodes = new EthCheatCodesWithState(config.l1RpcUrls, dateProvider);
328
339
 
329
340
  if (opts.stateLoad) {
@@ -373,10 +384,12 @@ export async function setup(
373
384
  addressesToFund.push(sponsoredFPCAddress);
374
385
  }
375
386
 
376
- const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(
387
+ const genesisTimestamp = BigInt(Math.floor(Date.now() / 1000));
388
+ const { genesisArchiveRoot, genesis, fundingNeeded } = await getGenesisValues(
377
389
  addressesToFund,
378
390
  opts.initialAccountFeeJuice,
379
391
  opts.genesisPublicData,
392
+ genesisTimestamp,
380
393
  );
381
394
 
382
395
  const wasAutomining = await ethCheatCodes.isAutoMining();
@@ -419,11 +432,12 @@ export async function setup(
419
432
  await ethCheatCodes.setIntervalMining(config.ethereumSlotDuration);
420
433
  }
421
434
 
422
- // Always sync dateProvider to L1 time after deploying L1 contracts, regardless of mining mode.
423
- // In compose mode, L1 time may have drifted ahead of system time due to the local-network watcher
424
- // warping time forward on each filled slot. Without this sync, the sequencer computes the wrong
425
- // slot from its dateProvider and cannot propose blocks.
426
- dateProvider.setTime((await ethCheatCodes.timestamp()) * 1000);
435
+ // In compose mode (no local anvil), sync dateProvider to L1 time since it may have drifted
436
+ // ahead of system time due to the local-network watcher warping time forward on each filled slot.
437
+ // When running with a local anvil, the dateProvider is kept in sync via the stdout listener.
438
+ if (!anvil) {
439
+ dateProvider.setTime((await ethCheatCodes.lastBlockTimestamp()) * 1000);
440
+ }
427
441
 
428
442
  if (opts.l2StartTime) {
429
443
  await ethCheatCodes.warp(opts.l2StartTime, { resetBlockInterval: true });
@@ -434,6 +448,7 @@ export async function setup(
434
448
  deployL1ContractsValues.l1ContractAddresses.rollupAddress,
435
449
  deployL1ContractsValues.l1Client,
436
450
  dateProvider,
451
+ opts.anvilTestWatcherOpts,
437
452
  );
438
453
  if (!opts.disableAnvilTestWatcher) {
439
454
  await watcher.start();
@@ -464,7 +479,7 @@ export async function setup(
464
479
  let p2pClientDeps: P2PClientDeps | undefined = undefined;
465
480
 
466
481
  if (opts.mockGossipSubNetwork) {
467
- mockGossipSubNetwork = new MockGossipSubNetwork();
482
+ mockGossipSubNetwork = new MockGossipSubNetwork(opts.mockGossipSubNetworkLatency);
468
483
  p2pClientDeps = { p2pServiceFactory: getMockPubSubP2PServiceFactory(mockGossipSubNetwork) };
469
484
  }
470
485
 
@@ -492,11 +507,22 @@ export async function setup(
492
507
  }
493
508
  }
494
509
 
510
+ // When skipInitialSequencer is set, the initial node is a lightweight RPC-only node.
511
+ // We apply these overrides to a copy so they don't leak into the returned config.
512
+ // Keep P2P enabled if mockGossipSubNetwork is used (needed for tx propagation to validators).
513
+ const initialNodeConfig = opts.skipInitialSequencer
514
+ ? {
515
+ ...config,
516
+ disableValidator: true,
517
+ ...(opts.mockGossipSubNetwork ? {} : { p2pEnabled: false, bootstrapNodes: [] as string[] }),
518
+ }
519
+ : config;
520
+
495
521
  const aztecNodeService = await withLoggerBindings({ actor: 'node-0' }, () =>
496
522
  AztecNodeService.createAndSync(
497
- config,
523
+ initialNodeConfig,
498
524
  { dateProvider, telemetry: telemetryClient, p2pClientDeps },
499
- { prefilledPublicData },
525
+ { genesis, dontStartSequencer: opts.skipInitialSequencer },
500
526
  ),
501
527
  );
502
528
  const sequencerClient = aztecNodeService.getSequencer();
@@ -521,7 +547,7 @@ export async function setup(
521
547
  dataDirectory: proverNodeDataDirectory,
522
548
  },
523
549
  { dateProvider, p2pClientDeps, telemetry: telemetryClient },
524
- { prefilledPublicData },
550
+ { genesis },
525
551
  ));
526
552
  }
527
553
 
@@ -557,7 +583,9 @@ export async function setup(
557
583
 
558
584
  let accounts: AztecAddress[] = [];
559
585
 
560
- if (shouldDeployAccounts) {
586
+ if (opts.skipInitialSequencer) {
587
+ logger.info('Sequencer not started on initial node, skipping block progression');
588
+ } else if (shouldDeployAccounts) {
561
589
  logger.info(
562
590
  `${numberOfAccounts} accounts are being deployed. Reliably progressing past genesis by setting minTxsPerBlock to 1 and waiting for the accounts to be deployed`,
563
591
  );
@@ -626,7 +654,7 @@ export async function setup(
626
654
  initialFundedAccounts,
627
655
  logger,
628
656
  mockGossipSubNetwork,
629
- prefilledPublicData,
657
+ genesis,
630
658
  proverNode,
631
659
  sequencerDelayer,
632
660
  proverDelayer,
@@ -726,7 +754,7 @@ export function createAndSyncProverNode(
726
754
  dateProvider: DateProvider;
727
755
  p2pClientDeps?: P2PClientDeps;
728
756
  },
729
- options: { prefilledPublicData: PublicDataTreeLeaf[]; dontStart?: boolean },
757
+ options: { genesis?: GenesisData; dontStart?: boolean },
730
758
  ): Promise<{ proverNode: AztecNodeService }> {
731
759
  return withLoggerBindings({ actor: 'prover-0' }, async () => {
732
760
  const proverNode = await AztecNodeService.createAndSync(
@@ -739,7 +767,7 @@ export function createAndSyncProverNode(
739
767
  proverPublisherPrivateKeys: [new SecretValue(proverNodePrivateKey)],
740
768
  },
741
769
  deps,
742
- { ...options, dontStartProverNode: options.dontStart },
770
+ { genesis: options.genesis, dontStartProverNode: options.dontStart },
743
771
  );
744
772
 
745
773
  if (!proverNode.getProverNode()) {
@@ -830,7 +858,7 @@ export async function ensureAccountContractsPublished(wallet: Wallet, accountsTo
830
858
  * Returns deployed account data that can be used by tests.
831
859
  */
832
860
  export const deployAccounts =
833
- (numberOfAccounts: number, logger: Logger) =>
861
+ (numberOfAccounts: number, logger: Logger, deployOptions?: Partial<DeployOptions<DeployInteractionWaitOptions>>) =>
834
862
  async ({ wallet, initialFundedAccounts }: { wallet: TestWallet; initialFundedAccounts: InitialAccountData[] }) => {
835
863
  if (initialFundedAccounts.length < numberOfAccounts) {
836
864
  throw new Error(`Cannot deploy more than ${initialFundedAccounts.length} initial accounts.`);
@@ -847,8 +875,9 @@ export const deployAccounts =
847
875
  );
848
876
  const deployMethod = await accountManager.getDeployMethod();
849
877
  await deployMethod.send({
850
- from: AztecAddress.ZERO,
878
+ from: NO_FROM,
851
879
  skipClassPublication: i !== 0, // Publish the contract class at most once.
880
+ ...deployOptions,
852
881
  });
853
882
  }
854
883